bot: resync on 'rejoin' rather than leave and join

The xmpp crate doesn't yet have mechanisms to wait for the next incoming
presence and so the `leave_room` method returns after the unavailable
presence has been set. Thus the code may still think it's being joined
when it pretty soon going not to be.

Instead, we chose to send another join presence to signal the MUC we
want to get the full state again (occupants, subject), without leaving.

Signed-off-by: pep <pep@bouah.net>
This commit is contained in:
pep 2025-12-28 19:08:19 +01:00
commit 8dfb89fe38
No known key found for this signature in database
GPG key ID: DEDA74AEECA9D0F2
2 changed files with 19 additions and 29 deletions

View file

@ -20,7 +20,7 @@ pretty_env_logger = "0.5"
serde = { version = "1.0", features = [ "derive" ] } serde = { version = "1.0", features = [ "derive" ] }
serde_json = "1.0" serde_json = "1.0"
toml = "0.9" toml = "0.9"
xmpp = { git = "https://gitlab.com/xmpp-rs/xmpp-rs", branch = "xmpp-config", default-features = false, features = [ "serde", "starttls", "rustls-native-certs", "aws_lc_rs" ] } xmpp = { git = "https://gitlab.com/xmpp-rs/xmpp-rs", branch = "xmpp-join-resync", default-features = false, features = [ "serde", "starttls", "rustls-native-certs", "aws_lc_rs" ] }
hmac = "0.12" hmac = "0.12"
sha2 = "0.10" sha2 = "0.10"
hex = "0.4" hex = "0.4"

View file

@ -23,7 +23,7 @@ use xmpp::parsers::message::MessageType;
use xmpp::{ use xmpp::{
Agent, ClientBuilder, ClientFeature, ClientType, Config as AgentConfig, Event, RoomNick, Agent, ClientBuilder, ClientFeature, ClientType, Config as AgentConfig, Event, RoomNick,
message::send::RawMessageSettings, message::send::RawMessageSettings,
muc::room::{JoinRoomSettings, LeaveRoomSettings}, muc::room::JoinRoomSettings,
}; };
pub struct XmppClient { pub struct XmppClient {
@ -69,7 +69,14 @@ impl XmppClient {
Event::Online => { Event::Online => {
self.is_online = true; self.is_online = true;
debug!("XMPP Online"); debug!("XMPP Online");
self.join_rooms().await for room in &self.rooms {
self.agent
.join_room(JoinRoomSettings {
nick: Some(RoomNick::from_resource_ref(self.nickname.as_ref())),
..JoinRoomSettings::new(room.clone())
})
.await
}
} }
Event::ChatMessage(_id, bare, message, _timeinfo) => { Event::ChatMessage(_id, bare, message, _timeinfo) => {
if !self.admins.contains(&bare) { if !self.admins.contains(&bare) {
@ -80,8 +87,15 @@ impl XmppClient {
debug!("Received chat message from {}: {}", bare, message); debug!("Received chat message from {}: {}", bare, message);
if message == "rejoin" { if message == "rejoin" {
self.leave_rooms().await; for room in &self.rooms {
self.join_rooms().await self.agent
.join_room(JoinRoomSettings {
nick: Some(RoomNick::from_resource_ref(self.nickname.as_ref())),
force_resync: true,
..JoinRoomSettings::new(room.clone())
})
.await
}
} }
} }
Event::Disconnected(e) => { Event::Disconnected(e) => {
@ -95,30 +109,6 @@ impl XmppClient {
} }
} }
pub async fn join_rooms(&mut self) {
for room in &self.rooms {
self.agent
.join_room(JoinRoomSettings {
room: room.clone(),
nick: Some(RoomNick::from_resource_ref(self.nickname.as_ref())),
password: None,
status: Some(("en", "Hi there!")),
})
.await
}
}
pub async fn leave_rooms(&mut self) {
for room in &self.rooms {
self.agent
.leave_room(LeaveRoomSettings {
room: room.clone(),
status: Some(("en", "See you!")),
})
.await
}
}
pub async fn receive(&mut self, mut rx: mpsc::UnboundedReceiver<Hook>) { pub async fn receive(&mut self, mut rx: mpsc::UnboundedReceiver<Hook>) {
loop { loop {
tokio::select! { tokio::select! {