From d1c12a08b0f3b0bcdab4711c6de25b4c388e21da Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 2 Dec 2024 02:35:49 +0500 Subject: [PATCH] init --- __pycache__/screen.cpython-313.pyc | Bin 0 -> 2746 bytes docker-compose.yml | 7 ++ dockerfile | 10 ++ index.html | 173 +++++++++++++++++++++++++++++ requirements.txt | 3 + screen.py | 60 ++++++++++ server.py | 95 ++++++++++++++++ 7 files changed, 348 insertions(+) create mode 100644 __pycache__/screen.cpython-313.pyc create mode 100644 docker-compose.yml create mode 100644 dockerfile create mode 100644 index.html create mode 100644 requirements.txt create mode 100644 screen.py create mode 100644 server.py diff --git a/__pycache__/screen.cpython-313.pyc b/__pycache__/screen.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..192e3889958d5ecf1aa86678a575a4495a6273f6 GIT binary patch literal 2746 zcmZuz&2JM|5P$1kuh+@Ou}L5y!NEWx3B6O{fAgdJkvy*W2BSpC5pd`DB_UMwMgX| zc`q5Nnx`#UE*@CN)#N&AtnDT}&}ddK#AU{hol{uQc6^+i z&oF6Dv+ZjZO*4K$r_5(qOi~KeFtg)RtjX2O7&)B=mv;A|6Oj1?DGzzN9THUz! zdx9wJv@Zj@K`L$Ai^5&0va=h8P^GgAhL*MF(0%UC@LEr7>B`e9&+^4nKTNH)gzxXU za}i~;PiLRyil^>Qtx1ux)cI2CTo!%_{S+!m17&HbBn`cm4sU?<%{hiS1V!%zteY6cUm_L=XY@P0ex$6oFxkp$)RnvM79v!MZ+F9>MJ=tq9rN%TG~x9s+;ftRmHvQa|aJSWEuo6C2G0vNeCj`r||F-AddtS(38OAXrKgI zZ6K%$Rb<7`BU|kXHf(|Ard?d3c?*qzXV>&y@FiM4*4X+qMN)zar!*ZAVr068xkL?9 zbvq7{wz@9{r-8f(dUpck*DCDv4o^AJ>CNgRc(xgC3bmk-4#KNFdol9)OTeN$c|I;s zjE}>N8{lwb1nxNYwQuxLTwp>nXhMCIEr*$=_E$UQHtJe%OZC$fjvzE)LE`Dq# zT~8bK9H=<97@s(Ok_oeOdUpLN91!Q3n6YSHE3m-Tc`auY7FqKgwX#&VZDT>ty4QVk zJRSnvXPJE**H(pL2yu>$wpqS8r0J^qA3=OImn<`-dMPbidt3q z1f=%QzyKGaZEKOXM;$+Qtn?iEqi^NQdx!}zRjvZh*i%t82O9|Hz~kwZnUT9hl{_D7)yq2h@*A_+%| z(!YKZieP1~ekh0gO5wiM@c!b7N^7_%IZgvuV4~1gWSB%wDo)0O*d$D7E>JIGX}K_Im6UVOI0cUf1rDiVNTKGz}R+Gh4xf1QmR&f9+#Ylj;5+F zh;zQ1fLQ-1GTd(??!P1Ne3F0UT|4KGy%QyW-+%3*KjLmd#dwHrhk+hOh7Mu8y=XHT z@M0U53H>c&F@Ij0wW#Z7EbuhqD4rXipcpaQj|{DOJvRpcrDG_?!tb^X>8ShoV{`&! zSd;B>U~hPi{s&e46w3er literal 0 HcmV?d00001 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e28e6aa --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +services: + python: + volumes: + - './:/usr/src/app' + working_dir: /usr/src/app + build: . + command: python server.py diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..b9bedfb --- /dev/null +++ b/dockerfile @@ -0,0 +1,10 @@ +FROM python:3 + +WORKDIR /usr/src/app + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD [ "python", "./server.py" ] diff --git a/index.html b/index.html new file mode 100644 index 0000000..652f6fc --- /dev/null +++ b/index.html @@ -0,0 +1,173 @@ + + + + + + + Document + + + + + +
+
Loading
+
+ + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..448ed83 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +flask +websockets +pillow diff --git a/screen.py b/screen.py new file mode 100644 index 0000000..34c43fc --- /dev/null +++ b/screen.py @@ -0,0 +1,60 @@ +#Copyright (C) 2021 Qijun Gu +# +#This file is part of Screenshare. +# +#Screenshare is free software: you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#Screenshare is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +#along with Screenshare. If not, see . + +import threading, time, base64, sys + +ver = sys.version_info.major +if ver==2: + import StringIO as io +elif ver==3: + import io + +from PIL import ImageGrab as ig + +class Screen(): + def __init__(self): + self.FPS = 30 + self.screenbuf = "" + self.password = "" + if ver==2: + self.screenfile = io.StringIO() + elif ver==3: + self.screenfile = io.BytesIO() + threading.Thread(target=self.getframes).start() + + def __del__(self): + self.screenfile.close() + + def getframes(self): + while True: + im = ig.grab(bbox=(0, 0, 1920, 1080), include_layered_windows=False, all_screens=False, xdisplay=":0") + self.screenfile.seek(0) + self.screenfile.truncate(0) + im_converted = im.convert("RGB") + im_converted.save(self.screenfile, format="jpeg", quality=60, progressive=True) + self.screenbuf = base64.b64encode(self.screenfile.getvalue()) + time.sleep(1.0/self.FPS) + + def gen(self): + s = '' + if ver==2: + s = self.screenbuf + elif ver==3: + s = self.screenbuf.decode() + return s + +screenlive = Screen() diff --git a/server.py b/server.py new file mode 100644 index 0000000..0785dec --- /dev/null +++ b/server.py @@ -0,0 +1,95 @@ +from screen import screenlive +import json, argparse +from flask import Flask, json +import threading +from time import sleep +from websockets.sync.server import serve +import websockets +import array +import time + +api = Flask(__name__) +watchers_last_seen = {} +stream = False +debug = False + +def current_time(): + return str(int(time.time())) + +@api.route("/off", methods=["GET"]) +def streaOff(): + global stream + stream=False + return "True" + +@api.route("/on", methods=["GET"]) +def streamOn(): + global stream + stream=True + return "True" + +@api.route("/views", methods=["GET"]) +def views(): + global watchers_last_seen + return str(len(watchers_last_seen)) + + +def ws_server(websocket): + global stream, watchers_last_seen + if debug: print("WebSocket: Server Started.") + try: + while True: + req=websocket.recv() + if "%" in req: + args= req.split("%")[1] + args = dict(x.split("=") for x in args.split(";")) + req = req.split("%")[0] + if debug: print(req,"-----",args) + match (req): + case ("get_stream"): + if stream: + watchers_last_seen[args["uuid"]] = current_time() + websocket.send(f""+str(json.dumps([True, screenlive.gen()]))) + else: + websocket.send(f"null") + case (_): + websocket.send(f"null") + except websockets.exceptions.ConnectionClosedOK: + if debug: print("hungup") + except websockets.ConnectionClosedError: + if debug: print("Internal Server Error.") + +def run_ws_server(): + with serve(ws_server, "0.0.0.0", 7890) as server: + server.serve_forever() + +def timeout_task(): + while True: + for key,value in watchers_last_seen.items(): + if debug: print(key+"||||"+value) + if (int(current_time())-int(value)) > 5: + if debug: print(key+"is timed out") + watchers_last_seen.pop(key) + break + if debug: print("time -",current_time()) + if debug: print("watchers -",watchers_last_seen.keys()) + sleep(10) + +def run_flask_server(): + api.run() + +def main(): + t1 = threading.Thread(target=run_ws_server) + t2 = threading.Thread(target=run_flask_server) + t3 = threading.Thread(target=timeout_task) + + t1.start() + t2.start() + t3.start() + + t1.join() + t2.join() + t3.join() + +if __name__ == "__main__": + main()