1extern 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
29pub const LONG_POLL_TIMEOUT_SECS: i32 = 30;
34
35pub const HTTP_TIMEOUT_SECS: u64 = 60;
39
40const POLL_ERROR_BACKOFF: Duration = Duration::from_secs(2);
44
45fn 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 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 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}