Skip to main content

rustigram_api/methods/
bot_settings.rs

1use crate::client::BotClient;
2use crate::error::Result;
3use reqwest::multipart::{Form, Part};
4use rustigram_types::keyboard::MenuButton;
5use rustigram_types::user::{
6    BotCommand, BotCommandScope, BotDescription, BotName, BotShortDescription,
7    ChatAdministratorRights, ChatId,
8};
9use serde::Serialize;
10use std::future::{Future, IntoFuture};
11use std::pin::Pin;
12
13// ─── Helper macro ─────────────────────────────────────────────────────────────
14
15/// Generates an `IntoFuture` impl that calls `BotClient::post_json`.
16macro_rules! impl_into_future {
17    ($builder:ident, $return_ty:ty, $method:literal) => {
18        impl IntoFuture for $builder {
19            type Output = Result<$return_ty>;
20            type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
21
22            fn into_future(self) -> Self::IntoFuture {
23                Box::pin(async move { self.client.post_json($method, &self.params).await })
24            }
25        }
26    };
27}
28
29// ─── setMyCommands ────────────────────────────────────────────────────────────
30
31#[derive(Serialize)]
32struct SetMyCommandsParams {
33    commands: Vec<BotCommand>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    scope: Option<BotCommandScope>,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    language_code: Option<String>,
38}
39
40/// Builder for the [`setMyCommands`](https://core.telegram.org/bots/api#setmycommands) method.
41pub struct SetMyCommands {
42    client: BotClient,
43    params: SetMyCommandsParams,
44}
45
46impl SetMyCommands {
47    pub(crate) fn new(client: BotClient, commands: Vec<BotCommand>) -> Self {
48        Self {
49            client,
50            params: SetMyCommandsParams {
51                commands,
52                scope: None,
53                language_code: None,
54            },
55        }
56    }
57    /// Restricts these commands to a specific scope (chat type or individual chat).
58    pub fn scope(mut self, s: BotCommandScope) -> Self {
59        self.params.scope = Some(s);
60        self
61    }
62    /// Sets the language code for localised command lists (IETF tag, e.g. `"en"`).
63    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
64        self.params.language_code = Some(lc.into());
65        self
66    }
67}
68
69impl_into_future!(SetMyCommands, bool, "setMyCommands");
70
71// ─── deleteMyCommands ─────────────────────────────────────────────────────────
72
73#[derive(Serialize, Default)]
74struct DeleteMyCommandsParams {
75    #[serde(skip_serializing_if = "Option::is_none")]
76    scope: Option<BotCommandScope>,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    language_code: Option<String>,
79}
80
81/// Builder for the [`deleteMyCommands`](https://core.telegram.org/bots/api#deletemycommands) method.
82///
83/// Deletes the bot's command list for the given scope and language.
84/// After deletion, higher-level commands will be shown to affected users.
85pub struct DeleteMyCommands {
86    client: BotClient,
87    params: DeleteMyCommandsParams,
88}
89
90impl DeleteMyCommands {
91    pub(crate) fn new(client: BotClient) -> Self {
92        Self {
93            client,
94            params: Default::default(),
95        }
96    }
97    /// Restricts deletion to a specific scope.
98    pub fn scope(mut self, s: BotCommandScope) -> Self {
99        self.params.scope = Some(s);
100        self
101    }
102    /// Restricts deletion to a specific language code (IETF tag, e.g. `"en"`).
103    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
104        self.params.language_code = Some(lc.into());
105        self
106    }
107}
108
109impl_into_future!(DeleteMyCommands, bool, "deleteMyCommands");
110
111// ─── getMyCommands ────────────────────────────────────────────────────────────
112
113#[derive(Serialize, Default)]
114struct GetMyCommandsParams {
115    #[serde(skip_serializing_if = "Option::is_none")]
116    scope: Option<BotCommandScope>,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    language_code: Option<String>,
119}
120
121/// Builder for the [`getMyCommands`](https://core.telegram.org/bots/api#getmycommands) method.
122pub struct GetMyCommands {
123    client: BotClient,
124    params: GetMyCommandsParams,
125}
126
127impl GetMyCommands {
128    pub(crate) fn new(client: BotClient) -> Self {
129        Self {
130            client,
131            params: Default::default(),
132        }
133    }
134    /// Restricts the list of retrieved commands to a specific scope (chat type or individual chat).
135    pub fn scope(mut self, s: BotCommandScope) -> Self {
136        self.params.scope = Some(s);
137        self
138    }
139    /// The language code for localised command lists (IETF tag, e.g. `"en"`).
140    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
141        self.params.language_code = Some(lc.into());
142        self
143    }
144}
145
146impl_into_future!(GetMyCommands, Vec<BotCommand>, "getMyCommands");
147
148// ─── setMyName ────────────────────────────────────────────────────────────────
149
150#[derive(Serialize, Default)]
151struct SetMyNameParams {
152    #[serde(skip_serializing_if = "Option::is_none")]
153    name: Option<String>,
154    #[serde(skip_serializing_if = "Option::is_none")]
155    language_code: Option<String>,
156}
157
158/// Builder for the [`setMyName`](https://core.telegram.org/bots/api#setmyname) method.
159pub struct SetMyName {
160    client: BotClient,
161    params: SetMyNameParams,
162}
163
164impl SetMyName {
165    pub(crate) fn new(client: BotClient) -> Self {
166        Self {
167            client,
168            params: Default::default(),
169        }
170    }
171    /// Sets the new bot name (up to 64 characters).
172    pub fn name(mut self, n: impl Into<String>) -> Self {
173        self.params.name = Some(n.into());
174        self
175    }
176    /// Sets the language code for localised bot names (IETF tag, e.g. `"en"`).
177    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
178        self.params.language_code = Some(lc.into());
179        self
180    }
181}
182
183impl_into_future!(SetMyName, bool, "setMyName");
184
185// ─── getMyName ────────────────────────────────────────────────────────────────
186
187#[derive(Serialize, Default)]
188struct GetMyNameParams {
189    #[serde(skip_serializing_if = "Option::is_none")]
190    language_code: Option<String>,
191}
192
193/// Builder for the [`getMyName`](https://core.telegram.org/bots/api#getmyname) method.
194pub struct GetMyName {
195    client: BotClient,
196    params: GetMyNameParams,
197}
198
199impl GetMyName {
200    pub(crate) fn new(client: BotClient) -> Self {
201        Self {
202            client,
203            params: Default::default(),
204        }
205    }
206    /// The language code for the localised bot name to retrieve (IETF tag, e.g. `"en"`).
207    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
208        self.params.language_code = Some(lc.into());
209        self
210    }
211}
212
213impl_into_future!(GetMyName, BotName, "getMyName");
214
215// ─── setMyDescription ─────────────────────────────────────────────────────────
216
217#[derive(Serialize, Default)]
218struct SetMyDescriptionParams {
219    #[serde(skip_serializing_if = "Option::is_none")]
220    description: Option<String>,
221    #[serde(skip_serializing_if = "Option::is_none")]
222    language_code: Option<String>,
223}
224
225/// Builder for the [`setMyDescription`](https://core.telegram.org/bots/api#setmydescription) method.
226pub struct SetMyDescription {
227    client: BotClient,
228    params: SetMyDescriptionParams,
229}
230
231impl SetMyDescription {
232    pub(crate) fn new(client: BotClient) -> Self {
233        Self {
234            client,
235            params: Default::default(),
236        }
237    }
238    /// Sets the new bot description shown on the profile page (up to 512 characters).
239    pub fn description(mut self, d: impl Into<String>) -> Self {
240        self.params.description = Some(d.into());
241        self
242    }
243    /// Sets the language code for localised bot descriptions (IETF tag, e.g. `"en"`).
244    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
245        self.params.language_code = Some(lc.into());
246        self
247    }
248}
249
250impl_into_future!(SetMyDescription, bool, "setMyDescription");
251
252// ─── getMyDescription ─────────────────────────────────────────────────────────
253
254#[derive(Serialize, Default)]
255struct GetMyDescriptionParams {
256    #[serde(skip_serializing_if = "Option::is_none")]
257    language_code: Option<String>,
258}
259
260/// Builder for the [`getMyDescription`](https://core.telegram.org/bots/api#getmydescription) method.
261pub struct GetMyDescription {
262    client: BotClient,
263    params: GetMyDescriptionParams,
264}
265
266impl GetMyDescription {
267    pub(crate) fn new(client: BotClient) -> Self {
268        Self {
269            client,
270            params: Default::default(),
271        }
272    }
273    /// The language code for the localised bot description to retrieve (IETF tag, e.g. `"en"`).
274    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
275        self.params.language_code = Some(lc.into());
276        self
277    }
278}
279
280impl_into_future!(GetMyDescription, BotDescription, "getMyDescription");
281
282// ─── setMyShortDescription ────────────────────────────────────────────────────
283
284#[derive(Serialize, Default)]
285struct SetMyShortDescriptionParams {
286    #[serde(skip_serializing_if = "Option::is_none")]
287    short_description: Option<String>,
288    #[serde(skip_serializing_if = "Option::is_none")]
289    language_code: Option<String>,
290}
291
292/// Builder for the [`setMyShortDescription`](https://core.telegram.org/bots/api#setmyshortdescription) method.
293///
294/// The short description is shown on the bot's profile page and sent with
295/// sharing links. Up to 120 characters; omit to remove the localised value.
296pub struct SetMyShortDescription {
297    client: BotClient,
298    params: SetMyShortDescriptionParams,
299}
300
301impl SetMyShortDescription {
302    pub(crate) fn new(client: BotClient) -> Self {
303        Self {
304            client,
305            params: Default::default(),
306        }
307    }
308    /// Sets the short description (0–120 characters). Omit to remove the dedicated value.
309    pub fn short_description(mut self, d: impl Into<String>) -> Self {
310        self.params.short_description = Some(d.into());
311        self
312    }
313    /// Sets the language code for the localised short description (IETF tag, e.g. `"en"`).
314    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
315        self.params.language_code = Some(lc.into());
316        self
317    }
318}
319
320impl_into_future!(SetMyShortDescription, bool, "setMyShortDescription");
321
322// ─── getMyShortDescription ────────────────────────────────────────────────────
323
324#[derive(Serialize, Default)]
325struct GetMyShortDescriptionParams {
326    #[serde(skip_serializing_if = "Option::is_none")]
327    language_code: Option<String>,
328}
329
330/// Builder for the [`getMyShortDescription`](https://core.telegram.org/bots/api#getmyshortdescription) method.
331pub struct GetMyShortDescription {
332    client: BotClient,
333    params: GetMyShortDescriptionParams,
334}
335
336impl GetMyShortDescription {
337    pub(crate) fn new(client: BotClient) -> Self {
338        Self {
339            client,
340            params: Default::default(),
341        }
342    }
343    /// The language code for the localised short description to retrieve (IETF tag, e.g. `"en"`).
344    pub fn language_code(mut self, lc: impl Into<String>) -> Self {
345        self.params.language_code = Some(lc.into());
346        self
347    }
348}
349
350impl_into_future!(
351    GetMyShortDescription,
352    BotShortDescription,
353    "getMyShortDescription"
354);
355
356// ─── setMyDefaultAdministratorRights ─────────────────────────────────────────
357
358#[derive(Serialize, Default)]
359struct SetMyDefaultAdministratorRightsParams {
360    #[serde(skip_serializing_if = "Option::is_none")]
361    rights: Option<ChatAdministratorRights>,
362    #[serde(skip_serializing_if = "Option::is_none")]
363    for_channels: Option<bool>,
364}
365
366/// Builder for the [`setMyDefaultAdministratorRights`](https://core.telegram.org/bots/api#setmydefaultadministratorrights) method.
367///
368/// Sets the default administrator rights suggested to users when the bot is
369/// added as an administrator. Pass `None` rights to clear the defaults.
370pub struct SetMyDefaultAdministratorRights {
371    client: BotClient,
372    params: SetMyDefaultAdministratorRightsParams,
373}
374
375impl SetMyDefaultAdministratorRights {
376    pub(crate) fn new(client: BotClient) -> Self {
377        Self {
378            client,
379            params: Default::default(),
380        }
381    }
382    /// Sets the new default administrator rights. Omit to clear the current defaults.
383    pub fn rights(mut self, r: ChatAdministratorRights) -> Self {
384        self.params.rights = Some(r);
385        self
386    }
387    /// Pass `true` to change defaults for channels; otherwise changes group/supergroup defaults.
388    pub fn for_channels(mut self, v: bool) -> Self {
389        self.params.for_channels = Some(v);
390        self
391    }
392}
393
394impl_into_future!(
395    SetMyDefaultAdministratorRights,
396    bool,
397    "setMyDefaultAdministratorRights"
398);
399
400// ─── getMyDefaultAdministratorRights ─────────────────────────────────────────
401
402#[derive(Serialize, Default)]
403struct GetMyDefaultAdministratorRightsParams {
404    #[serde(skip_serializing_if = "Option::is_none")]
405    for_channels: Option<bool>,
406}
407
408/// Builder for the [`getMyDefaultAdministratorRights`](https://core.telegram.org/bots/api#getmydefaultadministratorrights) method.
409pub struct GetMyDefaultAdministratorRights {
410    client: BotClient,
411    params: GetMyDefaultAdministratorRightsParams,
412}
413
414impl GetMyDefaultAdministratorRights {
415    pub(crate) fn new(client: BotClient) -> Self {
416        Self {
417            client,
418            params: Default::default(),
419        }
420    }
421    /// Pass `true` to get default administrator rights for channels;
422    /// otherwise returns defaults for groups and supergroups.
423    pub fn for_channels(mut self, v: bool) -> Self {
424        self.params.for_channels = Some(v);
425        self
426    }
427}
428
429impl_into_future!(
430    GetMyDefaultAdministratorRights,
431    ChatAdministratorRights,
432    "getMyDefaultAdministratorRights"
433);
434
435// ─── getChatMenuButton ────────────────────────────────────────────────────────
436
437#[derive(Serialize, Default)]
438struct GetChatMenuButtonParams {
439    #[serde(skip_serializing_if = "Option::is_none")]
440    chat_id: Option<ChatId>,
441}
442
443/// Builder for the [`getChatMenuButton`](https://core.telegram.org/bots/api#getchatmenubutton) method.
444pub struct GetChatMenuButton {
445    client: BotClient,
446    params: GetChatMenuButtonParams,
447}
448
449impl GetChatMenuButton {
450    pub(crate) fn new(client: BotClient) -> Self {
451        Self {
452            client,
453            params: Default::default(),
454        }
455    }
456    /// Restricts the menu button query to a specific private chat.
457    pub fn chat_id(mut self, id: impl Into<ChatId>) -> Self {
458        self.params.chat_id = Some(id.into());
459        self
460    }
461}
462
463impl_into_future!(GetChatMenuButton, MenuButton, "getChatMenuButton");
464
465// ─── setChatMenuButton ────────────────────────────────────────────────────────
466
467#[derive(Serialize, Default)]
468struct SetChatMenuButtonParams {
469    #[serde(skip_serializing_if = "Option::is_none")]
470    chat_id: Option<i64>,
471    #[serde(skip_serializing_if = "Option::is_none")]
472    menu_button: Option<MenuButton>,
473}
474
475/// Builder for the [`setChatMenuButton`](https://core.telegram.org/bots/api#setchatmenubutton) method.
476///
477/// Changes the bot's menu button in a private chat, or the default menu button.
478/// Omit `chat_id` to change the default; omit `menu_button` to reset to `MenuButtonDefault`.
479pub struct SetChatMenuButton {
480    client: BotClient,
481    params: SetChatMenuButtonParams,
482}
483
484impl SetChatMenuButton {
485    pub(crate) fn new(client: BotClient) -> Self {
486        Self {
487            client,
488            params: Default::default(),
489        }
490    }
491    /// Targets a specific private chat. Omit to change the default menu button.
492    pub fn chat_id(mut self, id: i64) -> Self {
493        self.params.chat_id = Some(id);
494        self
495    }
496    /// Sets the new menu button. Omit to reset to `MenuButtonDefault`.
497    pub fn menu_button(mut self, btn: MenuButton) -> Self {
498        self.params.menu_button = Some(btn);
499        self
500    }
501}
502
503impl_into_future!(SetChatMenuButton, bool, "setChatMenuButton");
504
505// ─── logOut ───────────────────────────────────────────────────────────────────
506
507/// Builder for the [`logOut`](https://core.telegram.org/bots/api#logout) method.
508///
509/// Logs out from the cloud Bot API server. Must be called before running the
510/// bot locally. After a successful call the bot cannot log back in to the cloud
511/// server for 10 minutes.
512pub struct LogOut {
513    client: BotClient,
514}
515
516impl LogOut {
517    pub(crate) fn new(client: BotClient) -> Self {
518        Self { client }
519    }
520}
521
522impl IntoFuture for LogOut {
523    type Output = Result<bool>;
524    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
525
526    fn into_future(self) -> Self::IntoFuture {
527        Box::pin(async move {
528            self.client
529                .post_json("logOut", &serde_json::json!({}))
530                .await
531        })
532    }
533}
534
535// ─── close ────────────────────────────────────────────────────────────────────
536
537/// Builder for the [`close`](https://core.telegram.org/bots/api#close) method.
538///
539/// Closes the bot instance before moving it to another local server. Delete
540/// the webhook before calling this to prevent the bot from restarting.
541/// Returns error 429 in the first 10 minutes after launch.
542pub struct Close {
543    client: BotClient,
544}
545
546impl Close {
547    pub(crate) fn new(client: BotClient) -> Self {
548        Self { client }
549    }
550}
551
552impl IntoFuture for Close {
553    type Output = Result<bool>;
554    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
555
556    fn into_future(self) -> Self::IntoFuture {
557        Box::pin(async move { self.client.post_json("close", &serde_json::json!({})).await })
558    }
559}
560
561// ─── setMyProfilePhoto ────────────────────────────────────────────────────────
562
563/// Builder for the [`setMyProfilePhoto`](https://core.telegram.org/bots/api#setmyprofilephoto) method (Bot API 9.4).
564///
565/// Changes the profile photo of the bot. The photo must be uploaded via
566/// multipart/form-data as an `InputProfilePhoto`.
567pub struct SetMyProfilePhoto {
568    client: BotClient,
569    /// The serialised `InputProfilePhoto` JSON sent as the `photo` field.
570    photo_json: String,
571}
572
573impl SetMyProfilePhoto {
574    /// Creates a new builder from a pre-serialised `InputProfilePhoto` value.
575    ///
576    /// Pass the result of `serde_json::to_string(&input_profile_photo)`.
577    pub(crate) fn new(client: BotClient, photo_json: String) -> Self {
578        Self { client, photo_json }
579    }
580}
581
582impl IntoFuture for SetMyProfilePhoto {
583    type Output = Result<bool>;
584    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
585
586    fn into_future(self) -> Self::IntoFuture {
587        Box::pin(async move {
588            let part = Part::text(self.photo_json)
589                .mime_str("application/json")
590                .map_err(|e| crate::error::Error::Decode(e.to_string()))?;
591            let form = Form::new().part("photo", part);
592            self.client.post_multipart("setMyProfilePhoto", form).await
593        })
594    }
595}
596
597// ─── removeMyProfilePhoto ─────────────────────────────────────────────────────
598
599/// Builder for the [`removeMyProfilePhoto`](https://core.telegram.org/bots/api#removemyprofilephoto) method (Bot API 9.4).
600///
601/// Removes the current profile photo of the bot. Requires no parameters.
602pub struct RemoveMyProfilePhoto {
603    client: BotClient,
604}
605
606impl RemoveMyProfilePhoto {
607    pub(crate) fn new(client: BotClient) -> Self {
608        Self { client }
609    }
610}
611
612impl IntoFuture for RemoveMyProfilePhoto {
613    type Output = Result<bool>;
614    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
615
616    fn into_future(self) -> Self::IntoFuture {
617        Box::pin(async move {
618            self.client
619                .post_json("removeMyProfilePhoto", &serde_json::json!({}))
620                .await
621        })
622    }
623}
624
625// ─── replaceManagedBotToken ───────────────────────────────────────────────────
626
627#[derive(Serialize)]
628struct ReplaceManagedBotTokenParams {
629    user_id: i64,
630}
631
632/// Builder for the [`replaceManagedBotToken`](https://core.telegram.org/bots/api#replacemanagedbottoken) method (Bot API 9.6).
633///
634/// Revokes the current token of a managed bot and generates a new one.
635/// Returns the new token as a `String`.
636pub struct ReplaceManagedBotToken {
637    client: BotClient,
638    params: ReplaceManagedBotTokenParams,
639}
640
641impl ReplaceManagedBotToken {
642    pub(crate) fn new(client: BotClient, user_id: i64) -> Self {
643        Self {
644            client,
645            params: ReplaceManagedBotTokenParams { user_id },
646        }
647    }
648}
649
650impl_into_future!(ReplaceManagedBotToken, String, "replaceManagedBotToken");
651
652// ─── getManagedBotToken ───────────────────────────────────────────────────────
653
654#[derive(Serialize)]
655struct GetManagedBotTokenParams {
656    user_id: i64,
657}
658
659/// Builder for the [`getManagedBotToken`](https://core.telegram.org/bots/api#getmanagedbottoken) method (Bot API 9.6).
660pub struct GetManagedBotToken {
661    client: BotClient,
662    params: GetManagedBotTokenParams,
663}
664
665impl GetManagedBotToken {
666    pub(crate) fn new(client: BotClient, user_id: i64) -> Self {
667        Self {
668            client,
669            params: GetManagedBotTokenParams { user_id },
670        }
671    }
672}
673
674impl_into_future!(GetManagedBotToken, String, "getManagedBotToken");