Envio de alertas Telegram desde el servicio (docs/legacy-telegram.md): por alerta, texto Markdown (content + firelink i18n) + ubicacion, como node-red. - types: canal 'telegram', notif.type 'telegram', campo telegramNotified - telegram/message.ts: buildTelegramMessages (firelink es/en/gl + location) - telegram/client.ts: cliente Bot API (fetch), interpretResponse (429 retry_after, 403 blocked) - telegram/rate.ts: throttle por chat (1 msg/s) + computeWaitMs puro - handlers.processTelegramJob: idempotencia (notification_sends canal telegram), modos dry-run/shadow/canary/full, throttle, 429->retry, bloqueo->sub inactiva - poller/queue/index: canal telegram integrado; worker con rate limiter global BullMQ (25/s por bot); cliente por idioma (es/gl->ES, en->EN) - config: bloque telegram (tokens es/en, server, globalPerSec, perChatMinMs) 85 tests en verde, typecheck y build OK. Sin TELEGRAM_TOKEN_* configurados el worker no se activa (todo inerte). Falta: extraer tokens de bot de flows_cred + rollout con el usuario. Los flujos conversacionales de los bots siguen en node-red.
57 lines
2.8 KiB
Markdown
57 lines
2.8 KiB
Markdown
# Envío Telegram viejo (fase 1c — caracterización)
|
|
|
|
> Fuente: `todos-contra-el-fuego/telegram-bot/flows.json` (nodos "calc distances",
|
|
> "send location", senders `telegram sender`), locales node-red.
|
|
|
|
## Qué envía node-red por cada alerta de fuego a un chat suscrito
|
|
|
|
**Dos mensajes** al `chatId` de la suscripción (subs `type: 'telegram'`):
|
|
|
|
1. **Texto** (`type: "message"`, `parse_mode: "Markdown"`):
|
|
`content` + salto de línea + `firelink`.
|
|
- `content` = la misma cadena `kmnasa`/`kmvecinal` del matching
|
|
(ver `legacy-matching.md` §3; lleva `🔥` y el `км` cirílico).
|
|
- `firelink` (i18n): `[<label>](https://{{server}}/fire/{{enc}})` con
|
|
`enc` = `sealed` (el mismo Iron del matching).
|
|
- es: `[más información](https://{{server}}/fire/{{enc}})`
|
|
- en: `[more information](https://{{server}}/fire/{{enc}})`
|
|
- gl: `[máis información](https://{{server}}/fire/{{enc}})`
|
|
2. **Ubicación** (`type: "location"`): `{ latitude: fire.lat, longitude: fire.lon }`.
|
|
|
|
No hay botones/inline-keyboard en la alerta (solo `parse_mode: Markdown`).
|
|
|
|
## Bots
|
|
|
|
- Dos instancias node-red separadas: **ES** (`/opt/node-red-data-git`, puerto
|
|
1880) y **EN** (`/opt/node-red-data-git-en`, 1881). Tokens en
|
|
`flows_cred*.json` (cifrados con el `credentialSecret` de node-red; copiados a
|
|
`tcef-private-config`). El servicio los recibe por env (`TELEGRAM_TOKEN_ES` /
|
|
`TELEGRAM_TOKEN_EN`) — **no** están en claro aquí; hay que extraerlos/pedirlos.
|
|
- Selección de bot: por idioma del suscriptor (es/gl → bot ES, en → bot EN).
|
|
|
|
## Límites de la Bot API de Telegram
|
|
|
|
- ~30 msg/s global por bot → el servicio usa **25/s** (margen).
|
|
- ~1 msg/s por chat individual.
|
|
- 429 devuelve `parameters.retry_after` (segundos) → respetar.
|
|
- Bot bloqueado por el usuario (403 "bot was blocked by the user") → marcar la
|
|
sub inactiva y **no** reintentar.
|
|
|
|
## Integración en el servicio (unificada)
|
|
|
|
- El matcher (1b) genera docs `notifications` con `type: 'telegram'` para las
|
|
subs telegram cuando `MATCHER_AUDIENCE` incluye `telegram`. El doc lleva
|
|
`subsId` → el worker carga la sub para el `chatId`.
|
|
- Un **`telegram-worker`** (canal `telegram`, como fcm/email) consume esos docs:
|
|
envía texto + ubicación, marca `telegramNotified`, idempotencia por
|
|
`notification_sends` (canal `telegram`), mismos modos
|
|
`dry-run/shadow/canary/full` y kill switch.
|
|
|
|
## Fuera de alcance (documentado)
|
|
|
|
- **Canales públicos**: si los flows publican alertas también en canales
|
|
públicos del proyecto (además de a las subs), esa vía se migra aparte o se deja
|
|
explícitamente en node-red. Config opcional `TELEGRAM_PUBLIC_CHANNELS`; por
|
|
defecto **no** se toca.
|
|
- Flujos conversacionales de los bots (/start, alta/baja de subs, /lang, etc.)
|
|
**se quedan en node-red** — solo se migra el ENVÍO de alertas.
|