From 28380021a7d3efc67a786ca9d4a46526cf59c892 Mon Sep 17 00:00:00 2001 From: Kitaiti Makoto Date: Thu, 18 Feb 2021 01:23:57 +0900 Subject: [PATCH] Determine file path of mirror of remote image using the URI --- plume-models/src/medias.rs | 47 +++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/plume-models/src/medias.rs b/plume-models/src/medias.rs index f6fa9b85..26e1c6b9 100644 --- a/plume-models/src/medias.rs +++ b/plume-models/src/medias.rs @@ -10,7 +10,14 @@ use plume_common::{ activity_pub::{inbox::FromId, Id}, utils::MediaProcessor, }; -use std::{fs, path::Path}; +use std::{ + fs, + path::{Path, PathBuf}, +}; +use tracing::warn; +use url::Url; + +const REMOTE_MEDIA_DIRECTORY: &str = "remote"; #[derive(Clone, Identifiable, Queryable)] pub struct Media { @@ -198,16 +205,7 @@ impl Media { // TODO: merge with save_remote? pub fn from_activity(conn: &DbConn, image: &Image) -> Result { let remote_url = image.object_props.url_string().ok()?; - let ext = remote_url - .rsplit('.') - .next() - .map(ToOwned::to_owned) - .unwrap_or_else(|| String::from("png")); - let path = Path::new(&super::CONFIG.media_directory).join(format!( - "{}.{}", - GUID::rand().to_string(), - ext - )); + let path = determine_mirror_file_path(&remote_url); let mut dest = fs::File::create(path.clone()).ok()?; if let Some(proxy) = CONFIG.proxy() { @@ -262,6 +260,33 @@ impl Media { } } +fn determine_mirror_file_path(url: &str) -> PathBuf { + let mut file_path = Path::new(&super::CONFIG.media_directory).join(REMOTE_MEDIA_DIRECTORY); + Url::parse(url) + .map(|url| { + if !url.has_host() { + return; + } + file_path.push(url.host_str().unwrap()); + for segment in url.path_segments().expect("FIXME") { + file_path.push(segment); + } + // TODO: handle query + // HINT: Use characters which must be percent-encoded in path as separator between path and query + // HINT: handle extension + }) + .unwrap_or_else(|err| { + warn!("Failed to parse url: {} {}", &url, err); + let ext = url + .rsplit('.') + .next() + .map(ToOwned::to_owned) + .unwrap_or_else(|| String::from("png")); + file_path.push(format!("{}.{}", GUID::rand().to_string(), ext)); + }); + file_path +} + #[cfg(test)] pub(crate) mod tests { use super::*;