aboutsummaryrefslogtreecommitdiff
path: root/import
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-01-24 04:31:48 +0100
committermetamuffin <metamuffin@disroot.org>2026-01-24 04:31:48 +0100
commitb2e88a8beabf04adc28947cf82996e8692a68b71 (patch)
tree23d66c8672b69cce7835ffabae4092669062ada8 /import
parent774f64c0789529884dd7a5232f190e347ad29532 (diff)
downloadjellything-b2e88a8beabf04adc28947cf82996e8692a68b71.tar
jellything-b2e88a8beabf04adc28947cf82996e8692a68b71.tar.bz2
jellything-b2e88a8beabf04adc28947cf82996e8692a68b71.tar.zst
move things around; kv crate
Diffstat (limited to 'import')
-rw-r--r--import/src/lib.rs100
-rw-r--r--import/src/plugins/acoustid.rs4
-rw-r--r--import/src/plugins/infojson.rs6
-rw-r--r--import/src/plugins/media_info.rs4
-rw-r--r--import/src/plugins/misc.rs12
-rw-r--r--import/src/plugins/mod.rs14
-rw-r--r--import/src/plugins/tags.rs4
-rw-r--r--import/src/plugins/tmdb.rs8
-rw-r--r--import/src/plugins/trakt.rs10
9 files changed, 82 insertions, 80 deletions
diff --git a/import/src/lib.rs b/import/src/lib.rs
index 56da625..7d48867 100644
--- a/import/src/lib.rs
+++ b/import/src/lib.rs
@@ -9,17 +9,17 @@ pub mod plugins;
pub mod reporting;
use crate::{
- plugins::{ImportContext, ImportPlugin, infojson::is_info_json, init_plugins, misc::is_cover},
+ plugins::{PluginContext, ImportPlugin, infojson::is_info_json, init_plugins, misc::is_cover},
reporting::IMPORT_PROGRESS,
};
use anyhow::{Context, Result, anyhow};
-use jellycache::{HashKey, cache_memory, cache_store};
+use jellycache::{Cache, HashKey};
use jellycommon::{
jellyobject::{self, ObjectBuffer, Path as TagPath, fields},
*,
};
use jellydb::{
- backends::Database,
+ kv::Database,
query::{Filter, Query, Sort},
table::{RowNum, Table},
};
@@ -84,7 +84,8 @@ pub fn is_importing() -> bool {
}
#[derive(Clone)]
-pub struct DatabaseTables {
+pub struct ImportConfig {
+ pub cache: Arc<Cache>,
pub db: Arc<dyn Database>,
pub nodes: Arc<Table>,
pub import_meta: Arc<Table>,
@@ -102,7 +103,7 @@ fn node_slug_query(slug: &str) -> Query {
}
}
-impl DatabaseTables {
+impl ImportConfig {
pub fn update_node(
&self,
node: RowNum,
@@ -148,7 +149,7 @@ impl DatabaseTables {
}
}
-pub async fn import_wrap(db: DatabaseTables, incremental: bool) -> Result<()> {
+pub async fn import_wrap(db: ImportConfig, incremental: bool) -> Result<()> {
let _sem = IMPORT_SEM.try_acquire().context("already importing")?;
let rt = Handle::current();
@@ -170,7 +171,7 @@ pub async fn import_wrap(db: DatabaseTables, incremental: bool) -> Result<()> {
Ok(())
}
-fn import(dba: DatabaseTables, rt: &Handle, incremental: bool) -> Result<()> {
+fn import(dba: ImportConfig, rt: &Handle, incremental: bool) -> Result<()> {
let plugins = init_plugins(&CONF.api);
let files = Mutex::new(Vec::new());
import_traverse(
@@ -230,7 +231,7 @@ pub struct InheritedFlags {
fn import_traverse(
path: &Path,
- dba: &DatabaseTables,
+ dba: &ImportConfig,
incremental: bool,
parent: Option<RowNum>,
mut iflags: InheritedFlags,
@@ -297,7 +298,7 @@ fn import_traverse(
}
fn import_file(
- dba: &DatabaseTables,
+ dba: &ImportConfig,
rt: &Handle,
pending_nodes: &Mutex<HashSet<RowNum>>,
plugins: &[Box<dyn ImportPlugin>],
@@ -306,7 +307,7 @@ fn import_file(
iflags: InheritedFlags,
) {
let mut all_ok = true;
- let ct = ImportContext {
+ let ct = PluginContext {
dba,
rt,
iflags,
@@ -412,7 +413,7 @@ fn import_file(
}
fn process_node(
- dba: &DatabaseTables,
+ dba: &ImportConfig,
rt: &Handle,
plugins: &[Box<dyn ImportPlugin>],
pending_nodes: &Mutex<HashSet<RowNum>>,
@@ -433,7 +434,7 @@ fn process_node(
reporting::catch(
p.process(
- &ImportContext {
+ &PluginContext {
dba,
rt,
iflags: InheritedFlags::default(),
@@ -447,7 +448,7 @@ fn process_node(
}
}
-fn compare_mtime(dba: &DatabaseTables, path: &Path) -> Result<bool> {
+fn compare_mtime(dba: &ImportConfig, path: &Path) -> Result<bool> {
let meta = path.metadata()?;
let mtime = meta.modified()?.duration_since(UNIX_EPOCH)?.as_secs();
let mut was_changed = false;
@@ -474,7 +475,7 @@ fn compare_mtime(dba: &DatabaseTables, path: &Path) -> Result<bool> {
Ok(was_changed)
}
-fn update_mtime(dba: &DatabaseTables, path: &Path) -> Result<()> {
+fn update_mtime(dba: &ImportConfig, path: &Path) -> Result<()> {
let meta = path.metadata()?;
let mtime = meta.modified()?.duration_since(UNIX_EPOCH)?.as_secs();
dba.db.write_transaction(&mut |txn| {
@@ -522,46 +523,47 @@ fn get_node_slug(path: &Path) -> Option<String> {
}
}
-pub fn read_media_metadata(path: &Path) -> Result<Arc<matroska::Segment>> {
- cache_memory(
- &format!("media/metadata/{}.json", HashKey(path)),
- move || {
- let media = File::open(path)?;
- let mut media = create_demuxer_autodetect(Box::new(media))?
- .ok_or(anyhow!("media format unknown"))?;
+pub fn read_media_metadata(cache: &Cache, path: &Path) -> Result<Arc<matroska::Segment>> {
+ cache
+ .cache_memory(
+ &format!("media/metadata/{}.json", HashKey(path)),
+ move || {
+ let media = File::open(path)?;
+ let mut media = create_demuxer_autodetect(Box::new(media))?
+ .ok_or(anyhow!("media format unknown"))?;
- let info = media.info()?;
- let tracks = media.tracks()?;
- let tags = media.tags()?;
- let mut attachments = media.attachments()?;
- let chapters = media.chapters()?;
+ let info = media.info()?;
+ let tracks = media.tracks()?;
+ let tags = media.tags()?;
+ let mut attachments = media.attachments()?;
+ let chapters = media.chapters()?;
- // Replace data of useful attachments with cache key; delete data of all others
- if let Some(attachments) = &mut attachments {
- for att in &mut attachments.files {
- if let Some(fname) = is_useful_attachment(&att) {
- let key = cache_store(
- format!("media/attachment/{}-{fname}", HashKey(path)),
- || Ok(att.data.clone()),
- )?;
- att.data = key.as_bytes().to_vec();
- } else {
- att.data.clear();
+ // Replace data of useful attachments with cache key; delete data of all others
+ if let Some(attachments) = &mut attachments {
+ for att in &mut attachments.files {
+ if let Some(fname) = is_useful_attachment(&att) {
+ let key = cache.cache_store(
+ format!("media/attachment/{}-{fname}", HashKey(path)),
+ || Ok(att.data.clone()),
+ )?;
+ att.data = key.as_bytes().to_vec();
+ } else {
+ att.data.clear();
+ }
}
}
- }
- Ok(Segment {
- info,
- tracks,
- tags: tags.into_iter().collect(),
- attachments,
- chapters,
- ..Default::default()
- })
- },
- )
- .context("reading media metadata")
+ Ok(Segment {
+ info,
+ tracks,
+ tags: tags.into_iter().collect(),
+ attachments,
+ chapters,
+ ..Default::default()
+ })
+ },
+ )
+ .context("reading media metadata")
}
pub fn is_useful_attachment(a: &AttachedFile) -> Option<&'static str> {
diff --git a/import/src/plugins/acoustid.rs b/import/src/plugins/acoustid.rs
index 9edcb63..9891927 100644
--- a/import/src/plugins/acoustid.rs
+++ b/import/src/plugins/acoustid.rs
@@ -5,7 +5,7 @@
*/
use crate::{
USER_AGENT,
- plugins::{ImportContext, ImportPlugin, PluginInfo},
+ plugins::{PluginContext, ImportPlugin, PluginInfo},
};
use anyhow::{Context, Result};
use jellycache::{HashKey, cache_memory};
@@ -169,7 +169,7 @@ impl ImportPlugin for AcoustID {
..Default::default()
}
}
- fn media(&self, ct: &ImportContext, node: RowNum, path: &Path, _seg: &Segment) -> Result<()> {
+ fn media(&self, ct: &PluginContext, node: RowNum, path: &Path, _seg: &Segment) -> Result<()> {
if !ct.iflags.use_acoustid {
return Ok(());
}
diff --git a/import/src/plugins/infojson.rs b/import/src/plugins/infojson.rs
index 3e6bdb8..d62983d 100644
--- a/import/src/plugins/infojson.rs
+++ b/import/src/plugins/infojson.rs
@@ -3,7 +3,7 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
+use crate::plugins::{PluginContext, ImportPlugin, PluginInfo};
use anyhow::{Context, Result, anyhow};
use chrono::{Utc, format::Parsed};
use jellycache::cache_read;
@@ -171,7 +171,7 @@ impl ImportPlugin for Infojson {
..Default::default()
}
}
- fn file(&self, ct: &ImportContext, parent: RowNum, path: &Path) -> Result<()> {
+ fn file(&self, ct: &PluginContext, parent: RowNum, path: &Path) -> Result<()> {
let filename = path.file_name().unwrap().to_string_lossy();
if filename != "channel.info.json" {
return Ok(());
@@ -208,7 +208,7 @@ impl ImportPlugin for Infojson {
})
}
- fn media(&self, ct: &ImportContext, row: RowNum, _path: &Path, seg: &Segment) -> Result<()> {
+ fn media(&self, ct: &PluginContext, row: RowNum, _path: &Path, seg: &Segment) -> Result<()> {
let infojson = seg
.attachments
.iter()
diff --git a/import/src/plugins/media_info.rs b/import/src/plugins/media_info.rs
index b750070..9b79efa 100644
--- a/import/src/plugins/media_info.rs
+++ b/import/src/plugins/media_info.rs
@@ -4,7 +4,7 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
+use crate::plugins::{PluginContext, ImportPlugin, PluginInfo};
use anyhow::Result;
use jellycommon::{
jellyobject::{Object, ObjectBuffer},
@@ -23,7 +23,7 @@ impl ImportPlugin for MediaInfo {
..Default::default()
}
}
- fn media(&self, ct: &ImportContext, row: RowNum, path: &Path, seg: &Segment) -> Result<()> {
+ fn media(&self, ct: &PluginContext, row: RowNum, path: &Path, seg: &Segment) -> Result<()> {
let size = path.metadata()?.len();
ct.dba.db.write_transaction(&mut |txn| {
let mut node = ct.dba.nodes.get(txn, row)?.unwrap();
diff --git a/import/src/plugins/misc.rs b/import/src/plugins/misc.rs
index ff08d87..babbcec 100644
--- a/import/src/plugins/misc.rs
+++ b/import/src/plugins/misc.rs
@@ -3,7 +3,7 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
+use crate::plugins::{PluginContext, ImportPlugin, PluginInfo};
use anyhow::{Context, Result, bail};
use jellycache::{HashKey, cache_store};
use jellycommon::{jellyobject::inspect::Inspector, *};
@@ -22,7 +22,7 @@ impl ImportPlugin for ImageFiles {
..Default::default()
}
}
- fn file(&self, ct: &ImportContext, row: RowNum, path: &Path) -> Result<()> {
+ fn file(&self, ct: &PluginContext, row: RowNum, path: &Path) -> Result<()> {
let filename = path.file_name().unwrap().to_string_lossy();
let slot = match filename.as_ref() {
"poster.jpeg" | "poster.webp" | "poster.png" => PICT_COVER,
@@ -66,7 +66,7 @@ impl ImportPlugin for ImageAttachments {
..Default::default()
}
}
- fn media(&self, ct: &ImportContext, row: RowNum, _path: &Path, seg: &Segment) -> Result<()> {
+ fn media(&self, ct: &PluginContext, row: RowNum, _path: &Path, seg: &Segment) -> Result<()> {
let Some(cover) = seg
.attachments
.iter()
@@ -94,7 +94,7 @@ impl ImportPlugin for General {
..Default::default()
}
}
- fn instruction(&self, ct: &ImportContext, node: RowNum, line: &str) -> Result<()> {
+ fn instruction(&self, ct: &PluginContext, node: RowNum, line: &str) -> Result<()> {
if line == "hidden" {
ct.dba.update_node(node, |node| {
node.as_object().insert(NO_VISIBILITY, VISI_HIDDEN)
@@ -144,7 +144,7 @@ impl ImportPlugin for Children {
..Default::default()
}
}
- fn file(&self, ct: &ImportContext, parent: RowNum, path: &Path) -> Result<()> {
+ fn file(&self, ct: &PluginContext, parent: RowNum, path: &Path) -> Result<()> {
// TODO use idents
// let filename = path.file_name().unwrap().to_string_lossy();
// if filename.as_ref() == "children" {
@@ -176,7 +176,7 @@ impl ImportPlugin for EpisodeIndex {
..Default::default()
}
}
- fn media(&self, ct: &ImportContext, node: RowNum, path: &Path, _seg: &Segment) -> Result<()> {
+ fn media(&self, ct: &PluginContext, node: RowNum, path: &Path, _seg: &Segment) -> Result<()> {
let filename = path.file_name().unwrap().to_string_lossy();
if let Some(cap) = RE_EPISODE_FILENAME.captures(&filename) {
if let Some(episode) = cap.name("episode").map(|m| m.as_str()) {
diff --git a/import/src/plugins/mod.rs b/import/src/plugins/mod.rs
index 91be437..d70c6e1 100644
--- a/import/src/plugins/mod.rs
+++ b/import/src/plugins/mod.rs
@@ -15,15 +15,15 @@ pub mod vgmdb;
pub mod wikidata;
pub mod wikimedia_commons;
-use crate::{ApiSecrets, DatabaseTables, InheritedFlags};
+use crate::{ApiSecrets, ImportConfig, InheritedFlags};
use anyhow::Result;
use jellydb::table::RowNum;
use jellyremuxer::matroska::Segment;
use std::{collections::HashSet, path::Path, sync::Mutex};
use tokio::runtime::Handle;
-pub struct ImportContext<'a> {
- pub dba: &'a DatabaseTables,
+pub struct PluginContext<'a> {
+ pub dba: &'a ImportConfig,
pub rt: &'a Handle,
pub iflags: InheritedFlags,
pub pending_nodes: &'a Mutex<HashSet<RowNum>>,
@@ -40,19 +40,19 @@ pub struct PluginInfo {
pub trait ImportPlugin: Send + Sync {
fn info(&self) -> PluginInfo;
- fn file(&self, ct: &ImportContext, parent: RowNum, path: &Path) -> Result<()> {
+ fn file(&self, ct: &PluginContext, parent: RowNum, path: &Path) -> Result<()> {
let _ = (ct, parent, path);
Ok(())
}
- fn media(&self, ct: &ImportContext, node: RowNum, path: &Path, seg: &Segment) -> Result<()> {
+ fn media(&self, ct: &PluginContext, node: RowNum, path: &Path, seg: &Segment) -> Result<()> {
let _ = (ct, node, path, seg);
Ok(())
}
- fn instruction(&self, ct: &ImportContext, node: RowNum, line: &str) -> Result<()> {
+ fn instruction(&self, ct: &PluginContext, node: RowNum, line: &str) -> Result<()> {
let _ = (ct, node, line);
Ok(())
}
- fn process(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ fn process(&self, ct: &PluginContext, node: RowNum) -> Result<()> {
let _ = (ct, node);
Ok(())
}
diff --git a/import/src/plugins/tags.rs b/import/src/plugins/tags.rs
index bfafbe8..e0652d4 100644
--- a/import/src/plugins/tags.rs
+++ b/import/src/plugins/tags.rs
@@ -4,7 +4,7 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::plugins::{ImportContext, ImportPlugin, PluginInfo};
+use crate::plugins::{PluginContext, ImportPlugin, PluginInfo};
use anyhow::Result;
use jellycommon::*;
use jellydb::table::RowNum;
@@ -20,7 +20,7 @@ impl ImportPlugin for Tags {
..Default::default()
}
}
- fn media(&self, ct: &ImportContext, node: RowNum, _path: &Path, seg: &Segment) -> Result<()> {
+ fn media(&self, ct: &PluginContext, node: RowNum, _path: &Path, seg: &Segment) -> Result<()> {
let tags = seg
.tags
.first()
diff --git a/import/src/plugins/tmdb.rs b/import/src/plugins/tmdb.rs
index 6b70d46..cf50938 100644
--- a/import/src/plugins/tmdb.rs
+++ b/import/src/plugins/tmdb.rs
@@ -5,7 +5,7 @@
*/
use crate::{
USER_AGENT,
- plugins::{ImportContext, ImportPlugin, PluginInfo},
+ plugins::{PluginContext, ImportPlugin, PluginInfo},
};
use anyhow::{Context, Result, anyhow, bail};
use chrono::{Utc, format::Parsed};
@@ -162,14 +162,14 @@ impl ImportPlugin for Tmdb {
..Default::default()
}
}
- fn process(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ fn process(&self, ct: &PluginContext, node: RowNum) -> Result<()> {
self.process_primary(ct, node)?;
self.process_episode(ct, node)?;
Ok(())
}
}
impl Tmdb {
- fn process_primary(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ fn process_primary(&self, ct: &PluginContext, node: RowNum) -> Result<()> {
let data = ct.dba.get_node(node)?.unwrap();
let data = data.as_object();
@@ -238,7 +238,7 @@ impl Tmdb {
})?;
Ok(())
}
- fn process_episode(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ fn process_episode(&self, ct: &PluginContext, node: RowNum) -> Result<()> {
let data = ct.dba.get_node(node)?.unwrap();
let data = data.as_object();
diff --git a/import/src/plugins/trakt.rs b/import/src/plugins/trakt.rs
index 7530449..3569454 100644
--- a/import/src/plugins/trakt.rs
+++ b/import/src/plugins/trakt.rs
@@ -5,7 +5,7 @@
*/
use crate::{
USER_AGENT,
- plugins::{ImportContext, ImportPlugin, PluginInfo},
+ plugins::{PluginContext, ImportPlugin, PluginInfo},
};
use anyhow::{Context, Result, anyhow, bail};
use jellycache::{HashKey, cache_memory};
@@ -380,7 +380,7 @@ impl ImportPlugin for Trakt {
..Default::default()
}
}
- fn instruction(&self, ct: &ImportContext, node: RowNum, line: &str) -> Result<()> {
+ fn instruction(&self, ct: &PluginContext, node: RowNum, line: &str) -> Result<()> {
use jellycommon::*;
if let Some(value) = line.strip_prefix("trakt-").or(line.strip_prefix("trakt=")) {
let (ty, id) = value.split_once(":").unwrap_or(("movie", value));
@@ -398,7 +398,7 @@ impl ImportPlugin for Trakt {
}
Ok(())
}
- fn process(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ fn process(&self, ct: &PluginContext, node: RowNum) -> Result<()> {
self.process_primary(ct, node)?;
self.process_episode(ct, node)?;
Ok(())
@@ -406,7 +406,7 @@ impl ImportPlugin for Trakt {
}
impl Trakt {
- fn process_primary(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ fn process_primary(&self, ct: &PluginContext, node: RowNum) -> Result<()> {
let data = ct.dba.get_node(node)?.unwrap();
let data = data.as_object();
let (trakt_kind, trakt_id): (_, u64) = if let Some(id) = data
@@ -492,7 +492,7 @@ impl Trakt {
})?;
Ok(())
}
- fn process_episode(&self, ct: &ImportContext, node: RowNum) -> Result<()> {
+ fn process_episode(&self, ct: &PluginContext, node: RowNum) -> Result<()> {
let node_data = ct.dba.get_node(node)?.unwrap();
let node_data = node_data.as_object();