[fractal] API, util, dw_media: use endpoint and merge with download_file
- From: Daniel Garcia Moreno <danigm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] API, util, dw_media: use endpoint and merge with download_file
- Date: Thu, 2 Apr 2020 10:39:51 +0000 (UTC)
commit 85606ffa149d513cc12cacd5cf2f569aae551ddd
Author: Alejandro DomÃnguez <adomu net-c com>
Date: Tue Mar 10 12:29:14 2020 +0100
API, util, dw_media: use endpoint and merge with download_file
fractal-matrix-api/src/backend/directory.rs | 8 +-
fractal-matrix-api/src/backend/media.rs | 23 +-----
fractal-matrix-api/src/backend/mod.rs | 6 +-
fractal-matrix-api/src/backend/room.rs | 10 +--
fractal-matrix-api/src/backend/sync.rs | 4 +-
fractal-matrix-api/src/backend/types.rs | 2 -
fractal-matrix-api/src/backend/user.rs | 25 ++----
fractal-matrix-api/src/globals.rs | 1 -
fractal-matrix-api/src/meson.build | 2 +-
fractal-matrix-api/src/model/room.rs | 6 +-
fractal-matrix-api/src/r0/media.rs | 4 +-
.../src/r0/media/{create.rs => create_content.rs} | 0
fractal-matrix-api/src/r0/media/get_content.rs | 33 ++++++++
.../src/r0/media/get_content_thumbnail.rs | 37 +++++++++
fractal-matrix-api/src/util.rs | 92 +++++++++-------------
15 files changed, 140 insertions(+), 113 deletions(-)
---
diff --git a/fractal-matrix-api/src/backend/directory.rs b/fractal-matrix-api/src/backend/directory.rs
index f9796b71..0982fe7a 100644
--- a/fractal-matrix-api/src/backend/directory.rs
+++ b/fractal-matrix-api/src/backend/directory.rs
@@ -115,8 +115,12 @@ pub fn room_search(
.inspect(|r: &Room| {
if let Some(avatar) = r.avatar.clone() {
if let Ok(dest) = cache_dir_path(None, &r.id.to_string()) {
- let _ =
- dw_media(&base, &avatar, ContentType::Download, Some(&dest));
+ let _ = dw_media(
+ base.clone(),
+ &avatar,
+ ContentType::Download,
+ Some(dest),
+ );
}
}
})
diff --git a/fractal-matrix-api/src/backend/media.rs b/fractal-matrix-api/src/backend/media.rs
index 6a75477c..f7996190 100644
--- a/fractal-matrix-api/src/backend/media.rs
+++ b/fractal-matrix-api/src/backend/media.rs
@@ -2,14 +2,10 @@ use crate::backend::types::Backend;
use crate::error::Error;
use crate::globals;
use ruma_identifiers::RoomId;
-use std::str::Split;
use std::sync::mpsc::Sender;
-use std::thread;
use url::Url;
use crate::r0::AccessToken;
-use crate::util::cache_dir_path;
-use crate::util::download_file;
use crate::util::dw_media;
use crate::util::get_prev_batch_from;
use crate::util::semaphore;
@@ -26,14 +22,14 @@ use crate::types::Message;
pub fn get_thumb_async(bk: &Backend, baseu: Url, media: String, tx: Sender<Result<String, Error>>) {
semaphore(bk.limit_threads.clone(), move || {
- let fname = dw_media(&baseu, &media, ContentType::default_thumbnail(), None);
+ let fname = dw_media(baseu, &media, ContentType::default_thumbnail(), None);
tx.send(fname).expect_log("Connection closed");
});
}
pub fn get_media_async(bk: &Backend, baseu: Url, media: String, tx: Sender<Result<String, Error>>) {
semaphore(bk.limit_threads.clone(), move || {
- let fname = dw_media(&baseu, &media, ContentType::Download, None);
+ let fname = dw_media(baseu, &media, ContentType::Download, None);
tx.send(fname).expect_log("Connection closed");
});
}
@@ -71,21 +67,6 @@ pub fn get_media_list_async(
});
}
-pub fn get_file_async(url: Url, tx: Sender<String>) -> Result<(), Error> {
- let name = url
- .path_segments()
- .and_then(Split::last)
- .unwrap_or_default();
- let fname = cache_dir_path(Some("files"), name)?;
-
- thread::spawn(move || {
- let fname = download_file(url, fname, None).unwrap_or_default();
- tx.send(fname).expect_log("Connection closed");
- });
-
- Ok(())
-}
-
fn get_room_media_list(
baseu: Url,
access_token: AccessToken,
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 9d55eb69..4d905cab 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -385,15 +385,11 @@ impl Backend {
),
Ok(BKCommand::GetMedia(server, media)) => {
thread::spawn(move || {
- let fname = dw_media(&server, &media, ContentType::Download, None);
+ let fname = dw_media(server, &media, ContentType::Download, None);
tx.send(BKResponse::Media(fname))
.expect_log("Connection closed");
});
}
- Ok(BKCommand::GetFileAsync(url, ctx)) => {
- let r = media::get_file_async(url, ctx);
- bkerror!(r, tx, BKResponse::GetFileAsyncError);
- }
// Directory module
Ok(BKCommand::DirectoryProtocols(server, access_token)) => {
diff --git a/fractal-matrix-api/src/backend/room.rs b/fractal-matrix-api/src/backend/room.rs
index 301cec06..39b44de4 100644
--- a/fractal-matrix-api/src/backend/room.rs
+++ b/fractal-matrix-api/src/backend/room.rs
@@ -37,9 +37,9 @@ use crate::r0::context::get_context::request as get_context;
use crate::r0::context::get_context::Parameters as GetContextParameters;
use crate::r0::context::get_context::Response as GetContextResponse;
use crate::r0::filter::RoomEventFilter;
-use crate::r0::media::create::request as create_content;
-use crate::r0::media::create::Parameters as CreateContentParameters;
-use crate::r0::media::create::Response as CreateContentResponse;
+use crate::r0::media::create_content::request as create_content;
+use crate::r0::media::create_content::Parameters as CreateContentParameters;
+use crate::r0::media::create_content::Response as CreateContentResponse;
use crate::r0::membership::invite_user::request as invite_user;
use crate::r0::membership::invite_user::Body as InviteUserBody;
use crate::r0::membership::invite_user::Parameters as InviteUserParameters;
@@ -154,10 +154,10 @@ pub fn get_room_avatar(
let dest = cache_dir_path(None, &room_id.to_string()).ok();
if let Some(ref avatar) = avatar {
let _ = dw_media(
- &base,
+ base,
avatar.as_str(),
ContentType::default_thumbnail(),
- dest.as_ref().map(String::as_str),
+ dest,
);
}
diff --git a/fractal-matrix-api/src/backend/sync.rs b/fractal-matrix-api/src/backend/sync.rs
index d008eda7..d1bfe39a 100644
--- a/fractal-matrix-api/src/backend/sync.rs
+++ b/fractal-matrix-api/src/backend/sync.rs
@@ -113,7 +113,7 @@ pub fn sync(
let join = &response.rooms.join;
// New rooms
- let rs = Room::from_sync_response(&response, user_id.clone(), &base)
+ let rs = Room::from_sync_response(&response, user_id.clone(), base)
.map_err(Into::into);
tx.send(BKResponse::UpdateRooms(rs))
.expect_log("Connection closed");
@@ -246,7 +246,7 @@ pub fn sync(
data.lock().unwrap().m_direct = parse_m_direct(&response.account_data.events);
let rooms_def =
- Room::from_sync_response(&response, user_id, &base)
+ Room::from_sync_response(&response, user_id, base)
.map(|rooms| {
let def =
data.lock().unwrap().join_to_room.as_ref().and_then(|jtr| {
diff --git a/fractal-matrix-api/src/backend/types.rs b/fractal-matrix-api/src/backend/types.rs
index 9297b708..6f995854 100644
--- a/fractal-matrix-api/src/backend/types.rs
+++ b/fractal-matrix-api/src/backend/types.rs
@@ -53,7 +53,6 @@ pub enum BKCommand {
Option<String>,
Sender<(Vec<Message>, String)>,
),
- GetFileAsync(Url, Sender<String>),
GetAvatarAsync(Url, Option<Member>, Sender<String>),
GetMedia(Url, String),
GetUserInfoAsync(Url, UserId, Option<Sender<(String, String)>>),
@@ -137,7 +136,6 @@ pub enum BKResponse {
GuestLoginError(Error),
SendTypingError(Error),
SetRoomError(Error),
- GetFileAsyncError(Error),
InviteError(Error),
ChangeLanguage(Result<(), Error>),
}
diff --git a/fractal-matrix-api/src/backend/user.rs b/fractal-matrix-api/src/backend/user.rs
index 4450169c..e01fee44 100644
--- a/fractal-matrix-api/src/backend/user.rs
+++ b/fractal-matrix-api/src/backend/user.rs
@@ -46,9 +46,9 @@ use crate::r0::contact::request_verification_token_msisdn::request as request_co
use crate::r0::contact::request_verification_token_msisdn::Body as PhoneTokenBody;
use crate::r0::contact::request_verification_token_msisdn::Parameters as PhoneTokenParameters;
use crate::r0::contact::request_verification_token_msisdn::Response as PhoneTokenResponse;
-use crate::r0::media::create::request as create_content;
-use crate::r0::media::create::Parameters as CreateContentParameters;
-use crate::r0::media::create::Response as CreateContentResponse;
+use crate::r0::media::create_content::request as create_content;
+use crate::r0::media::create_content::Parameters as CreateContentParameters;
+use crate::r0::media::create_content::Response as CreateContentResponse;
use crate::r0::profile::get_display_name::request as get_display_name;
use crate::r0::profile::get_display_name::Response as GetDisplayNameResponse;
use crate::r0::profile::set_avatar_url::request as set_avatar_url;
@@ -340,7 +340,7 @@ pub fn account_destruction(
}
pub fn get_avatar(base: Url, userid: UserId) -> Result<String, Error> {
- get_user_avatar(&base, &userid).map(|(_, fname)| fname)
+ get_user_avatar(base, &userid).map(|(_, fname)| fname)
}
pub fn get_avatar_async(bk: &Backend, base: Url, member: Option<Member>, tx: Sender<String>) {
@@ -349,7 +349,7 @@ pub fn get_avatar_async(bk: &Backend, base: Url, member: Option<Member>, tx: Sen
let avatar = member.avatar.clone().unwrap_or_default();
semaphore(bk.limit_threads.clone(), move || {
- let fname = get_user_avatar_img(&base, &uid, &avatar).unwrap_or_default();
+ let fname = get_user_avatar_img(base, &uid, &avatar).unwrap_or_default();
tx.send(fname).expect_log("Connection closed");
});
} else {
@@ -418,7 +418,7 @@ pub fn get_user_info_async(
bk.user_info_cache.insert(uid.clone(), info.clone());
semaphore(bk.limit_threads.clone(), move || {
- match (get_user_avatar(&baseu, &uid), tx) {
+ match (get_user_avatar(baseu, &uid), tx) {
(Ok(i0), Some(tx)) => {
tx.send(i0.clone()).expect_log("Connection closed");
*info.lock().unwrap() = i0;
@@ -454,16 +454,7 @@ pub fn search(
.map(|response| response.results.into_iter().map(Into::into).collect())
}
-fn get_user_avatar_img(baseu: &Url, userid: &UserId, avatar: &str) -> Result<String, Error> {
- if avatar.is_empty() {
- return Ok(String::new());
- }
-
+fn get_user_avatar_img(baseu: Url, userid: &UserId, avatar: &str) -> Result<String, Error> {
let dest = cache_dir_path(None, &userid.to_string())?;
- dw_media(
- baseu,
- &avatar,
- ContentType::default_thumbnail(),
- Some(&dest),
- )
+ dw_media(baseu, avatar, ContentType::default_thumbnail(), Some(dest))
}
diff --git a/fractal-matrix-api/src/globals.rs b/fractal-matrix-api/src/globals.rs
index e455724f..924c85df 100644
--- a/fractal-matrix-api/src/globals.rs
+++ b/fractal-matrix-api/src/globals.rs
@@ -7,7 +7,6 @@ pub static ROOM_DIRECTORY_LIMIT: i32 = 20;
pub static DEVICE_NAME: &str = "Fractal";
lazy_static! {
- pub static ref MATRIX_RE: Regex = Regex::new(r"mxc://(?P<server>[^/]+)/(?P<media>.+)").unwrap();
pub static ref EMAIL_RE: Regex = Regex::new(
r"^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])+@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$"
)
diff --git a/fractal-matrix-api/src/meson.build b/fractal-matrix-api/src/meson.build
index c4b1892b..99505a10 100644
--- a/fractal-matrix-api/src/meson.build
+++ b/fractal-matrix-api/src/meson.build
@@ -28,7 +28,7 @@ api_sources = files(
'r0/contact/request_verification_token_email.rs',
'r0/contact/request_verification_token_msisdn.rs',
'r0/directory/post_public_rooms.rs',
- 'r0/media/create.rs',
+ 'r0/media/create_content.rs',
'r0/membership/invite_user.rs',
'r0/membership/join_room_by_id_or_alias.rs',
'r0/membership/leave_room.rs',
diff --git a/fractal-matrix-api/src/model/room.rs b/fractal-matrix-api/src/model/room.rs
index a0b0b12e..af42612b 100644
--- a/fractal-matrix-api/src/model/room.rs
+++ b/fractal-matrix-api/src/model/room.rs
@@ -132,7 +132,7 @@ impl Room {
pub fn from_sync_response(
response: &SyncResponse,
user_id: UserId,
- baseu: &Url,
+ baseu: Url,
) -> Result<Vec<Self>, IdError> {
// getting the list of direct rooms
let direct: HashSet<RoomId> = parse_m_direct(&response.account_data.events)
@@ -206,7 +206,7 @@ impl Room {
if leave_id != user_id {
let kick_reason = &last_event["content"]["reason"];
if let Some((kicker_alias, kicker_avatar)) =
- get_user_avatar(baseu, &leave_id).ok()
+ get_user_avatar(baseu.clone(), &leave_id).ok()
{
let kicker = Member {
alias: Some(kicker_alias),
@@ -245,7 +245,7 @@ impl Room {
})
.map_or(Ok(None), |ev| {
Ok(get_user_avatar(
- baseu,
+ baseu.clone(),
&UserId::try_from(ev["sender"].as_str().unwrap_or_default())?,
)
.ok())
diff --git a/fractal-matrix-api/src/r0/media.rs b/fractal-matrix-api/src/r0/media.rs
index c5fb369c..eccd2e8e 100644
--- a/fractal-matrix-api/src/r0/media.rs
+++ b/fractal-matrix-api/src/r0/media.rs
@@ -1 +1,3 @@
-pub mod create;
+pub mod create_content;
+pub mod get_content;
+pub mod get_content_thumbnail;
diff --git a/fractal-matrix-api/src/r0/media/create.rs b/fractal-matrix-api/src/r0/media/create_content.rs
similarity index 100%
rename from fractal-matrix-api/src/r0/media/create.rs
rename to fractal-matrix-api/src/r0/media/create_content.rs
diff --git a/fractal-matrix-api/src/r0/media/get_content.rs b/fractal-matrix-api/src/r0/media/get_content.rs
new file mode 100644
index 00000000..bf8cb0ea
--- /dev/null
+++ b/fractal-matrix-api/src/r0/media/get_content.rs
@@ -0,0 +1,33 @@
+use reqwest::blocking::Client;
+use reqwest::blocking::Request;
+use reqwest::Error;
+use serde::Serialize;
+use url::{Host, Url};
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ #[serde(skip_serializing_if = "bool::clone")]
+ pub allow_remote: bool,
+}
+
+impl Default for Parameters {
+ fn default() -> Self {
+ Self { allow_remote: true }
+ }
+}
+
+pub fn request(
+ base: Url,
+ params: &Parameters,
+ server: &Host<String>,
+ media_id: &str,
+) -> Result<Request, Error> {
+ let url = base
+ .join(&format!(
+ "/_matrix/media/r0/download/{}/{}",
+ server, media_id,
+ ))
+ .expect("Malformed URL in get_content");
+
+ Client::new().get(url).query(params).build()
+}
diff --git a/fractal-matrix-api/src/r0/media/get_content_thumbnail.rs
b/fractal-matrix-api/src/r0/media/get_content_thumbnail.rs
new file mode 100644
index 00000000..9ec73e29
--- /dev/null
+++ b/fractal-matrix-api/src/r0/media/get_content_thumbnail.rs
@@ -0,0 +1,37 @@
+use reqwest::blocking::Client;
+use reqwest::blocking::Request;
+use reqwest::Error;
+use serde::Serialize;
+use url::{Host, Url};
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub width: u64,
+ pub height: u64,
+ pub method: Option<Method>,
+ #[serde(skip_serializing_if = "bool::clone")]
+ pub allow_remote: bool,
+}
+
+#[derive(Clone, Copy, Debug, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Method {
+ Crop,
+ Scale,
+}
+
+pub fn request(
+ base: Url,
+ params: &Parameters,
+ server: &Host<String>,
+ media_id: &str,
+) -> Result<Request, Error> {
+ let url = base
+ .join(&format!(
+ "/_matrix/media/r0/thumbnail/{}/{}",
+ server, media_id,
+ ))
+ .expect("Malformed URL in get_content_thumbnail");
+
+ Client::new().get(url).query(params).build()
+}
diff --git a/fractal-matrix-api/src/util.rs b/fractal-matrix-api/src/util.rs
index d90b2f06..6e5f060d 100644
--- a/fractal-matrix-api/src/util.rs
+++ b/fractal-matrix-api/src/util.rs
@@ -23,12 +23,15 @@ use crate::error::Error;
use crate::r0::context::get_context::request as get_context;
use crate::r0::context::get_context::Parameters as GetContextParameters;
use crate::r0::context::get_context::Response as GetContextResponse;
+use crate::r0::media::get_content::request as get_content;
+use crate::r0::media::get_content::Parameters as GetContentParameters;
+use crate::r0::media::get_content_thumbnail::request as get_content_thumbnail;
+use crate::r0::media::get_content_thumbnail::Method;
+use crate::r0::media::get_content_thumbnail::Parameters as GetContentThumbnailParameters;
use crate::r0::profile::get_profile::request as get_profile;
use crate::r0::profile::get_profile::Response as GetProfileResponse;
use crate::r0::AccessToken;
-use crate::globals;
-
lazy_static! {
pub static ref HTTP_CLIENT: Client = Client::new();
static ref CACHE_PATH: PathBuf = ProjectDirs::from("org", "GNOME", "Fractal")
@@ -117,7 +120,7 @@ macro_rules! bkerror2 {
pub enum ContentType {
Download,
- Thumbnail(i32, i32),
+ Thumbnail(u64, u64),
}
impl ContentType {
@@ -177,42 +180,43 @@ pub fn get_prev_batch_from(
}
pub fn dw_media(
- base: &Url,
- url: &str,
+ base: Url,
+ mxc: &str,
media_type: ContentType,
- dest: Option<&str>,
+ dest: Option<String>,
) -> Result<String, Error> {
- let caps = globals::MATRIX_RE
- .captures(url)
+ let mxc_url = Url::parse(mxc)?;
+
+ if mxc_url.scheme() != "mxc" {
+ return Err(Error::BackendError);
+ }
+
+ let server = mxc_url.host().ok_or(Error::BackendError)?.to_owned();
+ let media_id = mxc_url
+ .path_segments()
+ .and_then(|mut ps| ps.next())
+ .filter(|s| !s.is_empty())
.ok_or(Error::BackendError)?;
- let server = String::from(&caps["server"]);
- let media = String::from(&caps["media"]);
-
- let (params, path) = if let ContentType::Thumbnail(w, h) = media_type {
- (
- vec![
- ("width", w.to_string()),
- ("height", h.to_string()),
- ("method", String::from("crop")),
- ],
- format!("thumbnail/{}/{}", server, media),
- )
- } else {
- (vec![], format!("download/{}/{}", server, media))
- };
- let url = build_url(base, &format!("/_matrix/media/r0/{}", path), ¶ms)?;
+ let request = if let ContentType::Thumbnail(width, height) = media_type {
+ let params = GetContentThumbnailParameters {
+ width,
+ height,
+ method: Some(Method::Crop),
+ allow_remote: true,
+ };
+ get_content_thumbnail(base, ¶ms, &server, &media_id)
+ } else {
+ let params = GetContentParameters::default();
+ get_content(base, ¶ms, &server, &media_id)
+ }?;
let fname = match dest {
- None if media_type.is_thumbnail() => cache_dir_path(Some("thumbs"), &media)?,
- None => cache_dir_path(Some("medias"), &media)?,
- Some(d) => String::from(d),
+ None if media_type.is_thumbnail() => cache_dir_path(Some("thumbs"), &media_id)?,
+ None => cache_dir_path(Some("medias"), &media_id)?,
+ Some(ref d) => d.clone(),
};
- download_file(url, fname, dest)
-}
-
-pub fn download_file(url: Url, fname: String, dest: Option<&str>) -> Result<String, Error> {
let fpath = Path::new(&fname);
// If the file is already cached and recent enough, don't download it
@@ -223,17 +227,16 @@ pub fn download_file(url: Url, fname: String, dest: Option<&str>) -> Result<Stri
} else {
HTTP_CLIENT
.get_client()?
- .get(url)
- .send()?
+ .execute(request)?
.bytes()
.collect::<Result<Vec<u8>, std::io::Error>>()
.and_then(|media| write(&fname, media))
.and(Ok(fname))
- .map_err(Error::from)
+ .map_err(Into::into)
}
}
-pub fn get_user_avatar(base: &Url, user_id: &UserId) -> Result<(String, String), Error> {
+pub fn get_user_avatar(base: Url, user_id: &UserId) -> Result<(String, String), Error> {
let response = get_profile(base.clone(), user_id)
.map_err::<Error, _>(Into::into)
.and_then(|request| {
@@ -257,7 +260,7 @@ pub fn get_user_avatar(base: &Url, user_id: &UserId) -> Result<(String, String),
base,
url.as_str(),
ContentType::default_thumbnail(),
- Some(&dest),
+ Some(dest),
)
})
.unwrap_or(Ok(Default::default()))?;
@@ -265,23 +268,6 @@ pub fn get_user_avatar(base: &Url, user_id: &UserId) -> Result<(String, String),
Ok((name, img))
}
-pub fn build_url(base: &Url, path: &str, params: &[(&str, String)]) -> Result<Url, Error> {
- let mut url = base.join(path)?;
-
- {
- // If len was 0 `?` would be appended without being needed.
- if !params.is_empty() {
- let mut query = url.query_pairs_mut();
- query.clear();
- for (k, v) in params {
- query.append_pair(k, &v);
- }
- }
- }
-
- Ok(url)
-}
-
pub fn cache_dir_path(dir: Option<&str>, name: &str) -> Result<String, Error> {
let path = CACHE_PATH.join(dir.unwrap_or_default());
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]