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::{
 11    connect::ServerConnector,
 12    jid::{BareJid, Jid},
 13    minidom::Element,
 14    parsers::{
 15        bookmarks2::{self, Autojoin},
 16        ns,
 17        pubsub::event::PubSubEvent,
 18        pubsub::pubsub::PubSub,
 19    },
 20};
 21
 22#[cfg(feature = "avatars")]
 23pub(crate) mod avatar;
 24
 25pub(crate) async fn handle_event<C: ServerConnector>(
 26    #[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
 27    elem: Element,
 28    #[cfg_attr(not(feature = "avatars"), allow(unused_variables))] agent: &mut Agent<C>,
 29) -> Vec<Event> {
 30    let mut events = Vec::new();
 31    let event = PubSubEvent::try_from(elem);
 32    trace!("PubSub event: {:#?}", event);
 33    match event {
 34        Ok(PubSubEvent::PublishedItems { node, items }) => {
 35            match node.0 {
 36                #[cfg(feature = "avatars")]
 37                ref node if node == ns::AVATAR_METADATA => {
 38                    let new_events =
 39                        avatar::handle_metadata_pubsub_event(&from, agent, items).await;
 40                    events.extend(new_events);
 41                }
 42                ref node if node == ns::BOOKMARKS2 => {
 43                    // TODO: Check that our bare JID is the sender.
 44                    assert_eq!(items.len(), 1);
 45                    let item = items.clone().pop().unwrap();
 46                    let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
 47                    let payload = item.payload.clone().unwrap();
 48                    match bookmarks2::Conference::try_from(payload) {
 49                        Ok(conference) => {
 50                            if conference.autojoin == Autojoin::True {
 51                                events.push(Event::JoinRoom(jid, conference));
 52                            } else {
 53                                events.push(Event::LeaveRoom(jid));
 54                            }
 55                        }
 56                        Err(err) => println!("not bookmark: {}", err),
 57                    }
 58                }
 59                ref node => unimplemented!("node {}", node),
 60            }
 61        }
 62        Ok(PubSubEvent::RetractedItems { node, items }) => {
 63            match node.0 {
 64                ref node if node == ns::BOOKMARKS2 => {
 65                    // TODO: Check that our bare JID is the sender.
 66                    assert_eq!(items.len(), 1);
 67                    let item = items.clone().pop().unwrap();
 68                    let jid = BareJid::from_str(&item.0).unwrap();
 69                    events.push(Event::LeaveRoom(jid));
 70                }
 71                ref node => unimplemented!("node {}", node),
 72            }
 73        }
 74        Ok(PubSubEvent::Purge { node }) => {
 75            match node.0 {
 76                ref node if node == ns::BOOKMARKS2 => {
 77                    // TODO: Check that our bare JID is the sender.
 78                    events.push(Event::LeaveAllRooms);
 79                }
 80                ref node => unimplemented!("node {}", node),
 81            }
 82        }
 83        Err(e) => {
 84            error!("Error parsing PubSub event: {}", e);
 85        }
 86        _ => unimplemented!("PubSub event: {:#?}", event),
 87    }
 88    events
 89}
 90
 91pub(crate) fn handle_iq_result(
 92    #[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
 93    elem: Element,
 94) -> impl IntoIterator<Item = Event> {
 95    let mut events = Vec::new();
 96    let pubsub = PubSub::try_from(elem).unwrap();
 97    trace!("PubSub: {:#?}", pubsub);
 98    if let PubSub::Items(items) = pubsub {
 99        match items.node.0.clone() {
100            #[cfg(feature = "avatars")]
101            ref node if node == ns::AVATAR_DATA => {
102                let new_events = avatar::handle_data_pubsub_iq(&from, &items);
103                events.extend(new_events);
104            }
105            ref node if node == ns::BOOKMARKS2 => {
106                events.push(Event::LeaveAllRooms);
107                for item in items.items {
108                    let item = item.0;
109                    let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
110                    let payload = item.payload.clone().unwrap();
111                    match bookmarks2::Conference::try_from(payload) {
112                        Ok(conference) => {
113                            if let Autojoin::True = conference.autojoin {
114                                events.push(Event::JoinRoom(jid, conference));
115                            }
116                        }
117                        Err(err) => panic!("Wrong payload type in bookmarks 2 item: {}", err),
118                    }
119                }
120            }
121            _ => unimplemented!(),
122        }
123    }
124    events
125}