import socket import sys from argparse import ArgumentParser from pathlib import Path from subprocess import run from traceback import print_exception from urllib.parse import urlunsplit from falcon.asgi import App as FalconApp from falcon.constants import MEDIA_HTML from jinja2 import Environment, FileSystemLoader, select_autoescape from uvicorn import Config, Server from .hubapp import RootApp, HubApp class App(FalconApp): def __init__(self, secret, **kwargs): kwargs.setdefault("media_type", MEDIA_HTML) super().__init__(**kwargs) self.base_dir = Path(__file__).parents[1] / "webroot" self.env = Environment( loader=FileSystemLoader(self.base_dir), autoescape=select_autoescape(), extensions=["hub.utils.StaticTag"], ) self.hubapps = {"root": RootApp(self, self.base_dir, "/derp", secret)} for base_dir in self.base_dir.iterdir(): if not base_dir.is_dir() or RootApp.is_ignored_filename(base_dir): continue self.hubapps[base_dir.name] = HubApp( self, base_dir, base_uri=f"/derp/{base_dir.name}" ) self.add_error_handler(Exception, self.print_exception) async def print_exception(self, req, resp, ex, params): print_exception(*sys.exc_info()) class HubServer(Server): def __init__(self, *args, browser, **kwargs): self.browser = browser super().__init__(*args, **kwargs) async def startup(self, sockets: list[socket.socket] | None = None) -> None: await super().startup(sockets) root_app = self.config.loaded_app.app.hubapps["root"] print("Secret:", root_app.secret) for uri, file in root_app.files_per_uris.items(): if file.name == "index.html": break else: raise ValueError("Root page not found!") host, port, ssl = self.config.host, self.config.port, bool(self.config.ssl) if port and port != (80, 443)[ssl]: host = f"{host}:{port}" url = urlunsplit((f"http{'s'[:ssl]}", host, uri, "", "")) print("URL:", url) if self.browser: run([self.browser, url]) async def main(): ap = ArgumentParser() ap.add_argument("--secret") ap.add_argument("--browser", default="xdg-open") args = ap.parse_args() app = App(args.secret) await app.hubapps["root"].setup() config = Config(app, port=5000, log_level="info") config.setup_event_loop() hs = HubServer(config, browser=args.browser) await hs.serve()