aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-01-21 23:38:28 +0100
committermetamuffin <metamuffin@disroot.org>2024-01-21 23:38:28 +0100
commitb127ee51925f59b306b032dbacc11464ed175a60 (patch)
treeb7097c20a560019f90394de9e21da4c498aadabb /server/src/routes
parenta8fe841aaefe904121d936e608572a1422191167 (diff)
downloadjellything-b127ee51925f59b306b032dbacc11464ed175a60.tar
jellything-b127ee51925f59b306b032dbacc11464ed175a60.tar.bz2
jellything-b127ee51925f59b306b032dbacc11464ed175a60.tar.zst
refactor tmdb api, cast&crew, node ext
Diffstat (limited to 'server/src/routes')
-rw-r--r--server/src/routes/mod.rs8
-rw-r--r--server/src/routes/ui/assets.rs36
-rw-r--r--server/src/routes/ui/node.rs52
3 files changed, 80 insertions, 16 deletions
diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs
index a6a086f..d607eef 100644
--- a/server/src/routes/mod.rs
+++ b/server/src/routes/mod.rs
@@ -33,11 +33,11 @@ use ui::{
r_admin_remove_invite,
user::{r_admin_remove_user, r_admin_user, r_admin_user_permission, r_admin_users},
},
- assets::{r_item_assets, r_node_thumbnail},
+ assets::{r_item_assets, r_node_thumbnail, r_person_asset},
browser::r_all_items_filter,
error::{r_api_catch, r_catch},
home::{r_home, r_home_unpriv},
- node::r_library_node_filter,
+ node::{r_library_node_ext, r_library_node_filter},
player::r_player,
style::{r_assets_font, r_assets_js, r_assets_js_map, r_assets_style},
};
@@ -46,8 +46,8 @@ use userdata::{r_node_userdata, r_player_progress, r_player_watched};
use self::playersync::{r_streamsync, PlayersyncChannels};
pub mod api;
-pub mod stream;
pub mod playersync;
+pub mod stream;
pub mod ui;
pub mod userdata;
@@ -98,8 +98,10 @@ pub fn build_rocket(database: DataAcid, federation: Federation) -> Rocket<Build>
r_streamsync,
r_favicon,
r_item_assets,
+ r_person_asset,
r_all_items_filter,
r_library_node_filter,
+ r_library_node_ext,
r_assets_style,
r_assets_font,
r_assets_js,
diff --git a/server/src/routes/ui/assets.rs b/server/src/routes/ui/assets.rs
index 05ddc7c..ebd9453 100644
--- a/server/src/routes/ui/assets.rs
+++ b/server/src/routes/ui/assets.rs
@@ -10,13 +10,13 @@ use crate::{
use anyhow::{anyhow, Context};
use jellybase::{
cache::async_cache_file,
- database::{TableExt, T_NODE},
+ database::{TableExt, T_NODE, T_NODE_EXTENDED},
federation::Federation,
permission::NodePermissionExt,
AssetLocationExt,
};
pub use jellycommon::AssetRole;
-use jellycommon::{AssetLocation, LocalTrack, SourceTrackKind, TrackSource};
+use jellycommon::{AssetLocation, LocalTrack, PeopleGroup, SourceTrackKind, TrackSource};
use log::info;
use rocket::{get, http::ContentType, State};
use std::{path::PathBuf, str::FromStr};
@@ -56,6 +56,38 @@ pub async fn r_item_assets(
Ok(asset_with_res(asset, width).await?)
}
+#[get("/n/<id>/person/<index>/asset?<group>&<width>")]
+pub async fn r_person_asset(
+ session: Session,
+ db: &State<DataAcid>,
+ id: &str,
+ index: usize,
+ group: PeopleGroup,
+ width: Option<usize>,
+) -> MyResult<(ContentType, CacheControlFile)> {
+ T_NODE
+ .get(&db, id)?
+ .only_if_permitted(&session.user.permissions)
+ .ok_or(anyhow!("node does not exist"))?;
+
+ let ext = T_NODE_EXTENDED.get(db, id)?.unwrap_or_default();
+ let app = ext
+ .people
+ .get(&group)
+ .ok_or(anyhow!("group has no members"))?
+ .get(index)
+ .ok_or(anyhow!("person does not exist"))?;
+
+ let asset = app
+ .person
+ .asset
+ .as_ref()
+ .ok_or(anyhow!("no asset"))?
+ .to_owned();
+
+ Ok(asset_with_res(asset, width).await?)
+}
+
// TODO this can create "federation recursion" because track selection cannot be relied on.
#[get("/n/<id>/thumbnail?<t>&<width>")]
pub async fn r_node_thumbnail(
diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs
index 3820b14..fc12db3 100644
--- a/server/src/routes/ui/node.rs
+++ b/server/src/routes/ui/node.rs
@@ -5,7 +5,7 @@
*/
use super::{
assets::{rocket_uri_macro_r_item_assets, rocket_uri_macro_r_node_thumbnail},
- error::MyError,
+ error::MyResult,
sort::{filter_and_sort_nodes, NodeFilterSort, NodeFilterSortForm},
};
use crate::{
@@ -14,7 +14,7 @@ use crate::{
api::AcceptJson,
ui::{
account::session::Session,
- assets::AssetRole,
+ assets::{rocket_uri_macro_r_person_asset, AssetRole},
layout::{DynLayoutPage, LayoutPage},
player::{rocket_uri_macro_r_player, PlayerConfig},
},
@@ -25,12 +25,12 @@ use crate::{
use anyhow::{anyhow, Result};
use chrono::NaiveDateTime;
use jellybase::{
- database::{TableExt, T_NODE, T_USER_NODE},
+ database::{TableExt, T_NODE, T_NODE_EXTENDED, T_USER_NODE},
permission::NodePermissionExt,
};
use jellycommon::{
user::{NodeUserData, WatchedState},
- Chapter, MediaInfo, NodeKind, NodePublic, Rating, SourceTrackKind,
+ Chapter, ExtendedNode, MediaInfo, NodeKind, NodePublic, PeopleGroup, Rating, SourceTrackKind,
};
use rocket::{get, serde::json::Json, Either, State};
@@ -40,6 +40,20 @@ pub fn r_library_node(id: String) {
drop(id)
}
+#[get("/n/<id>/extended")]
+pub async fn r_library_node_ext<'a>(
+ session: Session,
+ id: &'a str,
+ db: &'a State<DataAcid>,
+) -> MyResult<Json<ExtendedNode>> {
+ T_NODE
+ .get(&db, id)?
+ .only_if_permitted(&session.user.permissions)
+ .ok_or(anyhow!("node does not exist"))?;
+
+ Ok(Json(T_NODE_EXTENDED.get(db, id)?.unwrap_or_default()))
+}
+
#[get("/n/<id>?<filter..>")]
pub async fn r_library_node_filter<'a>(
session: Session,
@@ -47,12 +61,13 @@ pub async fn r_library_node_filter<'a>(
db: &'a State<DataAcid>,
aj: AcceptJson,
filter: NodeFilterSort,
-) -> Result<Either<DynLayoutPage<'a>, Json<NodePublic>>, MyError> {
+) -> MyResult<Either<DynLayoutPage<'a>, Json<NodePublic>>> {
let node = T_NODE
.get(&db, id)?
.only_if_permitted(&session.user.permissions)
.ok_or(anyhow!("node does not exist"))?
.public;
+ let node_ext = T_NODE_EXTENDED.get(db, id)?.unwrap_or_default();
let udata = T_USER_NODE
.get(&db, &(session.user.name.as_str(), id))?
@@ -75,7 +90,7 @@ pub async fn r_library_node_filter<'a>(
Ok(Either::Left(LayoutPage {
title: node.title.clone().unwrap_or_default(),
content: markup::new! {
- @NodePage { node: &node, id: &id, udata: &udata, children: &children, filter: &filter }
+ @NodePage { node: &node, id: &id, udata: &udata, children: &children, filter: &filter, node_ext: &node_ext }
},
..Default::default()
}))
@@ -87,7 +102,7 @@ markup::define! {
div[class=cls] {
.poster {
a[href=uri!(r_library_node(id))] {
- img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(1024)))];
+ img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(1024))), loading="lazy"];
}
.cardhover.item {
@if !(matches!(node.kind.unwrap_or_default(), NodeKind::Collection | NodeKind::Channel)) {
@@ -103,13 +118,13 @@ markup::define! {
}
}
}
- NodePage<'a>(id: &'a str, node: &'a NodePublic, udata: &'a NodeUserData, children: &'a Vec<(String, NodePublic, NodeUserData)>, filter: &'a NodeFilterSort) {
+ NodePage<'a>(id: &'a str, node: &'a NodePublic, node_ext: &'a ExtendedNode, udata: &'a NodeUserData, children: &'a Vec<(String, NodePublic, NodeUserData)>, filter: &'a NodeFilterSort) {
@if !matches!(node.kind.unwrap_or_default(), NodeKind::Collection) {
- img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop, Some(2048)))];
+ img.backdrop[src=uri!(r_item_assets(id, AssetRole::Backdrop, Some(2048))), loading="lazy"];
}
.page.node {
@if !matches!(node.kind.unwrap_or_default(), NodeKind::Collection) {
- div.bigposter { img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(2048)))]; }
+ div.bigposter { img[src=uri!(r_item_assets(id, AssetRole::Poster, Some(2048))), loading="lazy"]; }
}
.title {
h1 { @node.title }
@@ -151,7 +166,7 @@ markup::define! {
li { .card."aspect-thumb" {
.poster {
a[href=&uri!(r_player(id, PlayerConfig::seek(chap.time_start.unwrap_or(0.))))] {
- img[src=&uri!(r_node_thumbnail(id, chapter_key_time(chap, media.duration), Some(1024)))];
+ img[src=&uri!(r_node_thumbnail(id, chapter_key_time(chap, media.duration), Some(1024))), loading="lazy"];
}
.cardhover { .props { p { @inl } } }
}
@@ -159,6 +174,21 @@ markup::define! {
}}
}}}
}
+ h2 { "Cast & Crew" }
+ @for (group, people) in &node_ext.people {
+ h3 { @format!("{:?}", group) }
+ .hlist { ul.children { @for (i, pe) in people.iter().enumerate() {
+ li { .card."aspect-port" {
+ .poster {
+ a[href="#"] {
+ img[src=&uri!(r_person_asset(id, i, group, Some(1024))), loading="lazy"];
+ }
+ // .cardhover { .props { p { @pe.person.name } } }
+ }
+ .title { @pe.person.name }
+ }}
+ }}}
+ }
details {
summary { "Tracks" }
ol { @for track in &media.tracks {