Merge branch 'moar-xmpp-parsers' into 'master'

lumi created

Moar xmpp-parsers

See merge request !9

Change summary

examples/client.rs      |  6 +
src/plugins/ping.rs     | 61 ++++++++++++++-----------
src/plugins/presence.rs | 98 +++++++++---------------------------------
3 files changed, 59 insertions(+), 106 deletions(-)

Detailed changes

examples/client.rs 🔗

@@ -2,8 +2,9 @@ extern crate xmpp;
 
 use xmpp::jid::Jid;
 use xmpp::client::ClientBuilder;
+use xmpp::plugins::stanza::StanzaPlugin;
 use xmpp::plugins::messaging::{MessagingPlugin, MessageEvent};
-use xmpp::plugins::presence::{PresencePlugin, Show};
+use xmpp::plugins::presence::{PresencePlugin, Type};
 use xmpp::plugins::ping::{PingPlugin, PingEvent};
 
 use std::env;
@@ -15,10 +16,11 @@ fn main() {
                                    .password(pass)
                                    .connect()
                                    .unwrap();
+    client.register_plugin(StanzaPlugin::new());
     client.register_plugin(MessagingPlugin::new());
     client.register_plugin(PresencePlugin::new());
     client.register_plugin(PingPlugin::new());
-    client.plugin::<PresencePlugin>().set_presence(Show::Available, None).unwrap();
+    client.plugin::<PresencePlugin>().set_presence(Type::Available, None, None).unwrap();
     client.main().unwrap();
     /*loop {
         let event = client.next_event().unwrap();

src/plugins/ping.rs 🔗

@@ -1,14 +1,17 @@
+use std::convert::TryFrom;
+
 use plugin::PluginProxy;
-use event::{Event, Priority, Propagation, ReceiveElement};
-use minidom::Element;
+use event::{Event, Priority, Propagation};
 use error::Error;
 use jid::Jid;
-use ns;
+
+use plugins::stanza::Iq;
+use xmpp_parsers::iq::{IqType, IqPayload};
+use xmpp_parsers::ping::Ping;
 
 #[derive(Debug)]
 pub struct PingEvent {
     pub from: Jid,
-    pub to: Jid,
     pub id: String,
 }
 
@@ -26,39 +29,43 @@ impl PingPlugin {
     }
 
     pub fn send_ping(&self, to: &Jid) -> Result<(), Error> {
-        let mut elem = Element::builder("iq")
-                               .attr("type", "get")
-                               .attr("to", to.to_string())
-                               .build();
-        elem.append_child(Element::builder("ping").ns(ns::PING).build());
-        self.proxy.send(elem);
+        let to = to.clone();
+        self.proxy.send(Iq {
+            from: None,
+            to: Some(to),
+            // TODO: use a generic way to generate ids.
+            id: Some(String::from("id")),
+            payload: IqType::Get(IqPayload::Ping(Ping).into()),
+        }.into());
         Ok(())
     }
 
-    pub fn reply_ping(&self, event: &PingEvent) {
-        let reply = Element::builder("iq")
-                            .attr("type", "result")
-                            .attr("to", event.from.to_string())
-                            .attr("id", event.id.to_string())
-                            .build();
-        self.proxy.send(reply);
-    }
-
-    fn handle_receive_element(&self, evt: &ReceiveElement) -> Propagation {
-        let elem = &evt.0;
-        if elem.is("iq", ns::CLIENT) && elem.attr("type") == Some("get") {
-            if elem.has_child("ping", ns::PING) {
+    fn handle_iq(&self, iq: &Iq) -> Propagation {
+        let iq = iq.clone();
+        if let IqType::Get(payload) = iq.payload {
+            // TODO: use an intermediate plugin to parse this payload.
+            if let Ok(IqPayload::Ping(_)) = IqPayload::try_from(payload) {
                 self.proxy.dispatch(PingEvent { // TODO: safety!!!
-                    from: elem.attr("from").unwrap().parse().unwrap(),
-                    to: elem.attr("to").unwrap().parse().unwrap(),
-                    id: elem.attr("id").unwrap().parse().unwrap(),
+                    from: iq.from.unwrap(),
+                    id: iq.id.unwrap(),
                 });
             }
         }
         Propagation::Continue
     }
+
+    fn reply_ping(&self, ping: &PingEvent) -> Propagation {
+        self.proxy.send(Iq {
+            from: None,
+            to: Some(ping.from.to_owned()),
+            id: Some(ping.id.to_owned()),
+            payload: IqType::Result(None),
+        }.into());
+        Propagation::Continue
+    }
 }
 
 impl_plugin!(PingPlugin, proxy, [
-    (ReceiveElement, Priority::Default) => handle_receive_element,
+    (Iq, Priority::Default) => handle_iq,
+    (PingEvent, Priority::Default) => reply_ping,
 ]);

src/plugins/presence.rs 🔗

@@ -1,56 +1,9 @@
+use std::collections::BTreeMap;
+
 use error::Error;
 use plugin::PluginProxy;
 
-use minidom::Element;
-
-use ns;
-
-use std::fmt;
-
-use std::str::FromStr;
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum Show {
-    Available,
-    Away,
-    ExtendedAway,
-    DoNotDisturb,
-    Chat,
-    Unavailable,
-}
-
-impl fmt::Display for Show {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Show::Away => write!(fmt, "away"),
-            Show::ExtendedAway => write!(fmt, "xa"),
-            Show::DoNotDisturb => write!(fmt, "dnd"),
-            Show::Chat => write!(fmt, "chat"),
-
-            // will never be seen inside a <show>, maybe should crash?
-            Show::Available => write!(fmt, "available"),
-            Show::Unavailable => write!(fmt, "unavailable"),
-        }
-    }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub struct InvalidShow;
-
-impl FromStr for Show {
-    type Err = InvalidShow;
-
-    fn from_str(s: &str) -> Result<Show, InvalidShow> {
-        Ok(match s {
-            "away" => Show::Away,
-            "xa" => Show::ExtendedAway,
-            "dnd" => Show::DoNotDisturb,
-            "chat" => Show::Chat,
-
-            _ => { return Err(InvalidShow); }
-        })
-    }
-}
+pub use xmpp_parsers::presence::{Presence, PresenceType as Type, Show};
 
 pub struct PresencePlugin {
     proxy: PluginProxy,
@@ -63,33 +16,24 @@ impl PresencePlugin {
         }
     }
 
-    pub fn set_presence(&self, show: Show, status: Option<String>) -> Result<(), Error> {
-        if show == Show::Unavailable {
-            self.proxy.send(Element::builder("presence")
-                                    .ns(ns::CLIENT)
-                                    .attr("type", "unavailable")
-                                    .build());
-        }
-        else {
-            let mut stanza = Element::builder("presence")
-                                     .ns(ns::CLIENT)
-                                     .build();
-            if let Some(stat) = status {
-                let elem = Element::builder("status")
-                                   .ns(ns::CLIENT)
-                                   .append(stat)
-                                   .build();
-                stanza.append_child(elem);
-            }
-            let mut elem = Element::builder("show")
-                                   .ns(ns::CLIENT)
-                                   .build();
-            if show != Show::Available {
-                elem.append_text_node(show.to_string());
-            }
-            stanza.append_child(elem);
-            self.proxy.send(stanza);
-        }
+    pub fn set_presence(&self, type_: Type, show: Option<Show>, status: Option<String>) -> Result<(), Error> {
+        let presence = Presence {
+            from: None,
+            to: None,
+            id: None,
+            type_: type_,
+            show: show,
+            priority: 0i8,
+            statuses: {
+                let mut statuses = BTreeMap::new();
+                if let Some(status) = status {
+                    statuses.insert(String::new(), status);
+                }
+                statuses
+            },
+            payloads: vec!(),
+        };
+        self.proxy.send(presence.into());
         Ok(())
     }
 }