use crate::parsers::message::MessageType;
use tokio_xmpp::connect::ServerConnector;
use tokio_xmpp::{
jid::BareJid,
parsers::{
muc::Muc,
presence::{Presence, Type as PresenceType},
},
};
use crate::Agent;
#[derive(Clone, Debug)]
pub struct JoinRoomSettings<'a> {
pub room: BareJid,
pub nick: Option<String>,
pub password: Option<String>,
pub status: Option<(&'a str, &'a str)>,
}
impl<'a> JoinRoomSettings<'a> {
pub fn new(room: BareJid) -> Self {
Self {
room,
nick: None,
password: None,
status: None,
}
}
pub fn with_nick(mut self, nick: impl AsRef<str>) -> Self {
self.nick = Some(nick.as_ref().into());
self
}
pub fn with_password(mut self, password: impl AsRef<str>) -> Self {
self.password = Some(password.as_ref().into());
self
}
pub fn with_status(mut self, lang: &'a str, content: &'a str) -> Self {
self.status = Some((lang, content));
self
}
}
pub async fn join_room<'a, C: ServerConnector>(
agent: &mut Agent<C>,
settings: JoinRoomSettings<'a>,
) {
let JoinRoomSettings {
room,
nick,
password,
status,
} = settings;
if agent.rooms_joining.contains_key(&room) {
warn!("Requesting to join again room {room} which is already joining...");
return;
}
if !agent.rooms_joined.contains_key(&room) {
warn!("Requesting to join room {room} which is already joined...");
return;
}
let mut muc = Muc::new();
if let Some(password) = password {
muc = muc.with_password(password);
}
let nick = if let Some(nick) = nick {
nick
} else {
agent.default_nick.read().await.clone()
};
let room_jid = room.with_resource_str(&nick).unwrap();
let mut presence = Presence::new(PresenceType::None).with_to(room_jid);
presence.add_payload(muc);
let (lang, status) = status.unwrap_or(("", ""));
presence.set_status(String::from(lang), String::from(status));
let _ = agent.client.send_stanza(presence.into()).await;
agent.rooms_joining.insert(room, nick);
}
#[derive(Clone, Debug)]
pub struct LeaveRoomSettings<'a> {
pub room: BareJid,
pub status: Option<(&'a str, &'a str)>,
}
impl<'a> LeaveRoomSettings<'a> {
pub fn new(room: BareJid) -> Self {
Self { room, status: None }
}
pub fn with_status(mut self, lang: &'a str, content: &'a str) -> Self {
self.status = Some((lang, content));
self
}
}
pub async fn leave_room<'a, C: ServerConnector>(
agent: &mut Agent<C>,
settings: LeaveRoomSettings<'a>,
) {
let LeaveRoomSettings { room, status } = settings;
if agent.rooms_leaving.contains_key(&room) {
warn!("Requesting to leave again room {room} which is already leaving...");
return;
}
if !agent.rooms_joined.contains_key(&room) {
warn!("Requesting to leave room {room} which is not joined...");
return;
}
let nickname = agent.rooms_joined.get(&room).unwrap();
let mut presence = Presence::new(PresenceType::Unavailable).with_to(
room.with_resource_str(nickname.as_str())
.expect("Invalid room JID after adding resource part."),
);
if let Some((lang, content)) = status {
presence.set_status(lang, content);
}
if let Err(e) = agent.client.send_stanza(presence.into()).await {
error!("Failed to send leave room presence: {}", e);
}
agent.rooms_leaving.insert(room, nickname.to_string());
}
#[derive(Clone, Debug)]
pub struct RoomMessageSettings<'a> {
pub room: BareJid,
pub message: &'a str,
pub lang: Option<&'a str>,
}
impl<'a> RoomMessageSettings<'a> {
pub fn new(room: BareJid, message: &'a str) -> Self {
Self {
room,
message,
lang: None,
}
}
pub fn with_lang(mut self, lang: &'a str) -> Self {
self.lang = Some(lang);
self
}
}
pub async fn send_room_message<'a, C: ServerConnector>(
agent: &mut Agent<C>,
settings: RoomMessageSettings<'a>,
) {
let RoomMessageSettings {
room,
message,
lang,
} = settings;
agent
.send_message(
room.into(),
MessageType::Groupchat,
lang.unwrap_or(""),
message,
)
.await;
}