tokio_xmpp::AsyncClient and xmpp::Agent take a fully parsed Jid (#72)
This commit is contained in:
parent
7064ef5c17
commit
209bab1441
8 changed files with 56 additions and 36 deletions
3
tokio-xmpp/ChangeLog
Normal file
3
tokio-xmpp/ChangeLog
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
xxxxxxxxxx
|
||||||
|
* Breaking changes:
|
||||||
|
- AsyncClient::new takes a parsed Jid instead of string (#72)
|
|
@ -2,13 +2,14 @@ use futures::stream::StreamExt;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
use std::str::FromStr;
|
||||||
use tokio_xmpp::AsyncClient as Client;
|
use tokio_xmpp::AsyncClient as Client;
|
||||||
use xmpp_parsers::{
|
use xmpp_parsers::{
|
||||||
disco::{DiscoInfoQuery, DiscoInfoResult},
|
disco::{DiscoInfoQuery, DiscoInfoResult},
|
||||||
iq::{Iq, IqType},
|
iq::{Iq, IqType},
|
||||||
ns,
|
ns,
|
||||||
server_info::ServerInfo,
|
server_info::ServerInfo,
|
||||||
Element, Jid,
|
BareJid, Element, Jid,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -18,12 +19,12 @@ async fn main() {
|
||||||
println!("Usage: {} <jid> <password> <target>", args[0]);
|
println!("Usage: {} <jid> <password> <target>", args[0]);
|
||||||
exit(1);
|
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 password = args[2].clone();
|
||||||
let target = &args[3];
|
let target = &args[3];
|
||||||
|
|
||||||
// Client instance
|
// Client instance
|
||||||
let mut client = Client::new(jid, password).unwrap();
|
let mut client = Client::new(jid, password);
|
||||||
|
|
||||||
// Main loop, processes events
|
// Main loop, processes events
|
||||||
let mut wait_for_stream_end = false;
|
let mut wait_for_stream_end = false;
|
||||||
|
|
|
@ -22,7 +22,7 @@ use xmpp_parsers::{
|
||||||
NodeName,
|
NodeName,
|
||||||
},
|
},
|
||||||
stanza_error::{DefinedCondition, ErrorType, StanzaError},
|
stanza_error::{DefinedCondition, ErrorType, StanzaError},
|
||||||
Element, Jid,
|
BareJid, Element, Jid,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -32,11 +32,11 @@ async fn main() {
|
||||||
println!("Usage: {} <jid> <password>", args[0]);
|
println!("Usage: {} <jid> <password>", args[0]);
|
||||||
exit(1);
|
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 password = args[2].clone();
|
||||||
|
|
||||||
// Client instance
|
// Client instance
|
||||||
let mut client = Client::new(jid, password).unwrap();
|
let mut client = Client::new(jid.clone(), password);
|
||||||
|
|
||||||
let disco_info = make_disco();
|
let disco_info = make_disco();
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ async fn main() {
|
||||||
} else if let IqType::Result(Some(payload)) = iq.payload {
|
} else if let IqType::Result(Some(payload)) = iq.payload {
|
||||||
if payload.is("pubsub", ns::PUBSUB) {
|
if payload.is("pubsub", ns::PUBSUB) {
|
||||||
let pubsub = PubSub::try_from(payload).unwrap();
|
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);
|
handle_iq_result(pubsub, &from);
|
||||||
}
|
}
|
||||||
} else if let IqType::Set(_) = iq.payload {
|
} else if let IqType::Set(_) = iq.payload {
|
||||||
|
|
|
@ -2,11 +2,12 @@ use futures::stream::StreamExt;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
use std::str::FromStr;
|
||||||
use tokio;
|
use tokio;
|
||||||
use tokio_xmpp::AsyncClient as Client;
|
use tokio_xmpp::AsyncClient as Client;
|
||||||
use xmpp_parsers::message::{Body, Message, MessageType};
|
use xmpp_parsers::message::{Body, Message, MessageType};
|
||||||
use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType};
|
use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType};
|
||||||
use xmpp_parsers::{Element, Jid};
|
use xmpp_parsers::{BareJid, Element, Jid};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -15,11 +16,11 @@ async fn main() {
|
||||||
println!("Usage: {} <jid> <password>", args[0]);
|
println!("Usage: {} <jid> <password>", args[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
let jid = &args[1];
|
let jid = BareJid::from_str(&args[1]).expect(&format!("Invalid JID: {}", &args[1]));
|
||||||
let password = &args[2];
|
let password = &args[2];
|
||||||
|
|
||||||
// Client instance
|
// 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);
|
client.set_reconnect(true);
|
||||||
|
|
||||||
// Main loop, processes events
|
// Main loop, processes events
|
||||||
|
|
|
@ -2,7 +2,6 @@ use futures::{sink::SinkExt, task::Poll, Future, Sink, Stream};
|
||||||
use sasl::common::{ChannelBinding, Credentials};
|
use sasl::common::{ChannelBinding, Credentials};
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::task::Context;
|
use std::task::Context;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
@ -10,7 +9,7 @@ use tokio::task::JoinHandle;
|
||||||
use tokio_native_tls::TlsStream;
|
use tokio_native_tls::TlsStream;
|
||||||
#[cfg(feature = "tls-rust")]
|
#[cfg(feature = "tls-rust")]
|
||||||
use tokio_rustls::client::TlsStream;
|
use tokio_rustls::client::TlsStream;
|
||||||
use xmpp_parsers::{ns, Element, Jid, JidParseError};
|
use xmpp_parsers::{ns, Element, Jid};
|
||||||
|
|
||||||
use super::auth::auth;
|
use super::auth::auth;
|
||||||
use super::bind::bind;
|
use super::bind::bind;
|
||||||
|
@ -74,15 +73,13 @@ impl Client {
|
||||||
///
|
///
|
||||||
/// Start polling the returned instance so that it will connect
|
/// Start polling the returned instance so that it will connect
|
||||||
/// and yield events.
|
/// and yield events.
|
||||||
pub fn new<P: Into<String>>(jid: &str, password: P) -> Result<Self, JidParseError> {
|
pub fn new<J: Into<Jid>, P: Into<String>>(jid: J, password: P) -> Self {
|
||||||
let jid = Jid::from_str(jid)?;
|
|
||||||
let config = Config {
|
let config = Config {
|
||||||
jid: jid.clone(),
|
jid: jid.into(),
|
||||||
password: password.into(),
|
password: password.into(),
|
||||||
server: ServerConfig::UseSrv,
|
server: ServerConfig::UseSrv,
|
||||||
};
|
};
|
||||||
let client = Self::new_with_config(config);
|
Self::new_with_config(config)
|
||||||
Ok(client)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a new client given that the JID is already parsed.
|
/// Start a new client given that the JID is already parsed.
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
Unreleased:
|
Unreleased:
|
||||||
xxxxxxxxxx
|
xxxxxxxxxx
|
||||||
|
* Breaking changes:
|
||||||
|
- ClientBuilder::new takes a parsed BareJid instead of string (#72)
|
||||||
* Improvements:
|
* Improvements:
|
||||||
- Agent is now Send, by replacing Rc with Arc and RefCell with RwLock (#64)
|
- 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:
|
Version 0.4.0:
|
||||||
2023-05-18 [ Maxime “pep” Buquet <pep@bouah.net>, Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> ]
|
2023-05-18 [ Maxime “pep” Buquet <pep@bouah.net>, Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> ]
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
|
|
||||||
use env_logger;
|
use env_logger;
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
|
use std::str::FromStr;
|
||||||
use xmpp::{ClientBuilder, ClientFeature, ClientType, Event};
|
use xmpp::{ClientBuilder, ClientFeature, ClientType, Event};
|
||||||
use xmpp_parsers::{message::MessageType, Jid};
|
use xmpp_parsers::{message::MessageType, BareJid, Jid};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Option<()>> {
|
async fn main() -> Result<(), Option<()>> {
|
||||||
|
@ -18,7 +19,8 @@ async fn main() -> Result<(), Option<()>> {
|
||||||
println!("Usage: {} <jid> <password>", args[0]);
|
println!("Usage: {} <jid> <password>", args[0]);
|
||||||
return Err(None);
|
return Err(None);
|
||||||
}
|
}
|
||||||
let jid = &args[1];
|
|
||||||
|
let jid = BareJid::from_str(&args[1]).expect(&format!("Invalid JID: {}", &args[1]));
|
||||||
let password = &args[2];
|
let password = &args[2];
|
||||||
|
|
||||||
// Client instance
|
// Client instance
|
||||||
|
@ -29,8 +31,7 @@ async fn main() -> Result<(), Option<()>> {
|
||||||
.enable_feature(ClientFeature::Avatars)
|
.enable_feature(ClientFeature::Avatars)
|
||||||
.enable_feature(ClientFeature::ContactList)
|
.enable_feature(ClientFeature::ContactList)
|
||||||
.enable_feature(ClientFeature::JoinRooms)
|
.enable_feature(ClientFeature::JoinRooms)
|
||||||
.build()
|
.build();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
while let Some(events) = client.wait_for_events().await {
|
while let Some(events) = client.wait_for_events().await {
|
||||||
for event in events {
|
for event in events {
|
||||||
|
|
|
@ -94,19 +94,19 @@ pub enum Event {
|
||||||
HttpUploadedFile(String),
|
HttpUploadedFile(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ClientBuilder<'a> {
|
pub struct ClientBuilder<'a> {
|
||||||
jid: &'a str,
|
jid: BareJid,
|
||||||
password: &'a str,
|
password: &'a str,
|
||||||
website: String,
|
website: String,
|
||||||
default_nick: String,
|
default_nick: String,
|
||||||
lang: Vec<String>,
|
lang: Vec<String>,
|
||||||
disco: (ClientType, String),
|
disco: (ClientType, String),
|
||||||
features: Vec<ClientFeature>,
|
features: Vec<ClientFeature>,
|
||||||
|
resource: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientBuilder<'_> {
|
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 {
|
ClientBuilder {
|
||||||
jid,
|
jid,
|
||||||
password,
|
password,
|
||||||
|
@ -115,9 +115,16 @@ impl ClientBuilder<'_> {
|
||||||
lang: vec![String::from("en")],
|
lang: vec![String::from("en")],
|
||||||
disco: (ClientType::default(), String::from("tokio-xmpp")),
|
disco: (ClientType::default(), String::from("tokio-xmpp")),
|
||||||
features: vec![],
|
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 {
|
pub fn set_client(mut self, type_: ClientType, name: &str) -> Self {
|
||||||
self.disco = (type_, String::from(name));
|
self.disco = (type_, String::from(name));
|
||||||
self
|
self
|
||||||
|
@ -168,26 +175,30 @@ impl ClientBuilder<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Result<Agent, Error> {
|
pub fn build(self) -> Agent {
|
||||||
let client = TokioXmppClient::new(self.jid, self.password)?;
|
let jid: Jid = if let Some(resource) = &self.resource {
|
||||||
Ok(self.build_impl(client)?)
|
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
|
// This function is meant to be used for testing build
|
||||||
pub(crate) fn build_impl(self, client: TokioXmppClient) -> Result<Agent, Error> {
|
pub(crate) fn build_impl(self, client: TokioXmppClient) -> Agent {
|
||||||
let disco = self.make_disco();
|
let disco = self.make_disco();
|
||||||
let node = self.website;
|
let node = self.website;
|
||||||
|
|
||||||
let agent = Agent {
|
Agent {
|
||||||
client,
|
client,
|
||||||
default_nick: Arc::new(RwLock::new(self.default_nick)),
|
default_nick: Arc::new(RwLock::new(self.default_nick)),
|
||||||
lang: Arc::new(self.lang),
|
lang: Arc::new(self.lang),
|
||||||
disco,
|
disco,
|
||||||
node,
|
node,
|
||||||
uploads: Vec::new(),
|
uploads: Vec::new(),
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(agent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,22 +520,25 @@ async fn handle_upload_result(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
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;
|
use tokio_xmpp::AsyncClient as TokioXmppClient;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_simple() {
|
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
|
// Client instance
|
||||||
let client_builder = ClientBuilder::new("foo@bar", "meh")
|
let client_builder = ClientBuilder::new(jid, "meh")
|
||||||
.set_client(ClientType::Bot, "xmpp-rs")
|
.set_client(ClientType::Bot, "xmpp-rs")
|
||||||
.set_website("https://gitlab.com/xmpp-rs/xmpp-rs")
|
.set_website("https://gitlab.com/xmpp-rs/xmpp-rs")
|
||||||
.set_default_nick("bot")
|
.set_default_nick("bot")
|
||||||
.enable_feature(ClientFeature::Avatars)
|
.enable_feature(ClientFeature::Avatars)
|
||||||
.enable_feature(ClientFeature::ContactList);
|
.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 {
|
while let Some(events) = agent.wait_for_events().await {
|
||||||
assert!(match events[0] {
|
assert!(match events[0] {
|
||||||
|
|
Loading…
Reference in a new issue