117 lines
2.9 KiB
Python
117 lines
2.9 KiB
Python
from datetime import datetime
|
|
|
|
from typing import Any
|
|
|
|
from pydantic import AnyHttpUrl, BaseModel, Field
|
|
|
|
|
|
class ProbeRequest(BaseModel):
|
|
url: AnyHttpUrl
|
|
|
|
|
|
|
|
|
|
class AnalyzeRequest(BaseModel):
|
|
url: AnyHttpUrl
|
|
|
|
|
|
class BrowserCapturedCandidate(BaseModel):
|
|
url: str
|
|
title: str | None = None
|
|
name: str | None = None
|
|
content_type: str | None = None
|
|
type: str | None = None
|
|
quality: str | None = None
|
|
|
|
|
|
class BrowserCaptureRequest(BaseModel):
|
|
page_url: AnyHttpUrl | None = None
|
|
candidates: list[BrowserCapturedCandidate] = Field(default_factory=list, max_length=80)
|
|
|
|
|
|
class MediaCandidateResponse(BaseModel):
|
|
url: str
|
|
kind: str
|
|
title: str | None = None
|
|
source: str
|
|
content_type: str | None = None
|
|
content_length: int | None = None
|
|
file_size: str | None = None
|
|
quality: str | None = None
|
|
allowed: bool = True
|
|
reason: str | None = None
|
|
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class AnalyzeResponse(BaseModel):
|
|
page_url: str
|
|
candidates: list[MediaCandidateResponse]
|
|
|
|
|
|
class InteractiveAnalyzeStartRequest(BaseModel):
|
|
url: AnyHttpUrl
|
|
|
|
|
|
class InteractiveAnalyzeClickRequest(BaseModel):
|
|
x: float = Field(ge=0)
|
|
y: float = Field(ge=0)
|
|
|
|
|
|
class InteractiveAnalyzeKeyRequest(BaseModel):
|
|
key: str = Field(min_length=1, max_length=40)
|
|
|
|
|
|
class InteractiveAnalyzeResponse(BaseModel):
|
|
session_id: str
|
|
page_url: str
|
|
screenshot: str
|
|
viewport: dict[str, int]
|
|
candidates: list[MediaCandidateResponse]
|
|
ublock_origin: bool = False
|
|
|
|
class ProbeResponse(BaseModel):
|
|
provider: str
|
|
title: str | None = None
|
|
description: str | None = None
|
|
thumbnail: str | None = None
|
|
duration_seconds: int | None = None
|
|
external_id: str | None = None
|
|
allowed: bool = True
|
|
|
|
|
|
class ImportRequest(BaseModel):
|
|
url: AnyHttpUrl
|
|
target_profile: str = Field(default="clip", pattern="^(film|serie|clip)$")
|
|
title: str | None = Field(default=None, max_length=180)
|
|
year: int | None = Field(default=None, ge=1888, le=2200)
|
|
series_title: str | None = Field(default=None, max_length=180)
|
|
season: int | None = Field(default=None, ge=1, le=200)
|
|
episode: int | None = Field(default=None, ge=1, le=1000)
|
|
episode_title: str | None = Field(default=None, max_length=180)
|
|
target_library: str | None = Field(default=None, max_length=80) # legacy API alias
|
|
max_height: int = Field(default=1080, ge=144, le=2160)
|
|
audio_only: bool = False
|
|
|
|
|
|
class ImportJobResponse(BaseModel):
|
|
id: int
|
|
source_id: int
|
|
title: str | None = None
|
|
status: str
|
|
target_library: str
|
|
target_path: str | None = None
|
|
progress: float
|
|
error: str | None = None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class SourceResponse(BaseModel):
|
|
id: int
|
|
kind: str
|
|
url: str
|
|
title: str | None = None
|
|
provider: str | None = None
|
|
external_id: str | None = None
|
|
created_at: datetime
|