325 lines
7.6 KiB
TypeScript
325 lines
7.6 KiB
TypeScript
// API response and request types matching the backend DTOs
|
|
|
|
export interface ActivityEvent {
|
|
id: string;
|
|
timestamp: string;
|
|
event_type: string;
|
|
detail: string;
|
|
channel_id?: string;
|
|
}
|
|
|
|
export interface LogLine {
|
|
level: string;
|
|
target: string;
|
|
message: string;
|
|
timestamp: string;
|
|
}
|
|
|
|
export type ContentType = "movie" | "episode" | "short";
|
|
|
|
export type AccessMode = "public" | "password_protected" | "account_required" | "owner_only";
|
|
|
|
export type LogoPosition = "top_left" | "top_right" | "bottom_left" | "bottom_right";
|
|
|
|
export type FillStrategy = "best_fit" | "sequential" | "random";
|
|
|
|
export interface MediaFilter {
|
|
content_type?: ContentType | null;
|
|
genres: string[];
|
|
decade?: number | null;
|
|
tags: string[];
|
|
min_duration_secs?: number | null;
|
|
max_duration_secs?: number | null;
|
|
collections: string[];
|
|
/** Filter to one or more TV series by name. OR-combined: any listed show is eligible. */
|
|
series_names?: string[];
|
|
/** Free-text search, used for library browsing only. */
|
|
search_term?: string | null;
|
|
}
|
|
|
|
// Library browsing
|
|
|
|
export interface CollectionResponse {
|
|
id: string;
|
|
name: string;
|
|
collection_type?: string | null;
|
|
}
|
|
|
|
export interface SeriesResponse {
|
|
id: string;
|
|
name: string;
|
|
episode_count: number;
|
|
genres: string[];
|
|
year?: number | null;
|
|
}
|
|
|
|
export interface LibraryItemResponse {
|
|
id: string;
|
|
title: string;
|
|
content_type: ContentType;
|
|
duration_secs: number;
|
|
series_name?: string | null;
|
|
season_number?: number | null;
|
|
episode_number?: number | null;
|
|
year?: number | null;
|
|
genres: string[];
|
|
}
|
|
|
|
export interface RecyclePolicy {
|
|
cooldown_days?: number | null;
|
|
cooldown_generations?: number | null;
|
|
min_available_ratio: number;
|
|
}
|
|
|
|
export type BlockContent =
|
|
| { type: "algorithmic"; filter: MediaFilter; strategy: FillStrategy; provider_id?: string }
|
|
| { type: "manual"; items: string[]; provider_id?: string };
|
|
|
|
export interface ProgrammingBlock {
|
|
id: string;
|
|
name: string;
|
|
/** "HH:MM:SS" */
|
|
start_time: string;
|
|
duration_mins: number;
|
|
content: BlockContent;
|
|
/** Sequential only: loop back to episode 1 after the last episode. Default true on backend. */
|
|
loop_on_finish?: boolean;
|
|
/** When true, skip the channel-level recycle policy for this block. Default false on backend. */
|
|
ignore_recycle_policy?: boolean;
|
|
access_mode?: AccessMode;
|
|
/** Plain-text password sent to API; hashed server-side. Only set on write operations. */
|
|
access_password?: string;
|
|
}
|
|
|
|
export type Weekday =
|
|
| 'monday' | 'tuesday' | 'wednesday' | 'thursday'
|
|
| 'friday' | 'saturday' | 'sunday'
|
|
|
|
export const WEEKDAYS: Weekday[] = [
|
|
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
|
|
]
|
|
|
|
export const WEEKDAY_LABELS: Record<Weekday, string> = {
|
|
monday: 'Mon', tuesday: 'Tue', wednesday: 'Wed', thursday: 'Thu',
|
|
friday: 'Fri', saturday: 'Sat', sunday: 'Sun',
|
|
}
|
|
|
|
export interface ScheduleConfig {
|
|
day_blocks: Record<Weekday, ProgrammingBlock[]>
|
|
}
|
|
|
|
export interface ConfigSnapshot {
|
|
id: string
|
|
version_num: number
|
|
label: string | null
|
|
created_at: string
|
|
}
|
|
|
|
export interface ScheduleHistoryEntry {
|
|
id: string
|
|
generation: number
|
|
valid_from: string
|
|
valid_until: string
|
|
}
|
|
|
|
// Config
|
|
|
|
export type StreamingProtocol = "hls" | "direct_file";
|
|
|
|
export interface ProviderCapabilities {
|
|
collections: boolean;
|
|
series: boolean;
|
|
genres: boolean;
|
|
tags: boolean;
|
|
decade: boolean;
|
|
search: boolean;
|
|
streaming_protocol: StreamingProtocol;
|
|
rescan: boolean;
|
|
transcode: boolean;
|
|
}
|
|
|
|
export interface TranscodeSettings {
|
|
cleanup_ttl_hours: number;
|
|
}
|
|
|
|
export interface TranscodeStats {
|
|
cache_size_bytes: number;
|
|
item_count: number;
|
|
}
|
|
|
|
export interface ProviderInfo {
|
|
id: string;
|
|
capabilities: ProviderCapabilities;
|
|
}
|
|
|
|
export interface ConfigResponse {
|
|
allow_registration: boolean;
|
|
/** All registered providers. Added in multi-provider update. */
|
|
providers: ProviderInfo[];
|
|
/** Primary provider capabilities — kept for backward compat. */
|
|
provider_capabilities: ProviderCapabilities;
|
|
available_provider_types: string[];
|
|
}
|
|
|
|
export interface ProviderConfig {
|
|
id: string;
|
|
provider_type: string;
|
|
config_json: Record<string, string>;
|
|
enabled: boolean;
|
|
}
|
|
|
|
export interface ProviderTestResult {
|
|
ok: boolean;
|
|
message: string;
|
|
}
|
|
|
|
// Auth
|
|
|
|
export interface TokenResponse {
|
|
access_token: string;
|
|
token_type: string;
|
|
expires_in: number;
|
|
refresh_token?: string;
|
|
}
|
|
|
|
export interface UserResponse {
|
|
id: string;
|
|
email: string;
|
|
created_at: string;
|
|
is_admin: boolean;
|
|
}
|
|
|
|
// Channels
|
|
|
|
export interface ChannelResponse {
|
|
id: string;
|
|
owner_id: string;
|
|
name: string;
|
|
description?: string | null;
|
|
timezone: string;
|
|
schedule_config: ScheduleConfig;
|
|
recycle_policy: RecyclePolicy;
|
|
auto_schedule: boolean;
|
|
access_mode: AccessMode;
|
|
logo?: string | null;
|
|
logo_position: LogoPosition;
|
|
logo_opacity: number;
|
|
webhook_url?: string | null;
|
|
webhook_poll_interval_secs?: number;
|
|
webhook_body_template?: string | null;
|
|
webhook_headers?: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface CreateChannelRequest {
|
|
name: string;
|
|
timezone: string;
|
|
description?: string;
|
|
access_mode?: AccessMode;
|
|
access_password?: string;
|
|
webhook_url?: string;
|
|
webhook_poll_interval_secs?: number;
|
|
webhook_body_template?: string;
|
|
webhook_headers?: string;
|
|
}
|
|
|
|
export interface UpdateChannelRequest {
|
|
name?: string;
|
|
description?: string;
|
|
timezone?: string;
|
|
schedule_config?: ScheduleConfig;
|
|
recycle_policy?: RecyclePolicy;
|
|
auto_schedule?: boolean;
|
|
access_mode?: AccessMode;
|
|
/** Empty string clears the password. */
|
|
access_password?: string;
|
|
/** null = clear logo */
|
|
logo?: string | null;
|
|
logo_position?: LogoPosition;
|
|
logo_opacity?: number;
|
|
/** null = clear webhook */
|
|
webhook_url?: string | null;
|
|
webhook_poll_interval_secs?: number;
|
|
/** null = clear template */
|
|
webhook_body_template?: string | null;
|
|
/** null = clear headers */
|
|
webhook_headers?: string | null;
|
|
}
|
|
|
|
// Media & Schedule
|
|
|
|
export interface MediaItemResponse {
|
|
id: string;
|
|
title: string;
|
|
content_type: ContentType;
|
|
duration_secs: number;
|
|
description?: string | null;
|
|
genres: string[];
|
|
tags: string[];
|
|
year?: number | null;
|
|
/** Episodes only: the parent TV show name. */
|
|
series_name?: string | null;
|
|
/** Episodes only: season number (1-based). */
|
|
season_number?: number | null;
|
|
/** Episodes only: episode number within the season (1-based). */
|
|
episode_number?: number | null;
|
|
}
|
|
|
|
export interface ScheduledSlotResponse {
|
|
id: string;
|
|
block_id: string;
|
|
item: MediaItemResponse;
|
|
/** RFC3339 */
|
|
start_at: string;
|
|
/** RFC3339 */
|
|
end_at: string;
|
|
block_access_mode: AccessMode;
|
|
}
|
|
|
|
export interface ScheduleResponse {
|
|
id: string;
|
|
channel_id: string;
|
|
generation: number;
|
|
generated_at: string;
|
|
valid_from: string;
|
|
valid_until: string;
|
|
slots: ScheduledSlotResponse[];
|
|
}
|
|
|
|
export interface CurrentBroadcastResponse {
|
|
slot: ScheduledSlotResponse;
|
|
offset_secs: number;
|
|
block_access_mode: AccessMode;
|
|
}
|
|
|
|
// Library management
|
|
// Note: LibraryItemResponse is already defined in this file (search for it above).
|
|
// LibraryItemFull extends it with the extra fields returned by the DB-backed endpoint.
|
|
|
|
export interface LibraryItemFull extends LibraryItemResponse {
|
|
thumbnail_url?: string | null;
|
|
collection_id?: string | null;
|
|
collection_name?: string | null;
|
|
}
|
|
|
|
export interface PagedLibraryResponse {
|
|
items: LibraryItemFull[];
|
|
total: number;
|
|
}
|
|
|
|
export interface LibrarySyncLogEntry {
|
|
id: number;
|
|
provider_id: string;
|
|
started_at: string;
|
|
finished_at?: string | null;
|
|
items_found: number;
|
|
status: 'running' | 'done' | 'error';
|
|
error_msg?: string | null;
|
|
}
|
|
|
|
export interface AdminSettings {
|
|
library_sync_interval_hours: number;
|
|
[key: string]: unknown;
|
|
}
|