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
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)
|
|
|