Skip to main content

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