telegram_api_rs2/
methods.rs

1//! This module contains all available methods to use the Bot API</br>
2//! To get started, you first have to create a bot
3//! ```ignore
4//! let bot = Bot::new("your_bot_api_key".to_json());
5//! ```
6//! Afterwards you can use the bot, e.g.:
7//! ```ignore
8//! bot.get_me();
9//! ```
10
11extern crate json;
12extern crate rustc_serialize;
13extern crate urlencoding;
14
15use crate::objects::*;
16use crate::*;
17use json::JsonValue;
18use std::sync::mpsc::Sender;
19use std::thread;
20
21pub struct Bot {
22    key: String,
23    offset: i64,
24}
25
26const BASE_URL: &str = "https://api.telegram.org/bot";
27
28impl Bot {
29    pub fn new<'a>(api_key: String) -> Bot {
30        Bot {
31            key: api_key,
32            offset: 0,
33        }
34    }
35
36    /// start_polling is used to get updates from the bot.
37    /// ```ignore
38    /// let (tx, rx) = mpsc::channel();
39    /// bot.start_polling(tx);
40    /// let received = rx.recv().unwrap();
41    /// println!("Got: {}", received);
42    /// ```
43
44    pub fn start_polling(&mut self, tx: Sender<Update>) {
45        let mut bot = self.clone();
46        thread::spawn(move || loop {
47            let updates = bot.get_updates(None, None, None);
48            match updates {
49                Some(us) => {
50                    for u in us {
51                        assert!(tx.send(u).is_ok());
52                    }
53                }
54                None => (),
55            };
56        });
57    }
58
59    fn send_request(&self, method: String, parameters: String) -> JsonValue {
60        let request = format!("{}{}/{}?{}", BASE_URL, self.key, method, parameters);
61        // println!("{}", request);
62        let res = reqwest::blocking::get(request);
63        let mut json_response = JsonValue::Null;
64        match res {
65            Ok(r) => match r.text() {
66                Ok(result) => json_response = json::parse(&*result).unwrap(),
67                Err(_) => (),
68            },
69            Err(_) => (),
70        }
71        json_response
72    }
73
74    pub fn get_updates(
75        &mut self,
76        limit: Option<i32>,
77        timeout: Option<i32>,
78        allowed_updates: Option<Vec<String>>,
79    ) -> Option<Vec<Update>> {
80        let mut parameters = "".to_string();
81        parameters.push_str(&*format!("offset={}&", self.offset));
82        match limit {
83            Some(o) => parameters.push_str(&*format!("limit={}&", Custom::to_json(o))),
84            None => (),
85        }
86        match timeout {
87            Some(o) => parameters.push_str(&*format!("timeout={}&", Custom::to_json(o))),
88            None => (),
89        }
90        match allowed_updates {
91            Some(o) => parameters.push_str(&*format!("allowed_updates={}&", Custom::to_json(o))),
92            None => (),
93        }
94        parameters.pop();
95        let res = self.send_request("getUpdates".to_string(), parameters);
96        let ret: Vec<Update> = Custom::from_json(res["result"].clone());
97        if !res["ok"].as_bool().unwrap() || ret.len() == 0 {
98            None
99        } else {
100            self.offset = ret[ret.len() - 1].clone().update_id + 1;
101            self.send_request("getUpdates".to_string(), format!("offset={}", self.offset));
102            Some(ret)
103        }
104    }
105
106    pub fn get_me(&mut self) -> User {
107        let res = self.send_request("getMe".to_string(), "".to_string());
108        if !res["ok"].as_bool().unwrap() {
109            User::empty()
110        } else {
111            let ret: User = Custom::from_json(res["result"].clone());
112            ret
113        }
114    }
115
116    pub fn send_message(
117        &mut self,
118        chat_id: i64,
119        text: String,
120        parse_mode: Option<String>,
121        entities: Option<Vec<MessageEntity>>,
122        disable_web_page_preview: Option<bool>,
123        disable_notification: Option<bool>,
124        reply_to_message_id: Option<i32>,
125        allow_sending_without_reply: Option<bool>,
126        reply_markup_ikm: Option<InlineKeyboardMarkup>,
127        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
128        reply_markup_rkr: Option<ReplyKeyboardRemove>,
129        reply_markup_fr: Option<ForceReply>,
130    ) -> Option<Message> {
131        let mut parameters = "".to_string();
132        expand_parameters_into_string! {
133            parameters, chat_id, text
134        }
135        expand_parameters_opt_into_string! {
136            parameters, parse_mode, entities, disable_web_page_preview, disable_notification, reply_to_message_id,
137            allow_sending_without_reply
138        }
139        expand_parameters_reply_markup_into_string! {
140            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
141        }
142        parameters.pop();
143        let res = self.send_request("sendMessage".to_string(), parameters);
144        expand_make_request_to_message! {
145            res
146        }
147    }
148
149    pub fn forward_message(
150        &mut self,
151        chat_id: i64,
152        from_chat_id: i64,
153        message_id: i32,
154        disable_notification: Option<bool>,
155    ) -> Option<Message> {
156        let mut parameters = "".to_string();
157        expand_parameters_into_string! {
158            parameters, chat_id, from_chat_id, message_id
159        }
160        expand_parameters_opt_into_string! {
161            parameters, disable_notification
162        }
163        parameters.pop();
164        let res = self.send_request("ForwardMessage".to_string(), parameters);
165        expand_make_request_to_message! {
166            res
167        }
168    }
169
170    pub fn copy_message(
171        &mut self,
172        chat_id: i64,
173        from_chat_id: i64,
174        message_id: i32,
175        caption: Option<String>,
176        parse_mode: Option<String>,
177        caption_entities: Option<Vec<MessageEntity>>,
178        disable_notification: Option<bool>,
179        reply_to_message_id: Option<i32>,
180        allow_sending_without_reply: Option<bool>,
181        reply_markup_ikm: Option<InlineKeyboardMarkup>,
182        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
183        reply_markup_rkr: Option<ReplyKeyboardRemove>,
184        reply_markup_fr: Option<ForceReply>,
185    ) -> i32 {
186        let mut parameters = "".to_string();
187        expand_parameters_into_string! {
188            parameters, chat_id, from_chat_id, message_id
189        }
190        expand_parameters_opt_into_string! {
191            parameters, caption, parse_mode, caption_entities, disable_notification, reply_to_message_id,
192            allow_sending_without_reply
193        }
194        expand_parameters_reply_markup_into_string! {
195            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
196        }
197        parameters.pop();
198        let res = self.send_request("copyMessage".to_string(), parameters);
199        if !res["ok"].as_bool().unwrap() {
200            0
201        } else {
202            let ret: i32 = Custom::from_json(res["result"].clone());
203            ret
204        }
205    }
206
207    pub fn send_photo(
208        &mut self,
209        chat_id: i64,
210        photo: String,
211        caption: Option<String>,
212        parse_mode: Option<String>,
213        caption_entities: Option<Vec<MessageEntity>>,
214        disable_notification: Option<bool>,
215        reply_to_message_id: Option<i32>,
216        allow_sending_without_reply: Option<bool>,
217        reply_markup_ikm: Option<InlineKeyboardMarkup>,
218        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
219        reply_markup_rkr: Option<ReplyKeyboardRemove>,
220        reply_markup_fr: Option<ForceReply>,
221    ) -> Option<Message> {
222        let mut parameters = "".to_string();
223        expand_parameters_into_string! {
224            parameters, chat_id, photo
225        }
226        expand_parameters_opt_into_string! {
227            parameters, caption, parse_mode, caption_entities, disable_notification, reply_to_message_id,
228            allow_sending_without_reply
229        }
230        expand_parameters_reply_markup_into_string! {
231            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
232        }
233        parameters.pop();
234        let res = self.send_request("sendPhoto".to_string(), parameters);
235        expand_make_request_to_message! {
236            res
237        }
238    }
239
240    pub fn send_audio(
241        &mut self,
242        chat_id: i64,
243        audio: String,
244        caption: Option<String>,
245        parse_mode: Option<String>,
246        caption_entities: Option<Vec<MessageEntity>>,
247        duration: Option<i32>,
248        performer: Option<String>,
249        title: Option<String>,
250        thumb: Option<String>,
251        disable_notification: Option<bool>,
252        reply_to_message_id: Option<i32>,
253        allow_sending_without_reply: Option<bool>,
254        reply_markup_ikm: Option<InlineKeyboardMarkup>,
255        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
256        reply_markup_rkr: Option<ReplyKeyboardRemove>,
257        reply_markup_fr: Option<ForceReply>,
258    ) -> Option<Message> {
259        let mut parameters = "".to_string();
260        expand_parameters_into_string! {
261            parameters, chat_id, audio
262        }
263        expand_parameters_opt_into_string! {
264            parameters, caption, parse_mode, caption_entities, duration, performer, title, thumb, disable_notification, reply_to_message_id,
265            allow_sending_without_reply
266        }
267        expand_parameters_reply_markup_into_string! {
268            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
269        }
270        parameters.pop();
271        let res = self.send_request("sendAudio".to_string(), parameters);
272        expand_make_request_to_message! {
273            res
274        }
275    }
276
277    pub fn send_document(
278        &mut self,
279        chat_id: i64,
280        document: String,
281        thumb: Option<String>,
282        caption: Option<String>,
283        parse_mode: Option<String>,
284        caption_entities: Option<Vec<MessageEntity>>,
285        disable_content_type_detection: Option<bool>,
286        disable_notification: Option<bool>,
287        reply_to_message_id: Option<i32>,
288        allow_sending_without_reply: Option<bool>,
289        reply_markup_ikm: Option<InlineKeyboardMarkup>,
290        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
291        reply_markup_rkr: Option<ReplyKeyboardRemove>,
292        reply_markup_fr: Option<ForceReply>,
293    ) -> Option<Message> {
294        let mut parameters = "".to_string();
295        expand_parameters_into_string! {
296            parameters, chat_id, document
297        }
298        expand_parameters_opt_into_string! {
299            parameters, thumb, caption, parse_mode, caption_entities, disable_content_type_detection, disable_notification,
300            reply_to_message_id, allow_sending_without_reply
301        }
302        expand_parameters_reply_markup_into_string! {
303            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
304        }
305        parameters.pop();
306        let res = self.send_request("sendDocument".to_string(), parameters);
307        expand_make_request_to_message! {
308            res
309        }
310    }
311
312    pub fn send_video(
313        &mut self,
314        chat_id: i64,
315        video: String,
316        duration: Option<i32>,
317        width: Option<i32>,
318        height: Option<i32>,
319        thumb: Option<String>,
320        caption: Option<String>,
321        parse_mode: Option<String>,
322        caption_entities: Option<Vec<MessageEntity>>,
323        supports_streaming: Option<bool>,
324        disable_notification: Option<bool>,
325        reply_to_message_id: Option<i32>,
326        allow_sending_without_reply: Option<bool>,
327        reply_markup_ikm: Option<InlineKeyboardMarkup>,
328        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
329        reply_markup_rkr: Option<ReplyKeyboardRemove>,
330        reply_markup_fr: Option<ForceReply>,
331    ) -> Option<Message> {
332        let mut parameters = "".to_string();
333        expand_parameters_into_string! {
334            parameters, chat_id, video
335        }
336        expand_parameters_opt_into_string! {
337            parameters, duration, width, height, thumb, caption, parse_mode, caption_entities, supports_streaming,
338            disable_notification, reply_to_message_id, allow_sending_without_reply
339        }
340        expand_parameters_reply_markup_into_string! {
341            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
342        }
343        parameters.pop();
344        let res = self.send_request("sendVideo".to_string(), parameters);
345        expand_make_request_to_message! {
346            res
347        }
348    }
349
350    pub fn send_animation(
351        &mut self,
352        chat_id: i64,
353        animation: String,
354        duration: Option<i32>,
355        width: Option<i32>,
356        height: Option<i32>,
357        thumb: Option<String>,
358        caption: Option<String>,
359        parse_mode: Option<String>,
360        caption_entities: Option<Vec<MessageEntity>>,
361        disable_notification: Option<bool>,
362        reply_to_message_id: Option<i32>,
363        allow_sending_without_reply: Option<bool>,
364        reply_markup_ikm: Option<InlineKeyboardMarkup>,
365        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
366        reply_markup_rkr: Option<ReplyKeyboardRemove>,
367        reply_markup_fr: Option<ForceReply>,
368    ) -> Option<Message> {
369        let mut parameters = "".to_string();
370        expand_parameters_into_string! {
371            parameters, chat_id, animation
372        }
373        expand_parameters_opt_into_string! {
374            parameters, duration, width, height, thumb, caption, parse_mode, caption_entities,
375            disable_notification, reply_to_message_id, allow_sending_without_reply
376        }
377        expand_parameters_reply_markup_into_string! {
378            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
379        }
380        parameters.pop();
381        let res = self.send_request("sendAnimation".to_string(), parameters);
382        expand_make_request_to_message! {
383            res
384        }
385    }
386
387    pub fn send_voice(
388        &mut self,
389        chat_id: i64,
390        voice: String,
391        caption: Option<String>,
392        parse_mode: Option<String>,
393        caption_entities: Option<Vec<MessageEntity>>,
394        duration: Option<i32>,
395        disable_notification: Option<bool>,
396        reply_to_message_id: Option<i32>,
397        allow_sending_without_reply: Option<bool>,
398        reply_markup_ikm: Option<InlineKeyboardMarkup>,
399        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
400        reply_markup_rkr: Option<ReplyKeyboardRemove>,
401        reply_markup_fr: Option<ForceReply>,
402    ) -> Option<Message> {
403        let mut parameters = "".to_string();
404        expand_parameters_into_string! {
405            parameters, chat_id, voice
406        }
407        expand_parameters_opt_into_string! {
408            parameters, caption, parse_mode, caption_entities, duration,
409            disable_notification, reply_to_message_id, allow_sending_without_reply
410        }
411        expand_parameters_reply_markup_into_string! {
412            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
413        }
414        parameters.pop();
415        let res = self.send_request("sendVoice".to_string(), parameters);
416        expand_make_request_to_message! {
417            res
418        }
419    }
420
421    pub fn send_video_note(
422        &mut self,
423        chat_id: i64,
424        video_note: String,
425        duration: Option<i32>,
426        length: Option<i32>,
427        thumb: Option<String>,
428        disable_notification: Option<bool>,
429        reply_to_message_id: Option<i32>,
430        allow_sending_without_reply: Option<bool>,
431        reply_markup_ikm: Option<InlineKeyboardMarkup>,
432        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
433        reply_markup_rkr: Option<ReplyKeyboardRemove>,
434        reply_markup_fr: Option<ForceReply>,
435    ) -> Option<Message> {
436        let mut parameters = "".to_string();
437        expand_parameters_into_string! {
438            parameters, chat_id, video_note
439        }
440        expand_parameters_opt_into_string! {
441            parameters, duration, length, thumb, disable_notification, reply_to_message_id, allow_sending_without_reply
442        }
443        expand_parameters_reply_markup_into_string! {
444            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
445        }
446        parameters.pop();
447        let res = self.send_request("sendVideoNote".to_string(), parameters);
448        expand_make_request_to_message! {
449            res
450        }
451    }
452
453    pub fn send_media_group(
454        &mut self,
455        chat_id: i64,
456        media: Vec<InputMedia>,
457        disable_notification: Option<bool>,
458        reply_to_message_id: Option<i32>,
459        allow_sending_without_reply: Option<bool>,
460    ) -> Option<Vec<Message>> {
461        let mut parameters = "".to_string();
462        expand_parameters_into_string! {
463            parameters, chat_id, media
464        }
465        expand_parameters_opt_into_string! {
466            parameters, disable_notification, reply_to_message_id, allow_sending_without_reply
467        }
468        parameters.pop();
469        let res = self.send_request("sendMediaGroup".to_string(), parameters);
470        if !res["ok"].as_bool().unwrap() {
471            None
472        } else {
473            let ret: Vec<Message> = Custom::from_json(res["result"].clone());
474            Some(ret)
475        }
476    }
477
478    pub fn send_location(
479        &mut self,
480        chat_id: i64,
481        latitude: f64,
482        longitude: f64,
483        horizontal_accuracy: Option<f64>,
484        live_period: Option<i32>,
485        heading: Option<i32>,
486        proximity_alert_radius: Option<i32>,
487        disable_notification: Option<bool>,
488        reply_to_message_id: Option<i32>,
489        allow_sending_without_reply: Option<bool>,
490        reply_markup_ikm: Option<InlineKeyboardMarkup>,
491        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
492        reply_markup_rkr: Option<ReplyKeyboardRemove>,
493        reply_markup_fr: Option<ForceReply>,
494    ) -> Option<Message> {
495        let mut parameters = "".to_string();
496        expand_parameters_into_string! {
497            parameters, chat_id, latitude, longitude
498        }
499        expand_parameters_opt_into_string! {
500            parameters, horizontal_accuracy, live_period, heading, proximity_alert_radius, disable_notification,
501            reply_to_message_id, allow_sending_without_reply
502        }
503        expand_parameters_reply_markup_into_string! {
504            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
505        }
506        parameters.pop();
507        let res = self.send_request("sendLocation".to_string(), parameters);
508        expand_make_request_to_message! {
509            res
510        }
511    }
512
513    pub fn edit_message_live_location(
514        &mut self,
515        chat_id: Option<i64>,
516        message_id: Option<i32>,
517        inline_message_id: Option<String>,
518        latitude: f64,
519        longitude: f64,
520        horizontal_accuracy: Option<f64>,
521        heading: Option<i32>,
522        proximity_alert_radius: Option<i32>,
523        reply_markup_ikm: Option<InlineKeyboardMarkup>,
524    ) -> Option<Message> {
525        let mut parameters = "".to_string();
526        expand_parameters_into_string! {
527            parameters, latitude, longitude
528        }
529        expand_parameters_opt_into_string! {
530            parameters, chat_id, message_id, inline_message_id, horizontal_accuracy, heading, proximity_alert_radius
531        }
532        expand_parameters_reply_markup_into_string! {
533            parameters, reply_markup_ikm
534        }
535        parameters.pop();
536        let res = self.send_request("editMessageLiveLocation".to_string(), parameters);
537        expand_make_request_to_message! {
538            res
539        }
540    }
541
542    pub fn stop_message_live_location(
543        &mut self,
544        chat_id: Option<i64>,
545        message_id: Option<i32>,
546        inline_message_id: Option<String>,
547        reply_markup_ikm: Option<InlineKeyboardMarkup>,
548    ) -> Option<Message> {
549        let mut parameters = "".to_string();
550        expand_parameters_opt_into_string! {
551            parameters, chat_id, message_id, inline_message_id
552        }
553        expand_parameters_reply_markup_into_string! {
554            parameters, reply_markup_ikm
555        }
556        parameters.pop();
557        let res = self.send_request("stopMessageLiveLocation".to_string(), parameters);
558        expand_make_request_to_message! {
559            res
560        }
561    }
562
563    pub fn send_venue(
564        &mut self,
565        chat_id: i64,
566        latitude: f64,
567        longitude: f64,
568        title: String,
569        address: String,
570        foursquare_id: Option<String>,
571        foursquare_type: Option<String>,
572        google_place_id: Option<String>,
573        google_place_type: Option<String>,
574        disable_notification: Option<bool>,
575        reply_to_message_id: Option<i32>,
576        allow_sending_without_reply: Option<bool>,
577        reply_markup_ikm: Option<InlineKeyboardMarkup>,
578        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
579        reply_markup_rkr: Option<ReplyKeyboardRemove>,
580        reply_markup_fr: Option<ForceReply>,
581    ) -> Option<Message> {
582        let mut parameters = "".to_string();
583        expand_parameters_into_string! {
584            parameters, chat_id, latitude, longitude, title, address
585        }
586        expand_parameters_opt_into_string! {
587            parameters, foursquare_id, foursquare_type, google_place_id, google_place_type, disable_notification,
588            reply_to_message_id, allow_sending_without_reply
589        }
590        expand_parameters_reply_markup_into_string! {
591            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
592        }
593        parameters.pop();
594        let res = self.send_request("sendVenue".to_string(), parameters);
595        expand_make_request_to_message! {
596            res
597        }
598    }
599
600    pub fn send_contact(
601        &mut self,
602        chat_id: i64,
603        phone_number: String,
604        first_name: String,
605        last_name: Option<String>,
606        vcard: Option<String>,
607        disable_notification: Option<bool>,
608        reply_to_message_id: Option<i32>,
609        allow_sending_without_reply: Option<bool>,
610        reply_markup_ikm: Option<InlineKeyboardMarkup>,
611        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
612        reply_markup_rkr: Option<ReplyKeyboardRemove>,
613        reply_markup_fr: Option<ForceReply>,
614    ) -> Option<Message> {
615        let mut parameters = "".to_string();
616        expand_parameters_into_string! {
617            parameters, chat_id, phone_number, first_name
618        }
619        expand_parameters_opt_into_string! {
620            parameters, last_name, vcard, disable_notification, reply_to_message_id, allow_sending_without_reply
621        }
622        expand_parameters_reply_markup_into_string! {
623            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
624        }
625        parameters.pop();
626        let res = self.send_request("sendContact".to_string(), parameters);
627        expand_make_request_to_message! {
628            res
629        }
630    }
631
632    pub fn send_poll(
633        &mut self,
634        chat_id: i64,
635        question: String,
636        options: Vec<String>,
637        is_anonymous: Option<bool>,
638        typ: Option<String>,
639        allows_multiple_answers: Option<bool>,
640        correct_option_id: Option<i32>,
641        explanation: Option<String>,
642        explanation_parse_mode: Option<String>,
643        explanation_entities: Option<Vec<MessageEntity>>,
644        open_period: Option<i32>,
645        close_date: Option<i32>,
646        is_closed: Option<i32>,
647        disable_notification: Option<bool>,
648        reply_to_message_id: Option<i32>,
649        allow_sending_without_reply: Option<bool>,
650        reply_markup_ikm: Option<InlineKeyboardMarkup>,
651        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
652        reply_markup_rkr: Option<ReplyKeyboardRemove>,
653        reply_markup_fr: Option<ForceReply>,
654    ) -> Option<Message> {
655        let mut parameters = "".to_string();
656        expand_parameters_into_string! {
657            parameters, chat_id, question, options
658        }
659        expand_parameters_opt_into_string! {
660            parameters, is_anonymous, typ, allows_multiple_answers, correct_option_id, explanation,
661            explanation_parse_mode, explanation_entities, open_period, close_date, is_closed,
662            disable_notification, reply_to_message_id, allow_sending_without_reply
663        }
664        expand_parameters_reply_markup_into_string! {
665            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
666        }
667        parameters.pop();
668        let res = self.send_request("sendPoll".to_string(), parameters);
669        expand_make_request_to_message! {
670            res
671        }
672    }
673
674    pub fn send_dice(
675        &mut self,
676        chat_id: i64,
677        emoji: Option<String>,
678        disable_notification: Option<bool>,
679        reply_to_message_id: Option<i32>,
680        allow_sending_without_reply: Option<bool>,
681        reply_markup_ikm: Option<InlineKeyboardMarkup>,
682        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
683        reply_markup_rkr: Option<ReplyKeyboardRemove>,
684        reply_markup_fr: Option<ForceReply>,
685    ) -> Option<Message> {
686        let mut parameters = "".to_string();
687        expand_parameters_into_string! {
688            parameters, chat_id
689        }
690        expand_parameters_opt_into_string! {
691            parameters, emoji, disable_notification, reply_to_message_id, allow_sending_without_reply
692        }
693        expand_parameters_reply_markup_into_string! {
694            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
695        }
696        parameters.pop();
697        let res = self.send_request("sendDice".to_string(), parameters);
698        expand_make_request_to_message! {
699            res
700        }
701    }
702
703    pub fn send_chat_action(&mut self, chat_id: i64, action: String) -> bool {
704        let mut parameters = "".to_string();
705        expand_parameters_into_string! {
706            parameters, chat_id, action
707        }
708        parameters.pop();
709        let res = self.send_request("sendChatAction".to_string(), parameters);
710        expand_make_request_to_bool! {
711            res
712        }
713    }
714
715    pub fn get_user_profile_photos(
716        &mut self,
717        user_id: i64,
718        offset: Option<i32>,
719        limit: Option<i32>,
720    ) -> Option<UserProfilePhotos> {
721        let mut parameters = "".to_string();
722        expand_parameters_into_string! {
723            parameters, user_id
724        }
725        expand_parameters_opt_into_string! {
726            parameters, offset, limit
727        }
728        parameters.pop();
729        let res = self.send_request("getUserProfilePhotos".to_string(), parameters);
730        if !res["ok"].as_bool().unwrap() {
731            None
732        } else {
733            let ret: UserProfilePhotos = Custom::from_json(res["result"].clone());
734            Some(ret)
735        }
736    }
737
738    pub fn kick_chat_member(
739        &mut self,
740        chat_id: i64,
741        user_id: i64,
742        until_date: Option<i32>,
743        revoke_messages: Option<bool>,
744    ) -> bool {
745        let mut parameters = "".to_string();
746        expand_parameters_into_string! {
747            parameters, chat_id, user_id
748        }
749        expand_parameters_opt_into_string! {
750            parameters, until_date, revoke_messages
751        }
752        parameters.pop();
753        let res = self.send_request("kickChatMember".to_string(), parameters);
754        expand_make_request_to_bool! {
755            res
756        }
757    }
758
759    pub fn unban_chat_member(
760        &mut self,
761        chat_id: i64,
762        user_id: i64,
763        only_if_banned: Option<bool>,
764    ) -> bool {
765        let mut parameters = "".to_string();
766        expand_parameters_into_string! {
767            parameters, chat_id, user_id
768        }
769        expand_parameters_opt_into_string! {
770            parameters, only_if_banned
771        }
772        parameters.pop();
773        let res = self.send_request("unbanChatMember".to_string(), parameters);
774        expand_make_request_to_bool! {
775            res
776        }
777    }
778
779    pub fn restrict_chat_member(
780        &mut self,
781        chat_id: i64,
782        user_id: i64,
783        permissions: ChatPermissions,
784        until_date: Option<i32>,
785    ) -> bool {
786        let mut parameters = "".to_string();
787        expand_parameters_into_string! {
788            parameters, chat_id, user_id, permissions
789        }
790        expand_parameters_opt_into_string! {
791            parameters, until_date
792        }
793        parameters.pop();
794        let res = self.send_request("restrictChatMember".to_string(), parameters);
795        expand_make_request_to_bool! {
796            res
797        }
798    }
799
800    pub fn promote_chat_member(
801        &mut self,
802        chat_id: i64,
803        user_id: i64,
804        is_anonymous: Option<bool>,
805        can_manage_chat: Option<bool>,
806        can_post_messages: Option<bool>,
807        can_edit_messages: Option<bool>,
808        can_delete_messages: Option<bool>,
809        can_manage_voice_chats: Option<bool>,
810        can_restrict_members: Option<bool>,
811        can_promote_members: Option<bool>,
812        can_change_info: Option<bool>,
813        can_invite_users: Option<bool>,
814        can_pin_messages: Option<bool>,
815    ) -> bool {
816        let mut parameters = "".to_string();
817        expand_parameters_into_string! {
818            parameters, chat_id, user_id
819        }
820        expand_parameters_opt_into_string! {
821            parameters, is_anonymous, can_manage_chat, can_post_messages, can_edit_messages,
822            can_delete_messages, can_manage_voice_chats, can_restrict_members, can_promote_members,
823            can_change_info, can_invite_users, can_pin_messages
824        }
825        parameters.pop();
826        let res = self.send_request("promoteChatMember".to_string(), parameters);
827        expand_make_request_to_bool! {
828            res
829        }
830    }
831
832    pub fn set_chat_administrator_custom_title(
833        &mut self,
834        chat_id: i64,
835        user_id: i64,
836        custom_title: String,
837    ) -> bool {
838        let mut parameters = "".to_string();
839        expand_parameters_into_string! {
840            parameters, chat_id, user_id, custom_title
841        }
842        parameters.pop();
843        let res = self.send_request("setChatAdministratorCustomTitle".to_string(), parameters);
844        expand_make_request_to_bool! {
845            res
846        }
847    }
848
849    pub fn set_chat_permissions(&mut self, chat_id: i64, permissions: ChatPermissions) -> bool {
850        let mut parameters = "".to_string();
851        expand_parameters_into_string! {
852            parameters, chat_id, permissions
853        }
854        parameters.pop();
855        let res = self.send_request("setChatPermissions".to_string(), parameters);
856        expand_make_request_to_bool! {
857            res
858        }
859    }
860
861    pub fn export_chat_invite_link(&mut self, chat_id: i64) -> Option<String> {
862        let mut parameters = "".to_string();
863        expand_parameters_into_string! {
864            parameters, chat_id
865        }
866        parameters.pop();
867        let res = self.send_request("exportChatInviteLink".to_string(), parameters);
868        if !res["ok"].as_bool().unwrap() {
869            None
870        } else {
871            let ret: String = Custom::from_json(res["result"].clone());
872            Some(ret)
873        }
874    }
875
876    pub fn create_chat_invite_link(
877        &mut self,
878        chat_id: i64,
879        expire_date: Option<i32>,
880        member_limit: Option<i32>,
881    ) -> Option<ChatInviteLink> {
882        let mut parameters = "".to_string();
883        expand_parameters_into_string! {
884            parameters, chat_id
885        }
886        expand_parameters_opt_into_string! {
887            parameters, expire_date, member_limit
888        }
889        parameters.pop();
890        let res = self.send_request("createChatInviteLink".to_string(), parameters);
891        if !res["ok"].as_bool().unwrap() {
892            None
893        } else {
894            let ret: ChatInviteLink = Custom::from_json(res["result"].clone());
895            Some(ret)
896        }
897    }
898
899    pub fn edit_chat_invite_link(
900        &mut self,
901        chat_id: i64,
902        invite_link: String,
903        expire_date: Option<i32>,
904        member_limit: Option<i32>,
905    ) -> Option<ChatInviteLink> {
906        let mut parameters = "".to_string();
907        expand_parameters_into_string! {
908            parameters, chat_id, invite_link
909        }
910        expand_parameters_opt_into_string! {
911            parameters, expire_date, member_limit
912        }
913        parameters.pop();
914        let res = self.send_request("editChatInviteLink".to_string(), parameters);
915        if !res["ok"].as_bool().unwrap() {
916            None
917        } else {
918            let ret: ChatInviteLink = Custom::from_json(res["result"].clone());
919            Some(ret)
920        }
921    }
922
923    pub fn revoke_chat_invite_link(
924        &mut self,
925        chat_id: i64,
926        invite_link: String,
927    ) -> Option<ChatInviteLink> {
928        let mut parameters = "".to_string();
929        expand_parameters_into_string! {
930            parameters, chat_id, invite_link
931        }
932        parameters.pop();
933        let res = self.send_request("revokeChatInviteLink".to_string(), parameters);
934        if !res["ok"].as_bool().unwrap() {
935            None
936        } else {
937            let ret: ChatInviteLink = Custom::from_json(res["result"].clone());
938            Some(ret)
939        }
940    }
941
942    pub fn delete_chat_photo(&mut self, chat_id: i64) -> bool {
943        let mut parameters = "".to_string();
944        expand_parameters_into_string! {
945            parameters, chat_id
946        }
947        parameters.pop();
948        let res = self.send_request("deleteChatPhoto".to_string(), parameters);
949        expand_make_request_to_bool! {
950            res
951        }
952    }
953
954    pub fn set_chat_title(&mut self, chat_id: i64, title: String) -> bool {
955        let mut parameters = "".to_string();
956        expand_parameters_into_string! {
957            parameters, chat_id, title
958        }
959        parameters.pop();
960        let res = self.send_request("setChatTitle".to_string(), parameters);
961        expand_make_request_to_bool! {
962            res
963        }
964    }
965
966    pub fn set_chat_description(&mut self, chat_id: i64, description: String) -> bool {
967        let mut parameters = "".to_string();
968        expand_parameters_into_string! {
969            parameters, chat_id, description
970        }
971        parameters.pop();
972        let res = self.send_request("setChatDescription".to_string(), parameters);
973        expand_make_request_to_bool! {
974            res
975        }
976    }
977
978    pub fn pin_chat_message(
979        &mut self,
980        chat_id: i64,
981        message_id: i32,
982        disable_notification: Option<bool>,
983    ) -> bool {
984        let mut parameters = "".to_string();
985        expand_parameters_into_string! {
986            parameters, chat_id, message_id
987        }
988        expand_parameters_opt_into_string! {
989            parameters, disable_notification
990        }
991        parameters.pop();
992        let res = self.send_request("pinChatMessage".to_string(), parameters);
993        expand_make_request_to_bool! {
994            res
995        }
996    }
997
998    pub fn unpin_chat_message(&mut self, chat_id: i64, message_id: i32) -> bool {
999        let mut parameters = "".to_string();
1000        expand_parameters_into_string! {
1001            parameters, chat_id, message_id
1002        }
1003        parameters.pop();
1004        let res = self.send_request("unpinChatMessage".to_string(), parameters);
1005        expand_make_request_to_bool! {
1006            res
1007        }
1008    }
1009
1010    pub fn unpin_all_chat_message(&mut self, chat_id: i64) -> bool {
1011        let mut parameters = "".to_string();
1012        expand_parameters_into_string! {
1013            parameters, chat_id
1014        }
1015        parameters.pop();
1016        let res = self.send_request("unpinAllChatMessages".to_string(), parameters);
1017        expand_make_request_to_bool! {
1018            res
1019        }
1020    }
1021
1022    pub fn leave_chat(&mut self, chat_id: i64) -> bool {
1023        let mut parameters = "".to_string();
1024        expand_parameters_into_string! {
1025            parameters, chat_id
1026        }
1027        parameters.pop();
1028        let res = self.send_request("leaveChat".to_string(), parameters);
1029        expand_make_request_to_bool! {
1030            res
1031        }
1032    }
1033
1034    pub fn get_chat(&mut self, chat_id: i64) -> Option<Chat> {
1035        let mut parameters = "".to_string();
1036        expand_parameters_into_string! {
1037            parameters, chat_id
1038        }
1039        parameters.pop();
1040        let res = self.send_request("getChat".to_string(), parameters);
1041        if !res["ok"].as_bool().unwrap() {
1042            None
1043        } else {
1044            let ret: Chat = Custom::from_json(res["result"].clone());
1045            Some(ret)
1046        }
1047    }
1048
1049    pub fn get_chat_administrators(&mut self, chat_id: i64) -> Option<Vec<ChatMember>> {
1050        let mut parameters = "".to_string();
1051        expand_parameters_into_string! {
1052            parameters, chat_id
1053        }
1054        parameters.pop();
1055        let res = self.send_request("getChatAdministrators".to_string(), parameters);
1056        if !res["ok"].as_bool().unwrap() {
1057            None
1058        } else {
1059            let ret: Vec<ChatMember> = Custom::from_json(res["result"].clone());
1060            Some(ret)
1061        }
1062    }
1063
1064    pub fn get_chat_chat_members_count(&mut self, chat_id: i64) -> Option<i32> {
1065        let mut parameters = "".to_string();
1066        expand_parameters_into_string! {
1067            parameters, chat_id
1068        }
1069        parameters.pop();
1070        let res = self.send_request("getChatMembersCount".to_string(), parameters);
1071        if !res["ok"].as_bool().unwrap() {
1072            None
1073        } else {
1074            let ret: i32 = Custom::from_json(res["result"].clone());
1075            Some(ret)
1076        }
1077    }
1078
1079    pub fn get_chat_chat_member(&mut self, chat_id: i64, user_id: i64) -> Option<ChatMember> {
1080        let mut parameters = "".to_string();
1081        expand_parameters_into_string! {
1082            parameters, chat_id, user_id
1083        }
1084        parameters.pop();
1085        let res = self.send_request("getChatMember".to_string(), parameters);
1086        if !res["ok"].as_bool().unwrap() {
1087            None
1088        } else {
1089            let ret: ChatMember = Custom::from_json(res["result"].clone());
1090            Some(ret)
1091        }
1092    }
1093
1094    pub fn set_chat_sticker_set(&mut self, chat_id: i64, sticker_set_name: String) -> bool {
1095        let mut parameters = "".to_string();
1096        expand_parameters_into_string! {
1097            parameters, chat_id, sticker_set_name
1098        }
1099        parameters.pop();
1100        let res = self.send_request("setChatStickerSet".to_string(), parameters);
1101        expand_make_request_to_bool! {
1102            res
1103        }
1104    }
1105
1106    pub fn delete_chat_sticker_set(&mut self, chat_id: i64) -> bool {
1107        let mut parameters = "".to_string();
1108        expand_parameters_into_string! {
1109            parameters, chat_id
1110        }
1111        parameters.pop();
1112        let res = self.send_request("deleteChatStickerSet".to_string(), parameters);
1113        expand_make_request_to_bool! {
1114            res
1115        }
1116    }
1117
1118    pub fn answer_callback_query(
1119        &mut self,
1120        callback_query_id: String,
1121        text: String,
1122        show_alert: Option<bool>,
1123        url: Option<String>,
1124        cache_time: Option<i32>,
1125    ) -> bool {
1126        let mut parameters = "".to_string();
1127        expand_parameters_into_string! {
1128            parameters, callback_query_id, text
1129        }
1130        expand_parameters_opt_into_string! {
1131            parameters, show_alert, url, cache_time
1132        }
1133        parameters.pop();
1134        let res = self.send_request("answerCallbackQuery".to_string(), parameters);
1135        expand_make_request_to_bool! {
1136            res
1137        }
1138    }
1139
1140    pub fn set_my_commands(&mut self, commands: Vec<BotCommand>) -> bool {
1141        let mut parameters = "".to_string();
1142        expand_parameters_into_string! {
1143            parameters, commands
1144        }
1145        parameters.pop();
1146        let res = self.send_request("setMyCommands".to_string(), parameters);
1147        expand_make_request_to_bool! {
1148            res
1149        }
1150    }
1151
1152    pub fn get_my_commands(&mut self) -> Option<Vec<BotCommand>> {
1153        let res = self.send_request("getMyCommands".to_string(), "".to_string());
1154        if !res["ok"].as_bool().unwrap() {
1155            None
1156        } else {
1157            let ret: Vec<BotCommand> = Custom::from_json(res["result"].clone());
1158            Some(ret)
1159        }
1160    }
1161
1162    pub fn edit_message_text(
1163        &mut self,
1164        chat_id: Option<i64>,
1165        message_id: Option<i32>,
1166        inline_message_id: Option<String>,
1167        text: Option<String>,
1168        parse_mode: Option<String>,
1169        entities: Option<Vec<MessageEntity>>,
1170        disable_web_page_preview: Option<bool>,
1171        reply_markup_ikm: Option<InlineKeyboardMarkup>,
1172    ) -> Option<Message> {
1173        let mut parameters = "".to_string();
1174        expand_parameters_opt_into_string! {
1175            parameters, chat_id, message_id, inline_message_id, text, parse_mode, entities, disable_web_page_preview
1176        }
1177        expand_parameters_reply_markup_into_string! {
1178            parameters, reply_markup_ikm
1179        }
1180        parameters.pop();
1181        let res = self.send_request("editMessageText".to_string(), parameters);
1182        expand_make_request_to_message! {
1183            res
1184        }
1185    }
1186
1187    pub fn edit_message_caption(
1188        &mut self,
1189        chat_id: Option<i64>,
1190        message_id: Option<i32>,
1191        inline_message_id: Option<String>,
1192        caption: Option<String>,
1193        parse_mode: Option<String>,
1194        caption_entities: Option<Vec<MessageEntity>>,
1195        reply_markup_ikm: Option<InlineKeyboardMarkup>,
1196    ) -> Option<Message> {
1197        let mut parameters = "".to_string();
1198        expand_parameters_opt_into_string! {
1199            parameters, chat_id, message_id, inline_message_id, caption, parse_mode, caption_entities
1200        }
1201        expand_parameters_reply_markup_into_string! {
1202            parameters, reply_markup_ikm
1203        }
1204        parameters.pop();
1205        let res = self.send_request("editMessageCaption".to_string(), parameters);
1206        expand_make_request_to_message! {
1207            res
1208        }
1209    }
1210
1211    pub fn edit_message_media(
1212        &mut self,
1213        chat_id: Option<i64>,
1214        message_id: Option<i32>,
1215        inline_message_id: Option<String>,
1216        media: Option<InputMedia>,
1217        reply_markup_ikm: Option<InlineKeyboardMarkup>,
1218    ) -> Option<Message> {
1219        let mut parameters = "".to_string();
1220        expand_parameters_opt_into_string! {
1221            parameters, chat_id, message_id, inline_message_id, media
1222        }
1223        expand_parameters_reply_markup_into_string! {
1224            parameters, reply_markup_ikm
1225        }
1226        parameters.pop();
1227        let res = self.send_request("editMessageMedia".to_string(), parameters);
1228        expand_make_request_to_message! {
1229            res
1230        }
1231    }
1232
1233    pub fn edit_message_reply_markup(
1234        &mut self,
1235        chat_id: Option<i64>,
1236        message_id: Option<i32>,
1237        inline_message_id: Option<String>,
1238        reply_markup_ikm: Option<InlineKeyboardMarkup>,
1239    ) -> Option<Message> {
1240        let mut parameters = "".to_string();
1241        expand_parameters_opt_into_string! {
1242            parameters, chat_id, message_id, inline_message_id
1243        }
1244        expand_parameters_reply_markup_into_string! {
1245            parameters, reply_markup_ikm
1246        }
1247        parameters.pop();
1248        let res = self.send_request("editMessageReplyMarkup".to_string(), parameters);
1249        expand_make_request_to_message! {
1250            res
1251        }
1252    }
1253
1254    pub fn stop_poll(
1255        &mut self,
1256        chat_id: i64,
1257        message_id: i32,
1258        reply_markup_ikm: Option<InlineKeyboardMarkup>,
1259    ) -> Option<Poll> {
1260        let mut parameters = "".to_string();
1261        expand_parameters_into_string! {
1262            parameters, chat_id, message_id
1263        }
1264        expand_parameters_reply_markup_into_string! {
1265            parameters, reply_markup_ikm
1266        }
1267        parameters.pop();
1268        let res = self.send_request("stopPoll".to_string(), parameters);
1269        if !res["ok"].as_bool().unwrap() {
1270            None
1271        } else {
1272            let ret: Poll = Custom::from_json(res["result"].clone());
1273            Some(ret)
1274        }
1275    }
1276
1277    pub fn delete_message(&mut self, chat_id: i64, message_id: i32) -> bool {
1278        let mut parameters = "".to_string();
1279        expand_parameters_into_string! {
1280            parameters, chat_id, message_id
1281        }
1282        parameters.pop();
1283        let res = self.send_request("deleteMessage".to_string(), parameters);
1284        expand_make_request_to_bool! {
1285            res
1286        }
1287    }
1288
1289    pub fn send_sticker(
1290        &mut self,
1291        chat_id: i64,
1292        sticker: String,
1293        disable_notification: Option<bool>,
1294        reply_to_message_id: Option<i32>,
1295        allow_sending_without_reply: Option<bool>,
1296        reply_markup_ikm: Option<InlineKeyboardMarkup>,
1297        reply_markup_rkm: Option<ReplyKeyboardMarkup>,
1298        reply_markup_rkr: Option<ReplyKeyboardRemove>,
1299        reply_markup_fr: Option<ForceReply>,
1300    ) -> Option<Message> {
1301        let mut parameters = "".to_string();
1302        expand_parameters_into_string! {
1303            parameters, chat_id, sticker
1304        }
1305        expand_parameters_opt_into_string! {
1306            parameters, disable_notification, reply_to_message_id, allow_sending_without_reply
1307        }
1308        expand_parameters_reply_markup_into_string! {
1309            parameters, reply_markup_ikm, reply_markup_rkm, reply_markup_rkr, reply_markup_fr
1310        }
1311        parameters.pop();
1312        let res = self.send_request("sendSticker".to_string(), parameters);
1313        expand_make_request_to_message! {
1314            res
1315        }
1316    }
1317
1318    pub fn get_sticker_set(&mut self, name: String) -> Option<StickerSet> {
1319        let mut parameters = "".to_string();
1320        expand_parameters_into_string! {
1321            parameters, name
1322        }
1323        parameters.pop();
1324        let res = self.send_request("getStickerSet".to_string(), parameters);
1325        if !res["ok"].as_bool().unwrap() {
1326            None
1327        } else {
1328            let ret: StickerSet = Custom::from_json(res["result"].clone());
1329            Some(ret)
1330        }
1331    }
1332
1333    pub fn create_new_sticker_set(
1334        &mut self,
1335        user_id: i64,
1336        name: String,
1337        title: String,
1338        png_sticker: Option<String>,
1339        emojis: String,
1340        contains_masks: Option<bool>,
1341        mask_position: Option<MaskPosition>,
1342    ) -> bool {
1343        let mut parameters = "".to_string();
1344        expand_parameters_into_string! {
1345            parameters, user_id, name, title, emojis
1346        }
1347        expand_parameters_opt_into_string! {
1348            parameters, png_sticker, contains_masks, mask_position
1349        }
1350        parameters.pop();
1351        let res = self.send_request("createNewStickerSet".to_string(), parameters);
1352        expand_make_request_to_bool! {
1353            res
1354        }
1355    }
1356
1357    pub fn add_sticker_to_set(
1358        &mut self,
1359        user_id: i64,
1360        name: String,
1361        png_sticker: Option<String>,
1362        emojis: String,
1363        mask_position: Option<MaskPosition>,
1364    ) -> bool {
1365        let mut parameters = "".to_string();
1366        expand_parameters_into_string! {
1367            parameters, user_id, name, emojis
1368        }
1369        expand_parameters_opt_into_string! {
1370            parameters, png_sticker, mask_position
1371        }
1372        parameters.pop();
1373        let res = self.send_request("addStickerToSet".to_string(), parameters);
1374        expand_make_request_to_bool! {
1375            res
1376        }
1377    }
1378
1379    pub fn add_sticker_position_in_set(&mut self, sticker: String, position: i32) -> bool {
1380        let mut parameters = "".to_string();
1381        expand_parameters_into_string! {
1382            parameters, sticker, position
1383        }
1384        parameters.pop();
1385        let res = self.send_request("setStickerPositionInSet".to_string(), parameters);
1386        expand_make_request_to_bool! {
1387            res
1388        }
1389    }
1390
1391    pub fn delete_sticker_from_chat(&mut self, sticker: String) -> bool {
1392        let mut parameters = "".to_string();
1393        expand_parameters_into_string! {
1394            parameters, sticker
1395        }
1396        parameters.pop();
1397        let res = self.send_request("deleteStickerFromSet".to_string(), parameters);
1398        expand_make_request_to_bool! {
1399            res
1400        }
1401    }
1402
1403    pub fn set_sticker_thumb(&mut self, name: String, user_id: i64, thumb: Option<String>) -> bool {
1404        let mut parameters = "".to_string();
1405        expand_parameters_into_string! {
1406            parameters, name, user_id
1407        }
1408        expand_parameters_opt_into_string! {
1409            parameters, thumb
1410        }
1411        parameters.pop();
1412        let res = self.send_request("setStickerSetThumb".to_string(), parameters);
1413        expand_make_request_to_bool! {
1414            res
1415        }
1416    }
1417}
1418
1419impl Clone for Bot {
1420    fn clone(&self) -> Self {
1421        Bot {
1422            key: self.key.clone(),
1423            offset: self.offset,
1424        }
1425    }
1426}