echo_bot.rs

 1extern crate futures;
 2extern crate tokio_core;
 3extern crate tokio_xmpp;
 4extern crate jid;
 5extern crate xml;
 6
 7use tokio_core::reactor::Core;
 8use futures::{Future, Stream, Sink, future};
 9use tokio_xmpp::Client;
10
11fn main() {
12    // Tokio_core context
13    let mut core = Core::new().unwrap();
14    // Client instance
15    let client = Client::new("astrobot@example.org", "", &core.handle()).unwrap();
16
17    // Make the two interfaces for sending and receiving independent
18    // of each other so we can move one into a closure.
19    let (sink, stream) = client.split();
20    // Wrap sink in Option so that we can take() it for the send(self)
21    // to consume and return it back when ready.
22    let mut sink = Some(sink);
23    let mut send = move |stanza| {
24        sink = Some(
25            sink.take().
26                expect("sink")
27                .send(stanza)
28                .wait()
29                .expect("sink.send")
30        );
31    };
32    // Main loop, processes events
33    let done = stream.for_each(|event| {
34        if event.is_online() {
35            println!("Online!");
36
37            let presence = make_presence();
38            send(presence);
39        } else if let Some(stanza) = event.as_stanza() {
40            if stanza.name == "message" &&
41                stanza.get_attribute("type", None) != Some("error") {
42                    // This is a message we'll echo
43                    let from = stanza.get_attribute("from", None);
44                    let body = stanza.get_child("body", Some("jabber:client"))
45                        .map(|el| el.content_str());
46
47                    match (from.as_ref(), body) {
48                        (Some(from), Some(body)) => {
49                            let reply = make_reply(from, body);
50                            send(reply);
51                        },
52                        _ => (),
53                    };
54                }
55        }
56
57        Box::new(future::ok(()))
58    });
59
60    // Start polling `done`
61    match core.run(done) {
62        Ok(_) => (),
63        Err(e) => {
64            println!("Fatal: {}", e);
65            ()
66        }
67    }
68}
69
70// Construct a <presence/>
71fn make_presence() -> xml::Element {
72    let mut presence = xml::Element::new("presence".to_owned(), None, vec![]);
73    presence.tag(xml::Element::new("status".to_owned(), None, vec![]))
74        .text("chat".to_owned());
75    presence.tag(xml::Element::new("show".to_owned(), None, vec![]))
76        .text("Echoing messages".to_owned());
77    presence
78}
79
80// Construct a chat <message/>
81fn make_reply(to: &str, body: String) -> xml::Element {
82    let mut message = xml::Element::new(
83        "message".to_owned(),
84        None,
85        vec![("type".to_owned(), None, "chat".to_owned()),
86             ("to".to_owned(), None, to.to_owned())]
87    );
88    message.tag(xml::Element::new("body".to_owned(), None, vec![]))
89        .text(body);
90    message
91}