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}