Baseline md2vk: docs, audit log, docker 8420, openspec, deploy

This commit is contained in:
estorozhenko
2026-09-18 22:05:01 +00:00
commit 09e960a3a9
39 changed files with 3716 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
"""Pydantic-схемы для API-запросов и ответов."""
from __future__ import annotations
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
# ─── Аутентификация ────────────────────────────────────────────────────────
class ApiKeyRequest(BaseModel):
api_key: str = Field(..., description="API-ключ пользователя")
# ─── Аккаунты ──────────────────────────────────────────────────────────────
class AccountCreateRequest(BaseModel):
api_key: str
vk_user_id: int = Field(..., description="VK owner_id (положительный — пользователь, отрицательный — сообщество)")
display_name: str = Field(..., max_length=255, description="Отображаемое имя аккаунта")
access_token: str = Field(..., description="VK OAuth-токен с правами wall")
token_type: str = Field(default="user", pattern="^(user|group)$", description="user | group")
class AccountResponse(BaseModel):
id: int
vk_user_id: int
display_name: str
token_type: str
is_active: bool
created_at: datetime
class AccountListResponse(BaseModel):
accounts: list[AccountResponse]
# ─── Публикация ────────────────────────────────────────────────────────────
class PublishRequest(BaseModel):
api_key: str
vk_account_id: int = Field(..., description="ID VK-аккаунта из /api/v1/accounts")
message_md: str = Field(..., min_length=1, description="Текст поста в Markdown")
publish_date: Optional[datetime] = Field(None, description="ISO datetime для отложенной публикации")
friends_only: bool = False
attachments: Optional[str] = Field(None, description="VK-вложения через запятую (photo123_456, ...)")
signed: Optional[bool] = Field(None, description="Подпись автора (для групп)")
class PublishResponse(BaseModel):
success: bool
publication_id: int
vk_post_id: Optional[int] = None
vk_owner_id: Optional[int] = None
url: Optional[str] = None
error: Optional[str] = None
# ─── Конвертация ───────────────────────────────────────────────────────────
class ConvertRequest(BaseModel):
message_md: str = Field(..., min_length=1, description="Markdown-текст для конвертации")
class FormatItemResponse(BaseModel):
type: str
offset: int
length: int
url: Optional[str] = None
class ConvertResponse(BaseModel):
text: str
format_data: Optional[dict] = None
# ─── Публикации (архив) ────────────────────────────────────────────────────
class PublicationFilterRequest(BaseModel):
api_key: str
vk_account_id: Optional[int] = None
status: Optional[str] = Field(None, pattern="^(draft|scheduled|published|error)$")
limit: int = Field(default=20, ge=1, le=100)
offset: int = Field(default=0, ge=0)
class PublicationItem(BaseModel):
id: int
vk_account_id: int
status: str
markdown_original: str
vk_post_id: Optional[int] = None
vk_owner_id: Optional[int] = None
scheduled_at: Optional[datetime] = None
published_at: Optional[datetime] = None
error_message: Optional[str] = None
created_at: datetime
class PublicationListResponse(BaseModel):
publications: list[PublicationItem]
total: int
# ─── Ошибки ────────────────────────────────────────────────────────────────
class ErrorResponse(BaseModel):
detail: str