Skip to main content

rustigram_api/methods/
gifts.rs

1use crate::client::BotClient;
2use crate::error::Result;
3use rustigram_types::gifts::Gifts;
4use rustigram_types::message::MessageEntity;
5use rustigram_types::payments::OwnedGifts;
6use rustigram_types::user::ChatId;
7use serde::Serialize;
8use std::future::{Future, IntoFuture};
9use std::pin::Pin;
10
11// ─── Helper macro ─────────────────────────────────────────────────────────────
12
13/// Generates an `IntoFuture` impl that calls `BotClient::post_json`.
14macro_rules! impl_into_future {
15    ($builder:ident, $return_ty:ty, $method:literal) => {
16        impl IntoFuture for $builder {
17            type Output = Result<$return_ty>;
18            type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
19
20            fn into_future(self) -> Self::IntoFuture {
21                Box::pin(async move { self.client.post_json($method, &self.params).await })
22            }
23        }
24    };
25}
26
27// ─── getAvailableGifts ────────────────────────────────────────────────────────
28
29/// Builder for the [`getAvailableGifts`](https://core.telegram.org/bots/api#getavailablegifts) method.
30///
31/// Returns the list of gifts that can be sent by the bot. Requires no parameters.
32pub struct GetAvailableGifts {
33    client: BotClient,
34}
35
36impl GetAvailableGifts {
37    pub(crate) fn new(client: BotClient) -> Self {
38        Self { client }
39    }
40}
41
42impl IntoFuture for GetAvailableGifts {
43    type Output = Result<Gifts>;
44    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
45
46    fn into_future(self) -> Self::IntoFuture {
47        Box::pin(async move {
48            self.client
49                .post_json("getAvailableGifts", &serde_json::json!({}))
50                .await
51        })
52    }
53}
54
55// ─── sendGift ─────────────────────────────────────────────────────────────────
56
57#[derive(Serialize)]
58struct SendGiftParams {
59    gift_id: String,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    user_id: Option<i64>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    chat_id: Option<ChatId>,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pay_for_upgrade: Option<bool>,
66    #[serde(skip_serializing_if = "Option::is_none")]
67    text: Option<String>,
68    #[serde(skip_serializing_if = "Option::is_none")]
69    text_parse_mode: Option<rustigram_types::message::ParseMode>,
70    #[serde(skip_serializing_if = "Option::is_none")]
71    text_entities: Option<Vec<MessageEntity>>,
72}
73
74/// Builder for the [`sendGift`](https://core.telegram.org/bots/api#sendgift) method.
75///
76/// Sends a gift to a user or channel chat. Either `user_id` or `chat_id` must be
77/// set — use the corresponding builder method.
78pub struct SendGift {
79    client: BotClient,
80    params: SendGiftParams,
81}
82
83impl SendGift {
84    pub(crate) fn new(client: BotClient, gift_id: impl Into<String>) -> Self {
85        Self {
86            client,
87            params: SendGiftParams {
88                gift_id: gift_id.into(),
89                user_id: None,
90                chat_id: None,
91                pay_for_upgrade: None,
92                text: None,
93                text_parse_mode: None,
94                text_entities: None,
95            },
96        }
97    }
98    /// Sends the gift to a user. Required if `chat_id` is not set.
99    pub fn user_id(mut self, id: i64) -> Self {
100        self.params.user_id = Some(id);
101        self
102    }
103    /// Sends the gift to a channel chat. Required if `user_id` is not set.
104    /// Limited gifts cannot be sent to channel chats.
105    pub fn chat_id(mut self, id: impl Into<ChatId>) -> Self {
106        self.params.chat_id = Some(id.into());
107        self
108    }
109    /// Pass `true` to pay for the upgrade from the bot's balance, making the upgrade free for the receiver.
110    pub fn pay_for_upgrade(mut self, v: bool) -> Self {
111        self.params.pay_for_upgrade = Some(v);
112        self
113    }
114    /// Optional text message to accompany the gift (0–128 characters).
115    pub fn text(mut self, t: impl Into<String>) -> Self {
116        self.params.text = Some(t.into());
117        self
118    }
119    /// Parse mode for entities in the gift text.
120    pub fn text_parse_mode(mut self, m: rustigram_types::message::ParseMode) -> Self {
121        self.params.text_parse_mode = Some(m);
122        self
123    }
124    /// Special entities in the gift text; alternative to `text_parse_mode`.
125    pub fn text_entities(mut self, e: Vec<MessageEntity>) -> Self {
126        self.params.text_entities = Some(e);
127        self
128    }
129}
130
131impl_into_future!(SendGift, bool, "sendGift");
132
133// ─── giftPremiumSubscription ──────────────────────────────────────────────────
134
135#[derive(Serialize)]
136struct GiftPremiumSubscriptionParams {
137    user_id: i64,
138    month_count: u32,
139    star_count: u32,
140    #[serde(skip_serializing_if = "Option::is_none")]
141    text: Option<String>,
142    #[serde(skip_serializing_if = "Option::is_none")]
143    text_parse_mode: Option<rustigram_types::message::ParseMode>,
144    #[serde(skip_serializing_if = "Option::is_none")]
145    text_entities: Option<Vec<MessageEntity>>,
146}
147
148/// Builder for the [`giftPremiumSubscription`](https://core.telegram.org/bots/api#giftpremiumsubscription) method.
149///
150/// Gifts a Telegram Premium subscription to a user.
151/// `month_count` must be `3`, `6`, or `12`.
152/// `star_count` must be `1000`, `1500`, or `2500` respectively.
153pub struct GiftPremiumSubscription {
154    client: BotClient,
155    params: GiftPremiumSubscriptionParams,
156}
157
158impl GiftPremiumSubscription {
159    pub(crate) fn new(client: BotClient, user_id: i64, month_count: u32, star_count: u32) -> Self {
160        Self {
161            client,
162            params: GiftPremiumSubscriptionParams {
163                user_id,
164                month_count,
165                star_count,
166                text: None,
167                text_parse_mode: None,
168                text_entities: None,
169            },
170        }
171    }
172    /// Optional text to accompany the gift (0–128 characters).
173    pub fn text(mut self, t: impl Into<String>) -> Self {
174        self.params.text = Some(t.into());
175        self
176    }
177    /// Parse mode for entities in the gift text.
178    pub fn text_parse_mode(mut self, m: rustigram_types::message::ParseMode) -> Self {
179        self.params.text_parse_mode = Some(m);
180        self
181    }
182    /// Special entities in the gift text; alternative to `text_parse_mode`.
183    pub fn text_entities(mut self, e: Vec<MessageEntity>) -> Self {
184        self.params.text_entities = Some(e);
185        self
186    }
187}
188
189impl_into_future!(GiftPremiumSubscription, bool, "giftPremiumSubscription");
190
191// ─── getBusinessAccountGifts ──────────────────────────────────────────────────
192
193#[derive(Serialize)]
194struct GetBusinessAccountGiftsParams {
195    business_connection_id: String,
196    #[serde(skip_serializing_if = "Option::is_none")]
197    exclude_unsaved: Option<bool>,
198    #[serde(skip_serializing_if = "Option::is_none")]
199    exclude_saved: Option<bool>,
200    #[serde(skip_serializing_if = "Option::is_none")]
201    exclude_unlimited: Option<bool>,
202    #[serde(skip_serializing_if = "Option::is_none")]
203    exclude_limited_upgradable: Option<bool>,
204    #[serde(skip_serializing_if = "Option::is_none")]
205    exclude_limited_non_upgradable: Option<bool>,
206    #[serde(skip_serializing_if = "Option::is_none")]
207    exclude_unique: Option<bool>,
208    #[serde(skip_serializing_if = "Option::is_none")]
209    exclude_from_blockchain: Option<bool>,
210    #[serde(skip_serializing_if = "Option::is_none")]
211    sort_by_price: Option<bool>,
212    #[serde(skip_serializing_if = "Option::is_none")]
213    offset: Option<String>,
214    #[serde(skip_serializing_if = "Option::is_none")]
215    limit: Option<u32>,
216}
217
218/// Builder for the [`getBusinessAccountGifts`](https://core.telegram.org/bots/api#getbusinessaccountgifts) method.
219///
220/// Returns the gifts received by a managed business account.
221/// Requires the `can_view_gifts_and_stars` business bot right.
222pub struct GetBusinessAccountGifts {
223    client: BotClient,
224    params: GetBusinessAccountGiftsParams,
225}
226
227impl GetBusinessAccountGifts {
228    pub(crate) fn new(client: BotClient, business_connection_id: impl Into<String>) -> Self {
229        Self {
230            client,
231            params: GetBusinessAccountGiftsParams {
232                business_connection_id: business_connection_id.into(),
233                exclude_unsaved: None,
234                exclude_saved: None,
235                exclude_unlimited: None,
236                exclude_limited_upgradable: None,
237                exclude_limited_non_upgradable: None,
238                exclude_unique: None,
239                exclude_from_blockchain: None,
240                sort_by_price: None,
241                offset: None,
242                limit: None,
243            },
244        }
245    }
246    /// Excludes gifts not saved to the account's profile page.
247    pub fn exclude_unsaved(mut self, v: bool) -> Self {
248        self.params.exclude_unsaved = Some(v);
249        self
250    }
251    /// Excludes gifts saved to the account's profile page.
252    pub fn exclude_saved(mut self, v: bool) -> Self {
253        self.params.exclude_saved = Some(v);
254        self
255    }
256    /// Excludes unlimited regular gifts.
257    pub fn exclude_unlimited(mut self, v: bool) -> Self {
258        self.params.exclude_unlimited = Some(v);
259        self
260    }
261    /// Excludes limited gifts that can be upgraded to unique.
262    pub fn exclude_limited_upgradable(mut self, v: bool) -> Self {
263        self.params.exclude_limited_upgradable = Some(v);
264        self
265    }
266    /// Excludes limited gifts that cannot be upgraded to unique.
267    pub fn exclude_limited_non_upgradable(mut self, v: bool) -> Self {
268        self.params.exclude_limited_non_upgradable = Some(v);
269        self
270    }
271    /// Excludes unique gifts.
272    pub fn exclude_unique(mut self, v: bool) -> Self {
273        self.params.exclude_unique = Some(v);
274        self
275    }
276    /// Excludes gifts assigned from the TON blockchain.
277    pub fn exclude_from_blockchain(mut self, v: bool) -> Self {
278        self.params.exclude_from_blockchain = Some(v);
279        self
280    }
281    /// Sorts results by price instead of send date.
282    pub fn sort_by_price(mut self, v: bool) -> Self {
283        self.params.sort_by_price = Some(v);
284        self
285    }
286    /// Pagination offset from the previous response.
287    pub fn offset(mut self, o: impl Into<String>) -> Self {
288        self.params.offset = Some(o.into());
289        self
290    }
291    /// Maximum number of gifts to return (1–100, default 100).
292    pub fn limit(mut self, v: u32) -> Self {
293        self.params.limit = Some(v);
294        self
295    }
296}
297
298impl_into_future!(
299    GetBusinessAccountGifts,
300    OwnedGifts,
301    "getBusinessAccountGifts"
302);
303
304// ─── getUserGifts ─────────────────────────────────────────────────────────────
305
306#[derive(Serialize)]
307struct GetUserGiftsParams {
308    user_id: i64,
309    #[serde(skip_serializing_if = "Option::is_none")]
310    exclude_unlimited: Option<bool>,
311    #[serde(skip_serializing_if = "Option::is_none")]
312    exclude_limited_upgradable: Option<bool>,
313    #[serde(skip_serializing_if = "Option::is_none")]
314    exclude_limited_non_upgradable: Option<bool>,
315    #[serde(skip_serializing_if = "Option::is_none")]
316    exclude_unique: Option<bool>,
317    #[serde(skip_serializing_if = "Option::is_none")]
318    exclude_from_blockchain: Option<bool>,
319    #[serde(skip_serializing_if = "Option::is_none")]
320    sort_by_price: Option<bool>,
321    #[serde(skip_serializing_if = "Option::is_none")]
322    offset: Option<String>,
323    #[serde(skip_serializing_if = "Option::is_none")]
324    limit: Option<u32>,
325}
326
327/// Builder for the [`getUserGifts`](https://core.telegram.org/bots/api#getusergifts) method.
328///
329/// Returns the gifts owned and hosted by a user.
330pub struct GetUserGifts {
331    client: BotClient,
332    params: GetUserGiftsParams,
333}
334
335impl GetUserGifts {
336    pub(crate) fn new(client: BotClient, user_id: i64) -> Self {
337        Self {
338            client,
339            params: GetUserGiftsParams {
340                user_id,
341                exclude_unlimited: None,
342                exclude_limited_upgradable: None,
343                exclude_limited_non_upgradable: None,
344                exclude_unique: None,
345                exclude_from_blockchain: None,
346                sort_by_price: None,
347                offset: None,
348                limit: None,
349            },
350        }
351    }
352    /// Excludes unlimited regular gifts.
353    pub fn exclude_unlimited(mut self, v: bool) -> Self {
354        self.params.exclude_unlimited = Some(v);
355        self
356    }
357    /// Excludes limited gifts that can be upgraded to unique.
358    pub fn exclude_limited_upgradable(mut self, v: bool) -> Self {
359        self.params.exclude_limited_upgradable = Some(v);
360        self
361    }
362    /// Excludes limited gifts that cannot be upgraded to unique.
363    pub fn exclude_limited_non_upgradable(mut self, v: bool) -> Self {
364        self.params.exclude_limited_non_upgradable = Some(v);
365        self
366    }
367    /// Excludes unique gifts.
368    pub fn exclude_unique(mut self, v: bool) -> Self {
369        self.params.exclude_unique = Some(v);
370        self
371    }
372    /// Excludes gifts assigned from the TON blockchain.
373    pub fn exclude_from_blockchain(mut self, v: bool) -> Self {
374        self.params.exclude_from_blockchain = Some(v);
375        self
376    }
377    /// Sorts results by price instead of send date.
378    pub fn sort_by_price(mut self, v: bool) -> Self {
379        self.params.sort_by_price = Some(v);
380        self
381    }
382    /// Pagination offset from the previous response.
383    pub fn offset(mut self, o: impl Into<String>) -> Self {
384        self.params.offset = Some(o.into());
385        self
386    }
387    /// Maximum number of gifts to return (1–100, default 100).
388    pub fn limit(mut self, v: u32) -> Self {
389        self.params.limit = Some(v);
390        self
391    }
392}
393
394impl_into_future!(GetUserGifts, OwnedGifts, "getUserGifts");
395
396// ─── getChatGifts ─────────────────────────────────────────────────────────────
397
398#[derive(Serialize)]
399struct GetChatGiftsParams {
400    chat_id: ChatId,
401    #[serde(skip_serializing_if = "Option::is_none")]
402    exclude_unsaved: Option<bool>,
403    #[serde(skip_serializing_if = "Option::is_none")]
404    exclude_saved: Option<bool>,
405    #[serde(skip_serializing_if = "Option::is_none")]
406    exclude_unlimited: Option<bool>,
407    #[serde(skip_serializing_if = "Option::is_none")]
408    exclude_limited_upgradable: Option<bool>,
409    #[serde(skip_serializing_if = "Option::is_none")]
410    exclude_limited_non_upgradable: Option<bool>,
411    #[serde(skip_serializing_if = "Option::is_none")]
412    exclude_unique: Option<bool>,
413    #[serde(skip_serializing_if = "Option::is_none")]
414    exclude_from_blockchain: Option<bool>,
415    #[serde(skip_serializing_if = "Option::is_none")]
416    sort_by_price: Option<bool>,
417    #[serde(skip_serializing_if = "Option::is_none")]
418    offset: Option<String>,
419    #[serde(skip_serializing_if = "Option::is_none")]
420    limit: Option<u32>,
421}
422
423/// Builder for the [`getChatGifts`](https://core.telegram.org/bots/api#getchatgifts) method.
424///
425/// Returns the gifts owned by a channel chat.
426pub struct GetChatGifts {
427    client: BotClient,
428    params: GetChatGiftsParams,
429}
430
431impl GetChatGifts {
432    pub(crate) fn new(client: BotClient, chat_id: impl Into<ChatId>) -> Self {
433        Self {
434            client,
435            params: GetChatGiftsParams {
436                chat_id: chat_id.into(),
437                exclude_unsaved: None,
438                exclude_saved: None,
439                exclude_unlimited: None,
440                exclude_limited_upgradable: None,
441                exclude_limited_non_upgradable: None,
442                exclude_unique: None,
443                exclude_from_blockchain: None,
444                sort_by_price: None,
445                offset: None,
446                limit: None,
447            },
448        }
449    }
450    /// Excludes gifts not saved to the chat's profile page.
451    pub fn exclude_unsaved(mut self, v: bool) -> Self {
452        self.params.exclude_unsaved = Some(v);
453        self
454    }
455    /// Excludes gifts saved to the chat's profile page.
456    pub fn exclude_saved(mut self, v: bool) -> Self {
457        self.params.exclude_saved = Some(v);
458        self
459    }
460    /// Excludes unlimited regular gifts.
461    pub fn exclude_unlimited(mut self, v: bool) -> Self {
462        self.params.exclude_unlimited = Some(v);
463        self
464    }
465    /// Excludes limited gifts that can be upgraded to unique.
466    pub fn exclude_limited_upgradable(mut self, v: bool) -> Self {
467        self.params.exclude_limited_upgradable = Some(v);
468        self
469    }
470    /// Excludes limited gifts that cannot be upgraded to unique.
471    pub fn exclude_limited_non_upgradable(mut self, v: bool) -> Self {
472        self.params.exclude_limited_non_upgradable = Some(v);
473        self
474    }
475    /// Excludes unique gifts.
476    pub fn exclude_unique(mut self, v: bool) -> Self {
477        self.params.exclude_unique = Some(v);
478        self
479    }
480    /// Excludes gifts assigned from the TON blockchain.
481    pub fn exclude_from_blockchain(mut self, v: bool) -> Self {
482        self.params.exclude_from_blockchain = Some(v);
483        self
484    }
485    /// Sorts results by price instead of send date.
486    pub fn sort_by_price(mut self, v: bool) -> Self {
487        self.params.sort_by_price = Some(v);
488        self
489    }
490    /// Pagination offset from the previous response.
491    pub fn offset(mut self, o: impl Into<String>) -> Self {
492        self.params.offset = Some(o.into());
493        self
494    }
495    /// Maximum number of gifts to return (1–100, default 100).
496    pub fn limit(mut self, v: u32) -> Self {
497        self.params.limit = Some(v);
498        self
499    }
500}
501
502impl_into_future!(GetChatGifts, OwnedGifts, "getChatGifts");
503
504// ─── convertGiftToStars ───────────────────────────────────────────────────────
505
506#[derive(Serialize)]
507struct ConvertGiftToStarsParams {
508    business_connection_id: String,
509    owned_gift_id: String,
510}
511
512/// Builder for the [`convertGiftToStars`](https://core.telegram.org/bots/api#convertgifttostars) method.
513///
514/// Converts a regular gift owned by a business account to Telegram Stars.
515/// Requires the `can_convert_gifts_to_stars` business bot right.
516pub struct ConvertGiftToStars {
517    client: BotClient,
518    params: ConvertGiftToStarsParams,
519}
520
521impl ConvertGiftToStars {
522    pub(crate) fn new(
523        client: BotClient,
524        business_connection_id: impl Into<String>,
525        owned_gift_id: impl Into<String>,
526    ) -> Self {
527        Self {
528            client,
529            params: ConvertGiftToStarsParams {
530                business_connection_id: business_connection_id.into(),
531                owned_gift_id: owned_gift_id.into(),
532            },
533        }
534    }
535}
536
537impl_into_future!(ConvertGiftToStars, bool, "convertGiftToStars");
538
539// ─── upgradeGift ──────────────────────────────────────────────────────────────
540
541#[derive(Serialize)]
542struct UpgradeGiftParams {
543    business_connection_id: String,
544    owned_gift_id: String,
545    #[serde(skip_serializing_if = "Option::is_none")]
546    keep_original_details: Option<bool>,
547    #[serde(skip_serializing_if = "Option::is_none")]
548    star_count: Option<u32>,
549}
550
551/// Builder for the [`upgradeGift`](https://core.telegram.org/bots/api#upgradegift) method.
552///
553/// Upgrades a regular gift to a unique gift.
554/// Requires the `can_transfer_and_upgrade_gifts` business bot right.
555/// Also requires `can_transfer_stars` if the upgrade is paid.
556pub struct UpgradeGift {
557    client: BotClient,
558    params: UpgradeGiftParams,
559}
560
561impl UpgradeGift {
562    pub(crate) fn new(
563        client: BotClient,
564        business_connection_id: impl Into<String>,
565        owned_gift_id: impl Into<String>,
566    ) -> Self {
567        Self {
568            client,
569            params: UpgradeGiftParams {
570                business_connection_id: business_connection_id.into(),
571                owned_gift_id: owned_gift_id.into(),
572                keep_original_details: None,
573                star_count: None,
574            },
575        }
576    }
577    /// Pass `true` to preserve the original gift text, sender, and receiver in the upgraded gift.
578    pub fn keep_original_details(mut self, v: bool) -> Self {
579        self.params.keep_original_details = Some(v);
580        self
581    }
582    /// Stars to pay for the upgrade from the business account balance.
583    /// Pass `0` if `gift.prepaid_upgrade_star_count > 0`.
584    pub fn star_count(mut self, v: u32) -> Self {
585        self.params.star_count = Some(v);
586        self
587    }
588}
589
590impl_into_future!(UpgradeGift, bool, "upgradeGift");
591
592// ─── transferGift ─────────────────────────────────────────────────────────────
593
594#[derive(Serialize)]
595struct TransferGiftParams {
596    business_connection_id: String,
597    owned_gift_id: String,
598    new_owner_chat_id: i64,
599    #[serde(skip_serializing_if = "Option::is_none")]
600    star_count: Option<u32>,
601}
602
603/// Builder for the [`transferGift`](https://core.telegram.org/bots/api#transfergift) method.
604///
605/// Transfers a unique gift to another user.
606/// Requires the `can_transfer_and_upgrade_gifts` business bot right.
607/// Also requires `can_transfer_stars` if the transfer is paid.
608pub struct TransferGift {
609    client: BotClient,
610    params: TransferGiftParams,
611}
612
613impl TransferGift {
614    pub(crate) fn new(
615        client: BotClient,
616        business_connection_id: impl Into<String>,
617        owned_gift_id: impl Into<String>,
618        new_owner_chat_id: i64,
619    ) -> Self {
620        Self {
621            client,
622            params: TransferGiftParams {
623                business_connection_id: business_connection_id.into(),
624                owned_gift_id: owned_gift_id.into(),
625                new_owner_chat_id,
626                star_count: None,
627            },
628        }
629    }
630    /// Stars to pay for the transfer from the business account balance.
631    /// Required if the transfer is not free.
632    pub fn star_count(mut self, v: u32) -> Self {
633        self.params.star_count = Some(v);
634        self
635    }
636}
637
638impl_into_future!(TransferGift, bool, "transferGift");