"""Unified in-app + optional ntfy push notifications.""" from __future__ import annotations import asyncio import re from app.config import settings from app.services import community_store, platform_store from app.services.ntfy_push import send_push _PREF_KEY = { "match": "match", "meetup": "meetup", "community": "community", "gig": "community", "general": None, } def _topic_for(user_id: str) -> str: safe = re.sub(r"[^a-zA-Z0-9_-]", "", user_id)[:48] or "guest" return f"nomadro-{safe}" def notify_user( user_id: str, title: str, body: str, link: str = "", category: str = "general", ) -> bool: """Persist inbox notification; optionally fire ntfy when push prefs allow.""" if not user_id: return False prefs = platform_store.get_notif_prefs(user_id) pref_key = _PREF_KEY.get(category) if pref_key is not None and not prefs.get(pref_key, True): return False community_store.add_notification(user_id, title, body, link, category) if prefs.get("push") and settings.ntfy_enabled: click = link if link.startswith("http") else f"{settings.site_base_url.rstrip('/')}{link or '/notifications'}" try: loop = asyncio.get_running_loop() loop.create_task( send_push( _topic_for(user_id), title, body, tags=["nomadro", category], click_url=click, ) ) except RuntimeError: # Outside async context — best-effort sync skip; inbox already saved pass return True