diff options
author | metamuffin <metamuffin@disroot.org> | 2025-02-04 15:18:45 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-02-04 15:18:45 +0100 |
commit | a117b0710fca0ba1ef1329a8921092d1bf46abcd (patch) | |
tree | c0524a44863bfce370f4a7d8a5efa7e9d381b134 | |
parent | 8118667fc80bdf0246b16dff08f5a522efea27cf (diff) | |
download | jellything-a117b0710fca0ba1ef1329a8921092d1bf46abcd.tar jellything-a117b0710fca0ba1ef1329a8921092d1bf46abcd.tar.bz2 jellything-a117b0710fca0ba1ef1329a8921092d1bf46abcd.tar.zst |
jellyfin backdrop
-rw-r--r-- | server/src/routes/compat/jellyfin/mod.rs | 117 | ||||
-rw-r--r-- | server/src/routes/compat/jellyfin/models.rs | 2 | ||||
-rw-r--r-- | server/src/routes/mod.rs | 16 | ||||
-rw-r--r-- | server/src/routes/ui/node.rs | 1 | ||||
-rw-r--r-- | server/src/routes/ui/sort.rs | 6 |
5 files changed, 92 insertions, 50 deletions
diff --git a/server/src/routes/compat/jellyfin/mod.rs b/server/src/routes/compat/jellyfin/mod.rs index 0fed578..85d6768 100644 --- a/server/src/routes/compat/jellyfin/mod.rs +++ b/server/src/routes/compat/jellyfin/mod.rs @@ -9,9 +9,13 @@ use crate::routes::{ stream::rocket_uri_macro_r_stream, ui::{ account::{login_logic, session::Session}, - assets::{rocket_uri_macro_r_asset, rocket_uri_macro_r_item_poster}, + assets::{ + rocket_uri_macro_r_asset, rocket_uri_macro_r_item_backdrop, + rocket_uri_macro_r_item_poster, + }, error::MyResult, node::{aspect_class, DatabaseNodeUserDataExt}, + sort::{filter_and_sort_nodes, FilterProperty, NodeFilterSort, SortOrder, SortProperty}, }, }; use anyhow::{anyhow, Context}; @@ -151,15 +155,25 @@ pub fn r_jellyfin_items_image_primary( _session: Session, id: &str, fillWidth: Option<usize>, - tag: Option<String>, + tag: String, ) -> Redirect { - if let Some(tag) = tag { - Redirect::permanent(rocket::uri!(r_asset(tag, fillWidth))) - } else { + if tag == "poster" { Redirect::permanent(rocket::uri!(r_item_poster(id, fillWidth))) + } else { + Redirect::permanent(rocket::uri!(r_asset(tag, fillWidth))) } } +#[get("/Items/<id>/Images/Backdrop/0?<maxWidth>")] +#[allow(non_snake_case)] +pub fn r_jellyfin_items_images_backdrop( + _session: Session, + id: &str, + maxWidth: Option<usize>, +) -> Redirect { + Redirect::permanent(rocket::uri!(r_item_backdrop(id, maxWidth))) +} + #[get("/Items/<id>")] #[allow(private_interfaces)] pub fn r_jellyfin_items_item( @@ -250,52 +264,70 @@ pub fn r_jellyfin_items( database: &State<Database>, query: JellyfinItemQuery, ) -> MyResult<Json<Value>> { - let mut items = Vec::new(); - - let nodes = if let Some(q) = query.search_term { - database - .search(&q, query.limit, query.start_index.unwrap_or_default())? - .1 + let (nodes, parent_kind) = if let Some(q) = query.search_term { + ( + database + .search(&q, query.limit, query.start_index.unwrap_or_default())? + .1, + None, + ) } else if let Some(parent) = query.parent_id { - database - .get_node_children(NodeID::from_slug(&parent))? - .into_iter() - .skip(query.start_index.unwrap_or_default()) - .take(query.limit) - .collect() + let parent = NodeID::from_slug(&parent); + ( + database + .get_node_children(parent)? + .into_iter() + .skip(query.start_index.unwrap_or_default()) + .take(query.limit) + .collect(), + database.get_node(parent)?.map(|n| n.kind), + ) } else { - vec![] + (vec![], None) }; let filter_kind = query .include_item_types - .map(|n| match n.as_str() { - "Movie" => NodeKind::Movie, - "Audio" => NodeKind::Music, - "Video" => NodeKind::Video, - _ => NodeKind::Unknown, + .and_then(|n| match n.as_str() { + "Movie" => Some(FilterProperty::KindMovie), + "Audio" => Some(FilterProperty::KindMusic), + "Video" => Some(FilterProperty::KindVideo), + _ => None, }) .or(if query.internal_artists { - Some(NodeKind::Channel) + Some(FilterProperty::KindChannel) } else { None }) .or(if query.internal_persons { - Some(NodeKind::Channel) + Some(FilterProperty::KindChannel) } else { None }); - for nid in nodes { - let (n, ud) = database.get_node_with_userdata(nid, &session)?; - if let Some(fk) = filter_kind { - if n.kind != fk { - continue; - } - } - if n.visibility >= Visibility::Reduced { - items.push(item_object(&n, &ud)) - } - } + + let mut nodes = nodes + .into_iter() + .map(|nid| database.get_node_with_userdata(nid, &session)) + .collect::<Result<Vec<_>, anyhow::Error>>()?; + + filter_and_sort_nodes( + &NodeFilterSort { + sort_by: None, + filter_kind: filter_kind.map(|a| vec![a]), + sort_order: None, + }, + match parent_kind { + Some(NodeKind::Channel) => (SortProperty::ReleaseDate, SortOrder::Descending), + _ => (SortProperty::Title, SortOrder::Ascending), + }, + &mut nodes, + ); + + let items = nodes + .into_iter() + .filter(|(n, _)| n.visibility >= Visibility::Reduced) + .map(|(n, ud)| item_object(&n, &ud)) + .collect::<Vec<_>>(); Ok(Json(json!({ "Items": items, @@ -361,6 +393,15 @@ pub fn r_jellyfin_items_intros(_session: Session, uid: &str, id: &str) -> Json<V })) } +#[get("/Shows/NextUp")] +pub fn r_jellyfin_shows_nextup(_session: Session) -> Json<Value> { + Json(json!({ + "Items": [], + "TotalRecordCount": 0, + "StartIndex": 0 + })) +} + #[post("/Items/<id>/PlaybackInfo")] pub fn r_jellyfin_items_playbackinfo( _session: Session, @@ -704,8 +745,8 @@ fn item_object(node: &Node, userdata: &NodeUserData) -> JellyfinItem { "aspect-square" | _ => 1., }, collection_type: "unknown".to_owned(), - image_tags: BTreeMap::from_iter([("Primary".to_string(), "the-image".to_string())]), - backdrop_image_tags: vec![], + image_tags: BTreeMap::from_iter([("Primary".to_string(), "poster".to_string())]), + backdrop_image_tags: vec!["backdrop".to_string()], media_type: if node.media.is_some() { "Video".to_owned() } else { diff --git a/server/src/routes/compat/jellyfin/models.rs b/server/src/routes/compat/jellyfin/models.rs index eeffa34..be41835 100644 --- a/server/src/routes/compat/jellyfin/models.rs +++ b/server/src/routes/compat/jellyfin/models.rs @@ -163,7 +163,7 @@ pub(super) struct JellyfinItem { pub primary_image_aspect_ratio: f64, pub collection_type: String, pub image_tags: BTreeMap<String, String>, - pub backdrop_image_tags: Vec<()>, + pub backdrop_image_tags: Vec<String>, pub location_type: Option<String>, pub media_type: String, pub video_type: Option<String>, diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs index 98ea4b0..a0c2de4 100644 --- a/server/src/routes/mod.rs +++ b/server/src/routes/mod.rs @@ -12,16 +12,16 @@ use compat::{ r_jellyfin_artists, r_jellyfin_branding_configuration, r_jellyfin_branding_css, r_jellyfin_displaypreferences_usersettings, r_jellyfin_displaypreferences_usersettings_post, r_jellyfin_items, - r_jellyfin_items_image_primary, r_jellyfin_items_intros, r_jellyfin_items_item, - r_jellyfin_items_playbackinfo, r_jellyfin_items_similar, + r_jellyfin_items_image_primary, r_jellyfin_items_images_backdrop, r_jellyfin_items_intros, + r_jellyfin_items_item, r_jellyfin_items_playbackinfo, r_jellyfin_items_similar, r_jellyfin_livetv_programs_recommended, r_jellyfin_persons, r_jellyfin_playback_bitratetest, r_jellyfin_quickconnect_enabled, r_jellyfin_sessions_capabilities_full, r_jellyfin_sessions_playing, - r_jellyfin_sessions_playing_progress, r_jellyfin_socket, r_jellyfin_system_endpoint, - r_jellyfin_system_info, r_jellyfin_system_info_public, r_jellyfin_system_info_public_case, - r_jellyfin_users_authenticatebyname, r_jellyfin_users_id, r_jellyfin_users_items, - r_jellyfin_users_items_item, r_jellyfin_users_public, r_jellyfin_users_views, - r_jellyfin_video_stream, + r_jellyfin_sessions_playing_progress, r_jellyfin_shows_nextup, r_jellyfin_socket, + r_jellyfin_system_endpoint, r_jellyfin_system_info, r_jellyfin_system_info_public, + r_jellyfin_system_info_public_case, r_jellyfin_users_authenticatebyname, + r_jellyfin_users_id, r_jellyfin_users_items, r_jellyfin_users_items_item, + r_jellyfin_users_public, r_jellyfin_users_views, r_jellyfin_video_stream, }, youtube::{r_youtube_channel, r_youtube_watch}, }; @@ -170,6 +170,7 @@ pub fn build_rocket(database: Database, federation: Federation) -> Rocket<Build> r_jellyfin_displaypreferences_usersettings_post, r_jellyfin_displaypreferences_usersettings, r_jellyfin_items_image_primary, + r_jellyfin_items_images_backdrop, r_jellyfin_items_intros, r_jellyfin_items_item, r_jellyfin_items_playbackinfo, @@ -182,6 +183,7 @@ pub fn build_rocket(database: Database, federation: Federation) -> Rocket<Build> r_jellyfin_sessions_capabilities_full, r_jellyfin_sessions_playing_progress, r_jellyfin_sessions_playing, + r_jellyfin_shows_nextup, r_jellyfin_socket, r_jellyfin_system_endpoint, r_jellyfin_system_info_public_case, diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs index 7c89462..337d249 100644 --- a/server/src/routes/ui/node.rs +++ b/server/src/routes/ui/node.rs @@ -76,7 +76,6 @@ pub async fn r_library_node_filter<'a>( NodeKind::Channel => (SortProperty::ReleaseDate, SortOrder::Descending), _ => (SortProperty::Title, SortOrder::Ascending), }, - // TODO &mut children, ); diff --git a/server/src/routes/ui/sort.rs b/server/src/routes/ui/sort.rs index 3831431..06e0209 100644 --- a/server/src/routes/ui/sort.rs +++ b/server/src/routes/ui/sort.rs @@ -12,9 +12,9 @@ use std::sync::Arc; #[derive(FromForm, UriDisplayQuery, Default, Clone)] pub struct NodeFilterSort { - sort_by: Option<SortProperty>, - filter_kind: Option<Vec<FilterProperty>>, - sort_order: Option<SortOrder>, + pub sort_by: Option<SortProperty>, + pub filter_kind: Option<Vec<FilterProperty>>, + pub sort_order: Option<SortOrder>, } macro_rules! form_enum { |