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

Moar xmpp-parsers

See merge request !9
This commit is contained in:
lumi 2017-05-27 15:53:57 +00:00
commit 09280ca8df
3 changed files with 59 additions and 106 deletions

View file

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

View file

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

View file

@ -1,56 +1,9 @@
use std::collections::BTreeMap;
use error::Error; use error::Error;
use plugin::PluginProxy; use plugin::PluginProxy;
use minidom::Element; pub use xmpp_parsers::presence::{Presence, PresenceType as Type, Show};
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 struct PresencePlugin { pub struct PresencePlugin {
proxy: PluginProxy, proxy: PluginProxy,
@ -63,33 +16,24 @@ impl PresencePlugin {
} }
} }
pub fn set_presence(&self, show: Show, status: Option<String>) -> Result<(), Error> { pub fn set_presence(&self, type_: Type, show: Option<Show>, status: Option<String>) -> Result<(), Error> {
if show == Show::Unavailable { let presence = Presence {
self.proxy.send(Element::builder("presence") from: None,
.ns(ns::CLIENT) to: None,
.attr("type", "unavailable") id: None,
.build()); type_: type_,
} show: show,
else { priority: 0i8,
let mut stanza = Element::builder("presence") statuses: {
.ns(ns::CLIENT) let mut statuses = BTreeMap::new();
.build(); if let Some(status) = status {
if let Some(stat) = status { statuses.insert(String::new(), 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);
} }
statuses
},
payloads: vec!(),
};
self.proxy.send(presence.into());
Ok(()) Ok(())
} }
} }