from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Text from sqlalchemy.orm import relationship from datetime import datetime from app.database import Base from app.models.user import User from app.models.lyrics import task_groups class Task(Base): __tablename__ = "tasks" id = Column(Integer, primary_key=True, index=True) task_id = Column(String, unique=True, index=True) user_id = Column(Integer, ForeignKey("users.id")) device_id = Column(String) song_name = Column(String) artist = Column(String, nullable=True, default=None) album = Column(String, nullable=True, default=None) cover_url = Column(String, nullable=True, default=None) stems = Column(Integer) status = Column(String, default="PENDING") created_at = Column(DateTime, default=datetime.utcnow) # Fecha en que el cliente confirmó que descargó todos los stems. downloaded_at = Column(DateTime, nullable=True, default=None) cloud_url = Column(Text, nullable=True, default=None) # JSON: {"vocals": "BQACAgIA...", "bass": "BQACAgIB..."} - file_ids de Telegram por stem telegram_file_ids = Column(Text, nullable=True, default=None) # JSON: {"vocals": 12345, "bass": 12346} - message_ids de Telegram (para borrar si el usuario elimina) telegram_message_ids = Column(Text, nullable=True, default=None) group_id = Column(Integer, ForeignKey("groups.id"), nullable=True) # JSON string con lista de acordes editados por el usuario [{"t": 0.5, "ch": "Am"}, ...] chords = Column(Text, nullable=True, default=None) # Fecha en que los archivos de Tebi (stems + voces corales) serán eliminados automáticamente # Normal: 3 días, Premium: 7 días desde la subida. NULL = ya expirado o tarea anterior al feature. cloud_expires_at = Column(DateTime, nullable=True, default=None) user = relationship("User", back_populates="tasks") group = relationship("Group", foreign_keys=[group_id]) groups_shared = relationship("Group", secondary=task_groups, back_populates="tasks_shared") @property def group_ids(self): return [g.id for g in self.groups_shared] class Worker(Base): __tablename__ = "workers" id = Column(Integer, primary_key=True, index=True) hostname = Column(String, unique=True, index=True) name = Column(String, nullable=True) # User-friendly custom name status = Column(String, default="offline") # online | offline | busy last_seen = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) # BYOK / Local Worker user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True, unique=True) token = Column(String, unique=True, index=True, nullable=True) command = Column(String, default="none") # start | stop | none is_active = Column(Boolean, default=False)