xmpp: Add ChatMessage and GroupMessage events; API likely to change

Maxime “pep” Buquet created

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>

Change summary

xmpp-rs/examples/hello_bot.rs |  6 ++++++
xmpp-rs/src/lib.rs            | 33 +++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)

Detailed changes

xmpp-rs/examples/hello_bot.rs 🔗

@@ -51,6 +51,9 @@ async fn main() -> Result<(), Option<()>> {
                 Event::ContactChanged(contact) => {
                     println!("Contact {} changed.", contact.jid);
                 }
+                Event::ChatMessage(jid, body) => {
+                    println!("Message from {}: {}", jid, body.0);
+                }
                 Event::JoinRoom(jid, conference) => {
                     println!("Joining room {} ({:?})…", jid, conference.name);
                     client
@@ -78,6 +81,9 @@ async fn main() -> Result<(), Option<()>> {
                 Event::RoomLeft(jid) => {
                     println!("Left room {}.", jid);
                 }
+                Event::RoomMessage(jid, nick, body) => {
+                    println!("Message in room {} from {}: {}", jid, nick, body.0);
+                }
                 Event::AvatarRetrieved(jid, path) => {
                     println!("Received avatar for {} in {}.", jid, path);
                 }

xmpp-rs/src/lib.rs 🔗

@@ -65,6 +65,8 @@ pub enum ClientFeature {
     JoinRooms,
 }
 
+pub type RoomNick = String;
+
 #[derive(Debug)]
 pub enum Event {
     Online,
@@ -74,11 +76,13 @@ pub enum Event {
     ContactChanged(RosterItem),
     #[cfg(feature = "avatars")]
     AvatarRetrieved(Jid, String),
+    ChatMessage(BareJid, Body),
     JoinRoom(BareJid, Conference),
     LeaveRoom(BareJid),
     LeaveAllRooms,
     RoomJoined(BareJid),
     RoomLeft(BareJid),
+    RoomMessage(BareJid, RoomNick, Body),
 }
 
 #[derive(Default)]
@@ -87,6 +91,7 @@ pub struct ClientBuilder<'a> {
     password: &'a str,
     website: String,
     default_nick: String,
+    lang: Vec<String>,
     disco: (ClientType, String),
     features: Vec<ClientFeature>,
 }
@@ -98,6 +103,7 @@ impl ClientBuilder<'_> {
             password,
             website: String::from("https://gitlab.com/xmpp-rs/tokio-xmpp"),
             default_nick: String::from("xmpp-rs"),
+            lang: vec![String::from("en")],
             disco: (ClientType::default(), String::from("tokio-xmpp")),
             features: vec![],
         }
@@ -118,6 +124,11 @@ impl ClientBuilder<'_> {
         self
     }
 
+    pub fn set_lang(mut self, lang: Vec<String>) -> Self {
+        self.lang = lang;
+        self
+    }
+
     pub fn enable_feature(mut self, feature: ClientFeature) -> Self {
         self.features.push(feature);
         self
@@ -161,6 +172,7 @@ impl ClientBuilder<'_> {
         let agent = Agent {
             client,
             default_nick: Rc::new(RefCell::new(self.default_nick)),
+            lang: Rc::new(self.lang),
             disco,
             node,
         };
@@ -172,6 +184,7 @@ impl ClientBuilder<'_> {
 pub struct Agent {
     client: TokioXmppClient,
     default_nick: Rc<RefCell<String>>,
+    lang: Rc<Vec<String>>,
     disco: DiscoInfoResult,
     node: String,
 }
@@ -323,6 +336,26 @@ impl Agent {
                     } else if stanza.is("message", "jabber:client") {
                         let message = Message::try_from(stanza).unwrap();
                         let from = message.from.clone().unwrap();
+                        let langs: Vec<&str> = self.lang.iter().map(String::as_str).collect();
+                        match message.get_best_body(langs) {
+                            Some((_lang, body)) => match message.type_ {
+                                MessageType::Groupchat => {
+                                    let event = Event::RoomMessage(
+                                        from.clone().into(),
+                                        FullJid::try_from(from.clone()).unwrap().resource,
+                                        body.clone(),
+                                    );
+                                    events.push(event)
+                                }
+                                MessageType::Chat | MessageType::Normal => {
+                                    let event =
+                                        Event::ChatMessage(from.clone().into(), body.clone());
+                                    events.push(event)
+                                }
+                                _ => (),
+                            },
+                            None => (),
+                        }
                         for child in message.payloads {
                             if child.is("event", ns::PUBSUB_EVENT) {
                                 let new_events = pubsub::handle_event(&from, child, self).await;