mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 18:05:03 +00:00
79 lines
5.0 KiB
Markdown
79 lines
5.0 KiB
Markdown
# 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 выше). |