diff --git a/src/app.rs b/src/app.rs index 1389cf5f..ae49079b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -198,6 +198,11 @@ impl AppOp { self.connect_guest(None); } } + + pub fn sync(&self) { + // TODO add a timeout_add for this + self.backend.sync().unwrap(); + } } /// State for the main thread. @@ -237,6 +242,7 @@ impl App { Ok(backend::BKResponse::Token(uid, _)) => { theop.lock().unwrap().set_username(&uid); theop.lock().unwrap().get_username(); + theop.lock().unwrap().sync(); }, Ok(backend::BKResponse::Name(username)) => { theop.lock().unwrap().set_username(&username); diff --git a/src/backend.rs b/src/backend.rs index 87b9cfe1..0c679338 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -2,10 +2,12 @@ extern crate url; extern crate reqwest; extern crate regex; extern crate xdg; - +extern crate serde_json; use self::regex::Regex; +use self::serde_json::Value as JsonValue; + use std::sync::{Arc, Mutex}; use std::thread; use std::collections::HashMap; @@ -20,6 +22,12 @@ use std::io; // TODO: send errors to the frontend macro_rules! get { + ($url: expr, $attrs: expr, $okcb: expr) => { + query!(get, $url, $attrs, JsonValue, $okcb, |err| { + println!("ERROR {:?}", err); + }); + }; + ($url: expr, $attrs: expr, $resp: ident, $okcb: expr) => { query!(get, $url, $attrs, $resp, $okcb, |err| { println!("ERROR {:?}", err); @@ -28,6 +36,12 @@ macro_rules! get { } macro_rules! post { + ($url: expr, $attrs: expr, $okcb: expr) => { + query!(post, $url, $attrs, JsonValue, $okcb, |err| { + println!("ERROR {:?}", err); + }); + }; + ($url: expr, $attrs: expr, $resp: ident, $okcb: expr) => { query!(post, $url, $attrs, $resp, $okcb, |err| { println!("ERROR {:?}", err); @@ -102,6 +116,7 @@ pub struct BackendData { user_id: String, access_token: String, server_url: String, + since: String, } pub struct Backend { @@ -116,24 +131,6 @@ pub enum BKResponse { Avatar(String), } -#[derive(Deserialize)] -#[derive(Debug)] -pub struct Response { - user_id: String, - access_token: String, -} - -#[derive(Deserialize)] -#[derive(Debug)] -pub struct DisplayNameResponse { - displayname: String, -} - -#[derive(Deserialize)] -#[derive(Debug)] -pub struct AvatarUrlResponse { - avatar_url: String, -} impl Backend { pub fn new(tx: Sender) -> Backend { @@ -141,6 +138,7 @@ impl Backend { user_id: String::from("Guest"), access_token: String::from(""), server_url: String::from("https://matrix.org"), + since: String::from(""), }; Backend { tx: tx, data: Arc::new(Mutex::new(data)) } } @@ -154,10 +152,10 @@ impl Backend { let data = self.data.clone(); let tx = self.tx.clone(); - post!(url, map, Response, - |r: Response| { - let uid = r.user_id.clone(); - let tk = r.access_token.clone(); + post!(url, map, + |r: JsonValue| { + let uid = String::from(r["user_id"].as_str().unwrap_or("")); + let tk = String::from(r["access_token"].as_str().unwrap_or("")); data.lock().unwrap().user_id = uid.clone(); data.lock().unwrap().access_token = tk.clone(); tx.send(BKResponse::Token(uid, tk)).unwrap(); @@ -179,10 +177,11 @@ impl Backend { let data = self.data.clone(); let tx = self.tx.clone(); - post!(url, map, Response, - |r: Response| { - let uid = r.user_id.clone(); - let tk = r.access_token.clone(); + post!(url, map, + |r: JsonValue| { + let uid = String::from(r["user_id"].as_str().unwrap_or("")); + let tk = String::from(r["access_token"].as_str().unwrap_or("")); + data.lock().unwrap().user_id = uid.clone(); data.lock().unwrap().access_token = tk.clone(); tx.send(BKResponse::Token(uid, tk)).unwrap(); @@ -199,9 +198,10 @@ impl Backend { let map: HashMap = HashMap::new(); let tx = self.tx.clone(); - get!(url, map, DisplayNameResponse, - |r: DisplayNameResponse| { - tx.send(BKResponse::Name(r.displayname.clone())).unwrap(); + get!(url, map, + |r: JsonValue| { + let name = String::from(r["displayname"].as_str().unwrap_or("")); + tx.send(BKResponse::Name(name)).unwrap(); } ); @@ -216,14 +216,59 @@ impl Backend { let map: HashMap = HashMap::new(); let tx = self.tx.clone(); - get!(url, map, AvatarUrlResponse, - |r: AvatarUrlResponse| { - let fname = thumb!(baseu, &r.avatar_url).unwrap(); + get!(url, map, + |r: JsonValue| { + let url = String::from(r["avatar_url"].as_str().unwrap_or("")); + let fname = thumb!(baseu, &url).unwrap(); + tx.send(BKResponse::Avatar(fname)).unwrap(); }); Ok(()) } + + pub fn sync(&self) -> Result<(), Error> { + let s = self.data.lock().unwrap().server_url.clone(); + let token = self.data.lock().unwrap().access_token.clone(); + let since = self.data.lock().unwrap().since.clone(); + let baseu = Url::parse(&s)?; + + let params: String; + + if since.is_empty() { + params = format!("?full_state=false&timeout=30000&access_token={}", token); + } else { + params = format!("?full_state=false&timeout=30000&access_token={}&since={}", token, since); + } + + let url = baseu.join("/_matrix/client/r0/sync")?.join(¶ms)?; + let map: HashMap = HashMap::new(); + + let tx = self.tx.clone(); + let data = self.data.clone(); + get!(url, map, + |r: JsonValue| { + let next_batch = String::from(r["next_batch"].as_str().unwrap_or("")); + data.lock().unwrap().since = next_batch; + + let rooms = &r["rooms"]; + let invite = rooms["invite"].as_object().unwrap(); + let join = rooms["join"].as_object().unwrap(); + let leave = rooms["leave"].as_object().unwrap(); + + for k in join.keys() { + let room = join.get(k).unwrap(); + let name = room["state"]["events"].as_array().unwrap().iter().find(|x| x["type"] == "m.room.name"); + let n = match name { + None => k.clone(), + Some(o) => String::from(o["content"]["name"].as_str().unwrap()), + }; + println!("room {}: {}", k, n); + } + }); + + Ok(()) + } } fn get_media(url: &str) -> Result, Error> { diff --git a/src/main.rs b/src/main.rs index 2cd66dc4..2e614f0d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,3 @@ -#[macro_use] -extern crate serde_derive; - #[macro_use] mod util;