Skip to main content

ronami_core/adaptors/
parse_mode.rs

1use std::future::IntoFuture;
2
3use url::Url;
4
5use crate::{
6    payloads::{
7        AnswerInlineQuery, AnswerWebAppQuery, CopyMessage, EditEphemeralMessageCaption,
8        EditEphemeralMessageMedia, EditEphemeralMessageText, EditMessageCaption,
9        EditMessageCaptionInline, EditMessageChecklist, EditMessageMedia, EditMessageMediaInline,
10        EditMessageText, EditMessageTextInline, EditStory, GiftPremiumSubscription, PostStory,
11        SavePreparedInlineMessage, SendAnimation, SendAudio, SendChecklist, SendDocument, SendGift,
12        SendGiftChat, SendLivePhoto, SendMediaGroup, SendMessage, SendMessageDraft, SendPaidMedia,
13        SendPhoto, SendPoll, SendVideo, SendVoice,
14    },
15    prelude::Requester,
16    requests::{HasPayload, Output, Request},
17    types::*,
18};
19
20/// Default parse mode adaptor, see
21/// [`RequesterExt::parse_mode`](crate::requests::RequesterExt::parse_mode).
22#[derive(Clone, Debug)]
23pub struct DefaultParseMode<B> {
24    bot: B,
25    mode: ParseMode,
26}
27
28/// Request returned by [`DefaultParseMode`] methods.
29#[derive(Clone)]
30pub struct DefaultParseModeRequest<R> {
31    req: R,
32    mode: ParseMode,
33}
34
35impl<B> DefaultParseMode<B> {
36    /// Creates new [`DefaultParseMode`].
37    ///
38    /// Note: it's recommended to use [`RequesterExt::parse_mode`] instead.
39    ///
40    /// [`RequesterExt::parse_mode`]: crate::requests::RequesterExt::parse_mode
41    pub fn new(bot: B, parse_mode: ParseMode) -> Self {
42        Self { bot, mode: parse_mode }
43    }
44
45    /// Allows to access the inner bot.
46    pub fn inner(&self) -> &B {
47        &self.bot
48    }
49
50    /// Unwraps the inner bot.
51    pub fn into_inner(self) -> B {
52        self.bot
53    }
54
55    /// Returns currently used [`ParseMode`].
56    pub fn parse_mode(&self) -> ParseMode {
57        self.mode
58    }
59}
60
61impl<R> Request for DefaultParseModeRequest<R>
62where
63    R: Request + Clone,
64    R::Payload: VisitParseModes,
65{
66    type Err = R::Err;
67    type Send = R::Send;
68    type SendRef = R::Send;
69
70    // Required methods
71    fn send(mut self) -> Self::Send {
72        self.req.payload_mut().visit_parse_modes(|mode| _ = mode.get_or_insert(self.mode));
73        self.req.send()
74    }
75
76    fn send_ref(&self) -> Self::SendRef {
77        // There is no other way to change the payload, given a `&self` :(
78        self.clone().send()
79    }
80}
81
82impl<R> IntoFuture for DefaultParseModeRequest<R>
83where
84    Self: Request,
85{
86    type Output = Result<Output<Self>, <Self as Request>::Err>;
87    type IntoFuture = <Self as Request>::Send;
88
89    fn into_future(self) -> Self::IntoFuture {
90        self.send()
91    }
92}
93
94impl<R> HasPayload for DefaultParseModeRequest<R>
95where
96    R: Request,
97{
98    type Payload = R::Payload;
99
100    fn payload_mut(&mut self) -> &mut Self::Payload {
101        self.req.payload_mut()
102    }
103
104    fn payload_ref(&self) -> &Self::Payload {
105        self.req.payload_ref()
106    }
107}
108
109macro_rules! f {
110    ($m:ident $this:ident ($($arg:ident : $T:ty),*)) => {
111        {
112            let req = $this.inner().$m($($arg),*);
113            DefaultParseModeRequest { req, mode: $this.mode }
114        }
115    };
116}
117
118macro_rules! fty {
119    ($T:ident) => {
120        DefaultParseModeRequest<B::$T>
121    };
122}
123
124macro_rules! ftyid {
125    ($T:ident) => {
126        B::$T
127    };
128}
129
130macro_rules! fid {
131    ($m:ident $this:ident ($($arg:ident : $T:ty),*)) => {
132        $this.inner().$m($($arg),*)
133    };
134}
135
136impl<B> Requester for DefaultParseMode<B>
137where
138    B: Requester,
139    B::SendMessage: Clone,
140    B::SendMessageDraft: Clone,
141    B::SendPhoto: Clone,
142    B::SendVideo: Clone,
143    B::SendAudio: Clone,
144    B::SendDocument: Clone,
145    B::SendAnimation: Clone,
146    B::SendVoice: Clone,
147    B::SendLivePhoto: Clone,
148    B::EditMessageText: Clone,
149    B::EditMessageTextInline: Clone,
150    B::EditMessageCaption: Clone,
151    B::EditMessageCaptionInline: Clone,
152    B::SendPoll: Clone,
153    B::SendChecklist: Clone,
154    B::CopyMessage: Clone,
155    B::PostStory: Clone,
156    B::EditStory: Clone,
157    B::AnswerInlineQuery: Clone,
158    B::AnswerWebAppQuery: Clone,
159    B::SavePreparedInlineMessage: Clone,
160    B::EditMessageMedia: Clone,
161    B::EditMessageMediaInline: Clone,
162    B::EditMessageChecklist: Clone,
163    B::SendPaidMedia: Clone,
164    B::SendMediaGroup: Clone,
165    B::GiftPremiumSubscription: Clone,
166    B::SendGift: Clone,
167    B::SendGiftChat: Clone,
168    B::EditEphemeralMessageText: Clone,
169    B::EditEphemeralMessageMedia: Clone,
170    B::EditEphemeralMessageCaption: Clone,
171{
172    type Err = B::Err;
173
174    requester_forward! {
175        send_message,
176        send_message_draft,
177        send_photo,
178        send_video,
179        send_audio,
180        send_document,
181        send_animation,
182        send_voice,
183        send_poll,
184        send_checklist,
185        edit_message_text,
186        edit_message_text_inline,
187        edit_message_caption,
188        edit_message_caption_inline,
189        edit_message_checklist,
190        copy_message,
191        post_story,
192        edit_story,
193        answer_inline_query,
194        answer_web_app_query,
195        save_prepared_inline_message,
196        send_paid_media,
197        send_media_group,
198        edit_message_media,
199        edit_message_media_inline,
200        gift_premium_subscription,
201        send_gift,
202        send_gift_chat,
203        edit_ephemeral_message_text,
204        edit_ephemeral_message_media,
205        edit_ephemeral_message_caption,
206        => f, fty
207    }
208
209    requester_forward! {
210        get_me,
211        log_out,
212        close,
213        get_updates,
214        set_webhook,
215        delete_webhook,
216        get_webhook_info,
217        forward_message,
218        forward_messages,
219        copy_messages,
220        send_rich_message,
221        send_rich_message_draft,
222        send_video_note,
223        send_location,
224        edit_message_live_location,
225        edit_message_live_location_inline,
226        stop_message_live_location,
227        stop_message_live_location_inline,
228        send_venue,
229        send_contact,
230        send_dice,
231        send_chat_action,
232        set_message_reaction,
233        get_user_profile_photos,
234        get_user_profile_audios,
235        set_user_emoji_status,
236        get_file,
237        kick_chat_member,
238        ban_chat_member,
239        unban_chat_member,
240        restrict_chat_member,
241        promote_chat_member,
242        set_chat_administrator_custom_title,
243        set_chat_member_tag,
244        ban_chat_sender_chat,
245        unban_chat_sender_chat,
246        set_chat_permissions,
247        export_chat_invite_link,
248        create_chat_invite_link,
249        edit_chat_invite_link,
250        create_chat_subscription_invite_link,
251        edit_chat_subscription_invite_link,
252        revoke_chat_invite_link,
253        set_chat_photo,
254        delete_chat_photo,
255        set_chat_title,
256        set_chat_description,
257        pin_chat_message,
258        unpin_chat_message,
259        unpin_all_chat_messages,
260        leave_chat,
261        get_chat,
262        get_chat_administrators,
263        get_chat_members_count,
264        get_chat_member_count,
265        get_chat_member,
266        set_chat_sticker_set,
267        delete_chat_sticker_set,
268        get_forum_topic_icon_stickers,
269        create_forum_topic,
270        edit_forum_topic,
271        close_forum_topic,
272        reopen_forum_topic,
273        delete_forum_topic,
274        unpin_all_forum_topic_messages,
275        edit_general_forum_topic,
276        close_general_forum_topic,
277        reopen_general_forum_topic,
278        hide_general_forum_topic,
279        unhide_general_forum_topic,
280        unpin_all_general_forum_topic_messages,
281        answer_callback_query,
282        get_user_chat_boosts,
283        set_my_commands,
284        get_business_connection,
285        get_my_commands,
286        set_my_name,
287        get_my_name,
288        set_my_description,
289        get_my_description,
290        set_my_short_description,
291        get_my_short_description,
292        set_my_profile_photo,
293        remove_my_profile_photo,
294        get_managed_bot_token,
295        replace_managed_bot_token,
296        save_prepared_keyboard_button,
297        send_live_photo,
298        get_user_personal_chat_messages,
299        answer_guest_query,
300        get_managed_bot_access_settings,
301        set_managed_bot_access_settings,
302        delete_message_reaction,
303        delete_all_message_reactions,
304        set_chat_menu_button,
305        get_chat_menu_button,
306        set_my_default_administrator_rights,
307        get_my_default_administrator_rights,
308        delete_my_commands,
309        edit_message_reply_markup,
310        edit_message_reply_markup_inline,
311        stop_poll,
312        approve_suggested_post,
313        decline_suggested_post,
314        delete_message,
315        delete_messages,
316        send_sticker,
317        get_sticker_set,
318        get_custom_emoji_stickers,
319        upload_sticker_file,
320        create_new_sticker_set,
321        add_sticker_to_set,
322        set_sticker_position_in_set,
323        delete_sticker_from_set,
324        replace_sticker_in_set,
325        set_sticker_set_thumbnail,
326        set_custom_emoji_sticker_set_thumbnail,
327        set_sticker_set_title,
328        delete_sticker_set,
329        set_sticker_emoji_list,
330        set_sticker_keywords,
331        set_sticker_mask_position,
332        get_available_gifts,
333        verify_user,
334        verify_chat,
335        remove_user_verification,
336        remove_chat_verification,
337        read_business_message,
338        delete_business_messages,
339        set_business_account_name,
340        set_business_account_username,
341        set_business_account_bio,
342        set_business_account_profile_photo,
343        remove_business_account_profile_photo,
344        set_business_account_gift_settings,
345        get_business_account_star_balance,
346        transfer_business_account_stars,
347        get_business_account_gifts,
348        get_user_gifts,
349        get_chat_gifts,
350        repost_story,
351        convert_gift_to_stars,
352        upgrade_gift,
353        transfer_gift,
354        delete_story,
355        send_invoice,
356        create_invoice_link,
357        answer_shipping_query,
358        answer_pre_checkout_query,
359        get_my_star_balance,
360        get_star_transactions,
361        refund_star_payment,
362        edit_user_star_subscription,
363        set_passport_data_errors,
364        send_game,
365        set_game_score,
366        set_game_score_inline,
367        get_game_high_scores,
368        approve_chat_join_request,
369        decline_chat_join_request,
370        answer_chat_join_request_query,
371        send_chat_join_request_web_app,
372        edit_ephemeral_message_reply_markup,
373        delete_ephemeral_message
374        => fid, ftyid
375    }
376}
377
378download_forward! {
379    B
380    DefaultParseMode<B>
381    { this => this.inner() }
382}
383
384trait VisitParseModes {
385    fn visit_parse_modes(&mut self, visitor: impl FnMut(&mut Option<ParseMode>));
386}
387
388macro_rules! impl_visit_parse_modes {
389    (
390        $(
391            $T:ty => [
392                $(
393                    $field:ident
394                ),*
395            ]
396            ,
397        )*
398    ) => {
399        $(
400            impl VisitParseModes for $T {
401                fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
402                    $(
403                        visitor(&mut self.$field);
404                    )*
405                }
406            }
407        )*
408    }
409}
410
411impl_visit_parse_modes! {
412    SendMessage => [parse_mode],
413    SendMessageDraft => [parse_mode],
414    SendPhoto => [parse_mode],
415    SendVideo => [parse_mode],
416    SendAudio => [parse_mode],
417    SendDocument => [parse_mode],
418    SendAnimation => [parse_mode],
419    SendVoice => [parse_mode],
420    SendLivePhoto => [parse_mode],
421    EditMessageText => [parse_mode],
422    EditMessageTextInline => [parse_mode],
423    EditMessageCaption => [parse_mode],
424    EditMessageCaptionInline => [parse_mode],
425    SendPaidMedia => [parse_mode],
426    GiftPremiumSubscription => [text_parse_mode],
427    SendGift => [text_parse_mode],
428    SendGiftChat => [text_parse_mode],
429    // FIXME: check if `parse_mode` changes anything if `.caption` is not set
430    //        (and if it does, maybe not call visitor if `self.caption.is_none()`)
431    CopyMessage => [parse_mode],
432    PostStory => [parse_mode],
433    EditStory => [parse_mode],
434    EditEphemeralMessageText => [parse_mode],
435    EditEphemeralMessageCaption => [parse_mode],
436    SendPoll => [explanation_parse_mode, description_parse_mode],
437}
438
439impl VisitParseModes for AnswerInlineQuery {
440    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
441        self.results
442            .iter_mut()
443            .for_each(|result| visit_parse_modes_in_inline_query_result(result, &mut visitor))
444    }
445}
446
447impl VisitParseModes for AnswerWebAppQuery {
448    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
449        visit_parse_modes_in_inline_query_result(&mut self.result, &mut visitor);
450    }
451}
452
453impl VisitParseModes for SavePreparedInlineMessage {
454    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
455        visit_parse_modes_in_inline_query_result(&mut self.result, &mut visitor);
456    }
457}
458
459impl VisitParseModes for SendMediaGroup {
460    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
461        self.media
462            .iter_mut()
463            .for_each(|media| visit_parse_modes_in_input_media(media, &mut visitor))
464    }
465}
466
467impl VisitParseModes for EditMessageMedia {
468    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
469        visit_parse_modes_in_input_media(&mut self.media, &mut visitor);
470    }
471}
472
473impl VisitParseModes for EditMessageMediaInline {
474    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
475        visit_parse_modes_in_input_media(&mut self.media, &mut visitor);
476    }
477}
478
479impl VisitParseModes for EditEphemeralMessageMedia {
480    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
481        visit_parse_modes_in_input_media(&mut self.media, &mut visitor);
482    }
483}
484
485impl VisitParseModes for EditMessageChecklist {
486    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
487        visitor(&mut self.checklist.parse_mode);
488    }
489}
490
491impl VisitParseModes for SendChecklist {
492    fn visit_parse_modes(&mut self, mut visitor: impl FnMut(&mut Option<ParseMode>)) {
493        visitor(&mut self.checklist.parse_mode);
494    }
495}
496
497fn visit_parse_modes_in_inline_query_result(
498    result: &mut InlineQueryResult,
499    visitor: &mut impl FnMut(&mut Option<ParseMode>),
500) {
501    use InlineQueryResult::*;
502
503    let parse_mode = match result {
504        // Simply contain `parse_mode`
505        CachedAudio(r) => &mut r.parse_mode,
506        CachedDocument(r) => &mut r.parse_mode,
507        CachedGif(r) => &mut r.parse_mode,
508        CachedMpeg4Gif(r) => &mut r.parse_mode,
509        CachedPhoto(r) => &mut r.parse_mode,
510        CachedVideo(r) => &mut r.parse_mode,
511        CachedVoice(r) => &mut r.parse_mode,
512        Audio(r) => &mut r.parse_mode,
513        Document(r) => &mut r.parse_mode,
514        Gif(r) => &mut r.parse_mode,
515        Mpeg4Gif(r) => &mut r.parse_mode,
516        Photo(r) => &mut r.parse_mode,
517        Video(r) => &mut r.parse_mode,
518        Voice(r) => &mut r.parse_mode,
519
520        // Can contain parse mode if `InputMessageContent::Text`
521        CachedSticker(r) => match &mut r.input_message_content {
522            Some(InputMessageContent::Text(t)) => &mut t.parse_mode,
523            _ => return,
524        },
525        Article(r) => match &mut r.input_message_content {
526            InputMessageContent::Text(t) => &mut t.parse_mode,
527            _ => return,
528        },
529        Contact(r) => match &mut r.input_message_content {
530            Some(InputMessageContent::Text(t)) => &mut t.parse_mode,
531            _ => return,
532        },
533        Location(r) => match &mut r.input_message_content {
534            Some(InputMessageContent::Text(t)) => &mut t.parse_mode,
535            _ => return,
536        },
537        Venue(r) => match &mut r.input_message_content {
538            Some(InputMessageContent::Text(t)) => &mut t.parse_mode,
539            _ => return,
540        },
541
542        // Can't contain `parse_mode` at all
543        Game(_r) => return,
544    };
545
546    visitor(parse_mode);
547}
548
549fn visit_parse_modes_in_input_media(
550    media: &mut InputMedia,
551    visitor: &mut impl FnMut(&mut Option<ParseMode>),
552) {
553    use InputMedia::*;
554
555    let parse_mode = match media {
556        Photo(m) => &mut m.parse_mode,
557        Video(m) => &mut m.parse_mode,
558        Animation(m) => &mut m.parse_mode,
559        Audio(m) => &mut m.parse_mode,
560        Document(m) => &mut m.parse_mode,
561        VoiceNote(m) => &mut m.parse_mode,
562    };
563
564    visitor(parse_mode);
565}