1use crate::{
8 Agent, RoomNick,
9 jid::{BareJid, ResourceRef},
10 message::send::RawMessageSettings,
11 parsers::{
12 message::MessageType,
13 muc::Muc,
14 presence::{Presence, Type as PresenceType},
15 },
16};
17
18#[derive(Clone, Debug)]
19pub struct JoinRoomSettings<'a> {
20 pub room: BareJid,
21 pub nick: Option<RoomNick>,
22 pub password: Option<String>,
23 pub status: Option<(&'a str, &'a str)>,
24 pub force_resync: bool,
29}
30
31impl<'a> JoinRoomSettings<'a> {
32 pub fn new(room: BareJid) -> Self {
33 Self {
34 room,
35 nick: None,
36 password: None,
37 status: None,
38 force_resync: false,
39 }
40 }
41
42 pub fn with_nick(mut self, nick: impl AsRef<ResourceRef>) -> Self {
43 self.nick = Some(RoomNick::from_resource_ref(nick.as_ref()));
44 self
45 }
46
47 pub fn with_password(mut self, password: impl AsRef<str>) -> Self {
48 self.password = Some(password.as_ref().into());
49 self
50 }
51
52 pub fn with_status(mut self, lang: &'a str, content: &'a str) -> Self {
53 self.status = Some((lang, content));
54 self
55 }
56
57 pub fn with_resync(mut self) -> Self {
58 self.force_resync = true;
59 self
60 }
61}
62
63pub async fn join_room<'a>(agent: &mut Agent, settings: JoinRoomSettings<'a>) {
65 let JoinRoomSettings {
66 room,
67 nick,
68 password,
69 status,
70 force_resync,
71 } = settings;
72
73 if agent.rooms_joining.contains_key(&room) {
74 warn!("Requesting to join again room {room} which is already joining...");
76 return;
77 }
78
79 if !force_resync || agent.rooms_joined.contains_key(&room) {
80 warn!("Requesting to join room {room} which is already joined...");
82 return;
83 }
84
85 let mut muc = Muc::new();
86 if let Some(password) = password {
87 muc = muc.with_password(password);
88 }
89
90 let nick = if let Some(nick) = nick {
91 nick
92 } else {
93 agent.get_config().await.default_nick
94 };
95
96 let room_jid = room.with_resource(&nick);
97 let mut presence = Presence::new(PresenceType::None).with_to(room_jid);
98 presence.add_payload(muc);
99
100 let (lang, status) = status.unwrap_or(("", ""));
101 presence.set_status(String::from(lang), String::from(status));
102
103 let _ = agent.client.send_stanza(presence.into()).await;
104
105 agent.rooms_joining.insert(room, nick);
106}
107
108#[derive(Clone, Debug)]
109pub struct LeaveRoomSettings<'a> {
110 pub room: BareJid,
111 pub status: Option<(&'a str, &'a str)>,
112}
113
114impl<'a> LeaveRoomSettings<'a> {
115 pub fn new(room: BareJid) -> Self {
116 Self { room, status: None }
117 }
118
119 pub fn with_status(mut self, lang: &'a str, content: &'a str) -> Self {
120 self.status = Some((lang, content));
121 self
122 }
123}
124
125pub async fn leave_room<'a>(agent: &mut Agent, settings: LeaveRoomSettings<'a>) {
134 let LeaveRoomSettings { room, status } = settings;
135
136 if agent.rooms_leaving.contains_key(&room) {
137 warn!("Requesting to leave again room {room} which is already leaving...");
139 return;
140 }
141
142 if !agent.rooms_joined.contains_key(&room) {
143 warn!("Requesting to leave room {room} which is not joined...");
145 return;
146 }
147
148 let nickname = agent.rooms_joined.get(&room).unwrap();
150
151 let mut presence =
154 Presence::new(PresenceType::Unavailable).with_to(room.with_resource(&nickname));
155
156 if let Some((lang, content)) = status {
160 presence.set_status(lang, content);
161 }
162
163 if let Err(e) = agent.client.send_stanza(presence.into()).await {
165 error!("Failed to send leave room presence: {}", e);
167 }
168
169 agent.rooms_leaving.insert(room, nickname.clone());
170}
171
172#[derive(Clone, Debug)]
173pub struct RoomMessageSettings<'a> {
174 pub room: BareJid,
175 pub message: &'a str,
176 pub lang: Option<&'a str>,
177}
178
179impl<'a> RoomMessageSettings<'a> {
180 pub fn new(room: BareJid, message: &'a str) -> Self {
181 Self {
182 room,
183 message,
184 lang: None,
185 }
186 }
187
188 pub fn with_lang(mut self, lang: &'a str) -> Self {
189 self.lang = Some(lang);
190 self
191 }
192}
193
194pub async fn send_room_message<'a>(agent: &mut Agent, settings: RoomMessageSettings<'a>) {
195 let RoomMessageSettings {
196 room,
197 message,
198 lang,
199 } = settings;
200
201 agent
203 .send_raw_message(
204 RawMessageSettings::new(room.into(), MessageType::Groupchat, message)
205 .with_lang_option(lang),
206 )
207 .await;
208}