Spaces:
Runtime error
Runtime error
| """ | |
| database/models.py — SQLAlchemy ORM models for the knowledge base. | |
| Schema Design: | |
| - User: Tracks all users who interact with the bot. | |
| - Admin: Stores admins appointed by the Owner. | |
| - Folder: A hierarchical container (can be nested via parent_id). | |
| - Item: A piece of content (file, image, video, link, or text) inside a Folder. | |
| - AdminLog: Audit trail of admin actions for the Owner dashboard. | |
| - UserLog: Tracks user navigation for the Admin dashboard. | |
| """ | |
| from datetime import datetime | |
| from sqlalchemy import ( | |
| BigInteger, Boolean, DateTime, ForeignKey, | |
| Integer, String, Text, func | |
| ) | |
| from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship | |
| class Base(DeclarativeBase): | |
| """Base class for all SQLAlchemy models.""" | |
| pass | |
| class User(Base): | |
| """Represents any Telegram user who has interacted with the bot.""" | |
| __tablename__ = "users" | |
| id: Mapped[int] = mapped_column(BigInteger, primary_key=True) # Telegram user ID | |
| username: Mapped[str | None] = mapped_column(String(64), nullable=True) | |
| full_name: Mapped[str] = mapped_column(String(256), nullable=False) | |
| is_banned: Mapped[bool] = mapped_column(Boolean, default=False) | |
| joined_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) | |
| # Relationships | |
| logs: Mapped[list["UserLog"]] = relationship("UserLog", back_populates="user") | |
| class Admin(Base): | |
| """Represents a user with admin privileges, appointed by the Owner.""" | |
| __tablename__ = "admins" | |
| id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) | |
| user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("users.id"), unique=True) | |
| username: Mapped[str | None] = mapped_column(String(64), nullable=True) | |
| full_name: Mapped[str] = mapped_column(String(256), nullable=False) | |
| added_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) | |
| added_by: Mapped[int] = mapped_column(BigInteger) # Owner's user ID | |
| # Relationships | |
| action_logs: Mapped[list["AdminLog"]] = relationship("AdminLog", back_populates="admin") | |
| class Folder(Base): | |
| """ | |
| A hierarchical folder (category) for organizing content. | |
| parent_id=None means it's a root-level folder. | |
| """ | |
| __tablename__ = "folders" | |
| id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) | |
| name: Mapped[str] = mapped_column(String(128), nullable=False) | |
| emoji: Mapped[str] = mapped_column(String(8), default="📁") | |
| parent_id: Mapped[int | None] = mapped_column( | |
| Integer, ForeignKey("folders.id", ondelete="CASCADE"), nullable=True | |
| ) | |
| created_by: Mapped[int] = mapped_column(BigInteger, ForeignKey("users.id")) | |
| created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) | |
| # Self-referential relationship for nested folders | |
| children: Mapped[list["Folder"]] = relationship( | |
| "Folder", | |
| back_populates="parent", | |
| cascade="all, delete-orphan" | |
| ) | |
| parent: Mapped["Folder | None"] = relationship( | |
| "Folder", back_populates="children", remote_side=[id] | |
| ) | |
| items: Mapped[list["Item"]] = relationship( | |
| "Item", back_populates="folder", cascade="all, delete-orphan" | |
| ) | |
| class Item(Base): | |
| """ | |
| A piece of content stored inside a Folder. | |
| Stores ONLY file_id for media — never downloads files locally. | |
| """ | |
| __tablename__ = "items" | |
| id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) | |
| folder_id: Mapped[int] = mapped_column(Integer, ForeignKey("folders.id", ondelete="CASCADE")) | |
| title: Mapped[str] = mapped_column(String(256), nullable=False) | |
| # Content type: 'text', 'link', 'photo', 'video', 'document', 'audio' | |
| content_type: Mapped[str] = mapped_column(String(32), nullable=False) | |
| # For media: Telegram's file_id (permanent reference, never download!) | |
| file_id: Mapped[str | None] = mapped_column(Text, nullable=True) | |
| # For text/link content | |
| text_content: Mapped[str | None] = mapped_column(Text, nullable=True) | |
| created_by: Mapped[int] = mapped_column(BigInteger, ForeignKey("users.id")) | |
| created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) | |
| # Relationships | |
| folder: Mapped["Folder"] = relationship("Folder", back_populates="items") | |
| class AdminLog(Base): | |
| """Audit trail of every action taken by an admin (for Owner dashboard).""" | |
| __tablename__ = "admin_logs" | |
| id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) | |
| admin_id: Mapped[int] = mapped_column(Integer, ForeignKey("admins.id"), nullable=True) | |
| admin_user_id: Mapped[int] = mapped_column(BigInteger) | |
| action: Mapped[str] = mapped_column(String(512), nullable=False) | |
| timestamp: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) | |
| admin: Mapped["Admin | None"] = relationship("Admin", back_populates="action_logs") | |
| class UserLog(Base): | |
| """Tracks user navigation events for the Admin dashboard.""" | |
| __tablename__ = "user_logs" | |
| id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) | |
| user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("users.id")) | |
| action: Mapped[str] = mapped_column(String(512), nullable=False) | |
| timestamp: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) | |
| user: Mapped["User"] = relationship("User", back_populates="logs") |