diff --git a/examples/client.rs b/examples/client.rs index 49548b1..e5c4a9b 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -7,7 +7,7 @@ use xmpp::plugins::unhandled_iq::UnhandledIqPlugin; use xmpp::plugins::messaging::{MessagingPlugin, MessageEvent}; use xmpp::plugins::presence::{PresencePlugin, Type}; use xmpp::plugins::ibb::IbbPlugin; -use xmpp::plugins::ping::{PingPlugin, PingEvent}; +use xmpp::plugins::ping::PingPlugin; use xmpp::event::{Priority, Propagation}; use std::env; diff --git a/src/plugins/messaging.rs b/src/plugins/messaging.rs index 519d150..aa8001f 100644 --- a/src/plugins/messaging.rs +++ b/src/plugins/messaging.rs @@ -1,18 +1,55 @@ +use std::convert::TryFrom; +use std::collections::BTreeMap; + use plugin::PluginProxy; -use event::{Event, ReceiveElement, Priority, Propagation}; -use minidom::Element; +use event::{Event, Priority, Propagation}; use error::Error; use jid::Jid; -use ns; +use plugins::stanza::Message; +use xmpp_parsers::message::{MessagePayload, MessageType}; +use xmpp_parsers::chatstates::ChatState; +use xmpp_parsers::receipts::Receipt; +use xmpp_parsers::stanza_id::StanzaId; + +// TODO: use the id (maybe even stanza-id) to identify every message. #[derive(Debug)] pub struct MessageEvent { pub from: Jid, - pub to: Jid, pub body: String, + pub subject: Option, + pub thread: Option, +} + +#[derive(Debug)] +pub struct ChatStateEvent { + pub from: Jid, + pub chat_state: ChatState, +} + +#[derive(Debug)] +pub struct ReceiptRequestEvent { + pub from: Jid, +} + +#[derive(Debug)] +pub struct ReceiptReceivedEvent { + pub from: Jid, + pub id: String, +} + +#[derive(Debug)] +pub struct StanzaIdEvent { + pub from: Jid, + pub stanza_id: StanzaId, + pub message: Message, } impl Event for MessageEvent {} +impl Event for ChatStateEvent {} +impl Event for ReceiptRequestEvent {} +impl Event for ReceiptReceivedEvent {} +impl Event for StanzaIdEvent {} pub struct MessagingPlugin { proxy: PluginProxy, @@ -26,30 +63,71 @@ impl MessagingPlugin { } pub fn send_message(&self, to: &Jid, body: &str) -> Result<(), Error> { - let mut elem = Element::builder("message") - .attr("type", "chat") - .attr("to", to.to_string()) - .build(); - elem.append_child(Element::builder("body").append(body).build()); - self.proxy.send(elem); + let message = Message { + from: None, + to: Some(to.clone()), + type_: MessageType::Chat, + // TODO: always use an id. + id: None, + bodies: { + let mut bodies = BTreeMap::new(); + bodies.insert(String::new(), String::from(body)); + bodies + }, + subjects: BTreeMap::new(), + thread: None, + payloads: vec!(), + }; + self.proxy.send(message.into()); Ok(()) } - fn handle_receive_element(&self, evt: &ReceiveElement) -> Propagation { - let elem = &evt.0; - if elem.is("message", ns::CLIENT) && elem.attr("type") == Some("chat") { - if let Some(body) = elem.get_child("body", ns::CLIENT) { - self.proxy.dispatch(MessageEvent { // TODO: safety!!! - from: elem.attr("from").unwrap().parse().unwrap(), - to: elem.attr("to").unwrap().parse().unwrap(), - body: body.text(), - }); + fn handle_message(&self, message: &Message) -> Propagation { + let from = message.from.clone().unwrap(); + for payload in message.payloads.clone() { + let payload = match MessagePayload::try_from(payload) { + Ok(payload) => payload, + Err(err) => { + println!("MessagePayload: {:?}", err); + continue; + } + }; + match payload { + // XEP-0085 + MessagePayload::ChatState(chat_state) => self.proxy.dispatch(ChatStateEvent { + from: from.clone(), + chat_state: chat_state, + }), + // XEP-0184 + MessagePayload::Receipt(Receipt::Request) => self.proxy.dispatch(ReceiptRequestEvent { + from: from.clone(), + }), + // XEP-0184 + MessagePayload::Receipt(Receipt::Received(id)) => self.proxy.dispatch(ReceiptReceivedEvent { + from: from.clone(), + id: id.unwrap(), + }), + // XEP-0359 + MessagePayload::StanzaId(stanza_id) => self.proxy.dispatch(StanzaIdEvent { + from: from.clone(), + stanza_id: stanza_id, + message: message.clone(), + }), + payload => println!("Unhandled payload: {:?}", payload), } } - Propagation::Continue + if message.bodies.contains_key("") { + self.proxy.dispatch(MessageEvent { + from: from, + body: message.bodies[""].clone(), + subject: if message.subjects.contains_key("") { Some(message.subjects[""].clone()) } else { None }, + thread: message.thread.clone(), + }); + } + Propagation::Stop } } impl_plugin!(MessagingPlugin, proxy, [ - (ReceiveElement, Priority::Default) => handle_receive_element, + (Message, Priority::Default) => handle_message, ]);