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