Backend: Add a command to fetch media list

This adds a command in the backend that asynchronously fetches
a list of media before a given message.

See https://gitlab.gnome.org/World/fractal/issues/265
This commit is contained in:
Eisha CHEN-YEN-SU 2018-07-04 18:39:20 +02:00
parent 33fa0560a9
commit d2999f85de
4 changed files with 88 additions and 0 deletions

View file

@ -1,3 +1,4 @@
use globals;
use std::thread;
use std::sync::mpsc::Sender;
use error::Error;
@ -7,8 +8,11 @@ use backend::types::Backend;
use util::dw_media;
use util::download_file;
use util::cache_dir_path;
use util::get_room_media_list;
use util::resolve_media_url;
use types::Message;
pub fn get_thumb_async(bk: &Backend, media: String, tx: Sender<String>) -> Result<(), Error> {
let baseu = bk.get_base_url()?;
@ -43,6 +47,31 @@ pub fn get_media_async(bk: &Backend, media: String, tx: Sender<String>) -> Resul
Ok(())
}
pub fn get_media_list_async(bk: &Backend,
roomid: String,
first_media_id: Option<String>,
prev_batch: Option<String>,
tx: Sender<(Vec<Message>, String)>)
-> Result<(), Error> {
let baseu = bk.get_base_url()?;
let tk = bk.data.lock().unwrap().access_token.clone();
semaphore!(bk.limit_threads, {
match get_room_media_list(&baseu, tk, roomid.clone(),
globals::PAGE_LIMIT,
first_media_id, prev_batch) {
Ok(media_list) => {
tx.send(media_list).unwrap();
}
Err(_) => {
tx.send((Vec::new(), String::new())).unwrap();
}
}
});
Ok(())
}
pub fn get_media(bk: &Backend, media: String) -> Result<(), Error> {
let baseu = bk.get_base_url()?;

View file

@ -316,6 +316,10 @@ impl Backend {
let r = media::get_media_async(self, media, ctx);
bkerror!(r, tx, BKResponse::CommandError);
}
Ok(BKCommand::GetMediaListAsync(roomid, first_media_id, prev_batch, ctx)) => {
let r = media::get_media_list_async(self, roomid, first_media_id, prev_batch, ctx);
bkerror!(r, tx, BKResponse::CommandError);
}
Ok(BKCommand::GetMedia(media)) => {
let r = media::get_media(self, media);
bkerror!(r, tx, BKResponse::CommandError);

View file

@ -44,6 +44,7 @@ pub enum BKCommand {
GetRoomAvatar(String),
GetThumbAsync(String, Sender<String>),
GetMediaAsync(String, Sender<String>),
GetMediaListAsync(String, Option<String>, Option<String>, Sender<(Vec<Message>, String)>),
GetFileAsync(String, Sender<String>),
GetAvatarAsync(Option<Member>, Sender<String>),
GetMedia(String),

View file

@ -472,6 +472,60 @@ pub fn parse_sync_events(r: &JsonValue) -> Result<Vec<Event>, Error> {
Ok(evs)
}
pub fn get_prev_batch_from(baseu: &Url, tk: String, roomid: String, evid: String) -> Result<String, Error> {
let params = vec![
("access_token", tk.clone()),
("limit", 0.to_string()),
];
let path = format!("rooms/{}/context/{}", roomid, evid);
let url = client_url!(baseu, &path, params)?;
let r = json_q("get", &url, &json!(null), globals::TIMEOUT)?;
let prev_batch = r["start"].to_string().trim_matches('"').to_string();
Ok(prev_batch)
}
pub fn get_room_media_list(baseu: &Url,
tk: String,
roomid: String,
limit: i32,
first_media_id: Option<String>,
prev_batch: Option<String>)
-> Result<(Vec<Message>, String), Error> {
let mut params = vec![
("dir", strn!("b")),
("limit", format!("{}", limit)),
("access_token", tk.clone()),
("filter", "{\"filter_json\": { \"contains_url\": true, \"not_types\": [\"m.sticker\"] } }".to_string()),
];
match prev_batch {
Some(ref pb) => { params.push(("from", pb.clone())) }
None => {
if let Some(id) = first_media_id {
params.push(("from", get_prev_batch_from(baseu, tk, roomid.clone(), id)?))
}
}
};
let path = format!("rooms/{}/messages", roomid);
let url = client_url!(baseu, &path, params)?;
let r = json_q("get", &url, &json!(null), globals::TIMEOUT)?;
let array = r["chunk"].as_array();
let prev_batch = r["end"].to_string().trim_matches('"').to_string();
if array.is_none() || array.unwrap().len() == 0 {
return Ok((vec![], prev_batch));
}
let evs = array.unwrap().iter().rev();
let media_list = Message::from_json_events_iter(roomid.clone(), evs);
Ok((media_list, prev_batch))
}
pub fn get_media(url: &str) -> Result<Vec<u8>, Error> {
let client = reqwest::Client::new();
let mut conn = client.get(url);