/* 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) 2025 metamuffin */ use crate::{DATABASE, session::Session}; use anyhow::{Result, anyhow}; use jellycommon::{Asset, LocalTrack, NodeID, PeopleGroup, SourceTrackKind, TrackSource}; use jellyimport_asset_token::AssetInner; pub fn get_node_backdrop(_session: &Session, id: NodeID) -> Result { // TODO perm let node = DATABASE .get_node(id)? .ok_or(anyhow!("node does not exist"))?; let mut asset = node.backdrop.clone(); if asset.is_none() { if let Some(parent) = node.parents.last().copied() { let parent = DATABASE .get_node(parent)? .ok_or(anyhow!("node does not exist"))?; asset = parent.backdrop.clone(); } }; Ok(asset.unwrap_or_else(|| { AssetInner::Assets(format!("fallback-{:?}.avif", node.kind).into()).ser() })) } pub fn get_node_poster(_session: &Session, id: NodeID) -> Result { // TODO perm let node = DATABASE .get_node(id)? .ok_or(anyhow!("node does not exist"))?; let mut asset = node.poster.clone(); if asset.is_none() { if let Some(parent) = node.parents.last().copied() { let parent = DATABASE .get_node(parent)? .ok_or(anyhow!("node does not exist"))?; asset = parent.poster.clone(); } }; Ok(asset.unwrap_or_else(|| { AssetInner::Assets(format!("fallback-{:?}.avif", node.kind).into()).ser() })) } pub fn get_node_person_asset( _session: &Session, id: NodeID, group: PeopleGroup, index: usize, ) -> Result { // TODO perm let node = DATABASE .get_node(id)? .ok_or(anyhow!("node does not exist"))?; let app = node .people .get(&group) .ok_or(anyhow!("group has no members"))? .get(index) .ok_or(anyhow!("person does not exist"))?; let asset = app .person .headshot .to_owned() .unwrap_or(AssetInner::Assets("fallback-Person.avif".into()).ser()); Ok(asset) } pub async fn get_node_thumbnail(_session: &Session, id: NodeID, t: f64) -> Result { let node = DATABASE .get_node(id)? .ok_or(anyhow!("node does not exist"))?; let media = node.media.as_ref().ok_or(anyhow!("no media"))?; let (thumb_track_index, _thumb_track) = media .tracks .iter() .enumerate() .find(|(_i, t)| matches!(t.kind, SourceTrackKind::Video { .. })) .ok_or(anyhow!("no video track to create a thumbnail of"))?; let source = media .tracks .get(thumb_track_index) .ok_or(anyhow!("no source"))?; let thumb_track_source = source.source.clone(); if t < 0. || t > media.duration { Err(anyhow!("thumbnail instant not within media duration"))? } let step = 8.; let t = (t / step).floor() * step; let asset = match thumb_track_source { TrackSource::Local(a) => { let AssetInner::LocalTrack(LocalTrack { path, .. }) = AssetInner::deser(&a.0)? else { return Err(anyhow!("track set to wrong asset type").into()); }; // the track selected might be different from thumb_track jellytranscoder::thumbnail::create_thumbnail(&path, t).await? } TrackSource::Remote(_) => { // // TODO in the new system this is preferrably a property of node ext for regular fed // let session = fed // .get_session( // thumb_track // .federated // .last() // .ok_or(anyhow!("federation broken"))?, // ) // .await?; // async_cache_file("fed-thumb", (id.0, t as i64), |out| { // session.node_thumbnail(out, id.0.into(), 2048, t) // }) // .await? todo!() } }; Ok(AssetInner::Cache(asset).ser()) }