From 3c7ecf4e4f1acf0b9a8aa01596e904b46afa0ef9 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Fri, 8 May 2026 23:34:58 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20notification=20test=20endpoints=20?= =?UTF-8?q?=E2=80=94=20POST=20/api/push/test=20and=20/api/push/reminders/c?= =?UTF-8?q?heck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- cortex/routers/push.py | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/cortex/routers/push.py b/cortex/routers/push.py index c28ce07..6d1122c 100644 --- a/cortex/routers/push.py +++ b/cortex/routers/push.py @@ -58,3 +58,63 @@ async def unsubscribe(req: UnsubscribeRequest, request: Request) -> dict: username = _require_user(request) found = push_utils.remove_subscription(username, req.endpoint) 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}