1use crate::{
8 Agent, Event, RoomNick,
9 jid::{BareJid, Jid},
10 minidom::Element,
11 muc::room::{JoinRoomSettings, LeaveRoomSettings},
12 parsers::{
13 bookmarks2, ns,
14 pubsub::{self, pubsub::PubSub},
15 },
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 let config = agent.get_config().await;
54 if let [item] = &published[..] {
56 let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
57 let payload = item.payload.clone().unwrap();
58 match bookmarks2::Conference::try_from(payload) {
59 Ok(conference) => {
60 if conference.autojoin {
61 if !agent.rooms_joined.contains_key(&jid) {
62 agent
63 .join_room(JoinRoomSettings {
64 room: jid,
65 nick: conference.nick.map(RoomNick::new),
66 password: conference.password,
67 status: None,
68 })
69 .await;
70 } else {
71 if config.bookmarks_autojoin {
72 agent.leave_room(LeaveRoomSettings::new(jid)).await;
74 }
75 }
76 }
77 }
78 Err(err) => println!("not bookmark: {}", err),
79 }
80 } else if let [item] = &retracted[..] {
81 if config.bookmarks_autojoin {
82 let jid = BareJid::from_str(&item.0).unwrap();
83
84 agent.leave_room(LeaveRoomSettings::new(jid)).await;
85 }
86 } else {
87 error!("No published or retracted item in pubsub event!");
88 }
89 }
90 ref node => unimplemented!("node {}", node),
91 }
92 }
93 Ok(pubsub::Event {
94 payload: pubsub::event::Payload::Purge { node },
95 }) => match node.0 {
96 ref node if node == ns::BOOKMARKS2 => {
97 warn!("The bookmarks2 PEP node was deleted!");
98 }
99 ref node => unimplemented!("node {}", node),
100 },
101 Err(e) => {
102 error!("Error parsing PubSub event: {}", e);
103 }
104 _ => unimplemented!("PubSub event: {:#?}", event),
105 }
106 events
107}
108
109pub(crate) async fn handle_iq_result(
110 #[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
111 elem: Element,
112 agent: &mut Agent,
113) -> impl IntoIterator<Item = Event> {
114 #[allow(unused_mut)]
117 let mut events = Vec::new();
118
119 let pubsub = PubSub::try_from(elem).unwrap();
120 trace!("PubSub: {:#?}", pubsub);
121 if let PubSub::Items(items) = pubsub {
122 match items.node.0.clone() {
123 #[cfg(feature = "avatars")]
124 ref node if node == ns::AVATAR_DATA => {
125 let new_events = avatar::handle_data_pubsub_iq(&from, &items);
126 events.extend(new_events);
127 }
128 ref node if node == ns::BOOKMARKS2 => {
129 let config = agent.get_config().await;
130 let mut new_room_list: Vec<BareJid> = Vec::new();
133
134 for item in items.items {
135 let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
136 let payload = item.payload.clone().unwrap();
137 match bookmarks2::Conference::try_from(payload) {
138 Ok(conference) => {
139 new_room_list.push(jid.clone());
142
143 if conference.autojoin {
144 if !agent.rooms_joined.contains_key(&jid) {
145 agent
146 .join_room(JoinRoomSettings {
147 room: jid,
148 nick: conference.nick.map(RoomNick::new),
149 password: conference.password,
150 status: None,
151 })
152 .await;
153 }
154 } else {
155 if config.bookmarks_autojoin {
156 agent.leave_room(LeaveRoomSettings::new(jid)).await;
158 }
159 }
160 }
161 Err(err) => {
162 warn!("Wrong payload type in bookmarks2 item: {}", err);
163 }
164 }
165 }
166
167 if config.bookmarks_autojoin {
168 let mut rooms_to_leave: Vec<BareJid> = Vec::new();
170 for (room, _nick) in &agent.rooms_joined {
171 if !new_room_list.contains(&room) {
172 rooms_to_leave.push(room.clone());
173 }
174 }
175
176 for room in rooms_to_leave {
177 agent.leave_room(LeaveRoomSettings::new(room)).await;
178 }
179 }
180 }
181 _ => unimplemented!(),
182 }
183 }
184 events
185}