messaging.rs

  1use try_from::TryFrom;
  2use std::collections::BTreeMap;
  3
  4use plugin::PluginProxy;
  5use event::{Event, Priority, Propagation};
  6use error::Error;
  7use jid::Jid;
  8
  9use plugins::stanza::Message;
 10use xmpp_parsers::message::{MessagePayload, MessageType, Body};
 11use xmpp_parsers::chatstates::ChatState;
 12use xmpp_parsers::receipts::{Request, Received};
 13use xmpp_parsers::stanza_id::StanzaId;
 14
 15// TODO: use the id (maybe even stanza-id) to identify every message.
 16#[derive(Debug)]
 17pub struct MessageEvent {
 18    pub from: Jid,
 19    pub body: String,
 20    pub subject: Option<String>,
 21    pub thread: Option<String>,
 22}
 23
 24#[derive(Debug)]
 25pub struct ChatStateEvent {
 26    pub from: Jid,
 27    pub chat_state: ChatState,
 28}
 29
 30#[derive(Debug)]
 31pub struct ReceiptRequestEvent {
 32    pub from: Jid,
 33}
 34
 35#[derive(Debug)]
 36pub struct ReceiptReceivedEvent {
 37    pub from: Jid,
 38    pub id: String,
 39}
 40
 41#[derive(Debug)]
 42pub struct StanzaIdEvent {
 43    pub from: Jid,
 44    pub stanza_id: StanzaId,
 45    pub message: Message,
 46}
 47
 48impl Event for MessageEvent {}
 49impl Event for ChatStateEvent {}
 50impl Event for ReceiptRequestEvent {}
 51impl Event for ReceiptReceivedEvent {}
 52impl Event for StanzaIdEvent {}
 53
 54pub struct MessagingPlugin {
 55    proxy: PluginProxy,
 56}
 57
 58impl MessagingPlugin {
 59    pub fn new() -> MessagingPlugin {
 60        MessagingPlugin {
 61            proxy: PluginProxy::new(),
 62        }
 63    }
 64
 65    pub fn send_message(&self, to: &Jid, body: &str) -> Result<(), Error> {
 66        let message = Message {
 67            from: None,
 68            to: Some(to.clone()),
 69            type_: MessageType::Chat,
 70            id: Some(self.proxy.gen_id()),
 71            bodies: {
 72                let mut bodies = BTreeMap::new();
 73                bodies.insert(String::new(), Body(body.to_owned()));
 74                bodies
 75            },
 76            subjects: BTreeMap::new(),
 77            thread: None,
 78            payloads: vec!(),
 79        };
 80        self.proxy.send(message.into());
 81        Ok(())
 82    }
 83
 84    fn handle_message(&self, message: &Message) -> Propagation {
 85        let from = message.from.clone().unwrap_or(self.proxy.get_own_jid());
 86        for payload in message.payloads.clone() {
 87            let payload = match MessagePayload::try_from(payload) {
 88                Ok(payload) => payload,
 89                Err(err) => {
 90                    println!("MessagePayload: {:?}", err);
 91                    continue;
 92                }
 93            };
 94            match payload {
 95                // XEP-0085
 96                MessagePayload::ChatState(chat_state) => self.proxy.dispatch(ChatStateEvent {
 97                    from: from.clone(),
 98                    chat_state: chat_state,
 99                }),
100                // XEP-0184
101                MessagePayload::ReceiptRequest(Request) => self.proxy.dispatch(ReceiptRequestEvent {
102                    from: from.clone(),
103                }),
104                // XEP-0184
105                MessagePayload::ReceiptReceived(Received {id}) => self.proxy.dispatch(ReceiptReceivedEvent {
106                    from: from.clone(),
107                    id: id.unwrap(),
108                }),
109                // XEP-0359
110                MessagePayload::StanzaId(stanza_id) => self.proxy.dispatch(StanzaIdEvent {
111                    from: from.clone(),
112                    stanza_id: stanza_id,
113                    message: message.clone(),
114                }),
115                payload => println!("Unhandled payload: {:?}", payload),
116            }
117        }
118        if message.bodies.contains_key("") {
119            self.proxy.dispatch(MessageEvent {
120                from: from,
121                body: message.bodies[""].clone().0,
122                subject: if message.subjects.contains_key("") { Some(message.subjects[""].clone().0) } else { None },
123                thread: match message.thread.clone() { Some(thread) => Some(thread.0), None => None },
124            });
125        }
126        Propagation::Stop
127    }
128}
129
130impl_plugin!(MessagingPlugin, proxy, [
131    (Message, Priority::Default) => handle_message,
132]);