Skip to main content

ronami_core/adaptors/
cache_me.rs

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