feat: notification test endpoints — POST /api/push/test and /api/push/reminders/check
- POST /api/push/test: sends "Test notification from Cortex" via the user's configured notification channel (web_push / NCT / email / etc.) - POST /api/push/reminders/check: runs the daily reminder check immediately for the current user, returns reminders_found count Both require an active session cookie. Useful for verifying channel setup without waiting for the 09:00 scheduler job. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,3 +58,63 @@ async def unsubscribe(req: UnsubscribeRequest, request: Request) -> dict:
|
|||||||
username = _require_user(request)
|
username = _require_user(request)
|
||||||
found = push_utils.remove_subscription(username, req.endpoint)
|
found = push_utils.remove_subscription(username, req.endpoint)
|
||||||
return {"ok": True, "found": found}
|
return {"ok": True, "found": found}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/test")
|
||||||
|
async def notify_test(request: Request) -> dict:
|
||||||
|
"""Send a test notification via the user's configured notification channel.
|
||||||
|
|
||||||
|
Useful for verifying channel setup (web push, NCT, email, etc.) without
|
||||||
|
waiting for a cron job or reminder to fire naturally.
|
||||||
|
"""
|
||||||
|
username = _require_user(request)
|
||||||
|
from notification import notify
|
||||||
|
await notify(username, "Test notification from Cortex — your notification channel is working.")
|
||||||
|
return {"ok": True, "user": username}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/reminders/check")
|
||||||
|
async def reminder_check_now(request: Request) -> dict:
|
||||||
|
"""Run the reminder check for the current user immediately.
|
||||||
|
|
||||||
|
Same logic as the daily 09:00 scheduler job, but scoped to one user
|
||||||
|
and fired on demand. Returns how many reminders were found and whether
|
||||||
|
a notification was sent.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
username = _require_user(request)
|
||||||
|
|
||||||
|
from persona import list_user_personas, set_context
|
||||||
|
from notification import notify
|
||||||
|
|
||||||
|
total_sent = 0
|
||||||
|
for persona_name in list_user_personas(username):
|
||||||
|
set_context(username, persona_name)
|
||||||
|
from tools.reminders import load_due_reminders
|
||||||
|
content = load_due_reminders()
|
||||||
|
if not content:
|
||||||
|
continue
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
for line in content.splitlines():
|
||||||
|
m = re.match(r"^\d+\.\s+(.+)", line.strip())
|
||||||
|
if m:
|
||||||
|
text = re.sub(r"\[(OVERDUE|due TODAY|due: \S+)\]", "", m.group(1)).strip()
|
||||||
|
if text:
|
||||||
|
entries.append(text)
|
||||||
|
|
||||||
|
if not entries:
|
||||||
|
continue
|
||||||
|
|
||||||
|
count = len(entries)
|
||||||
|
if count == 1:
|
||||||
|
msg = f"Reminder: {entries[0]}"
|
||||||
|
else:
|
||||||
|
bullet_list = "\n".join(f"• {e}" for e in entries[:3])
|
||||||
|
tail = f"\n…and {count - 3} more" if count > 3 else ""
|
||||||
|
msg = f"{count} reminders due:\n{bullet_list}{tail}"
|
||||||
|
|
||||||
|
await notify(username, msg)
|
||||||
|
total_sent += count
|
||||||
|
|
||||||
|
return {"ok": True, "user": username, "reminders_found": total_sent}
|
||||||
|
|||||||
Reference in New Issue
Block a user