freelance-project-34-market.../dotfiles/.local/bin/commands
2023-03-19 12:01:51 +03:00

2615 lines
76 KiB
Python
Executable File

#!/usr/bin/env python3
import enum
import datetime
import functools
import io
import json
import logging
import optparse
import os
import pprint
import re
import select
import signal
import socket
import subprocess
import sys
import tempfile
import time
import traceback
def custom_notify(
title=None,
msg=None,
timeout=None,
):
if timeout is None:
timeout = 5
timeout2 = int(timeout * 1000)
assert isinstance(timeout2, int) and timeout2 >= 500
if title is None:
title = 'commands'
assert isinstance(title, str) and len(title) > 0
assert isinstance(msg, str) and len(msg) > 0
if sys.platform == 'darwin':
osascript_translate = functools.partial(
custom_translate,
check=lambda a, b:
not re.compile(
r'^[a-zA-Z0-9\<\>\/\(\)\s\.\,\:]*$'
)\
.match(b) is None,
)
subprocess.check_call([
'osascript',
'-e',
'display notification "%s" with title "%s"' % (
osascript_translate(msg),
osascript_translate(title),
)
])
else:
subprocess.check_call([
'notify-send',
'-t', '%d' % timeout2,
title,
msg[-128:]
])
def intercept_output(
current_subprocess,
return_aggregated=None,
transform_callback=None,
real_time=None,
timeout=None,
):
if real_time is None:
real_time = False
start_timestamp = datetime.datetime.now()
if not return_aggregated:
return_aggregated = False
t1 = select.poll()
t1.register(current_subprocess.stdout, select.POLLIN)
print([current_subprocess, current_subprocess.poll()])
output = []
last_data = None
while not (
not current_subprocess.poll() is None and \
not last_data is None
):
if not timeout is None and \
(datetime.datetime.now() - start_timestamp).total_seconds() > timeout:
break
t2 = t1.poll(100)
if len(t2) == 1 and (t2[0][1] & select.POLLIN) > 0 and \
not (isinstance(last_data, bytes) and len(last_data) == 0):
t3 = current_subprocess.stdout.peek()
t4 = current_subprocess.stdout.read(len(t3))
last_data = t3
output.append(t3)
yield dict(
data=t3,
aggregated=False,
)
t6 = t3
if not transform_callback is None:
t5 = transform_callback(t3)
if not t5 is None:
t6 = t5
os.write(sys.stdout.fileno(), t6)
elif real_time:
yield dict(
data=b'',
aggregated=False,
)
if return_aggregated:
yield dict(
data=b''.join(output),
aggregated=True,
returncode=current_subprocess.poll(),
)
def player_metadata():
for k in range(20):
try:
time.sleep(1.0)
return subprocess.check_output(['playerctl', 'metadata']).decode('utf-8').strip()
except:
continue
def memory_stats():
if sys.platform == 'linux':
with io.BytesIO(
subprocess.check_output(
'free',
shell=True
)
) as f:
t1 = f.read().decode('utf-8').splitlines()
mem_total = int(t1[1].strip().split()[1])
mem_used = \
int(t1[1].strip().split()[2]) + \
int(t1[1].strip().split()[4])
return dict(
mem_total=mem_total,
mem_used=mem_used,
)
elif sys.platform == 'darwin':
sysctl_value = lambda name, custom_cast=int: \
custom_cast(
subprocess.check_output(
'sysctl -a | grep %s' % name,
shell=True,
).decode('utf-8').split(':')[1]
)
vm_pagesize = sysctl_value('vm.pagesize')
mem_total = sysctl_value('hw.memsize')
t1 = subprocess.check_output('vm_stat').decode('utf-8')
t2 = [o.split(':') for o in t1.splitlines() if ':' in o]
t3 = {
o[0].replace(' ', '_').replace('-', '_').lower() \
: \
int(o[1].strip().rstrip('.'))
for o in t2
if len(o) == 2 and len(o[0]) > 0 \
and not re.compile(r'^\s*\d+\.\s*$').match(o[1]) is None \
and not re.compile(r'^[a-zA-Z0-9\_\-\s]+$').match(o[0]) is None
}
mem_used = (
t3['pages_active'] + \
t3['pages_wired_down']
) * vm_pagesize
return dict(
mem_total=mem_total / 1024,
mem_used=mem_used / 1024,
)
else:
raise NotImplementedError
def chrome(
argv
):
assert isinstance(argv, list) and all([isinstance(o, str) for o in argv])
parser = optparse.OptionParser()
parser.add_option(
'--user_data_dir',
dest='user_data_dir',
default=None,
type=str,
)
options, args = parser.parse_args(argv)
if options.user_data_dir is None:
options.user_data_dir = os.path.join(
os.environ['HOME'],
'.config',
'google-chrome',
)
#assert os.path.exists(options.user_data_dir)
if sys.platform == 'linux':
subprocess.check_call([
'google-chrome-stable',
'--enable-features=useOzonePlatform',
'--ozone-platform=wayland',
'--process-per-site',
'--user-data-dir=%s' % options.user_data_dir,
*args,
])
else:
raise NotImplementedError
def eternal_oom(argv):
import signal
import re
import time
import pprint
assert isinstance(argv, list) and all([isinstance(o, str) for o in argv])
parser = optparse.OptionParser()
parser.add_option(
'--cpu_wait',
dest='cpu_wait',
default=None,
type=float,
)
parser.add_option(
'--mean_size',
dest='mean_size',
default=None,
type=int,
)
parser.add_option(
'--one_shot_clean',
dest='one_shot_clean',
action='store_true',
default=None,
)
parser.add_option(
'--one_shot_app',
dest='one_shot_app',
default=[],
action='append',
)
parser.add_option(
'--period',
dest='period',
default=None,
type=float,
)
parser.add_option(
'--memory_limit',
dest='memory_limit',
default=None,
type=float,
)
parser.add_option(
'--cpu_limit',
dest='cpu_limit',
default=None,
type=float,
)
parser.add_option(
'--debug',
dest='debug',
action='store_true',
default=False,
)
options, args = parser.parse_args(argv)
self_pid = os.getpid()
if isinstance(options.one_shot_clean, bool) and options.one_shot_clean:
if len(options.one_shot_app) == 0:
options.one_shot_app = ['chrome', 'teams']
config = dict(
chrome=(r'chrome.*type=renderer', r'^.*--extension-process.*$'),
teams=(r'teams.*type=renderer', None),
)
for app in options.one_shot_app:
p = config[app]
try:
t1 = subprocess.check_output([
'pgrep', '-a', '-f', p[0]
]).decode('utf-8')
except:
continue
t2 = t1.splitlines()
if not p[1] is None:
t3 = [o for o in t2 if re.compile(p[1]).match(o) is None]
else:
t3 = t2
t4 = [
int(o.split()[0]) for o in t3
]
for pid in t4:
if pid == self_pid:
raise NotImplementedError
os.kill(pid, signal.SIGTERM)
logging.info(json.dumps(dict(
apps=options.one_shot_app,
count=len(t4),
processes=[
o.split()[:3] for o in t3
],
)))
if len(t4) > 0:
print(
'\n'.join([
str(o.split()[:3]) for o in t3
])
)
return
if options.period is None:
options.period = 1
if options.memory_limit is None:
options.memory_limit = 3 * 1024 * 1024
if options.cpu_limit is None:
options.cpu_limit = 0.6 * os.cpu_count()
if options.cpu_wait is None:
options.cpu_wait = 10
if options.mean_size is None:
options.mean_size = 30
if isinstance(options.memory_limit, float):
options.memory_limit = int(options.memory_limit)
assert isinstance(options.memory_limit, int) \
and options.memory_limit < memory_stats()['mem_total'] * 0.95 \
and options.memory_limit > 512 * 1024
assert isinstance(options.cpu_limit, float) \
and options.cpu_limit > 0.2 * os.cpu_count() and \
options.cpu_limit < os.cpu_count() * 0.95
assert options.period >= 1
assert options.cpu_wait >= 10
assert options.mean_size >= 16
def pandas_data_frame(lines, groups_regex, header_regex, extra_columns):
header = re.compile(header_regex).search(lines[0]).groups()
rows = [
re.compile(groups_regex).search(row).groups()
for row in lines[1:]
]
columns = {
column: []
for column in header
}
for row in rows:
for value, column in zip(row, header):
columns[column].append(value)
for column, transformation in extra_columns.items():
columns[column] = [
transformation(
{
k : v[index]
for k, v in columns.items()
}
)
for index in range(len(rows))
]
return columns
def pandas_merge(left, right, on):
index = {}
input_data_frames = [
('left', left),
('right', right),
]
for index_name, data_frame in input_data_frames:
current_index = {}
for row_index, value in enumerate(data_frame[on]):
if not value in current_index:
current_index[value] = []
current_index[value].append(row_index)
index[index_name] = current_index
merged_data_frame = dict(
header=[
column + '_x'
for column in left
] + [
column + '_y'
for column in right
],
columns={},
)
for column in merged_data_frame['header']:
merged_data_frame['columns'][column] = []
common_values = {
left_value
for left_value in index['left']
if left_value in index['right']
}
common_rows = sorted(
[
dict(
left_row_index=index['left'][value][0],
right_row_index=index['right'][value][0],
)
for value in common_values
],
key=lambda x: x['left_row_index'],
)
for common_row in common_rows:
row = sum([
[
values[
common_row['%s_row_index' % index_name]
]
for column, values in data_frame.items()
]
for index_name, data_frame in input_data_frames
], [])
for column, value in zip(merged_data_frame['header'], row):
merged_data_frame['columns'][column].append(value)
return merged_data_frame['columns']
def pandas_sort_values(data_frame, by, ascending):
assert len(by) == 1
assert ascending is False
t1 = [
o['row_index']
for o in sorted(
[
dict(
row_index=row_index,
value=value
)
for row_index, value in enumerate(data_frame[by[0]])
],
key=lambda x: x['value']
)[::-1]
]
return {
column : [
values[row_index]
for row_index in t1
]
for column, values in data_frame.items()
}
def pandas_filter_values(data_frame, condition):
shape = [
len(data_frame),
]
if shape[0] > 0:
shape.append(
len(list(data_frame.values())[0])
)
t1 = [
row_index
for row_index in range(shape[1])
if condition(
{
column : values[row_index]
for column, values in data_frame.items()
}
)
]
return {
column : [
values[row_index]
for row_index in t1
]
for column, values in data_frame.items()
}
def pandas_row(data_frame, row_index):
return {
column : values[row_index]
for column, values in data_frame.items()
}
def pandas_shape(data_frame):
columns_count = len(data_frame)
if columns_count > 0:
rows_count = len(data_frame[
next(iter(data_frame.keys()))
])
else:
rows_count = 0
return [
columns_count,
rows_count,
]
def ps_regex(groups_cnt):
assert groups_cnt >= 1
return ''.join([
r'^\s*',
r'([^\s]+)\s+' * (groups_cnt - 1),
r'([^\s]+)\s*$',
])
def oom_get_processes():
with io.BytesIO(
subprocess.check_output(
'ps -e -o pid,rss,user,%cpu',
shell=True
)
) as f:
t1 = pandas_data_frame(
f.read().decode('utf-8').splitlines(),
ps_regex(4),
ps_regex(4),
dict(
PID=lambda row: int(row['PID']),
RSS=lambda row: int(row['RSS']),
CPU=lambda row: float(row['%CPU']),
),
)
del t1['%CPU']
assert set(t1.keys()) == set(['PID', 'RSS', 'USER', 'CPU'])
t5 = subprocess.check_output(
'ps -e -o pid,args',
shell=True
).decode('utf-8').splitlines()
t6 = pandas_data_frame(
t5,
r'^\s*(\d+)\s(.*)$',
r'^\s+(\w+)\s+(\w+)\s*$',
dict(
PID=lambda row: int(row['PID'])
),
)
if not 'COMMAND' in t6:
if sys.platform == 'darwin' and 'ARGS' in t6:
t6['COMMAND'] = t6['ARGS']
del t6['ARGS']
else:
raise NotImplementedError
assert set(t6.keys()) == set(['PID', 'COMMAND'])
t11 = pandas_merge(t1, t6, on='PID')
t7 = pandas_filter_values(
t11,
lambda row: \
row['PID_x'] != self_pid and \
not 'freelancer' in row['COMMAND_y']
)
t8 = pandas_sort_values(
t7,
by=['RSS_x'],
ascending=False
)
t9 = pandas_sort_values(
t7,
by=['CPU_x'],
ascending=False
)
t10 = sum(t9['CPU_x'], 0.0) / 100
if options.debug:
pprint.pprint([t9['CPU_x'][:10], t10 * 100])
return dict(
by_mem=t8,
by_cpu=t9,
total_cpu=t10,
)
def oom_display_rows(current_dataframe):
print('\n'.join([
(
lambda row: \
'% 8d\t% 6.3f GiB\t% 5.2f %%\t% 10s\t%s' % (
row['PID_x'],
row['RSS_x'] / 1024 / 1024,
row['CPU_x'],
row['USER_x'],
row['COMMAND_y'],
)
)(
pandas_row(current_dataframe, k)
)
for k in range(
0,
min(
5,
pandas_shape(current_dataframe)[1],
)
)
]))
def oom_kill(pid):
assert isinstance(pid, int)
try:
logging.info('%s oom_kill, pid %d' % (
datetime.datetime.now().isoformat(),
pid,
))
os.kill(pid, signal.SIGKILL)
except:
logging.error(traceback.format_exc())
custom_notify(
msg='oom_kill, failed to kill pid %d' % pid
)
def oom_status():
print(
'\r%s %6.2f / %.2f %%, %6.2f / %.2f GiB' % (
datetime.datetime.now().isoformat(),
oom_mean_cpu() / os.cpu_count() * 100,
options.cpu_limit / os.cpu_count() * 100,
memory_stats()['mem_used'] / 1024 / 1024,
options.memory_limit / 1024 / 1024,
),
end=''
)
def first_check():
current_memory_stats = memory_stats()
t11 = oom_get_processes()
t8 = t11['by_mem']
if current_memory_stats['mem_used'] > options.memory_limit:
oom_display_rows(t8)
if t11['total_cpu'] > options.cpu_limit:
oom_display_rows(t11['by_cpu'])
free_before_oom = (
options.memory_limit - current_memory_stats['mem_used']
)
print(
'available %5.2f %% out of %5.2f %% of cpu limit before OOC' % (
(options.cpu_limit - t11['total_cpu']) * 100 / os.cpu_count(),
options.cpu_limit * 100 / os.cpu_count(),
)
)
print(
'%5.2f GiB [%5.2f %%] out of %5.2f GiB of free memory before OOM' % (
free_before_oom / 1024 / 1024,
free_before_oom / options.memory_limit * 100,
options.memory_limit / 1024 / 1024,
)
)
del t8
del t11
print('press Enter to start monitoring: ...', end='')
input()
print('\nstarted...')
first_check()
last_total_cpu = []
last_cpu_high = None
def oom_add_cpu(total_cpu):
if options.debug:
pprint.pprint([total_cpu, last_total_cpu])
last_total_cpu.append(total_cpu)
if len(last_total_cpu) > options.mean_size:
del last_total_cpu[-options.mean_size:]
def oom_mean_cpu():
return sum(last_total_cpu) / (len(last_total_cpu) + 1e-8)
def oom_cpu_high():
nonlocal last_cpu_high
if oom_mean_cpu() > options.cpu_limit:
if last_cpu_high is None:
last_cpu_high = datetime.datetime.now().timestamp()
if datetime.datetime.now().timestamp() - last_cpu_high > options.cpu_wait:
last_cpu_high = None
del last_total_cpu[:]
return True
return False
while True:
mem_used = memory_stats()['mem_used']
t11 = oom_get_processes()
oom_add_cpu(t11['total_cpu'])
t8 = t11['by_mem']
t9 = t8
t4 = lambda : oom_kill(t9['PID_x'][0])
t10 = lambda : mem_used > options.memory_limit
oom_status()
if t10():
print('\n', end='')
pprint.pprint([
'Killing [OOM]',
pandas_row(t9, 0),
mem_used,
])
t4()
if oom_cpu_high():
oom_display_rows(t11['by_cpu'])
print('\n', end='')
pprint.pprint([
'Killing [CPU]',
pandas_row(t11['by_cpu'], 0),
[options.cpu_limit, oom_mean_cpu(), t11['total_cpu']],
])
oom_kill(t11['by_cpu']['PID_x'][0])
time.sleep(options.period)
def resilient_vlc(stream=None):
if stream is None:
streams_path = os.path.join(
os.environ['CACHE_PATH'],
'resilient-vlc-streams.json'
)
if os.path.exists(streams_path):
with io.open(
streams_path,
'r'
) as f:
stream = json.load(f)
else:
raise RuntimeError(
'not found, %s' % streams_path
)
if isinstance(stream, str):
stream = [stream]
if len(stream) == 0:
raise RuntimeError('no streams')
import subprocess
import time
while True:
print('new start')
with subprocess.Popen([
'cvlc', '--verbose', '2', *stream,
], stderr=subprocess.PIPE) as p:
while p.returncode is None:
t1 = p.stderr.readline().decode('utf-8')
if len(t1) > 0:
print(t1)
if not all([
o in t1
for o in [
'prefetch stream error',
'terror',
'main interface error',
]
]) and any([
o in t1
for o in [
'pulse audio output debug: underflow'
]
]):
print('shit')
p.kill()
while True:
try:
t2 = p.wait(timeout=1)
print(t2)
break
except:
print('shit')
pass
time.sleep(1.0)
def sway_sock():
import glob
uid = os.stat(os.environ['HOME']).st_uid
t1 = glob.glob(
os.path.join(
'/run',
'user',
'%d' % uid,
'sway-ipc.%d*.sock' % uid,
)
)
t2 = [
os.stat(o).st_mtime
for o in t1
]
t3 = sorted(enumerate(t1), key=lambda x: t2[x[0]])[-1][0]
return t1[t3]
def eternal_firefox(
tabs=None,
profile=None,
group_name=None,
window_position=None,
debug=None,
):
import os
import datetime
import pprint
import subprocess
import time
if debug is None:
debug = False
if tabs is None:
raise RuntimeError('no tabs provided')
if profile is None:
raise RuntimeError('no profile provided')
if group_name is None:
raise RuntimeError('no group provided')
if window_position is None:
#window_position = '1,600,0,600,540'
raise RuntimeError('no window-position provided')
while True:
os.system(r'''date''')
with subprocess.Popen([
'firefox',
'-P', profile,
*tabs,
]) as p:
try:
if debug:
assert subprocess.check_call(['notify-send', '%s:Starting' % group_name]) == 0
#t3 = ''
for k in range(300):
t1 = subprocess.check_output(r'''
swaymsg -t get_tree | jq -r '..|try select(.pid== %d)'
''' % p.pid, shell=True).decode('utf-8')
if len(t1) > 10:
break
#time.sleep(0.1)
#t1 = subprocess.check_output(['wmctrl', '-p', '-l']).decode('utf-8')
#t4 = [o for o in t1.splitlines() if str(p.pid) in o]
#if len(t4) == 1:
# t3 = t4[0]
# break
#if t3 == '':
# raise RuntimeError
#t2 = t3.split()[0]
#assert os.system('wmctrl -i -r %s -e %s' % (t2, window_position)) == 0
#assert os.system('wmctrl -i -r %s -b add,below' % t2) == 0
def reposition():
t1 = lambda s: \
s \
.replace('{{PID}}', str(p.pid)) \
.replace('{{X}}', str(window_position[1])) \
.replace('{{Y}}', str(window_position[2])) \
.replace('{{W}}', str(window_position[3])) \
.replace('{{H}}', str(window_position[4])) \
.replace('{{WORKSPACE}}', str(window_position[0]))
assert os.system(t1(r'''
swaymsg '[pid="{{PID}}"] move window to workspace {{WORKSPACE}}'
''')) == 0
if window_position[1] != '' and window_position[2] != '':
assert os.system(t1(r'''
swaymsg '[pid="{{PID}}"] floating enable' \
swaymsg '[pid="{{PID}}"] resize set width {{W}}px height {{H}}px' && \
swaymsg '[pid="{{PID}}"] move absolute position {{X}}px {{Y}}px'
''')) == 0
else:
assert os.system(t1(r'''
swaymsg '[pid="{{PID}}"] floating disable'
''')) == 0
if False:
for tab in tabs[1:]:
time.sleep(10)
assert subprocess.check_call([
'firefox',
'-P', profile,
'--new-tab',
tab,
]) == 0
reposition()
if debug:
assert subprocess.check_call(['notify-send', '%s:Started' % group_name]) == 0
start = datetime.datetime.now()
is_to_restart = lambda : (datetime.datetime.now() - start).total_seconds() >= 900 * 4
polling_count = 0
while not is_to_restart():
if polling_count == 0:
reposition()
if not p.poll() is None:
break
time.sleep(10)
polling_count += 1
if debug:
assert subprocess.check_call(['notify-send', '%s:Closing' % group_name]) == 0
#assert os.system('wmctrl -i -c %s' % t2) == 0
assert os.system(r'''
swaymsg '[pid="%d"] kill'
''' % (p.pid,)) == 0
except KeyboardInterrupt:
assert os.system(r'''
swaymsg '[pid="%d"] kill'
''' % (p.pid,)) == 0
break
except:
import traceback
import pprint
pprint.pprint(traceback.format_exc())
finally:
try:
p.wait(20)
except subprocess.TimeoutExpired:
pprint.pprint([p.pid, '20 seconds timeout', 'kill'])
p.kill()
if debug:
assert subprocess.check_call(['notify-send', '%s:Closed' % group_name]) == 0
def resilient_ethernet(ip_addr, ethernet_device):
subprocess.check_call(
r'''
sudo sh -c '\
while true; \
do ping -c 3 -w 3 -W 1 {{IP_ADDR}} || (\
ip link set {{ETHERNET_DEVICE}} down; \
ip link set {{ETHERNET_DEVICE}} up; \
sleep 4; true;\
); \
sleep 10; clear; date; \
done'
'''.replace(
'{{IP_ADDR}}',
ip_addr
).replace(
'{{ETHERNET_DEVICE}}}',
ethernet_device
),
shell=True
)
def http_server(argv):
assert isinstance(argv, list) and all([isinstance(o, str) for o in argv])
parser = optparse.OptionParser()
parser.add_option(
'--public',
dest='public',
action='store_true',
default=False,
)
parser.add_option(
'--port',
dest='port',
type='int',
default=80,
)
parser.add_option(
'--host',
dest='host',
type='str',
default='127.0.0.1',
)
options, args = parser.parse_args(argv)
assert options.port >= 1
try:
assert not socket.inet_aton(options.host) is None
subprocess.check_call([
'ping', '-w', '1',
options.host
])
except:
raise RuntimeError('invalid ip address %s' % options.host)
index_section = 'autoindex on;'
if options.public:
location_section = 'location / {%s}' % index_section
else:
token = os.urandom(16).hex()
print(
'access url is http://%s:%d/%s/' % (
options.host,
options.port,
token,
)
)
location_section = (
'location / {'
'deny all;'
'}'
'location /%s/ {'
'alias /app/;'
'%s'
'}'
) % (token, index_section)
subprocess.check_call(
r'''
sudo docker run \
-p %s:%d:80 \
-u root \
-it --entrypoint=/bin/bash \
-v $PWD:/app:ro \
nginx:latest \
-c 'echo "server{listen 80; charset UTF-8; root /app; %s}" > /etc/nginx/conf.d/default.conf; nginx -g "daemon off;"'
''' % (
options.host,
options.port,
location_section,
),
shell=True)
def pass_ssh_osx(argv):
assert isinstance(argv, list) and all([isinstance(o, str) for o in argv])
parser = optparse.OptionParser()
parser.add_option(
'--list',
dest='list',
default=False,
action='store_true',
)
parser.add_option(
'--pass_option',
dest='pass_option',
action='append',
default=[],
type=str,
)
parser.add_option(
'--clipboard_copy',
dest='clipboard_copy',
default=None,
type=str,
)
parser.add_option(
'--debug',
dest='debug',
action='store_true',
default=False,
)
assert sys.platform in ['darwin', 'linux']
options, args = parser.parse_args(argv)
if options.clipboard_copy is None:
if sys.platform == 'linux':
options.clipboard_copy = 'wl-copy'
elif sys.platform == 'darwin':
options.clipboard_copy = 'pbcopy'
else:
raise NotImplementedError
if len(args) == 0:
raise RuntimeError('ssh_command is required')
if options.debug:
print(options.pass_option)
pprint.pprint(args)
reset_gpg_agent = r'''
gpgconf --kill gpg-agent && \
gpgconf --reload gpg-agent
'''
if not options.list:
t1 = options.pass_option
assert len(t1) > 0
print(
'select on of pass names\n%s' % '\n'.join([
'%d: %s' % (k, v)
for k, v in enumerate(t1)
])
)
while True:
try:
t2 = input()
t3 = int(t2)
assert t3 >= 0 and t3 < len(t1)
break
except:
continue
command = r'''
%s
gpg \
--pinentry-mode=ask \
-q -u $(cat ~/.password-store/.gpg-id) \
--decrypt \
~/.password-store/%s.gpg && \
echo -n '['$?']' && \
%s
''' % (
reset_gpg_agent,
t1[t3],
reset_gpg_agent,
)
else:
command = 'pass list | less -R'
ssh_command = [
'ssh', '-C',
'-o', 'ConnectTimeout 10',
'-o', 'ServerAliveInterval 1',
*args,
'-t',
command,
]
if options.debug:
pprint.pprint(
dict(
ssh_command=ssh_command,
)
)
if options.list:
subprocess.check_call(ssh_command)
else:
def clipboard_set(text):
with subprocess.Popen([
options.clipboard_copy,
], stdin=subprocess.PIPE) as p:
p.stdin.write(text.encode('utf-8'))
p.stdin.flush()
p.stdin.close()
p.wait(1)
assert p.poll() == 0
with subprocess.Popen(
ssh_command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
) as p:
password = None
last_chunk = None
hide_password = False
pinentry_delimeter = b'\x1b>'
def transform_callback(data):
nonlocal hide_password
nonlocal pinentry_delimeter
data2 = None
if not last_chunk is None:
data = last_chunk['data'] + data
if hide_password:
data2 = b''
elif pinentry_delimeter in data:
hide_password = True
pos = data.rfind(pinentry_delimeter)
if pos == -1:
data2 = data
else:
data2 = data[:pos + len(pinentry_delimeter)]
elif data == b'':
#return b'\r\n'
return b''
else:
data2 = None
return data2
for chunk in intercept_output(
current_subprocess=p,
return_aggregated=True,
transform_callback=transform_callback,
real_time=True,
#timeout=10,
):
if chunk['aggregated']:
last_chunk = chunk
break
assert not last_chunk is None
assert last_chunk['returncode'] == 0
if options.debug:
pprint.pprint(last_chunk['data'])
if last_chunk['data'].endswith('\r\n[0]'.encode('utf-8')) and \
last_chunk['data'].rfind(pinentry_delimeter) != -1:
last_line = last_chunk['data'].splitlines()[-2]
else:
raise RuntimeError(
'gpg failure %s' % str(
last_chunk['data'][
max(last_chunk['data'].find(pinentry_delimeter), -128):
]
)
)
pos2 = last_line.rfind(pinentry_delimeter)
if pos2 == -1:
last_line2 = last_line
else:
last_line2 = last_line[
pos2 + len(pinentry_delimeter):
]
password = last_line2.decode('utf-8').rstrip('\r\n')
assert not password is None
clipboard_set(password)
get_time = lambda : datetime.datetime.now().timestamp()
start = get_time()
while True:
cur = get_time()
remains = 10 - (cur - start)
if remains <= 1e-8:
break
else:
print('\r%5.2fs remains' % remains, end='')
time.sleep(0.1)
clipboard_set('')
print('\rcleared cliboard\n', end='')
def player_v1(folder_url, item_id):
import sys
import urllib.parse
import re
import subprocess
import os
import tqdm
t4 = folder_url
t1 = subprocess.check_output(['curl', '-s', t4]).decode('utf-8')
t2 = re.compile(r"href=\"(.*\.mp3)\"");
t3 = [o.group(1) for o in t2.finditer(t1)];
t5 = ['%s/%s' % (t4, o) for o in t3]
t6 = item_id
t9 = range(t6, len(t5))
with tqdm.tqdm(
total=len(t5),
) as progress_bar:
progress_bar.update(t6)
for k in t9:
t7 = t5[k]
t9 = urllib.parse.unquote(os.path.split(t7)[1])
progress_bar.set_description('%03d %s' % (k, t9))
with subprocess.Popen(['ffprobe', '-hide_banner', '-i', t7], stderr=subprocess.PIPE, stdout=subprocess.PIPE) as p:
p.wait()
assert p.returncode == 0
t8 = p.stderr.read().decode('utf-8')
#print(t8)
with subprocess.Popen(['ffplay', '-hide_banner', '-nodisp', '-autoexit', '-loop', '1', t7], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) as p:
p.wait()
assert p.returncode == 0
progress_bar.update(1)
def numpy_linspace(a, b, count):
pos = a
step = (b - a) / count
steps = []
for i in range(count):
if i == 0:
pos = a
elif i == count - 1:
pos = b
else:
pos = a + i * step
steps.append(pos)
return steps
def desktop_services(argv):
parser = optparse.OptionParser()
parser.add_option(
'--background_image',
dest='background_image',
default=None,
type=str,
)
parser.add_option(
'--cpufreq',
dest='cpufreq',
default=None,
type=int,
help='0 - mac book air (no turbo boost, max pct 30, every 4 seconds',
)
parser.add_option(
'--battery',
dest='battery',
default=None,
type=int,
help='0 - battery check with sleep <10%, every 10 seconds',
)
parser.add_option(
'--backlight-increase',
dest='backlight_increase',
default=False,
action='store_true',
help='increase keyboard backlight',
)
parser.add_option(
'--backlight-type',
dest='backlight_type',
default=[],
action='append',
help='backlight type, like keyboard, output',
)
parser.add_option(
'--backlight-decrease',
dest='backlight_decrease',
default=False,
action='store_true',
help='decrease keyboard backlight',
)
options, args = parser.parse_args(argv)
class Battery:
def __init__(self, should_start=None,):
if should_start is None:
should_start = False
assert isinstance(should_start, bool)
self.last_check = None
self.period = 10
self.is_running = should_start
def check_is_needed(self):
now = datetime.datetime.now(tz=datetime.timezone.utc)
is_needed = None
if self.last_check is None:
is_needed = True
else:
if ((now - self.last_check).total_seconds() >= self.period):
is_needed = True
else:
is_needed = False
if is_needed:
self.last_check = now
return is_needed
def run(self):
while True:
self.check()
time.sleep(self.period)
def terminate(self):
self.is_running = False
def wait(self, *args, **kwargs):
if self.is_running:
raise NotImplementedError
def poll(self):
if self.is_running:
return None
else:
return 0
def check(self):
try:
if not self.check_is_needed():
return
t1 = subprocess.check_output(
['upower', '-d'],
timeout=1,
).decode('utf-8')
t2 = [
o for o in t1.splitlines() if 'percentage' in o.lower()
]
t4 = [
o for o in t1.splitlines() if 'state' in o.lower()
]
t3 = float(t2[0].split(':')[1].strip()[:-1])
t5 = any(['discharging' in o.lower() for o in t4])
if t3 < 10 and t5:
logging.error(json.dumps(dict(
msg='too low', t3=t3, t5=t5
)))
subprocess.check_call(['systemctl', 'suspend'])
elif t3 < 15 and t5:
msg = 'battery near low'
logging.error(json.dumps(dict(
msg=msg, t3=t3, t5=t5
)))
subprocess.check_call([
'notify-send', '-t', '%d' % (5 * 1000), msg
])
else:
pass
print(
'\r%s % 5.2f%% %s' % (
datetime.datetime.now().isoformat(), t3, str(t5)
),
end=''
)
except:
print(traceback.format_exc())
class Backlight:
class Direction(enum.Enum):
increase = 'increase'
decrease = 'decrease'
absolute = 'absolute'
get_state = 'get_state'
class Mode(enum.Enum):
light = 'light'
def __init__(self):
self.state = []
self.dpms = Backlight.dpms_get()
@classmethod
def dpms_get(cls):
try:
t1 = subprocess.check_output(['swaymsg', '-r', '-t', 'get_outputs'])
t2 = t1.decode('utf-8')
t3 = json.loads(t2)
t4 = [
dict(
id=o['id'],
name=o['name'],
dpms=o['dpms'],
)
for o in t3
]
return any([o['dpms'] for o in t4])
except:
return True
def check(self):
try:
new_dpms = Backlight.dpms_get()
if new_dpms != self.dpms:
logging.info(json.dumps(dict(
module='backlight',
action='new_dpms',
dpms=self.dpms,
new_dpms=new_dpms,
)))
if new_dpms:
Backlight.enable(self.state)
else:
self.state = Backlight.change(
Backlight.Direction.get_state,
)
logging.info(json.dumps(dict(
state=pprint.pformat(
self.state,
width=1e+8,
compact=True,
),
action='disable',
)))
Backlight.disable()
self.dpms = new_dpms
except:
logging.error(traceback.format_exc())
@classmethod
def get_state(cls):
raise NotImplementedError
@classmethod
def set_state(cls):
raise NotImplementedError
@classmethod
def disable(cls):
return cls.change(
cls.Direction.absolute,
0,
)
@classmethod
def enable(cls, state,):
res = []
for device_state in state:
res.append(
cls.change(
direction=cls.Direction.absolute,
value=device_state['value'],
device_name=device_state['device_name'],
)
)
return res
@classmethod
def change(
cls,
direction,
value=None,
devices=None,
device_name=None,
types=None,
):
assert isinstance(direction, Backlight.Direction)
state = []
devices_all = dict(
smc_kbd=dict(
sysfs_path='sysfs/leds/smc::kbd_backlight',
),
intel_backlight=dict(
sysfs_path='sysfs/backlight/intel_backlight',
),
)
if devices is None:
devices = []
if not device_name is None:
devices.append(device_name)
if len(devices) == 0:
if types is None:
types = [
'keyboard',
'output',
]
for current_type in types:
if current_type == 'keyboard':
devices.extend([
'smc_kbd'
])
elif current_type == 'output':
devices.extend([
'intel_backlight',
])
else:
raise NotImplementedError
else:
assert types is None
devices2 = list(set(devices))
if sys.platform == 'linux':
assert all([
o in devices_all
for o in devices2
])
leds = \
[
o.strip()
for o in subprocess.check_output(
['light', '-L'],
timeout=1,
)\
.decode('utf-8')\
.splitlines()[1:]
]
for current_device_name in devices2:
device = devices_all[current_device_name]
sysfs_path = device['sysfs_path']
if not sysfs_path in leds:
raise NotImplementedError
extra_args = []
if value is None:
value = 20.0
value2 = max(float(value), 0.0)
assert isinstance(value2, float) and value >= -1e-8
if direction == cls.Direction.increase:
extra_args.extend(['-A', '%f' % value2])
elif direction == cls.Direction.decrease:
extra_args.extend(['-U', '%f' % value2])
elif direction == cls.Direction.absolute:
extra_args.extend(['-S', '%f' % value2])
elif direction == cls.Direction.get_state:
pass
else:
raise NotImplementedError
get_current = lambda : float(subprocess.check_output([
'light', '-G',
'-s', sysfs_path,
], timeout=1).decode('utf-8'))
if not (direction == cls.Direction.get_state):
old_value = get_current()
value_steps = None
if direction == cls.Direction.decrease:
value_steps = numpy_linspace(
old_value,
max(old_value - value2, 0),
10,
)
elif direction == cls.Direction.increase:
value_steps = numpy_linspace(
old_value,
min(old_value + value2, 100),
10,
)
elif direction == cls.Direction.absolute:
value_steps = numpy_linspace(
old_value,
min(
max(
0,
value2,
),
100
),
10,
)
else:
raise NotImplementedError
for current_value in value_steps:
subprocess.check_call(
[
'light', '-v', '3',
'-s', sysfs_path,
'-S', '%f' % current_value,
],
stderr=subprocess.PIPE,
stdout=subprocess.PIPE
)
time.sleep(0.05)
state.append(
dict(
mode=cls.Mode.light,
device_path=sysfs_path,
device_name=current_device_name,
value=get_current(),
)
)
else:
raise NotImplementedError
return state
if options.backlight_increase or options.backlight_decrease:
if options.backlight_increase:
direction = Backlight.Direction.increase
elif options.backlight_decrease:
direction = Backlight.Direction.decrease
else:
raise NotImplementedError
Backlight.change(
direction=direction,
types=options.backlight_type,
)
return
else:
pass
os.environ['SWAYSOCK'] = sway_sock()
assert all([
env_name in os.environ
for env_name in [
'GTK_IM_MODULE',
'XMODIFIERS',
'QT_IM_MODULE',
'I3SOCK',
'SWAYSOCK',
'WAYLAND_DISPLAY',
]
]) and os.environ['SWAYSOCK'] == sway_sock()
services = []
shutdown = False
def on_interrupt(*args, **kwargs):
nonlocal shutdown
shutdown = True
signal.signal(
signal.SIGINT,
on_interrupt,
)
signal.signal(
signal.SIGTERM,
on_interrupt,
)
try:
if options.cpufreq == 0:
print('launching cpufreq, need sudo')
subprocess.check_call(['sudo', 'whoami'])
services.append(
subprocess.Popen(r'''
exec sudo sh -c 'echo cpufreq, user; whoami;
while [[ -a /proc/{pid} ]]; do
echo passive > /sys/devices/system/cpu/intel_pstate/status;
echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo;
echo 40 > /sys/devices/system/cpu/intel_pstate/max_perf_pct;
for cpu_path in /sys/devices/system/cpu/cpu?; do
echo 900000 > $cpu_path/cpufreq/scaling_max_freq;
echo schedutil > $cpu_path/cpufreq/scaling_governor;
done;
sleep 10;
done;'
'''.format(pid=os.getpid()), shell=True)
)
class start_swayidle:
def __init__(self):
swaylock_cmd = [
'swaylock', '-f', '-d',
]
if not options.background_image is None:
swaylock_cmd.extend(
[
'-i',
'"%s"' % options.background_image,
]
)
subprocess.check_call([
'swaymsg',
'--',
'output',
'*',
'bg',
options.background_image,
'fill',
])
self.commands = dict(
swaylock_cmd2=' '.join(swaylock_cmd),
timeout1='echo timeout1; swaymsg "output * dpms off";',
lock='echo lock; pkill --signal SIGUSR1 swayidle;',
unlock='echo unlock; pkill --signal SIGINT swaylock; swaymsg "output * dpms on";',
unlock2='pkill --signal SIGINT swaylock;',
resume='echo resume; swaymsg "output * dpms on";',
before_sleep='echo before_sleep; loginctl lock-session;',
after_resume='echo after_resume; pkill --signal SIGUSR1 swayidle;',
)
self.last_force_idle = None
self.commands.update(
timeout2='echo timeout2; {swaylock_cmd};'.format(
swaylock_cmd=self.commands['swaylock_cmd2']
)
)
self.swayidle = subprocess.Popen(
r'''
exec swayidle -d -w \
timeout 300 'echo t1; read;' \
resume 'echo t5; ' \
timeout 900 'echo t4; read;' \
resume 'echo t5; ' \
lock 'echo t2; read;' \
unlock 'echo t3;' \
before-sleep 'echo t6; read;' \
after-resume 'echo t7; read;'
''',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
self.output = intercept_output(
self.swayidle,
real_time=True,
)
self.events = []
self.data = []
self.backlight = Backlight()
def poll(self):
return self.swayidle.poll()
def release_lock(self):
self.swayidle.stdin.write(b'\n')
self.swayidle.stdin.flush()
def force_idle(self):
if self.last_force_idle is None or (
datetime.datetime.now() - self.last_force_idle
).total_seconds() >= 10:
self.last_force_idle = datetime.datetime.now()
return True
else:
return False
def terminate(self, *args, **kwargs):
return self.swayidle.terminate(*args, **kwargs)
def wait(self, *args, **kwargs):
return self.swayidle.wait(*args, **kwargs)
def kill(self):
return self.swayidle.kill()
def dpms(self, direction):
assert direction in ['on', 'off']
raise NotImplementedError
def check(self):
while True:
if self.output is None:
break
chunk = next(self.output)
if chunk['aggregated']:
self.output = None
continue
if len(chunk['data']) == 0:
break
self.data.append(chunk)
if b'\n' in chunk['data']:
total = b''.join([
o['data']
for o in self.data
]).decode('utf-8')
sep_pos = total.rfind('\n')
lines = total[:sep_pos].splitlines()
self.data = [
dict(
data=total[sep_pos:].encode('utf-8'),
aggregated=False,
)
]
self.events.extend([
line
for line in lines
if line in [
't1', 't2', 't3', 't4',
't5', 't5', 't6', 't7',
] or (
'idle state' in line or \
'active state' in line
)
])
def retry(cb, cnt=None):
if cnt is None:
cnt = 10
i = 0
while True:
print('retry i = %d, cnt = %d' % (i, cnt))
if not (
subprocess.call(['swaymsg', '-t', 'get_version']) == 0
):
continue
if cb() == 0:
break
time.sleep(0.5)
i += 1
if len(self.events) > 0:
for o in self.events:
if o == 't1':
#if self.force_idle():
# subprocess.check_call(self.commands['lock'], shell=True)
print('started t1')
if self.force_idle():
subprocess.check_call(self.commands['timeout1'], shell=True)
print('done t1')
self.release_lock()
elif o == 't2':
print('started lock')
if self.force_idle():
subprocess.check_call(self.commands['lock'], shell=True)
subprocess.call(self.commands['timeout2'], shell=True)
subprocess.check_call(self.commands['timeout1'], shell=True)
print('done lock')
self.release_lock()
elif o == 't3':
pass
elif o == 't4':
print('started t4')
if self.force_idle():
subprocess.check_call(self.commands['lock'], shell=True)
subprocess.call(self.commands['timeout2'], shell=True)
subprocess.check_call(self.commands['timeout1'], shell=True)
print('done t4')
self.release_lock()
elif o == 't5':
print('started timeout resume')
if self.force_idle():
subprocess.check_call(self.commands['lock'], shell=True)
retry(
lambda: subprocess.call(self.commands['resume'], shell=True),
)
print('done timeout resume')
elif o == 't6':
print('started before-sleep')
if self.force_idle():
subprocess.call(self.commands['timeout2'], shell=True),
subprocess.check_call(self.commands['timeout1'], shell=True),
print('done before-sleep')
self.release_lock()
elif o == 't7':
print('started after-resume')
#if self.force_idle():
#subprocess.check_call(self.commands['lock'], shell=True)
while True:
if subprocess.call(
self.commands['resume'],
shell=True
) == 0:
break
else:
time.sleep(0.5)
print('done after-resume')
self.release_lock()
else:
raise NotImplementedError
pprint.pprint(self.events)
del self.events[:]
self.backlight.check()
services.extend([
subprocess.Popen(['ibus-daemon']),
start_swayidle(),
])
if not options.battery is None:
assert options.battery in [0]
print('launching battery')
services.append(
Battery(
should_start=True,
)
)
while True:
if shutdown:
print('shutdown')
break
if all([not o.poll() is None for o in services]):
print('done')
break
for o in services:
if hasattr(o, 'check'):
o.check()
time.sleep(0.1)
except:
logging.error(traceback.format_exc())
finally:
for o in services:
try:
o.terminate()
o.wait(timeout=10)
except:
logging.error(traceback.format_exc())
logging.error('killed %s' % str(o.__dict__))
o.kill()
def suspend_timer(argv):
import datetime;
import subprocess;
import time;
import sys;
if len(argv) == 0:
print("enter HH:MM");
t3 = input().strip()
else:
t3 = argv[0]
t2 = datetime.datetime.strptime(t3, "%H:%M").time()
while True:
t1 = datetime.datetime.now()
if ((t1.hour, t1.minute) >= (t2.hour, t2.minute)):
break
else:
t3 = [
(t2.hour - t1.hour),
t2.minute - t1.minute
]
if t3[1] < 0:
t3[1] += 60
t3[0] -= 1
print("\r%s, %02d:%02d" % (
t1,
*t3,
), end="")
time.sleep(1)
print("suspend computer at %s" % t1.isoformat())
subprocess.check_call(["systemctl", "suspend"]);
def socat_ssh(argv):
parser = optparse.OptionParser()
parser.add_option(
'--local_port',
dest='local_port',
default=None,
type=int,
)
parser.add_option(
'--ssh_key',
dest='ssh_key',
default=None,
type=str,
)
parser.add_option(
'--socat_verbose',
dest='socat_verbose',
action='store_true',
default=False,
)
parser.add_option(
'--ssh_host',
dest='ssh_host',
default=None,
type=str,
)
parser.add_option(
'--target_port',
dest='target_port',
default=None,
type=int,
)
parser.add_option(
'--ssh_command',
dest='ssh_command',
default=None,
type=str,
)
parser.add_option(
'--gateway_command',
dest='gateway_command',
default=None,
type=str,
help=(
'a shell command that forwards ssh socket data '
'somewhere else, like '
'busybox nc 127.0.0.1 $(cat remote-ssh.port)'
),
)
options, args = parser.parse_args(argv)
if options.ssh_command is None:
ssh_command = ['ssh', '-T', '-C']
else:
ssh_command = options.ssh_command.split()
if not options.ssh_key is None:
subprocess.check_call(['ssh-add', options.ssh_key])
ssh_command.extend([
'-i', options.ssh_key,
])
if not options.ssh_host is None:
ssh_command.extend([options.ssh_host])
restart = False
def on_interrupt(*args, **kwargs):
nonlocal restart
restart = True
socat_command = ['socat']
if options.socat_verbose:
socat_command.extend(['-v'])
socat_command.extend([
'tcp-listen:%d,fork,bind=127.0.0.1' % (
options.local_port,
),
])
signal.signal(
signal.SIGINT,
on_interrupt,
)
signal.signal(
signal.SIGTERM,
on_interrupt,
)
gateway = None
p = None
while True:
if gateway is None:
gateway = tempfile.NamedTemporaryFile(suffix='.sh', mode='w')
gateway.write(
r'''
exec %s
''' % ' '.join(
ssh_command + [options.gateway_command]
)
)
gateway.flush()
if p is None:
p = subprocess.Popen(
socat_command + [
'EXEC:sh %s' % gateway.name,
]
)
time.sleep(1)
if restart:
try:
p.terminate()
p.wait(10)
except:
p.kill()
restart = False
if not p.poll() is None:
p = None
if not gateway is None:
os.path.unlink(gateway.name)
if not p is None:
p.terminate()
def share_wifi(argv):
parser = optparse.OptionParser()
parser.add_option(
'--to-wifi',
dest='to_wifi',
default=None,
type=str,
)
parser.add_option(
'--from-eth',
dest='from_eth',
default=None,
type=str,
)
parser.add_option(
'--ap-name',
dest='ap_name',
default=None,
type=str,
)
parser.add_option(
'--restart-delay',
dest='restart_delay',
default=None,
type=int,
)
options, args = parser.parse_args(argv)
if options.restart_delay is None:
options.restart_delay = 2
assert not options.to_wifi is None
assert not options.from_eth is None
assert not options.ap_name is None
assert options.restart_delay >= 1
print('enter password:')
pw = subprocess.check_output(
'read -s PW; echo -n $PW',
shell=True
).decode('utf-8')
if len(pw) == 0:
p2 = subprocess.check_output(
'pwgen -syn 20 1',
shell=True
).decode('utf-8')
with subprocess.Popen(
['qrencode', '-t', 'UTF8'],
stdin=subprocess.PIPE
) as p:
p.stdin.write(pw.encode('utf-8'))
p.stdin.flush()
p.stdin.close()
try:
p.wait(5)
except Exception as exception:
p.kill()
raise exception
last_timestamp = datetime.datetime.now()
hostapd = None
restart = False
def on_interrupt(*args, **kwargs):
nonlocal restart
restart = True
signal.signal(
signal.SIGINT,
on_interrupt,
)
signal.signal(
signal.SIGTERM,
on_interrupt,
)
while True:
try:
if hostapd is None:
print('\n%s, start new' % last_timestamp)
hostapd = subprocess.Popen([
'create_ap',
'--hostapd-timestamps',
options.to_wifi,
options.from_eth,
options.ap_name,
pw,
])
else:
if restart:
print('\n%s, shutdown current' % last_timestamp)
os.kill(
hostapd.pid,
signal.SIGINT
)
try:
hostapd.wait(20)
except:
hostapd.terminate()
restart = False
if not hostapd.poll() is None:
hostapd = None
if (
datetime.datetime.now() - last_timestamp
).total_seconds() > options.restart_delay:
restart = True
last_timestamp = datetime.datetime.now()
except:
print(traceback.format_exc())
restart = True
finally:
time.sleep(1)
def status(argv):
import inspect
import textwrap
assert isinstance(argv, list) and all([isinstance(o, str) for o in argv])
class c1(optparse.IndentedHelpFormatter):
def format_option(self, *args, **kwargs):
f1 = lambda text, width: '\n'.join([
textwrap.fill('\t' + o, width, replace_whitespace=False)
for o in text.splitlines()
]).splitlines()
t1 = inspect.getsource(optparse.IndentedHelpFormatter.format_option)
t2 = '\n'.join([o[4:] for o in t1.splitlines()[:]]).replace(
'textwrap.wrap', 'f1',
).replace('format_option', 'f2')
exec(t2, dict(f1=f1), locals())
return locals()['f2'](self, *args, **kwargs)
parser = optparse.OptionParser(
formatter=c1(
width=None,
),
)
parser.add_option(
'--sh',
dest='sh',
default=[],
action='append',
type=str,
)
parser.add_option(
'--timeout',
dest='timeout',
default=None,
type=float,
)
parser.add_option(
'--config',
dest='config',
default=None,
type=str,
help=''.join([
'.json file with array of strings, each is a shell command ',
'that outputs a separate status text value, ',
'like\n',
r'''
ping -w 1 -i 0.02 <hostname> -c 3 | tail -n 2| head -n 1 | grep -Po $'time\\s+.*$'
sensors -j | jq -r '.\"coretemp-isa-0000\".\"Package id 0\".temp1_input|tostring + \" C\"'
printf '%d RPM' $(cat /sys/devices/platform/applesmc.768/fan1_input)
printf '% 3.0f%%' $(upower -d | grep -Po 'percentage:\\s+\\d+(\\.\\d+)?%' | grep -Po '\\d+(\\.\\d+)?' | head -n 1)
'''.strip()
])
)
options, args = parser.parse_args(argv)
if options.timeout is None:
options.timeout = 0.5
timeout2 = max(options.timeout, 0.0)
assert timeout2 >= 0.0 and timeout2 <= 4
config = dict()
try:
if not options.config is None:
with io.open(options.config, 'r') as f:
config.update(
json.load(f)
)
except:
logging.error(traceback.format_exc())
pass
options.sh.extend(
config.get('sh', [])
)
t1 = []
for sh_index, o in enumerate([
*options.sh,
*[
r'''
free -h | \
grep -P Mem: | grep -Po '[\w\.\d]+' | tail -n +2 | head -n 3 | xargs echo -n;
''',
r'''
date +'%Y-%m-%d %l:%M:%S %p';
''',
],
]):
try:
t1.append(
subprocess.check_output(
o,
shell=True,
timeout=timeout2,
).decode('utf-8').strip()
)
except:
t1.append('fail %d' % sh_index)
t3 = ' | '.join(t1).replace('\n\r', '')
sys.stdout.write(t3)
sys.stdout.flush()
def custom_translate(current_string, check, none_char=None,):
if none_char is None:
none_char = '.'
class A:
def __getitem__(self, k):
t1 = chr(k)
t2 = check(k, t1)
if isinstance(t2, bool):
if t2:
return t1
else:
return none_char
elif isinstance(t2, str):
return t2
return current_string.translate(
A()
)
def media_keys(argv):
assert isinstance(argv, list) and all([isinstance(o, str) for o in argv])
parser = optparse.OptionParser()
parser.add_option(
'--command',
dest='command',
type=str,
default=None,
)
options, args = parser.parse_args(argv)
if options.command is None and len(args) > 0:
assert len(args) == 1
options.command = args[0]
assert options.command in [
'media-play-pause',
'media-next',
'media-prev',
'media-lower-volume',
]
msg = None
mode = None
is_mocp = lambda : \
subprocess.call([
'pgrep',
'-u', os.environ['USER'],
'mocp',
], stdout=subprocess.PIPE) == 0
def mocp_info():
t1 = subprocess.check_output(['mocp', '-i'])
t3 = t1.decode('utf-8')
t2 = dict([
tuple(o.split(':')[:2])
for o in t3.splitlines()
])
return t2['Title'].strip()[:128]
if is_mocp:
mode = 'mocp'
else:
mode = 'playerctl'
if options.command == 'media-play-pause':
if mode == 'mocp':
subprocess.check_call(['mocp', '--toggle-pause'])
msg = mocp_info()
elif mode == 'playerctl':
subprocess.check_call(['playerctl', 'play-pause'])
msg = player_metadata()
else:
raise NotImplementedError
elif options.command == 'media-next':
if mode == 'mocp':
subprocess.check_call(['mocp', '--next'])
msg = mocp_info()
elif mode == 'playerctl':
subprocess.check_call(['playerctl', 'next'])
msg = player_metadata()
else:
raise NotImplementedError
elif options.command == 'media-prev':
if mode == 'mocp':
subprocess.check_call(['mocp', '--previous'])
msg = mocp_info()
elif mode == 'playerctl':
subprocess.check_call(['playerctl', 'previous'])
msg = player_metadata()
else:
raise NotImplementedError
elif options.command == 'media-lower-volume':
subprocess.check_call([
'pactl',
'set-sink-volume',
'@DEFAULT_SINK@',
'-5%'
])
msg = subprocess.check_output([
'pactl',
'get-sink-volume',
'@DEFAULT_SINK@'
]).decode('utf-8').strip()
elif options.command == 'media-raise-volume':
subprocess.check_call([
'pactl',
'set-sink-volume',
'@DEFAULT_SINK@',
'+5%'
])
msg = subprocess.check_output([
'pactl',
'get-sink-volume',
'@DEFAULT_SINK@'
]).decode('utf-8').strip()
else:
raise NotImplementedError
logging.info(
json.dumps(
dict(
command=options.command,
msg=msg,
mode=mode,
),
ensure_ascii=False
)
)
return dict(
msg=msg,
)
def commands_cli():
logging.getLogger().setLevel(logging.INFO)
msg = None
try:
if sys.argv[1].startswith('media'):
msg = media_keys(sys.argv[1:]).get('msg')
elif sys.argv[1] == 'status':
status(sys.argv[2:])
elif sys.argv[1] == 'http-server':
http_server(sys.argv[2:])
elif sys.argv[1] == 'pass-ssh-osx':
pass_ssh_osx(sys.argv[2:])
elif sys.argv[1] == 'wl-screenshot':
subprocess.check_call(r'''
grim -g "$(slurp)" - | wl-copy
''', shell=True)
elif sys.argv[1] == 'chrome':
chrome(sys.argv[2:])
elif sys.argv[1] == 'eternal-oom':
eternal_oom(sys.argv[2:])
elif sys.argv[1] == 'resilient-vlc':
resilient_vlc(sys.argv[2:])
elif sys.argv[1] == 'eternal-firefox':
eternal_firefox(
profile=sys.argv[2],
group_name=sys.argv[3],
window_position=json.loads(sys.argv[4]),
debug=json.loads(sys.argv[5]),
tabs=sys.argv[6:],
)
elif sys.argv[1] == 'resilient-ethernet':
resilient_ethernet(
ip_addr=sys.argv[2],
ethernet_device=sys.argv[3],
)
elif sys.argv[1] == 'player':
player_v1(
folder_url=sys.argv[2],
item_id=int(sys.argv[3]),
)
elif sys.argv[1] == 'share-wifi':
share_wifi(sys.argv[2:])
elif sys.argv[1] == 'socat-ssh':
socat_ssh(sys.argv[2:])
elif sys.argv[1] == 'sway_sock':
print(sway_sock())
elif sys.argv[1] == 'suspend-timer':
suspend_timer(sys.argv[2:])
elif sys.argv[1] == 'desktop-services':
desktop_services(sys.argv[2:])
else:
raise NotImplementedError
except SystemExit:
pass
except:
msg = 'not implemented\n%s' % traceback.format_exc()
logging.error(msg)
if not msg is None:
custom_notify(msg=msg)
if __name__ == '__main__':
commands_cli()