Skip to main content

ronami_core/adaptors/
cache_me.rs

1use std::{future::IntoFuture, pin::Pin, sync::Arc};
2
3use futures::{
4    future,
5    future::{ok, Ready},
6    task::{Context, Poll},
7    Future,
8};
9use once_cell::sync::OnceCell;
10use url::Url;
11
12use crate::{
13    payloads::GetMe,
14    requests::{HasPayload, Request, Requester},
15    types::*,
16};
17
18/// `get_me` cache.
19///
20/// Bot's user is hardly ever changed, so sometimes it's reasonable to cache
21/// response from `get_me` method.
22#[derive(Clone, Debug)]
23pub struct CacheMe<B> {
24    bot: B,
25    me: Arc<OnceCell<Me>>,
26}
27
28impl<B> CacheMe<B> {
29    /// Creates new cache.
30    ///
31    /// Note: it's recommended to use [`RequesterExt::cache_me`] instead.
32    ///
33    /// [`RequesterExt::cache_me`]: crate::requests::RequesterExt::cache_me
34    pub fn new(bot: B) -> CacheMe<B> {
35        Self { bot, me: Arc::new(OnceCell::new()) }
36    }
37
38    /// Allows to access inner bot
39    pub fn inner(&self) -> &B {
40        &self.bot
41    }
42
43    /// Unwraps inner bot
44    pub fn into_inner(self) -> B {
45        self.bot
46    }
47
48    /// Clear cache.
49    ///
50    /// Returns cached response from `get_me`, if it was cached.
51    ///
52    /// Note: internally this uses [`Arc::make_mut`] so this will **not**
53    /// clear cache of clones of self.
54    pub fn clear(&mut self) -> Option<Me> {
55        Arc::make_mut(&mut self.me).take()
56    }
57}
58
59macro_rules! f {
60    ($m:ident $this:ident ($($arg:ident : $T:ty),*)) => {
61        $this.inner().$m($($arg),*)
62    };
63}
64
65macro_rules! fty {
66    ($T:ident) => {
67        B::$T
68    };
69}
70
71impl<B> Requester for CacheMe<B>
72where
73    B: Requester,
74{
75    type Err = B::Err;
76
77    type GetMe = CachedMeRequest<B::GetMe>;
78
79    fn get_me(&self) -> Self::GetMe {
80        match self.me.get() {
81            Some(me) => CachedMeRequest(Inner::Ready(me.clone()), GetMe::new()),
82            None => CachedMeRequest(
83                Inner::Pending(self.bot.get_me(), Arc::clone(&self.me)),
84                GetMe::new(),
85            ),
86        }
87    }
88
89    requester_forward! {
90        log_out,
91        close,
92        get_updates,
93        set_webhook,
94        delete_webhook,
95        get_webhook_info,
96        forward_message,
97        forward_messages,
98        copy_message,
99        copy_messages,
100        send_message,
101        send_message_draft,
102        send_rich_message,
103        send_rich_message_draft,
104        send_photo,
105        send_audio,
106        send_document,
107        send_video,
108        send_animation,
109        send_voice,
110        send_video_note,
111        send_paid_media,
112        send_media_group,
113        send_location,
114        edit_message_live_location,
115        edit_message_live_location_inline,
116        stop_message_live_location,
117        stop_message_live_location_inline,
118        edit_message_checklist,
119        send_venue,
120        send_contact,
121        send_poll,
122        send_checklist,
123        send_dice,
124        send_chat_action,
125        set_message_reaction,
126        get_user_profile_photos,
127        get_user_profile_audios,
128        set_user_emoji_status,
129        get_file,
130        kick_chat_member,
131        ban_chat_member,
132        unban_chat_member,
133        restrict_chat_member,
134        promote_chat_member,
135        set_chat_administrator_custom_title,
136        set_chat_member_tag,
137        ban_chat_sender_chat,
138        unban_chat_sender_chat,
139        set_chat_permissions,
140        export_chat_invite_link,
141        create_chat_invite_link,
142        edit_chat_invite_link,
143        create_chat_subscription_invite_link,
144        edit_chat_subscription_invite_link,
145        revoke_chat_invite_link,
146        set_chat_photo,
147        delete_chat_photo,
148        set_chat_title,
149        set_chat_description,
150        pin_chat_message,
151        unpin_chat_message,
152        unpin_all_chat_messages,
153        leave_chat,
154        get_chat,
155        get_chat_administrators,
156        get_chat_members_count,
157        get_chat_member_count,
158        get_chat_member,
159        set_chat_sticker_set,
160        delete_chat_sticker_set,
161        get_forum_topic_icon_stickers,
162        create_forum_topic,
163        edit_forum_topic,
164        close_forum_topic,
165        reopen_forum_topic,
166        delete_forum_topic,
167        unpin_all_forum_topic_messages,
168        edit_general_forum_topic,
169        close_general_forum_topic,
170        reopen_general_forum_topic,
171        hide_general_forum_topic,
172        unhide_general_forum_topic,
173        unpin_all_general_forum_topic_messages,
174        answer_callback_query,
175        get_user_chat_boosts,
176        set_my_commands,
177        get_business_connection,
178        get_my_commands,
179        set_my_name,
180        get_my_name,
181        set_my_description,
182        get_my_description,
183        set_my_short_description,
184        get_my_short_description,
185        set_my_profile_photo,
186        remove_my_profile_photo,
187        get_managed_bot_token,
188        replace_managed_bot_token,
189        save_prepared_keyboard_button,
190        send_live_photo,
191        get_user_personal_chat_messages,
192        answer_guest_query,
193        get_managed_bot_access_settings,
194        set_managed_bot_access_settings,
195        delete_message_reaction,
196        delete_all_message_reactions,
197        set_chat_menu_button,
198        get_chat_menu_button,
199        set_my_default_administrator_rights,
200        get_my_default_administrator_rights,
201        delete_my_commands,
202        answer_inline_query,
203        answer_web_app_query,
204        save_prepared_inline_message,
205        edit_message_text,
206        edit_message_text_inline,
207        edit_message_caption,
208        edit_message_caption_inline,
209        edit_message_media,
210        edit_message_media_inline,
211        edit_message_reply_markup,
212        edit_message_reply_markup_inline,
213        stop_poll,
214        approve_suggested_post,
215        decline_suggested_post,
216        delete_message,
217        delete_messages,
218        send_sticker,
219        get_sticker_set,
220        get_custom_emoji_stickers,
221        upload_sticker_file,
222        create_new_sticker_set,
223        add_sticker_to_set,
224        set_sticker_position_in_set,
225        delete_sticker_from_set,
226        replace_sticker_in_set,
227        set_sticker_set_thumbnail,
228        set_custom_emoji_sticker_set_thumbnail,
229        set_sticker_set_title,
230        delete_sticker_set,
231        set_sticker_emoji_list,
232        set_sticker_keywords,
233        set_sticker_mask_position,
234        get_available_gifts,
235        send_gift,
236        send_gift_chat,
237        gift_premium_subscription,
238        verify_user,
239        verify_chat,
240        remove_user_verification,
241        remove_chat_verification,
242        read_business_message,
243        delete_business_messages,
244        set_business_account_name,
245        set_business_account_username,
246        set_business_account_bio,
247        set_business_account_profile_photo,
248        remove_business_account_profile_photo,
249        set_business_account_gift_settings,
250        get_business_account_star_balance,
251        transfer_business_account_stars,
252        get_business_account_gifts,
253        get_user_gifts,
254        get_chat_gifts,
255        convert_gift_to_stars,
256        upgrade_gift,
257        transfer_gift,
258        post_story,
259        repost_story,
260        edit_story,
261        delete_story,
262        send_invoice,
263        create_invoice_link,
264        answer_shipping_query,
265        answer_pre_checkout_query,
266        get_my_star_balance,
267        get_star_transactions,
268        refund_star_payment,
269        edit_user_star_subscription,
270        set_passport_data_errors,
271        send_game,
272        set_game_score,
273        set_game_score_inline,
274        get_game_high_scores,
275        approve_chat_join_request,
276        decline_chat_join_request,
277        answer_chat_join_request_query,
278        send_chat_join_request_web_app,
279        edit_ephemeral_message_text,
280        edit_ephemeral_message_media,
281        edit_ephemeral_message_caption,
282        edit_ephemeral_message_reply_markup,
283        delete_ephemeral_message
284        => f, fty
285    }
286}
287
288download_forward! {
289    B
290    CacheMe<B>
291    { this => this.inner() }
292}
293
294#[must_use = "Requests are lazy and do nothing unless sent"]
295pub struct CachedMeRequest<R: Request<Payload = GetMe>>(Inner<R>, GetMe);
296
297enum Inner<R: Request<Payload = GetMe>> {
298    Ready(Me),
299    Pending(R, Arc<OnceCell<Me>>),
300}
301
302impl<R> Request for CachedMeRequest<R>
303where
304    R: Request<Payload = GetMe>,
305{
306    type Err = R::Err;
307    type Send = Send<R>;
308    type SendRef = SendRef<R>;
309
310    fn send(self) -> Self::Send {
311        let fut = match self.0 {
312            Inner::Ready(me) => future::Either::Left(ok(me)),
313            Inner::Pending(req, cell) => future::Either::Right(Init(req.send(), cell)),
314        };
315        Send(fut)
316    }
317
318    fn send_ref(&self) -> Self::SendRef {
319        let fut = match &self.0 {
320            Inner::Ready(me) => future::Either::Left(ok(me.clone())),
321            Inner::Pending(req, cell) => {
322                future::Either::Right(Init(req.send_ref(), Arc::clone(cell)))
323            }
324        };
325        SendRef(fut)
326    }
327}
328
329impl<R: Request<Payload = GetMe>> HasPayload for CachedMeRequest<R> {
330    type Payload = GetMe;
331
332    fn payload_mut(&mut self) -> &mut Self::Payload {
333        &mut self.1
334    }
335
336    fn payload_ref(&self) -> &Self::Payload {
337        &self.1
338    }
339}
340
341impl<R: Request<Payload = GetMe>> IntoFuture for CachedMeRequest<R> {
342    type Output = Result<Me, R::Err>;
343    type IntoFuture = Send<R>;
344
345    fn into_future(self) -> Self::IntoFuture {
346        self.send()
347    }
348}
349
350type ReadyMe<Err> = Ready<Result<Me, Err>>;
351
352#[pin_project::pin_project]
353pub struct Send<R: Request<Payload = GetMe>>(
354    #[pin] future::Either<ReadyMe<R::Err>, Init<R::Send, Me>>,
355);
356
357impl<R: Request<Payload = GetMe>> Future for Send<R> {
358    type Output = Result<Me, R::Err>;
359
360    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
361        let this = self.project();
362        this.0.poll(cx)
363    }
364}
365
366#[pin_project::pin_project]
367pub struct SendRef<R: Request<Payload = GetMe>>(
368    #[pin] future::Either<ReadyMe<R::Err>, Init<R::SendRef, Me>>,
369);
370
371impl<R: Request<Payload = GetMe>> Future for SendRef<R> {
372    type Output = Result<Me, R::Err>;
373
374    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
375        let this = self.project();
376        this.0.poll(cx)
377    }
378}
379
380#[pin_project::pin_project]
381struct Init<F, T>(#[pin] F, Arc<OnceCell<T>>);
382
383impl<F: Future<Output = Result<T, E>>, T: Clone, E> Future for Init<F, T> {
384    type Output = Result<T, E>;
385
386    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
387        let this = self.project();
388        match this.0.poll(cx) {
389            Poll::Ready(Ok(ok)) => Poll::Ready(Ok(this.1.get_or_init(|| ok).clone())),
390            poll @ Poll::Ready(_) | poll @ Poll::Pending => poll,
391        }
392    }
393}