from fastapi import FastAPI, HTTPException, Form from fastapi.responses import HTMLResponse import os, json, uuid from datetime import datetime DATA = "/data/freqs.json" app = FastAPI(redirect_slashes=False) def load(): if os.path.exists(DATA): with open(DATA) as f: return json.load(f) return {} def save(d): with open(DATA, "w") as f: json.dump(d, f, indent=2) @app.get("/api/list") def list_freqs(): items = load() return sorted( [{"id": k, **v} for k, v in items.items()], key=lambda x: (x.get("band", ""), float(x.get("freq", 0) or 0)) ) @app.post("/api/add") def add(freq: str = Form(""), name: str = Form(""), mode: str = Form(""), band: str = Form(""), tone: str = Form(""), offset: str = Form(""), description: str = Form(""), tag: str = Form("")): items = load() fid = uuid.uuid4().hex[:12] items[fid] = { "freq": freq, "name": name, "mode": mode, "band": band, "tone": tone, "offset": offset, "description": description, "tag": tag, "added": datetime.utcnow().isoformat() } save(items) return {"id": fid} @app.patch("/api/update/{fid}") def update(fid: str, freq: str = Form(None), name: str = Form(None), mode: str = Form(None), band: str = Form(None), tone: str = Form(None), offset: str = Form(None), description: str = Form(None), tag: str = Form(None)): items = load() if fid not in items: raise HTTPException(404) for k, v in {"freq": freq, "name": name, "mode": mode, "band": band, "tone": tone, "offset": offset, "description": description, "tag": tag}.items(): if v is not None: items[fid][k] = v save(items) return {"ok": True} @app.delete("/api/delete/{fid}") def delete(fid: str): items = load() if fid not in items: raise HTTPException(404) del items[fid] save(items) return {"ok": True} @app.get("/", response_class=HTMLResponse) def root(): with open("/static/index.html") as f: return f.read()