Detailed changes
@@ -43,6 +43,7 @@ XXXX-YY-ZZ [ RELEASER <admin@localhost> ]
stanzas.
- Added documentation on `Event` enum.
- Update to edition 2024
+ - Add Config::Config struct as a user-facing Agent configuration method.
* Fixes:
- Use tokio::sync::RwLock not std::sync::RwLock (!432)
- The default caps node has been shortened to https://xmpp.rs since we
@@ -12,7 +12,7 @@ use tokio::io;
use tokio::sync::RwLock;
use crate::{
- Error, Event, RoomNick, event_loop,
+ Config, Error, Event, RoomNick, event_loop,
jid::{BareJid, Jid},
message, muc,
parsers::disco::DiscoInfoResult,
@@ -24,6 +24,7 @@ use tokio_xmpp::{Stanza, stanzastream::StanzaToken};
pub struct Agent {
pub(crate) client: TokioXmppClient,
+ pub(crate) config: Arc<RwLock<Config>>,
pub(crate) default_nick: Arc<RwLock<RoomNick>>,
pub(crate) lang: Arc<Vec<String>>,
pub(crate) disco: DiscoInfoResult,
@@ -39,6 +40,7 @@ pub struct Agent {
impl Agent {
pub fn new(
client: TokioXmppClient,
+ config: Config,
default_nick: RoomNick,
lang: Vec<String>,
disco: DiscoInfoResult,
@@ -46,6 +48,7 @@ impl Agent {
) -> Agent {
Agent {
client,
+ config: Arc::new(RwLock::new(config)),
default_nick: Arc::new(RwLock::new(default_nick)),
lang: Arc::new(lang),
disco,
@@ -58,6 +61,13 @@ impl Agent {
}
}
+ /// Reset the agent configuration to the provided Config struct
+ // TODO: refresh everything that is affected by this reset?
+ pub async fn set_config(&mut self, config: Config) {
+ let mut c = self.config.write().await;
+ *c = config;
+ }
+
pub async fn disconnect(self) -> Result<(), Error> {
self.client.send_end().await
}
@@ -9,7 +9,7 @@ use crate::tokio_xmpp::connect::{DnsConfig, StartTlsServerConnector};
use core::str::FromStr;
use crate::{
- Agent, ClientFeature, RoomNick,
+ Agent, ClientFeature, Config, RoomNick,
jid::{BareJid, Jid, ResourceRef},
parsers::{
disco::{DiscoInfoResult, Feature, Identity},
@@ -43,6 +43,7 @@ pub struct ClientBuilder<'a, C: ServerConnector> {
jid: BareJid,
password: &'a str,
server_connector: C,
+ config: Config,
website: String,
default_nick: RoomNick,
lang: Vec<String>,
@@ -73,6 +74,7 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
jid,
password,
server_connector,
+ config: Config::default(),
website: String::from("https://gitlab.com/xmpp-rs/tokio-xmpp"),
default_nick: RoomNick::from_str("xmpp-rs").unwrap(),
lang: vec![String::from("en")],
@@ -89,6 +91,11 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
self
}
+ pub fn set_config(mut self, config: Config) -> Self {
+ self.config = config;
+ self
+ }
+
pub fn set_client(mut self, type_: ClientType, name: &str) -> Self {
self.disco = (type_, String::from(name));
self
@@ -169,6 +176,13 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
let disco = self.make_disco();
let node = self.website;
- Agent::new(client, self.default_nick, self.lang, disco, node)
+ Agent::new(
+ client,
+ self.config,
+ self.default_nick,
+ self.lang,
+ disco,
+ node,
+ )
}
}
@@ -0,0 +1,31 @@
+// Copyright (c) 2025 Crate authors
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/// Store Agent configuration. Differs from state which is generated at runtime
+pub struct Config {
+ /// Synchronize bookmarks based on autojoin flag.
+ /// The client will join and leave based on the value of the `autojoin` flag on the (pubsub)
+ /// bookmark item.
+ /// If this `bookmarks_autojoin` attribute is set to false, `autojoin` set to false won't make
+ /// the client leave a room, neither will the removal of a bookmark item. This will only happen
+ /// after the client is restarted, as these items won't be automatically joined anymore.
+ /// <https://xmpp.org/extensions/xep-0402.html#notification>
+ pub bookmarks_autojoin: bool,
+}
+
+impl Default for Config {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Config {
+ fn new() -> Self {
+ Config {
+ bookmarks_autojoin: true,
+ }
+ }
+}
@@ -65,6 +65,7 @@ use parsers::message::Id as MessageId;
pub mod agent;
pub mod builder;
+pub mod config;
pub mod delay;
pub mod disco;
pub mod event;
@@ -79,6 +80,7 @@ pub mod upload;
pub use agent::Agent;
pub use builder::{ClientBuilder, ClientType};
+pub use config::Config;
pub use event::Event;
pub use feature::ClientFeature;
@@ -66,18 +66,22 @@ pub(crate) async fn handle_event(
status: None,
})
.await;
+ } else {
+ if agent.config.read().await.bookmarks_autojoin {
+ // So maybe another client of ours left the room... let's leave it too
+ agent.leave_room(LeaveRoomSettings::new(jid)).await;
+ }
}
- } else {
- // So maybe another client of ours left the room... let's leave it too
- agent.leave_room(LeaveRoomSettings::new(jid)).await;
}
}
Err(err) => println!("not bookmark: {}", err),
}
} else if let [item] = &retracted[..] {
- let jid = BareJid::from_str(&item.0).unwrap();
+ if agent.config.read().await.bookmarks_autojoin {
+ let jid = BareJid::from_str(&item.0).unwrap();
- agent.leave_room(LeaveRoomSettings::new(jid)).await;
+ agent.leave_room(LeaveRoomSettings::new(jid)).await;
+ }
} else {
error!("No published or retracted item in pubsub event!");
}
@@ -146,8 +150,10 @@ pub(crate) async fn handle_iq_result(
.await;
}
} else {
- // Leave the room that is no longer autojoin
- agent.leave_room(LeaveRoomSettings::new(jid)).await;
+ if agent.config.read().await.bookmarks_autojoin {
+ // Leave the room that is no longer autojoin
+ agent.leave_room(LeaveRoomSettings::new(jid)).await;
+ }
}
}
Err(err) => {
@@ -156,16 +162,18 @@ pub(crate) async fn handle_iq_result(
}
}
- // Now we leave the rooms that are no longer in the bookmarks
- 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());
+ if agent.config.read().await.bookmarks_autojoin {
+ // Now we leave the rooms that are no longer in the bookmarks
+ 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;
+ for room in rooms_to_leave {
+ agent.leave_room(LeaveRoomSettings::new(room)).await;
+ }
}
}
_ => unimplemented!(),