"""Platform persistence — PocketBase backed.""" from __future__ import annotations import json import secrets from datetime import datetime, timezone from pathlib import Path from app.services.pb_repo import q, safe_create, safe_first, safe_list, safe_update, use_pb _JSON_PATH = Path(__file__).resolve().parents[1] / "data" / "platform_store.json" _j: dict = {} def _now() -> str: return datetime.now(timezone.utc).strftime("%Y-%m-%d") def _jload() -> dict: global _j if _j: return _j if _JSON_PATH.exists(): try: _j = json.loads(_JSON_PATH.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): _j = {} else: _j = {} return _j def _jsave() -> None: _JSON_PATH.parent.mkdir(parents=True, exist_ok=True) _JSON_PATH.write_text(json.dumps(_j, ensure_ascii=False), encoding="utf-8") def add_service_lead(service_id: str, user_id: str | None, name: str, email: str, message: str) -> dict: item = { "serviceSlug": service_id, "userId": user_id or "", "email": email, "note": f"{name}: {message}"[:1000], "status": "open", } if use_pb(): row = safe_create("service_leads", item) return {"id": row["id"] if row else secrets.token_hex(6), **item} _jload() out = {"id": secrets.token_hex(6), "service_id": service_id, "name": name, "email": email, "message": message, "created_at": _now()} _j.setdefault("leads", []).append(out) _jsave() return out def add_content_submission(user_id: str | None, name: str, title: str, content_type: str, url: str, notes: str) -> dict: if use_pb(): row = safe_create( "content_submissions", { "title": title, "type": content_type, "mediaUrl": url, "submittedBy": user_id or "", "authorName": name, "description": notes[:2000], "reviewStatus": "pending", }, ) return {"id": row["id"] if row else secrets.token_hex(6), "title": title, "status": "pending"} _jload() out = {"id": secrets.token_hex(6), "title": title, "content_type": content_type, "url": url, "status": "pending", "created_at": _now()} _j.setdefault("submissions", []).append(out) _jsave() return out def add_volunteer(city_slug: str, user_id: str | None, name: str, email: str, message: str) -> dict: if use_pb(): row = safe_create( "volunteer_applications", { "citySlug": city_slug, "userId": user_id or "", "applicantName": name, "email": email, "motivation": message[:2000], "status": "pending", }, ) return {"id": row["id"] if row else secrets.token_hex(6), "city_slug": city_slug} _jload() out = {"id": secrets.token_hex(6), "city_slug": city_slug, "name": name, "email": email, "created_at": _now()} _j.setdefault("volunteers", []).append(out) _jsave() return out def add_report(reporter_id: str | None, target_type: str, target_id: str, reason: str) -> dict: if use_pb(): row = safe_create( "reports", { "reporterId": reporter_id or "", "targetType": target_type, "targetId": target_id, "reason": reason[:2000], "status": "open", }, ) return {"id": row["id"] if row else secrets.token_hex(6), "status": "open"} _jload() out = {"id": secrets.token_hex(6), "target_type": target_type, "target_id": target_id, "status": "open", "created_at": _now()} _j.setdefault("reports", []).append(out) _jsave() return out def subscribe_newsletter(email: str, source: str = "site") -> dict: if use_pb(): dup = safe_first("subscriptions", filter=f"email={q(email)}") if dup: return {"ok": True, "message": "已订阅"} safe_create("subscriptions", {"email": email}) return {"ok": True, "message": "订阅成功"} _jload() for n in _j.get("newsletter") or []: if n["email"] == email: return {"ok": True, "message": "已订阅"} _j.setdefault("newsletter", []).append({"email": email, "source": source, "created_at": _now()}) _jsave() return {"ok": True, "message": "订阅成功"} def get_notif_prefs(user_id: str) -> dict: default = { "email": True, "push": False, "match": True, "meetup": True, "community": True, "marketing": False, "quiet_hours": "", } if use_pb(): row = safe_first("notification_preferences", filter=f"userId={q(user_id)}") if not row: return default channels = row.get("channels") or {} return {**default, **channels} _jload() return _j.get("notif_prefs", {}).get(user_id) or default def set_notif_prefs(user_id: str, prefs: dict) -> dict: merged = {**get_notif_prefs(user_id), **prefs} if use_pb(): row = safe_first("notification_preferences", filter=f"userId={q(user_id)}") if row: safe_update("notification_preferences", row["id"], {"channels": merged, "userId": user_id}) else: safe_create("notification_preferences", {"userId": user_id, "channels": merged}) return merged _jload() _j.setdefault("notif_prefs", {})[user_id] = merged _jsave() return merged