Major upgrades, much code and docs rewritten.
This commit is contained in:
50
cista/app.py
50
cista/app.py
@@ -1,13 +1,10 @@
|
||||
import asyncio
|
||||
from importlib.resources import files
|
||||
from pathlib import Path
|
||||
|
||||
import msgspec
|
||||
from sanic import Sanic
|
||||
from sanic.log import logger
|
||||
from sanic.response import html
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from watchdog.observers import Observer
|
||||
|
||||
from . import watching
|
||||
from .fileio import ROOT, FileServer
|
||||
@@ -15,6 +12,7 @@ from .protocol import ErrorMsg, FileRange, StatusMsg
|
||||
|
||||
app = Sanic("cista")
|
||||
fileserver = FileServer()
|
||||
watching.register(app, "/api/watch")
|
||||
|
||||
def asend(ws, msg):
|
||||
return ws.send(msg if isinstance(msg, bytes) else msgspec.json.encode(msg).decode())
|
||||
@@ -27,22 +25,6 @@ async def start_fileserver(app, _):
|
||||
async def stop_fileserver(app, _):
|
||||
await fileserver.stop()
|
||||
|
||||
@app.before_server_start
|
||||
async def start_watcher(app, _):
|
||||
class Handler(FileSystemEventHandler):
|
||||
def on_any_event(self, event):
|
||||
watching.update(Path(event.src_path).relative_to(ROOT))
|
||||
app.ctx.observer = Observer()
|
||||
app.ctx.observer.schedule(Handler(), str(ROOT), recursive=True)
|
||||
app.ctx.observer.start()
|
||||
|
||||
@app.after_server_stop
|
||||
async def stop_watcher(app, _):
|
||||
app.ctx.observer.stop()
|
||||
app.ctx.observer.join()
|
||||
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def index_page(request):
|
||||
index = files("cista").joinpath("static", "index.html").read_text()
|
||||
@@ -50,16 +32,6 @@ async def index_page(request):
|
||||
|
||||
app.static("/files", ROOT, use_content_range=True, stream_large_files=True, directory_view=True)
|
||||
|
||||
@app.websocket('/api/watch')
|
||||
async def watch(request, ws):
|
||||
try:
|
||||
q = watching.pubsub[ws] = asyncio.Queue()
|
||||
await asend(ws, {"root": watching.tree})
|
||||
while True:
|
||||
await asend(ws, await q.get())
|
||||
finally:
|
||||
del watching.pubsub[ws]
|
||||
|
||||
@app.websocket('/api/upload')
|
||||
async def upload(request, ws):
|
||||
alink = fileserver.alink
|
||||
@@ -78,24 +50,28 @@ async def upload(request, ws):
|
||||
d = f"{len(data)} bytes" if isinstance(data, bytes) else data
|
||||
raise ValueError(f"Expected {req.end - pos} more bytes, got {d}")
|
||||
# Report success
|
||||
res = StatusMsg(status="upload", url=url, req=req)
|
||||
res = StatusMsg(status="ack", req=req)
|
||||
await asend(ws, res)
|
||||
print(res)
|
||||
|
||||
await ws.drain()
|
||||
except Exception as e:
|
||||
res = ErrorMsg(error=str(e), url=url, req=req)
|
||||
res = ErrorMsg(error=str(e), req=req)
|
||||
await asend(ws, res)
|
||||
logger.exception(repr(res), e)
|
||||
return
|
||||
|
||||
@app.websocket("/ws")
|
||||
async def ws(request, ws):
|
||||
while True:
|
||||
data = await ws.recv()
|
||||
await ws.send(data)
|
||||
|
||||
@app.websocket('/api/download')
|
||||
async def download(request, ws):
|
||||
alink = fileserver.alink
|
||||
url = request.url_for("download")
|
||||
while True:
|
||||
req = None
|
||||
try:
|
||||
print("Waiting for download command")
|
||||
text = await ws.recv()
|
||||
if not isinstance(text, str):
|
||||
raise ValueError(f"Expected JSON control, got binary len(data) = {len(text)}")
|
||||
@@ -108,12 +84,14 @@ async def download(request, ws):
|
||||
await asend(ws, data)
|
||||
pos += len(data)
|
||||
# Report success
|
||||
res = StatusMsg(status="download", url=url, req=req)
|
||||
res = StatusMsg(status="ack", req=req)
|
||||
await asend(ws, res)
|
||||
print(ws, dir(ws))
|
||||
await ws.drain()
|
||||
print(res)
|
||||
|
||||
except Exception as e:
|
||||
res = ErrorMsg(error=str(e), url=url, req=req)
|
||||
res = ErrorMsg(error=str(e), req=req)
|
||||
await asend(ws, res)
|
||||
logger.exception(repr(res), e)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user