from __future__ import annotations from datetime import datetime from typing import Optional from sqlalchemy import DateTime, Enum, ForeignKey, String, UniqueConstraint, func, Text, JSON, Boolean from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import Enum as EnumType # Явный импорт Enum для типизации from app.db.session import Base from app.models.post import PostType from enum import Enum as PyEnum class PostStatus(str, PyEnum): draft = "draft" scheduled = "scheduled" sent = "sent" failed = "failed" class TemplateVisibility(str, PyEnum): private = "private" org = "org" public = "public" class Template(Base): __tablename__ = "templates" __table_args__ = ( UniqueConstraint("owner_id", "name", name="uq_template_owner_name"), ) id: Mapped[int] = mapped_column(primary_key=True) owner_id: Mapped[int] = mapped_column(ForeignKey("users.id")) name: Mapped[str] = mapped_column(String(100)) title: Mapped[str] = mapped_column(String(200)) description: Mapped[Optional[str]] = mapped_column(Text, nullable=True) content: Mapped[str] = mapped_column(Text) keyboard_tpl: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True) parse_mode: Mapped[str] = mapped_column(String(20), default="HTML") type: Mapped[PostType] = mapped_column(Enum(PostType)) visibility: Mapped[TemplateVisibility] = mapped_column( EnumType(TemplateVisibility), default=TemplateVisibility.private ) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime, server_default=func.now(), onupdate=func.now() ) @classmethod async def get_by_name(cls, session, name: str) -> Optional[Template]: """Получение шаблона по имени.""" stmt = cls.__table__.select().where(cls.__table__.c.name == name) result = await session.execute(stmt) return result.scalar_one_or_none() async def render(self, template_vars: dict, context: dict) -> dict: """Рендеринг шаблона. Args: template_vars: Переменные для подстановки context: Дополнительный контекст Returns: Отрендеренные данные """ text = self.content keyboard = self.keyboard_tpl # Подстановка переменных for key, value in template_vars.items(): text = text.replace(f"{{${key}}}", str(value)) # Подготовка данных для отправки return { "type": self.type, "text": text, "keyboard": keyboard, "parse_mode": self.parse_mode } id: Mapped[int] = mapped_column(primary_key=True) owner_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), index=True) name: Mapped[str] = mapped_column(String(64)) title: Mapped[Optional[str]] = mapped_column(String(128)) type: Mapped[PostType] = mapped_column(EnumType(PostType), default=PostType.text) content: Mapped[str] = mapped_column(Text) keyboard_tpl: Mapped[Optional[list[dict]]] = mapped_column(JSON, nullable=True) parse_mode: Mapped[Optional[str]] = mapped_column(String(16), default="HTML") visibility: Mapped[TemplateVisibility] = mapped_column(EnumType(TemplateVisibility), default=TemplateVisibility.private) is_archived: Mapped[bool] = mapped_column(Boolean, default=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())