echo_bot.rs

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