Commit d2999f85 authored by Eisha Chen-yen-su's avatar Eisha Chen-yen-su

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 #265
parent 33fa0560
use globals;
use std::thread; use std::thread;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use error::Error; use error::Error;
...@@ -7,8 +8,11 @@ use backend::types::Backend; ...@@ -7,8 +8,11 @@ use backend::types::Backend;
use util::dw_media; use util::dw_media;
use util::download_file; use util::download_file;
use util::cache_dir_path; use util::cache_dir_path;
use util::get_room_media_list;
use util::resolve_media_url; use util::resolve_media_url;
use types::Message;
pub fn get_thumb_async(bk: &Backend, media: String, tx: Sender<String>) -> Result<(), Error> { pub fn get_thumb_async(bk: &Backend, media: String, tx: Sender<String>) -> Result<(), Error> {
let baseu = bk.get_base_url()?; let baseu = bk.get_base_url()?;
...@@ -43,6 +47,31 @@ pub fn get_media_async(bk: &Backend, media: String, tx: Sender<String>) -> Resul ...@@ -43,6 +47,31 @@ pub fn get_media_async(bk: &Backend, media: String, tx: Sender<String>) -> Resul
Ok(()) 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> { pub fn get_media(bk: &Backend, media: String) -> Result<(), Error> {
let baseu = bk.get_base_url()?; let baseu = bk.get_base_url()?;
......
...@@ -316,6 +316,10 @@ impl Backend { ...@@ -316,6 +316,10 @@ impl Backend {
let r = media::get_media_async(self, media, ctx); let r = media::get_media_async(self, media, ctx);
bkerror!(r, tx, BKResponse::CommandError); 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)) => { Ok(BKCommand::GetMedia(media)) => {
let r = media::get_media(self, media); let r = media::get_media(self, media);
bkerror!(r, tx, BKResponse::CommandError); bkerror!(r, tx, BKResponse::CommandError);
......
...@@ -44,6 +44,7 @@ pub enum BKCommand { ...@@ -44,6 +44,7 @@ pub enum BKCommand {
GetRoomAvatar(String), GetRoomAvatar(String),
GetThumbAsync(String, Sender<String>), GetThumbAsync(String, Sender<String>),
GetMediaAsync(String, Sender<String>), GetMediaAsync(String, Sender<String>),
GetMediaListAsync(String, Option<String>, Option<String>, Sender<(Vec<Message>, String)>),
GetFileAsync(String, Sender<String>), GetFileAsync(String, Sender<String>),
GetAvatarAsync(Option<Member>, Sender<String>), GetAvatarAsync(Option<Member>, Sender<String>),
GetMedia(String), GetMedia(String),
......
...@@ -472,6 +472,60 @@ pub fn parse_sync_events(r: &JsonValue) -> Result<Vec<Event>, Error> { ...@@ -472,6 +472,60 @@ pub fn parse_sync_events(r: &JsonValue) -> Result<Vec<Event>, Error> {
Ok(evs) 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> { pub fn get_media(url: &str) -> Result<Vec<u8>, Error> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let mut conn = client.get(url); let mut conn = client.get(url);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment