diff options
Diffstat (limited to 'import/src/plugins/misc.rs')
| -rw-r--r-- | import/src/plugins/misc.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/import/src/plugins/misc.rs b/import/src/plugins/misc.rs new file mode 100644 index 0000000..4717753 --- /dev/null +++ b/import/src/plugins/misc.rs @@ -0,0 +1,100 @@ +/* + 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::plugins::{ImportContext, ImportPlugin}; +use anyhow::{Result, bail}; +use jellycache::{HashKey, cache_store}; +use jellycommon::{Asset, NodeID, NodeKind, PictureSlot, Visibility}; +use jellyremuxer::matroska::{AttachedFile, Segment}; +use log::info; +use std::{fs::File, io::Read, path::Path}; + +pub struct ImageFiles; +impl ImportPlugin for ImageFiles { + fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> { + let filename = path.file_name().unwrap().to_string_lossy(); + let slot = match filename.as_ref() { + "poster.jpeg" | "poster.webp" | "poster.png" => PictureSlot::Cover, + "backdrop.jpeg" | "backdrop.webp" | "backdrop.png" => PictureSlot::Backdrop, + _ => return Ok(()), + }; + info!("import {slot:?} at {path:?}"); + let asset = Asset(cache_store( + format!("media/literal/{}-poster.image", HashKey(path)), + || { + let mut data = Vec::new(); + File::open(path)?.read_to_end(&mut data)?; + Ok(data) + }, + )?); + ct.db.update_node_init(parent, |node| { + node.pictures.insert(PictureSlot::Cover, asset); + Ok(()) + })?; + Ok(()) + } +} + +pub fn is_cover(a: &&AttachedFile) -> bool { + a.name.starts_with("cover") && a.media_type.starts_with("image/") +} +pub struct ImageAttachments; +impl ImportPlugin for ImageAttachments { + fn media(&self, ct: &ImportContext, node: NodeID, _path: &Path, seg: &Segment) -> Result<()> { + let Some(cover) = seg + .attachments + .iter() + .flat_map(|a| &a.files) + .find(is_cover) + .map(|att| Asset(att.data.clone().try_into().unwrap())) + else { + return Ok(()); + }; + + ct.db.update_node_init(node, |node| { + node.pictures.insert(PictureSlot::Cover, cover); + Ok(()) + })?; + Ok(()) + } +} + +pub struct General; +impl ImportPlugin for General { + fn import_instruction(&self, ct: &ImportContext, node: NodeID, line: &str) -> Result<()> { + if line == "hidden" { + ct.db.update_node_init(node, |node| { + node.visibility = node.visibility.min(Visibility::Hidden); + Ok(()) + })?; + } + if line == "reduced" { + ct.db.update_node_init(node, |node| { + node.visibility = node.visibility.min(Visibility::Reduced); + Ok(()) + })?; + } + if let Some(kind) = line.strip_prefix("kind-").or(line.strip_prefix("kind=")) { + let kind = match kind { + "movie" => NodeKind::Movie, + "video" => NodeKind::Video, + "music" => NodeKind::Music, + "short_form_video" => NodeKind::ShortFormVideo, + "collection" => NodeKind::Collection, + "channel" => NodeKind::Channel, + "show" => NodeKind::Show, + "series" => NodeKind::Series, + "season" => NodeKind::Season, + "episode" => NodeKind::Episode, + _ => bail!("unknown node kind"), + }; + ct.db.update_node_init(node, |node| { + node.kind = kind; + Ok(()) + })?; + } + Ok(()) + } +} |