85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
from importlib import import_module, reload
|
|
from os import environ
|
|
from pathlib import Path
|
|
import json
|
|
|
|
from gibil.classes.env_loader import EnvLoader
|
|
|
|
EnvLoader().load()
|
|
|
|
HOST = environ.get("ASTRAPE_WEB_HOST", "0.0.0.0")
|
|
PORT = int(environ.get("ASTRAPE_WEB_PORT", "8080"))
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
WATCHED_PATHS = [
|
|
PROJECT_ROOT / "gibil" / "classes" / "webui.py",
|
|
PROJECT_ROOT / "gibil" / "classes" / "weather_display.py",
|
|
PROJECT_ROOT / "gibil" / "classes" / "weather_store.py",
|
|
]
|
|
|
|
|
|
class AstrapeWebHandler(BaseHTTPRequestHandler):
|
|
def do_GET(self) -> None:
|
|
if self.path == "/":
|
|
self._send_html(self._webui().render_page())
|
|
return
|
|
|
|
if self.path == "/api/weather":
|
|
self._send_json_text(self._webui().weather_payload())
|
|
return
|
|
|
|
if self.path == "/api/ui-version":
|
|
self._send_json_text(json.dumps({"version": self._ui_version()}))
|
|
return
|
|
|
|
self.send_error(404)
|
|
|
|
def log_message(self, format: str, *args: object) -> None:
|
|
print(f"{self.address_string()} - {format % args}")
|
|
|
|
def _webui(self):
|
|
weather_store_module = import_module("gibil.classes.weather_store")
|
|
weather_display_module = import_module("gibil.classes.weather_display")
|
|
webui_module = import_module("gibil.classes.webui")
|
|
reload(weather_store_module)
|
|
reload(weather_display_module)
|
|
reload(webui_module)
|
|
return webui_module.WebUI()
|
|
|
|
def _ui_version(self) -> str:
|
|
mtimes = [
|
|
str(path.stat().st_mtime_ns)
|
|
for path in WATCHED_PATHS
|
|
if path.exists()
|
|
]
|
|
return ".".join(mtimes)
|
|
|
|
def _send_html(self, body: str) -> None:
|
|
encoded = body.encode("utf-8")
|
|
self.send_response(200)
|
|
self.send_header("Content-Type", "text/html; charset=utf-8")
|
|
self.send_header("Content-Length", str(len(encoded)))
|
|
self.end_headers()
|
|
self.wfile.write(encoded)
|
|
|
|
def _send_json_text(self, body: str) -> None:
|
|
encoded = body.encode("utf-8")
|
|
self.send_response(200)
|
|
self.send_header("Content-Type", "application/json; charset=utf-8")
|
|
self.send_header("Cache-Control", "no-store")
|
|
self.send_header("Content-Length", str(len(encoded)))
|
|
self.end_headers()
|
|
self.wfile.write(encoded)
|
|
|
|
|
|
def main() -> None:
|
|
server = ThreadingHTTPServer((HOST, PORT), AstrapeWebHandler)
|
|
print(f"Astrape web UI listening on http://{HOST}:{PORT}")
|
|
server.serve_forever()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|