Notification Channels

Notification Channels

All outbound messages (alerts, reports, charts, trade notifications) route through a fan-out registry in arb_bot/channels/ instead of calling send_telegram() directly. Each enabled channel receives every message independently; a per-channel try/except isolates failures so one broken channel never silences another.

arb_bot/telegram.py ← backward-compat shim, delegates to registry └── arb_bot/channels/registry.py ← notify() / notify_photo() / notify_document() ├── TelegramChannel → POST /sendMessage, /sendPhoto, /sendDocument └── CliqChannel → POST incoming webhook (text); deep link for files

Channel protocol

Each channel implements three methods:

MethodSignatureNotes
enabled()() → boolChecked per-call; channel skipped if False
send_text(html: str)Telegram HTML; Cliq converts via to_cliq()
send_photo(png: bytes, caption: str)Cliq sends dashboard deep link instead
send_document(pdf: bytes, filename: str, caption: str)Cliq sends dashboard deep link instead

Config flags

FlagDefaultPurpose
TELEGRAM_ENABLEDtrueEnable/disable Telegram channel
CLIQ_ENABLEDfalseEnable Zoho Cliq backup channel
CLIQ_INCOMING_WEBHOOK_URLBot incoming webhook URL from Zoho
CLIQ_WEBHOOK_TOKENzapikey token for webhook auth
CLIQ_COMMAND_SECRETShared secret in X-Cliq-Secret header
CLIQ_ALLOWED_SENDERComma-separated Zoho user IDs that may issue commands
DASHBOARD_PUBLIC_URLUsed to generate deep links in photo/doc replies
CLIQ_POLL_INTERVAL2.0 sHow often CliqCommandConsumer polls the queue

Inbound commands (Cliq → bot)

Cliq pushes inbound messages to the dashboard (POST /api/cliq/command) via a Deluge message handler. The dashboard validates the shared secret and the sender, then enqueues the command in the cliq_inbound SQLite table. A daemon thread (CliqCommandConsumer) polls the queue and dispatches each command through the existing TelegramCommandHandler._dispatch() with a CliqResponder so replies go back over the incoming webhook.

Cliq user sends message └── Deluge message handler ← POST /api/cliq/command + X-Cliq-Secret └── dashboard_server.py ← validates secret + sender, enqueues row └── cliq_inbound table ← pending → processing → done/error └── CliqCommandConsumer._loop() ← daemon thread, polls every 2 s └── TelegramCommandHandler._dispatch() ← CliqResponder replies to webhook

OTP login

The dashboard OTP (POST /api/auth/request-otp) calls notify() so the one-time code is delivered to every enabled channel. If Telegram is blocked, the OTP arrives via Cliq.

Cliq limitations Cliq incoming webhooks accept text only — charts and PDF reports send a dashboard deep link instead of the file. Commands are async: Cliq replies ⏳ received immediately; the full reply arrives ~1–2 s later as a separate webhook push.

See docs/cliq_setup.md for the Zoho UI setup steps and the Deluge handler snippet.