1use std::future::{Future, IntoFuture};
2use std::pin::Pin;
3
4use reqwest::multipart::{Form, Part};
5use serde::Serialize;
6
7use rustigram_types::file::{InputFile, InputMedia, InputPaidMedia};
8use rustigram_types::keyboard::ReplyMarkup;
9use rustigram_types::message::{LinkPreviewOptions, Message, ParseMode, ReplyParameters};
10use rustigram_types::poll::InputPollOption;
11use rustigram_types::suggested_post::SuggestedPostParameters;
12use rustigram_types::user::ChatId;
13
14use crate::client::BotClient;
15use crate::error::Result;
16
17macro_rules! impl_into_future {
21 ($builder:ident, $return_ty:ty, $method:literal) => {
22 impl IntoFuture for $builder {
23 type Output = Result<$return_ty>;
24 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
25
26 fn into_future(self) -> Self::IntoFuture {
27 Box::pin(async move { self.client.post_json($method, &self.params).await })
28 }
29 }
30 };
31}
32
33#[derive(Serialize)]
36struct SendMessageParams {
37 chat_id: ChatId,
38 text: String,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 business_connection_id: Option<String>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 message_thread_id: Option<i64>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 direct_messages_topic_id: Option<i64>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 parse_mode: Option<ParseMode>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 entities: Option<Vec<rustigram_types::message::MessageEntity>>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 link_preview_options: Option<LinkPreviewOptions>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 disable_notification: Option<bool>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 protect_content: Option<bool>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 allow_paid_broadcast: Option<bool>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 message_effect_id: Option<String>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 reply_parameters: Option<ReplyParameters>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 reply_markup: Option<ReplyMarkup>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 suggested_post_parameters: Option<SuggestedPostParameters>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 receiver_user_id: Option<i64>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 callback_query_id: Option<String>,
69}
70
71pub struct SendMessage {
73 client: BotClient,
74 params: SendMessageParams,
75}
76
77impl SendMessage {
78 pub(crate) fn new(
79 client: BotClient,
80 chat_id: impl Into<ChatId>,
81 text: impl Into<String>,
82 ) -> Self {
83 Self {
84 client,
85 params: SendMessageParams {
86 chat_id: chat_id.into(),
87 text: text.into(),
88 business_connection_id: None,
89 message_thread_id: None,
90 direct_messages_topic_id: None,
91 parse_mode: None,
92 entities: None,
93 link_preview_options: None,
94 disable_notification: None,
95 protect_content: None,
96 allow_paid_broadcast: None,
97 message_effect_id: None,
98 reply_parameters: None,
99 reply_markup: None,
100 suggested_post_parameters: None,
101 receiver_user_id: None,
102 callback_query_id: None,
103 },
104 }
105 }
106 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
108 self.params.business_connection_id = Some(id.into());
109 self
110 }
111 pub fn message_thread_id(mut self, id: i64) -> Self {
113 self.params.message_thread_id = Some(id);
114 self
115 }
116 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
118 self.params.direct_messages_topic_id = Some(id);
119 self
120 }
121 pub fn parse_mode(mut self, mode: ParseMode) -> Self {
123 self.params.parse_mode = Some(mode);
124 self
125 }
126 pub fn entities(mut self, entities: Vec<rustigram_types::message::MessageEntity>) -> Self {
128 self.params.entities = Some(entities);
129 self
130 }
131 pub fn link_preview_options(mut self, opts: LinkPreviewOptions) -> Self {
133 self.params.link_preview_options = Some(opts);
134 self
135 }
136 pub fn disable_notification(mut self, v: bool) -> Self {
138 self.params.disable_notification = Some(v);
139 self
140 }
141 pub fn protect_content(mut self, v: bool) -> Self {
143 self.params.protect_content = Some(v);
144 self
145 }
146 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
148 self.params.allow_paid_broadcast = Some(v);
149 self
150 }
151 pub fn message_effect_id(mut self, id: impl Into<String>) -> Self {
153 self.params.message_effect_id = Some(id.into());
154 self
155 }
156 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
158 self.params.reply_parameters = Some(rp);
159 self
160 }
161 pub fn reply_to(mut self, message_id: i64) -> Self {
163 self.params.reply_parameters = Some(ReplyParameters {
164 message_id: Some(message_id),
165 ephemeral_message_id: None,
166 chat_id: None,
167 allow_sending_without_reply: None,
168 quote: None,
169 quote_parse_mode: None,
170 quote_entities: None,
171 quote_position: None,
172 poll_option_id: None,
173 checklist_task_id: None,
174 });
175 self
176 }
177 pub fn reply_to_ephemeral(mut self, ephemeral_message_id: i64) -> Self {
182 self.params.reply_parameters = Some(ReplyParameters {
183 message_id: None,
184 ephemeral_message_id: Some(ephemeral_message_id),
185 chat_id: None,
186 allow_sending_without_reply: None,
187 quote: None,
188 quote_parse_mode: None,
189 quote_entities: None,
190 quote_position: None,
191 poll_option_id: None,
192 checklist_task_id: None,
193 });
194 self
195 }
196 pub fn reply_markup(mut self, markup: impl Into<ReplyMarkup>) -> Self {
198 self.params.reply_markup = Some(markup.into());
199 self
200 }
201 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self {
203 self.params.suggested_post_parameters = Some(params);
204 self
205 }
206 pub fn receiver_user_id(mut self, id: i64) -> Self {
212 self.params.receiver_user_id = Some(id);
213 self
214 }
215 pub fn callback_query_id(mut self, id: impl Into<String>) -> Self {
217 self.params.callback_query_id = Some(id.into());
218 self
219 }
220}
221
222impl_into_future!(SendMessage, Message, "sendMessage");
223
224#[derive(Serialize)]
227struct ForwardMessageParams {
228 chat_id: ChatId,
229 from_chat_id: ChatId,
230 message_id: i64,
231 #[serde(skip_serializing_if = "Option::is_none")]
232 message_thread_id: Option<i64>,
233 #[serde(skip_serializing_if = "Option::is_none")]
234 direct_messages_topic_id: Option<i64>,
235 #[serde(skip_serializing_if = "Option::is_none")]
236 video_start_timestamp: Option<i64>,
237 #[serde(skip_serializing_if = "Option::is_none")]
238 disable_notification: Option<bool>,
239 #[serde(skip_serializing_if = "Option::is_none")]
240 protect_content: Option<bool>,
241 #[serde(skip_serializing_if = "Option::is_none")]
242 message_effect_id: Option<String>,
243 #[serde(skip_serializing_if = "Option::is_none")]
244 suggested_post_parameters: Option<SuggestedPostParameters>,
245}
246
247pub struct ForwardMessage {
249 client: BotClient,
250 params: ForwardMessageParams,
251}
252
253impl ForwardMessage {
254 pub(crate) fn new(
255 client: BotClient,
256 chat_id: impl Into<ChatId>,
257 from_chat_id: impl Into<ChatId>,
258 message_id: i64,
259 ) -> Self {
260 Self {
261 client,
262 params: ForwardMessageParams {
263 chat_id: chat_id.into(),
264 from_chat_id: from_chat_id.into(),
265 message_id,
266 message_thread_id: None,
267 direct_messages_topic_id: None,
268 video_start_timestamp: None,
269 disable_notification: None,
270 protect_content: None,
271 message_effect_id: None,
272 suggested_post_parameters: None,
273 },
274 }
275 }
276 pub fn message_thread_id(mut self, id: i64) -> Self {
278 self.params.message_thread_id = Some(id);
279 self
280 }
281 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
283 self.params.direct_messages_topic_id = Some(id);
284 self
285 }
286 pub fn video_start_timestamp(mut self, ts: i64) -> Self {
288 self.params.video_start_timestamp = Some(ts);
289 self
290 }
291 pub fn disable_notification(mut self, v: bool) -> Self {
293 self.params.disable_notification = Some(v);
294 self
295 }
296 pub fn protect_content(mut self, v: bool) -> Self {
298 self.params.protect_content = Some(v);
299 self
300 }
301 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
303 self.params.message_effect_id = Some(v.into());
304 self
305 }
306 pub fn suggested_post_parameters(mut self, v: SuggestedPostParameters) -> Self {
308 self.params.suggested_post_parameters = Some(v);
309 self
310 }
311}
312
313impl_into_future!(ForwardMessage, Message, "forwardMessage");
314
315#[derive(Serialize)]
318struct CopyMessageParams {
319 chat_id: ChatId,
320 from_chat_id: ChatId,
321 message_id: i64,
322 #[serde(skip_serializing_if = "Option::is_none")]
323 message_thread_id: Option<i64>,
324 #[serde(skip_serializing_if = "Option::is_none")]
325 direct_messages_topic_id: Option<i64>,
326 #[serde(skip_serializing_if = "Option::is_none")]
327 video_start_timestamp: Option<i64>,
328 #[serde(skip_serializing_if = "Option::is_none")]
329 caption: Option<String>,
330 #[serde(skip_serializing_if = "Option::is_none")]
331 parse_mode: Option<ParseMode>,
332 #[serde(skip_serializing_if = "Option::is_none")]
333 caption_entities: Option<Vec<rustigram_types::message::MessageEntity>>,
334 #[serde(skip_serializing_if = "Option::is_none")]
335 show_caption_above_media: Option<bool>,
336 #[serde(skip_serializing_if = "Option::is_none")]
337 disable_notification: Option<bool>,
338 #[serde(skip_serializing_if = "Option::is_none")]
339 protect_content: Option<bool>,
340 #[serde(skip_serializing_if = "Option::is_none")]
341 reply_parameters: Option<ReplyParameters>,
342 #[serde(skip_serializing_if = "Option::is_none")]
343 reply_markup: Option<ReplyMarkup>,
344 #[serde(skip_serializing_if = "Option::is_none")]
345 allow_paid_broadcast: Option<bool>,
346 #[serde(skip_serializing_if = "Option::is_none")]
347 message_effect_id: Option<String>,
348 #[serde(skip_serializing_if = "Option::is_none")]
349 suggested_post_parameters: Option<SuggestedPostParameters>,
350}
351
352pub struct CopyMessage {
354 client: BotClient,
355 params: CopyMessageParams,
356}
357
358impl CopyMessage {
359 pub(crate) fn new(
360 client: BotClient,
361 chat_id: impl Into<ChatId>,
362 from_chat_id: impl Into<ChatId>,
363 message_id: i64,
364 ) -> Self {
365 Self {
366 client,
367 params: CopyMessageParams {
368 chat_id: chat_id.into(),
369 from_chat_id: from_chat_id.into(),
370 message_id,
371 message_thread_id: None,
372 direct_messages_topic_id: None,
373 video_start_timestamp: None,
374 caption: None,
375 parse_mode: None,
376 caption_entities: None,
377 show_caption_above_media: None,
378 disable_notification: None,
379 protect_content: None,
380 reply_parameters: None,
381 reply_markup: None,
382 allow_paid_broadcast: None,
383 message_effect_id: None,
384 suggested_post_parameters: None,
385 },
386 }
387 }
388 pub fn message_thread_id(mut self, id: i64) -> Self {
390 self.params.message_thread_id = Some(id);
391 self
392 }
393 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
395 self.params.direct_messages_topic_id = Some(id);
396 self
397 }
398 pub fn video_start_timestamp(mut self, ts: i64) -> Self {
400 self.params.video_start_timestamp = Some(ts);
401 self
402 }
403 pub fn caption(mut self, c: impl Into<String>) -> Self {
405 self.params.caption = Some(c.into());
406 self
407 }
408 pub fn parse_mode(mut self, m: ParseMode) -> Self {
410 self.params.parse_mode = Some(m);
411 self
412 }
413 pub fn disable_notification(mut self, v: bool) -> Self {
415 self.params.disable_notification = Some(v);
416 self
417 }
418 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
420 self.params.reply_markup = Some(m.into());
421 self
422 }
423 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
425 self.params.allow_paid_broadcast = Some(v);
426 self
427 }
428 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
430 self.params.message_effect_id = Some(v.into());
431 self
432 }
433 pub fn suggested_post_parameters(mut self, v: SuggestedPostParameters) -> Self {
435 self.params.suggested_post_parameters = Some(v);
436 self
437 }
438 pub fn caption_entities(
440 mut self,
441 entities: Vec<rustigram_types::message::MessageEntity>,
442 ) -> Self {
443 self.params.caption_entities = Some(entities);
444 self
445 }
446 pub fn show_caption_above_media(mut self, v: bool) -> Self {
448 self.params.show_caption_above_media = Some(v);
449 self
450 }
451 pub fn protect_content(mut self, v: bool) -> Self {
453 self.params.protect_content = Some(v);
454 self
455 }
456 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
458 self.params.reply_parameters = Some(rp);
459 self
460 }
461}
462
463impl_into_future!(
464 CopyMessage,
465 rustigram_types::message::MessageId,
466 "copyMessage"
467);
468
469#[derive(Serialize)]
472struct SendChatActionParams {
473 chat_id: ChatId,
474 action: ChatAction,
475 #[serde(skip_serializing_if = "Option::is_none")]
476 business_connection_id: Option<String>,
477 #[serde(skip_serializing_if = "Option::is_none")]
478 message_thread_id: Option<i64>,
479}
480
481#[derive(Serialize, Clone, Copy)]
482#[serde(rename_all = "snake_case")]
484pub enum ChatAction {
485 Typing,
487 UploadPhoto,
489 RecordVideo,
491 UploadVideo,
493 RecordVoice,
495 UploadVoice,
497 UploadDocument,
499 ChooseSticker,
501 FindLocation,
503 RecordVideoNote,
505 UploadVideoNote,
507}
508
509pub struct SendChatAction {
511 client: BotClient,
512 params: SendChatActionParams,
513}
514
515impl SendChatAction {
516 pub(crate) fn new(client: BotClient, chat_id: impl Into<ChatId>, action: ChatAction) -> Self {
517 Self {
518 client,
519 params: SendChatActionParams {
520 chat_id: chat_id.into(),
521 action,
522 business_connection_id: None,
523 message_thread_id: None,
524 },
525 }
526 }
527 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
529 self.params.business_connection_id = Some(id.into());
530 self
531 }
532 pub fn message_thread_id(mut self, id: i64) -> Self {
534 self.params.message_thread_id = Some(id);
535 self
536 }
537}
538
539impl_into_future!(SendChatAction, bool, "sendChatAction");
540
541#[derive(Serialize)]
544struct SendDiceParams {
545 chat_id: ChatId,
546 #[serde(skip_serializing_if = "Option::is_none")]
547 emoji: Option<String>,
548 #[serde(skip_serializing_if = "Option::is_none")]
549 message_thread_id: Option<i64>,
550 #[serde(skip_serializing_if = "Option::is_none")]
551 direct_messages_topic_id: Option<i64>,
552 #[serde(skip_serializing_if = "Option::is_none")]
553 disable_notification: Option<bool>,
554 #[serde(skip_serializing_if = "Option::is_none")]
555 protect_content: Option<bool>,
556 #[serde(skip_serializing_if = "Option::is_none")]
557 reply_parameters: Option<ReplyParameters>,
558 #[serde(skip_serializing_if = "Option::is_none")]
559 reply_markup: Option<ReplyMarkup>,
560 #[serde(skip_serializing_if = "Option::is_none")]
561 business_connection_id: Option<String>,
562 #[serde(skip_serializing_if = "Option::is_none")]
563 allow_paid_broadcast: Option<bool>,
564 #[serde(skip_serializing_if = "Option::is_none")]
565 message_effect_id: Option<String>,
566 #[serde(skip_serializing_if = "Option::is_none")]
567 suggested_post_parameters: Option<SuggestedPostParameters>,
568}
569
570pub struct SendDice {
572 client: BotClient,
573 params: SendDiceParams,
574}
575
576impl SendDice {
577 pub(crate) fn new(client: BotClient, chat_id: impl Into<ChatId>) -> Self {
578 Self {
579 client,
580 params: SendDiceParams {
581 chat_id: chat_id.into(),
582 emoji: None,
583 message_thread_id: None,
584 direct_messages_topic_id: None,
585 disable_notification: None,
586 protect_content: None,
587 reply_parameters: None,
588 reply_markup: None,
589 business_connection_id: None,
590 allow_paid_broadcast: None,
591 message_effect_id: None,
592 suggested_post_parameters: None,
593 },
594 }
595 }
596 pub fn emoji(mut self, e: impl Into<String>) -> Self {
598 self.params.emoji = Some(e.into());
599 self
600 }
601 pub fn message_thread_id(mut self, id: i64) -> Self {
603 self.params.message_thread_id = Some(id);
604 self
605 }
606 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
608 self.params.direct_messages_topic_id = Some(id);
609 self
610 }
611 pub fn disable_notification(mut self, v: bool) -> Self {
613 self.params.disable_notification = Some(v);
614 self
615 }
616 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
618 self.params.reply_markup = Some(m.into());
619 self
620 }
621 pub fn business_connection_id(mut self, v: impl Into<String>) -> Self {
623 self.params.business_connection_id = Some(v.into());
624 self
625 }
626 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
628 self.params.allow_paid_broadcast = Some(v);
629 self
630 }
631 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
633 self.params.message_effect_id = Some(v.into());
634 self
635 }
636 pub fn suggested_post_parameters(mut self, v: SuggestedPostParameters) -> Self {
638 self.params.suggested_post_parameters = Some(v);
639 self
640 }
641 pub fn protect_content(mut self, v: bool) -> Self {
643 self.params.protect_content = Some(v);
644 self
645 }
646 pub fn reply_parameters(mut self, v: ReplyParameters) -> Self {
648 self.params.reply_parameters = Some(v);
649 self
650 }
651}
652
653impl_into_future!(SendDice, Message, "sendDice");
654
655#[derive(Serialize)]
658struct SendLocationParams {
659 chat_id: ChatId,
660 latitude: f64,
661 longitude: f64,
662 #[serde(skip_serializing_if = "Option::is_none")]
663 message_thread_id: Option<i64>,
664 #[serde(skip_serializing_if = "Option::is_none")]
665 direct_messages_topic_id: Option<i64>,
666 #[serde(skip_serializing_if = "Option::is_none")]
667 horizontal_accuracy: Option<f64>,
668 #[serde(skip_serializing_if = "Option::is_none")]
669 live_period: Option<u32>,
670 #[serde(skip_serializing_if = "Option::is_none")]
671 heading: Option<u16>,
672 #[serde(skip_serializing_if = "Option::is_none")]
673 proximity_alert_radius: Option<u32>,
674 #[serde(skip_serializing_if = "Option::is_none")]
675 disable_notification: Option<bool>,
676 #[serde(skip_serializing_if = "Option::is_none")]
677 protect_content: Option<bool>,
678 #[serde(skip_serializing_if = "Option::is_none")]
679 reply_parameters: Option<ReplyParameters>,
680 #[serde(skip_serializing_if = "Option::is_none")]
681 reply_markup: Option<ReplyMarkup>,
682 #[serde(skip_serializing_if = "Option::is_none")]
683 receiver_user_id: Option<i64>,
684 #[serde(skip_serializing_if = "Option::is_none")]
685 callback_query_id: Option<String>,
686 #[serde(skip_serializing_if = "Option::is_none")]
687 business_connection_id: Option<String>,
688 #[serde(skip_serializing_if = "Option::is_none")]
689 allow_paid_broadcast: Option<bool>,
690 #[serde(skip_serializing_if = "Option::is_none")]
691 message_effect_id: Option<String>,
692 #[serde(skip_serializing_if = "Option::is_none")]
693 suggested_post_parameters: Option<SuggestedPostParameters>,
694}
695
696pub struct SendLocation {
698 client: BotClient,
699 params: SendLocationParams,
700}
701
702impl SendLocation {
703 pub(crate) fn new(
704 client: BotClient,
705 chat_id: impl Into<ChatId>,
706 latitude: f64,
707 longitude: f64,
708 ) -> Self {
709 Self {
710 client,
711 params: SendLocationParams {
712 chat_id: chat_id.into(),
713 latitude,
714 longitude,
715 message_thread_id: None,
716 direct_messages_topic_id: None,
717 horizontal_accuracy: None,
718 live_period: None,
719 heading: None,
720 proximity_alert_radius: None,
721 disable_notification: None,
722 protect_content: None,
723 reply_parameters: None,
724 reply_markup: None,
725 receiver_user_id: None,
726 callback_query_id: None,
727 business_connection_id: None,
728 allow_paid_broadcast: None,
729 message_effect_id: None,
730 suggested_post_parameters: None,
731 },
732 }
733 }
734 pub fn message_thread_id(mut self, id: i64) -> Self {
736 self.params.message_thread_id = Some(id);
737 self
738 }
739 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
741 self.params.direct_messages_topic_id = Some(id);
742 self
743 }
744 pub fn horizontal_accuracy(mut self, v: f64) -> Self {
746 self.params.horizontal_accuracy = Some(v);
747 self
748 }
749 pub fn live_period(mut self, v: u32) -> Self {
753 self.params.live_period = Some(v);
754 self
755 }
756 pub fn heading(mut self, v: u16) -> Self {
758 self.params.heading = Some(v);
759 self
760 }
761 pub fn proximity_alert_radius(mut self, v: u32) -> Self {
763 self.params.proximity_alert_radius = Some(v);
764 self
765 }
766 pub fn disable_notification(mut self, v: bool) -> Self {
768 self.params.disable_notification = Some(v);
769 self
770 }
771 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
773 self.params.reply_markup = Some(m.into());
774 self
775 }
776 pub fn receiver_user_id(mut self, id: i64) -> Self {
778 self.params.receiver_user_id = Some(id);
779 self
780 }
781 pub fn callback_query_id(mut self, id: impl Into<String>) -> Self {
783 self.params.callback_query_id = Some(id.into());
784 self
785 }
786 pub fn business_connection_id(mut self, v: impl Into<String>) -> Self {
788 self.params.business_connection_id = Some(v.into());
789 self
790 }
791 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
793 self.params.allow_paid_broadcast = Some(v);
794 self
795 }
796 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
798 self.params.message_effect_id = Some(v.into());
799 self
800 }
801 pub fn suggested_post_parameters(mut self, v: SuggestedPostParameters) -> Self {
803 self.params.suggested_post_parameters = Some(v);
804 self
805 }
806 pub fn protect_content(mut self, v: bool) -> Self {
808 self.params.protect_content = Some(v);
809 self
810 }
811 pub fn reply_parameters(mut self, v: ReplyParameters) -> Self {
813 self.params.reply_parameters = Some(v);
814 self
815 }
816}
817
818impl_into_future!(SendLocation, Message, "sendLocation");
819
820#[derive(Serialize)]
823struct SendContactParams {
824 chat_id: ChatId,
825 phone_number: String,
826 first_name: String,
827 #[serde(skip_serializing_if = "Option::is_none")]
828 last_name: Option<String>,
829 #[serde(skip_serializing_if = "Option::is_none")]
830 vcard: Option<String>,
831 #[serde(skip_serializing_if = "Option::is_none")]
832 message_thread_id: Option<i64>,
833 #[serde(skip_serializing_if = "Option::is_none")]
834 direct_messages_topic_id: Option<i64>,
835 #[serde(skip_serializing_if = "Option::is_none")]
836 disable_notification: Option<bool>,
837 #[serde(skip_serializing_if = "Option::is_none")]
838 protect_content: Option<bool>,
839 #[serde(skip_serializing_if = "Option::is_none")]
840 reply_parameters: Option<ReplyParameters>,
841 #[serde(skip_serializing_if = "Option::is_none")]
842 reply_markup: Option<ReplyMarkup>,
843 #[serde(skip_serializing_if = "Option::is_none")]
844 receiver_user_id: Option<i64>,
845 #[serde(skip_serializing_if = "Option::is_none")]
846 callback_query_id: Option<String>,
847 #[serde(skip_serializing_if = "Option::is_none")]
848 business_connection_id: Option<String>,
849 #[serde(skip_serializing_if = "Option::is_none")]
850 allow_paid_broadcast: Option<bool>,
851 #[serde(skip_serializing_if = "Option::is_none")]
852 message_effect_id: Option<String>,
853 #[serde(skip_serializing_if = "Option::is_none")]
854 suggested_post_parameters: Option<SuggestedPostParameters>,
855}
856
857pub struct SendContact {
859 client: BotClient,
860 params: SendContactParams,
861}
862
863impl SendContact {
864 pub(crate) fn new(
865 client: BotClient,
866 chat_id: impl Into<ChatId>,
867 phone_number: impl Into<String>,
868 first_name: impl Into<String>,
869 ) -> Self {
870 Self {
871 client,
872 params: SendContactParams {
873 chat_id: chat_id.into(),
874 phone_number: phone_number.into(),
875 first_name: first_name.into(),
876 last_name: None,
877 vcard: None,
878 message_thread_id: None,
879 direct_messages_topic_id: None,
880 disable_notification: None,
881 protect_content: None,
882 reply_parameters: None,
883 reply_markup: None,
884 receiver_user_id: None,
885 callback_query_id: None,
886 business_connection_id: None,
887 allow_paid_broadcast: None,
888 message_effect_id: None,
889 suggested_post_parameters: None,
890 },
891 }
892 }
893 pub fn message_thread_id(mut self, id: i64) -> Self {
895 self.params.message_thread_id = Some(id);
896 self
897 }
898 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
900 self.params.direct_messages_topic_id = Some(id);
901 self
902 }
903 pub fn last_name(mut self, v: impl Into<String>) -> Self {
905 self.params.last_name = Some(v.into());
906 self
907 }
908 pub fn vcard(mut self, v: impl Into<String>) -> Self {
910 self.params.vcard = Some(v.into());
911 self
912 }
913 pub fn disable_notification(mut self, v: bool) -> Self {
915 self.params.disable_notification = Some(v);
916 self
917 }
918 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
920 self.params.reply_markup = Some(m.into());
921 self
922 }
923 pub fn receiver_user_id(mut self, id: i64) -> Self {
925 self.params.receiver_user_id = Some(id);
926 self
927 }
928 pub fn callback_query_id(mut self, id: impl Into<String>) -> Self {
930 self.params.callback_query_id = Some(id.into());
931 self
932 }
933 pub fn business_connection_id(mut self, v: impl Into<String>) -> Self {
935 self.params.business_connection_id = Some(v.into());
936 self
937 }
938 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
940 self.params.allow_paid_broadcast = Some(v);
941 self
942 }
943 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
945 self.params.message_effect_id = Some(v.into());
946 self
947 }
948 pub fn suggested_post_parameters(mut self, v: SuggestedPostParameters) -> Self {
950 self.params.suggested_post_parameters = Some(v);
951 self
952 }
953 pub fn protect_content(mut self, v: bool) -> Self {
955 self.params.protect_content = Some(v);
956 self
957 }
958 pub fn reply_parameters(mut self, v: ReplyParameters) -> Self {
960 self.params.reply_parameters = Some(v);
961 self
962 }
963}
964
965impl_into_future!(SendContact, Message, "sendContact");
966
967#[derive(Serialize)]
970struct SendPollParams {
971 chat_id: ChatId,
972 question: String,
973 options: Vec<InputPollOption>,
974 #[serde(skip_serializing_if = "Option::is_none")]
975 question_parse_mode: Option<ParseMode>,
976 #[serde(skip_serializing_if = "Option::is_none")]
977 question_entities: Option<Vec<rustigram_types::message::MessageEntity>>,
978 #[serde(skip_serializing_if = "Option::is_none")]
979 message_thread_id: Option<i64>,
980 #[serde(skip_serializing_if = "Option::is_none")]
981 direct_messages_topic_id: Option<i64>,
982 #[serde(skip_serializing_if = "Option::is_none", rename = "type")]
983 poll_type: Option<rustigram_types::poll::PollType>,
984 #[serde(skip_serializing_if = "Option::is_none")]
985 is_anonymous: Option<bool>,
986 #[serde(skip_serializing_if = "Option::is_none")]
987 allows_multiple_answers: Option<bool>,
988 #[serde(skip_serializing_if = "Option::is_none")]
989 allows_revoting: Option<bool>,
990 #[serde(skip_serializing_if = "Option::is_none")]
991 correct_option_ids: Option<Vec<u8>>,
992 #[serde(skip_serializing_if = "Option::is_none")]
993 explanation: Option<String>,
994 #[serde(skip_serializing_if = "Option::is_none")]
995 explanation_parse_mode: Option<ParseMode>,
996 #[serde(skip_serializing_if = "Option::is_none")]
997 explanation_entities: Option<Vec<rustigram_types::message::MessageEntity>>,
998 #[serde(skip_serializing_if = "Option::is_none")]
999 open_period: Option<u32>,
1000 #[serde(skip_serializing_if = "Option::is_none")]
1001 close_date: Option<i64>,
1002 #[serde(skip_serializing_if = "Option::is_none")]
1003 is_closed: Option<bool>,
1004 #[serde(skip_serializing_if = "Option::is_none")]
1005 shuffle_options: Option<bool>,
1006 #[serde(skip_serializing_if = "Option::is_none")]
1007 allow_adding_options: Option<bool>,
1008 #[serde(skip_serializing_if = "Option::is_none")]
1009 hide_results_until_closes: Option<bool>,
1010 #[serde(skip_serializing_if = "Option::is_none")]
1011 description: Option<String>,
1012 #[serde(skip_serializing_if = "Option::is_none")]
1013 description_parse_mode: Option<ParseMode>,
1014 #[serde(skip_serializing_if = "Option::is_none")]
1015 description_entities: Option<Vec<rustigram_types::message::MessageEntity>>,
1016 #[serde(skip_serializing_if = "Option::is_none")]
1017 disable_notification: Option<bool>,
1018 #[serde(skip_serializing_if = "Option::is_none")]
1019 protect_content: Option<bool>,
1020 #[serde(skip_serializing_if = "Option::is_none")]
1021 reply_parameters: Option<ReplyParameters>,
1022 #[serde(skip_serializing_if = "Option::is_none")]
1023 reply_markup: Option<ReplyMarkup>,
1024 #[serde(skip_serializing_if = "Option::is_none")]
1025 suggested_post_parameters: Option<SuggestedPostParameters>,
1026 #[serde(skip_serializing_if = "Option::is_none")]
1027 members_only: Option<bool>,
1028 #[serde(skip_serializing_if = "Option::is_none")]
1029 country_codes: Option<Vec<String>>,
1030 #[serde(skip_serializing_if = "Option::is_none")]
1031 media: Option<rustigram_types::poll::InputPollMedia>,
1032 #[serde(skip_serializing_if = "Option::is_none")]
1033 explanation_media: Option<rustigram_types::poll::InputPollMedia>,
1034 #[serde(skip_serializing_if = "Option::is_none")]
1035 business_connection_id: Option<String>,
1036 #[serde(skip_serializing_if = "Option::is_none")]
1037 allow_paid_broadcast: Option<bool>,
1038 #[serde(skip_serializing_if = "Option::is_none")]
1039 message_effect_id: Option<String>,
1040}
1041
1042pub struct SendPoll {
1044 client: BotClient,
1045 params: SendPollParams,
1046}
1047
1048impl SendPoll {
1049 pub(crate) fn new(
1050 client: BotClient,
1051 chat_id: impl Into<ChatId>,
1052 question: impl Into<String>,
1053 options: Vec<InputPollOption>,
1054 ) -> Self {
1055 Self {
1056 client,
1057 params: SendPollParams {
1058 chat_id: chat_id.into(),
1059 question: question.into(),
1060 options,
1061 question_parse_mode: None,
1062 question_entities: None,
1063 message_thread_id: None,
1064 direct_messages_topic_id: None,
1065 poll_type: None,
1066 is_anonymous: None,
1067 allows_multiple_answers: None,
1068 allows_revoting: None,
1069 correct_option_ids: None,
1070 explanation: None,
1071 explanation_parse_mode: None,
1072 explanation_entities: None,
1073 open_period: None,
1074 close_date: None,
1075 is_closed: None,
1076 shuffle_options: None,
1077 allow_adding_options: None,
1078 hide_results_until_closes: None,
1079 description: None,
1080 description_parse_mode: None,
1081 description_entities: None,
1082 disable_notification: None,
1083 protect_content: None,
1084 reply_parameters: None,
1085 reply_markup: None,
1086 suggested_post_parameters: None,
1087 members_only: None,
1088 country_codes: None,
1089 media: None,
1090 explanation_media: None,
1091 business_connection_id: None,
1092 allow_paid_broadcast: None,
1093 message_effect_id: None,
1094 },
1095 }
1096 }
1097 pub fn message_thread_id(mut self, id: i64) -> Self {
1099 self.params.message_thread_id = Some(id);
1100 self
1101 }
1102 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
1104 self.params.direct_messages_topic_id = Some(id);
1105 self
1106 }
1107 pub fn is_anonymous(mut self, v: bool) -> Self {
1109 self.params.is_anonymous = Some(v);
1110 self
1111 }
1112 pub fn allows_multiple_answers(mut self, v: bool) -> Self {
1114 self.params.allows_multiple_answers = Some(v);
1115 self
1116 }
1117 pub fn allows_revoting(mut self, v: bool) -> Self {
1119 self.params.allows_revoting = Some(v);
1120 self
1121 }
1122 pub fn quiz(mut self, ids: Vec<u8>) -> Self {
1124 self.params.poll_type = Some(rustigram_types::poll::PollType::Quiz);
1125 self.params.correct_option_ids = Some(ids);
1126 self
1127 }
1128 pub fn quiz_single(self, id: u8) -> Self {
1130 self.quiz(vec![id])
1131 }
1132 pub fn explanation(mut self, text: impl Into<String>) -> Self {
1134 self.params.explanation = Some(text.into());
1135 self
1136 }
1137 pub fn explanation_parse_mode(mut self, mode: ParseMode) -> Self {
1139 self.params.explanation_parse_mode = Some(mode);
1140 self
1141 }
1142 pub fn explanation_entities(mut self, e: Vec<rustigram_types::message::MessageEntity>) -> Self {
1144 self.params.explanation_entities = Some(e);
1145 self
1146 }
1147 pub fn open_period(mut self, secs: u32) -> Self {
1149 self.params.open_period = Some(secs);
1150 self
1151 }
1152 pub fn close_date(mut self, ts: i64) -> Self {
1154 self.params.close_date = Some(ts);
1155 self
1156 }
1157 pub fn shuffle_options(mut self, v: bool) -> Self {
1159 self.params.shuffle_options = Some(v);
1160 self
1161 }
1162 pub fn allow_adding_options(mut self, v: bool) -> Self {
1164 self.params.allow_adding_options = Some(v);
1165 self
1166 }
1167 pub fn hide_results_until_closes(mut self, v: bool) -> Self {
1169 self.params.hide_results_until_closes = Some(v);
1170 self
1171 }
1172 pub fn description(mut self, d: impl Into<String>) -> Self {
1174 self.params.description = Some(d.into());
1175 self
1176 }
1177 pub fn description_parse_mode(mut self, mode: ParseMode) -> Self {
1179 self.params.description_parse_mode = Some(mode);
1180 self
1181 }
1182 pub fn description_entities(mut self, e: Vec<rustigram_types::message::MessageEntity>) -> Self {
1184 self.params.description_entities = Some(e);
1185 self
1186 }
1187 pub fn question_parse_mode(mut self, mode: ParseMode) -> Self {
1189 self.params.question_parse_mode = Some(mode);
1190 self
1191 }
1192 pub fn question_entities(mut self, e: Vec<rustigram_types::message::MessageEntity>) -> Self {
1194 self.params.question_entities = Some(e);
1195 self
1196 }
1197 pub fn disable_notification(mut self, v: bool) -> Self {
1199 self.params.disable_notification = Some(v);
1200 self
1201 }
1202 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
1204 self.params.reply_markup = Some(m.into());
1205 self
1206 }
1207 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self {
1209 self.params.suggested_post_parameters = Some(params);
1210 self
1211 }
1212 pub fn members_only(mut self, v: bool) -> Self {
1215 self.params.members_only = Some(v);
1216 self
1217 }
1218 pub fn country_codes(mut self, codes: Vec<impl Into<String>>) -> Self {
1220 self.params.country_codes = Some(codes.into_iter().map(Into::into).collect());
1221 self
1222 }
1223
1224 pub fn media(mut self, m: rustigram_types::poll::InputPollMedia) -> Self {
1226 self.params.media = Some(m);
1227 self
1228 }
1229
1230 pub fn explanation_media(mut self, m: rustigram_types::poll::InputPollMedia) -> Self {
1232 self.params.explanation_media = Some(m);
1233 self
1234 }
1235 pub fn business_connection_id(mut self, v: impl Into<String>) -> Self {
1237 self.params.business_connection_id = Some(v.into());
1238 self
1239 }
1240 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
1242 self.params.allow_paid_broadcast = Some(v);
1243 self
1244 }
1245 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
1247 self.params.message_effect_id = Some(v.into());
1248 self
1249 }
1250 pub fn is_closed(mut self, v: bool) -> Self {
1252 self.params.is_closed = Some(v);
1253 self
1254 }
1255 pub fn protect_content(mut self, v: bool) -> Self {
1257 self.params.protect_content = Some(v);
1258 self
1259 }
1260 pub fn reply_parameters(mut self, v: ReplyParameters) -> Self {
1262 self.params.reply_parameters = Some(v);
1263 self
1264 }
1265}
1266
1267impl_into_future!(SendPoll, Message, "sendPoll");
1268
1269#[derive(Serialize)]
1272struct SendMessageDraftParams {
1273 chat_id: ChatId,
1274 draft_id: i64,
1275 #[serde(skip_serializing_if = "Option::is_none")]
1279 text: Option<String>,
1280 #[serde(skip_serializing_if = "Option::is_none")]
1281 message_thread_id: Option<i64>,
1282 #[serde(skip_serializing_if = "Option::is_none")]
1283 parse_mode: Option<ParseMode>,
1284 #[serde(skip_serializing_if = "Option::is_none")]
1285 entities: Option<Vec<rustigram_types::message::MessageEntity>>,
1286}
1287
1288pub struct SendMessageDraft {
1291 client: BotClient,
1292 params: SendMessageDraftParams,
1293}
1294
1295impl SendMessageDraft {
1296 pub(crate) fn new(
1297 client: BotClient,
1298 chat_id: impl Into<ChatId>,
1299 draft_id: i64,
1300 text: impl Into<String>,
1301 ) -> Self {
1302 Self {
1303 client,
1304 params: SendMessageDraftParams {
1305 chat_id: chat_id.into(),
1306 draft_id,
1307 text: Some(text.into()),
1308 message_thread_id: None,
1309 parse_mode: None,
1310 entities: None,
1311 },
1312 }
1313 }
1314 pub fn parse_mode(mut self, m: ParseMode) -> Self {
1316 self.params.parse_mode = Some(m);
1317 self
1318 }
1319 pub fn entities(mut self, e: Vec<rustigram_types::message::MessageEntity>) -> Self {
1321 self.params.entities = Some(e);
1322 self
1323 }
1324 pub fn clear_text(mut self) -> Self {
1326 self.params.text = None;
1327 self
1328 }
1329 pub fn message_thread_id(mut self, v: i64) -> Self {
1331 self.params.message_thread_id = Some(v);
1332 self
1333 }
1334}
1335
1336impl_into_future!(SendMessageDraft, bool, "sendMessageDraft");
1337
1338fn apply_media_opts(mut form: Form, opts: &MediaSendOptions) -> Form {
1355 fn json_text(form: Form, key: &'static str, value: &impl Serialize) -> Form {
1356 match serde_json::to_string(value) {
1359 Ok(json) => form.text(key, json),
1360 Err(_) => form,
1361 }
1362 }
1363
1364 if let Some(v) = &opts.business_connection_id {
1365 form = form.text("business_connection_id", v.clone());
1366 }
1367 if let Some(v) = opts.message_thread_id {
1368 form = form.text("message_thread_id", v.to_string());
1369 }
1370 if let Some(v) = opts.direct_messages_topic_id {
1371 form = form.text("direct_messages_topic_id", v.to_string());
1372 }
1373 if let Some(v) = &opts.caption {
1374 form = form.text("caption", v.clone());
1375 }
1376 if let Some(v) = &opts.parse_mode {
1377 form = form.text("parse_mode", format!("{v:?}"));
1378 }
1379 if let Some(v) = &opts.caption_entities {
1380 form = json_text(form, "caption_entities", v);
1381 }
1382 if let Some(v) = opts.show_caption_above_media {
1383 form = form.text("show_caption_above_media", v.to_string());
1384 }
1385 if let Some(v) = opts.has_spoiler {
1386 form = form.text("has_spoiler", v.to_string());
1387 }
1388 if let Some(v) = opts.disable_notification {
1389 form = form.text("disable_notification", v.to_string());
1390 }
1391 if let Some(v) = opts.protect_content {
1392 form = form.text("protect_content", v.to_string());
1393 }
1394 if let Some(v) = opts.allow_paid_broadcast {
1395 form = form.text("allow_paid_broadcast", v.to_string());
1396 }
1397 if let Some(v) = &opts.message_effect_id {
1398 form = form.text("message_effect_id", v.clone());
1399 }
1400 if let Some(v) = &opts.reply_parameters {
1401 form = json_text(form, "reply_parameters", v);
1402 }
1403 if let Some(v) = &opts.reply_markup {
1404 form = json_text(form, "reply_markup", v);
1405 }
1406 if let Some(v) = &opts.suggested_post_parameters {
1407 form = json_text(form, "suggested_post_parameters", v);
1408 }
1409 if let Some(v) = opts.receiver_user_id {
1410 form = form.text("receiver_user_id", v.to_string());
1411 }
1412 if let Some(v) = &opts.callback_query_id {
1413 form = form.text("callback_query_id", v.clone());
1414 }
1415 form
1416}
1417
1418#[derive(Default)]
1420pub struct MediaSendOptions {
1421 pub business_connection_id: Option<String>,
1423 pub message_thread_id: Option<i64>,
1425 pub direct_messages_topic_id: Option<i64>,
1427 pub caption: Option<String>,
1429 pub parse_mode: Option<ParseMode>,
1431 pub caption_entities: Option<Vec<rustigram_types::message::MessageEntity>>,
1433 pub show_caption_above_media: Option<bool>,
1435 pub has_spoiler: Option<bool>,
1437 pub disable_notification: Option<bool>,
1439 pub protect_content: Option<bool>,
1441 pub allow_paid_broadcast: Option<bool>,
1443 pub message_effect_id: Option<String>,
1445 pub reply_parameters: Option<ReplyParameters>,
1447 pub reply_markup: Option<ReplyMarkup>,
1449 pub suggested_post_parameters: Option<SuggestedPostParameters>,
1451 pub receiver_user_id: Option<i64>,
1455 pub callback_query_id: Option<String>,
1458}
1459
1460fn media_json_body(
1462 chat_id: &ChatId,
1463 media_field: &str,
1464 media_value: &str,
1465 opts: &MediaSendOptions,
1466 extra: serde_json::Value,
1467) -> serde_json::Value {
1468 let mut map = serde_json::json!({
1469 "chat_id": chat_id,
1470 media_field: media_value,
1471 });
1472 let obj = map.as_object_mut().unwrap();
1473 if let Some(v) = &opts.business_connection_id {
1474 obj.insert("business_connection_id".to_owned(), serde_json::json!(v));
1475 }
1476 if let Some(v) = &opts.message_thread_id {
1477 obj.insert("message_thread_id".to_owned(), serde_json::json!(v));
1478 }
1479 if let Some(v) = &opts.direct_messages_topic_id {
1480 obj.insert("direct_messages_topic_id".to_owned(), serde_json::json!(v));
1481 }
1482 if let Some(v) = &opts.caption {
1483 obj.insert("caption".to_owned(), serde_json::json!(v));
1484 }
1485 if let Some(v) = &opts.parse_mode {
1486 obj.insert("parse_mode".to_owned(), serde_json::json!(v));
1487 }
1488 if let Some(v) = &opts.caption_entities {
1489 obj.insert("caption_entities".to_owned(), serde_json::json!(v));
1490 }
1491 if let Some(v) = opts.show_caption_above_media {
1492 obj.insert("show_caption_above_media".to_owned(), serde_json::json!(v));
1493 }
1494 if let Some(v) = opts.has_spoiler {
1495 obj.insert("has_spoiler".to_owned(), serde_json::json!(v));
1496 }
1497 if let Some(v) = opts.disable_notification {
1498 obj.insert("disable_notification".to_owned(), serde_json::json!(v));
1499 }
1500 if let Some(v) = opts.protect_content {
1501 obj.insert("protect_content".to_owned(), serde_json::json!(v));
1502 }
1503 if let Some(v) = opts.allow_paid_broadcast {
1504 obj.insert("allow_paid_broadcast".to_owned(), serde_json::json!(v));
1505 }
1506 if let Some(v) = &opts.message_effect_id {
1507 obj.insert("message_effect_id".to_owned(), serde_json::json!(v));
1508 }
1509 if let Some(v) = &opts.reply_parameters {
1510 obj.insert("reply_parameters".to_owned(), serde_json::json!(v));
1511 }
1512 if let Some(v) = &opts.reply_markup {
1513 obj.insert("reply_markup".to_owned(), serde_json::json!(v));
1514 }
1515 if let Some(v) = &opts.suggested_post_parameters {
1516 obj.insert("suggested_post_parameters".to_owned(), serde_json::json!(v));
1517 }
1518 if let Some(v) = opts.receiver_user_id {
1519 obj.insert("receiver_user_id".to_owned(), serde_json::json!(v));
1520 }
1521 if let Some(v) = &opts.callback_query_id {
1522 obj.insert("callback_query_id".to_owned(), serde_json::json!(v));
1523 }
1524 if let serde_json::Value::Object(extra_obj) = extra {
1525 for (k, v) in extra_obj {
1526 obj.insert(k, v);
1527 }
1528 }
1529 map
1530}
1531
1532pub struct SendPhoto {
1536 client: BotClient,
1537 chat_id: ChatId,
1538 photo: InputFile,
1539 opts: MediaSendOptions,
1540}
1541
1542impl SendPhoto {
1543 pub(crate) fn new(client: BotClient, chat_id: impl Into<ChatId>, photo: InputFile) -> Self {
1544 Self {
1545 client,
1546 chat_id: chat_id.into(),
1547 photo,
1548 opts: MediaSendOptions::default(),
1549 }
1550 }
1551 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
1553 self.opts.business_connection_id = Some(id.into());
1554 self
1555 }
1556 pub fn message_thread_id(mut self, id: i64) -> Self {
1558 self.opts.message_thread_id = Some(id);
1559 self
1560 }
1561 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
1563 self.opts.direct_messages_topic_id = Some(id);
1564 self
1565 }
1566 pub fn caption(mut self, c: impl Into<String>) -> Self {
1568 self.opts.caption = Some(c.into());
1569 self
1570 }
1571 pub fn parse_mode(mut self, m: ParseMode) -> Self {
1573 self.opts.parse_mode = Some(m);
1574 self
1575 }
1576 pub fn has_spoiler(mut self, v: bool) -> Self {
1578 self.opts.has_spoiler = Some(v);
1579 self
1580 }
1581 pub fn caption_entities(
1583 mut self,
1584 entities: Vec<rustigram_types::message::MessageEntity>,
1585 ) -> Self {
1586 self.opts.caption_entities = Some(entities);
1587 self
1588 }
1589 pub fn show_caption_above_media(mut self, v: bool) -> Self {
1591 self.opts.show_caption_above_media = Some(v);
1592 self
1593 }
1594 pub fn disable_notification(mut self, v: bool) -> Self {
1596 self.opts.disable_notification = Some(v);
1597 self
1598 }
1599 pub fn protect_content(mut self, v: bool) -> Self {
1601 self.opts.protect_content = Some(v);
1602 self
1603 }
1604 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
1606 self.opts.allow_paid_broadcast = Some(v);
1607 self
1608 }
1609 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
1611 self.opts.reply_parameters = Some(rp);
1612 self
1613 }
1614 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
1616 self.opts.reply_markup = Some(m.into());
1617 self
1618 }
1619 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self {
1621 self.opts.suggested_post_parameters = Some(params);
1622 self
1623 }
1624 pub fn receiver_user_id(mut self, id: i64) -> Self {
1626 self.opts.receiver_user_id = Some(id);
1627 self
1628 }
1629 pub fn callback_query_id(mut self, id: impl Into<String>) -> Self {
1631 self.opts.callback_query_id = Some(id.into());
1632 self
1633 }
1634 pub fn message_effect_id(mut self, id: impl Into<String>) -> Self {
1636 self.opts.message_effect_id = Some(id.into());
1637 self
1638 }
1639}
1640
1641impl IntoFuture for SendPhoto {
1642 type Output = Result<Message>;
1643 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
1644
1645 fn into_future(self) -> Self::IntoFuture {
1646 Box::pin(async move {
1647 match &self.photo {
1648 InputFile::Bytes {
1649 filename,
1650 data,
1651 mime_type,
1652 } => {
1653 let part = Part::bytes(data.clone())
1654 .file_name(filename.clone())
1655 .mime_str(mime_type)
1656 .map_err(|e| crate::error::Error::Decode(e.to_string()))?;
1657 let mut form = Form::new().part("photo", part);
1658 form = form.text("chat_id", self.chat_id.to_string());
1659 form = apply_media_opts(form, &self.opts);
1660 self.client.post_multipart("sendPhoto", form).await
1661 }
1662 _ => {
1663 let body = media_json_body(
1664 &self.chat_id,
1665 "photo",
1666 self.photo.as_str(),
1667 &self.opts,
1668 serde_json::Value::Null,
1669 );
1670 self.client.post_json("sendPhoto", &body).await
1671 }
1672 }
1673 })
1674 }
1675}
1676
1677pub struct SendLivePhoto {
1681 client: BotClient,
1682 chat_id: ChatId,
1683 live_photo: InputFile,
1684 photo: InputFile,
1685 opts: MediaSendOptions,
1686}
1687
1688impl SendLivePhoto {
1689 pub(crate) fn new(
1690 client: BotClient,
1691 chat_id: impl Into<ChatId>,
1692 live_photo: InputFile,
1693 photo: InputFile,
1694 ) -> Self {
1695 Self {
1696 client,
1697 chat_id: chat_id.into(),
1698 live_photo,
1699 photo,
1700 opts: MediaSendOptions::default(),
1701 }
1702 }
1703 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
1705 self.opts.business_connection_id = Some(id.into());
1706 self
1707 }
1708 pub fn message_thread_id(mut self, id: i64) -> Self {
1710 self.opts.message_thread_id = Some(id);
1711 self
1712 }
1713 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
1715 self.opts.direct_messages_topic_id = Some(id);
1716 self
1717 }
1718 pub fn caption(mut self, c: impl Into<String>) -> Self {
1720 self.opts.caption = Some(c.into());
1721 self
1722 }
1723 pub fn parse_mode(mut self, m: ParseMode) -> Self {
1725 self.opts.parse_mode = Some(m);
1726 self
1727 }
1728 pub fn show_caption_above_media(mut self, v: bool) -> Self {
1730 self.opts.show_caption_above_media = Some(v);
1731 self
1732 }
1733 pub fn has_spoiler(mut self, v: bool) -> Self {
1735 self.opts.has_spoiler = Some(v);
1736 self
1737 }
1738 pub fn caption_entities(
1740 mut self,
1741 entities: Vec<rustigram_types::message::MessageEntity>,
1742 ) -> Self {
1743 self.opts.caption_entities = Some(entities);
1744 self
1745 }
1746 pub fn receiver_user_id(mut self, id: i64) -> Self {
1748 self.opts.receiver_user_id = Some(id);
1749 self
1750 }
1751 pub fn callback_query_id(mut self, id: impl Into<String>) -> Self {
1753 self.opts.callback_query_id = Some(id.into());
1754 self
1755 }
1756 pub fn disable_notification(mut self, v: bool) -> Self {
1758 self.opts.disable_notification = Some(v);
1759 self
1760 }
1761 pub fn protect_content(mut self, v: bool) -> Self {
1763 self.opts.protect_content = Some(v);
1764 self
1765 }
1766 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
1768 self.opts.allow_paid_broadcast = Some(v);
1769 self
1770 }
1771 pub fn message_effect_id(mut self, id: impl Into<String>) -> Self {
1773 self.opts.message_effect_id = Some(id.into());
1774 self
1775 }
1776 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
1778 self.opts.reply_parameters = Some(rp);
1779 self
1780 }
1781 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
1783 self.opts.reply_markup = Some(m.into());
1784 self
1785 }
1786 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self {
1788 self.opts.suggested_post_parameters = Some(params);
1789 self
1790 }
1791}
1792
1793impl IntoFuture for SendLivePhoto {
1794 type Output = Result<Message>;
1795 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
1796
1797 fn into_future(self) -> Self::IntoFuture {
1798 Box::pin(async move {
1799 let lp_bytes = self.live_photo.requires_multipart();
1800 let ph_bytes = self.photo.requires_multipart();
1801
1802 if lp_bytes || ph_bytes {
1803 let mut form = Form::new();
1804 form = form.text("chat_id", self.chat_id.to_string());
1805
1806 if let InputFile::Bytes {
1807 filename,
1808 data,
1809 mime_type,
1810 } = self.live_photo
1811 {
1812 let part = Part::bytes(data)
1813 .file_name(filename)
1814 .mime_str(&mime_type)
1815 .map_err(|e| crate::error::Error::Decode(e.to_string()))?;
1816 form = form.part("live_photo", part);
1817 } else {
1818 form = form.text("live_photo", self.live_photo.as_str().to_owned());
1819 }
1820
1821 if let InputFile::Bytes {
1822 filename,
1823 data,
1824 mime_type,
1825 } = self.photo
1826 {
1827 let part = Part::bytes(data)
1828 .file_name(filename)
1829 .mime_str(&mime_type)
1830 .map_err(|e| crate::error::Error::Decode(e.to_string()))?;
1831 form = form.part("photo", part);
1832 } else {
1833 form = form.text("photo", self.photo.as_str().to_owned());
1834 }
1835
1836 form = apply_media_opts(form, &self.opts);
1837
1838 self.client.post_multipart("sendLivePhoto", form).await
1839 } else {
1840 let mut body = media_json_body(
1841 &self.chat_id,
1842 "live_photo",
1843 self.live_photo.as_str(),
1844 &self.opts,
1845 serde_json::json!({}),
1846 );
1847 body.as_object_mut()
1848 .unwrap()
1849 .insert("photo".to_owned(), serde_json::json!(self.photo.as_str()));
1850 self.client.post_json("sendLivePhoto", &body).await
1851 }
1852 })
1853 }
1854}
1855
1856macro_rules! caption_setter {
1865 (caption) => {
1866 pub fn caption(mut self, c: impl Into<String>) -> Self {
1868 self.opts.caption = Some(c.into());
1869 self
1870 }
1871 };
1872 (parse_mode) => {
1873 pub fn parse_mode(mut self, m: ParseMode) -> Self {
1875 self.opts.parse_mode = Some(m);
1876 self
1877 }
1878 };
1879 (caption_entities) => {
1880 pub fn caption_entities(
1882 mut self,
1883 entities: Vec<rustigram_types::message::MessageEntity>,
1884 ) -> Self {
1885 self.opts.caption_entities = Some(entities);
1886 self
1887 }
1888 };
1889 (show_caption_above_media) => {
1890 pub fn show_caption_above_media(mut self, v: bool) -> Self {
1892 self.opts.show_caption_above_media = Some(v);
1893 self
1894 }
1895 };
1896 (has_spoiler) => {
1897 pub fn has_spoiler(mut self, v: bool) -> Self {
1899 self.opts.has_spoiler = Some(v);
1900 self
1901 }
1902 };
1903}
1904
1905macro_rules! media_sender {
1906 ($(#[$doc:meta])* $name:ident, $field:literal, $method:literal, $return_ty:ty,
1907 [$($extra_field:ident: $extra_ty:ty),*], [$($caption_opt:ident),*]) => {
1908 $(#[$doc])*
1909 pub struct $name {
1910 client: BotClient,
1912 chat_id: ChatId,
1914 file: InputFile,
1916 opts: MediaSendOptions,
1918 $($extra_field: Option<$extra_ty>,)*
1920 }
1921
1922 impl $name {
1923 pub(crate) fn new(client: BotClient, chat_id: impl Into<ChatId>, file: InputFile) -> Self {
1924 Self {
1925 client,
1926 chat_id: chat_id.into(),
1927 file,
1928 opts: MediaSendOptions::default(),
1929 $($extra_field: None,)*
1930 }
1931 }
1932 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self { self.opts.business_connection_id = Some(id.into()); self }
1934 pub fn message_thread_id(mut self, id: i64) -> Self { self.opts.message_thread_id = Some(id); self }
1936 pub fn direct_messages_topic_id(mut self, id: i64) -> Self { self.opts.direct_messages_topic_id = Some(id); self }
1938 $(caption_setter!($caption_opt);)*
1943 pub fn disable_notification(mut self, v: bool) -> Self { self.opts.disable_notification = Some(v); self }
1945 pub fn message_effect_id(mut self, id: impl Into<String>) -> Self { self.opts.message_effect_id = Some(id.into()); self }
1947 pub fn protect_content(mut self, v: bool) -> Self { self.opts.protect_content = Some(v); self }
1949 pub fn allow_paid_broadcast(mut self, v: bool) -> Self { self.opts.allow_paid_broadcast = Some(v); self }
1951 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self { self.opts.reply_parameters = Some(rp); self }
1953 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self { self.opts.reply_markup = Some(m.into()); self }
1955 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self { self.opts.suggested_post_parameters = Some(params); self }
1957 pub fn receiver_user_id(mut self, id: i64) -> Self { self.opts.receiver_user_id = Some(id); self }
1959 pub fn callback_query_id(mut self, id: impl Into<String>) -> Self { self.opts.callback_query_id = Some(id.into()); self }
1961
1962 $(
1963 #[doc = concat!("Sets the ", stringify!($extra_field), " for the media.")]
1964 pub fn $extra_field(mut self, v: $extra_ty) -> Self {
1965 self.$extra_field = Some(v);
1966 self
1967 }
1968 )*
1969 }
1970
1971 impl IntoFuture for $name {
1972 type Output = Result<$return_ty>;
1973 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
1974
1975 fn into_future(self) -> Self::IntoFuture {
1976 Box::pin(async move {
1977 match &self.file {
1978 InputFile::Bytes { filename, data, mime_type } => {
1979 let part = Part::bytes(data.clone())
1980 .file_name(filename.clone())
1981 .mime_str(mime_type)
1982 .map_err(|e| crate::error::Error::Decode(e.to_string()))?;
1983 let mut form = Form::new().part($field, part);
1984 form = form.text("chat_id", self.chat_id.to_string());
1985 form = apply_media_opts(form, &self.opts);
1992
1993 $(
1994 if let Some(ref v) = self.$extra_field {
1995 form = form.text(stringify!($extra_field), v.to_string());
1996 }
1997 )*
1998
1999 self.client.post_multipart($method, form).await
2000 }
2001 _ => {
2002 let mut extra = serde_json::json!({});
2003 $(
2004 if let Some(ref v) = self.$extra_field {
2005 extra[stringify!($extra_field)] = serde_json::json!(v);
2006 }
2007 )*
2008 let body = media_json_body(&self.chat_id, $field, self.file.as_str(), &self.opts, extra);
2009 self.client.post_json($method, &body).await
2010 }
2011 }
2012 })
2013 }
2014 }
2015 };
2016}
2017
2018media_sender!(
2019 SendAudio, "audio", "sendAudio", Message, [duration: u32, performer: String, title: String, thumbnail: String], [caption, parse_mode, caption_entities]);
2021media_sender!(
2022 SendDocument, "document", "sendDocument", Message, [disable_content_type_detection: bool, thumbnail: String], [caption, parse_mode, caption_entities]);
2024media_sender!(
2025 SendVideo, "video", "sendVideo", Message, [duration: u32, width: u32, height: u32, supports_streaming: bool, cover: String, start_timestamp: i64, thumbnail: String], [caption, parse_mode, caption_entities, show_caption_above_media, has_spoiler]);
2027media_sender!(
2028 SendAnimation, "animation", "sendAnimation", Message, [duration: u32, width: u32, height: u32, thumbnail: String], [caption, parse_mode, caption_entities, show_caption_above_media, has_spoiler]);
2030media_sender!(
2031 SendVoice, "voice", "sendVoice", Message, [duration: u32], [caption, parse_mode, caption_entities]);
2033media_sender!(
2034 SendVideoNote, "video_note", "sendVideoNote", Message, [duration: u32, length: u32, thumbnail: String], []);
2036media_sender!(
2037 SendSticker, "sticker", "sendSticker", Message, [emoji: String], []);
2039
2040#[derive(Serialize)]
2043struct DeleteMessageParams {
2044 chat_id: ChatId,
2045 message_id: i64,
2046}
2047
2048pub struct DeleteMessage {
2050 client: BotClient,
2051 params: DeleteMessageParams,
2052}
2053impl DeleteMessage {
2054 pub(crate) fn new(client: BotClient, chat_id: impl Into<ChatId>, message_id: i64) -> Self {
2055 Self {
2056 client,
2057 params: DeleteMessageParams {
2058 chat_id: chat_id.into(),
2059 message_id,
2060 },
2061 }
2062 }
2063}
2064impl_into_future!(DeleteMessage, bool, "deleteMessage");
2065
2066#[derive(Serialize)]
2067struct DeleteMessagesParams {
2068 chat_id: ChatId,
2069 message_ids: Vec<i64>,
2070}
2071
2072pub struct DeleteMessages {
2074 client: BotClient,
2075 params: DeleteMessagesParams,
2076}
2077impl DeleteMessages {
2078 pub(crate) fn new(
2079 client: BotClient,
2080 chat_id: impl Into<ChatId>,
2081 message_ids: Vec<i64>,
2082 ) -> Self {
2083 Self {
2084 client,
2085 params: DeleteMessagesParams {
2086 chat_id: chat_id.into(),
2087 message_ids,
2088 },
2089 }
2090 }
2091}
2092impl_into_future!(DeleteMessages, bool, "deleteMessages");
2093
2094#[derive(Serialize)]
2097struct DeleteEphemeralMessageParams {
2098 chat_id: ChatId,
2099 receiver_user_id: i64,
2100 ephemeral_message_id: i64,
2101}
2102
2103pub struct DeleteEphemeralMessage {
2108 client: BotClient,
2109 params: DeleteEphemeralMessageParams,
2110}
2111impl DeleteEphemeralMessage {
2112 pub(crate) fn new(
2113 client: BotClient,
2114 chat_id: impl Into<ChatId>,
2115 receiver_user_id: i64,
2116 ephemeral_message_id: i64,
2117 ) -> Self {
2118 Self {
2119 client,
2120 params: DeleteEphemeralMessageParams {
2121 chat_id: chat_id.into(),
2122 receiver_user_id,
2123 ephemeral_message_id,
2124 },
2125 }
2126 }
2127}
2128impl_into_future!(DeleteEphemeralMessage, bool, "deleteEphemeralMessage");
2129
2130#[derive(Serialize)]
2133struct StopPollParams {
2134 chat_id: ChatId,
2135 message_id: i64,
2136 #[serde(skip_serializing_if = "Option::is_none")]
2137 reply_markup: Option<rustigram_types::keyboard::InlineKeyboardMarkup>,
2138 #[serde(skip_serializing_if = "Option::is_none")]
2139 business_connection_id: Option<String>,
2140}
2141
2142pub struct StopPoll {
2144 client: BotClient,
2145 params: StopPollParams,
2146}
2147impl StopPoll {
2148 pub(crate) fn new(client: BotClient, chat_id: impl Into<ChatId>, message_id: i64) -> Self {
2149 Self {
2150 client,
2151 params: StopPollParams {
2152 chat_id: chat_id.into(),
2153 message_id,
2154 reply_markup: None,
2155 business_connection_id: None,
2156 },
2157 }
2158 }
2159 pub fn reply_markup(mut self, m: rustigram_types::keyboard::InlineKeyboardMarkup) -> Self {
2161 self.params.reply_markup = Some(m);
2162 self
2163 }
2164 pub fn business_connection_id(mut self, v: impl Into<String>) -> Self {
2166 self.params.business_connection_id = Some(v.into());
2167 self
2168 }
2169}
2170impl_into_future!(StopPoll, rustigram_types::poll::Poll, "stopPoll");
2171
2172#[derive(Serialize)]
2175struct AnswerCallbackQueryParams {
2176 callback_query_id: String,
2177 #[serde(skip_serializing_if = "Option::is_none")]
2178 text: Option<String>,
2179 #[serde(skip_serializing_if = "Option::is_none")]
2180 show_alert: Option<bool>,
2181 #[serde(skip_serializing_if = "Option::is_none")]
2182 url: Option<String>,
2183 #[serde(skip_serializing_if = "Option::is_none")]
2184 cache_time: Option<u32>,
2185}
2186
2187pub struct AnswerCallbackQuery {
2189 client: BotClient,
2190 params: AnswerCallbackQueryParams,
2191}
2192impl AnswerCallbackQuery {
2193 pub(crate) fn new(client: BotClient, callback_query_id: impl Into<String>) -> Self {
2194 Self {
2195 client,
2196 params: AnswerCallbackQueryParams {
2197 callback_query_id: callback_query_id.into(),
2198 text: None,
2199 show_alert: None,
2200 url: None,
2201 cache_time: None,
2202 },
2203 }
2204 }
2205 pub fn text(mut self, t: impl Into<String>) -> Self {
2207 self.params.text = Some(t.into());
2208 self
2209 }
2210 pub fn show_alert(mut self, v: bool) -> Self {
2212 self.params.show_alert = Some(v);
2213 self
2214 }
2215 pub fn url(mut self, u: impl Into<String>) -> Self {
2217 self.params.url = Some(u.into());
2218 self
2219 }
2220 pub fn cache_time(mut self, secs: u32) -> Self {
2222 self.params.cache_time = Some(secs);
2223 self
2224 }
2225 pub fn alert(self, text: impl Into<String>) -> Self {
2227 self.text(text).show_alert(true)
2228 }
2229}
2230impl_into_future!(AnswerCallbackQuery, bool, "answerCallbackQuery");
2231#[derive(Serialize)]
2234struct ForwardMessagesParams {
2235 chat_id: ChatId,
2236 from_chat_id: ChatId,
2237 message_ids: Vec<i64>,
2238 #[serde(skip_serializing_if = "Option::is_none")]
2239 message_thread_id: Option<i64>,
2240 #[serde(skip_serializing_if = "Option::is_none")]
2241 direct_messages_topic_id: Option<i64>,
2242 #[serde(skip_serializing_if = "Option::is_none")]
2243 disable_notification: Option<bool>,
2244 #[serde(skip_serializing_if = "Option::is_none")]
2245 protect_content: Option<bool>,
2246}
2247
2248pub struct ForwardMessages {
2253 client: BotClient,
2254 params: ForwardMessagesParams,
2255}
2256
2257impl ForwardMessages {
2258 pub(crate) fn new(
2259 client: BotClient,
2260 chat_id: impl Into<ChatId>,
2261 from_chat_id: impl Into<ChatId>,
2262 message_ids: Vec<i64>,
2263 ) -> Self {
2264 Self {
2265 client,
2266 params: ForwardMessagesParams {
2267 chat_id: chat_id.into(),
2268 from_chat_id: from_chat_id.into(),
2269 message_ids,
2270 message_thread_id: None,
2271 direct_messages_topic_id: None,
2272 disable_notification: None,
2273 protect_content: None,
2274 },
2275 }
2276 }
2277 pub fn message_thread_id(mut self, id: i64) -> Self {
2279 self.params.message_thread_id = Some(id);
2280 self
2281 }
2282 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
2284 self.params.direct_messages_topic_id = Some(id);
2285 self
2286 }
2287 pub fn disable_notification(mut self, v: bool) -> Self {
2289 self.params.disable_notification = Some(v);
2290 self
2291 }
2292 pub fn protect_content(mut self, v: bool) -> Self {
2294 self.params.protect_content = Some(v);
2295 self
2296 }
2297}
2298
2299impl_into_future!(
2300 ForwardMessages,
2301 Vec<rustigram_types::message::MessageId>,
2302 "forwardMessages"
2303);
2304
2305#[derive(Serialize)]
2308struct CopyMessagesParams {
2309 chat_id: ChatId,
2310 from_chat_id: ChatId,
2311 message_ids: Vec<i64>,
2312 #[serde(skip_serializing_if = "Option::is_none")]
2313 message_thread_id: Option<i64>,
2314 #[serde(skip_serializing_if = "Option::is_none")]
2315 direct_messages_topic_id: Option<i64>,
2316 #[serde(skip_serializing_if = "Option::is_none")]
2317 disable_notification: Option<bool>,
2318 #[serde(skip_serializing_if = "Option::is_none")]
2319 protect_content: Option<bool>,
2320 #[serde(skip_serializing_if = "Option::is_none")]
2321 remove_caption: Option<bool>,
2322}
2323
2324pub struct CopyMessages {
2329 client: BotClient,
2330 params: CopyMessagesParams,
2331}
2332
2333impl CopyMessages {
2334 pub(crate) fn new(
2335 client: BotClient,
2336 chat_id: impl Into<ChatId>,
2337 from_chat_id: impl Into<ChatId>,
2338 message_ids: Vec<i64>,
2339 ) -> Self {
2340 Self {
2341 client,
2342 params: CopyMessagesParams {
2343 chat_id: chat_id.into(),
2344 from_chat_id: from_chat_id.into(),
2345 message_ids,
2346 message_thread_id: None,
2347 direct_messages_topic_id: None,
2348 disable_notification: None,
2349 protect_content: None,
2350 remove_caption: None,
2351 },
2352 }
2353 }
2354 pub fn message_thread_id(mut self, id: i64) -> Self {
2356 self.params.message_thread_id = Some(id);
2357 self
2358 }
2359 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
2361 self.params.direct_messages_topic_id = Some(id);
2362 self
2363 }
2364 pub fn disable_notification(mut self, v: bool) -> Self {
2366 self.params.disable_notification = Some(v);
2367 self
2368 }
2369 pub fn protect_content(mut self, v: bool) -> Self {
2371 self.params.protect_content = Some(v);
2372 self
2373 }
2374 pub fn remove_caption(mut self, v: bool) -> Self {
2376 self.params.remove_caption = Some(v);
2377 self
2378 }
2379}
2380
2381impl_into_future!(
2382 CopyMessages,
2383 Vec<rustigram_types::message::MessageId>,
2384 "copyMessages"
2385);
2386
2387#[derive(Serialize)]
2390struct SendVenueParams {
2391 chat_id: ChatId,
2392 latitude: f64,
2393 longitude: f64,
2394 title: String,
2395 address: String,
2396 #[serde(skip_serializing_if = "Option::is_none")]
2397 message_thread_id: Option<i64>,
2398 #[serde(skip_serializing_if = "Option::is_none")]
2399 direct_messages_topic_id: Option<i64>,
2400 #[serde(skip_serializing_if = "Option::is_none")]
2401 foursquare_id: Option<String>,
2402 #[serde(skip_serializing_if = "Option::is_none")]
2403 foursquare_type: Option<String>,
2404 #[serde(skip_serializing_if = "Option::is_none")]
2405 google_place_id: Option<String>,
2406 #[serde(skip_serializing_if = "Option::is_none")]
2407 google_place_type: Option<String>,
2408 #[serde(skip_serializing_if = "Option::is_none")]
2409 disable_notification: Option<bool>,
2410 #[serde(skip_serializing_if = "Option::is_none")]
2411 protect_content: Option<bool>,
2412 #[serde(skip_serializing_if = "Option::is_none")]
2413 reply_parameters: Option<ReplyParameters>,
2414 #[serde(skip_serializing_if = "Option::is_none")]
2415 reply_markup: Option<ReplyMarkup>,
2416 #[serde(skip_serializing_if = "Option::is_none")]
2417 receiver_user_id: Option<i64>,
2418 #[serde(skip_serializing_if = "Option::is_none")]
2419 callback_query_id: Option<String>,
2420 #[serde(skip_serializing_if = "Option::is_none")]
2421 business_connection_id: Option<String>,
2422 #[serde(skip_serializing_if = "Option::is_none")]
2423 allow_paid_broadcast: Option<bool>,
2424 #[serde(skip_serializing_if = "Option::is_none")]
2425 message_effect_id: Option<String>,
2426 #[serde(skip_serializing_if = "Option::is_none")]
2427 suggested_post_parameters: Option<SuggestedPostParameters>,
2428}
2429
2430pub struct SendVenue {
2432 client: BotClient,
2433 params: SendVenueParams,
2434}
2435
2436impl SendVenue {
2437 pub(crate) fn new(
2438 client: BotClient,
2439 chat_id: impl Into<ChatId>,
2440 latitude: f64,
2441 longitude: f64,
2442 title: impl Into<String>,
2443 address: impl Into<String>,
2444 ) -> Self {
2445 Self {
2446 client,
2447 params: SendVenueParams {
2448 chat_id: chat_id.into(),
2449 latitude,
2450 longitude,
2451 title: title.into(),
2452 address: address.into(),
2453 message_thread_id: None,
2454 direct_messages_topic_id: None,
2455 foursquare_id: None,
2456 foursquare_type: None,
2457 google_place_id: None,
2458 google_place_type: None,
2459 disable_notification: None,
2460 protect_content: None,
2461 reply_parameters: None,
2462 reply_markup: None,
2463 receiver_user_id: None,
2464 callback_query_id: None,
2465 business_connection_id: None,
2466 allow_paid_broadcast: None,
2467 message_effect_id: None,
2468 suggested_post_parameters: None,
2469 },
2470 }
2471 }
2472 pub fn message_thread_id(mut self, id: i64) -> Self {
2474 self.params.message_thread_id = Some(id);
2475 self
2476 }
2477 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
2479 self.params.direct_messages_topic_id = Some(id);
2480 self
2481 }
2482 pub fn foursquare_id(mut self, id: impl Into<String>) -> Self {
2484 self.params.foursquare_id = Some(id.into());
2485 self
2486 }
2487 pub fn foursquare_type(mut self, t: impl Into<String>) -> Self {
2489 self.params.foursquare_type = Some(t.into());
2490 self
2491 }
2492 pub fn google_place_id(mut self, id: impl Into<String>) -> Self {
2494 self.params.google_place_id = Some(id.into());
2495 self
2496 }
2497 pub fn google_place_type(mut self, t: impl Into<String>) -> Self {
2499 self.params.google_place_type = Some(t.into());
2500 self
2501 }
2502 pub fn disable_notification(mut self, v: bool) -> Self {
2504 self.params.disable_notification = Some(v);
2505 self
2506 }
2507 pub fn protect_content(mut self, v: bool) -> Self {
2509 self.params.protect_content = Some(v);
2510 self
2511 }
2512 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
2514 self.params.reply_parameters = Some(rp);
2515 self
2516 }
2517 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
2519 self.params.reply_markup = Some(m.into());
2520 self
2521 }
2522 pub fn receiver_user_id(mut self, id: i64) -> Self {
2524 self.params.receiver_user_id = Some(id);
2525 self
2526 }
2527 pub fn callback_query_id(mut self, id: impl Into<String>) -> Self {
2529 self.params.callback_query_id = Some(id.into());
2530 self
2531 }
2532 pub fn business_connection_id(mut self, v: impl Into<String>) -> Self {
2534 self.params.business_connection_id = Some(v.into());
2535 self
2536 }
2537 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
2539 self.params.allow_paid_broadcast = Some(v);
2540 self
2541 }
2542 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
2544 self.params.message_effect_id = Some(v.into());
2545 self
2546 }
2547 pub fn suggested_post_parameters(mut self, v: SuggestedPostParameters) -> Self {
2549 self.params.suggested_post_parameters = Some(v);
2550 self
2551 }
2552}
2553
2554impl_into_future!(SendVenue, Message, "sendVenue");
2555
2556#[derive(Serialize)]
2559struct SendMediaGroupParams {
2560 chat_id: ChatId,
2561 media: Vec<InputMedia>,
2564 #[serde(skip_serializing_if = "Option::is_none")]
2565 message_thread_id: Option<i64>,
2566 #[serde(skip_serializing_if = "Option::is_none")]
2567 direct_messages_topic_id: Option<i64>,
2568 #[serde(skip_serializing_if = "Option::is_none")]
2569 business_connection_id: Option<String>,
2570 #[serde(skip_serializing_if = "Option::is_none")]
2571 disable_notification: Option<bool>,
2572 #[serde(skip_serializing_if = "Option::is_none")]
2573 protect_content: Option<bool>,
2574 #[serde(skip_serializing_if = "Option::is_none")]
2575 reply_parameters: Option<ReplyParameters>,
2576 #[serde(skip_serializing_if = "Option::is_none")]
2577 allow_paid_broadcast: Option<bool>,
2578 #[serde(skip_serializing_if = "Option::is_none")]
2579 message_effect_id: Option<String>,
2580}
2581
2582pub struct SendMediaGroup {
2587 client: BotClient,
2588 params: SendMediaGroupParams,
2589}
2590
2591impl SendMediaGroup {
2592 pub(crate) fn new(
2593 client: BotClient,
2594 chat_id: impl Into<ChatId>,
2595 media: Vec<InputMedia>,
2596 ) -> Self {
2597 Self {
2598 client,
2599 params: SendMediaGroupParams {
2600 chat_id: chat_id.into(),
2601 media,
2602 message_thread_id: None,
2603 direct_messages_topic_id: None,
2604 business_connection_id: None,
2605 disable_notification: None,
2606 protect_content: None,
2607 reply_parameters: None,
2608 allow_paid_broadcast: None,
2609 message_effect_id: None,
2610 },
2611 }
2612 }
2613 pub fn message_thread_id(mut self, id: i64) -> Self {
2615 self.params.message_thread_id = Some(id);
2616 self
2617 }
2618 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
2620 self.params.direct_messages_topic_id = Some(id);
2621 self
2622 }
2623 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
2625 self.params.business_connection_id = Some(id.into());
2626 self
2627 }
2628 pub fn disable_notification(mut self, v: bool) -> Self {
2630 self.params.disable_notification = Some(v);
2631 self
2632 }
2633 pub fn protect_content(mut self, v: bool) -> Self {
2635 self.params.protect_content = Some(v);
2636 self
2637 }
2638 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
2640 self.params.reply_parameters = Some(rp);
2641 self
2642 }
2643 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
2645 self.params.allow_paid_broadcast = Some(v);
2646 self
2647 }
2648 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
2650 self.params.message_effect_id = Some(v.into());
2651 self
2652 }
2653}
2654
2655impl_into_future!(SendMediaGroup, Vec<Message>, "sendMediaGroup");
2656
2657#[derive(Serialize)]
2660struct SendPaidMediaParams {
2661 chat_id: ChatId,
2662 star_count: u32,
2663 media: Vec<InputPaidMedia>,
2666 #[serde(skip_serializing_if = "Option::is_none")]
2667 business_connection_id: Option<String>,
2668 #[serde(skip_serializing_if = "Option::is_none")]
2669 payload: Option<String>,
2670 #[serde(skip_serializing_if = "Option::is_none")]
2671 caption: Option<String>,
2672 #[serde(skip_serializing_if = "Option::is_none")]
2673 parse_mode: Option<ParseMode>,
2674 #[serde(skip_serializing_if = "Option::is_none")]
2675 show_caption_above_media: Option<bool>,
2676 #[serde(skip_serializing_if = "Option::is_none")]
2677 disable_notification: Option<bool>,
2678 #[serde(skip_serializing_if = "Option::is_none")]
2679 protect_content: Option<bool>,
2680 #[serde(skip_serializing_if = "Option::is_none")]
2681 reply_parameters: Option<ReplyParameters>,
2682 #[serde(skip_serializing_if = "Option::is_none")]
2683 reply_markup: Option<ReplyMarkup>,
2684 #[serde(skip_serializing_if = "Option::is_none")]
2685 allow_paid_broadcast: Option<bool>,
2686 #[serde(skip_serializing_if = "Option::is_none")]
2687 caption_entities: Option<Vec<rustigram_types::message::MessageEntity>>,
2688 #[serde(skip_serializing_if = "Option::is_none")]
2689 direct_messages_topic_id: Option<i64>,
2690 #[serde(skip_serializing_if = "Option::is_none")]
2691 message_thread_id: Option<i64>,
2692 #[serde(skip_serializing_if = "Option::is_none")]
2693 suggested_post_parameters: Option<SuggestedPostParameters>,
2694}
2695
2696pub struct SendPaidMedia {
2701 client: BotClient,
2702 params: SendPaidMediaParams,
2703}
2704
2705impl SendPaidMedia {
2706 pub(crate) fn new(
2707 client: BotClient,
2708 chat_id: impl Into<ChatId>,
2709 star_count: u32,
2710 media: Vec<InputPaidMedia>,
2711 ) -> Self {
2712 Self {
2713 client,
2714 params: SendPaidMediaParams {
2715 chat_id: chat_id.into(),
2716 star_count,
2717 media,
2718 business_connection_id: None,
2719 payload: None,
2720 caption: None,
2721 parse_mode: None,
2722 show_caption_above_media: None,
2723 disable_notification: None,
2724 protect_content: None,
2725 reply_parameters: None,
2726 reply_markup: None,
2727 allow_paid_broadcast: None,
2728 caption_entities: None,
2729 direct_messages_topic_id: None,
2730 message_thread_id: None,
2731 suggested_post_parameters: None,
2732 },
2733 }
2734 }
2735 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
2737 self.params.business_connection_id = Some(id.into());
2738 self
2739 }
2740 pub fn payload(mut self, p: impl Into<String>) -> Self {
2742 self.params.payload = Some(p.into());
2743 self
2744 }
2745 pub fn caption(mut self, c: impl Into<String>) -> Self {
2747 self.params.caption = Some(c.into());
2748 self
2749 }
2750 pub fn parse_mode(mut self, m: ParseMode) -> Self {
2752 self.params.parse_mode = Some(m);
2753 self
2754 }
2755 pub fn show_caption_above_media(mut self, v: bool) -> Self {
2757 self.params.show_caption_above_media = Some(v);
2758 self
2759 }
2760 pub fn disable_notification(mut self, v: bool) -> Self {
2762 self.params.disable_notification = Some(v);
2763 self
2764 }
2765 pub fn protect_content(mut self, v: bool) -> Self {
2767 self.params.protect_content = Some(v);
2768 self
2769 }
2770 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
2772 self.params.reply_parameters = Some(rp);
2773 self
2774 }
2775 pub fn reply_markup(mut self, m: impl Into<ReplyMarkup>) -> Self {
2777 self.params.reply_markup = Some(m.into());
2778 self
2779 }
2780 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
2782 self.params.allow_paid_broadcast = Some(v);
2783 self
2784 }
2785 pub fn caption_entities(mut self, v: Vec<rustigram_types::message::MessageEntity>) -> Self {
2787 self.params.caption_entities = Some(v);
2788 self
2789 }
2790 pub fn direct_messages_topic_id(mut self, v: i64) -> Self {
2792 self.params.direct_messages_topic_id = Some(v);
2793 self
2794 }
2795 pub fn message_thread_id(mut self, v: i64) -> Self {
2797 self.params.message_thread_id = Some(v);
2798 self
2799 }
2800 pub fn suggested_post_parameters(mut self, v: SuggestedPostParameters) -> Self {
2802 self.params.suggested_post_parameters = Some(v);
2803 self
2804 }
2805}
2806
2807impl_into_future!(SendPaidMedia, Message, "sendPaidMedia");
2808
2809#[derive(Serialize)]
2812struct SendGameParams {
2813 chat_id: i64,
2814 game_short_name: String,
2815 #[serde(skip_serializing_if = "Option::is_none")]
2816 business_connection_id: Option<String>,
2817 #[serde(skip_serializing_if = "Option::is_none")]
2818 message_thread_id: Option<i64>,
2819 #[serde(skip_serializing_if = "Option::is_none")]
2820 direct_messages_topic_id: Option<i64>,
2821 #[serde(skip_serializing_if = "Option::is_none")]
2822 disable_notification: Option<bool>,
2823 #[serde(skip_serializing_if = "Option::is_none")]
2824 protect_content: Option<bool>,
2825 #[serde(skip_serializing_if = "Option::is_none")]
2826 reply_parameters: Option<ReplyParameters>,
2827 #[serde(skip_serializing_if = "Option::is_none")]
2828 reply_markup: Option<rustigram_types::keyboard::InlineKeyboardMarkup>,
2829 #[serde(skip_serializing_if = "Option::is_none")]
2830 allow_paid_broadcast: Option<bool>,
2831 #[serde(skip_serializing_if = "Option::is_none")]
2832 message_effect_id: Option<String>,
2833}
2834
2835pub struct SendGame {
2840 client: BotClient,
2841 params: SendGameParams,
2842}
2843
2844impl SendGame {
2845 pub(crate) fn new(client: BotClient, chat_id: i64, game_short_name: impl Into<String>) -> Self {
2846 Self {
2847 client,
2848 params: SendGameParams {
2849 chat_id,
2850 game_short_name: game_short_name.into(),
2851 business_connection_id: None,
2852 message_thread_id: None,
2853 direct_messages_topic_id: None,
2854 disable_notification: None,
2855 protect_content: None,
2856 reply_parameters: None,
2857 reply_markup: None,
2858 allow_paid_broadcast: None,
2859 message_effect_id: None,
2860 },
2861 }
2862 }
2863 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
2865 self.params.business_connection_id = Some(id.into());
2866 self
2867 }
2868 pub fn message_thread_id(mut self, id: i64) -> Self {
2870 self.params.message_thread_id = Some(id);
2871 self
2872 }
2873 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
2875 self.params.direct_messages_topic_id = Some(id);
2876 self
2877 }
2878 pub fn disable_notification(mut self, v: bool) -> Self {
2880 self.params.disable_notification = Some(v);
2881 self
2882 }
2883 pub fn protect_content(mut self, v: bool) -> Self {
2885 self.params.protect_content = Some(v);
2886 self
2887 }
2888 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
2890 self.params.reply_parameters = Some(rp);
2891 self
2892 }
2893 pub fn reply_markup(mut self, m: rustigram_types::keyboard::InlineKeyboardMarkup) -> Self {
2895 self.params.reply_markup = Some(m);
2896 self
2897 }
2898 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
2900 self.params.allow_paid_broadcast = Some(v);
2901 self
2902 }
2903 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
2905 self.params.message_effect_id = Some(v.into());
2906 self
2907 }
2908}
2909
2910impl_into_future!(SendGame, Message, "sendGame");
2911
2912#[derive(Serialize)]
2915struct SendChecklistParams {
2916 business_connection_id: String,
2917 chat_id: i64,
2918 checklist: rustigram_types::checklist::InputChecklist,
2919 #[serde(skip_serializing_if = "Option::is_none")]
2920 direct_messages_topic_id: Option<i64>,
2921 #[serde(skip_serializing_if = "Option::is_none")]
2922 disable_notification: Option<bool>,
2923 #[serde(skip_serializing_if = "Option::is_none")]
2924 protect_content: Option<bool>,
2925 #[serde(skip_serializing_if = "Option::is_none")]
2926 message_effect_id: Option<String>,
2927 #[serde(skip_serializing_if = "Option::is_none")]
2928 reply_parameters: Option<ReplyParameters>,
2929 #[serde(skip_serializing_if = "Option::is_none")]
2930 reply_markup: Option<rustigram_types::keyboard::InlineKeyboardMarkup>,
2931 #[serde(skip_serializing_if = "Option::is_none")]
2932 suggested_post_parameters: Option<SuggestedPostParameters>,
2933}
2934
2935pub struct SendChecklist {
2940 client: BotClient,
2941 params: SendChecklistParams,
2942}
2943
2944impl SendChecklist {
2945 pub(crate) fn new(
2946 client: BotClient,
2947 business_connection_id: impl Into<String>,
2948 chat_id: i64,
2949 checklist: rustigram_types::checklist::InputChecklist,
2950 ) -> Self {
2951 Self {
2952 client,
2953 params: SendChecklistParams {
2954 business_connection_id: business_connection_id.into(),
2955 chat_id,
2956 checklist,
2957 direct_messages_topic_id: None,
2958 disable_notification: None,
2959 protect_content: None,
2960 message_effect_id: None,
2961 reply_parameters: None,
2962 reply_markup: None,
2963 suggested_post_parameters: None,
2964 },
2965 }
2966 }
2967 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
2969 self.params.direct_messages_topic_id = Some(id);
2970 self
2971 }
2972 pub fn disable_notification(mut self, v: bool) -> Self {
2974 self.params.disable_notification = Some(v);
2975 self
2976 }
2977 pub fn protect_content(mut self, v: bool) -> Self {
2979 self.params.protect_content = Some(v);
2980 self
2981 }
2982 pub fn message_effect_id(mut self, id: impl Into<String>) -> Self {
2984 self.params.message_effect_id = Some(id.into());
2985 self
2986 }
2987 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
2989 self.params.reply_parameters = Some(rp);
2990 self
2991 }
2992 pub fn reply_markup(mut self, m: rustigram_types::keyboard::InlineKeyboardMarkup) -> Self {
2994 self.params.reply_markup = Some(m);
2995 self
2996 }
2997 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self {
2999 self.params.suggested_post_parameters = Some(params);
3000 self
3001 }
3002}
3003
3004impl_into_future!(SendChecklist, Message, "sendChecklist");
3005
3006#[derive(Serialize)]
3009struct SendRichMessageParams {
3010 chat_id: ChatId,
3011 rich_message: rustigram_types::rich_message::InputRichMessage,
3012 #[serde(skip_serializing_if = "Option::is_none")]
3013 business_connection_id: Option<String>,
3014 #[serde(skip_serializing_if = "Option::is_none")]
3015 message_thread_id: Option<i64>,
3016 #[serde(skip_serializing_if = "Option::is_none")]
3017 direct_messages_topic_id: Option<i64>,
3018 #[serde(skip_serializing_if = "Option::is_none")]
3019 disable_notification: Option<bool>,
3020 #[serde(skip_serializing_if = "Option::is_none")]
3021 protect_content: Option<bool>,
3022 #[serde(skip_serializing_if = "Option::is_none")]
3023 allow_paid_broadcast: Option<bool>,
3024 #[serde(skip_serializing_if = "Option::is_none")]
3025 message_effect_id: Option<String>,
3026 #[serde(skip_serializing_if = "Option::is_none")]
3027 suggested_post_parameters: Option<SuggestedPostParameters>,
3028 #[serde(skip_serializing_if = "Option::is_none")]
3029 reply_parameters: Option<ReplyParameters>,
3030 #[serde(skip_serializing_if = "Option::is_none")]
3031 reply_markup: Option<rustigram_types::keyboard::ReplyMarkup>,
3032}
3033
3034pub struct SendRichMessage {
3036 client: BotClient,
3037 params: SendRichMessageParams,
3038}
3039
3040impl SendRichMessage {
3041 pub(crate) fn new(
3042 client: BotClient,
3043 chat_id: impl Into<ChatId>,
3044 rich_message: rustigram_types::rich_message::InputRichMessage,
3045 ) -> Self {
3046 Self {
3047 client,
3048 params: SendRichMessageParams {
3049 chat_id: chat_id.into(),
3050 rich_message,
3051 business_connection_id: None,
3052 message_thread_id: None,
3053 direct_messages_topic_id: None,
3054 disable_notification: None,
3055 protect_content: None,
3056 allow_paid_broadcast: None,
3057 message_effect_id: None,
3058 suggested_post_parameters: None,
3059 reply_parameters: None,
3060 reply_markup: None,
3061 },
3062 }
3063 }
3064
3065 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
3067 self.params.business_connection_id = Some(id.into());
3068 self
3069 }
3070 pub fn message_thread_id(mut self, id: i64) -> Self {
3072 self.params.message_thread_id = Some(id);
3073 self
3074 }
3075 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
3077 self.params.direct_messages_topic_id = Some(id);
3078 self
3079 }
3080 pub fn disable_notification(mut self, v: bool) -> Self {
3082 self.params.disable_notification = Some(v);
3083 self
3084 }
3085 pub fn protect_content(mut self, v: bool) -> Self {
3087 self.params.protect_content = Some(v);
3088 self
3089 }
3090 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
3092 self.params.allow_paid_broadcast = Some(v);
3093 self
3094 }
3095 pub fn message_effect_id(mut self, id: impl Into<String>) -> Self {
3097 self.params.message_effect_id = Some(id.into());
3098 self
3099 }
3100 pub fn suggested_post_parameters(mut self, p: SuggestedPostParameters) -> Self {
3102 self.params.suggested_post_parameters = Some(p);
3103 self
3104 }
3105 pub fn reply_parameters(mut self, rp: ReplyParameters) -> Self {
3107 self.params.reply_parameters = Some(rp);
3108 self
3109 }
3110 pub fn reply_markup(mut self, m: rustigram_types::keyboard::ReplyMarkup) -> Self {
3112 self.params.reply_markup = Some(m);
3113 self
3114 }
3115}
3116
3117impl_into_future!(SendRichMessage, Message, "sendRichMessage");
3118
3119#[derive(Serialize)]
3122struct SendRichMessageDraftParams {
3123 chat_id: i64,
3124 draft_id: i64,
3125 rich_message: rustigram_types::rich_message::InputRichMessage,
3126 #[serde(skip_serializing_if = "Option::is_none")]
3127 message_thread_id: Option<i64>,
3128}
3129
3130pub struct SendRichMessageDraft {
3135 client: BotClient,
3136 params: SendRichMessageDraftParams,
3137}
3138
3139impl SendRichMessageDraft {
3140 pub(crate) fn new(
3141 client: BotClient,
3142 chat_id: i64,
3143 draft_id: i64,
3144 rich_message: rustigram_types::rich_message::InputRichMessage,
3145 ) -> Self {
3146 Self {
3147 client,
3148 params: SendRichMessageDraftParams {
3149 chat_id,
3150 draft_id,
3151 rich_message,
3152 message_thread_id: None,
3153 },
3154 }
3155 }
3156
3157 pub fn message_thread_id(mut self, id: i64) -> Self {
3159 self.params.message_thread_id = Some(id);
3160 self
3161 }
3162}
3163
3164impl_into_future!(SendRichMessageDraft, bool, "sendRichMessageDraft");
3165
3166#[cfg(test)]
3167mod tests {
3168 use super::*;
3169 use crate::client::BotClient;
3170
3171 fn client() -> BotClient {
3172 BotClient::from_token("123456:test-token-for-unit-tests").unwrap()
3173 }
3174
3175 #[test]
3178 fn api_wide_parameters_serialize_on_the_json_path() {
3179 let contact = SendContact::new(client(), 1_i64, "+100", "A")
3180 .business_connection_id("biz")
3181 .allow_paid_broadcast(true)
3182 .message_effect_id("effect")
3183 .suggested_post_parameters(SuggestedPostParameters {
3184 price: None,
3185 send_date: Some(1_700_000_000),
3186 });
3187 let json = serde_json::to_value(&contact.params).unwrap();
3188
3189 assert_eq!(json["business_connection_id"], "biz");
3190 assert_eq!(json["allow_paid_broadcast"], true);
3191 assert_eq!(json["message_effect_id"], "effect");
3192 assert!(json.get("suggested_post_parameters").is_some());
3193 }
3194
3195 #[test]
3197 fn unset_parameters_are_omitted() {
3198 let dice = SendDice::new(client(), 1_i64);
3199 let json = serde_json::to_value(&dice.params).unwrap();
3200 for key in [
3201 "business_connection_id",
3202 "allow_paid_broadcast",
3203 "message_effect_id",
3204 "suggested_post_parameters",
3205 ] {
3206 assert!(
3207 json.get(key).is_none(),
3208 "{key} should be omitted when unset"
3209 );
3210 }
3211 }
3212
3213 #[test]
3216 fn message_draft_text_can_be_cleared() {
3217 let draft = SendMessageDraft::new(client(), 1_i64, 7, "hello");
3218 assert_eq!(
3219 serde_json::to_value(&draft.params).unwrap()["text"],
3220 "hello"
3221 );
3222
3223 let empty = SendMessageDraft::new(client(), 1_i64, 7, "hello").clear_text();
3224 assert!(serde_json::to_value(&empty.params)
3225 .unwrap()
3226 .get("text")
3227 .is_none());
3228 }
3229
3230 #[test]
3234 fn multipart_and_json_paths_cover_the_same_options() {
3235 let source = include_str!("sending.rs");
3236 let struct_body = source
3237 .split("pub struct MediaSendOptions {")
3238 .nth(1)
3239 .and_then(|s| s.split("\n}").next())
3240 .expect("MediaSendOptions struct");
3241 let fields: Vec<&str> = struct_body
3242 .lines()
3243 .filter_map(|l| l.trim().strip_prefix("pub "))
3244 .filter_map(|l| l.split(':').next())
3245 .collect();
3246 assert_eq!(
3247 fields.len(),
3248 17,
3249 "field count changed; update both send paths"
3250 );
3251
3252 for (helper, path) in [
3258 ("fn apply_media_opts(", "multipart form"),
3259 ("fn media_json_body(", "JSON body"),
3260 ] {
3261 let body = source
3262 .split(helper)
3263 .nth(1)
3264 .and_then(|s| s.split("\nfn ").next())
3265 .unwrap_or_else(|| panic!("{helper} body"));
3266 for field in &fields {
3267 assert!(
3268 body.contains(&format!("opts.{field}")),
3269 "`{field}` is settable but never written to the {path}"
3270 );
3271 }
3272 }
3273 }
3274}