Compare commits
No commits in common. "d441c69fefeaef7ab7e58becc787d1f353ae9365" and "e4ca2eecce316990e9af154c4f678c52bbcb79ce" have entirely different histories.
d441c69fef
...
e4ca2eecce
10 changed files with 41 additions and 182 deletions
5
PGUI.pyw
5
PGUI.pyw
|
|
@ -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__':
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
11
getpid.py
11
getpid.py
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
''',
|
||||
|
|
|
|||
|
|
@ -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:]))
|
||||
|
|
|
|||
|
|
@ -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:]))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
66
sdingest.py
66
sdingest.py
|
|
@ -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:]))
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue