diff --git a/tokio-xmpp/ChangeLog b/tokio-xmpp/ChangeLog new file mode 100644 index 00000000..00f8736c --- /dev/null +++ b/tokio-xmpp/ChangeLog @@ -0,0 +1,3 @@ +xxxxxxxxxx + * Breaking changes: + - AsyncClient::new takes a parsed Jid instead of string (#72) \ No newline at end of file diff --git a/tokio-xmpp/examples/contact_addr.rs b/tokio-xmpp/examples/contact_addr.rs index fcf65eba..65e1062c 100644 --- a/tokio-xmpp/examples/contact_addr.rs +++ b/tokio-xmpp/examples/contact_addr.rs @@ -2,13 +2,14 @@ use futures::stream::StreamExt; use std::convert::TryFrom; use std::env::args; use std::process::exit; +use std::str::FromStr; use tokio_xmpp::AsyncClient as Client; use xmpp_parsers::{ disco::{DiscoInfoQuery, DiscoInfoResult}, iq::{Iq, IqType}, ns, server_info::ServerInfo, - Element, Jid, + BareJid, Element, Jid, }; #[tokio::main] @@ -18,12 +19,12 @@ async fn main() { println!("Usage: {} ", args[0]); exit(1); } - let jid = &args[1]; + let jid = BareJid::from_str(&args[1]).expect(&format!("Invalid JID: {}", &args[1])); let password = args[2].clone(); let target = &args[3]; // Client instance - let mut client = Client::new(jid, password).unwrap(); + let mut client = Client::new(jid, password); // Main loop, processes events let mut wait_for_stream_end = false; diff --git a/tokio-xmpp/examples/download_avatars.rs b/tokio-xmpp/examples/download_avatars.rs index 7fbdf60c..2af1580c 100644 --- a/tokio-xmpp/examples/download_avatars.rs +++ b/tokio-xmpp/examples/download_avatars.rs @@ -22,7 +22,7 @@ use xmpp_parsers::{ NodeName, }, stanza_error::{DefinedCondition, ErrorType, StanzaError}, - Element, Jid, + BareJid, Element, Jid, }; #[tokio::main] @@ -32,11 +32,11 @@ async fn main() { println!("Usage: {} ", args[0]); exit(1); } - let jid = &args[1]; + let jid = BareJid::from_str(&args[1]).expect(&format!("Invalid JID: {}", &args[1])); let password = args[2].clone(); // Client instance - let mut client = Client::new(jid, password).unwrap(); + let mut client = Client::new(jid.clone(), password); let disco_info = make_disco(); @@ -94,7 +94,7 @@ async fn main() { } else if let IqType::Result(Some(payload)) = iq.payload { if payload.is("pubsub", ns::PUBSUB) { let pubsub = PubSub::try_from(payload).unwrap(); - let from = iq.from.clone().unwrap_or(Jid::from_str(jid).unwrap()); + let from = iq.from.clone().unwrap_or(jid.clone().into()); handle_iq_result(pubsub, &from); } } else if let IqType::Set(_) = iq.payload { diff --git a/tokio-xmpp/examples/echo_bot.rs b/tokio-xmpp/examples/echo_bot.rs index dcc4b020..eed8c2e6 100644 --- a/tokio-xmpp/examples/echo_bot.rs +++ b/tokio-xmpp/examples/echo_bot.rs @@ -2,11 +2,12 @@ use futures::stream::StreamExt; use std::convert::TryFrom; use std::env::args; use std::process::exit; +use std::str::FromStr; use tokio; use tokio_xmpp::AsyncClient as Client; use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; -use xmpp_parsers::{Element, Jid}; +use xmpp_parsers::{BareJid, Element, Jid}; #[tokio::main] async fn main() { @@ -15,11 +16,11 @@ async fn main() { println!("Usage: {} ", args[0]); exit(1); } - let jid = &args[1]; + let jid = BareJid::from_str(&args[1]).expect(&format!("Invalid JID: {}", &args[1])); let password = &args[2]; // Client instance - let mut client = Client::new(jid, password.to_owned()).unwrap(); + let mut client = Client::new(jid, password.to_owned()); client.set_reconnect(true); // Main loop, processes events diff --git a/tokio-xmpp/src/client/async_client.rs b/tokio-xmpp/src/client/async_client.rs index 2d233ff5..44d9bdf9 100644 --- a/tokio-xmpp/src/client/async_client.rs +++ b/tokio-xmpp/src/client/async_client.rs @@ -2,7 +2,6 @@ use futures::{sink::SinkExt, task::Poll, Future, Sink, Stream}; use sasl::common::{ChannelBinding, Credentials}; use std::mem::replace; use std::pin::Pin; -use std::str::FromStr; use std::task::Context; use tokio::net::TcpStream; use tokio::task::JoinHandle; @@ -10,7 +9,7 @@ use tokio::task::JoinHandle; use tokio_native_tls::TlsStream; #[cfg(feature = "tls-rust")] use tokio_rustls::client::TlsStream; -use xmpp_parsers::{ns, Element, Jid, JidParseError}; +use xmpp_parsers::{ns, Element, Jid}; use super::auth::auth; use super::bind::bind; @@ -74,15 +73,13 @@ impl Client { /// /// Start polling the returned instance so that it will connect /// and yield events. - pub fn new>(jid: &str, password: P) -> Result { - let jid = Jid::from_str(jid)?; + pub fn new, P: Into>(jid: J, password: P) -> Self { let config = Config { - jid: jid.clone(), + jid: jid.into(), password: password.into(), server: ServerConfig::UseSrv, }; - let client = Self::new_with_config(config); - Ok(client) + Self::new_with_config(config) } /// Start a new client given that the JID is already parsed. diff --git a/xmpp/ChangeLog b/xmpp/ChangeLog index 9071140d..40fdee49 100644 --- a/xmpp/ChangeLog +++ b/xmpp/ChangeLog @@ -1,7 +1,10 @@ Unreleased: xxxxxxxxxx + * Breaking changes: + - ClientBuilder::new takes a parsed BareJid instead of string (#72) * Improvements: - Agent is now Send, by replacing Rc with Arc and RefCell with RwLock (#64) + - ClientBuilder now has a set_resource method for manual resource management (#72) Version 0.4.0: 2023-05-18 [ Maxime “pep” Buquet , Emmanuel Gil Peyrot ] diff --git a/xmpp/examples/hello_bot.rs b/xmpp/examples/hello_bot.rs index 791e33f8..74b56c1a 100644 --- a/xmpp/examples/hello_bot.rs +++ b/xmpp/examples/hello_bot.rs @@ -6,8 +6,9 @@ use env_logger; use std::env::args; +use std::str::FromStr; use xmpp::{ClientBuilder, ClientFeature, ClientType, Event}; -use xmpp_parsers::{message::MessageType, Jid}; +use xmpp_parsers::{message::MessageType, BareJid, Jid}; #[tokio::main] async fn main() -> Result<(), Option<()>> { @@ -18,7 +19,8 @@ async fn main() -> Result<(), Option<()>> { println!("Usage: {} ", args[0]); return Err(None); } - let jid = &args[1]; + + let jid = BareJid::from_str(&args[1]).expect(&format!("Invalid JID: {}", &args[1])); let password = &args[2]; // Client instance @@ -29,8 +31,7 @@ async fn main() -> Result<(), Option<()>> { .enable_feature(ClientFeature::Avatars) .enable_feature(ClientFeature::ContactList) .enable_feature(ClientFeature::JoinRooms) - .build() - .unwrap(); + .build(); while let Some(events) = client.wait_for_events().await { for event in events { diff --git a/xmpp/src/lib.rs b/xmpp/src/lib.rs index ae2a7dce..7df2300b 100644 --- a/xmpp/src/lib.rs +++ b/xmpp/src/lib.rs @@ -94,19 +94,19 @@ pub enum Event { HttpUploadedFile(String), } -#[derive(Default)] pub struct ClientBuilder<'a> { - jid: &'a str, + jid: BareJid, password: &'a str, website: String, default_nick: String, lang: Vec, disco: (ClientType, String), features: Vec, + resource: Option, } impl ClientBuilder<'_> { - pub fn new<'a>(jid: &'a str, password: &'a str) -> ClientBuilder<'a> { + pub fn new<'a>(jid: BareJid, password: &'a str) -> ClientBuilder<'a> { ClientBuilder { jid, password, @@ -115,9 +115,16 @@ impl ClientBuilder<'_> { lang: vec![String::from("en")], disco: (ClientType::default(), String::from("tokio-xmpp")), features: vec![], + resource: None, } } + /// Optionally set a resource associated to this device on the client + pub fn set_resource(mut self, resource: &str) -> Self { + self.resource = Some(resource.to_string()); + self + } + pub fn set_client(mut self, type_: ClientType, name: &str) -> Self { self.disco = (type_, String::from(name)); self @@ -168,26 +175,30 @@ impl ClientBuilder<'_> { } } - pub fn build(self) -> Result { - let client = TokioXmppClient::new(self.jid, self.password)?; - Ok(self.build_impl(client)?) + pub fn build(self) -> Agent { + let jid: Jid = if let Some(resource) = &self.resource { + self.jid.clone().with_resource(resource.to_string()).into() + } else { + self.jid.clone().into() + }; + + let client = TokioXmppClient::new(jid, self.password); + self.build_impl(client) } // This function is meant to be used for testing build - pub(crate) fn build_impl(self, client: TokioXmppClient) -> Result { + pub(crate) fn build_impl(self, client: TokioXmppClient) -> Agent { let disco = self.make_disco(); let node = self.website; - let agent = Agent { + Agent { client, default_nick: Arc::new(RwLock::new(self.default_nick)), lang: Arc::new(self.lang), disco, node, uploads: Vec::new(), - }; - - Ok(agent) + } } } @@ -509,22 +520,25 @@ async fn handle_upload_result( #[cfg(test)] mod tests { - use super::{Agent, ClientBuilder, ClientFeature, ClientType, Event}; + use super::{Agent, BareJid, ClientBuilder, ClientFeature, ClientType, Event}; + use std::str::FromStr; use tokio_xmpp::AsyncClient as TokioXmppClient; #[tokio::test] async fn test_simple() { - let client = TokioXmppClient::new("foo@bar", "meh").unwrap(); + let jid = BareJid::from_str("foo@bar").unwrap(); + + let client = TokioXmppClient::new(jid.clone(), "meh"); // Client instance - let client_builder = ClientBuilder::new("foo@bar", "meh") + let client_builder = ClientBuilder::new(jid, "meh") .set_client(ClientType::Bot, "xmpp-rs") .set_website("https://gitlab.com/xmpp-rs/xmpp-rs") .set_default_nick("bot") .enable_feature(ClientFeature::Avatars) .enable_feature(ClientFeature::ContactList); - let mut agent: Agent = client_builder.build_impl(client).unwrap(); + let mut agent: Agent = client_builder.build_impl(client); while let Some(events) = agent.wait_for_events().await { assert!(match events[0] {