mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 09:55:03 +00:00
104 lines
4.3 KiB
Markdown
104 lines
4.3 KiB
Markdown
# Design: publisher-service
|
|
|
|
## Approach
|
|
|
|
Выносим публикацию в Telegram из веб-процесса в изолированный FastAPI-микросервис.
|
|
Сервис — единственная точка, которая знает токен бота (прокси), каналы и Bot API.
|
|
Остальные компоненты (веб, в будущем cron/боты) вызывают его по HTTP.
|
|
|
|
Схема:
|
|
```
|
|
vesti-web (:8400) ──POST /api/v1/publish──▶ publisher-service (:8410) ──Bot API (SOCKS5 127.0.0.1:1080)──▶ Telegram
|
|
approve (человек) │ VESTI_BOT_TOKEN, VESTI_BOT_CHANNELS
|
|
▼
|
|
Telegram: @dedinit_vesti (+ другие каналы)
|
|
```
|
|
|
|
## Files
|
|
|
|
```bash
|
|
# Новый сервис
|
|
services/publisher/
|
|
├── app/
|
|
│ ├── __init__.py
|
|
│ ├── main.py # FastAPI: POST /api/v1/publish, GET /healthz
|
|
│ ├── config.py # env: VESTI_BOT_TOKEN, TG_PROXY, VESTI_BOT_CHANNELS, LISTEN_PORT
|
|
│ ├── telegram.py # Bot API клиент (httpx + SOCKS5): send, get_views
|
|
│ └── channels.py # разбор списка каналов (VESTI_BOT_CHANNELS)
|
|
├── requirements.txt # fastapi, uvicorn, httpx[socks], pydantic, python-dotenv
|
|
├── Dockerfile # python:slim, non-root, read-only fs
|
|
├── docker-compose.yml # сервис, порт 8410, healthcheck, env из .env
|
|
├── .env.example # без секретов
|
|
└── README.md # API, порты, запуск, безопасность
|
|
|
|
# Изменения
|
|
web/app.py # approve → HTTP POST в publisher-service (вместо import publisher.bot)
|
|
.env.example # + VESTI_BOT_CHANNELS, TG_PROXY
|
|
STATUS.md / TODO.md / WALKTHROUGH.md # статус
|
|
```
|
|
|
|
## Data / Config
|
|
|
|
```bash
|
|
# .env (реальные значения; НЕ коммитить)
|
|
VESTI_BOT_TOKEN=<токен @dedinit_controller_bot> # уже в .env
|
|
TG_PROXY=socks5://127.0.0.1:1080 # уже есть
|
|
VESTI_BOT_CHANNELS=@dedinit_vesti # список каналов, разделитель запятая
|
|
PUBLISHER_PORT=8410
|
|
```
|
|
|
|
## API
|
|
|
|
### POST /api/v1/publish
|
|
```json
|
|
{
|
|
"card": {"text": "...", "media": "/path/to/photo.jpg", "direction": "linux", "lang": "ru"},
|
|
"channels": ["@dedinit_vesti"] // опционально; default = VESTI_BOT_CHANNELS
|
|
}
|
|
```
|
|
Ответ 200:
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"results": {
|
|
"@dedinit_vesti": {"message_id": 123, "media_message_id": 122, "views": 0}
|
|
},
|
|
"dry_run": false
|
|
}
|
|
```
|
|
Ошибки: 400 (невалидный card), 502 (Bot API / прокси недоступен), 403 (бот не админ).
|
|
|
|
### GET /healthz
|
|
```json
|
|
{"status": "ok", "bot": "@dedinit_controller_bot", "proxy": "socks5://127.0.0.1:1080", "channels": ["@dedinit_vesti"]}
|
|
```
|
|
Healthcheck: `curl -f http://127.0.0.1:8410/healthz`.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
cd /opt/vesti
|
|
# dev (без Docker):
|
|
.venv/bin/pip install -r services/publisher/requirements.txt
|
|
.venv/bin/uvicorn services.publisher.app.main:app --host 127.0.0.1 --port 8410
|
|
curl -s http://127.0.0.1:8410/healthz
|
|
|
|
# prod (Docker):
|
|
docker compose -f services/publisher/docker-compose.yml up -d --build
|
|
curl -s http://127.0.0.1:8410/healthz
|
|
curl -s -X POST http://127.0.0.1:8410/api/v1/publish \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"card": {"text": "<b>Тест</b>", "direction": "linux", "lang": "ru"}}'
|
|
|
|
# переключение веба:
|
|
# в web/app.py заменить `from publisher.bot import publish_multi` на HTTP-клиент
|
|
# (или переменная окружения PUBLISHER_URL=http://127.0.0.1:8410)
|
|
```
|
|
|
|
## Verification
|
|
|
|
- [ ] `openspec validate publisher-service` → 0 ошибок
|
|
- [ ] `curl :8410/healthz` → ok, бот, прокси, каналы
|
|
- [ ] POST /api/v1/publish с тестовой карточкой → message_id в @dedinit_vesti
|
|
- [ ] Бот не админ / прокси упал → понятная ошибка (4xx/502), веб показывает
|
|
- [ ] approve в вебе → реальное сообщение в канале (микросервис вызван по HTTP) |