Files

92 lines
4.4 KiB
Python

"""ORM-модели: User, VkAccount, Publication."""
from __future__ import annotations
import datetime
from typing import Optional
from sqlalchemy import (
Boolean,
DateTime,
ForeignKey,
Integer,
String,
Text,
func,
)
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
email: Mapped[Optional[str]] = mapped_column(String(255), nullable=True, unique=True)
api_key_hash: Mapped[str] = mapped_column(String(64), nullable=False, unique=True)
api_key_prefix: Mapped[str] = mapped_column(String(12), nullable=False, comment="Первые ~10 символов ключа для идентификации")
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
updated_at: Mapped[datetime.datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now(), nullable=False)
vk_accounts: Mapped[list[VkAccount]] = relationship(back_populates="user", cascade="all, delete-orphan")
class VkAccount(Base):
__tablename__ = "vk_accounts"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False, index=True)
vk_user_id: Mapped[int] = mapped_column(Integer, nullable=False, comment="VK owner_id (положительный — пользователь, отрицательный — сообщество)")
display_name: Mapped[str] = mapped_column(String(255), nullable=False, comment="Отображаемое имя (например, 'Моя стена')")
access_token_enc: Mapped[str] = mapped_column(Text, nullable=False, comment="Зашифрованный VK-токен")
token_type: Mapped[str] = mapped_column(String(10), default="user", nullable=False, comment="user | group")
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
expires_at: Mapped[Optional[datetime.datetime]] = mapped_column(DateTime, nullable=True)
last_used_at: Mapped[Optional[datetime.datetime]] = mapped_column(DateTime, nullable=True)
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
user: Mapped[User] = relationship(back_populates="vk_accounts")
publications: Mapped[list[Publication]] = relationship(back_populates="vk_account", cascade="all, delete-orphan")
class Publication(Base):
__tablename__ = "publications"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
vk_account_id: Mapped[int] = mapped_column(ForeignKey("vk_accounts.id"), nullable=False, index=True)
status: Mapped[str] = mapped_column(
String(20),
default="draft",
nullable=False,
comment="draft | scheduled | published | error",
)
# Входные данные
markdown_original: Mapped[str] = mapped_column(Text, nullable=False, comment="Исходный Markdown")
# Результат конвертации
vk_text: Mapped[str] = mapped_column(Text, nullable=False, comment="Текст для VK")
vk_format_data: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="JSON format_data")
# Результат публикации
vk_post_id: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
vk_owner_id: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
attachments: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="JSON attachments")
# Отложенная публикация
scheduled_at: Mapped[Optional[datetime.datetime]] = mapped_column(DateTime, nullable=True)
published_at: Mapped[Optional[datetime.datetime]] = mapped_column(DateTime, nullable=True)
# Ошибки
error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime.datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
updated_at: Mapped[datetime.datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now(), nullable=False)
vk_account: Mapped[VkAccount] = relationship(back_populates="publications")