aboutsummaryrefslogtreecommitdiff
path: root/import/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'import/src/plugins')
-rw-r--r--import/src/plugins/acoustid.rs9
-rw-r--r--import/src/plugins/infojson.rs10
-rw-r--r--import/src/plugins/media_info.rs9
-rw-r--r--import/src/plugins/misc.rs60
-rw-r--r--import/src/plugins/mod.rs53
-rw-r--r--import/src/plugins/musicbrainz.rs14
-rw-r--r--import/src/plugins/tags.rs9
-rw-r--r--import/src/plugins/tmdb.rs22
-rw-r--r--import/src/plugins/trakt.rs11
-rw-r--r--import/src/plugins/vgmdb.rs20
-rw-r--r--import/src/plugins/wikidata.rs14
-rw-r--r--import/src/plugins/wikimedia_commons.rs18
12 files changed, 218 insertions, 31 deletions
diff --git a/import/src/plugins/acoustid.rs b/import/src/plugins/acoustid.rs
index 154b0a2..bf07f90 100644
--- a/import/src/plugins/acoustid.rs
+++ b/import/src/plugins/acoustid.rs
@@ -5,7 +5,7 @@
*/
use crate::{
USER_AGENT,
- plugins::{ImportContext, ImportPlugin},
+ plugins::{ImportContext, ImportPlugin, PluginInfo},
};
use anyhow::{Context, Result};
use jellycache::{HashKey, cache_memory};
@@ -159,6 +159,13 @@ pub(crate) fn acoustid_fingerprint(path: &Path) -> Result<Arc<Fingerprint>> {
}
impl ImportPlugin for AcoustID {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "acoustid",
+ handle_media: true,
+ ..Default::default()
+ }
+ }
fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, _seg: &Segment) -> Result<()> {
let fp = acoustid_fingerprint(path)?;
if let Some((atid, mbid)) = self.get_atid_mbid(&fp, &ct.rt)? {
diff --git a/import/src/plugins/infojson.rs b/import/src/plugins/infojson.rs
index 4dceeb8..5c3645c 100644
--- a/import/src/plugins/infojson.rs
+++ b/import/src/plugins/infojson.rs
@@ -14,7 +14,7 @@ use log::info;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fs::File, io::BufReader, path::Path};
-use crate::plugins::{ImportContext, ImportPlugin};
+use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YVideo {
@@ -160,6 +160,14 @@ pub fn is_info_json(a: &&AttachedFile) -> bool {
}
pub struct Infojson;
impl ImportPlugin for Infojson {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "infojson",
+ handle_file: true,
+ handle_media: true,
+ ..Default::default()
+ }
+ }
fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> {
let filename = path.file_name().unwrap().to_string_lossy();
if filename != "channel.info.json" {
diff --git a/import/src/plugins/media_info.rs b/import/src/plugins/media_info.rs
index 1d4d627..43d76e8 100644
--- a/import/src/plugins/media_info.rs
+++ b/import/src/plugins/media_info.rs
@@ -4,7 +4,7 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::plugins::{ImportContext, ImportPlugin};
+use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
use anyhow::{Result, anyhow};
use jellycommon::{Chapter, NodeID, SourceTrack, SourceTrackKind, TrackSource};
use jellyremuxer::matroska::Segment;
@@ -12,6 +12,13 @@ use std::path::Path;
pub struct MediaInfo;
impl ImportPlugin for MediaInfo {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "media-info",
+ handle_media: true,
+ ..Default::default()
+ }
+ }
fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, seg: &Segment) -> Result<()> {
let tracks = seg
.tracks
diff --git a/import/src/plugins/misc.rs b/import/src/plugins/misc.rs
index 4717753..6f2c18e 100644
--- a/import/src/plugins/misc.rs
+++ b/import/src/plugins/misc.rs
@@ -3,16 +3,27 @@
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 crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
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};
+use std::{
+ fs::{File, read_to_string},
+ io::Read,
+ path::Path,
+};
pub struct ImageFiles;
impl ImportPlugin for ImageFiles {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "image-files",
+ handle_file: true,
+ ..Default::default()
+ }
+ }
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() {
@@ -42,6 +53,13 @@ pub fn is_cover(a: &&AttachedFile) -> bool {
}
pub struct ImageAttachments;
impl ImportPlugin for ImageAttachments {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "image-attachments",
+ handle_media: true,
+ ..Default::default()
+ }
+ }
fn media(&self, ct: &ImportContext, node: NodeID, _path: &Path, seg: &Segment) -> Result<()> {
let Some(cover) = seg
.attachments
@@ -63,7 +81,14 @@ impl ImportPlugin for ImageAttachments {
pub struct General;
impl ImportPlugin for General {
- fn import_instruction(&self, ct: &ImportContext, node: NodeID, line: &str) -> Result<()> {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "general",
+ handle_instruction: true,
+ ..Default::default()
+ }
+ }
+ fn 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);
@@ -98,3 +123,32 @@ impl ImportPlugin for General {
Ok(())
}
}
+
+pub struct Children;
+impl ImportPlugin for Children {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "children",
+ handle_file: true,
+ ..Default::default()
+ }
+ }
+ fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> {
+ let filename = path.file_name().unwrap().to_string_lossy();
+ if filename.as_ref() == "children" {
+ info!("import children at {path:?}");
+ for line in read_to_string(path)?.lines() {
+ let line = line.trim();
+ if line.starts_with("#") || line.is_empty() {
+ continue;
+ }
+ ct.db.update_node_init(NodeID::from_slug(line), |n| {
+ n.slug = line.to_owned();
+ n.parents.insert(parent);
+ Ok(())
+ })?;
+ }
+ }
+ Ok(())
+ }
+}
diff --git a/import/src/plugins/mod.rs b/import/src/plugins/mod.rs
index 47fcfbf..a5cc3dc 100644
--- a/import/src/plugins/mod.rs
+++ b/import/src/plugins/mod.rs
@@ -5,6 +5,8 @@
*/
pub mod acoustid;
pub mod infojson;
+pub mod media_info;
+pub mod misc;
pub mod musicbrainz;
pub mod tags;
pub mod tmdb;
@@ -12,23 +14,32 @@ pub mod trakt;
pub mod vgmdb;
pub mod wikidata;
pub mod wikimedia_commons;
-pub mod media_info;
-pub mod misc;
-
-use std::path::Path;
use anyhow::Result;
use jellycommon::NodeID;
use jellydb::Database;
use jellyremuxer::matroska::Segment;
+use std::path::Path;
use tokio::runtime::Handle;
+use crate::ApiSecrets;
+
pub struct ImportContext {
pub db: Database,
pub rt: Handle,
}
-pub trait ImportPlugin {
+#[derive(Default, Clone, Copy)]
+pub struct PluginInfo {
+ name: &'static str,
+ handle_file: bool,
+ handle_media: bool,
+ handle_instruction: bool,
+ handle_process: bool,
+}
+
+pub trait ImportPlugin: Send + Sync {
+ fn info(&self) -> PluginInfo;
fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> {
let _ = (ct, parent, path);
Ok(())
@@ -37,12 +48,40 @@ pub trait ImportPlugin {
let _ = (ct, node, path, seg);
Ok(())
}
- fn import_instruction(&self, ct: &ImportContext, node: NodeID, line: &str) -> Result<()> {
+ fn instruction(&self, ct: &ImportContext, node: NodeID, line: &str) -> Result<()> {
let _ = (ct, node, line);
Ok(())
}
- fn process_node(&self, ct: &ImportContext, node: NodeID) -> Result<()> {
+ fn process(&self, ct: &ImportContext, node: NodeID) -> Result<()> {
let _ = (ct, node);
Ok(())
}
}
+
+pub fn init_plugins(secrets: &ApiSecrets) -> Vec<Box<dyn ImportPlugin>> {
+ let mut plugins = Vec::<Box<dyn ImportPlugin>>::new();
+
+ plugins.push(Box::new(misc::General));
+ plugins.push(Box::new(misc::Children));
+ plugins.push(Box::new(misc::ImageAttachments));
+ plugins.push(Box::new(misc::ImageFiles));
+ plugins.push(Box::new(tags::Tags));
+ plugins.push(Box::new(media_info::MediaInfo));
+
+ if let Some(s) = &secrets.trakt {
+ plugins.push(Box::new(trakt::Trakt::new(&s)));
+ }
+ if let Some(s) = &secrets.tmdb {
+ plugins.push(Box::new(tmdb::Tmdb::new(&s))); // deps: trakt
+ }
+
+ if let Some(s) = &secrets.acoustid {
+ plugins.push(Box::new(acoustid::AcoustID::new(&s)));
+ }
+ plugins.push(Box::new(musicbrainz::MusicBrainz::new())); // deps: acoustid
+ plugins.push(Box::new(wikidata::Wikidata::new())); // deps: musicbrainz
+ plugins.push(Box::new(wikimedia_commons::WikimediaCommons::new())); // deps: wikidata
+ plugins.push(Box::new(vgmdb::Vgmdb::new())); // deps: wikidata
+
+ plugins
+}
diff --git a/import/src/plugins/musicbrainz.rs b/import/src/plugins/musicbrainz.rs
index 44b2a06..305b03f 100644
--- a/import/src/plugins/musicbrainz.rs
+++ b/import/src/plugins/musicbrainz.rs
@@ -4,7 +4,10 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::{USER_AGENT, plugins::ImportPlugin};
+use crate::{
+ USER_AGENT,
+ plugins::{ImportPlugin, PluginInfo},
+};
use anyhow::{Context, Result};
use jellycache::cache_memory;
use log::info;
@@ -317,4 +320,11 @@ impl MusicBrainz {
}
}
-impl ImportPlugin for MusicBrainz {}
+impl ImportPlugin for MusicBrainz {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "musicbrainz",
+ ..Default::default()
+ }
+ }
+}
diff --git a/import/src/plugins/tags.rs b/import/src/plugins/tags.rs
index 8452aad..7e30504 100644
--- a/import/src/plugins/tags.rs
+++ b/import/src/plugins/tags.rs
@@ -4,7 +4,7 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::plugins::{ImportContext, ImportPlugin};
+use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
use anyhow::Result;
use jellycommon::{IdentifierType, NodeID, NodeKind};
use jellyremuxer::matroska::Segment;
@@ -12,6 +12,13 @@ use std::{collections::HashMap, path::Path};
pub struct Tags;
impl ImportPlugin for Tags {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "tags",
+ handle_media: true,
+ ..Default::default()
+ }
+ }
fn media(&self, ct: &ImportContext, node: NodeID, _path: &Path, seg: &Segment) -> Result<()> {
let tags = seg
.tags
diff --git a/import/src/plugins/tmdb.rs b/import/src/plugins/tmdb.rs
index 3d6e832..5980d53 100644
--- a/import/src/plugins/tmdb.rs
+++ b/import/src/plugins/tmdb.rs
@@ -3,17 +3,20 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::USER_AGENT;
-use anyhow::{anyhow, bail, Context, Result};
-use jellycache::{cache_memory, cache_store, EscapeKey, HashKey};
+use crate::{
+ USER_AGENT,
+ plugins::{ImportPlugin, PluginInfo},
+};
+use anyhow::{Context, Result, anyhow, bail};
+use jellycache::{EscapeKey, HashKey, cache_memory, cache_store};
use jellycommon::{
- chrono::{format::Parsed, Utc},
Asset,
+ chrono::{Utc, format::Parsed},
};
use log::info;
use reqwest::{
- header::{HeaderMap, HeaderName, HeaderValue},
Client, ClientBuilder,
+ header::{HeaderMap, HeaderName, HeaderValue},
};
use serde::{Deserialize, Serialize};
use std::{fmt::Display, sync::Arc};
@@ -153,6 +156,15 @@ impl Tmdb {
}
}
+impl ImportPlugin for Tmdb {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "tmdb",
+ ..Default::default()
+ }
+ }
+}
+
pub fn parse_release_date(d: &str) -> Result<Option<i64>> {
if d.is_empty() {
return Ok(None);
diff --git a/import/src/plugins/trakt.rs b/import/src/plugins/trakt.rs
index 5a1aa8e..6d5b007 100644
--- a/import/src/plugins/trakt.rs
+++ b/import/src/plugins/trakt.rs
@@ -5,7 +5,7 @@
*/
use crate::{
USER_AGENT,
- plugins::{ImportContext, ImportPlugin},
+ plugins::{ImportContext, ImportPlugin, PluginInfo},
};
use anyhow::{Context, Result, bail};
use jellycache::{HashKey, cache_memory};
@@ -383,7 +383,14 @@ impl Display for TraktKind {
}
impl ImportPlugin for Trakt {
- fn import_instruction(&self, ct: &ImportContext, node: NodeID, line: &str) -> Result<()> {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "takt",
+ handle_instruction: true,
+ ..Default::default()
+ }
+ }
+ fn instruction(&self, ct: &ImportContext, node: NodeID, line: &str) -> Result<()> {
if let Some(value) = line.strip_prefix("trakt-").or(line.strip_prefix("trakt=")) {
let (ty, id) = value.split_once(":").unwrap_or(("movie", value));
let ty = match ty {
diff --git a/import/src/plugins/vgmdb.rs b/import/src/plugins/vgmdb.rs
index 402fd90..a3928bd 100644
--- a/import/src/plugins/vgmdb.rs
+++ b/import/src/plugins/vgmdb.rs
@@ -4,15 +4,18 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::USER_AGENT;
+use crate::{
+ USER_AGENT,
+ plugins::{ImportPlugin, PluginInfo},
+};
use anyhow::{Context, Result};
-use jellycache::{cache, cache_store, HashKey};
+use jellycache::{HashKey, cache, cache_store};
use jellycommon::Asset;
use log::info;
use regex::Regex;
use reqwest::{
- header::{HeaderMap, HeaderName, HeaderValue},
Client, ClientBuilder,
+ header::{HeaderMap, HeaderName, HeaderValue},
};
use std::{
sync::{Arc, LazyLock},
@@ -21,7 +24,7 @@ use std::{
use tokio::{
runtime::Handle,
sync::Semaphore,
- time::{sleep_until, Instant},
+ time::{Instant, sleep_until},
};
pub struct Vgmdb {
@@ -125,3 +128,12 @@ impl Vgmdb {
.context("vgmdb artist page scrape")
}
}
+
+impl ImportPlugin for Vgmdb {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "vgmdb",
+ ..Default::default()
+ }
+ }
+}
diff --git a/import/src/plugins/wikidata.rs b/import/src/plugins/wikidata.rs
index 358996e..095e4bd 100644
--- a/import/src/plugins/wikidata.rs
+++ b/import/src/plugins/wikidata.rs
@@ -4,7 +4,10 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::USER_AGENT;
+use crate::{
+ USER_AGENT,
+ plugins::{ImportPlugin, PluginInfo},
+};
use anyhow::{Context, Result, bail};
use jellycache::{EscapeKey, cache_memory};
use log::info;
@@ -127,3 +130,12 @@ impl Wikidata {
.context("wikidata entity")
}
}
+
+impl ImportPlugin for Wikidata {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "wikidata",
+ ..Default::default()
+ }
+ }
+}
diff --git a/import/src/plugins/wikimedia_commons.rs b/import/src/plugins/wikimedia_commons.rs
index 86d934c..3d11d74 100644
--- a/import/src/plugins/wikimedia_commons.rs
+++ b/import/src/plugins/wikimedia_commons.rs
@@ -4,14 +4,17 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::USER_AGENT;
+use crate::{
+ USER_AGENT,
+ plugins::{ImportPlugin, PluginInfo},
+};
use anyhow::{Context, Result};
-use jellycache::{cache_store, EscapeKey};
+use jellycache::{EscapeKey, cache_store};
use jellycommon::Asset;
use reqwest::{
+ Client, ClientBuilder,
header::{HeaderMap, HeaderName, HeaderValue},
redirect::Policy,
- Client, ClientBuilder,
};
use tokio::runtime::Handle;
@@ -61,3 +64,12 @@ impl WikimediaCommons {
.map(Asset)
}
}
+
+impl ImportPlugin for WikimediaCommons {
+ fn info(&self) -> PluginInfo {
+ PluginInfo {
+ name: "wikimedia-commons",
+ ..Default::default()
+ }
+ }
+}