feat(UI): added docker image and config

This commit is contained in:
2025-10-10 11:15:28 +13:00
parent 9e61d18bf6
commit 9f5a25fcf5
23 changed files with 3287 additions and 18 deletions
+130
View File
@@ -0,0 +1,130 @@
"""
Database models for scheduled downloads.
"""
from sqlalchemy import Column, String, Integer, Boolean, DateTime, Time, ForeignKey, Text
from sqlalchemy.orm import relationship
from datetime import datetime, time as time_type
import uuid
import pytz
from .database import Base
def generate_uuid():
"""Generate a UUID string"""
return str(uuid.uuid4())
class ScheduledTask(Base):
"""
Represents a scheduled download task.
Tasks run at a specified time each day.
"""
__tablename__ = "scheduled_tasks"
# Primary key
id = Column(String(36), primary_key=True, default=generate_uuid)
# Task identification
name = Column(String(255), nullable=False, index=True)
enabled = Column(Boolean, default=True, nullable=False, index=True)
# Download configuration
source_type = Column(String(20), nullable=False) # "subreddit" or "user"
source_name = Column(String(255), nullable=False, index=True)
download_mode = Column(String(20), nullable=False) # "download", "archive", "clone"
# Filter options
limit = Column(Integer, default=25, nullable=False)
sort = Column(String(20), default="hot", nullable=False)
time_filter = Column(String(20), default="day", nullable=False) # Always "day" for daily tasks
min_score = Column(Integer, nullable=True)
no_dupes = Column(Boolean, default=True, nullable=False) # Always true for scheduled
simple_check = Column(Boolean, default=False, nullable=False)
# Scheduling
schedule_frequency = Column(String(20), default="daily", nullable=False)
run_time = Column(Time, nullable=False) # Time of day to run
timezone = Column(String(50), default="UTC", nullable=False)
# Metadata
created_at = Column(DateTime, default=lambda: datetime.now(pytz.UTC), nullable=False)
updated_at = Column(DateTime, default=lambda: datetime.now(pytz.UTC), onupdate=lambda: datetime.now(pytz.UTC), nullable=False)
last_run_at = Column(DateTime, nullable=True, index=True)
next_run_at = Column(DateTime, nullable=True, index=True)
# Authentication
auth_state = Column(String(255), nullable=True)
# Relationships
executions = relationship("TaskExecutionHistory", back_populates="task", cascade="all, delete-orphan")
def to_dict(self):
"""Convert to dictionary for JSON serialization"""
return {
"id": self.id,
"name": self.name,
"enabled": self.enabled,
"source_type": self.source_type,
"source_name": self.source_name,
"download_mode": self.download_mode,
"limit": self.limit,
"sort": self.sort,
"time_filter": self.time_filter,
"min_score": self.min_score,
"no_dupes": self.no_dupes,
"simple_check": self.simple_check,
"schedule_frequency": self.schedule_frequency,
"run_time": self.run_time.isoformat() if self.run_time else None,
"timezone": self.timezone,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
"last_run_at": self.last_run_at.isoformat() if self.last_run_at else None,
"next_run_at": self.next_run_at.isoformat() if self.next_run_at else None,
"auth_state": self.auth_state
}
class TaskExecutionHistory(Base):
"""
Records each execution of a scheduled task.
Tracks success/failure and metrics.
"""
__tablename__ = "task_execution_history"
# Primary key
id = Column(String(36), primary_key=True, default=generate_uuid)
# Foreign key to task
task_id = Column(String(36), ForeignKey("scheduled_tasks.id", ondelete="CASCADE"), nullable=False, index=True)
# Execution details
started_at = Column(DateTime, default=lambda: datetime.now(pytz.UTC), nullable=False, index=True)
completed_at = Column(DateTime, nullable=True)
status = Column(String(20), default="queued", nullable=False, index=True) # queued, running, success, failed, skipped
# Results
items_found = Column(Integer, default=0, nullable=False)
items_downloaded = Column(Integer, default=0, nullable=False)
error_message = Column(Text, nullable=True)
# Link to download
download_id = Column(String(255), nullable=True, index=True)
# Relationships
task = relationship("ScheduledTask", back_populates="executions")
def to_dict(self):
"""Convert to dictionary for JSON serialization"""
return {
"id": self.id,
"task_id": self.task_id,
"started_at": self.started_at.isoformat() if self.started_at else None,
"completed_at": self.completed_at.isoformat() if self.completed_at else None,
"status": self.status,
"items_found": self.items_found,
"items_downloaded": self.items_downloaded,
"error_message": self.error_message,
"download_id": self.download_id
}