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