From ebe6fab9c6f46f5c2d9027adc19c5b501d7078a4 Mon Sep 17 00:00:00 2001 From: hkc Date: Thu, 4 Jul 2024 15:14:24 +0300 Subject: [PATCH] Live viewer now takes a screenshot once as second --- .gitignore | 1 + astley.png | Bin 0 -> 1585 bytes async-bot.py | 3 ++- live-viewer.py | 25 +++++++++++++++++++++++-- 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 astley.png diff --git a/.gitignore b/.gitignore index 7f62b1f..0540138 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ logs.txt rgb111-full.png state-new.json settings.json +screenshots/ diff --git a/astley.png b/astley.png new file mode 100644 index 0000000000000000000000000000000000000000..6c86ea479f82fefd1f426a9f9e067ccd435b3e8a GIT binary patch literal 1585 zcmV-12G043P)EX>4Tx04R}tkv&MmKpe$i(@I4v4t5Z6$WWc^;0Nkht5Adrp;l;vxAeOi5kvsJ7{`pvEMrcRlIS?T?&0I>U6f~aKKJM7Q*#yrd?Im-8KzCVK|H-_ z8=Uuv!>lN)#OK6gCS8#Dk?V@bZ=4G*3p_Jyrc?98VPdh+#!4HrqNx#25l2)_r+gvf zvC4UivsSLM<~{ifLpgnAnd>x%k-#FBAVGwJDoQBBMwC{a6bmWZk9Y77xqgXU3b{&P z#tGnm2Cnp$zfuQgKS{5( zw8#V$mfCgGy0}1FmMa>ta-gP_i_3Fq^Yaq4RCM> zj20++y~De^+k5->OtZfq*bj2g$%Z={00009P)t-s0000000960|AXDn(f|Me0d!JM zQvg8b*k%9#010qNS#tmYE+YT{E+YYWr9XB6000McNliru=m!J~IRp+p-bw%f02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00a3+L_t(oN2OQWmg67{OZWdj zdIQ$YgwBxNoOx&`*vPVE=ym=4{E6q6rQ6pTKR&bq*9%l2=`% zkl~4U@c=NlEKiZuLpv``FoQ32grYG>Am?KerT$LD1a>ymGJ~af4B*~GZgdmM;%5M6 zg36(3`bLLi7xm3Pegi;KbQfO8aF!_=V-g$_zzh(fQ=Bpw98k!m<(COOl5jj9$5#(I zilYrj85kWt^cCUv3=WqT$>B*KjXmoJ01)w=$yT|Lc>i%ufA>QK@Jz0If#y+N68NlS zH0<+EpmA20gTY8W+Z6I%TqqF5XV47@PAJ9wx~0qXb;C^%m`ogfW<9N8iHhM0;i&^FgOFU zxWDNDAj>*SEPC`7G|OJ%KsM=G^S@h@WKfXK`JZiOM=2t04PQdy6;dZqlMcRsgK~A+ zK&R~lLm63TRunv%0OZr?0uhjN*#Xn20pPd*)%Ow}!o+P!r}?c?DpvDJ6rj$IBaLh? zwc8U8VZ9XsijE?HJCg760w^c|cH&4>bf;74XQlxMeN;6ziZm%%{j}(B1hjG((z@t9 za-~xIMXTE{h5$yXk<^ORLIlC_tbFQE6p);tX|jEPzY%n^;YE6G8J^49wyK@|RkAGj0S+tC0Y% z?;?9N@^+)uDLc6y^df5SDTWuM!^{-d^b|<2p+rQGMxqA5&O?YsK@t~;bc(v5i0mWS zc_L_fW5lC$t)h@ZD^c~LoQEQ;gDwsTLp{j-sR|~eoh_#w)ups;9iEBg-Ye(&d&oC?X(!c~6(YlIjQ*c$gK00000NkvXXu0mjf-?GB$ literal 0 HcmV?d00001 diff --git a/async-bot.py b/async-bot.py index 7aea545..884897a 100644 --- a/async-bot.py +++ b/async-bot.py @@ -59,6 +59,7 @@ class AsyncBotManager: bits_on, bits_off, timestamp = data if timestamp < self._last_update: print("SKIPPING UPDATES: TOO OLD") + self._last_update: int = data["timestamp"] for ndx in bits_on: y, x = divmod(ndx, 1000) self.canvas.putpixel((x, y), 255) @@ -107,7 +108,7 @@ async def amain(): mgr.font = ImageFont.truetype(settings["font"], 8) for elem in settings["elements"]: if elem["type"] == "text": - mgr.put_text(elem["text"], elem["x"], elem["y"]) + mgr.put_text(elem["x"], elem["y"], elem["text"]) elif elem["type"] == "image": with Image.open(elem["path"]).convert("LA") as im: mgr.put_image(elem["x"], elem["y"], im) diff --git a/live-viewer.py b/live-viewer.py index 82d1218..18fa447 100644 --- a/live-viewer.py +++ b/live-viewer.py @@ -4,10 +4,12 @@ from PIL import Image, ImageTk from socketio import SimpleClient, exceptions from threading import Thread from requests import get +from datetime import datetime COLORS = [(0x33, 0x33, 0x66), (0x96, 0x96, 0xe0)] COLORS_UNPACKED = COLORS[0] + ((0, 0, 0) * 254) + COLORS[1] +SCREENSHOTS_TMPL = "./screenshots/%Y%m%d_%H%M%S.png" class App(tk.Tk): def __init__(self, url: str = "https://onemillioncheckboxes.com") -> None: @@ -22,6 +24,8 @@ class App(tk.Tk): self._canvas.pack() self.config(width=1000, height=1000, borderwidth=0, highlightthickness=0) + self._last_update = 0 + self._running = False self._image = Image.new("RGB", (1000, 1000), COLORS[0]) @@ -38,15 +42,25 @@ class App(tk.Tk): x, y = event.x, event.y self.sio.emit("toggle_bit", { "index": x + y * 1000 }) + def _save_image(self): + ts = datetime.fromtimestamp(self._last_update / 1000) + path = ts.strftime(SCREENSHOTS_TMPL) + print("SAVED", path) + self._image.save(path) + + self.after(1000, self._save_image) + def _on_key_down(self, event: tk.Event): # if event.keysym == "r": print("FULL REFRESH") with get(f"{self.url}/api/initial-state") as req: - buffer = b64decode(req.json()["full_state"].encode() + b"=") + data = req.json() + buffer = b64decode(data["full_state"].encode() + b"=") img = Image.frombytes("1", (1000, 1000), buffer).convert("P") img.putpalette(COLORS_UNPACKED) self._image.paste(img.convert("RGB")) + self._last_update = data["timestamp"] print("FULL REFRESH DONE") def _reader(self): @@ -59,6 +73,10 @@ class App(tk.Tk): if name == "batched_bit_toggles": bits_on, bits_off, timestamp = data + if timestamp < self._last_update: + print("SKIP partial updates: too old") + continue + self._last_update = timestamp for ndx in bits_on: y, x = divmod(ndx, 1000) self._image.putpixel((x, y), COLORS[1]) @@ -92,7 +110,9 @@ class App(tk.Tk): self.sio.connect(f"{self.url}/socket.io") with get(f"{self.url}/api/initial-state") as req: - buffer = b64decode(req.json()["full_state"].encode() + b"=") + data = req.json() + buffer = b64decode(data["full_state"].encode() + b"=") + self._last_update = data["timestamp"] img = Image.frombytes("1", (1000, 1000), buffer).convert("P") img.putpalette(COLORS_UNPACKED) self._image.paste(img.convert("RGB")) @@ -104,6 +124,7 @@ class App(tk.Tk): self._reader_thr.start() self.protocol("WM_DELETE_WINDOW", self._close) + self.after(1000, self._save_image) self.mainloop() if __name__ == "__main__":