xmpp: Merge Agent configuration into new Config struct

Signed-off-by: pep <pep@bouah.net>
This commit is contained in:
pep 2025-11-13 23:57:50 +01:00
commit a1a31ce11c
8 changed files with 65 additions and 68 deletions

View file

@ -25,10 +25,7 @@ use tokio_xmpp::{Stanza, stanzastream::StanzaToken};
pub struct Agent { pub struct Agent {
pub(crate) client: TokioXmppClient, pub(crate) client: TokioXmppClient,
pub(crate) config: Arc<RwLock<Config>>, pub(crate) config: Arc<RwLock<Config>>,
pub(crate) default_nick: Arc<RwLock<RoomNick>>,
pub(crate) lang: Arc<Vec<String>>,
pub(crate) disco: DiscoInfoResult, pub(crate) disco: DiscoInfoResult,
pub(crate) node: String,
pub(crate) uploads: Vec<(String, Jid, PathBuf)>, pub(crate) uploads: Vec<(String, Jid, PathBuf)>,
pub(crate) awaiting_disco_bookmarks_type: bool, pub(crate) awaiting_disco_bookmarks_type: bool,
// Mapping of room->nick // Mapping of room->nick
@ -38,21 +35,11 @@ pub struct Agent {
} }
impl Agent { impl Agent {
pub fn new( pub fn new(client: TokioXmppClient, config: Config, disco: DiscoInfoResult) -> Agent {
client: TokioXmppClient,
config: Config,
default_nick: RoomNick,
lang: Vec<String>,
disco: DiscoInfoResult,
node: String,
) -> Agent {
Agent { Agent {
client, client,
config: Arc::new(RwLock::new(config)), config: Arc::new(RwLock::new(config)),
default_nick: Arc::new(RwLock::new(default_nick)),
lang: Arc::new(lang),
disco, disco,
node,
uploads: Vec::new(), uploads: Vec::new(),
awaiting_disco_bookmarks_type: false, awaiting_disco_bookmarks_type: false,
rooms_joined: HashMap::new(), rooms_joined: HashMap::new(),

View file

@ -6,10 +6,9 @@
#[cfg(feature = "starttls")] #[cfg(feature = "starttls")]
use crate::tokio_xmpp::connect::{DnsConfig, StartTlsServerConnector}; use crate::tokio_xmpp::connect::{DnsConfig, StartTlsServerConnector};
use core::str::FromStr;
use crate::{ use crate::{
Agent, ClientFeature, Config, RoomNick, Agent, ClientFeature, ClientType, Config, RoomNick,
jid::{BareJid, Jid, ResourceRef}, jid::{BareJid, Jid, ResourceRef},
parsers::{ parsers::{
disco::{DiscoInfoResult, Feature, Identity}, disco::{DiscoInfoResult, Feature, Identity},
@ -18,36 +17,11 @@ use crate::{
tokio_xmpp::{Client as TokioXmppClient, connect::ServerConnector, xmlstream::Timeouts}, tokio_xmpp::{Client as TokioXmppClient, connect::ServerConnector, xmlstream::Timeouts},
}; };
#[derive(Debug)]
pub enum ClientType {
Bot,
Pc,
}
impl Default for ClientType {
fn default() -> Self {
ClientType::Bot
}
}
impl ToString for ClientType {
fn to_string(&self) -> String {
String::from(match self {
ClientType::Bot => "bot",
ClientType::Pc => "pc",
})
}
}
pub struct ClientBuilder<'a, C: ServerConnector> { pub struct ClientBuilder<'a, C: ServerConnector> {
jid: BareJid, jid: BareJid,
password: &'a str, password: &'a str,
server_connector: C, server_connector: C,
config: Config, config: Config,
website: String,
default_nick: RoomNick,
lang: Vec<String>,
disco: (ClientType, String),
features: Vec<ClientFeature>, features: Vec<ClientFeature>,
resource: Option<String>, resource: Option<String>,
timeouts: Timeouts, timeouts: Timeouts,
@ -75,10 +49,6 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
password, password,
server_connector, server_connector,
config: Config::default(), 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")],
disco: (ClientType::default(), String::from("tokio-xmpp")),
features: vec![], features: vec![],
resource: None, resource: None,
timeouts: Timeouts::default(), timeouts: Timeouts::default(),
@ -97,22 +67,22 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
} }
pub fn set_client(mut self, type_: ClientType, name: &str) -> Self { pub fn set_client(mut self, type_: ClientType, name: &str) -> Self {
self.disco = (type_, String::from(name)); self.config.disco = (type_, String::from(name));
self self
} }
pub fn set_website(mut self, url: &str) -> Self { pub fn set_website(mut self, url: &str) -> Self {
self.website = String::from(url); self.config.website = String::from(url);
self self
} }
pub fn set_default_nick(mut self, nick: impl AsRef<ResourceRef>) -> Self { pub fn set_default_nick(mut self, nick: impl AsRef<ResourceRef>) -> Self {
self.default_nick = RoomNick::from_resource_ref(nick.as_ref()); self.config.default_nick = RoomNick::from_resource_ref(nick.as_ref());
self self
} }
pub fn set_lang(mut self, lang: Vec<String>) -> Self { pub fn set_lang(mut self, lang: Vec<String>) -> Self {
self.lang = lang; self.config.lang = lang;
self self
} }
@ -133,9 +103,9 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
fn make_disco(&self) -> DiscoInfoResult { fn make_disco(&self) -> DiscoInfoResult {
let identities = vec![Identity::new( let identities = vec![Identity::new(
"client", "client",
self.disco.0.to_string(), self.config.disco.0.to_string(),
"en", "en",
self.disco.1.to_string(), self.config.disco.1.to_string(),
)]; )];
let mut features = vec![Feature::new(ns::DISCO_INFO)]; let mut features = vec![Feature::new(ns::DISCO_INFO)];
#[cfg(feature = "avatars")] #[cfg(feature = "avatars")]
@ -174,15 +144,7 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
// This function is meant to be used for testing build // This function is meant to be used for testing build
pub(crate) fn build_impl(self, client: TokioXmppClient) -> Agent { pub(crate) fn build_impl(self, client: TokioXmppClient) -> Agent {
let disco = self.make_disco(); let disco = self.make_disco();
let node = self.website;
Agent::new( Agent::new(client, self.config, disco)
client,
self.config,
self.default_nick,
self.lang,
disco,
node,
)
} }
} }

View file

@ -4,7 +4,33 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use crate::RoomNick;
use core::str::FromStr;
/// [Disco](https://xmpp.org/registrar/disco-categories.html#client) identity type
#[derive(Debug)]
pub enum ClientType {
Bot,
Pc,
}
impl Default for ClientType {
fn default() -> Self {
ClientType::Bot
}
}
impl ToString for ClientType {
fn to_string(&self) -> String {
String::from(match self {
ClientType::Bot => "bot",
ClientType::Pc => "pc",
})
}
}
/// Store Agent configuration. Differs from state which is generated at runtime /// Store Agent configuration. Differs from state which is generated at runtime
#[derive(Debug)]
pub struct Config { pub struct Config {
/// Synchronize bookmarks based on autojoin flag. /// Synchronize bookmarks based on autojoin flag.
/// The client will join and leave based on the value of the `autojoin` flag on the (pubsub) /// The client will join and leave based on the value of the `autojoin` flag on the (pubsub)
@ -14,6 +40,18 @@ pub struct Config {
/// after the client is restarted, as these items won't be automatically joined anymore. /// after the client is restarted, as these items won't be automatically joined anymore.
/// <https://xmpp.org/extensions/xep-0402.html#notification> /// <https://xmpp.org/extensions/xep-0402.html#notification>
pub bookmarks_autojoin: bool, pub bookmarks_autojoin: bool,
/// Nickname to use if no other is specified.
pub default_nick: RoomNick,
/// Client “Disco” identity.
pub disco: (ClientType, String),
/// Default language conveyed in stanza. Mostly useful for messages content.
pub lang: Vec<String>,
/// Project website advertized in client capabilities.
pub website: String,
} }
impl Default for Config { impl Default for Config {
@ -26,6 +64,10 @@ impl Config {
fn new() -> Self { fn new() -> Self {
Config { Config {
bookmarks_autojoin: true, bookmarks_autojoin: true,
default_nick: RoomNick::from_str("xmpp-rs").unwrap(),
disco: (ClientType::default(), String::from("tokio-xmpp")),
lang: vec![String::from("en")],
website: String::from("https://gitlab.com/xmpp-rs/tokio-xmpp"),
} }
} }
} }

View file

@ -19,8 +19,11 @@ pub async fn wait_for_events(agent: &mut Agent) -> Vec<Event> {
match event { match event {
TokioXmppEvent::Online { resumed: false, .. } => { TokioXmppEvent::Online { resumed: false, .. } => {
let presence = let presence = presence::send::make_initial_presence(
presence::send::make_initial_presence(&agent.disco, &agent.node).into(); &agent.disco,
&agent.config.read().await.website,
)
.into();
let _ = agent.client.send_stanza(presence).await; let _ = agent.client.send_stanza(presence).await;
events.push(Event::Online); events.push(Event::Online);
// TODO: only send this when the ContactList feature is enabled. // TODO: only send this when the ContactList feature is enabled.

View file

@ -79,8 +79,8 @@ pub mod pubsub;
pub mod upload; pub mod upload;
pub use agent::Agent; pub use agent::Agent;
pub use builder::{ClientBuilder, ClientType}; pub use builder::ClientBuilder;
pub use config::Config; pub use config::{ClientType, Config};
pub use event::Event; pub use event::Event;
pub use feature::ClientFeature; pub use feature::ClientFeature;

View file

@ -18,7 +18,8 @@ pub async fn handle_message_chat(
message: &mut Message, message: &mut Message,
time_info: StanzaTimeInfo, time_info: StanzaTimeInfo,
) { ) {
let langs: Vec<&str> = agent.lang.iter().map(String::as_str).collect(); let config = agent.config.read().await;
let langs: Vec<&str> = config.lang.iter().map(String::as_str).collect();
let confirm = message.extract_valid_payload::<Confirm>(); let confirm = message.extract_valid_payload::<Confirm>();
let is_muc_pm = message.extract_valid_payload::<MucUser>().is_some(); let is_muc_pm = message.extract_valid_payload::<MucUser>().is_some();

View file

@ -18,7 +18,8 @@ pub async fn handle_message_group_chat(
message: &mut Message, message: &mut Message,
time_info: StanzaTimeInfo, time_info: StanzaTimeInfo,
) { ) {
let langs: Vec<&str> = agent.lang.iter().map(String::as_str).collect(); let config = agent.config.read().await;
let langs: Vec<&str> = config.lang.iter().map(String::as_str).collect();
let mut found_subject = false; let mut found_subject = false;
if let Some((_lang, subject)) = message.get_best_subject(langs.clone()) { if let Some((_lang, subject)) = message.get_best_subject(langs.clone()) {

View file

@ -78,7 +78,8 @@ pub async fn join_room<'a>(agent: &mut Agent, settings: JoinRoomSettings<'a>) {
let nick = if let Some(nick) = nick { let nick = if let Some(nick) = nick {
nick nick
} else { } else {
agent.default_nick.read().await.clone() let config = agent.config.read().await;
config.default_nick.clone()
}; };
let room_jid = room.with_resource(&nick); let room_jid = room.with_resource(&nick);