models.py
Rama main · réplica de lectura del repositorio original.
"""
models.py - Manages Pydantic models
"""
from typing import List, Optional, Dict, Any
from pydantic import BaseModel, Field
class SettingsRequest(BaseModel):
connection_id: Optional[str] = None
label: str = Field(default="", max_length=100)
clear_external_api_key: bool = False
server_type: str
emby_url: str
emby_user: str
emby_pass: str
external_api_key: Optional[str] = None
# AI fields are accepted for compatibility with older clients and ignored: saving a
# media connection no longer writes ai_settings, so a stale form can never blank a
# provider the user configured in the AI Hub. Use AiSettingsUpdateRequest instead.
gemini_key: Optional[str] = None
ai_provider: Optional[str] = None
ollama_url: Optional[str] = None
ollama_model: Optional[str] = None
ollama_timeout: Optional[int] = None
starred_models: Optional[List[str]] = None
class ModelUpdateRequest(BaseModel):
ollama_model: str
class AiSettingsUpdateRequest(BaseModel):
# None means "leave this field as stored". Defaults here would make a partial post
# silently blank out settings the caller never mentioned -- that is how a saved
# Gemini key gets destroyed. An empty string is still an explicit clear.
ai_provider: Optional[str] = None
gemini_key: Optional[str] = None
ollama_url: Optional[str] = None
ollama_model: Optional[str] = None
ollama_timeout: Optional[int] = None
starred_models: Optional[List[str]] = None
class MovieFinderRequest(BaseModel):
user_id: str
filters: Dict[str, Any] = Field(default_factory=dict)
class MusicFinderRequest(BaseModel):
user_id: str
filters: Dict[str, Any] = Field(default_factory=dict)
class FreshnessOptions(BaseModel):
last_successful_builds: int = 0
history_scope: str = "series"
watched_within_days: int = 0
exhaustion_policy: str = "shorter"
class DuplicatePolicyOptions(BaseModel):
cross_block_policy: Optional[str] = None
mode: str = "suppress"
max_movies_per_franchise: int = 0
class SequencingItem(BaseModel):
block_id: str
take: int = 1
class SequencingOptions(BaseModel):
mode: str = "sequential"
pattern: Optional[List[SequencingItem]] = None
exhaustion_policy: str = "continue"
class RuntimeBudgetOptions(BaseModel):
mode: str = "off"
target_minutes: int = 0
allowed_overrun_minutes: int = Field(default=15, ge=0)
end_local_time: Optional[str] = None
timezone: Optional[str] = None
class MixOptions(BaseModel):
freshness: Optional[FreshnessOptions] = Field(default_factory=FreshnessOptions)
duplicate_policy: Optional[DuplicatePolicyOptions] = Field(default_factory=DuplicatePolicyOptions)
sequencing: Optional[SequencingOptions] = Field(default_factory=SequencingOptions)
runtime_budget: Optional[RuntimeBudgetOptions] = Field(default_factory=RuntimeBudgetOptions)
class MixedPlaylistRequest(BaseModel):
user_id: str
playlist_name: str
blocks: Optional[List[Dict[str, Any]]] = None
item_ids: Optional[List[str]] = None
create_as_collection: bool = False
mix_options: Optional[Dict[str, Any]] = None
class BuilderPreviewRequest(BaseModel):
user_id: str
blocks: List[Dict[str, Any]]
mix_options: Optional[Dict[str, Any]] = None
class ReorderItemsRequest(BaseModel):
user_id: str
item_ids: List[str]
class AddItemsRequest(BaseModel):
user_id: str
blocks: List[Dict[str, Any]]
mix_options: Optional[Dict[str, Any]] = None
class ScheduleDetails(BaseModel):
frequency: str
time: Optional[str] = None
days_of_week: Optional[List[int]] = None
interval_minutes: Optional[int] = None
class QuickPlaylistScheduleData(BaseModel):
quick_playlist_type: str
options: Optional[Dict[str, Any]] = None
class EnrichmentScheduleData(BaseModel):
batch_size: int = Field(default=15, ge=1, le=500)
timeout: int = Field(default=120, ge=10, le=600)
class ScheduleRequest(BaseModel):
job_type: str
playlist_name: str
user_id: str
schedule_details: ScheduleDetails
preset_id: Optional[str] = None
preset_name: Optional[str] = None
blocks: Optional[List[Dict[str, Any]]] = None
quick_playlist_data: Optional[QuickPlaylistScheduleData] = None
enrichment_data: Optional[EnrichmentScheduleData] = None
create_as_collection: bool = False
mix_options: Optional[Dict[str, Any]] = None
enabled: bool = True
snoozed_until: Optional[str] = None
trigger_sources: List[str] = ["clock", "watch", "library"]
timezone: Optional[str] = None
class SnoozeRequest(BaseModel):
minutes: Optional[int] = 60
until: Optional[str] = None
class AiTweaks(BaseModel):
threshold: float = 0.65
limit: int = 25
strictness: str = "genre_verified"
temperature: float = 0.2
target_size: int = 10
only_unwatched: bool = False
system_prompt: str = ""
class AiPromptRequest(BaseModel):
prompt: str
tweaks: Optional[AiTweaks] = None
existing_blocks: Optional[List[Dict[str, Any]]] = None
class QuickBuildRequest(BaseModel):
user_id: str
playlist_name: str
quick_build_type: str
options: Dict[str, Any] = Field(default_factory=dict)
class DeleteItemRequest(BaseModel):
item_id: str
user_id: str
class RemoveFromPlaylistRequest(BaseModel):
item_id_to_remove: str
user_id: str
class ConvertItemRequest(BaseModel):
item_id: str
user_id: str
new_name: str
target_type: str
delete_original: bool = False
class ResetWatchRequest(BaseModel):
user_id: str
season_number: Optional[int] = None
class ExternalPromptRequest(BaseModel):
prompt: str
preset_name: str
class ExternalBuildRequest(BaseModel):
preset_name: str
playlist_name: str
class ResetVectorDbRequest(BaseModel):
preserve_enrichments: bool = True
class StartEnrichmentRequest(BaseModel):
batch_size: int = 10
max_items: Optional[int] = None
class BulkDeleteRequest(BaseModel):
item_ids: List[str]
user_id: str
class OverlapReportRequest(BaseModel):
item_ids: Optional[List[str]] = None
user_id: str
class ReplayRunRequest(BaseModel):
playlist_name: Optional[str] = None
user_id: Optional[str] = None
dry_run: bool = False
class AssistItem(BaseModel):
"""One movie on the Playlist Assist canvas as the browser reports it."""
Id: str
locked: bool = False
Name: Optional[str] = None
class AssistChatMessage(BaseModel):
role: str = "user"
content: str = ""
class AssistChatRequest(BaseModel):
prompt: str
revision_id: Optional[str] = None
current_items: List[AssistItem] = Field(default_factory=list)
chat_history: List[AssistChatMessage] = Field(default_factory=list)
class AssistSaveRequest(BaseModel):
playlist_name: str
description: str = ""
item_ids: List[str] = Field(default_factory=list)
user_id: Optional[str] = None