diff options
author | metamuffin <metamuffin@disroot.org> | 2025-04-28 18:27:03 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-04-28 18:27:03 +0200 |
commit | 51761cbdefa39107b9e1f931f1aa8df6aebb2a94 (patch) | |
tree | 957ca180786ece777e6e1153ada91da741d845ec /logic/src/node.rs | |
parent | 80d28b764c95891551e28c395783f5ff9d065743 (diff) | |
download | jellything-51761cbdefa39107b9e1f931f1aa8df6aebb2a94.tar jellything-51761cbdefa39107b9e1f931f1aa8df6aebb2a94.tar.bz2 jellything-51761cbdefa39107b9e1f931f1aa8df6aebb2a94.tar.zst |
many much more generic refactor
Diffstat (limited to 'logic/src/node.rs')
-rw-r--r-- | logic/src/node.rs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/logic/src/node.rs b/logic/src/node.rs new file mode 100644 index 0000000..8a53bec --- /dev/null +++ b/logic/src/node.rs @@ -0,0 +1,112 @@ +/* + 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 <metamuffin.org> +*/ +use crate::{filter_sort::filter_and_sort_nodes, session::Session}; +use anyhow::{Result, anyhow}; +use jellybase::database::Database; +use jellycommon::{ + Node, NodeID, NodeKind, Visibility, + api::{ApiNodeResponse, NodeFilterSort, SortOrder, SortProperty}, + user::NodeUserData, +}; +use std::{cmp::Reverse, collections::BTreeMap, sync::Arc}; + +pub fn get_node( + db: &Database, + id: NodeID, + session: &Session, + children: bool, + parents: bool, + filter: NodeFilterSort, +) -> Result<ApiNodeResponse> { + let (node, udata) = db.get_node_with_userdata(id, &session)?; + + let mut children = if children { + db.get_node_children(id)? + .into_iter() + .map(|c| db.get_node_with_userdata(c, &session)) + .collect::<anyhow::Result<Vec<_>>>()? + } else { + Vec::new() + }; + + let mut parents = if parents { + node.parents + .iter() + .map(|pid| db.get_node_with_userdata(*pid, &session)) + .collect::<anyhow::Result<Vec<_>>>()? + } else { + Vec::new() + }; + + let mut similar = get_similar_media(&node, db, &session)?; + + similar.retain(|(n, _)| n.visibility >= Visibility::Reduced); + children.retain(|(n, _)| n.visibility >= Visibility::Reduced); + parents.retain(|(n, _)| n.visibility >= Visibility::Reduced); + + filter_and_sort_nodes( + &filter, + match node.kind { + NodeKind::Channel => (SortProperty::ReleaseDate, SortOrder::Descending), + NodeKind::Season | NodeKind::Show => (SortProperty::Index, SortOrder::Ascending), + _ => (SortProperty::Title, SortOrder::Ascending), + }, + &mut children, + ); + + Ok(ApiNodeResponse { + children, + parents, + node, + userdata: udata, + }) +} + +pub fn get_similar_media( + node: &Node, + db: &Database, + session: &Session, +) -> Result<Vec<(Arc<Node>, NodeUserData)>> { + let this_id = NodeID::from_slug(&node.slug); + let mut ranking = BTreeMap::<NodeID, usize>::new(); + for tag in &node.tags { + let nodes = db.get_tag_nodes(tag)?; + let weight = 1_000_000 / nodes.len(); + for n in nodes { + if n != this_id { + *ranking.entry(n).or_default() += weight; + } + } + } + let mut ranking = ranking.into_iter().collect::<Vec<_>>(); + ranking.sort_by_key(|(_, k)| Reverse(*k)); + ranking + .into_iter() + .take(32) + .map(|(pid, _)| db.get_node_with_userdata(pid, session)) + .collect::<anyhow::Result<Vec<_>>>() +} + +pub trait DatabaseNodeUserDataExt { + fn get_node_with_userdata( + &self, + id: NodeID, + session: &Session, + ) -> Result<(Arc<Node>, NodeUserData)>; +} +impl DatabaseNodeUserDataExt for Database { + fn get_node_with_userdata( + &self, + id: NodeID, + session: &Session, + ) -> Result<(Arc<Node>, NodeUserData)> { + Ok(( + self.get_node(id)?.ok_or(anyhow!("node does not exist"))?, + self.get_node_udata(id, &session.user.name)? + .unwrap_or_default(), + )) + } +} |