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:
parent
33fa0560a9
commit
d2999f85de
4 changed files with 88 additions and 0 deletions
|
@ -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()?;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue