Files

81 lines
3.4 KiB
Python

"""Request models for API endpoints."""
from typing import Optional, List
from pydantic import BaseModel, Field, validator
class TracklistEntry(BaseModel):
"""A single track entry from the tracklist."""
ts: str = Field(..., description="Timestamp (e.g., '00:00' or '00:00-01:30')")
tn: Optional[str] = Field("", description="Track name")
an: Optional[str] = Field("", description="Author/artist")
al: Optional[str] = Field("", description="Album")
date: Optional[str] = Field("", description="Date/year")
ext: Optional[str] = Field("", description="File extension")
@validator("ts")
def validate_timestamp(cls, v: str) -> str:
v = v.strip()
if not v:
raise ValueError("Timestamp cannot be empty")
if "-" in v:
parts = v.split("-", 1)
start = parts[0].strip()
end = parts[1].strip()
if not start or not end:
raise ValueError("Invalid range format. Expected 'start-end'")
for ts in [start, end]:
cls._validate_single_timestamp(ts)
else:
cls._validate_single_timestamp(v)
return v
@staticmethod
def _validate_single_timestamp(ts: str) -> None:
parts = ts.split(":")
if len(parts) not in (2, 3):
raise ValueError(f"Invalid timestamp format: {ts}. Expected mm:ss or HH:MM:SS")
try:
for p in parts:
int(p)
except ValueError:
raise ValueError(f"Invalid timestamp: {ts}. Must contain only numbers.")
class SplitRequest(BaseModel):
"""Request model for the split endpoint."""
task_id: str = Field(..., description="Task ID from upload")
tracklist: List[TracklistEntry] = Field(..., description="List of tracks")
# Container and codec options
container: Optional[str] = Field(None, description="Output container (auto-detect if None)")
audio_codec: Optional[str] = Field("copy", description="Audio codec (copy or encoder name)")
video_codec: Optional[str] = Field("copy", description="Video codec (copy or encoder name)")
subtitle_codec: Optional[str] = Field("copy", description="Subtitle codec (copy or encoder name)")
video_quality: Optional[int] = Field(None, description="Video quality (encoder-specific integer)")
# Stream handling
drop_video: bool = Field(False, description="Remove video streams")
drop_subs: bool = Field(False, description="Remove subtitle streams")
# Filename options
number_tracks: bool = Field(False, description="Prepend track numbers")
replace_bad_chars: bool = Field(False, description="Replace bad characters")
replacement_char: str = Field("_", description="Replacement character")
bad_chars: str = Field(r'!@#№$;:%^&?*(){}[]\/<>+=~`\' ', description="Bad characters to replace")
skip_existing: bool = Field(False, description="Skip existing files")
output_template: str = Field("%an-%tn.%ext", description="Output filename template")
# Metadata options
album: Optional[str] = Field(None, description="Album name")
comment: Optional[str] = Field(None, description="Comment")
no_comment: bool = Field(False, description="Ignore comment")
comment_stream: Optional[int] = Field(None, description="Comment stream index")
merge_comments: bool = Field(False, description="Merge all comments")
comment_separator: str = Field("; ", description="Separator for merged comments")