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