190 lines
4.7 KiB
Python
Executable file
190 lines
4.7 KiB
Python
Executable file
"""
|
|
StreamFlow Pydantic Schemas
|
|
Type-safe request/response models for the API
|
|
"""
|
|
from datetime import datetime
|
|
from typing import Optional, List
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# ====================
|
|
# Video Extraction
|
|
# ====================
|
|
|
|
class ExtractRequest(BaseModel):
|
|
"""Request to extract video stream URL"""
|
|
url: str = Field(..., description="Source video URL to extract")
|
|
quality: Optional[str] = Field(None, description="Preferred quality (e.g., '1080p', '720p')")
|
|
|
|
|
|
class ExtractResponse(BaseModel):
|
|
"""Response with extracted video stream information"""
|
|
title: str
|
|
thumbnail: str
|
|
duration: int = Field(..., description="Duration in seconds")
|
|
stream_url: str = Field(..., description="Direct stream URL (m3u8 or mp4)")
|
|
resolution: str
|
|
cached: bool = Field(..., description="Whether result was from cache")
|
|
extraction_time_ms: int = Field(..., description="Time taken to extract in milliseconds")
|
|
|
|
|
|
# ====================
|
|
# Video Library
|
|
# ====================
|
|
|
|
class VideoCreate(BaseModel):
|
|
"""Request to add a video to library"""
|
|
title: str = Field(..., min_length=1, max_length=500)
|
|
source_url: str = Field(..., min_length=1, max_length=2000)
|
|
description: Optional[str] = None
|
|
thumbnail: Optional[str] = None
|
|
category: Optional[str] = None
|
|
|
|
|
|
class VideoResponse(BaseModel):
|
|
"""Video from the library"""
|
|
id: int
|
|
title: str
|
|
source_url: str
|
|
thumbnail: Optional[str]
|
|
duration: int
|
|
resolution: Optional[str]
|
|
category: Optional[str]
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
# ====================
|
|
# Movie Catalog
|
|
# ====================
|
|
|
|
class MovieItem(BaseModel):
|
|
"""Movie item from catalog"""
|
|
id: str
|
|
title: str
|
|
original_title: Optional[str] = None
|
|
slug: str
|
|
thumbnail: str
|
|
poster_url: Optional[str] = None
|
|
backdrop: Optional[str] = None
|
|
year: Optional[int] = None
|
|
quality: Optional[str] = "HD"
|
|
duration: Optional[str] = None
|
|
category: str = "single"
|
|
rating: Optional[float] = None
|
|
tmdb_rating: Optional[float] = None
|
|
imdb_rating: Optional[float] = None
|
|
vote_count: Optional[int] = 0
|
|
genres: Optional[List[str]] = None
|
|
country: Optional[List[str]] = None
|
|
description: Optional[str] = None
|
|
episode_current: Optional[str] = None
|
|
lang: Optional[str] = None
|
|
modified: Optional[str] = None
|
|
|
|
|
|
class CatalogResponse(BaseModel):
|
|
"""Response with movie catalog"""
|
|
movies: List[MovieItem]
|
|
page: int
|
|
category: str
|
|
sort: Optional[str] = "modified"
|
|
total: int
|
|
|
|
|
|
class SearchResponse(BaseModel):
|
|
"""Search results response"""
|
|
movies: List[MovieItem]
|
|
total: int
|
|
|
|
|
|
class SectionResponse(BaseModel):
|
|
"""Single section with movies"""
|
|
title: str
|
|
key: str
|
|
movies: List[MovieItem]
|
|
|
|
|
|
class CuratedHomeResponse(BaseModel):
|
|
"""Curated homepage sections"""
|
|
sections: List[SectionResponse]
|
|
total: int
|
|
|
|
|
|
# ====================
|
|
# System
|
|
# ====================
|
|
|
|
class HealthResponse(BaseModel):
|
|
"""Health check response"""
|
|
status: str = "healthy"
|
|
cache_type: str
|
|
version: str
|
|
|
|
|
|
class VersionInfo(BaseModel):
|
|
"""Version information for a package"""
|
|
current: str
|
|
latest: Optional[str] = None
|
|
|
|
|
|
class VersionsResponse(BaseModel):
|
|
"""All package versions"""
|
|
status: str
|
|
versions: dict
|
|
|
|
|
|
class UpdateResponse(BaseModel):
|
|
"""Update operation response"""
|
|
package: Optional[str] = None
|
|
success: bool
|
|
message: str
|
|
|
|
|
|
# ====================
|
|
# Stream
|
|
# ====================
|
|
|
|
class StreamRequest(BaseModel):
|
|
"""Request for video stream URL"""
|
|
slug: str = Field(..., description="Movie slug identifier")
|
|
episode: int = Field(1, ge=1, description="Episode number")
|
|
|
|
|
|
class StreamResponse(BaseModel):
|
|
"""Video stream URL response"""
|
|
stream_url: str
|
|
|
|
|
|
# ====================
|
|
# Watch History
|
|
# ====================
|
|
|
|
class WatchHistoryItem(BaseModel):
|
|
"""Single watch history entry"""
|
|
slug: str
|
|
title: str
|
|
thumbnail: Optional[str] = None
|
|
episode: int = 1
|
|
progress: float = 0.0
|
|
duration: Optional[int] = None
|
|
timestamp: datetime
|
|
|
|
|
|
class WatchHistoryRequest(BaseModel):
|
|
"""Request to save watch progress"""
|
|
slug: str
|
|
title: str
|
|
thumbnail: Optional[str] = None
|
|
episode: int = 1
|
|
progress: float = Field(0.0, ge=0.0, le=1.0, description="Progress as decimal (0.0 to 1.0)")
|
|
duration: Optional[int] = None
|
|
|
|
|
|
class MyListItem(BaseModel):
|
|
"""Item in user's saved list"""
|
|
slug: str
|
|
title: str
|
|
thumbnail: Optional[str] = None
|
|
poster_url: Optional[str] = None
|
|
added_at: datetime
|