mirror of
https://github.com/Astatin3/Polyboard.git
synced 2026-06-09 00:28:07 -06:00
112 lines
2.7 KiB
Python
112 lines
2.7 KiB
Python
|
|
import os
|
||
|
|
import base64
|
||
|
|
from hashlib import sha256
|
||
|
|
from flask import Flask, render_template, Response
|
||
|
|
from flask import request, redirect, url_for, make_response
|
||
|
|
|
||
|
|
import src.jsonpack as jsonpack
|
||
|
|
import src.utils as utils
|
||
|
|
|
||
|
|
import queue
|
||
|
|
|
||
|
|
class rawClient:
|
||
|
|
def __init__(self, app):
|
||
|
|
self.clientid = utils.randID(32)
|
||
|
|
self.messages = queue.Queue()
|
||
|
|
self.app = app
|
||
|
|
self.address = None
|
||
|
|
def send(self, type, msg):
|
||
|
|
self.app.rawServer.sendClient(self, jsonpack.pack({
|
||
|
|
'type': type,
|
||
|
|
'data': msg,
|
||
|
|
'cid': self.clientid
|
||
|
|
}))
|
||
|
|
|
||
|
|
#Credit to https://github.com/MaxHalford/flask-sse-no-deps
|
||
|
|
class rawServer:
|
||
|
|
|
||
|
|
def __init__(self, app):
|
||
|
|
self.eventListeners = []
|
||
|
|
self.clients = []
|
||
|
|
self.app = app
|
||
|
|
app.rawServer = self.app
|
||
|
|
|
||
|
|
def listen(self):
|
||
|
|
c = rawClient(self.app)
|
||
|
|
self.clients.append(c)
|
||
|
|
return self.clients[-1]
|
||
|
|
|
||
|
|
def broadcast(self, msg):
|
||
|
|
# We go in reverse order because we might have to delete an element, which will shift the
|
||
|
|
# indices backward
|
||
|
|
ssedata = format_sse(msg)
|
||
|
|
for i in reversed(range(len(clients))):
|
||
|
|
try:
|
||
|
|
self.clients[i].messages.put_nowait(ssedata)
|
||
|
|
except queue.Full:
|
||
|
|
del self.clients[i]
|
||
|
|
|
||
|
|
def sendClient(self, c, msg):
|
||
|
|
if c not in self.clients:
|
||
|
|
return
|
||
|
|
ssedata = format_sse(msg)
|
||
|
|
c.messages.put_nowait(ssedata)
|
||
|
|
|
||
|
|
def clientByCID(self, cid):
|
||
|
|
for c in self.clients:
|
||
|
|
if c.clientid == cid:
|
||
|
|
return c
|
||
|
|
return None
|
||
|
|
|
||
|
|
def addEventListener(self, eventName, func):
|
||
|
|
self.eventListeners.append({
|
||
|
|
'name': eventName,
|
||
|
|
'func': func
|
||
|
|
})
|
||
|
|
|
||
|
|
|
||
|
|
def format_sse(data: str, event=None) -> str:
|
||
|
|
#Formats a string and an event name in order to follow the event stream convention.
|
||
|
|
msg = f'data: {data}\n\n'
|
||
|
|
if event is not None:
|
||
|
|
msg = f'event: {event}\n{msg}'
|
||
|
|
return msg
|
||
|
|
|
||
|
|
|
||
|
|
def startRawListener(app):
|
||
|
|
app.rawServer = rawServer(app)
|
||
|
|
|
||
|
|
@app.route('/listen', methods=['GET', 'POST'])
|
||
|
|
def listen():
|
||
|
|
|
||
|
|
if request.method == 'GET':
|
||
|
|
|
||
|
|
c = app.rawServer.listen() # returns a queue.Queue
|
||
|
|
c.address = request.remote_addr
|
||
|
|
c.send('clidata', {
|
||
|
|
'cid': c.clientid
|
||
|
|
})
|
||
|
|
|
||
|
|
def stream():
|
||
|
|
while True:
|
||
|
|
msg = c.messages.get() # blocks until a new message arrives
|
||
|
|
yield msg
|
||
|
|
|
||
|
|
return Response(stream(), mimetype='text/event-stream')
|
||
|
|
if request.method == 'POST':
|
||
|
|
|
||
|
|
data = jsonpack.unpack(request.data.decode("utf-8"))
|
||
|
|
|
||
|
|
if data['cid'] == None:
|
||
|
|
return {}, 400
|
||
|
|
c = utils.getatribinarr(app.rawServer.clients, 'clientid', data['cid'])
|
||
|
|
if c == None:
|
||
|
|
return {}, 400
|
||
|
|
|
||
|
|
for event in app.rawServer.eventListeners:
|
||
|
|
if event['name'] == data['type']:
|
||
|
|
event['func'](c, data)
|
||
|
|
|
||
|
|
return {}, 200
|
||
|
|
|
||
|
|
#return rawServer
|