You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
6.3 KiB
159 lines
6.3 KiB
use globals; |
|
use std::{thread, time}; |
|
use error::Error; |
|
use util::json_q; |
|
use util::get_rooms_from_json; |
|
use util::get_rooms_timeline_from_json; |
|
use util::get_rooms_notifies_from_json; |
|
use util::parse_sync_events; |
|
use util::parse_m_direct; |
|
use backend::types::BKResponse; |
|
use backend::types::Backend; |
|
use types::Room; |
|
|
|
pub fn sync(bk: &Backend) -> Result<(), Error> { |
|
let tk = bk.data.lock().unwrap().access_token.clone(); |
|
if tk.is_empty() { |
|
return Err(Error::BackendError); |
|
} |
|
|
|
let since = bk.data.lock().unwrap().since.clone(); |
|
let userid = bk.data.lock().unwrap().user_id.clone(); |
|
|
|
let mut params: Vec<(&str, String)> = vec![]; |
|
params.push(("full_state", String::from("false"))); |
|
|
|
let timeout; |
|
|
|
if since.is_empty() { |
|
let filter = format!("{{ |
|
\"room\": {{ |
|
\"state\": {{ |
|
\"types\": [\"m.room.*\"], |
|
\"not_types\": [\"m.room.member\"] |
|
}}, |
|
\"timeline\": {{ |
|
\"types\": [\"m.room.message\", \"m.sticker\"], |
|
\"limit\": {} |
|
}}, |
|
\"ephemeral\": {{ \"types\": [] }} |
|
}}, |
|
\"presence\": {{ \"types\": [] }}, |
|
\"event_format\": \"client\", |
|
\"event_fields\": [\"type\", \"content\", \"sender\", \"event_id\", \"age\", \"unsigned\"] |
|
}}", globals::PAGE_LIMIT); |
|
|
|
params.push(("filter", String::from(filter))); |
|
params.push(("timeout", String::from("0"))); |
|
timeout = 0; |
|
} else { |
|
params.push(("since", since.clone())); |
|
params.push(("timeout", String::from("30000"))); |
|
timeout = 30; |
|
} |
|
|
|
let baseu = bk.get_base_url()?; |
|
let url = bk.url("sync", params)?; |
|
|
|
let tx = bk.tx.clone(); |
|
let data = bk.data.clone(); |
|
|
|
let attrs = json!(null); |
|
|
|
thread::spawn(move || { |
|
match json_q("get", &url, &attrs, timeout) { |
|
Ok(r) => { |
|
let next_batch = String::from(r["next_batch"].as_str().unwrap_or("")); |
|
if since.is_empty() { |
|
data.lock().unwrap().m_direct = parse_m_direct(&r); |
|
|
|
let rooms = match get_rooms_from_json(&r, &userid, &baseu) { |
|
Ok(rs) => rs, |
|
Err(err) => { |
|
tx.send(BKResponse::SyncError(err)).unwrap(); |
|
vec![] |
|
} |
|
}; |
|
|
|
let mut def: Option<Room> = None; |
|
let jtr = data.lock().unwrap().join_to_room.clone(); |
|
if !jtr.is_empty() { |
|
if let Some(r) = rooms.iter().find(|x| x.id == jtr) { |
|
def = Some(r.clone()); |
|
} |
|
} |
|
tx.send(BKResponse::Rooms(rooms, def)).unwrap(); |
|
} else { |
|
// New rooms |
|
match get_rooms_from_json(&r, &userid, &baseu) { |
|
Ok(rs) => tx.send(BKResponse::NewRooms(rs)).unwrap(), |
|
Err(err) => tx.send(BKResponse::SyncError(err)).unwrap(), |
|
}; |
|
|
|
// Message events |
|
match get_rooms_timeline_from_json(&baseu, &r, tk.clone(), since.clone()) { |
|
Ok(msgs) => tx.send(BKResponse::RoomMessages(msgs)).unwrap(), |
|
Err(err) => tx.send(BKResponse::RoomMessagesError(err)).unwrap(), |
|
}; |
|
// Room notifications |
|
match get_rooms_notifies_from_json(&r) { |
|
Ok(notifies) => { |
|
for (r, n, h) in notifies { |
|
tx.send(BKResponse::RoomNotifications(r.clone(), n, h)).unwrap(); |
|
} |
|
}, |
|
Err(_) => {} |
|
}; |
|
// Other events |
|
match parse_sync_events(&r) { |
|
Err(err) => tx.send(BKResponse::SyncError(err)).unwrap(), |
|
Ok(events) => { |
|
for ev in events { |
|
match ev.stype.as_ref() { |
|
"m.room.name" => { |
|
let name = String::from(ev.content["name"].as_str().unwrap_or("")); |
|
tx.send(BKResponse::RoomName(ev.room.clone(), name)).unwrap(); |
|
} |
|
"m.room.topic" => { |
|
let t = String::from(ev.content["topic"].as_str().unwrap_or("")); |
|
tx.send(BKResponse::RoomTopic(ev.room.clone(), t)).unwrap(); |
|
} |
|
"m.room.avatar" => { |
|
tx.send(BKResponse::NewRoomAvatar(ev.room.clone())).unwrap(); |
|
} |
|
"m.room.member" => { |
|
tx.send(BKResponse::RoomMemberEvent(ev)).unwrap(); |
|
} |
|
"m.sticker" => { |
|
// This event is managed in the room list |
|
} |
|
_ => { |
|
eprintln!("EVENT NOT MANAGED: {:?}", ev); |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
} |
|
|
|
tx.send(BKResponse::Sync(next_batch.clone())).unwrap(); |
|
data.lock().unwrap().since = next_batch; |
|
}, |
|
Err(err) => { |
|
// we wait if there's an error to avoid 100% CPU |
|
eprintln!("Sync Error, waiting 10 seconds to respond for the next sync"); |
|
let ten_seconds = time::Duration::from_millis(10000); |
|
thread::sleep(ten_seconds); |
|
|
|
tx.send(BKResponse::SyncError(err)).unwrap(); |
|
} |
|
}; |
|
}); |
|
|
|
Ok(()) |
|
} |
|
|
|
pub fn force_sync(bk: &Backend) -> Result<(), Error> { |
|
bk.data.lock().unwrap().since = String::from(""); |
|
sync(bk) |
|
}
|
|
|