Compare commits

..

No commits in common. "d441c69fefeaef7ab7e58becc787d1f353ae9365" and "e4ca2eecce316990e9af154c4f678c52bbcb79ce" have entirely different histories.

10 changed files with 41 additions and 182 deletions

View file

@ -148,8 +148,7 @@ def main(argv):
pgui = PGUILauncher(root)
pgui.pack(fill=tkinter.BOTH, expand=True)
pgui.filter_entry.focus_set()
pgui.filter_entry.focus_force()
pgui.filter_entry.focus()
width = root.winfo_reqwidth()
height = root.winfo_reqheight()
@ -158,8 +157,6 @@ def main(argv):
root.geometry('%dx%d+%d+%d' % (width, height, x_offset, y_offset-50))
root.deiconify()
root.focus()
root.after(100, lambda: pgui.filter_entry.focus_force())
root.mainloop()
if __name__ == '__main__':

View file

@ -12,7 +12,7 @@ log = vlogging.getLogger(__name__, 'adbinstall')
def adbinstall_argparse(args):
patterns = pipeable.input_many(args.apks, skip_blank=True, strip=True)
apks = pathclass.glob_many(patterns)
apks = pathclass.glob_many_files(patterns)
installs = []
for apk in apks:
apk = pathclass.Path(apk)

View file

@ -18,7 +18,7 @@ log = vlogging.getLogger(__name__, 'getcrx')
FILENAME_BADCHARS = '\\/:*?<>|"'
WEBSTORE_URL = 'https://chrome.google.com/webstore/detail/{extension_id}'
CRX_URL = 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion=131.0.6167.161&acceptformat=crx2,crx3&x=id%3D{extension_id}%26uc'
CRX_URL = 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion=121.0.6167.161&acceptformat=crx2,crx3&x=id%3D{extension_id}%26uc'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
session = requests.Session()

View file

@ -3,16 +3,17 @@ import psutil
import sys
from voussoirkit import betterhelp
from voussoirkit import subproctools
from voussoirkit import vlogging
log = vlogging.getLogger(__name__, 'getpid')
def getpid_argparse(args):
pids = subproctools.getpid(args.process_name)
status = 0 if len(pids) > 0 else 1
for pid in pids:
print(pid)
status = 1
target = args.process_name.lower()
for process in psutil.process_iter():
if process.name().lower() == target:
print(process.pid)
status = 0
return status
@vlogging.main_decorator

View file

@ -360,7 +360,7 @@ def main(argv):
nargs='+',
type=str,
help='''
Run `git <command>` in each directory. You can use \\- to escape - in your
Run `git <command>` in each directory. You can use \- to escape - in your
git arguments, since they would confuse this program's argparse.
If this is used, any --fetch, --pull, --push is ignored.
''',

View file

@ -1,10 +1,8 @@
import argparse
import socket
import sqlite3
import sys
import time
from voussoirkit import betterhelp
from voussoirkit import hms
from voussoirkit import threadpool
from voussoirkit import vlogging
@ -37,11 +35,12 @@ def percentage(items):
trues = sum(bool(i) for i in items)
return trues / len(items)
def ping_lan(gateway_ip):
log.debug('Checking LAN at %s.', gateway_ip)
def ping_lan():
ip = '192.168.1.1'
log.debug('Checking LAN at %s.', ip)
try:
socket.setdefaulttimeout(1)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((gateway_ip, 80))
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((ip, 80))
return True
except socket.error:
return False
@ -77,12 +76,21 @@ def check_ip():
log.debug('Checking IP %s.', ip)
try:
socket.setdefaulttimeout(2)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((ip, 80))
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(('104.43.253.214', 80))
return True
except socket.error:
return False
ips = [
'198.100.155.125', # voussoir.net
'104.43.253.214',
'13.107.21.200',
'13.77.161.179',
'142.136.81.136',
'151.101.1.140',
'172.217.11.174',
'172.217.11.78',
'176.32.103.205',
'35.165.194.49',
'69.252.80.75',
]
thread_pool.pause()
jobs = [{'function': check, 'args': [ip]} for ip in ips]
@ -119,10 +127,10 @@ def end_down():
down = False
outage_started = None
def check_forever(lan_gateway_ip):
def check_forever():
while True:
now = time.strftime('%Y-%m-%d %H:%M:%S')
lan_ok = int(ping_lan(lan_gateway_ip))
lan_ok = int(ping_lan())
dns_stat = check_dns()
ip_stat = check_ip()
message = f'{now}, LAN={lan_ok}, DNS={dns_stat:0.2f}, IP={ip_stat:0.2f}'
@ -140,31 +148,13 @@ def check_forever(lan_gateway_ip):
else:
time.sleep(20)
def internetcheck_argparse(args):
@vlogging.main_decorator
def main(argv):
try:
check_forever(lan_gateway_ip=args.lan_gateway_ip)
check_forever()
except KeyboardInterrupt:
pass
return 0
@vlogging.main_decorator
def main(argv):
parser = argparse.ArgumentParser(
description='''
This program will periodically ping both LAN and external IP addresses
to help you troubleshoot the time and duration of network outages.
''',
)
parser.add_argument(
'--lan_gateway_ip',
'--lan-gateway-ip',
default='192.168.1.1',
help='''
''',
)
parser.set_defaults(func=internetcheck_argparse)
return betterhelp.go(parser, argv)
if __name__ == '__main__':
raise SystemExit(main(sys.argv[1:]))

View file

@ -4,7 +4,6 @@ import os
import re
import sys
from voussoirkit import betterhelp
from voussoirkit import imagetools
from voussoirkit import interactive
from voussoirkit import pathclass
@ -14,14 +13,13 @@ from voussoirkit import vlogging
log = vlogging.getLogger(__name__)
def makename(file, read_exif=False, read_mtime=False, minus_duration=False):
def makename(file, read_exif=False):
old = file.replace_extension('').basename
new = old
final_pattern = r'^(\d\d\d\d)-(\d\d)-(\d\d)_(\d\d)-(\d\d)-(\d\d)(?:x\d+)?$'
# Already optimized filenames need not apply
# This is also important when the filename and the exif disagree
if re.match(final_pattern, old) and not read_exif:
if re.match(r'^(\d\d\d\d)-(\d\d)-(\d\d)_(\d\d)-(\d\d)-(\d\d)(?:x\d+)?$', old) and not read_exif:
return file
# Microsoft ICE
@ -108,13 +106,6 @@ def makename(file, read_exif=False, read_mtime=False, minus_duration=False):
new,
)
# Sony videos
new = re.sub(
r'^VideoPro_(\d\d\d\d)(\d\d)(\d\d)_(\d\d)(\d\d)(\d\d)+$',
r'\1-\2-\3_\4-\5-\6',
new,
)
new = re.sub(
r'^(\d\d\d\d)-(\d\d)-(\d\d)_(\d\d)-(\d\d)-(\d\d)[_-](\d+)$',
r'\1-\2-\3_\4-\5-\6x\7',
@ -156,16 +147,6 @@ def makename(file, read_exif=False, read_mtime=False, minus_duration=False):
if new == old and read_exif and file.extension in {'jpg', 'jpeg'}:
new = makename_exif(file, old)
if new == old and re.match(final_pattern, new):
return file
if new == old and read_mtime:
mtime = file.stat.st_mtime
if minus_duration:
mtime -= get_file_duration(file)
date = datetime.datetime.fromtimestamp(mtime)
new = date.strftime('%Y-%m-%d_%H-%M-%S')
new = file.parent.with_child(new).add_extension(file.extension)
return new
@ -175,23 +156,11 @@ def makename_exif(file, fallback):
return fallback
return dt.strftime('%Y-%m-%d_%H-%M-%S')
def get_file_duration(file):
import kkroening_ffmpeg
probe = kkroening_ffmpeg.probe(file.absolute_path)
duration = float(probe['format']['duration'])
return duration
def makename_ffmpeg(file, fallback):
import kkroening_ffmpeg
probe = kkroening_ffmpeg.probe(file.absolute_path)
duration = float(probe['format']['duration'])
zulu = probe['streams'][0]['tags']['creation_time']
def makenames(files, read_exif=False, read_mtime=False, minus_duration=False):
def makenames(files, read_exif=False):
pairs = {}
new_duplicates = {}
for file in files:
newname = makename(file, read_exif=read_exif, read_mtime=read_mtime, minus_duration=minus_duration)
newname = makename(file, read_exif=read_exif)
new_duplicates.setdefault(newname, []).append(file)
if file.basename == newname.basename:
continue
@ -224,7 +193,7 @@ def photo_rename_argparse(args):
else:
files = pathclass.glob_many_files(patterns)
pairs = makenames(files, read_exif=args.read_exif, read_mtime=args.read_mtime, minus_duration=args.minus_duration)
pairs = makenames(files, read_exif=args.read_exif)
if not pairs:
return 0
@ -243,37 +212,12 @@ def main(argv):
parser.add_argument('patterns', nargs='+')
parser.add_argument('--recurse', action='store_true')
parser.add_argument(
'--exif',
dest='read_exif',
action='store_true',
help='''
Program will look for EXIF metadata and use ImageDateTime, if available.
''',
)
parser.add_argument(
'--mtime',
dest='read_mtime',
action='store_true',
help='''
Program will use the file's mtime as a last resort.
''',
)
parser.add_argument(
'--minus_duration',
'--minus-duration',
dest='minus_duration',
action='store_true',
help='''
When used with --mtime, the file's duration will be subtracted.
Use for cameras that set the mtime to the end of the video and you want
the name to be the start.
''',
)
parser.add_argument('--exif', dest='read_exif', action='store_true')
parser.add_argument('--yes', dest='autoyes', action='store_true')
parser.set_defaults(func=photo_rename_argparse)
return betterhelp.go(parser, argv)
args = parser.parse_args(argv)
return args.func(args)
if __name__ == '__main__':
raise SystemExit(main(sys.argv[1:]))

View file

@ -67,7 +67,7 @@ body.noscrollbar::-webkit-scrollbar
}
body.noscrollbar
{
scrollbar-width: 0;
scrollbar-width: none;
}
header
@ -286,10 +286,6 @@ pre,
<p>Click each photo to view its full resolution. Click the number to download it.</p>
{% for zip in zipz %}
<p>Click here to download <a target="_blank" href="{{urlroot}}{{zip.relative_to('.', simple=True)}}">{{zip.basename}}</a></p>
{% endfor %}
{% for file in files %}
{% if file.extension == 'jpg' %}
<article class="photograph">
@ -300,7 +296,7 @@ pre,
</article>
{% elif file.extension in ['mp4', 'mov'] %}
<article class="photograph">
<p>{{file.replace_extension('').basename}} (<a download="{{file.basename}}" href="{{urlroot}}{{file.relative_to('.', simple=True)}}">#{{loop.index}}/{{files|length}}</a>)</p>
<p>{{file.replace_extension('').basename}}</p>
<video controls preload="none" src="{{urlroot}}{{file.relative_to('.', simple=True)}}" poster="{{urlroot}}thumbs/small_{{file.replace_extension('jpg').relative_to('.', simple=True)}}"></video>
</article>
{% endif %}
@ -442,10 +438,7 @@ document.addEventListener("DOMContentLoaded", on_pageload);
''')
def imagegallery(files, title, urlroot, with_download_links):
zipz = [f for f in files if f.extension == 'zip']
files = [f for f in files if f.extension != 'zip']
html = TEMPLATE.render(
zipz=zipz,
files=files,
title=title,
urlroot=urlroot,

View file

@ -1,66 +0,0 @@
import shutil
import argparse
import sys
from voussoirkit import betterhelp
from voussoirkit import pathclass
from voussoirkit import spinal
from voussoirkit import vlogging
from voussoirkit import windrives
from voussoirkit import progressbars
log = vlogging.getLogger(__name__, 'sdingest')
def sdingest_one(folder):
cwd = pathclass.cwd()
for file in folder.walk_files():
# print(file.absolute_path)
spinal.copy_file(
file,
cwd.with_child(file.basename),
progressbar=progressbars.Bar1_bytestring,
)
def sdingest_all():
dcim = None
drives = windrives.get_drive_map()
for (mount, info) in drives.items():
mount = pathclass.Path(mount)
# Panasonic HC-X1500/HC-X2000
panasonic = mount.with_child('PRIVATE').with_child('PANA_GRP').with_child('001YAQAM')
if panasonic.is_folder:
sdingest_one(panasonic)
continue
# Most cameras
dcim = mount.with_child('DCIM')
if dcim.is_folder:
sdingest_one(dcim)
continue
# Sony ICD UX570
if info.get('name').upper() == 'MEMORY CARD':
folder = mount.join('PRIVATE\\SONY\\REC_FILE')
if folder.exists:
sdingest_one(folder)
continue
if dcim is None:
return 1
def sdingest_argparse(args):
return sdingest_all()
@vlogging.main_decorator
def main(argv):
parser = argparse.ArgumentParser(
description='''
''',
)
parser.set_defaults(func=sdingest_argparse)
return betterhelp.go(parser, argv)
if __name__ == '__main__':
raise SystemExit(main(sys.argv[1:]))

View file

@ -16,7 +16,7 @@ alias move=mv
alias copy=cp
alias md=mkdir
alias cls=clear
alias gfa='git fetch --all'
alias gfa=git fetch --all
# This generates a warning in some non-interactive situations, like cron.
bind TAB:menu-complete > /dev/null 2>&1