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::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();

View file

@ -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,
]);

View file

@ -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(())
}
}