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