Files

5.0 KiB
Raw Permalink Blame History

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 выше).