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#[derive(Clone, Debug)]
23pub struct CacheMe<B> {
24 bot: B,
25 me: Arc<OnceCell<Me>>,
26}
27
28impl<B> CacheMe<B> {
29 pub fn new(bot: B) -> CacheMe<B> {
35 Self { bot, me: Arc::new(OnceCell::new()) }
36 }
37
38 pub fn inner(&self) -> &B {
40 &self.bot
41 }
42
43 pub fn into_inner(self) -> B {
45 self.bot
46 }
47
48 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}