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