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