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}