Require login for meetup RSVP with cancel, notify organizers/authors/posters on RSVP/reply/gig/match, optional ntfy + Listmonk hooks, and honest newsletter messaging. Co-authored-by: Cursor <cursoragent@cursor.com>
59 lines
1.5 KiB
Python
59 lines
1.5 KiB
Python
"""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
|