aboutsummaryrefslogtreecommitdiff
path: root/import/src/plugins/misc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'import/src/plugins/misc.rs')
-rw-r--r--import/src/plugins/misc.rs100
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(())
+ }
+}