use crate::{
Agent, Event, RoomNick,
jid::{BareJid, Jid},
minidom::Element,
muc::room::{JoinRoomSettings, LeaveRoomSettings},
parsers::{
bookmarks2, ns,
pubsub::{self, pubsub::PubSub},
},
};
use std::str::FromStr;
#[cfg(feature = "avatars")]
pub(crate) mod avatar;
pub(crate) async fn handle_event(
#[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
elem: Element,
#[cfg_attr(not(feature = "avatars"), allow(unused_variables))] agent: &mut Agent,
) -> Vec<Event> {
#[allow(unused_mut)]
let mut events = Vec::new();
let event = pubsub::Event::try_from(elem);
trace!("PubSub event: {:#?}", event);
match event {
Ok(pubsub::Event {
payload:
pubsub::event::Payload::Items {
node,
published,
retracted,
},
}) => {
match node.0 {
#[cfg(feature = "avatars")]
ref node if node == ns::AVATAR_METADATA => {
let new_events =
avatar::handle_metadata_pubsub_event(&from, agent, published).await;
events.extend(new_events);
}
ref node if node == ns::BOOKMARKS2 => {
let config = agent.get_config().await;
if let [item] = &published[..] {
let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
let payload = item.payload.clone().unwrap();
match bookmarks2::Conference::try_from(payload) {
Ok(conference) => {
if conference.autojoin {
if !agent.rooms_joined.contains_key(&jid) {
agent
.join_room(JoinRoomSettings {
nick: conference.nick.map(RoomNick::new),
password: conference.password,
..JoinRoomSettings::new(jid)
})
.await;
} else {
if config.bookmarks_autojoin {
agent.leave_room(LeaveRoomSettings::new(jid)).await;
}
}
}
}
Err(err) => println!("not bookmark: {}", err),
}
} else if let [item] = &retracted[..] {
if config.bookmarks_autojoin {
let jid = BareJid::from_str(&item.0).unwrap();
agent.leave_room(LeaveRoomSettings::new(jid)).await;
}
} else {
error!("No published or retracted item in pubsub event!");
}
}
ref node => info!("Unhandled PubSub node {}", node),
}
}
Ok(pubsub::Event {
payload: pubsub::event::Payload::Purge { node },
}) => match node.0 {
ref node if node == ns::BOOKMARKS2 => {
warn!("The bookmarks2 PEP node was deleted!");
}
ref node => info!("Unhandled PubSub node {}", node),
},
Err(e) => {
error!("Error parsing PubSub event: {}", e);
}
_ => info!("Unhandled PubSub event: {:#?}", event),
}
events
}
pub(crate) async fn handle_iq_result(
#[cfg_attr(not(feature = "avatars"), allow(unused_variables))] from: &Jid,
elem: Element,
agent: &mut Agent,
) -> impl IntoIterator<Item = Event> {
#[allow(unused_mut)]
let mut events = Vec::new();
let pubsub = PubSub::try_from(elem).unwrap();
trace!("PubSub: {:#?}", pubsub);
if let PubSub::Items(items) = pubsub {
match items.node.0.clone() {
#[cfg(feature = "avatars")]
ref node if node == ns::AVATAR_DATA => {
let new_events = avatar::handle_data_pubsub_iq(&from, &items);
events.extend(new_events);
}
ref node if node == ns::BOOKMARKS2 => {
let config = agent.get_config().await;
let mut new_room_list: Vec<BareJid> = Vec::new();
for item in items.items {
let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
let payload = item.payload.clone().unwrap();
match bookmarks2::Conference::try_from(payload) {
Ok(conference) => {
new_room_list.push(jid.clone());
if conference.autojoin {
if !agent.rooms_joined.contains_key(&jid) {
agent
.join_room(JoinRoomSettings {
nick: conference.nick.map(RoomNick::new),
password: conference.password,
..JoinRoomSettings::new(jid)
})
.await;
}
} else {
if config.bookmarks_autojoin {
agent.leave_room(LeaveRoomSettings::new(jid)).await;
}
}
}
Err(err) => {
warn!("Wrong payload type in bookmarks2 item: {}", err);
}
}
}
if config.bookmarks_autojoin {
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 {
agent.leave_room(LeaveRoomSettings::new(room)).await;
}
}
}
ref node => info!("Unhandled PubSub node: {}", node),
}
}
events
}