2019-09-29 03:59:44 +02:00
|
|
|
// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
|
|
|
|
//
|
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
2020-03-08 19:57:59 +01:00
|
|
|
use super::Agent;
|
2024-12-16 20:19:51 +01:00
|
|
|
use crate::{
|
|
|
|
|
muc::room::{JoinRoomSettings, LeaveRoomSettings},
|
|
|
|
|
Event,
|
|
|
|
|
};
|
2019-09-29 03:59:44 +02:00
|
|
|
use std::str::FromStr;
|
2023-12-31 01:17:29 -05:00
|
|
|
use tokio_xmpp::{
|
2024-07-24 20:52:10 +02:00
|
|
|
jid::{BareJid, Jid},
|
|
|
|
|
minidom::Element,
|
2023-12-31 01:17:29 -05:00
|
|
|
parsers::{
|
2024-12-15 19:11:00 +01:00
|
|
|
bookmarks2, ns,
|
|
|
|
|
pubsub::{event::PubSubEvent, pubsub::PubSub},
|
2023-12-31 01:17:29 -05:00
|
|
|
},
|
2019-09-29 03:59:44 +02:00
|
|
|
};
|
|
|
|
|
|
2019-09-29 04:02:32 +02:00
|
|
|
#[cfg(feature = "avatars")]
|
2019-09-29 03:59:44 +02:00
|
|
|
pub(crate) mod avatar;
|
|
|
|
|
|
2024-08-20 16:54:48 +02:00
|
|
|
pub(crate) async fn handle_event(
|
2024-01-18 15:18:33 +01:00
|
|
|
#[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
|
2023-12-31 01:17:29 -05:00
|
|
|
elem: Element,
|
2024-08-20 16:54:48 +02:00
|
|
|
#[cfg_attr(not(feature = "avatars"), allow(unused_variables))] agent: &mut Agent,
|
2023-12-31 01:17:29 -05:00
|
|
|
) -> Vec<Event> {
|
2024-12-16 18:43:05 +01:00
|
|
|
// We allow the useless mut warning for no-default-features,
|
|
|
|
|
// since for now only avatars pushes events here.
|
|
|
|
|
#[allow(unused_mut)]
|
2019-09-29 03:59:44 +02:00
|
|
|
let mut events = Vec::new();
|
2024-12-16 18:43:05 +01:00
|
|
|
|
2019-09-29 04:08:56 +02:00
|
|
|
let event = PubSubEvent::try_from(elem);
|
|
|
|
|
trace!("PubSub event: {:#?}", event);
|
|
|
|
|
match event {
|
2019-09-29 03:59:44 +02:00
|
|
|
Ok(PubSubEvent::PublishedItems { node, items }) => {
|
|
|
|
|
match node.0 {
|
2019-09-29 04:02:32 +02:00
|
|
|
#[cfg(feature = "avatars")]
|
2019-10-23 00:46:26 +02:00
|
|
|
ref node if node == ns::AVATAR_METADATA => {
|
2020-03-08 19:57:59 +01:00
|
|
|
let new_events =
|
|
|
|
|
avatar::handle_metadata_pubsub_event(&from, agent, items).await;
|
2019-09-29 03:59:44 +02:00
|
|
|
events.extend(new_events);
|
2019-10-23 01:32:41 +02:00
|
|
|
}
|
2019-10-23 00:46:26 +02:00
|
|
|
ref node if node == ns::BOOKMARKS2 => {
|
2019-09-29 03:59:44 +02:00
|
|
|
// TODO: Check that our bare JID is the sender.
|
|
|
|
|
assert_eq!(items.len(), 1);
|
|
|
|
|
let item = items.clone().pop().unwrap();
|
|
|
|
|
let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
|
|
|
|
|
let payload = item.payload.clone().unwrap();
|
2023-12-16 16:06:38 +01:00
|
|
|
match bookmarks2::Conference::try_from(payload) {
|
2019-09-29 03:59:44 +02:00
|
|
|
Ok(conference) => {
|
2024-12-15 19:11:00 +01:00
|
|
|
if conference.autojoin {
|
2024-12-16 18:43:05 +01:00
|
|
|
if !agent.rooms_joined.contains_key(&jid) {
|
|
|
|
|
agent
|
2024-12-16 20:19:51 +01:00
|
|
|
.join_room(JoinRoomSettings {
|
|
|
|
|
room: jid,
|
|
|
|
|
nick: conference.nick,
|
|
|
|
|
password: conference.password,
|
|
|
|
|
status: None,
|
|
|
|
|
})
|
2024-12-16 18:43:05 +01:00
|
|
|
.await;
|
|
|
|
|
}
|
2019-09-29 03:59:44 +02:00
|
|
|
} else {
|
2024-12-16 18:43:05 +01:00
|
|
|
// So maybe another client of ours left the room... let's leave it too
|
2024-12-16 20:19:51 +01:00
|
|
|
agent.leave_room(LeaveRoomSettings::new(jid)).await;
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
2019-10-23 01:32:41 +02:00
|
|
|
}
|
|
|
|
|
Err(err) => println!("not bookmark: {}", err),
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
2019-10-23 01:32:41 +02:00
|
|
|
}
|
|
|
|
|
ref node => unimplemented!("node {}", node),
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(PubSubEvent::RetractedItems { node, items }) => {
|
|
|
|
|
match node.0 {
|
2019-10-23 00:46:26 +02:00
|
|
|
ref node if node == ns::BOOKMARKS2 => {
|
2019-09-29 03:59:44 +02:00
|
|
|
// TODO: Check that our bare JID is the sender.
|
|
|
|
|
assert_eq!(items.len(), 1);
|
|
|
|
|
let item = items.clone().pop().unwrap();
|
|
|
|
|
let jid = BareJid::from_str(&item.0).unwrap();
|
2024-12-16 18:43:05 +01:00
|
|
|
|
2024-12-16 20:19:51 +01:00
|
|
|
agent.leave_room(LeaveRoomSettings::new(jid)).await;
|
2019-10-23 01:32:41 +02:00
|
|
|
}
|
|
|
|
|
ref node => unimplemented!("node {}", node),
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-12-16 18:43:05 +01:00
|
|
|
Ok(PubSubEvent::Purge { node }) => match node.0 {
|
|
|
|
|
ref node if node == ns::BOOKMARKS2 => {
|
|
|
|
|
warn!("The bookmarks2 PEP node was deleted!");
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
2024-12-16 18:43:05 +01:00
|
|
|
ref node => unimplemented!("node {}", node),
|
|
|
|
|
},
|
2023-12-03 13:37:46 +00:00
|
|
|
Err(e) => {
|
|
|
|
|
error!("Error parsing PubSub event: {}", e);
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
2023-12-03 13:37:46 +00:00
|
|
|
_ => unimplemented!("PubSub event: {:#?}", event),
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
|
|
|
|
events
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-20 16:54:48 +02:00
|
|
|
pub(crate) async fn handle_iq_result(
|
2024-01-18 15:18:33 +01:00
|
|
|
#[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
|
|
|
|
|
elem: Element,
|
2024-08-20 16:54:48 +02:00
|
|
|
agent: &mut Agent,
|
2024-01-18 15:18:33 +01:00
|
|
|
) -> impl IntoIterator<Item = Event> {
|
2024-12-16 18:43:05 +01:00
|
|
|
// We allow the useless mut warning for no-default-features,
|
|
|
|
|
// since for now only avatars pushes events here.
|
|
|
|
|
#[allow(unused_mut)]
|
2019-09-29 03:59:44 +02:00
|
|
|
let mut events = Vec::new();
|
2024-12-16 18:43:05 +01:00
|
|
|
|
2019-09-29 03:59:44 +02:00
|
|
|
let pubsub = PubSub::try_from(elem).unwrap();
|
2019-09-29 04:08:56 +02:00
|
|
|
trace!("PubSub: {:#?}", pubsub);
|
2019-09-29 03:59:44 +02:00
|
|
|
if let PubSub::Items(items) = pubsub {
|
2019-09-29 04:02:32 +02:00
|
|
|
match items.node.0.clone() {
|
|
|
|
|
#[cfg(feature = "avatars")]
|
2019-10-23 00:46:26 +02:00
|
|
|
ref node if node == ns::AVATAR_DATA => {
|
2019-09-29 04:02:32 +02:00
|
|
|
let new_events = avatar::handle_data_pubsub_iq(&from, &items);
|
|
|
|
|
events.extend(new_events);
|
2019-10-23 01:32:41 +02:00
|
|
|
}
|
2019-10-23 00:46:26 +02:00
|
|
|
ref node if node == ns::BOOKMARKS2 => {
|
2024-12-16 18:43:05 +01:00
|
|
|
// Keep track of the new added/removed rooms in the bookmarks2 list.
|
|
|
|
|
// The rooms we joined which are no longer in the list should be left ASAP.
|
|
|
|
|
let mut new_room_list: Vec<BareJid> = Vec::new();
|
|
|
|
|
|
2019-09-29 04:02:32 +02:00
|
|
|
for item in items.items {
|
|
|
|
|
let item = item.0;
|
|
|
|
|
let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
|
|
|
|
|
let payload = item.payload.clone().unwrap();
|
2023-12-16 16:06:38 +01:00
|
|
|
match bookmarks2::Conference::try_from(payload) {
|
2019-09-29 04:02:32 +02:00
|
|
|
Ok(conference) => {
|
2024-12-16 18:43:05 +01:00
|
|
|
// This room was either marked for join or leave, but it was still in the bookmarks.
|
|
|
|
|
// Keep track in new_room_list.
|
|
|
|
|
new_room_list.push(jid.clone());
|
|
|
|
|
|
2024-12-15 19:11:00 +01:00
|
|
|
if conference.autojoin {
|
2024-12-16 18:43:05 +01:00
|
|
|
if !agent.rooms_joined.contains_key(&jid) {
|
|
|
|
|
agent
|
2024-12-16 20:19:51 +01:00
|
|
|
.join_room(JoinRoomSettings {
|
|
|
|
|
room: jid,
|
|
|
|
|
nick: conference.nick,
|
|
|
|
|
password: conference.password,
|
|
|
|
|
status: None,
|
|
|
|
|
})
|
2024-12-16 18:43:05 +01:00
|
|
|
.await;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Leave the room that is no longer autojoin
|
2024-12-16 20:19:51 +01:00
|
|
|
agent.leave_room(LeaveRoomSettings::new(jid)).await;
|
2019-09-29 04:02:32 +02:00
|
|
|
}
|
2019-10-23 01:32:41 +02:00
|
|
|
}
|
2024-12-16 18:43:05 +01:00
|
|
|
Err(err) => {
|
|
|
|
|
warn!("Wrong payload type in bookmarks2 item: {}", err);
|
|
|
|
|
}
|
2019-09-29 04:02:32 +02:00
|
|
|
}
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
2024-12-16 18:43:05 +01:00
|
|
|
|
|
|
|
|
// Now we leave the rooms that are no longer in the bookmarks
|
|
|
|
|
let mut rooms_to_leave: Vec<BareJid> = Vec::new();
|
|
|
|
|
for (room, _nick) in &agent.rooms_joined {
|
|
|
|
|
if !new_room_list.contains(&room) {
|
|
|
|
|
rooms_to_leave.push(room.clone());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for room in rooms_to_leave {
|
2024-12-16 20:19:51 +01:00
|
|
|
agent.leave_room(LeaveRoomSettings::new(room)).await;
|
2024-12-16 18:43:05 +01:00
|
|
|
}
|
2019-10-23 01:32:41 +02:00
|
|
|
}
|
|
|
|
|
_ => unimplemented!(),
|
2019-09-29 03:59:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
events
|
|
|
|
|
}
|