From 5f6a6a78607e6e45a66e91d968fc7e96fc1aed13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Moreno?= Date: Fri, 18 Aug 2017 18:35:51 +0200 Subject: [PATCH] Storing avatar and media files in cache dir --- Cargo.toml | 1 + src/app.rs | 11 ------ src/backend.rs | 94 ++++++++++++++++++++++++++++++++++++++------------ src/util.rs | 11 ++++++ 4 files changed, 83 insertions(+), 34 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f9db84f7..9f23c95b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ serde = "1.0.11" serde_derive = "1.0.11" serde_json = "1.0.2" url = "1.5.1" +xdg = "2.1.0" [dependencies.gtk] features = ["v3_12"] diff --git a/src/app.rs b/src/app.rs index 0a20a1a0..1389cf5f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -18,17 +18,6 @@ use backend::Backend; use backend; -macro_rules! derror { - ($from: path, $to: path) => { - impl From<$from> for Error { - fn from(_: $from) -> Error { - $to - } - } - }; -} - - #[derive(Debug)] pub enum Error { SecretServiceError, diff --git a/src/backend.rs b/src/backend.rs index 0ef6bb21..87b9cfe1 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,6 +1,8 @@ extern crate url; extern crate reqwest; extern crate regex; +extern crate xdg; + use self::regex::Regex; @@ -13,6 +15,7 @@ use std::io::Read; use std::fs::File; use std::io::prelude::*; +use std::io; // TODO: send errors to the frontend @@ -58,6 +61,26 @@ macro_rules! query { }; } +macro_rules! media { + ($base: expr, $url: expr, $dest: expr) => { + dw_media($base, $url, false, $dest, 0, 0) + }; + ($base: expr, $url: expr) => { + dw_media($base, $url, false, None, 0, 0) + }; +} + +macro_rules! thumb { + ($base: expr, $url: expr) => { + dw_media($base, $url, true, None, 64, 64) + }; + ($base: expr, $url: expr, $size: expr) => { + dw_media($base, $url, true, None, $size, $size) + }; + ($base: expr, $url: expr, $w: expr, $h: expr) => { + dw_media($base, $url, true, None, $w, $h) + }; +} #[derive(Debug)] pub enum Error { @@ -71,11 +94,9 @@ impl From for Error { } } -impl From for Error { - fn from(_: url::ParseError) -> Error { - Error::BackendError - } -} +derror!(url::ParseError, Error::BackendError); +derror!(io::Error, Error::BackendError); +derror!(regex::Error, Error::BackendError); pub struct BackendData { user_id: String, @@ -197,27 +218,54 @@ impl Backend { let tx = self.tx.clone(); get!(url, map, AvatarUrlResponse, |r: AvatarUrlResponse| { - let re = Regex::new(r"mxc://(?P[^/]+)/(?P.+)").unwrap(); - let caps = re.captures(&r.avatar_url).unwrap(); - let (server, media) = (String::from(&caps["server"]), String::from(&caps["media"])); - let mut url = baseu.join("/_matrix/media/r0/thumbnail/").unwrap(); - url = url.join(&(server + "/")).unwrap(); - url = url.join(&(media + "?width=64&height=64&method=scale")).unwrap(); - - let client = reqwest::Client::new().unwrap(); - let mut conn = client.get(url.as_str()).unwrap(); - let mut res = conn.send().unwrap(); - - let fname = String::from("/tmp/avatar"); - let mut file = File::create(&fname).unwrap(); - let mut buffer = Vec::new(); - res.read_to_end(&mut buffer).unwrap(); - file.write_all(&buffer).unwrap(); - println!("image created! {}", fname); - + let fname = thumb!(baseu, &r.avatar_url).unwrap(); tx.send(BKResponse::Avatar(fname)).unwrap(); }); Ok(()) } } + +fn get_media(url: &str) -> Result, Error> { + let client = reqwest::Client::new()?; + let mut conn = client.get(url)?; + let mut res = conn.send()?; + + let mut buffer = Vec::new(); + res.read_to_end(&mut buffer)?; + + Ok(buffer) +} + +fn dw_media(base: Url, url: &str, thumb: bool, dest: Option<&str>, w: i32, h: i32) -> Result { + let xdg_dirs = xdg::BaseDirectories::with_prefix("guillotine").unwrap(); + + let re = Regex::new(r"mxc://(?P[^/]+)/(?P.+)")?; + let caps = re.captures(url).ok_or(Error::BackendError)?; + let server = String::from(&caps["server"]); + let media = String::from(&caps["media"]); + + let mut url: Url; + + if thumb { + url = base.join("/_matrix/media/r0/thumbnail/")?; + url = url.join(&(server + "/"))?; + let f = format!("?width={}&height={}&method=scale", w, h); + url = url.join(&(media.clone() + &f))?; + } else { + url = base.join("/_matrix/media/r0/download/")?; + url = url.join(&(server + "/"))?; + url = url.join(&(media))?; + } + + let fname = match dest { + None => String::from(xdg_dirs.place_cache_file(&media)?.to_str().ok_or(Error::BackendError)?), + Some(d) => String::from(d) + &media + }; + + let mut file = File::create(&fname)?; + let buffer = get_media(url.as_str())?; + file.write_all(&buffer)?; + + Ok(fname) +} diff --git a/src/util.rs b/src/util.rs index e6958147..1ec60477 100644 --- a/src/util.rs +++ b/src/util.rs @@ -16,3 +16,14 @@ macro_rules! clone { } ); } + +#[macro_export] +macro_rules! derror { + ($from: path, $to: path) => { + impl From<$from> for Error { + fn from(_: $from) -> Error { + $to + } + } + }; +}