crackle_lib/
lib.rs

1use ruma::events::*;
2pub use ruma::{
3    api::client::sync::sync_events::v3::Response, OwnedEventId, OwnedRoomAliasId, OwnedRoomId,
4    OwnedRoomName, OwnedServerName, OwnedUserId, RoomAliasId, RoomId, RoomName, ServerName, UserId,
5};
6//use serde::{Deserialize, Serialize};
7//use serde_json::{json, Value};
8use std::collections::BTreeMap;
9use std::time::Duration;
10//use ureq::{Agent, AgentBuilder, OrAnyStatus};
11//use uuid::Uuid;
12const TIMEOUT: Duration = Duration::from_secs(3);
13
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct UserInfo {
16    pub user_id: OwnedUserId,
17    //rooms: Vec<OwnedRoomId>,
18    pub display_name_in_room: BTreeMap<OwnedRoomId, String>,
19}
20
21impl UserInfo {
22    pub fn new(user_id: OwnedUserId) -> Self {
23        Self {
24            user_id: user_id,
25            display_name_in_room: BTreeMap::new(),
26        }
27    }
28    pub fn get_name_string(&self, room_id: OwnedRoomId) -> String {
29        if self.display_name_in_room.contains_key(&room_id) {
30            self.display_name_in_room[&room_id].clone()
31        } else {
32            self.user_id.to_string()
33        }
34    }
35    pub fn set_display_name_in_room(&mut self, room_id: OwnedRoomId, name: impl Into<String>) {
36        self.display_name_in_room.insert(room_id, name.into());
37    }
38}
39
40#[derive(Clone, Debug, Default, Eq, PartialEq)]
41pub struct StorageData {
42    pub auth_token: String,
43    pub room_to_aliases: BTreeMap<OwnedRoomId, Vec<OwnedRoomAliasId>>,
44    pub alias_to_room: BTreeMap<OwnedRoomAliasId, OwnedRoomId>,
45    pub joined_rooms: Vec<OwnedRoomId>,
46    pub room_id_to_cananoical_alias: BTreeMap<OwnedRoomId, OwnedRoomAliasId>,
47    pub room_to_name: BTreeMap<OwnedRoomId, OwnedRoomName>,
48    pub room_to_direct_name: BTreeMap<OwnedRoomId, String>,
49    pub recent_event_ids: Vec<OwnedEventId>,
50    pub last_sent_messages: Vec<(OwnedRoomId, String)>,
51    pub room_userid: BTreeMap<OwnedUserId, UserInfo>,
52    pub room_id_user_list: BTreeMap<OwnedRoomId, Vec<OwnedUserId>>,
53}
54/*
55#[derive(Clone, Debug, Serialize, Deserialize, Default)]
56pub struct Response {
57    /// The batch token to supply in the `since` param of the next `/sync` request.
58    pub next_batch: String,
59
60    /// Updates to rooms.
61    #[serde(default, skip_serializing_if = "Rooms::is_empty")]
62    pub rooms: Rooms,
63
64    /// Updates to the presence status of other users.
65    #[serde(default, skip_serializing_if = "Presence::is_empty")]
66    pub presence: Presence,
67
68    /// The global private data created by this user.
69    #[serde(default, skip_serializing_if = "GlobalAccountData::is_empty")]
70    pub account_data: GlobalAccountData,
71
72    /// Messages sent directly between devices.
73    #[serde(default, skip_serializing_if = "ToDevice::is_empty")]
74    pub to_device: ToDevice,
75
76    /// Information on E2E device updates.
77    ///
78    /// Only present on an incremental sync.
79    #[serde(default, skip_serializing_if = "DeviceLists::is_empty")]
80    pub device_lists: DeviceLists,
81
82    /// For each key algorithm, the number of unclaimed one-time keys
83    /// currently held on the server for a device.
84    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
85    pub device_one_time_keys_count: BTreeMap<DeviceKeyAlgorithm, UInt>,
86
87    /// For each key algorithm, the number of unclaimed one-time keys
88    /// currently held on the server for a device.
89    ///
90    /// The presence of this field indicates that the server supports
91    /// fallback keys.
92    #[serde(rename = "org.matrix.msc2732.device_unused_fallback_key_types")]
93    pub device_unused_fallback_key_types: Option<Vec<DeviceKeyAlgorithm>>,
94}*/
95#[allow(dead_code)]
96#[derive(Debug, Clone)]
97pub struct Client {
98    client: ruma::Client<ruma::client::http_client::Reqwest>,
99    pub me: OwnedUserId,
100    since: Option<String>,
101    host: String,
102    pub data: StorageData,
103    room_list_updated: bool,
104}
105pub enum Authentication {
106    Password(String),
107    AuthToken(String),
108}
109impl Client {
110    pub async fn new(
111        host: impl Into<String>,
112        username: impl Into<String>,
113        server_name: impl Into<String>,
114        authentication: Authentication,
115    ) -> Self {
116        let good_host = Self::get_correct_host(host.into().trim_end_matches("/").to_string()).await;
117        let mut me = UserId::parse_with_server_name(
118            username.into(),
119            &ruma::ServerName::parse(server_name.into()).unwrap(),
120        )
121        .unwrap();
122        let client = match authentication {
123            Authentication::Password(x) => {
124                let c = ruma::Client::builder()
125                    .homeserver_url(good_host.clone())
126                    .build()
127                    .await
128                    .unwrap();
129                c.log_in(me.clone().as_str(), x.as_str(), None, None)
130                    .await
131                    .unwrap();
132                c
133            }
134            Authentication::AuthToken(x) => ruma::Client::builder()
135                .homeserver_url(good_host.clone())
136                .access_token(Some(x))
137                .build()
138                .await
139                .unwrap(),
140        };
141        me = client
142            .send_request(ruma::api::client::account::whoami::v3::Request::new())
143            .await
144            .unwrap()
145            .user_id;
146        Self {
147            client: client,
148            host: good_host, //host.into().trim_end_matches("/").to_string(),
149            me: me,          /*UserId::parse_with_server_name(
150                                 username.into(),
151                                 &*ruma::ServerName::parse(server_name.into()).unwrap(),
152                             )
153                             .unwrap(),
154                             agent: AgentBuilder::new()
155                                 .timeout_read(Duration::from_secs(3))
156                                 .build(),
157                             */
158            since: None,
159            data: StorageData::default(),
160            room_list_updated: false,
161        }
162    }
163    pub fn room_list_updated(&mut self) -> bool {
164        if self.room_list_updated {
165            self.room_list_updated = false;
166            return true;
167        }
168        false
169    }
170    pub async fn get_correct_host(host: String) -> String {
171        let should_req_well_known = match host.split(":").last().unwrap().parse::<usize>() {
172            Ok(port) => {
173                if port != 443 {
174                    false
175                } else {
176                    true
177                }
178            }
179            Err(_) => true,
180        };
181        let mut correct_host = host.clone();
182        if should_req_well_known {
183            if let Ok(z) = ruma::client::http_client::Reqwest::new()
184                .get(&format!("{correct_host}/.well-known/matrix/client"))
185                .send()
186                .await
187            //ureq::get(&format!("{}/.well-known/matrix/client", self.host.clone())).call()
188            {
189                let resp: serde_json::Value =
190                    serde_json::from_str(&z.text().await.unwrap()).unwrap();
191                let base_url: String = resp["m.homeserver"]["base_url"]
192                    .as_str()
193                    .unwrap()
194                    .to_string();
195                correct_host = base_url.trim_end_matches("/").to_string();
196            }
197        }
198        correct_host
199    }
200    /*
201    pub fn login(&mut self, password: String) -> Result<(), Value> {
202        let should_req_well_known = match self.host.split(":").last().unwrap().parse::<usize>() {
203            Ok(port) => {
204                if port != 443 {
205                    false
206                } else {
207                    true
208                }
209            }
210            Err(_) => true,
211        };
212        if should_req_well_known {
213            if let Ok(z) =
214                ureq::get(&format!("{}/.well-known/matrix/client", self.host.clone())).call()
215            {
216                let resp: Value = z.into_json().unwrap();
217                let base_url: String = resp["m.homeserver"]["base_url"]
218                    .as_str()
219                    .unwrap()
220                    .to_string();
221                self.host = base_url.trim_end_matches("/").to_string();
222            }
223        }
224        let content = json!({
225            "type": "m.login.password",
226            "identifier": {
227                "type": "m.id.user",
228                "user": self.me.localpart()
229            },
230            "password": password
231        });
232        let val: Value = self
233            .post_r0("login", content, None)
234            .unwrap()
235            .into_json()
236            .unwrap();
237        //println!("{:#}", val);
238        if !val.clone().as_object().unwrap().contains_key("auth_token") {
239            return Err(val);
240        }
241        self.data.auth_token = val["access_token"].as_str().unwrap().to_string();
242        self.me = OwnedUserId::try_from(val["user_id"].as_str().unwrap()).unwrap();
243        Ok(())
244    }
245    */
246    pub fn get_me(&self) -> OwnedUserId {
247        self.me.clone()
248    }
249    /*
250    fn post(
251        &self,
252        url_ext: impl Into<String>,
253        content: Value,
254        query_pairs: Option<Vec<(String, String)>>,
255    ) -> Result<ureq::Response, ureq::Transport> {
256        let mut r = self
257            .agent
258            .post(format!("{}{}{}", self.host, BASE, url_ext.into()).as_str())
259            .set(
260                "Authorization",
261                format!("Bearer {}", self.data.auth_token).as_str(),
262            );
263        if let Some(pairs) = query_pairs {
264            for pair in pairs {
265                r = r.query(pair.0.as_str(), pair.1.as_str());
266            }
267        }
268        //let x = r.send_json(content).or_any_status();
269        //println!("{:#?}", x);
270        //x
271        let mut resp = r.clone().send_json(content.clone()).or_any_status();
272        while let Err(_e) = resp {
273            resp = r.clone().send_json(content.clone()).or_any_status();
274            //eprintln!("{}", e);
275        }
276        resp
277    }
278
279    fn post_r0(
280        &self,
281        url_ext: impl Into<String>,
282        content: Value,
283        query_pairs: Option<Vec<(String, String)>>,
284    ) -> Result<ureq::Response, ureq::Transport> {
285        let mut r = self
286            .agent
287            .post(
288                format!(
289                    "{}{}{}",
290                    self.host,
291                    BASE.replace("v3", "r0"),
292                    url_ext.into()
293                )
294                .as_str(),
295            )
296            .set(
297                "Authorization",
298                format!("Bearer {}", self.data.auth_token).as_str(),
299            );
300        if let Some(pairs) = query_pairs {
301            for pair in pairs {
302                r = r.query(pair.0.as_str(), pair.1.as_str());
303            }
304        }
305        //let x = r.send_json(content).or_any_status();
306        //println!("{:#?}", x);
307        //x
308        let mut resp = r.clone().send_json(content.clone()).or_any_status();
309        while let Err(_e) = resp {
310            resp = r.clone().send_json(content.clone()).or_any_status();
311            //eprintln!("{}", e);
312        }
313        resp
314    }
315    fn put(
316        &self,
317        url_ext: impl Into<String>,
318        content: Value,
319        query_pairs: Option<Vec<(String, String)>>,
320    ) -> Result<ureq::Response, ureq::Transport> {
321        let mut r = self
322            .agent
323            .put(format!("{}{}{}", self.host, BASE, url_ext.into()).as_str())
324            .set(
325                "Authorization",
326                format!("Bearer {}", self.data.auth_token).as_str(),
327            );
328        if let Some(pairs) = query_pairs {
329            for pair in pairs {
330                r = r.query(pair.0.as_str(), pair.1.as_str());
331            }
332        }
333
334        let mut resp = r.clone().send_json(content.clone()).or_any_status();
335        while let Err(_e) = resp {
336            resp = r.clone().send_json(content.clone()).or_any_status();
337            //eprintln!("{}", e);
338        }
339        resp
340    }
341    fn get(
342        &self,
343        url_ext: impl Into<String>,
344        query_pairs: Option<Vec<(String, String)>>,
345    ) -> Result<ureq::Response, ureq::Transport> {
346        let mut r = self
347            .agent
348            .get(format!("{}{}{}", self.host, BASE, url_ext.into()).as_str())
349            .set(
350                "Authorization",
351                format!("Bearer {}", self.data.auth_token).as_str(),
352            );
353        if let Some(pairs) = query_pairs {
354            for pair in pairs {
355                r = r.query(pair.0.as_str(), pair.1.as_str());
356            }
357        }
358        let mut resp = r.clone().call().or_any_status();
359        while let Err(_e) = resp {
360            resp = r.clone().call().or_any_status();
361            //eprintln!("{}", e);
362        }
363        //println!("{:#?}", resp);
364        resp
365    }
366    pub fn join_room_id(&self, room_id: OwnedRoomId) -> Value {
367        let rid = room_id.to_string();
368        let room = urlencoding::encode(rid.as_str());
369        let content = json!({});
370        self.post(format!("rooms/{}/join", room).as_str(), content, None)
371            .unwrap()
372            .into_json()
373            .unwrap()
374    }
375    */
376    pub async fn join_room_id(
377        &self,
378        room_id: OwnedRoomId,
379    ) -> ruma::api::client::membership::join_room_by_id::v3::Response {
380        self.client
381            .send_request(
382                ruma::api::client::membership::join_room_by_id::v3::Request::new(&room_id),
383            )
384            .await
385            .unwrap()
386    }
387    pub async fn sync(&mut self) -> Result<Response, ()> {
388        //let since: Option<&'a str>;
389        //since = Some(self.since.unwrap().as_str())
390        /*
391        if let Some(start) = self.since.clone() {
392            since = Some(&start);
393        } else {
394            since = None;
395        }
396        */
397        let mut req = ruma::api::client::sync::sync_events::v3::Request::new();
398        req.filter = None;
399        req.since = match self.since {
400            Some(ref x) => Some(x),
401            None => None,
402        };
403        req.full_state = self.since.clone().is_none();
404        //set_presence: &PresenceState::Online,
405        req.timeout = Some(TIMEOUT);
406        if let Ok(res) = self.client.send_request(req).await {
407            self.since = Some(res.clone().next_batch);
408            return Ok(res);
409        } else {
410            return Err(());
411        }
412    }
413    /*
414    pub fn sync(&mut self) -> Result<Response, Value> {
415        let req: ureq::Response;
416        if let Some(start) = self.since.clone() {
417            req = self
418                .get(
419                    "sync",
420                    Some(vec![
421                        ("since".to_string(), start),
422                        ("full_state".to_string(), "false".to_string()),
423                        (
424                            "set_presence".to_string(),
425                            format!("{}", PresenceState::Online),
426                        ),
427                        ("timeout".to_string(), "3000".to_string()),
428                    ]),
429                )
430                .unwrap();
431        } else {
432            req = self
433                .get(
434                    "sync",
435                    Some(vec![
436                        ("full_state".to_string(), "true".to_string()),
437                        (
438                            "set_presence".to_string(),
439                            format!("{}", PresenceState::Online),
440                        ),
441                        ("timeout".to_string(), "3000".to_string()),
442                    ]),
443                )
444                .unwrap();
445        }
446        let val: Value = req.into_json().unwrap();
447        if val.clone().as_object().unwrap().contains_key("error") {
448            Err(val)
449        } else {
450            let x: Response = serde_json::from_str::<Raw<Response>>(val.to_string().as_str())
451                .unwrap()
452                .deserialize()
453                .unwrap();
454            self.since = Some(x.clone().next_batch);
455            Ok(x)
456        }
457    }
458    */
459    pub async fn join_with_alias(&self, alias: impl Into<String>) {
460        let room_alias = alias.into();
461        self.join_room_id(self.room_id_from_alias(room_alias).await)
462            .await;
463    }
464    /*
465    pub fn join_with_alias(&self, alias: impl Into<String>) {
466        let room_alias = alias.into();
467        let this_room_id_val: Value = self
468            .get(
469                format!(
470                    "directory/room/{}",
471                    urlencoding::encode(room_alias.as_str())
472                        .to_string()
473                        .as_str()
474                )
475                None,
476            )
477            .unwrap()
478            .into_json()
479            .unwrap();
480        let room_id =
481            OwnedRoomId::try_from(this_room_id_val["room_id"].as_str().unwrap()).unwrap();
482        self.join_room_id(room_id);
483    }
484    pub fn leave_room_id(&mut self, room_id: OwnedRoomId) -> Value {
485        let rid = room_id.to_string();
486        let room = urlencoding::encode(rid.as_str());
487        let content = json!({});
488        let output = self
489            .post(format!("rooms/{}/leave", room).as_str(), content, None)
490            .unwrap()
491            .into_json()
492            .unwrap();
493        self.data.joined_rooms.retain(|x| x != &room_id);
494        self.room_list_updated = true;
495        output
496    }
497    */
498    pub async fn leave_room_id(
499        &mut self,
500        room_id: OwnedRoomId,
501    ) -> ruma::api::client::membership::leave_room::v3::Response {
502        let resp = self
503            .client
504            .send_request(ruma::api::client::membership::leave_room::v3::Request::new(
505                &room_id,
506            ))
507            .await
508            .unwrap();
509        self.data.joined_rooms.retain(|x| x != &room_id);
510        self.room_list_updated = true;
511        resp
512    }
513    /*
514    pub fn room_id_from_alias(&self, alias: impl Into<String>) -> OwnedRoomId {
515        let room_alias = alias.into();
516        let this_room_id_val: Value = self
517            .get(
518                format!(
519                    "directory/room/{}",
520                    urlencoding::encode(room_alias.as_str())
521                        .to_string()
522                        .as_str()
523                ),
524                None,
525            )
526            .unwrap()
527            .into_json()
528            .unwrap();
529        OwnedRoomId::try_from(this_room_id_val["room_id"].as_str().unwrap()).unwrap()
530    }
531    */
532    pub async fn room_id_from_alias(&self, alias: impl Into<String>) -> OwnedRoomId {
533        let room_alias_string = alias.into();
534        let room_alias = RoomAliasId::parse(room_alias_string.as_str()).unwrap();
535        self.client
536            .send_request(ruma::api::client::alias::get_alias::v3::Request::new(
537                &room_alias,
538            ))
539            .await
540            .unwrap()
541            .room_id
542    }
543    /*
544    pub fn send_message(&mut self, room_id: OwnedRoomId, message: impl Into<String>) {
545        let msg = message.into();
546        let txid = Uuid::new_v4()
547            .to_simple()
548            .encode_lower(&mut Uuid::encode_buffer())
549            .to_string();
550        self.put(
551            format!("rooms/{}/send/m.room.message/{}", room_id.clone(), txid).as_str(),
552            json!({"body": msg, "msgtype": "m.text"}),
553            None,
554        )
555        .unwrap();
556        self.data.last_sent_messages.push((room_id.clone(), msg));
557    }
558    */
559    pub async fn send_message(
560        &mut self,
561        room_id: OwnedRoomId,
562        message: impl Into<String>,
563    ) -> ruma::api::client::message::send_message_event::v3::Response {
564        let msg = message.into();
565        let resp = self
566            .client
567            .send_request(
568                ruma::api::client::message::send_message_event::v3::Request::new(
569                    &room_id,
570                    &ruma::TransactionId::new(),
571                    &ruma::events::room::message::RoomMessageEventContent::text_plain(msg.clone()),
572                )
573                .unwrap(),
574            )
575            .await
576            .unwrap();
577        self.data.last_sent_messages.push((room_id.clone(), msg));
578        resp
579    }
580    pub fn extract_data(&mut self, sync_results: Response) -> Vec<MessageInfo> {
581        let mut messages: Vec<MessageInfo> = Vec::new();
582        let x = sync_results.rooms.join;
583        for (room_id, joined_room) in x.iter() {
584            if !self.data.joined_rooms.contains(room_id) {
585                self.data.joined_rooms.push(room_id.clone());
586                self.data
587                    .room_id_user_list
588                    .insert(room_id.clone(), Vec::new());
589                self.room_list_updated = true;
590            }
591            let mut room_members: Vec<String> = Vec::new();
592            let mut is_direct = false;
593            for event in joined_room.state.events.clone() {
594                if let Ok(ev) = event.deserialize() {
595                    if let ruma::events::AnySyncStateEvent::RoomAliases(SyncStateEvent::Original(
596                        room_aliases_event,
597                    )) = ev.clone()
598                    {
599                        let aliases = room_aliases_event.content.aliases;
600                        for alias in aliases {
601                            if !self.data.alias_to_room.contains_key(&alias) {
602                                self.data
603                                    .alias_to_room
604                                    .insert(alias.clone(), room_id.clone());
605                            }
606                            if !self.data.room_to_aliases.contains_key(room_id) {
607                                self.data
608                                    .room_to_aliases
609                                    .insert(room_id.clone(), vec![alias]);
610                            } else {
611                                if !self.data.room_to_aliases[room_id].contains(&alias) {
612                                    let mut current = self.data.room_to_aliases[room_id].clone();
613                                    current.push(alias.clone());
614                                    self.data.room_to_aliases.insert(room_id.clone(), current);
615                                }
616                            }
617                        }
618                    }
619                    if let ruma::events::AnySyncStateEvent::RoomName(SyncStateEvent::Original(
620                        room_name_event,
621                    )) = ev.clone()
622                    {
623                        if let Some(room_name) = room_name_event.content.name {
624                            self.data
625                                .room_to_name
626                                .insert(room_id.clone(), room_name.into());
627                        }
628                    } else if let ruma::events::AnySyncStateEvent::RoomCanonicalAlias(
629                        SyncStateEvent::Original(room_canonical_alias_event),
630                    ) = ev.clone()
631                    {
632                        if let Some(alias) = room_canonical_alias_event.content.alias {
633                            self.data
634                                .room_id_to_cananoical_alias
635                                .insert(room_id.clone(), alias);
636                        }
637                    } else if let ruma::events::AnySyncStateEvent::RoomMember(
638                        SyncStateEvent::Original(room_member_event),
639                    ) = ev.clone()
640                    {
641                        self.room_list_updated = true;
642                        let state_key_userid = UserId::parse(ev.state_key()).unwrap();
643                        if !self.data.room_userid.contains_key(&state_key_userid) {
644                            self.data.room_userid.insert(
645                                state_key_userid.clone(),
646                                UserInfo::new(state_key_userid.clone()),
647                            );
648                        }
649                        if let Some(display_name) = room_member_event.content.displayname {
650                            room_members.push(display_name.clone());
651                            let mut user_info = self
652                                .data
653                                .room_userid
654                                .get(&state_key_userid)
655                                .unwrap()
656                                .clone();
657                            user_info.set_display_name_in_room(room_id.clone(), display_name);
658                            self.data
659                                .room_userid
660                                .insert(state_key_userid.clone(), user_info);
661                        }
662                        if let Some(direct) = room_member_event.content.is_direct {
663                            if !is_direct && direct == true {
664                                room_members.pop();
665                                is_direct = true;
666                            }
667                        }
668                        if let ruma::events::room::member::MembershipState::Join =
669                            room_member_event.content.membership
670                        {
671                            let mut user_list =
672                                self.data.room_id_user_list.get(room_id).unwrap().clone();
673                            user_list.push(state_key_userid.clone());
674                            self.data
675                                .room_id_user_list
676                                .insert(room_id.clone(), user_list);
677                        } else if let ruma::events::room::member::MembershipState::Leave =
678                            room_member_event.content.membership
679                        {
680                            let mut user_list =
681                                self.data.room_id_user_list.get(room_id).unwrap().clone();
682                            user_list.retain(|x| x != &state_key_userid.clone());
683                            self.data
684                                .room_id_user_list
685                                .insert(room_id.clone(), user_list);
686                        } else if let ruma::events::room::member::MembershipState::Ban =
687                            room_member_event.content.membership
688                        {
689                            let mut user_list =
690                                self.data.room_id_user_list.get(room_id).unwrap().clone();
691                            user_list.retain(|x| x != &state_key_userid.clone());
692                            self.data
693                                .room_id_user_list
694                                .insert(room_id.clone(), user_list);
695                        }
696                    }
697                }
698            }
699            if is_direct {
700                if room_members.len() > 0 {
701                    self.data
702                        .room_to_direct_name
703                        .insert(room_id.clone(), room_members[0].clone());
704                }
705            }
706            for message_info in joined_room.timeline.events.iter().filter_map(|m| {
707                if let Ok(ruma::events::AnySyncRoomEvent::MessageLike(message_event)) =
708                    m.deserialize_as()
709                {
710                    let msg_event_id = Box::new(message_event.event_id().to_owned());
711                    if self.data.recent_event_ids.contains(&msg_event_id) {
712                        return None;
713                    }
714                    if !self.data.recent_event_ids.contains(&msg_event_id) {
715                        self.data.recent_event_ids.push(*msg_event_id);
716                    }
717                    if self.data.recent_event_ids.len() > 500 {
718                        self.data.recent_event_ids.remove(0);
719                    }
720                    if let AnySyncMessageLikeEvent::RoomMessage(SyncMessageLikeEvent::Original(
721                        room_message,
722                    )) = message_event
723                    {
724                        let sender = room_message.sender;
725                        let message: String;
726                        let mut is_emote: bool = false;
727                        if let room::message::MessageType::Text(text_message_event_content) =
728                            room_message.content.msgtype
729                        {
730                            message = text_message_event_content.body;
731                            //is_emote = false;
732                        } else if let room::message::MessageType::Emote(
733                            emote_message_event_content,
734                        ) = room_message.content.msgtype
735                        {
736                            message = emote_message_event_content.body;
737                            is_emote = true;
738                        } else if let room::message::MessageType::Notice(
739                            notice_message_event_content,
740                        ) = room_message.content.msgtype
741                        {
742                            message = notice_message_event_content.body;
743                        } else {
744                            return None;
745                        }
746                        if sender == self.me {
747                            //return None;
748                            let look_for = &(room_id.clone(), message.clone());
749                            if self.data.last_sent_messages.contains(&look_for) {
750                                self.data.last_sent_messages.retain(|q| q != look_for);
751                                return None;
752                            }
753                        }
754                        return Some(MessageInfo {
755                            message: message.clone(),
756                            sender: sender,
757                            room_id: room_id.clone(),
758                            is_emote: is_emote,
759                        });
760                    }
761                }
762                None
763            }) {
764                messages.push(message_info);
765            }
766        }
767        messages
768    }
769}
770
771pub struct MessageInfo {
772    pub room_id: OwnedRoomId,
773    pub sender: OwnedUserId,
774    pub message: String,
775    pub is_emote: bool,
776}