youtube-summarizer/backend/models/summary.py

123 lines
4.8 KiB
Python

"""Summary model for storing YouTube video summaries."""
from sqlalchemy import Column, String, Text, Float, DateTime, ForeignKey, JSON, Integer, Boolean, Index
from sqlalchemy.orm import relationship
import uuid
from datetime import datetime
import secrets
from backend.core.database_registry import registry
from backend.models.base import Model
Base = registry.Base
class Summary(Model):
"""Summary model for storing processed video summaries."""
__tablename__ = "summaries"
__table_args__ = {"extend_existing": True}
# Primary key
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
# Foreign key to user (nullable for anonymous summaries)
user_id = Column(String(36), ForeignKey("users.id"), nullable=True, index=True)
# Video information
video_id = Column(String(20), nullable=False, index=True)
video_title = Column(Text)
video_url = Column(Text, nullable=False)
video_duration = Column(Integer) # Duration in seconds
channel_name = Column(String(255))
published_at = Column(DateTime)
# Transcript and summary
transcript = Column(Text)
summary = Column(Text)
key_points = Column(JSON) # Array of key points
main_themes = Column(JSON) # Array of main themes
chapters = Column(JSON) # Array of chapter objects with timestamps
actionable_insights = Column(JSON) # Array of actionable insights
# AI processing details
model_used = Column(String(50))
processing_time = Column(Float) # Time in seconds
confidence_score = Column(Float)
quality_score = Column(Float)
# Cost tracking
input_tokens = Column(Integer)
output_tokens = Column(Integer)
cost_usd = Column(Float)
# Configuration used
summary_length = Column(String(20)) # brief, standard, detailed
focus_areas = Column(JSON) # Array of focus areas
include_timestamps = Column(Boolean, default=False)
# Source tracking (added for unified storage)
source = Column(String(20), default="frontend") # frontend, cli, api, migrated_from_file
job_id = Column(String(36), nullable=True) # Pipeline job ID
# History management fields
is_starred = Column(Boolean, default=False, index=True)
notes = Column(Text) # User's personal notes
tags = Column(JSON) # Array of user tags
shared_token = Column(String(64), unique=True, nullable=True) # For sharing
is_public = Column(Boolean, default=False)
view_count = Column(Integer, default=0)
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
user = relationship("backend.models.user.User", back_populates="summaries")
exports = relationship("backend.models.summary.ExportHistory", back_populates="summary", cascade="all, delete-orphan")
agent_analyses = relationship("backend.models.agent_models.AgentSummary", back_populates="summary", cascade="all, delete-orphan")
# Enhanced export relationships (Story 4.4)
export_metadata = relationship("backend.models.enhanced_export.ExportMetadata", back_populates="summary", cascade="all, delete-orphan")
sections = relationship("backend.models.enhanced_export.SummarySection", back_populates="summary", cascade="all, delete-orphan")
def __repr__(self):
return f"<Summary(video_id='{self.video_id}', user_id='{self.user_id}', model='{self.model_used}')>"
def generate_share_token(self):
"""Generate a unique share token for this summary."""
self.shared_token = secrets.token_urlsafe(32)
return self.shared_token
# Create composite indexes for performance
Index('idx_user_starred', Summary.user_id, Summary.is_starred)
Index('idx_user_created', Summary.user_id, Summary.created_at)
class ExportHistory(Model):
"""Track export history for summaries."""
__tablename__ = "export_history"
__table_args__ = {"extend_existing": True}
# Primary key
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
# Foreign keys
summary_id = Column(String(36), ForeignKey("summaries.id"), nullable=False, index=True)
user_id = Column(String(36), ForeignKey("users.id"), nullable=True)
# Export details
export_format = Column(String(20), nullable=False) # markdown, pdf, html, json, text
file_size = Column(Integer) # Size in bytes
file_path = Column(Text) # Storage path if saved
# Metadata
created_at = Column(DateTime, default=datetime.utcnow)
# Relationships
summary = relationship("backend.models.summary.Summary", back_populates="exports")
def __repr__(self):
return f"<ExportHistory(summary_id='{self.summary_id}', format='{self.export_format}')>"