mod.rs

  1// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use super::Agent;
  8use crate::Event;
  9use std::str::FromStr;
 10use tokio_xmpp::parsers::{
 11    bookmarks2::{self, Autojoin},
 12    ns,
 13    pubsub::event::PubSubEvent,
 14    pubsub::pubsub::PubSub,
 15    BareJid, Element, Jid,
 16};
 17
 18#[cfg(feature = "avatars")]
 19pub(crate) mod avatar;
 20
 21pub(crate) async fn handle_event(from: &Jid, elem: Element, agent: &mut Agent) -> Vec<Event> {
 22    let mut events = Vec::new();
 23    let event = PubSubEvent::try_from(elem);
 24    trace!("PubSub event: {:#?}", event);
 25    match event {
 26        Ok(PubSubEvent::PublishedItems { node, items }) => {
 27            match node.0 {
 28                #[cfg(feature = "avatars")]
 29                ref node if node == ns::AVATAR_METADATA => {
 30                    let new_events =
 31                        avatar::handle_metadata_pubsub_event(&from, agent, items).await;
 32                    events.extend(new_events);
 33                }
 34                ref node if node == ns::BOOKMARKS2 => {
 35                    // TODO: Check that our bare JID is the sender.
 36                    assert_eq!(items.len(), 1);
 37                    let item = items.clone().pop().unwrap();
 38                    let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
 39                    let payload = item.payload.clone().unwrap();
 40                    match bookmarks2::Conference::try_from(payload) {
 41                        Ok(conference) => {
 42                            if conference.autojoin == Autojoin::True {
 43                                events.push(Event::JoinRoom(jid, conference));
 44                            } else {
 45                                events.push(Event::LeaveRoom(jid));
 46                            }
 47                        }
 48                        Err(err) => println!("not bookmark: {}", err),
 49                    }
 50                }
 51                ref node => unimplemented!("node {}", node),
 52            }
 53        }
 54        Ok(PubSubEvent::RetractedItems { node, items }) => {
 55            match node.0 {
 56                ref node if node == ns::BOOKMARKS2 => {
 57                    // TODO: Check that our bare JID is the sender.
 58                    assert_eq!(items.len(), 1);
 59                    let item = items.clone().pop().unwrap();
 60                    let jid = BareJid::from_str(&item.0).unwrap();
 61                    events.push(Event::LeaveRoom(jid));
 62                }
 63                ref node => unimplemented!("node {}", node),
 64            }
 65        }
 66        Ok(PubSubEvent::Purge { node }) => {
 67            match node.0 {
 68                ref node if node == ns::BOOKMARKS2 => {
 69                    // TODO: Check that our bare JID is the sender.
 70                    events.push(Event::LeaveAllRooms);
 71                }
 72                ref node => unimplemented!("node {}", node),
 73            }
 74        }
 75        Err(e) => {
 76            error!("Error parsing PubSub event: {}", e);
 77        }
 78        _ => unimplemented!("PubSub event: {:#?}", event),
 79    }
 80    events
 81}
 82
 83pub(crate) fn handle_iq_result(from: &Jid, elem: Element) -> impl IntoIterator<Item = Event> {
 84    let mut events = Vec::new();
 85    let pubsub = PubSub::try_from(elem).unwrap();
 86    trace!("PubSub: {:#?}", pubsub);
 87    if let PubSub::Items(items) = pubsub {
 88        match items.node.0.clone() {
 89            #[cfg(feature = "avatars")]
 90            ref node if node == ns::AVATAR_DATA => {
 91                let new_events = avatar::handle_data_pubsub_iq(&from, &items);
 92                events.extend(new_events);
 93            }
 94            ref node if node == ns::BOOKMARKS2 => {
 95                events.push(Event::LeaveAllRooms);
 96                for item in items.items {
 97                    let item = item.0;
 98                    let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
 99                    let payload = item.payload.clone().unwrap();
100                    match bookmarks2::Conference::try_from(payload) {
101                        Ok(conference) => {
102                            if let Autojoin::True = conference.autojoin {
103                                events.push(Event::JoinRoom(jid, conference));
104                            }
105                        }
106                        Err(err) => panic!("Wrong payload type in bookmarks 2 item: {}", err),
107                    }
108                }
109            }
110            _ => unimplemented!(),
111        }
112    }
113    events
114}