echo_bot.rs

 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}