/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2024 metamuffin */ pub mod config; pub mod helpers; pub mod r#impl; pub mod jhls; pub mod seek_index; pub mod stream; pub mod user; pub use chrono; use bincode::{Decode, Encode}; #[cfg(feature = "rocket")] use rocket::{FromFormField, UriDisplayQuery}; use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct Node { #[serde(default)] pub public: NodePublic, #[serde(default)] pub private: NodePrivate, } #[rustfmt::skip] #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode,Decode)] pub struct NodePrivate { #[serde(default)] pub id: Option, #[serde(default)] pub source: Option>, #[serde(default)] pub poster: Option, #[serde(default)] pub backdrop: Option, } #[rustfmt::skip] #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct NodePublic { #[serde(default)] pub kind: Option, #[serde(default)] pub poster: Option, #[serde(default)] pub backdrop: Option, #[serde(default)] pub title: Option, #[serde(default)] pub id: Option, #[serde(default)] pub path: Vec, #[serde(default)] pub children: Vec, #[serde(default)] pub tagline: Option, #[serde(default)] pub description: Option, #[serde(default)] pub release_date: Option, // in unix millis #[serde(default)] pub index: Option, #[serde(default)] pub media: Option, #[serde(default)] pub ratings: BTreeMap, #[serde(default)] pub federated: Option, } #[derive(Debug, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, Clone)] pub struct Asset(pub String); #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct ExtendedNode { pub ids: ObjectIds, pub people: BTreeMap>, } #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct Appearance { #[serde(default)] pub jobs: Vec, #[serde(default)] pub characters: Vec, pub person: Person, } #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct Person { pub name: String, pub headshot: Option, pub ids: ObjectIds, } #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct ObjectIds { pub trakt: Option, pub slug: Option, pub imdb: Option, pub tmdb: Option, pub omdb: Option, pub tvdb: Option, } #[rustfmt::skip] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] #[cfg_attr(feature = "rocket", derive(FromFormField, UriDisplayQuery))] #[serde(rename_all = "snake_case")] pub enum PeopleGroup { #[cfg_attr(feature = "rocket", field(value = "cast"))] Cast, #[cfg_attr(feature = "rocket", field(value = "writing"))] Writing, #[cfg_attr(feature = "rocket", field(value = "directing"))] Directing, #[cfg_attr(feature = "rocket", field(value = "art"))] Art, #[cfg_attr(feature = "rocket", field(value = "sound"))] Sound, #[cfg_attr(feature = "rocket", field(value = "camera"))] Camera, #[cfg_attr(feature = "rocket", field(value = "lighting"))] Lighting, #[cfg_attr(feature = "rocket", field(value = "crew"))] Crew, #[cfg_attr(feature = "rocket", field(value = "editing"))] Editing, #[cfg_attr(feature = "rocket", field(value = "production"))] Production, #[cfg_attr(feature = "rocket", field(value = "vfx"))] Vfx, #[cfg_attr(feature = "rocket", field(value = "costume"))] CostumeMakeup, #[cfg_attr(feature = "rocket", field(value = "createdby"))] CreatedBy, } #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct ImportOptions { pub id: String, pub sources: Vec, } #[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] #[serde(rename_all = "snake_case")] pub enum ImportSource { Override(Node), Tmdb { kind: TmdbKind, id: u64, }, Trakt { kind: TraktKind, id: u64, }, AutoChildren { path: Option, }, Media { path: PathBuf, #[serde(default)] ignore_metadata: bool, #[serde(default)] ignore_attachments: bool, #[serde(default)] ignore_chapters: bool, }, Federated { host: String, }, } #[rustfmt::skip] #[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Default, Encode,Decode)] #[cfg_attr(feature = "rocket", derive(FromFormField, UriDisplayQuery))] #[serde(rename_all = "snake_case")] pub enum NodeKind { #[cfg_attr(feature = "rocket", field(value = "movie"))] #[default] Movie, #[cfg_attr(feature = "rocket", field(value = "video"))] Video, #[cfg_attr(feature = "rocket", field(value = "shortformvideo"))] ShortFormVideo, #[cfg_attr(feature = "rocket", field(value = "collection"))] Collection, #[cfg_attr(feature = "rocket", field(value = "channel"))] Channel, #[cfg_attr(feature = "rocket", field(value = "show"))] Show, #[cfg_attr(feature = "rocket", field(value = "series"))] Series, #[cfg_attr(feature = "rocket", field(value = "season"))] Season, #[cfg_attr(feature = "rocket", field(value = "episode"))] Episode, } #[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] #[serde(rename_all = "snake_case")] pub enum TrackSource { Local(LocalTrack), Remote(usize), } pub type TrackID = usize; #[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode, Hash)] pub struct LocalTrack { pub path: PathBuf, pub track: TrackID, pub codec_private: Option>, } #[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] pub struct MediaInfo { pub duration: f64, // in seconds pub tracks: Vec, #[serde(default)] pub chapters: Vec, } #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct Chapter { pub time_start: Option, pub time_end: Option, pub labels: Vec<(String, String)>, } #[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] pub struct SourceTrack { pub kind: SourceTrackKind, pub name: String, pub codec: String, pub language: String, pub default_duration: Option, #[serde(default)] pub federated: Vec, } #[derive( Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode, )] #[serde(rename_all = "snake_case")] pub enum Rating { Imdb, Tmdb, RottenTomatoes, Metacritic, YoutubeViews, YoutubeLikes, YoutubeFollowers, Trakt, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Encode, Decode)] #[serde(rename_all = "snake_case")] pub enum SourceTrackKind { Video { width: u64, height: u64, display_width: Option, display_height: Option, display_unit: Option, fps: Option, }, Audio { channels: usize, sample_rate: f64, bit_depth: Option, }, Subtitles, } #[rustfmt::skip] #[derive(Debug, Clone, Copy, Encode, Decode)] #[cfg_attr(feature = "rocket", derive(FromFormField, UriDisplayQuery))] pub enum AssetRole { #[cfg_attr(feature = "rocket", field(value = "poster"))] Poster, #[cfg_attr(feature = "rocket", field(value = "backdrop"))] Backdrop, } #[derive(Debug, Serialize, Deserialize, Clone, Copy, Encode, Decode)] #[serde(rename_all = "snake_case")] pub enum TraktKind { Movie, Show, Season, Episode, Person, User, } impl TraktKind { pub fn singular(self) -> &'static str { match self { TraktKind::Movie => "movie", TraktKind::Show => "show", TraktKind::Season => "season", TraktKind::Episode => "episode", TraktKind::Person => "person", TraktKind::User => "user", } } pub fn plural(self) -> &'static str { match self { TraktKind::Movie => "movies", TraktKind::Show => "shows", TraktKind::Season => "seasons", TraktKind::Episode => "episodes", TraktKind::Person => "people", TraktKind::User => "users", // //! not used in API } } } impl ToString for TraktKind { fn to_string(&self) -> String { match self { TraktKind::Movie => "Movie", TraktKind::Show => "Show", TraktKind::Season => "Season", TraktKind::Episode => "Episode", TraktKind::Person => "Person", TraktKind::User => "User", } .to_string() } } impl Display for ObjectIds { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if let Some(id) = self.trakt { f.write_fmt(format_args!("trakt={}", id))?; } if let Some(_id) = &self.slug { f.write_str(",slug")?; } if let Some(id) = self.tmdb { f.write_fmt(format_args!(",tmdb={}", id))?; } if let Some(_id) = &self.imdb { f.write_str(",imdb")?; } if let Some(_id) = &self.tvdb { f.write_str(",tvdb")?; } if let Some(_id) = &self.omdb { f.write_str(",omdb")?; } Ok(()) } } impl Display for PeopleGroup { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { PeopleGroup::Cast => "Cast", PeopleGroup::Writing => "Writing", PeopleGroup::Directing => "Directing", PeopleGroup::Art => "Art", PeopleGroup::Sound => "Sound", PeopleGroup::Camera => "Camera", PeopleGroup::Lighting => "Lighting", PeopleGroup::Crew => "Crew", PeopleGroup::Editing => "Editing", PeopleGroup::Production => "Production", PeopleGroup::Vfx => "Visual Effects", PeopleGroup::CostumeMakeup => "Costume & Makeup", PeopleGroup::CreatedBy => "Created by:", }) } } #[derive(Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode)] pub enum TmdbKind { Tv, Movie, } impl Display for TmdbKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { TmdbKind::Tv => "tv", TmdbKind::Movie => "movie", }) } }