1use crate::{
8 jid::{BareJid, Jid},
9 minidom::Element,
10 muc::room::{JoinRoomSettings, LeaveRoomSettings},
11 parsers::{
12 bookmarks2, ns,
13 pubsub::{self, pubsub::PubSub},
14 },
15 Agent, Event, RoomNick,
16};
17
18use std::str::FromStr;
19
20#[cfg(feature = "avatars")]
21pub(crate) mod avatar;
22
23pub(crate) async fn handle_event(
24 #[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
25 elem: Element,
26 #[cfg_attr(not(feature = "avatars"), allow(unused_variables))] agent: &mut Agent,
27) -> Vec<Event> {
28 #[allow(unused_mut)]
31 let mut events = Vec::new();
32
33 let event = pubsub::Event::try_from(elem);
34 trace!("PubSub event: {:#?}", event);
35 match event {
36 Ok(pubsub::Event {
37 payload:
38 pubsub::event::Payload::Items {
39 node,
40 published,
41 retracted,
42 },
43 }) => {
44 match node.0 {
45 #[cfg(feature = "avatars")]
46 ref node if node == ns::AVATAR_METADATA => {
47 let new_events =
49 avatar::handle_metadata_pubsub_event(&from, agent, published).await;
50 events.extend(new_events);
51 }
52 ref node if node == ns::BOOKMARKS2 => {
53 if let [item] = &published[..] {
55 let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
56 let payload = item.payload.clone().unwrap();
57 match bookmarks2::Conference::try_from(payload) {
58 Ok(conference) => {
59 if conference.autojoin {
60 if !agent.rooms_joined.contains_key(&jid) {
61 agent
62 .join_room(JoinRoomSettings {
63 room: jid,
64 nick: conference.nick.map(RoomNick::new),
65 password: conference.password,
66 status: None,
67 })
68 .await;
69 }
70 } else {
71 agent.leave_room(LeaveRoomSettings::new(jid)).await;
73 }
74 }
75 Err(err) => println!("not bookmark: {}", err),
76 }
77 } else if let [item] = &retracted[..] {
78 let jid = BareJid::from_str(&item.0).unwrap();
79
80 agent.leave_room(LeaveRoomSettings::new(jid)).await;
81 } else {
82 error!("No published or retracted item in pubsub event!");
83 }
84 }
85 ref node => unimplemented!("node {}", node),
86 }
87 }
88 Ok(pubsub::Event {
89 payload: pubsub::event::Payload::Purge { node },
90 }) => match node.0 {
91 ref node if node == ns::BOOKMARKS2 => {
92 warn!("The bookmarks2 PEP node was deleted!");
93 }
94 ref node => unimplemented!("node {}", node),
95 },
96 Err(e) => {
97 error!("Error parsing PubSub event: {}", e);
98 }
99 _ => unimplemented!("PubSub event: {:#?}", event),
100 }
101 events
102}
103
104pub(crate) async fn handle_iq_result(
105 #[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
106 elem: Element,
107 agent: &mut Agent,
108) -> impl IntoIterator<Item = Event> {
109 #[allow(unused_mut)]
112 let mut events = Vec::new();
113
114 let pubsub = PubSub::try_from(elem).unwrap();
115 trace!("PubSub: {:#?}", pubsub);
116 if let PubSub::Items(items) = pubsub {
117 match items.node.0.clone() {
118 #[cfg(feature = "avatars")]
119 ref node if node == ns::AVATAR_DATA => {
120 let new_events = avatar::handle_data_pubsub_iq(&from, &items);
121 events.extend(new_events);
122 }
123 ref node if node == ns::BOOKMARKS2 => {
124 let mut new_room_list: Vec<BareJid> = Vec::new();
127
128 for item in items.items {
129 let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
130 let payload = item.payload.clone().unwrap();
131 match bookmarks2::Conference::try_from(payload) {
132 Ok(conference) => {
133 new_room_list.push(jid.clone());
136
137 if conference.autojoin {
138 if !agent.rooms_joined.contains_key(&jid) {
139 agent
140 .join_room(JoinRoomSettings {
141 room: jid,
142 nick: conference.nick.map(RoomNick::new),
143 password: conference.password,
144 status: None,
145 })
146 .await;
147 }
148 } else {
149 agent.leave_room(LeaveRoomSettings::new(jid)).await;
151 }
152 }
153 Err(err) => {
154 warn!("Wrong payload type in bookmarks2 item: {}", err);
155 }
156 }
157 }
158
159 let mut rooms_to_leave: Vec<BareJid> = Vec::new();
161 for (room, _nick) in &agent.rooms_joined {
162 if !new_room_list.contains(&room) {
163 rooms_to_leave.push(room.clone());
164 }
165 }
166
167 for room in rooms_to_leave {
168 agent.leave_room(LeaveRoomSettings::new(room)).await;
169 }
170 }
171 _ => unimplemented!(),
172 }
173 }
174 events
175}