From a2ed5026f01013faf39d9b861cc87781a7a5d68b Mon Sep 17 00:00:00 2001 From: pep Date: Sun, 28 Dec 2025 17:48:49 +0100 Subject: [PATCH] xmpp: Allow resyncs in Agent::join_room Signed-off-by: pep --- xmpp/ChangeLog | 2 ++ xmpp/examples/hello_bot.rs | 4 +--- xmpp/src/iq/result.rs | 3 +-- xmpp/src/muc/room.rs | 14 +++++++++++++- xmpp/src/pubsub/mod.rs | 6 ++---- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/xmpp/ChangeLog b/xmpp/ChangeLog index 60f90b19907ffbea072398379bf1f236802dfdb5..d949673e788a0e706c780c06d173c08044cacf0e 100644 --- a/xmpp/ChangeLog +++ b/xmpp/ChangeLog @@ -26,6 +26,8 @@ XXXX-YY-ZZ [ RELEASER ] to be enabled for compilation to succeed). Please refer to the crate docs for details. (!581) + - Allow joining an already joined room with `Agent::join_room` to enable + resyncs. Adds a parameter to `muc::room::JoinRoomSettings`. * Added: - Agent::send_room_message takes RoomMessageSettings argument (!483) - Agent::send_raw_message takes RawMessageSettings for any message type (!487) diff --git a/xmpp/examples/hello_bot.rs b/xmpp/examples/hello_bot.rs index ae35e6f64192a7d5f8b465e4df1860152211b030..e45517913489554316b89e18052d9083c893fe03 100644 --- a/xmpp/examples/hello_bot.rs +++ b/xmpp/examples/hello_bot.rs @@ -103,10 +103,8 @@ async fn handle_events(client: &mut Agent, event: Event, rooms: &Vec) { log::info!("Joining room {} from CLI argument…", room); client .join_room(JoinRoomSettings { - room: room.clone(), - nick: None, - password: None, status: Some(("en", "Yet another bot!")), + ..JoinRoomSettings::new(room.clone()) }) .await; } diff --git a/xmpp/src/iq/result.rs b/xmpp/src/iq/result.rs index 7c101e2a32f7fd0ae3da46e83112a8ae8eb33088..af00d2d049e79df0478fc0b99f85bf20866820a3 100644 --- a/xmpp/src/iq/result.rs +++ b/xmpp/src/iq/result.rs @@ -41,10 +41,9 @@ pub async fn handle_iq_result( let (jid, room) = conf.into_bookmarks2(); agent .join_room(JoinRoomSettings { - room: jid, nick: room.nick.map(RoomNick::new), password: room.password, - status: None, + ..JoinRoomSettings::new(jid) }) .await; } diff --git a/xmpp/src/muc/room.rs b/xmpp/src/muc/room.rs index d21390b0f50e4d2c07b59d47a344ea80e6f0d893..3a8c2f8c24bb8db28488a6431eec9364955740e9 100644 --- a/xmpp/src/muc/room.rs +++ b/xmpp/src/muc/room.rs @@ -21,6 +21,11 @@ pub struct JoinRoomSettings<'a> { pub nick: Option, pub password: Option, pub status: Option<(&'a str, &'a str)>, + /// Send the join payload again even though we're already supposedly joined. + /// This was made explicit in version 1.27 of XEP-0045 (cee524dbde4, 2016), that is just rejoin + /// with the standard MUC payload to force a resync of the client state (receive all occupants + /// and subject again). + pub force_resync: bool, } impl<'a> JoinRoomSettings<'a> { @@ -30,6 +35,7 @@ impl<'a> JoinRoomSettings<'a> { nick: None, password: None, status: None, + force_resync: false, } } @@ -47,6 +53,11 @@ impl<'a> JoinRoomSettings<'a> { self.status = Some((lang, content)); self } + + pub fn with_resync(mut self) -> Self { + self.force_resync = true; + self + } } /// TODO: this method should add bookmark and ensure autojoin is true @@ -56,6 +67,7 @@ pub async fn join_room<'a>(agent: &mut Agent, settings: JoinRoomSettings<'a>) { nick, password, status, + force_resync, } = settings; if agent.rooms_joining.contains_key(&room) { @@ -64,7 +76,7 @@ pub async fn join_room<'a>(agent: &mut Agent, settings: JoinRoomSettings<'a>) { return; } - if agent.rooms_joined.contains_key(&room) { + if !force_resync && agent.rooms_joined.contains_key(&room) { // We are already joined, cannot join warn!("Requesting to join room {room} which is already joined..."); return; diff --git a/xmpp/src/pubsub/mod.rs b/xmpp/src/pubsub/mod.rs index 84d73ab098984d4a7d3471b165f853557eb16f6d..1adc61e3ac3e955de6fe5c76ffccc1c484f3f4dd 100644 --- a/xmpp/src/pubsub/mod.rs +++ b/xmpp/src/pubsub/mod.rs @@ -61,10 +61,9 @@ pub(crate) async fn handle_event( if !agent.rooms_joined.contains_key(&jid) { agent .join_room(JoinRoomSettings { - room: jid, nick: conference.nick.map(RoomNick::new), password: conference.password, - status: None, + ..JoinRoomSettings::new(jid) }) .await; } else { @@ -144,10 +143,9 @@ pub(crate) async fn handle_iq_result( if !agent.rooms_joined.contains_key(&jid) { agent .join_room(JoinRoomSettings { - room: jid, nick: conference.nick.map(RoomNick::new), password: conference.password, - status: None, + ..JoinRoomSettings::new(jid) }) .await; }