5.0 KiB
Spec: tg-publisher-service
Purpose
Изолированный FastAPI-сервис публикации карточек в Telegram-каналы через Bot API. Единая точка вызова для всех компонентов (веб, cron, будущие боты). Один бот-контроллер публикует во все каналы, в которые добавлен администратором. Telegram доступен только через SOCKS5-прокси (127.0.0.1:1080).
ADDED Requirements
Requirement: Изолированный сервис публикации
Сервис MUST быть отдельным FastAPI-приложением (контейнер), НЕ импортируемым модулем веба.
Он MUST предоставлять GET /healthz (статус, бот, прокси, каналы) и
POST /api/v1/publish (публикация карточки).
Scenario: Healthcheck
- GIVEN сервис запущен
- THEN
GET /healthzвозвращает 200 с{"status":"ok","bot":...,"channels":[...]}и healthcheck в docker-compose (curl -f) проходит
Scenario: Публикация карточки
- GIVEN POST /api/v1/publish c
card: {text, direction, lang}иchannels: ["@dedinit_vesti"] - THEN сервис отправляет сообщение через Bot API в каждый канал и возвращает
{"ok":true,"results":{"@dedinit_vesti":{"message_id":<int>,"views":0}}}
Requirement: Один бот, несколько каналов (конфиг)
Сервис MUST поддерживать список каналов из конфигурации (VESTI_BOT_CHANNELS, через запятую).
channels в запросе MAY переопределять список. Если бот добавлен в канал администратором —
публикация MUST работать; иначе сервис MUST вернуть понятную ошибку (403).
Scenario: Несколько каналов
- GIVEN
VESTI_BOT_CHANNELS=@dedinit_vesti,@other_channel(оба добавлены боту) - WHEN POST /api/v1/publish без поля channels
- THEN карточка публикуется в оба канала; results содержит оба message_id
Scenario: Бот не админ канала
- GIVEN канал, в котором бот не администратор
- WHEN публикация в него
- THEN сервис возвращает 403 с текстом ошибки Bot API (sendMessage → Forbidden)
Requirement: Прокси SOCKS5 для Bot API
Все запросы к api.telegram.org MUST идти через прокси из TG_PROXY=socks5://127.0.0.1:1080.
Если прокси недоступен — сервис MUST вернуть 502 (не падать).
Scenario: Прокси недоступен
- GIVEN прокси 127.0.0.1:1080 выключен
- WHEN POST /api/v1/publish
- THEN сервис возвращает 502 с ошибкой подключения (не 500, не краш)
Requirement: Сбор views
Сервис MUST предоставлять способ получения просмотров для опубликованных сообщений (через Bot API getMessage), чтобы веб показывал метрики.
Scenario: Views после публикации
- GIVEN сообщение опубликовано (message_id получен)
- WHEN запрос views для этого message_id
- THEN возвращается число просмотров (0 если ещё нет)
Requirement: Режим подтверждения
Сервис MUST НЕ публиковать автоматически: вызывается только по HTTP-запросу (из веба после клика «Опубликовать»). Автопостинга по таймеру внутри сервиса НЕТ.
Scenario: Нет автопостинга
- GIVEN сервис запущен без входящих запросов
- THEN ничего не публикуется (процесс только слушает HTTP)
Modified Requirements (из tg-publisher)
publish_multiиget_viewsпереезжают в сервис (HTTP-интерфейс вместо импорта).- vesti-web: approve вызывает POST /api/v1/publish; ответ используется для distributed_dirs + views (как раньше, только источник данных — HTTP).
NOT Requirements
- Не реализуем чтение каналов (краулинг) — это остаётся в tg-crawler (Telethon).
- Не реализуем веб-интерфейс сервиса (только API + healthz).
- Не храним БД в сервисе (вся персистентность — в vesti.db через веб).
- Не делаем автопостинг (см. Requirement выше).