diff options
author | metamuffin <metamuffin@disroot.org> | 2023-08-02 23:07:55 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-08-02 23:07:55 +0200 |
commit | 8e33fcdfbd9df042c0cfd8e9a2084993313961c9 (patch) | |
tree | 9b18183237177b6c2b7060140ed92e62581ab588 /server/src/import.rs | |
parent | c81d8bbfd46d53fba6e0086b5f859f8af8639f4a (diff) | |
download | jellything-8e33fcdfbd9df042c0cfd8e9a2084993313961c9.tar jellything-8e33fcdfbd9df042c0cfd8e9a2084993313961c9.tar.bz2 jellything-8e33fcdfbd9df042c0cfd8e9a2084993313961c9.tar.zst |
federated import works but relies on private data
Diffstat (limited to 'server/src/import.rs')
-rw-r--r-- | server/src/import.rs | 86 |
1 files changed, 64 insertions, 22 deletions
diff --git a/server/src/import.rs b/server/src/import.rs index b306332..a172ad9 100644 --- a/server/src/import.rs +++ b/server/src/import.rs @@ -3,37 +3,42 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin <metamuffin.org> */ -use crate::{database::Database, CONF}; -use anyhow::{bail, Context, Ok}; +use crate::{database::Database, federation::Federation, CONF}; +use anyhow::{anyhow, bail, Context, Ok}; use async_recursion::async_recursion; -use jellycommon::Node; -use log::info; +use jellycommon::{Node, RemoteImportOptions}; +use log::{error, info}; use std::{ffi::OsStr, fs::File, os::unix::prelude::OsStrExt, path::PathBuf, sync::LazyLock}; use tokio::sync::Semaphore; static IMPORT_SEM: LazyLock<Semaphore> = LazyLock::new(|| Semaphore::new(1)); -pub async fn import(db: &Database) -> anyhow::Result<()> { +pub async fn import(db: &Database, fed: &Federation) -> anyhow::Result<()> { info!("clearing node tree"); let permit = IMPORT_SEM.try_acquire()?; - { - db.node.clear()?; - info!("importing..."); - import_path(CONF.library_path.clone(), db, None) - .await - .context("indexing")?; - info!("import completed"); - } + db.node.clear()?; + info!("importing..."); + let (_, errs) = import_path(CONF.library_path.clone(), db, fed, None) + .await + .context("indexing")?; + info!("import completed"); drop(permit); - Ok(()) + if errs == 0 { + Ok(()) + } else { + Err(anyhow!( + "partial import, {errs} errors occured; see server log" + )) + } } #[async_recursion] pub async fn import_path( path: PathBuf, db: &Database, + fed: &Federation, parent: Option<String>, -) -> anyhow::Result<Vec<String>> { +) -> anyhow::Result<(Vec<String>, usize)> { if path.is_dir() { let mpath = path.join("directory.json"); let children_paths = path.read_dir()?.map(Result::unwrap).filter_map(|e| { @@ -47,8 +52,19 @@ pub async fn import_path( }); let identifier = path.file_name().unwrap().to_str().unwrap().to_string(); let mut children_ids = Vec::new(); + let mut errs = 0; for p in children_paths { - children_ids.extend(import_path(p, db, Some(identifier.clone())).await?) + let k = import_path(p, db, fed, Some(identifier.clone())).await; + match k { + core::result::Result::Ok((els, errs2)) => { + errs += errs2; + children_ids.extend(els) + } + Err(e) => { + errs += 1; + error!("import failed: {e:?}") + } + } } if mpath.exists() { let mut data: Node = @@ -56,14 +72,14 @@ pub async fn import_path( data.public.children = children_ids; data.public.parent = parent; - info!("insert {identifier}"); + info!("adding {identifier}"); db.node.insert(&identifier, &data)?; - Ok(vec![identifier]) + Ok((vec![identifier], errs)) } else { - Ok(children_ids) + Ok((children_ids, errs)) } } else if path.is_file() { - info!("loading item {path:?}"); + info!("loading {path:?}"); let datafile = File::open(path.clone()).context("cant load metadata")?; let mut data: Node = serde_json::from_reader(datafile).context("invalid metadata")?; let identifier = path @@ -75,11 +91,37 @@ pub async fn import_path( .unwrap() .to_string(); - info!("insert {identifier}"); + if let Some(io) = data.private.import.take() { + let title = data.public.title; + data = import_remote(io, db, fed) + .await + .context("federated import")?; + data.public.title = title; + } + + info!("adding {identifier}"); data.public.parent = parent; db.node.insert(&identifier, &data)?; - Ok(vec![identifier]) + Ok((vec![identifier], 0)) } else { bail!("did somebody really put a fifo or socket in the library?!") } } + +async fn import_remote( + opts: RemoteImportOptions, + db: &Database, + fed: &Federation, +) -> anyhow::Result<Node> { + let sess = fed + .get_session(&opts.host) + .await + .context("creating session")?; + let node = sess.node(&opts.id).await.context("fetching remote node")?; + + if !node.public.children.is_empty() { + todo!() + } + + Ok(node) +} |