Files
vesti/openspec/changes/publisher-service/specs/tg-publisher-service/spec.md
T

79 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 выше).