import json import mimetypes import os from pathlib import Path from .utils import scramble class StaticFile: template_ext = ".tpl" def __init__(self, path): self.path = path self.mime_type = mimetypes.guess_type(self.remove_template_ext(str(path)))[0] self.mtime = None self.content = None def load_content(self): with open(self.path, "rb") as fh: return fh.read() def get(self): if self.path.stat().st_mtime != self.mtime: self.content = self.load_content() return self.content def render(self, context_vars): content = self.get() if self.path.suffix == self.template_ext: for k, v in context_vars.items(): content = content.replace(b"{{ %s }}" % k.encode(), v.encode()) return content def __str__(self): return f"" @classmethod def remove_template_ext(cls, filename): if filename.endswith(cls.template_ext): filename = filename[:-4] return filename class StaticResource: def __init__(self, secret, current_hubapp, master_ws_uri): mimetypes.init() hub_js_path = Path(__file__).parent / "hub.js" self.static_files = { "/hub.js": StaticFile(hub_js_path), } self.context_vars = { "master_ws_uri": json.dumps(master_ws_uri), } self.master_uri = "" self.setup(secret, current_hubapp) def setup(self, secret, current_hubapp): hubapp_dir = Path(__file__).parents[1] / "hubapps" / current_hubapp for file in os.listdir(hubapp_dir): uri_file = StaticFile.remove_template_ext(file) if uri_file.startswith("master."): uri = f"/{scramble(secret, uri_file)}" if uri_file == "master.html": self.master_uri = uri self.context_vars[uri_file.replace(".", "_")] = uri else: uri = f"/{uri_file}" self.static_files[uri] = StaticFile(hubapp_dir / file) if uri_file == "index.html": self.static_files["/"] = self.static_files[uri] async def on_get(self, req, resp): path = req.path index_uri = f"/index.html" if path == "/": path = index_uri res = self.static_files[path] resp.data = res.render(self.context_vars) resp.content_type = res.mime_type def add_routes(self, app): for uri_template in self.static_files: app.add_route(uri_template, self)