aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-08-03 15:36:34 +0200
committermetamuffin <metamuffin@disroot.org>2023-08-03 15:36:34 +0200
commit9898998344f9897d59b629ce643a0e243f5e7b09 (patch)
tree8571f09510b9e940c0cf86b714e24dce226557ef /server/src
parentc0828abd8a0f02240520f3c36419d3a83086fd2b (diff)
downloadjellything-9898998344f9897d59b629ce643a0e243f5e7b09.tar
jellything-9898998344f9897d59b629ce643a0e243f5e7b09.tar.bz2
jellything-9898998344f9897d59b629ce643a0e243f5e7b09.tar.zst
federated assets and refactored asset paths
Diffstat (limited to 'server/src')
-rw-r--r--server/src/import.rs48
-rw-r--r--server/src/routes/ui/assets.rs23
2 files changed, 65 insertions, 6 deletions
diff --git a/server/src/import.rs b/server/src/import.rs
index 2cd1998..a059694 100644
--- a/server/src/import.rs
+++ b/server/src/import.rs
@@ -6,10 +6,13 @@
use crate::{database::Database, federation::Federation, CONF};
use anyhow::{anyhow, bail, Context, Ok};
use async_recursion::async_recursion;
+use base64::Engine;
use jellyclient::Session;
-use jellycommon::{MediaSource, Node, NodePrivate, RemoteImportOptions};
+use jellycommon::{AssetLocation, MediaSource, Node, NodePrivate, RemoteImportOptions};
use log::{error, info};
-use std::{ffi::OsStr, fs::File, os::unix::prelude::OsStrExt, path::PathBuf, sync::LazyLock};
+use std::{
+ ffi::OsStr, fs::File, os::unix::prelude::OsStrExt, path::PathBuf, str::FromStr, sync::LazyLock,
+};
use tokio::sync::Semaphore;
static IMPORT_SEM: LazyLock<Semaphore> = LazyLock::new(|| Semaphore::new(1));
@@ -125,11 +128,15 @@ async fn import_remote(
.node(&opts.id)
.await
.context("fetching remote node")?;
+
+ let poster = cache_federation_asset(session, &opts.id, "poster").await?;
+ let backdrop = cache_federation_asset(session, &opts.id, "backdrop").await?;
+
let mut node = Node {
public: node,
private: NodePrivate {
- backdrop: None,
- poster: None,
+ backdrop: Some(AssetLocation::Cache(backdrop)),
+ poster: Some(AssetLocation::Cache(poster)),
import: None,
source: Some(MediaSource::Remote {
host: opts.host.clone(),
@@ -160,3 +167,36 @@ async fn import_remote(
Ok(())
}
+
+async fn cache_federation_asset(
+ session: &Session,
+ identifier: &String,
+ role: &str,
+) -> anyhow::Result<PathBuf> {
+ let (poster, download) = cache_file(&["federation-asset", role, identifier]);
+ if let Some(d) = download {
+ session.node_asset(&identifier, role, d).await?;
+ }
+ Ok(poster)
+}
+
+fn cache_file(seed: &[&str]) -> (PathBuf, Option<File>) {
+ use sha2::Digest;
+ let mut d = sha2::Sha512::new();
+ for s in seed {
+ d.update(s.as_bytes());
+ d.update(b"\0");
+ }
+ let d = d.finalize();
+ let fname = base64::engine::general_purpose::URL_SAFE.encode(d);
+ let fname = &fname[..22]; // about 128 bits
+ let fullpath = CONF.cache_path.join(fname);
+ let cachepath = PathBuf::from_str(fname).unwrap();
+
+ let f = if !fullpath.exists() {
+ Some(File::create(&fullpath).unwrap())
+ } else {
+ None
+ };
+ (cachepath, f)
+}
diff --git a/server/src/routes/ui/assets.rs b/server/src/routes/ui/assets.rs
index 7fa083c..4b5c64a 100644
--- a/server/src/routes/ui/assets.rs
+++ b/server/src/routes/ui/assets.rs
@@ -9,6 +9,7 @@ use crate::{
CONF,
};
use anyhow::anyhow;
+use jellycommon::AssetLocation;
use log::info;
use rocket::{get, http::ContentType, FromFormField, State, UriDisplayQuery};
use std::{path::PathBuf, str::FromStr};
@@ -16,7 +17,9 @@ use tokio::fs::File;
#[derive(FromFormField, UriDisplayQuery)]
pub enum AssetRole {
+ #[field(value = "poster")]
Poster,
+ #[field(value = "backdrop")]
Backdrop,
}
@@ -32,15 +35,31 @@ pub async fn r_item_assets(
AssetRole::Backdrop => node.private.backdrop,
AssetRole::Poster => node.private.poster,
}
- .map(|e| CONF.library_path.join(e))
+ .map(|e| e.path())
.unwrap_or_else(|| {
CONF.asset_path
.join(PathBuf::from_str("fallback.jpeg").unwrap())
});
info!("loading asset from {path:?}");
- let ext = path.extension().unwrap().to_str().unwrap();
+ let ext = path
+ .extension()
+ .map(|e| e.to_str().unwrap())
+ .unwrap_or("jpeg");
Ok((
ContentType::from_extension(ext).unwrap(),
CacheControlFile::new(File::open(path).await?).await,
))
}
+
+pub trait AssetLocationExt {
+ fn path(&self) -> PathBuf;
+}
+impl AssetLocationExt for AssetLocation {
+ fn path(&self) -> PathBuf {
+ match self {
+ AssetLocation::Assets(p) => CONF.asset_path.join(p),
+ AssetLocation::Cache(p) => CONF.cache_path.join(p),
+ AssetLocation::Library(p) => CONF.library_path.join(p),
+ }
+ }
+}