diff --git a/Cargo.lock b/Cargo.lock index 302b723..306ce86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "MacTypes-sys" version = "2.1.0" @@ -1374,7 +1376,7 @@ dependencies = [ "trust-dns-proto 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xmpp-parsers 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1562,7 +1564,7 @@ dependencies = [ [[package]] name = "xmpp-parsers" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1755,4 +1757,4 @@ dependencies = [ "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd7ebf0203c620906230ce22caa5df0b603c32b6fef72a275a48f6a2ae64b9" -"checksum xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "58b4400e1ae0d246044db5fa7f2e693fdfe9cc6e8eaa72ef2a68c5dc1d3c96de" +"checksum xmpp-parsers 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c467bb13e01718be793cb7a1c3d38d0e9ba45898db306aa43e70657a8aa3c2f2" diff --git a/examples/contact_addr.rs b/examples/contact_addr.rs new file mode 100644 index 0000000..0d74f8e --- /dev/null +++ b/examples/contact_addr.rs @@ -0,0 +1,130 @@ +use futures::{future, Sink, Stream}; +use std::env::args; +use std::process::exit; +use tokio::runtime::current_thread::Runtime; +use tokio_xmpp::{Client, xmpp_codec::Packet}; +use xmpp_parsers::{ + Element, + Jid, + TryFrom, + ns, + iq::{ + Iq, + IqType, + }, + disco::{ + DiscoInfoResult, + DiscoInfoQuery, + }, + server_info::ServerInfo, +}; + +fn main() { + let args: Vec = args().collect(); + if args.len() != 4 { + println!("Usage: {} ", args[0]); + exit(1); + } + let jid = &args[1]; + let password = &args[2]; + let target = &args[3]; + + // tokio_core context + let mut rt = Runtime::new().unwrap(); + // Client instance + let client = Client::new(jid, password).unwrap(); + + // Make the two interfaces for sending and receiving independent + // of each other so we can move one into a closure. + let (mut sink, stream) = client.split(); + // Wrap sink in Option so that we can take() it for the send(self) + // to consume and return it back when ready. + let mut send = move |packet| { + sink.start_send(packet).expect("start_send"); + }; + // Main loop, processes events + let mut wait_for_stream_end = false; + let done = stream.for_each(|event| { + if wait_for_stream_end { + /* Do Nothing. */ + } else if event.is_online() { + println!("Online!"); + + let target_jid: Jid = target.clone().parse().unwrap(); + let iq = make_disco_iq(target_jid); + println!("Sending disco#info request to {}", target.clone()); + println!(">> {}", String::from(&iq)); + send(Packet::Stanza(iq)); + } else if let Some(stanza) = event.into_stanza() { + if stanza.is("iq", "jabber:client") { + let iq = Iq::try_from(stanza).unwrap(); + if let IqType::Result(Some(payload)) = iq.payload { + if payload.is("query", ns::DISCO_INFO) { + if let Ok(disco_info) = DiscoInfoResult::try_from(payload) { + for ext in disco_info.extensions { + if let Ok(server_info) = ServerInfo::try_from(ext) { + print_server_info(server_info); + wait_for_stream_end = true; + send(Packet::StreamEnd); + } + } + } + } + } + } + } + + Box::new(future::ok(())) + }); + + // Start polling `done` + match rt.block_on(done) { + Ok(_) => (), + Err(e) => { + println!("Fatal: {}", e); + () + } + } +} + +fn make_disco_iq(target: Jid) -> Element { + Iq::from_get("disco", DiscoInfoQuery { node: None }) + .with_id(String::from("contact")) + .with_to(target) + .into() +} + +fn convert_field(field: Vec) -> String { + field.iter() + .fold((field.len(), String::new()), |(l, mut acc), s| { + acc.push('<'); + acc.push_str(&s); + acc.push('>'); + if l > 1 { + acc.push(','); + acc.push(' '); + } + (0, acc) + }).1 +} + +fn print_server_info(server_info: ServerInfo) { + if server_info.abuse.len() != 0 { + println!("abuse: {}", convert_field(server_info.abuse)); + } + if server_info.admin.len() != 0 { + println!("admin: {}", convert_field(server_info.admin)); + } + if server_info.feedback.len() != 0 { + println!("feedback: {}", convert_field(server_info.feedback)); + } + if server_info.sales.len() != 0 { + println!("sales: {}", convert_field(server_info.sales)); + } + if server_info.security.len() != 0 { + println!("security: {}", convert_field(server_info.security)); + } + if server_info.support.len() != 0 { + println!("support: {}", convert_field(server_info.support)); + } +}