summaryrefslogtreecommitdiffstats
path: root/prog/jelka/daemon.py
blob: a288f351189aed2dbcd0c2570eb1780cce8e0b98 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/python3
import flask
import threading
import os
import secrets
import subprocess
import hashlib
import base64
import time

http = flask.Flask(__name__)
onemogočeni = set(["onemogočen.py"])
skrivnost = secrets.token_bytes(8)
čas_vzorca = 5
proces = None
naslednji = None

def trenuten():
	if proces:
		return proces.args[1]
	return None

def http_event_stream():
	while sprememba_stanja.wait():
		print("geslo je: " + kode()[0])
		sprememba_stanja.clear()
		yield "data: " + http.json.dumps({"čas": čas_vzorca, "vzorci": os.listdir("vzorci"), "trenuten": trenuten(), "onemogočeni": [x for x in onemogočeni]}) + "\n\n"

@http.route("/vzorci/<vzorec>", methods=["GET"])
def vzorec(vzorec):
	if "/" in vzorec:
		return flask.Response(http.json.dumps({"napaka": {"koda": 3, "besedilo": "vzorec ne sme vsebovati poševnice"}}), status=403)
	return flask.send_file("vzorci/" + vzorec, mimetype="text/x-python")

@http.route("/", methods=["GET"])
def index():
	return flask.render_template("index.html");

@http.route("/stream/", methods=["GET"])
def stream():
	return flask.Response(http_event_stream(), headers={"Access-Control-Allow-Origin": "*", "Content-Type": "text/event-stream"})

@http.route("/<koda>", methods=["POST"])
def update(koda):
	global onemogočeni
	global čas_vzorca
	global naslednji
	if koda not in kode():
		return flask.Response(http.json.dumps({"napaka": {"koda": 1, "besedilo": "napačna koda"}}), status=200)
	data = flask.json.loads(flask.request.data)
	if "omogoči" in data.keys():
		onemogočeni -= set(data["omogoči"])
	if "onemogoči" in data.keys():
		onemogočeni |= set(data["onemogoči"])
	if "čas" in data.keys():
		if data["čas"] < 1 or data["čas"] > 300:
			return flask.Response(http.json.dumps({"napaka": {"koda": 2, "besedilo": "čas ni v [1,300]"}}), status=200)
		čas_vzorca = data["čas"]
	sprememba_stanja.set()
	if "začni" in data.keys() and type(data["začni"]) == str:
		naslednji = data["začni"]
		začni_vzorec.set()
	return "true"

@http.route("/<koda>", methods=["OPTIONS"])
def update_preflight(koda):
	return flask.Response("", status=204, headers={"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type", "Access-Control-Max-Age": "86400"})

def kode():
	return [base64.b64encode(hashlib.sha256(skrivnost+bytes(str(int(time.time()/1000)), encoding="utf-8")).digest()).replace(b"/", b"").replace(b"+", b"")[:4].lower().decode(), base64.b64encode(hashlib.sha256(skrivnost+bytes(str(int(time.time()/1000)-1), encoding="utf-8")).digest()).replace(b"/", b"").replace(b"+", b"")[:4].lower().decode()]

def zaznaj_smrt():
	proces.wait()
	začni_vzorec.set()

def subprocess_manager():
	global naslednji
	global proces
	global začni_vzorec
	while True:
		if not naslednji:
			vzorci = set(os.listdir("vzorci"))-set(["začasen.py"])-onemogočeni
			naslednji = sorted(vzorci)[0]
		print("daemon: starting " + naslednji)
		proces = subprocess.Popen(["./wrapper.py", naslednji])
		sprememba_stanja.set()
		vzorci = set(os.listdir("vzorci"))-set(["začasen.py"])-onemogočeni
		naslednji = sorted(vzorci)[0]
		if trenuten() in vzorci:
			naslednji = sorted(vzorci)[(sorted(vzorci).index(trenuten())+1)%len(vzorci)]
		začni_vzorec.clear()
		threading.Thread(target=zaznaj_smrt).start()
		razlog = začni_vzorec.wait(timeout=čas_vzorca)
		proces.send_signal(subprocess.signal.SIGINT)
		proces.wait()
	
začni_vzorec = threading.Event()
sprememba_stanja = threading.Event()

if __name__ == "__main__":
	threading.Thread(target=lambda: http.run(host="::", port=6969, debug=True, use_reloader=False)).start()
	threading.Thread(target=subprocess_manager).start()