mirror of
https://gitverse.ru/kpa39l/md2vk.git
synced 2026-09-29 18:05:04 +00:00
5.3 KiB
5.3 KiB
md2vk — Архитектура
Обзор
FastAPI-сервис, публикует Markdown на стену VK через wall.post с format_data.
Полный стек: Python 3.12, FastAPI, SQLAlchemy 2.0 async, SQLite, httpx, cryptography (Fernet), Docker.
Компоненты
┌─────────────────────────────── /opt/md2vk (bigbox) ───────────────────────────────┐
│ │
│ docker (контейнер md2vk, порт 127.0.0.1:8420) │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ app/main.py FastAPI entrypoint, lifespan → init_db │ │
│ │ app/config.py Settings из env (pydantic-settings) │ │
│ │ app/database.py async engine (aiosqlite), get_db │ │
│ │ app/models.py ORM: User, VkAccount, Publication │ │
│ │ app/security.py Fernet encrypt/decrypt, API-key gen/verify │ │
│ │ app/vk_client.py httpx-клиент: wall.post, users.get │ │
│ │ app/converters/markdown_to_vk.py MD → VK format_data + чанки │ │
│ │ app/api/v1.py эндпоинты /api/v1/* │ │
│ │ app/api/deps.py auth по API-ключу (Bearer / тело) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ /data (volume) → SQLite /data/md2vk.db │
│ /logs → access.{date}.log (JSONL аудит) │
│ /run/secrets/token_encryption_key (Docker secret) │
└───────────────────────────────────────────────────────────────────────────────────┘
Поток публикации
- Клиент (Hermes/skill)
POST /api/v1/publishcapi_key,vk_account_id,message_md - Auth: hash api_key → User.is_active
- Load VkAccount → decrypt_token (Fernet, только в памяти)
markdown_to_vk(message_md)→ chunks (VK-лимит ~4096 симв., режет по абзацам;@= 2 симв.)- Publication (status=draft|scheduled)
- Если
publish_dateзадан → status=scheduled (планировщик — TODO) - Иначе
vk.wall_post(message, owner_id, from_group, ..., format_data=items) - Ответ: post_id, owner_id, url
https://vk.com/wall{owner}_{post}; ошибки → status=error + error_message
Порт/интерфейсы
| Интерфейс | Адрес | Назначение |
|---|---|---|
| Локальный | 127.0.0.1:8420 | внутренний (Caddy на vps02 → 10.8.0.2:8420) |
| VK API | https://api.vk.com/method | исходящий (wall.post, users.get) |
| Swagger | /docs | openapi, за basic auth |
База данных (SQLite)
| Таблица | Ключевые поля |
|---|---|
| users | id, name, email, api_key_hash, api_key_prefix, is_active, created_at, updated_at |
| vk_accounts | id, user_id→users, vk_user_id (owner_id, - = сообщество), display_name, access_token_enc (Fernet), token_type (user|group), is_active, expires_at, last_used_at |
| publications | id, vk_account_id→vk_accounts, status (draft|scheduled|published|error), markdown_original, vk_text, vk_format_data, vk_post_id, vk_owner_id, attachments, scheduled_at, published_at, error_message |
Отложенные посты
Модель поддерживает scheduled_at, /publish с publish_date создаёт запись scheduled.
Планировщика нет — открытая задача (worker-процесс/cron, выбирающий status=scheduled AND scheduled_at<=now).
Ошибки VK API
| Код | Смысл |
|---|---|
VkApiError |
обёртка: error_code + error_msg из ответа VK; пишется в publications.error_message |
Конвертер Markdown
| Markdown | VK format |
|---|---|
**bold**, __bold__ |
bold |
*italic*, _italic_ |
italic |
***bold italic*** |
bold + italic |
`code` |
inline_code |
[text](url) |
link (+url) |
# H1..H6 |
bold (uppercase) |
> quote |
italic |
```code |
code (без format) |
--- |
─── |
Длинный текст режется на чанки по \n\n (абзацы), запас 10% от лимита 4096.