bot_framework/
lib.rs

1use std::collections::HashMap;
2
3use futures::stream::Stream;
4use telegram_bot::types::{InlineQuery, Message, MessageKind, Update, UpdateKind};
5use telegram_bot::Api;
6use tokio_core::reactor::Core;
7
8pub struct BotWrapper<B: BotHandler> {
9    api: Api,
10    core: Core,
11    commands: HashMap<String, Box<dyn Fn(&Api, &Message) -> ()>>,
12    handler: B,
13}
14
15impl BotWrapper<NoBotHandler> {
16    pub fn new(token: String) -> BotWrapper<NoBotHandler> {
17        let core = Core::new().expect("Failed to execute tokio core");
18
19        let api = Api::configure(token.clone())
20            .build(core.handle())
21            .expect("Failed to spawn bot threads");
22        BotWrapper {
23            api,
24            core,
25            commands: HashMap::new(),
26            handler: NoBotHandler,
27        }
28    }
29}
30
31impl<B: BotHandler> BotWrapper<B> {
32    fn handle_update(
33        api: &Api,
34        commands: &HashMap<String, Box<dyn Fn(&Api, &Message) -> ()>>,
35        update: Update,
36        handler: &B
37    ) {
38        if let UpdateKind::Message(ref msg) = update.kind {
39            if let MessageKind::Text {
40                ref data,
41                entities: _,
42            } = msg.kind
43            {
44                let data = data.clone().split_off(1);
45                let data = data.split_whitespace().next().unwrap_or("");
46                commands.get(data).map(|command| command(api, msg));
47                return;
48            }
49        }
50
51        match update.kind {
52            UpdateKind::InlineQuery(query) => handler.inline_query(api, query),
53            _ => ()
54        }
55    }
56
57    pub fn new_with_handler(token: String, handler: B) -> BotWrapper<B> {
58        let core = Core::new().expect("Failed to execute tokio core");
59
60        let api = Api::configure(token.clone())
61            .build(core.handle())
62            .expect("Failed to spawn bot threads");
63        BotWrapper {
64            api,
65            core,
66            commands: HashMap::new(),
67            handler,
68        }
69    }
70
71    pub fn run(self) {
72        let BotWrapper {
73            api,
74            mut core,
75            commands,
76            handler,
77        } = self;
78        let update_stream = api
79            .stream()
80            .for_each(|update| Ok(BotWrapper::handle_update(&api, &commands, update, &handler)));
81
82        core.run(update_stream).expect("Failed to run core reactor");
83    }
84
85    pub fn command<F>(&mut self, command: String, handle: F)
86    where
87        F: 'static + Fn(&Api, &Message) -> (),
88    {
89        self.commands.insert(command, Box::new(handle));
90    }
91}
92
93#[allow(unused_variables)]
94pub trait BotHandler {
95    fn inline_query(&self, api: &Api, query: InlineQuery) {}
96}
97
98pub struct NoBotHandler;
99impl BotHandler for NoBotHandler {}