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_photo,
103        send_audio,
104        send_document,
105        send_video,
106        send_animation,
107        send_voice,
108        send_video_note,
109        send_paid_media,
110        send_media_group,
111        send_location,
112        edit_message_live_location,
113        edit_message_live_location_inline,
114        stop_message_live_location,
115        stop_message_live_location_inline,
116        edit_message_checklist,
117        send_venue,
118        send_contact,
119        send_poll,
120        send_checklist,
121        send_dice,
122        send_chat_action,
123        set_message_reaction,
124        get_user_profile_photos,
125        get_user_profile_audios,
126        set_user_emoji_status,
127        get_file,
128        kick_chat_member,
129        ban_chat_member,
130        unban_chat_member,
131        restrict_chat_member,
132        promote_chat_member,
133        set_chat_administrator_custom_title,
134        set_chat_member_tag,
135        ban_chat_sender_chat,
136        unban_chat_sender_chat,
137        set_chat_permissions,
138        export_chat_invite_link,
139        create_chat_invite_link,
140        edit_chat_invite_link,
141        create_chat_subscription_invite_link,
142        edit_chat_subscription_invite_link,
143        revoke_chat_invite_link,
144        set_chat_photo,
145        delete_chat_photo,
146        set_chat_title,
147        set_chat_description,
148        pin_chat_message,
149        unpin_chat_message,
150        unpin_all_chat_messages,
151        leave_chat,
152        get_chat,
153        get_chat_administrators,
154        get_chat_members_count,
155        get_chat_member_count,
156        get_chat_member,
157        set_chat_sticker_set,
158        delete_chat_sticker_set,
159        get_forum_topic_icon_stickers,
160        create_forum_topic,
161        edit_forum_topic,
162        close_forum_topic,
163        reopen_forum_topic,
164        delete_forum_topic,
165        unpin_all_forum_topic_messages,
166        edit_general_forum_topic,
167        close_general_forum_topic,
168        reopen_general_forum_topic,
169        hide_general_forum_topic,
170        unhide_general_forum_topic,
171        unpin_all_general_forum_topic_messages,
172        answer_callback_query,
173        get_user_chat_boosts,
174        set_my_commands,
175        get_business_connection,
176        get_my_commands,
177        set_my_name,
178        get_my_name,
179        set_my_description,
180        get_my_description,
181        set_my_short_description,
182        get_my_short_description,
183        set_my_profile_photo,
184        remove_my_profile_photo,
185        get_managed_bot_token,
186        replace_managed_bot_token,
187        save_prepared_keyboard_button,
188        send_live_photo,
189        get_user_personal_chat_messages,
190        answer_guest_query,
191        get_managed_bot_access_settings,
192        set_managed_bot_access_settings,
193        delete_message_reaction,
194        delete_all_message_reactions,
195        set_chat_menu_button,
196        get_chat_menu_button,
197        set_my_default_administrator_rights,
198        get_my_default_administrator_rights,
199        delete_my_commands,
200        answer_inline_query,
201        answer_web_app_query,
202        save_prepared_inline_message,
203        edit_message_text,
204        edit_message_text_inline,
205        edit_message_caption,
206        edit_message_caption_inline,
207        edit_message_media,
208        edit_message_media_inline,
209        edit_message_reply_markup,
210        edit_message_reply_markup_inline,
211        stop_poll,
212        approve_suggested_post,
213        decline_suggested_post,
214        delete_message,
215        delete_messages,
216        send_sticker,
217        get_sticker_set,
218        get_custom_emoji_stickers,
219        upload_sticker_file,
220        create_new_sticker_set,
221        add_sticker_to_set,
222        set_sticker_position_in_set,
223        delete_sticker_from_set,
224        replace_sticker_in_set,
225        set_sticker_set_thumbnail,
226        set_custom_emoji_sticker_set_thumbnail,
227        set_sticker_set_title,
228        delete_sticker_set,
229        set_sticker_emoji_list,
230        set_sticker_keywords,
231        set_sticker_mask_position,
232        get_available_gifts,
233        send_gift,
234        send_gift_chat,
235        gift_premium_subscription,
236        verify_user,
237        verify_chat,
238        remove_user_verification,
239        remove_chat_verification,
240        read_business_message,
241        delete_business_messages,
242        set_business_account_name,
243        set_business_account_username,
244        set_business_account_bio,
245        set_business_account_profile_photo,
246        remove_business_account_profile_photo,
247        set_business_account_gift_settings,
248        get_business_account_star_balance,
249        transfer_business_account_stars,
250        get_business_account_gifts,
251        get_user_gifts,
252        get_chat_gifts,
253        convert_gift_to_stars,
254        upgrade_gift,
255        transfer_gift,
256        post_story,
257        repost_story,
258        edit_story,
259        delete_story,
260        send_invoice,
261        create_invoice_link,
262        answer_shipping_query,
263        answer_pre_checkout_query,
264        get_my_star_balance,
265        get_star_transactions,
266        refund_star_payment,
267        edit_user_star_subscription,
268        set_passport_data_errors,
269        send_game,
270        set_game_score,
271        set_game_score_inline,
272        get_game_high_scores,
273        approve_chat_join_request,
274        decline_chat_join_request
275        => f, fty
276    }
277}
278
279download_forward! {
280    B
281    CacheMe<B>
282    { this => this.inner() }
283}
284
285#[must_use = "Requests are lazy and do nothing unless sent"]
286pub struct CachedMeRequest<R: Request<Payload = GetMe>>(Inner<R>, GetMe);
287
288enum Inner<R: Request<Payload = GetMe>> {
289    Ready(Me),
290    Pending(R, Arc<OnceCell<Me>>),
291}
292
293impl<R> Request for CachedMeRequest<R>
294where
295    R: Request<Payload = GetMe>,
296{
297    type Err = R::Err;
298    type Send = Send<R>;
299    type SendRef = SendRef<R>;
300
301    fn send(self) -> Self::Send {
302        let fut = match self.0 {
303            Inner::Ready(me) => future::Either::Left(ok(me)),
304            Inner::Pending(req, cell) => future::Either::Right(Init(req.send(), cell)),
305        };
306        Send(fut)
307    }
308
309    fn send_ref(&self) -> Self::SendRef {
310        let fut = match &self.0 {
311            Inner::Ready(me) => future::Either::Left(ok(me.clone())),
312            Inner::Pending(req, cell) => {
313                future::Either::Right(Init(req.send_ref(), Arc::clone(cell)))
314            }
315        };
316        SendRef(fut)
317    }
318}
319
320impl<R: Request<Payload = GetMe>> HasPayload for CachedMeRequest<R> {
321    type Payload = GetMe;
322
323    fn payload_mut(&mut self) -> &mut Self::Payload {
324        &mut self.1
325    }
326
327    fn payload_ref(&self) -> &Self::Payload {
328        &self.1
329    }
330}
331
332impl<R: Request<Payload = GetMe>> IntoFuture for CachedMeRequest<R> {
333    type Output = Result<Me, R::Err>;
334    type IntoFuture = Send<R>;
335
336    fn into_future(self) -> Self::IntoFuture {
337        self.send()
338    }
339}
340
341type ReadyMe<Err> = Ready<Result<Me, Err>>;
342
343#[pin_project::pin_project]
344pub struct Send<R: Request<Payload = GetMe>>(
345    #[pin] future::Either<ReadyMe<R::Err>, Init<R::Send, Me>>,
346);
347
348impl<R: Request<Payload = GetMe>> Future for Send<R> {
349    type Output = Result<Me, R::Err>;
350
351    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
352        let this = self.project();
353        this.0.poll(cx)
354    }
355}
356
357#[pin_project::pin_project]
358pub struct SendRef<R: Request<Payload = GetMe>>(
359    #[pin] future::Either<ReadyMe<R::Err>, Init<R::SendRef, Me>>,
360);
361
362impl<R: Request<Payload = GetMe>> Future for SendRef<R> {
363    type Output = Result<Me, R::Err>;
364
365    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
366        let this = self.project();
367        this.0.poll(cx)
368    }
369}
370
371#[pin_project::pin_project]
372struct Init<F, T>(#[pin] F, Arc<OnceCell<T>>);
373
374impl<F: Future<Output = Result<T, E>>, T: Clone, E> Future for Init<F, T> {
375    type Output = Result<T, E>;
376
377    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
378        let this = self.project();
379        match this.0.poll(cx) {
380            Poll::Ready(Ok(ok)) => Poll::Ready(Ok(this.1.get_or_init(|| ok).clone())),
381            poll @ Poll::Ready(_) | poll @ Poll::Pending => poll,
382        }
383    }
384}