178 lines
6.1 KiB
Python
Executable File
178 lines
6.1 KiB
Python
Executable File
from microdot import Microdot
|
|
from microdot import send_file
|
|
from microdot.websocket import with_websocket
|
|
from microdot import Request
|
|
|
|
import random
|
|
import json
|
|
import time
|
|
import msgpack
|
|
|
|
# Enable 500 kB files in the webui
|
|
Request.max_content_length = 1024 * 1024 * 0.5
|
|
Request.max_body_length = 1024 * 1024 * 0.5
|
|
Request.max_readline = 1024 * 1024
|
|
|
|
|
|
class Server:
|
|
"""
|
|
Web server that serves the web ui and provides web to node communication
|
|
|
|
`🔗 Source <https://git.utopic.work/PierMesh/piermesh/src/branch/main/src/Sponge/serve.py>`__
|
|
|
|
Attributes
|
|
----------
|
|
cLog
|
|
Reference to `run.Node.cLog` for logging
|
|
|
|
transmitter: Transmission.transmission.Transmitter
|
|
Reference to our `Transmission.transmission.Transmitter` instance
|
|
|
|
network: Siph.Network.Network
|
|
Reference to our `Siph.Network.Network`
|
|
|
|
nodeID: str
|
|
String converted PierMesh node ID
|
|
|
|
peerIDs: dict
|
|
Map of peer IDs to Websocket sessions
|
|
|
|
app
|
|
Microdot server instance
|
|
|
|
catch: Daisy.Catch.Catch
|
|
Reference to our Catch Cache instance to pull from for serving Catchs
|
|
"""
|
|
|
|
def __init__(self, transceiver, catch, onodeID, network, cLog):
|
|
self.cLog = cLog
|
|
self.transceiver = transceiver
|
|
self.network = network
|
|
self.network.addLookup(onodeID, self.transceiver.interface.localNode.nodeNum)
|
|
self.nodeID = str(onodeID)
|
|
self.peerIDs = {}
|
|
self.app = Microdot()
|
|
self.catch = catch
|
|
# self.nmap = {self.nodeID: self.t.interface.localNode.nodeNum}
|
|
# self.cLog(20, "Initialized server")
|
|
|
|
@self.app.route("/res/<path:path>")
|
|
async def static(request, path):
|
|
"""
|
|
Static resources endpoint
|
|
"""
|
|
if ".." in path:
|
|
# directory traversal is not allowed
|
|
return "Not found", 404
|
|
return send_file("webui/build/res/" + path, max_age=86400)
|
|
|
|
@self.app.route("/bubble")
|
|
@with_websocket
|
|
async def bubble(request, ws):
|
|
"""
|
|
Websocket handler that bridges HTMX to our transmitter
|
|
|
|
Notes
|
|
-----
|
|
`🔗 HTMX docs <https://htmx.org/docs/>`_
|
|
"""
|
|
while True:
|
|
r = await ws.receive()
|
|
message = json.loads(r)
|
|
trigger = message["HEADERS"]["HX-Trigger"]
|
|
# TODO: Drop old id from cache on regen
|
|
if trigger == "gpID":
|
|
peerID = str(random.randrange(0, 1000000)).zfill(6)
|
|
await ws.send(
|
|
"""
|
|
<p id="vpeerID">Peer ID: {0}</p>
|
|
""".format(
|
|
peerID
|
|
)
|
|
)
|
|
await ws.send(
|
|
"""
|
|
<input id="peerID" type="hidden" value="{0}" >
|
|
""".format(
|
|
peerID
|
|
)
|
|
)
|
|
await ws.send(
|
|
"""
|
|
<p id="vnodeID">Node ID: {0}</p>
|
|
""".format(
|
|
self.nodeID
|
|
)
|
|
)
|
|
await ws.send(
|
|
""" <input id="nodeID" type="hidden" value="{0}" >""".format(
|
|
self.nodeID
|
|
)
|
|
)
|
|
await ws.send(
|
|
"<input id='gID' type='hidden' value='{0}' hx-swap-oob='true'>".format(
|
|
peerID
|
|
)
|
|
)
|
|
await ws.send(
|
|
"<input type='hidden' name='eID' value='{0}' hx-swap-oob='true'>".format(
|
|
peerID
|
|
)
|
|
)
|
|
peer = {"usedLast": round(time.time() * 1000), "ws": ws}
|
|
self.peerIDs[peerID] = peer
|
|
elif trigger == "bubble":
|
|
sender = message["bID"]
|
|
data = message["chat_message"]
|
|
# TODO: Setting sender name id
|
|
# senderName = message["senderID"]
|
|
senderName = 000000
|
|
recipient = message["recipientID"]
|
|
recipientNode = message["recipientNode"]
|
|
await self.t.addPackets(
|
|
msgpack.dumps({"data": data}),
|
|
sender,
|
|
senderName,
|
|
recipient,
|
|
int(recipientNode),
|
|
directID=self.network.doLookup(recipientNode),
|
|
packetsClass=2,
|
|
)
|
|
elif trigger == "catch":
|
|
res = self.catch.get(message["head"], message["body"])
|
|
await ws.send('<div id="catchDisplay">{0}</div>'.format(res))
|
|
# TODO: Catch update packets
|
|
elif trigger == "catchEdit":
|
|
self.catch.addc(
|
|
message["eID"],
|
|
self.nodeID,
|
|
message["sep"],
|
|
message["head"],
|
|
message["body"],
|
|
{"html": message["catchContent"]},
|
|
)
|
|
await ws.send(
|
|
"""
|
|
<ul id="resultsCatch" hx-swap-oob='true'><li>OK</li></ul>
|
|
"""
|
|
)
|
|
else:
|
|
await ws.send(
|
|
"""<div id="chat_room" hx-swap-oob="beforeend">hi</div>"""
|
|
)
|
|
|
|
@self.app.route("/")
|
|
async def index(request):
|
|
"""
|
|
Static handler to serve the web ui
|
|
"""
|
|
return send_file("webui/build/index/index.html")
|
|
|
|
async def sendToPeer(self, peerID: str, data: str):
|
|
"""
|
|
Send data to Websocket of peer with peerID
|
|
"""
|
|
await self.peerIDs[peerID]["ws"].send(
|
|
"<ul id='chat_room' hx-swap-oob='afterend'><li>{0}</li></ul>".format(data)
|
|
)
|