feat: add telegram notification channel with outbox service and per-user preferences
Extend the notification system with a third channel (telegram) alongside existing in_app and push channels. Add `telegram_enabled` column to `notification_preferences` table, update `NOTIFICATION_CHANNELS` and `_NOTIFICATION_CHANNEL_COLUMNS` mappings, and set telegram default to off (`_NOTIFICATION_CHANNEL_DEFAULTS`). Create `telegram_outbox` table with columns for uid, user_uid, chat_id, text, status, attempts, created_at, and sent_at, plus an index on status/id for efficient polling. Register `TelegramOutboxService` in the service manager lifecycle. Update API documentation strings to describe the new channel and its pairing requirement. Extend admin notification defaults view to include telegram column. Pass `notif_telegram_paired` flag to profile template based on `telegram_store.is_paired()` check. Update `NotificationPrefForm` and `NotificationDefaultForm` model literals to accept "telegram" as a valid channel value.
This commit is contained in:
@@ -26,10 +26,10 @@ NOTIFICATION_ACTIONS: tuple[Action, ...] = (
|
||||
name="notification_list",
|
||||
method="LOCAL",
|
||||
path="",
|
||||
summary="List the user's notification preferences (in-app and push per type)",
|
||||
summary="List the user's notification preferences (in-app, push and telegram per type)",
|
||||
description=(
|
||||
"Returns every notification type with the user's current in-app and push setting and "
|
||||
"whether it has been customized. Use this before changing a setting."
|
||||
"Returns every notification type with the user's current in-app, push and telegram "
|
||||
"setting and whether it has been customized. Use this before changing a setting."
|
||||
),
|
||||
handler="notification",
|
||||
requires_auth=True,
|
||||
@@ -41,14 +41,15 @@ NOTIFICATION_ACTIONS: tuple[Action, ...] = (
|
||||
path="",
|
||||
summary="Enable or disable one notification type on one channel",
|
||||
description=(
|
||||
"Sets whether the user receives a given notification type on a given channel. The two "
|
||||
"channels are independent: in-app (shown on DevPlace) and push (sent to subscribed devices)."
|
||||
"Sets whether the user receives a given notification type on a given channel. The three "
|
||||
"channels are independent: in-app (shown on DevPlace), push (sent to subscribed devices) "
|
||||
"and telegram (delivered to the user's paired Telegram chat, off by default)."
|
||||
),
|
||||
handler="notification",
|
||||
requires_auth=True,
|
||||
params=(
|
||||
arg("notification_type", TYPES, required=True),
|
||||
arg("channel", "Either 'in_app' or 'push'.", required=True),
|
||||
arg("channel", "Either 'in_app', 'push' or 'telegram'.", required=True),
|
||||
arg(
|
||||
"value",
|
||||
"true to deliver this notification on this channel, false to suppress it.",
|
||||
|
||||
@@ -40,7 +40,7 @@ class NotificationController:
|
||||
def _channel(self, arguments: dict[str, Any]) -> str:
|
||||
channel = str(arguments.get("channel", "")).strip().lower()
|
||||
if channel not in NOTIFICATION_CHANNELS:
|
||||
raise ToolInputError("'channel' must be 'in_app' or 'push'.")
|
||||
raise ToolInputError("'channel' must be 'in_app', 'push' or 'telegram'.")
|
||||
return channel
|
||||
|
||||
def _value(self, arguments: dict[str, Any]) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user