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