sync.rs 5.63 KB
Newer Older
1 2 3 4 5 6
use globals;
use std::thread;
use error::Error;
use util::json_q;
use util::get_rooms_from_json;
use util::get_rooms_timeline_from_json;
7
use util::get_rooms_notifies_from_json;
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
use util::parse_sync_events;
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", strn!("false")));

25 26
    let timeout;

27 28 29 30
    if since.is_empty() {
        let filter = format!("{{
            \"room\": {{
                \"state\": {{
31 32
                    \"types\": [\"m.room.*\"],
                    \"not_types\": [\"m.room.member\"]
33 34 35
                }},
                \"timeline\": {{
                    \"types\": [\"m.room.message\"],
36
                    \"limit\": {}
37 38 39 40 41 42 43 44 45
                }},
                \"ephemeral\": {{ \"types\": [] }}
            }},
            \"presence\": {{ \"types\": [] }},
            \"event_format\": \"client\",
            \"event_fields\": [\"type\", \"content\", \"sender\", \"event_id\", \"age\", \"unsigned\"]
        }}", globals::PAGE_LIMIT);

        params.push(("filter", strn!(filter)));
46
        params.push(("timeout", strn!("0")));
47
        timeout = 0;
48 49
    } else {
        params.push(("since", since.clone()));
50
        params.push(("timeout", strn!("30000")));
51
        timeout = 30;
52 53 54 55 56 57 58 59 60 61 62
    }

    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 || {
63
        match json_q("get", &url, &attrs, timeout) {
64 65 66
            Ok(r) => {
                let next_batch = String::from(r["next_batch"].as_str().unwrap_or(""));
                if since.is_empty() {
67
                    let rooms = match get_rooms_from_json(&r, &userid, &baseu) {
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
                        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 {
84 85 86 87 88 89
                    // 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(),
                    };

90
                    // Message events
91
                    match get_rooms_timeline_from_json(&baseu, &r, tk.clone(), since.clone()) {
92 93 94
                        Ok(msgs) => tx.send(BKResponse::RoomMessages(msgs)).unwrap(),
                        Err(err) => tx.send(BKResponse::RoomMessagesError(err)).unwrap(),
                    };
95
                    // Room notifications
96
                    match get_rooms_notifies_from_json(&r) {
97 98 99 100 101 102 103
                        Ok(notifies) => {
                            for (r, n, h) in notifies {
                                tx.send(BKResponse::RoomNotifications(r.clone(), n, h)).unwrap();
                            }
                        },
                        Err(_) => {}
                    };
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
                    // 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 = strn!(ev.content["name"].as_str().unwrap_or(""));
                                        tx.send(BKResponse::RoomName(ev.room.clone(), name)).unwrap();
                                    }
                                    "m.room.topic" => {
                                        let t = strn!(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();
                                    }
                                    _ => {
                                        println!("EVENT NOT MANAGED: {:?}", ev);
                                    }
                                }
                            }
                        }
                    };
                }

                tx.send(BKResponse::Sync(next_batch.clone())).unwrap();
                data.lock().unwrap().since = next_batch;
            },
            Err(err) => { tx.send(BKResponse::SyncError(err)).unwrap() }
        };
    });

    Ok(())
}

pub fn force_sync(bk: &Backend) -> Result<(), Error> {
    bk.data.lock().unwrap().since = String::from("");
    sync(bk)
}