1use futures::stream::StreamExt;
2use std::convert::TryFrom;
3use std::env::args;
4use std::process::exit;
5use std::str::FromStr;
6use tokio;
7use tokio_xmpp::AsyncClient as Client;
8use xmpp_parsers::message::{Body, Message, MessageType};
9use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType};
10use xmpp_parsers::{BareJid, Element, Jid};
11
12#[tokio::main]
13async fn main() {
14 env_logger::init();
15
16 let args: Vec<String> = args().collect();
17 if args.len() != 3 {
18 println!("Usage: {} <jid> <password>", args[0]);
19 exit(1);
20 }
21 let jid = BareJid::from_str(&args[1]).expect(&format!("Invalid JID: {}", &args[1]));
22 let password = &args[2];
23
24 // Client instance
25 let mut client = Client::new(jid, password.to_owned());
26 client.set_reconnect(true);
27
28 // Main loop, processes events
29 let mut wait_for_stream_end = false;
30 let mut stream_ended = false;
31 while !stream_ended {
32 if let Some(event) = client.next().await {
33 println!("event: {:?}", event);
34 if wait_for_stream_end {
35 /* Do nothing */
36 } else if event.is_online() {
37 let jid = event
38 .get_jid()
39 .map(|jid| format!("{}", jid))
40 .unwrap_or("unknown".to_owned());
41 println!("Online at {}", jid);
42
43 let presence = make_presence();
44 client.send_stanza(presence).await.unwrap();
45 } else if let Some(message) = event
46 .into_stanza()
47 .and_then(|stanza| Message::try_from(stanza).ok())
48 {
49 match (message.from, message.bodies.get("")) {
50 (Some(ref from), Some(ref body)) if body.0 == "die" => {
51 println!("Secret die command triggered by {}", from);
52 wait_for_stream_end = true;
53 client.send_end().await.unwrap();
54 }
55 (Some(ref from), Some(ref body)) => {
56 if message.type_ != MessageType::Error {
57 // This is a message we'll echo
58 let reply = make_reply(from.clone(), &body.0);
59 client.send_stanza(reply).await.unwrap();
60 }
61 }
62 _ => {}
63 }
64 }
65 } else {
66 println!("stream_ended");
67 stream_ended = true;
68 }
69 }
70}
71
72// Construct a <presence/>
73fn make_presence() -> Element {
74 let mut presence = Presence::new(PresenceType::None);
75 presence.show = Some(PresenceShow::Chat);
76 presence
77 .statuses
78 .insert(String::from("en"), String::from("Echoing messages."));
79 presence.into()
80}
81
82// Construct a chat <message/>
83fn make_reply(to: Jid, body: &str) -> Element {
84 let mut message = Message::new(Some(to));
85 message.bodies.insert(String::new(), Body(body.to_owned()));
86 message.into()
87}