HamClock Remote Access
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

163 lines
4.1 KiB

import os
import base64
import threading
import random
import time
import shutil
import tempfile
import tornado.web, tornado.websocket, tornado.ioloop
import imgproc as hcapi
import argon2
import asyncio
import importlib
import parse_config
import sys
try:
conf = sys.argv[1]
except IndexError:
conf = 'conf.txt'
with open(conf) as f:
config_data = parse_config.load(f)
hcapi.backend = importlib.import_module(f'backends.{config_data["backend"]}')
hcapi.backend.config = config_data
hcapi.config = config_data
ph = argon2.PasswordHasher()
client = None
class HCRAServer(tornado.websocket.WebSocketHandler):
def open(self):
global client
if client is not None:
self.write_message('err%*inuse%Server already in use')
self.close()
else:
client = self
self.items = {}
self.lock = threading.Lock()
self.good = True
try:
imgname = hcapi.get_full_img()
except Exception as e:
self.write_message('err%noconn%Server failed to capture screenshot')
return
with open(imgname, 'rb') as f:
img = f.read()
os.unlink(imgname)
self.write_message(f'pic%0x0%data:imgage/jpeg;base64,{base64.b64encode(img).decode("utf-8")}')
self.ack()
loop = asyncio.new_event_loop()
threading.Thread(target=self.run, args=(loop,)).start()
def send(self, item, name):
with self.lock:
self.items[name] = item
def ack(self):
with self.lock:
self.items['ack'] = 'ack'
async def cycle(self):
with self.lock:
while not self.good:
pass
for name, item in list(self.items.items()):
if not self.good:
break
self.write_message(item)
del self.items[name]
if item == 'ack':
self.good = False
def run(self, loop):
asyncio.set_event_loop(loop)
while True:
if client is not self:
break
loop.run_until_complete(self.cycle())
def on_close(self):
global client
if client is self:
self.good = None
client = None
def on_message(self, message):
action = message.split(' ', 1)[0]
if action == 'ack':
self.good = True
else:
_, password, x, y, w, is_long = message.split(' ')
try:
ph.verify(config_data['password_argon2'], password)
x, y, w, is_long = int(x), int(y), int(w), is_long == 'true'
hcapi.touch(x, y, w, is_long)
except argon2.exceptions.VerifyMismatchError:
self.send(f'err%*badpass%Incorrect password', 'BADPASS')
self.close()
def check_origin(self, origin):
return True
def cycle():
try:
changed = hcapi.get_split_imgs()
except Exception as e:
if client is not None:
client.send('err%noconn%Server failed to capture screenshot', 'ERR')
time.sleep(3)
return
for i in changed:
threading.Thread(target=do_img, args=(i,)).start()
if client is not None:
client.ack()
def do_img(imgname):
if client is not None:
client.send(img(imgname), imgname)
def img(imgname):
with open(f'pieces/{imgname}.jpg', 'rb') as f:
img = f.read()
response = f'pic%{imgname}%data:imgage/jpeg;base64,{base64.b64encode(img).decode("utf-8")}'
return response
def do_cycles():
while True:
if client is not None:
cycle()
time.sleep(0.4)
else:
time.sleep(1)
tmp = tempfile.mkdtemp(prefix="HCRA-")
try:
shutil.copy('crops.json', tmp)
os.chdir(tmp)
os.mkdir('pieces')
threading.Thread(target=do_cycles).start()
application = tornado.web.Application([
(r"/", HCRAServer),
])
application.listen(1234)
tornado.ioloop.IOLoop.current().start()
finally:
os.chdir('/')
shutil.rmtree(tmp)