mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 09:55:03 +00:00
51 lines
5.5 KiB
Markdown
51 lines
5.5 KiB
Markdown
# Tasks: publisher-service
|
||
|
||
## 1. Скелет сервиса
|
||
|
||
- [x] 1.1 Создать services/publisher/ (app/, requirements.txt, .env.example, README.md)
|
||
Проверка: `ls services/publisher/app/` → main.py, config.py, telegram.py, channels.py
|
||
- [x] 1.2 requirements.txt: fastapi, uvicorn, httpx[socks], pydantic, python-dotenv
|
||
Проверка: `.venv/bin/pip install -r services/publisher/requirements.txt` без ошибок
|
||
- [x] 1.3 config.py: env VESTI_BOT_TOKEN, TG_PROXY, VESTI_BOT_CHANNELS, PUBLISHER_PORT
|
||
Проверка: `python -c "from services.publisher.app.config import Settings; print(Settings().channels)"` → ['@dedinit_vesti']
|
||
- Замечание: токен не читался из-за порядка (os.getenv при ClassVar, до load_dotenv) и неверного пути BASE (3x parent → /opt/vesti/services, нужно parents[3] → /opt/vesti). Исправлено: Settings → @dataclass + __post_init__, load_dotenv(override=True), BASE=parents[3].
|
||
|
||
## 2. Telegram-клиент (Bot API через SOCKS5)
|
||
|
||
- [x] 2.1 telegram.py: клиент httpx с proxy=socks5://127.0.0.1:1080, методы sendMessage/sendPhoto/getMessage
|
||
- [x] 2.2 channels.py: разбор VESTI_BOT_CHANNELS ("@a,@b" → ["@a","@b"])
|
||
- [x] 2.3 Обработка ошибок: 403 (бот не админ), сеть (прокси) → 502
|
||
|
||
## 3. FastAPI-эндпоинты
|
||
|
||
- [x] 3.1 main.py: GET /healthz (status, bot, proxy, channels)
|
||
Проверка: `curl -s :8410/healthz` → ok + бот + каналы. Реальное: {"status":"ok","bot":"dedinit_controller_bot","token_set":true,"proxy":"socks5://127.0.0.1:1080","channels":["@dedinit_vesti"]}
|
||
- [x] 3.2 main.py: POST /api/v1/publish (card {text, media?, direction, lang}, channels?) → results по каналам
|
||
Проверка: `curl -X POST :8410/api/v1/publish -d '{"card":{"text":"тест","direction":"linux","lang":"ru"}}'` → ok, message_id в @dedinit_vesti. Реальное: {"ok":true,"results":{"@dedinit_vesti":{"message_id":2,...}}}
|
||
- [x] 3.3 views: эндпоинт GET /api/v1/views/{channel}/{mid} (в main.py) + поле views в ответе publish (get_views при публикации)
|
||
|
||
## 4. Контейнеризация
|
||
|
||
- [x] 4.1 Dockerfile: python:slim, non-root, read-only fs, expose 8410
|
||
- [x] 4.2 docker-compose.yml: сервис publisher, порт 127.0.0.1:8410, env из .env, healthcheck curl /healthz
|
||
- Проверено 2026-09-09: `docker compose up -d --build` → vesti-publisher Up (healthy), 127.0.0.1:8410, healthz: bot=dedinit_controller_bot, proxy=host.docker.internal.
|
||
- Питфолы Docker: (1) пути в compose отсчитываются от services/publisher/ → .env надо `../../.env`, media `../../media`; (2) TG_PROXY=127.0.0.1 в контейнере = сам контейнер → заменить на socks5://host.docker.internal:1080 + extra_hosts host-gateway; (3) load_dotenv(override=True) перебивал env контейнера → override=False (env окружения приоритетнее .env); (4) dataclass-дефолт tg_proxy="socks5://127.0.0.1:1080" был truthy → os.getenv не срабатывал → дефолт сделан пустым.
|
||
|
||
## 5. Интеграция с вебом
|
||
|
||
- [x] 5.1 web/app.py: убрать `from publisher.bot import publish_multi/get_views_multi`; вместо них web/publisher_client.py (HTTP POST на PUBLISHER_URL, default http://127.0.0.1:8410)
|
||
- Проверка: grep — импорт publisher.bot убран; карточка шлёт card{direction,lang}, сервис берёт каналы из VESTI_BOT_CHANNELS.
|
||
- [x] 5.2 Обновить .env.example (VESTI_BOT_CHANNELS, TG_PROXY, PUBLISHER_URL)
|
||
- [x] 5.3 Реальный approve через веб: сквозной путь веб → HTTP → publisher(Docker) → канал.
|
||
- Проверено 2026-09-09: approve постов 136 и 137 через POST /posts/<id>/approve — 302 → /published, статус published, бандл, tg_message_id=3 и 4 в @dedinit_vesti.
|
||
- Веб-баги, найденные при проверке: (1) `raise RedirectResponse(...)` в _require_auth → TypeError (исключение не BaseException) → 500 на /candidates; фикс: HTTPException(303, headers={"Location": "/login"}); (2) tg_message_id для внешних постов искался по направлению (results["linux"]), а ключи results — каналы (@dedinit_vesti) → 0; фикс: брать первый message_id из results.values().
|
||
|
||
## 6. Проверка и документация
|
||
|
||
- [x] 6.1 `openspec validate publisher-service` → 0 ошибок (valid)
|
||
- [x] 6.2 Реальная публикация тестовой карточки в @dedinit_vesti (бот админ) → message_id в ответе. Реальное: message_id=2, ok.
|
||
- Бот добавлен админом канала (подтверждено пользователем).
|
||
- [x] 6.3 Обновить STATUS.md / TODO.md — сделано; WALKTHROUGH/PRD — обновлено (см. PRD.md)
|
||
|
||
## Открытые пункты
|
||
- [x] publisher: медиа из card.media — путь в БД /opt/vesti/media/... не совпадает с монтированием в контейнере (/srv/publisher/media) → send_photo не уходит при Docker-запуске — ЗАКРЫТО change fix-media-mount (2026-09-14): контейнер монтирует весь каталог media/, publisher резолвит media/ и media/media/ |