mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 09:55:03 +00:00
fediverse: публикация в GoToSocial (@vesti@dedinit.ru) из publisher-service
- gotosocial.py: клиент GtS (httpx): post_status (markdown), upload_media v2, verify_credentials, delete_status - config.py: gt_social_url/token/visibility/format/channels - channels.py: fediverse-каналы (VESTI_GTS_CHANNELS, префикс gt:), gt: уходит только в fediverse - main.py: _publish_gotosocial + healthz-блок gotosocial + dry_run; status_id (ULID) в ответе - .env.example: GT_SOCIAL_* и VESTI_GTS_CHANNELS - STATUS.md/WALKTHROUGH.md: fediverse-раздел, хронология - openspec: change gotosocial-publisher (proposal/design/tasks/specs), validate чисто
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
## Why
|
||||
|
||||
У VESTI уже работает публикация в Telegram через изолированный publisher-service
|
||||
(`POST /api/v1/publish`, Docker-контейнер :8410, каналы `@dedinit_vesti`). Но у проекта есть
|
||||
вторая цель — «ленты ботов (Telegram, VK, **fediverse**)» (openspec/config.yaml, домен:
|
||||
медиа-конвейер → банк статей → дайджесты + ленты ботов). Fediverse-нода — собственный
|
||||
GoToSocial на social.dedinit.ru (bigbox, Docker-контейнер, :8082), аккаунт **@vesti**
|
||||
(`@vesti@dedinit.ru`) — обычный пользователь (admin=0), создан и подтверждён.
|
||||
|
||||
Сейчас при approve статьи веб зовёт publisher-service, и тот умеет публиковать **только в
|
||||
Telegram**. Чтобы публиковать одобренные карточки ещё и в свой GoToSocial-аккаунт
|
||||
(от имени vesti), publisher-service нужно расширить fediverse-каналом.
|
||||
|
||||
GtS 0.22.x реализует **Mastodon-совместимый REST API** (проверено: POST /api/v1/apps
|
||||
работает, возвращает client_id/client_secret; у ноды есть действующие OAuth-приложения
|
||||
Phanpy/Tusky/GoToSocial Settings). Значит, публикация в GtS идентична Mastodon:
|
||||
`POST /api/v1/statuses` с Bearer-токеном пользователя и опциональными медиа
|
||||
(`POST /api/v2/media`). Это стандарт, библиотек не требует — хватит httpx (уже есть в
|
||||
publisher).
|
||||
|
||||
## What Changes
|
||||
|
||||
Расширяем **publisher-service** (FastAPI, :8410) мульти-канальной отправкой:
|
||||
помимо Telegram-каналов (`@dedinit_vesti`) появляется fediverse-канал
|
||||
`@vesti@dedinit.ru` — публикация в GoToSocial через Mastodon-совместимый API.
|
||||
|
||||
- Новый модуль `services/publisher/app/gotosocial.py` — клиент GtS:
|
||||
- `post_status(text, media_paths, visibility="public")` → `POST /api/v1/statuses`
|
||||
(текст ≤5000, лимит GtS; разметка: markdown или plaintext);
|
||||
- `upload_media(path)` → `POST /api/v2/media` (multipart) до публикации,
|
||||
вернёт `media_id`; до 6 вложений (лимит GtS);
|
||||
- `get_me()` → GET /api/v1/accounts/verify_credentials (healthz);
|
||||
- `delete_status(id)` → DELETE /api/v1/statuses/{id} (для отмены тестовых);
|
||||
- все GET запросы к GtS напрямую (без прокси — social.dedinit.ru доступен из
|
||||
контейнера, проверено HTTP 200).
|
||||
- Конфиг (config.py + .env): `GT_SOCIAL_URL=https://social.dedinit.ru`,
|
||||
`GT_SOCIAL_ACCESS_TOKEN=<токен @vesti>` (Bearer, scope write),
|
||||
`GT_SOCIAL_VISIBILITY=public` (MAY: private/unlisted).
|
||||
- main.py: `channels`-список может содержать помимо `@...` (Telegram) ещё и
|
||||
fediverse-канал (например `@vesti@dedinit.ru` или префикс `gt:`); publisher умеет
|
||||
отправлять карточку в оба типа каналов, результаты — в `results` как обычно.
|
||||
dry_run также эмулирует fediverse-публикацию (не уходит наружу).
|
||||
- healthz: добавить `gotosocial` блок (url, аккаунт, токен задан?).
|
||||
- Документация: .env.example, README publisher, STATUS.md.
|
||||
|
||||
### Не меняется
|
||||
- Telegram-путь (telegram.py, каналы @dedinit_vesti) — работает как раньше.
|
||||
- Веб :8400 (approve) — публикация по-прежнему через HTTP POST /api/v1/publish;
|
||||
веб-клиент не меняется (только конфиг каналов publisher).
|
||||
- Формат карточки (текст+медиа) — один и тот же для всех каналов.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `gotosocial-publisher`: публикация карточки VESTI в собственный GoToSocial
|
||||
(Mastodon API, Bearer-токен @vesti), медиа-аплоад, healthz, dry_run, delete.
|
||||
|
||||
### Modified Capabilities
|
||||
- `tg-publisher-service`: publisher-service теперь мульти-канальный (Telegram +
|
||||
fediverse); конфиг каналов расширяется.
|
||||
- `vesti-web`: без изменений кода (approve шлёт карточку publisher как раньше,
|
||||
но та уходит и в GtS если канал в конфиге).
|
||||
|
||||
## Impact
|
||||
|
||||
- Затронутые сервисы/порты: publisher-service :8410 (Docker-контейнер vesti-publisher) —
|
||||
только пересборка образа; GtS :8082/8443 (social.dedinit.ru) — читается по HTTPS.
|
||||
- Файлы:
|
||||
- новый: services/publisher/app/gotosocial.py
|
||||
- изменён: services/publisher/app/main.py, config.py, channels.py,
|
||||
services/publisher/Dockerfile (НЕ нужно — httpx уже есть), .env.example
|
||||
- Данные: без миграций БД.
|
||||
- Секреты: GT_SOCIAL_ACCESS_TOKEN (новый, в .env), URL GtS не секретен.
|
||||
- Прокси: Telegram — как раньше через SOCKS5; GoToSocial — НАПРЯМУЮ (внутренняя сеть
|
||||
WG → vps02 → bigbox; из контейнера publisher social.dedinit.ru отвечает 200).
|
||||
- Rollback: убрать канал `@vesti@dedinit.ru` из VESTI_BOT_CHANNELS (или вернуть
|
||||
конфиг) — Telegram-публикация не затронута; модуль gotosocial.py можно оставить
|
||||
невостребованным.
|
||||
|
||||
## Risks
|
||||
|
||||
- Токен @vesti (scope write) — если протухнет, publisher вернёт 401/403 в results с
|
||||
понятной ошибкой; healthz покажет `token_set=false`.
|
||||
- GtS недоступен → HTTP 502 в результатах канала; остальные каналы продолжают работать
|
||||
(fan-out не падает целиком — уже реализовано в main.py).
|
||||
- Лимиты GtS: 5000 символов, 6 вложений, MIME ограничен — текст обрезается до 5000,
|
||||
медиа до 6; неподдерживаемый тип → ошибка в результатах канала.
|
||||
- Спам-защита GtS (rate limit) при частой публикации — допустимо (публикует человек,
|
||||
не автопостинг).
|
||||
Reference in New Issue
Block a user