tgbot/types/forum/
mod.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    api::{Method, Payload},
5    types::{ChatId, ForumTopicIconColor, Integer, Sticker},
6};
7
8#[cfg(test)]
9mod tests;
10
11/// Represents a forum topic.
12#[serde_with::skip_serializing_none]
13#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
14pub struct ForumTopic {
15    /// Color of the icon.
16    pub icon_color: ForumTopicIconColor,
17    /// Unique identifier.
18    pub message_thread_id: Integer,
19    /// Name.
20    pub name: String,
21    /// Unique identifier of the custom emoji shown as the topic icon.
22    pub icon_custom_emoji_id: Option<String>,
23}
24
25impl ForumTopic {
26    /// Creates a new `ForumTopic`.
27    ///
28    /// # Arguments
29    ///
30    /// * `icon_color` - Color of the icon.
31    /// * `message_thread_id` - Unique identifier of the topic.
32    /// * `name` - Name of the topic.
33    pub fn new<A, B>(icon_color: A, message_thread_id: Integer, name: B) -> Self
34    where
35        A: Into<ForumTopicIconColor>,
36        B: Into<String>,
37    {
38        Self {
39            icon_color: icon_color.into(),
40            message_thread_id,
41            name: name.into(),
42            icon_custom_emoji_id: None,
43        }
44    }
45
46    /// Sets a new icon custom emoji ID.
47    ///
48    /// # Arguments
49    ///
50    /// * `value` - Emoji ID.
51    pub fn with_icon_custom_emoji_id<T>(mut self, value: T) -> Self
52    where
53        T: Into<String>,
54    {
55        self.icon_custom_emoji_id = Some(value.into());
56        self
57    }
58}
59
60/// Closes an open topic in a forum supergroup chat.
61///
62/// The bot must be an administrator in the chat for this to work
63/// and must have the `can_manage_topics` administrator rights,
64/// unless it is the creator of the topic.
65#[derive(Clone, Debug, Serialize)]
66pub struct CloseForumTopic {
67    chat_id: ChatId,
68    message_thread_id: Integer,
69}
70
71impl CloseForumTopic {
72    /// Creates a new `CloseForumTopic`.
73    ///
74    /// # Arguments
75    ///
76    /// * `chat_id` - Unique identifier of the target chat.
77    /// * `message_thread_id` - Unique identifier of the target message thread of the forum topic.
78    pub fn new<T>(chat_id: T, message_thread_id: Integer) -> Self
79    where
80        T: Into<ChatId>,
81    {
82        Self {
83            chat_id: chat_id.into(),
84            message_thread_id,
85        }
86    }
87}
88
89impl Method for CloseForumTopic {
90    type Response = bool;
91
92    fn into_payload(self) -> Payload {
93        Payload::json("closeForumTopic", self)
94    }
95}
96
97/// Creates a topic in a forum supergroup chat.
98///
99/// The bot must be an administrator in the chat for this to work
100/// and must have the can_manage_topics administrator rights.
101#[serde_with::skip_serializing_none]
102#[derive(Clone, Debug, Serialize)]
103pub struct CreateForumTopic {
104    chat_id: ChatId,
105    name: String,
106    icon_color: Option<ForumTopicIconColor>,
107    icon_custom_emoji_id: Option<String>,
108}
109
110impl CreateForumTopic {
111    /// Creates a new `CreateForumTopic`.
112    ///
113    /// # Arguments
114    ///
115    /// * `chat_id` - Unique identifier of the target chat.
116    /// * `name` - Topic name; 1 - 128 characters.
117    pub fn new<A, B>(chat_id: A, name: B) -> Self
118    where
119        A: Into<ChatId>,
120        B: Into<String>,
121    {
122        Self {
123            chat_id: chat_id.into(),
124            name: name.into(),
125            icon_color: None,
126            icon_custom_emoji_id: None,
127        }
128    }
129
130    /// Sets a new color of the topic icon.
131    ///
132    /// # Arguments
133    ///
134    /// * `value` - Color of the topic icon.
135    pub fn with_icon_color(mut self, value: ForumTopicIconColor) -> Self {
136        self.icon_color = Some(value);
137        self
138    }
139
140    /// Sets a new icon custom emoji ID.
141    ///
142    /// # Arguments
143    ///
144    /// * `value` - Unique identifier of the custom emoji shown as the topic icon.
145    ///
146    /// Use [`GetForumTopicIconStickers`] to get all allowed custom emoji identifiers.
147    pub fn with_icon_custom_emoji_id<T>(mut self, value: T) -> Self
148    where
149        T: Into<String>,
150    {
151        self.icon_custom_emoji_id = Some(value.into());
152        self
153    }
154}
155
156impl Method for CreateForumTopic {
157    type Response = ForumTopic;
158
159    fn into_payload(self) -> Payload {
160        Payload::json("createForumTopic", self)
161    }
162}
163
164/// Closes an opened 'General' topic in a forum supergroup chat.
165///
166/// The bot must be an administrator in the chat for this to work
167/// and must have the can_manage_topics administrator rights.
168#[derive(Clone, Debug, Serialize)]
169pub struct CloseGeneralForumTopic {
170    chat_id: ChatId,
171}
172
173impl CloseGeneralForumTopic {
174    /// Creates a new `CloseGeneralForumTopic`.
175    ///
176    /// # Arguments
177    ///
178    /// * `chat_id` - Unique identifier of the target chat.
179    pub fn new<T>(chat_id: T) -> Self
180    where
181        T: Into<ChatId>,
182    {
183        Self {
184            chat_id: chat_id.into(),
185        }
186    }
187}
188
189impl Method for CloseGeneralForumTopic {
190    type Response = bool;
191
192    fn into_payload(self) -> Payload {
193        Payload::json("closeGeneralForumTopic", self)
194    }
195}
196
197/// Deletes a forum topic along with all its messages in a forum supergroup chat.
198///
199/// The bot must be an administrator in the chat for this to work
200/// and must have the can_delete_messages administrator rights.
201#[derive(Clone, Debug, Serialize)]
202pub struct DeleteForumTopic {
203    chat_id: ChatId,
204    message_thread_id: Integer,
205}
206
207impl DeleteForumTopic {
208    /// Creates a new `DeleteForumTopic`.
209    ///
210    /// # Arguments
211    ///
212    /// * `chat_id` - Unique identifier of the target chat.
213    /// * `message_thread_id` - Unique identifier of the target message thread of the forum topic.
214    pub fn new<T>(chat_id: T, message_thread_id: Integer) -> Self
215    where
216        T: Into<ChatId>,
217    {
218        Self {
219            chat_id: chat_id.into(),
220            message_thread_id,
221        }
222    }
223}
224
225impl Method for DeleteForumTopic {
226    type Response = bool;
227
228    fn into_payload(self) -> Payload {
229        Payload::json("deleteForumTopic", self)
230    }
231}
232
233/// Changes name and icon of a topic in a forum supergroup chat.
234///
235/// The bot must be an administrator in the chat for this to work
236/// and must have can_manage_topics administrator rights,
237/// unless it is the creator of the topic.
238#[serde_with::skip_serializing_none]
239#[derive(Clone, Debug, Serialize)]
240pub struct EditForumTopic {
241    chat_id: ChatId,
242    message_thread_id: Integer,
243    icon_custom_emoji_id: Option<String>,
244    name: Option<String>,
245}
246
247impl EditForumTopic {
248    /// Creates a new `EditForumTopic`.
249    ///
250    /// # Arguments
251    ///
252    /// * `chat_id` - Unique identifier of the target.
253    /// * `message_thread_id` - Unique identifier of the target message thread of the forum topic.
254    pub fn new<C>(chat_id: C, message_thread_id: Integer) -> Self
255    where
256        C: Into<ChatId>,
257    {
258        Self {
259            chat_id: chat_id.into(),
260            message_thread_id,
261            icon_custom_emoji_id: None,
262            name: None,
263        }
264    }
265
266    /// Sets a new icon custom emoji ID.
267    ///
268    /// # Arguments
269    ///
270    /// * `value` - New unique identifier of the custom emoji shown as the topic icon.
271    ///
272    /// Use [`GetForumTopicIconStickers`] to get all allowed custom emoji identifiers.
273    /// Pass an empty string to remove the icon.
274    /// If not specified, the current icon will be kept.
275    pub fn with_icon_custom_emoji_id<T>(mut self, value: T) -> Self
276    where
277        T: Into<String>,
278    {
279        self.icon_custom_emoji_id = Some(value.into());
280        self
281    }
282
283    /// Sets a new name.
284    ///
285    /// # Arguments
286    ///
287    /// * `value` - New topic name; 0-128 characters.
288    ///
289    /// If not specified or empty, the current name of the topic will be kept.
290    pub fn with_name<T>(mut self, value: T) -> Self
291    where
292        T: Into<String>,
293    {
294        self.name = Some(value.into());
295        self
296    }
297}
298
299impl Method for EditForumTopic {
300    type Response = bool;
301
302    fn into_payload(self) -> Payload {
303        Payload::json("editForumTopic", self)
304    }
305}
306
307/// Changes the name of the 'General' topic in a forum supergroup chat.
308///
309/// The bot must be an administrator in the chat for this to work
310/// and must have `can_manage_topics` administrator rights.
311#[derive(Clone, Debug, Serialize)]
312pub struct EditGeneralForumTopic {
313    chat_id: ChatId,
314    name: String,
315}
316
317impl EditGeneralForumTopic {
318    /// Creates a new `EditGeneralForumTopic`.
319    ///
320    /// # Arguments
321    ///
322    /// * `chat_id` - Unique identifier for the target chat.
323    /// * `name` - New topic name, 1-128 characters.
324    pub fn new<A, B>(chat_id: A, name: B) -> Self
325    where
326        A: Into<ChatId>,
327        B: Into<String>,
328    {
329        Self {
330            chat_id: chat_id.into(),
331            name: name.into(),
332        }
333    }
334}
335
336impl Method for EditGeneralForumTopic {
337    type Response = bool;
338
339    fn into_payload(self) -> Payload {
340        Payload::json("editGeneralForumTopic", self)
341    }
342}
343
344/// Returns custom emoji stickers, which can be used as a forum topic icon by any user.
345#[derive(Clone, Copy, Debug)]
346pub struct GetForumTopicIconStickers;
347
348impl Method for GetForumTopicIconStickers {
349    type Response = Vec<Sticker>;
350
351    fn into_payload(self) -> Payload {
352        Payload::empty("getForumTopicIconStickers")
353    }
354}
355
356/// Hides the 'General' topic in a forum supergroup chat.
357///
358/// The bot must be an administrator in the chat for this to work
359/// and must have the `can_manage_topics` administrator rights.
360/// The topic will be automatically closed if it was open.
361#[derive(Clone, Debug, Serialize)]
362pub struct HideGeneralForumTopic {
363    chat_id: ChatId,
364}
365
366impl HideGeneralForumTopic {
367    /// Creates a new `HideGeneralForumTopic`.
368    ///
369    /// # Arguments
370    ///
371    /// * `chat_id` - Unique identifier for the target chat.
372    pub fn new<T>(chat_id: T) -> Self
373    where
374        T: Into<ChatId>,
375    {
376        Self {
377            chat_id: chat_id.into(),
378        }
379    }
380}
381
382impl Method for HideGeneralForumTopic {
383    type Response = bool;
384
385    fn into_payload(self) -> Payload {
386        Payload::json("hideGeneralForumTopic", self)
387    }
388}
389
390/// Reopens a closed topic in a forum supergroup chat.
391///
392/// The bot must be an administrator in the chat for this to work
393/// and must have the `can_manage_topics` administrator rights,
394/// unless it is the creator of the topic.
395#[derive(Clone, Debug, Serialize)]
396pub struct ReopenForumTopic {
397    chat_id: ChatId,
398    message_thread_id: Integer,
399}
400
401impl ReopenForumTopic {
402    /// Creates a new `ReopenForumTopic`.
403    ///
404    /// # Arguments
405    ///
406    /// * `chat_id` - Unique identifier of the target chat.
407    /// * `message_thread_id` - Unique identifier of the target message thread of the forum topic.
408    pub fn new<T>(chat_id: T, message_thread_id: Integer) -> Self
409    where
410        T: Into<ChatId>,
411    {
412        Self {
413            chat_id: chat_id.into(),
414            message_thread_id,
415        }
416    }
417}
418
419impl Method for ReopenForumTopic {
420    type Response = bool;
421
422    fn into_payload(self) -> Payload {
423        Payload::json("reopenForumTopic", self)
424    }
425}
426
427/// Reopens a closed 'General' topic in a forum supergroup chat.
428///
429/// The bot must be an administrator in the chat for this to work
430/// and must have the `can_manage_topics` administrator rights.
431/// The topic will be automatically unhidden if it was hidden.
432#[derive(Clone, Debug, Serialize)]
433pub struct ReopenGeneralForumTopic {
434    chat_id: ChatId,
435}
436
437impl ReopenGeneralForumTopic {
438    /// Creates a new `ReopenGeneralForumTopic`.
439    ///
440    /// # Arguments
441    ///
442    /// * `chat_id` - Unique identifier of the target chat.
443    pub fn new<T>(chat_id: T) -> Self
444    where
445        T: Into<ChatId>,
446    {
447        Self {
448            chat_id: chat_id.into(),
449        }
450    }
451}
452
453impl Method for ReopenGeneralForumTopic {
454    type Response = bool;
455
456    fn into_payload(self) -> Payload {
457        Payload::json("reopenGeneralForumTopic", self)
458    }
459}
460
461/// Reveals the 'General' topic in a forum supergroup chat.
462///
463/// The bot must be an administrator in the chat for this to work
464/// and must have the `can_manage_topics` administrator rights.
465#[derive(Clone, Debug, Serialize)]
466pub struct UnhideGeneralForumTopic {
467    chat_id: ChatId,
468}
469
470impl UnhideGeneralForumTopic {
471    /// Creates a new `UnhideGeneralForumTopic`.
472    ///
473    /// # Arguments
474    ///
475    /// * `chat_id` - Unique identifier of the target chat.
476    pub fn new<T>(chat_id: T) -> Self
477    where
478        T: Into<ChatId>,
479    {
480        Self {
481            chat_id: chat_id.into(),
482        }
483    }
484}
485
486impl Method for UnhideGeneralForumTopic {
487    type Response = bool;
488
489    fn into_payload(self) -> Payload {
490        Payload::json("unhideGeneralForumTopic", self)
491    }
492}
493
494/// Clears the list of pinned messages in a forum topic.
495///
496/// The bot must be an administrator in the chat for this to work
497/// and must have the `can_pin_messages` administrator right in the supergroup.
498#[derive(Clone, Debug, Serialize)]
499pub struct UnpinAllForumTopicMessages {
500    chat_id: ChatId,
501    message_thread_id: Integer,
502}
503
504impl UnpinAllForumTopicMessages {
505    /// Creates a new `UnpinAllForumTopicMessages`.
506    ///
507    /// # Arguments
508    ///
509    /// * `chat_id` - Unique identifier of the target chat.
510    /// * `message_thread_id` - Unique identifier of the target message thread of the forum topic.
511    pub fn new<T>(chat_id: T, message_thread_id: Integer) -> Self
512    where
513        T: Into<ChatId>,
514    {
515        Self {
516            chat_id: chat_id.into(),
517            message_thread_id,
518        }
519    }
520}
521
522impl Method for UnpinAllForumTopicMessages {
523    type Response = bool;
524
525    fn into_payload(self) -> Payload {
526        Payload::json("unpinAllForumTopicMessages", self)
527    }
528}
529
530/// Clears the list of pinned messages in a General forum topic.
531///
532/// The bot must be an administrator in the chat for this to work
533/// and must have the `can_pin_messages` administrator right in the supergroup.
534#[derive(Clone, Debug, Serialize)]
535pub struct UnpinAllGeneralForumTopicMessages {
536    chat_id: ChatId,
537}
538
539impl UnpinAllGeneralForumTopicMessages {
540    /// Creates a new `UnpinAllGeneralForumTopicMessages`.
541    ///
542    /// # Arguments
543    ///
544    /// * `chat_id` - Unique identifier of the target chat.
545    pub fn new<T>(chat_id: T) -> Self
546    where
547        T: Into<ChatId>,
548    {
549        Self {
550            chat_id: chat_id.into(),
551        }
552    }
553}
554
555impl Method for UnpinAllGeneralForumTopicMessages {
556    type Response = bool;
557
558    fn into_payload(self) -> Payload {
559        Payload::json("unpinAllGeneralForumTopicMessages", self)
560    }
561}