tgbot/types/definitions/sticker/
set.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    api::{Form, Method, Payload},
5    types::{
6        InputFile,
7        InputSticker,
8        InputStickerError,
9        InputStickers,
10        Integer,
11        PhotoSize,
12        Sticker,
13        StickerFormat,
14        StickerType,
15    },
16};
17
18/// Represents a sticker set.
19#[serde_with::skip_serializing_none]
20#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
21pub struct StickerSet {
22    /// Name of the sticker set.
23    pub name: String,
24    /// Type of stickers.
25    pub sticker_type: StickerType,
26    /// List of stickers.
27    pub stickers: Vec<Sticker>,
28    /// Title of the sticker set.
29    pub title: String,
30    /// Sticker set thumbnail in the WEBP or TGS format.
31    pub thumbnail: Option<PhotoSize>,
32}
33
34impl StickerSet {
35    /// Creates a new `StickerSet`.
36    ///
37    /// # Arguments
38    ///
39    /// * `name` - Name of the sticker set.
40    /// * `sticker_type` - Type of stickers.
41    /// * `stickers` - List of stickers.
42    /// * `title` - Title of the sticker set.
43    pub fn new<A, B, C>(name: A, sticker_type: StickerType, stickers: C, title: B) -> Self
44    where
45        A: Into<String>,
46        B: Into<String>,
47        C: IntoIterator<Item = Sticker>,
48    {
49        Self {
50            name: name.into(),
51            sticker_type,
52            stickers: stickers.into_iter().collect(),
53            title: title.into(),
54            thumbnail: None,
55        }
56    }
57
58    /// Sets a new thumbnail.
59    ///
60    /// # Arguments
61    ///
62    /// * `value` - Thumbnail.
63    pub fn with_thumbnail(mut self, value: PhotoSize) -> Self {
64        self.thumbnail = Some(value);
65        self
66    }
67}
68
69/// Adds a new sticker to a set created by the bot.
70///
71/// The format of the added sticker must match the format of the other stickers in the set.
72/// Emoji sticker sets can have up to 200 stickers.
73/// Animated and video sticker sets can have up to 50 stickers.
74/// Static sticker sets can have up to 120 stickers.
75#[derive(Debug)]
76pub struct AddStickerToSet {
77    form: Form,
78}
79
80impl AddStickerToSet {
81    /// Creates a new `AddStickerToSet`.
82    ///
83    /// # Arguments
84    ///
85    /// * `user_id` - User identifier of sticker set owner.
86    /// * `name` - Sticker set name.
87    /// * `sticker` - Sticker file.
88    pub fn new<T>(user_id: Integer, name: T, sticker: InputSticker) -> Result<Self, InputStickerError>
89    where
90        T: Into<String>,
91    {
92        let mut form: Form = sticker.try_into()?;
93        form.insert_field("user_id", user_id);
94        form.insert_field("name", name.into());
95        Ok(Self { form })
96    }
97}
98
99impl Method for AddStickerToSet {
100    type Response = bool;
101
102    fn into_payload(self) -> Payload {
103        Payload::form("addStickerToSet", self.form)
104    }
105}
106
107/// Creates a new sticker set owned by a user.
108///
109/// The bot will be able to edit the created sticker set.
110#[derive(Debug)]
111pub struct CreateNewStickerSet {
112    form: Form,
113}
114
115impl CreateNewStickerSet {
116    /// Creates a new `CreateNewStickerSet`.
117    ///
118    /// # Arguments
119    ///
120    /// * `user_id` - User identifier of created sticker set owner.
121    /// * `name` - Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., animals);
122    ///   can contain only english letters, digits and underscores;
123    ///   must begin with a letter, can't contain consecutive underscores
124    ///   and must end in `_by_<bot username>`;
125    ///   <bot_username> is case insensitive;
126    ///   1-64 characters.
127    /// * `title` - Sticker set title; 1-64 characters.
128    /// * `stickers` - A list of 1-50 initial stickers to be added to the sticker set.
129    pub fn new<A, B>(user_id: Integer, name: A, title: B, stickers: InputStickers) -> Result<Self, InputStickerError>
130    where
131        A: Into<String>,
132        B: Into<String>,
133    {
134        let mut form: Form = stickers.try_into()?;
135        form.insert_field("user_id", user_id);
136        form.insert_field("name", name.into());
137        form.insert_field("title", title.into());
138        Ok(Self { form })
139    }
140
141    /// Sets a new value for the `needs_repainting` flag.
142    ///
143    /// # Arguments
144    ///
145    /// * `value` - Indicates whether stickers in the sticker set must be repainted to the color
146    ///   of text when used in messages, the accent color if used as emoji status,
147    ///   white on chat photos, or another appropriate color based on context;
148    ///   for custom emoji sticker sets only.
149    pub fn with_needs_repainting(mut self, value: bool) -> Self {
150        self.form.insert_field("needs_repainting", value);
151        self
152    }
153
154    /// Sets a new sticker type.
155    ///
156    /// # Arguments
157    ///
158    /// * `value` - Type of stickers in the set.
159    ///
160    /// By default, a regular sticker set is created.
161    pub fn with_sticker_type(mut self, value: StickerType) -> Self {
162        self.form.insert_field("sticker_type", value.as_ref());
163        self
164    }
165}
166
167impl Method for CreateNewStickerSet {
168    type Response = bool;
169
170    fn into_payload(self) -> Payload {
171        Payload::form("createNewStickerSet", self.form)
172    }
173}
174
175/// Deletes a sticker from a set created by the bot.
176#[derive(Clone, Debug, Serialize)]
177pub struct DeleteStickerFromSet {
178    sticker: String,
179}
180
181impl DeleteStickerFromSet {
182    /// Creates a new `DeleteStickerFromSet`.
183    ///
184    /// # Arguments
185    ///
186    /// * `sticker` - File identifier of the sticker.
187    pub fn new<T>(sticker: T) -> Self
188    where
189        T: Into<String>,
190    {
191        Self {
192            sticker: sticker.into(),
193        }
194    }
195}
196
197impl Method for DeleteStickerFromSet {
198    type Response = bool;
199
200    fn into_payload(self) -> Payload {
201        Payload::json("deleteStickerFromSet", self)
202    }
203}
204
205/// Deletes a sticker set that was created by the bot.
206#[derive(Clone, Debug, Serialize)]
207pub struct DeleteStickerSet {
208    name: String,
209}
210
211impl DeleteStickerSet {
212    /// Creates a new `DeleteStickerSet`.
213    ///
214    /// # Arguments
215    ///
216    /// * `name` - Sticker set name.
217    pub fn new<T>(name: T) -> Self
218    where
219        T: Into<String>,
220    {
221        Self { name: name.into() }
222    }
223}
224
225impl Method for DeleteStickerSet {
226    type Response = bool;
227
228    fn into_payload(self) -> Payload {
229        Payload::json("deleteStickerSet", self)
230    }
231}
232
233/// Returns a sticker set.
234#[derive(Clone, Debug, Serialize)]
235pub struct GetStickerSet {
236    name: String,
237}
238
239impl GetStickerSet {
240    /// Creates a new `GetStickerSet`.
241    ///
242    /// # Arguments
243    ///
244    /// * `name` - Name of the sticker set.
245    pub fn new<T>(name: T) -> Self
246    where
247        T: Into<String>,
248    {
249        Self { name: name.into() }
250    }
251}
252
253impl Method for GetStickerSet {
254    type Response = StickerSet;
255
256    fn into_payload(self) -> Payload {
257        Payload::json("getStickerSet", self)
258    }
259}
260
261/// Replaces an existing sticker in a sticker set with a new one.
262///
263/// The method is equivalent to calling [`crate::types::DeleteStickerFromSet`],
264/// then [`crate::types::AddStickerToSet`],
265/// then [`crate::types::SetStickerPositionInSet`].
266#[derive(Debug)]
267pub struct ReplaceStickerInSet {
268    form: Form,
269}
270
271impl ReplaceStickerInSet {
272    /// Creates a new `ReplaceStickerInSet`.
273    ///
274    /// # Arguments
275    ///
276    /// * `name` - Sticker set name.
277    /// * `old_sticker` - File identifier of the replaced sticker.
278    /// * `sticker` -  Information about the added sticker;
279    ///   if exactly the same sticker had already been added to the set, then the set remains unchanged.
280    /// * `user_id` - User identifier of the sticker set owner.
281    pub fn new<A, B>(
282        name: A,
283        old_sticker: B,
284        sticker: InputSticker,
285        user_id: Integer,
286    ) -> Result<Self, InputStickerError>
287    where
288        A: Into<String>,
289        B: Into<String>,
290    {
291        let mut form: Form = sticker.try_into()?;
292        form.insert_field("name", name.into());
293        form.insert_field("old_sticker", old_sticker.into());
294        form.insert_field("user_id", user_id);
295        Ok(Self { form })
296    }
297}
298
299impl Method for ReplaceStickerInSet {
300    type Response = bool;
301
302    fn into_payload(self) -> Payload {
303        Payload::form("replaceStickerInSet", self.form)
304    }
305}
306
307/// Sets the thumbnail of a custom emoji sticker set.
308#[serde_with::skip_serializing_none]
309#[derive(Clone, Debug, Serialize)]
310pub struct SetCustomEmojiStickerSetThumbnail {
311    name: String,
312    custom_emoji_id: Option<String>,
313}
314
315impl SetCustomEmojiStickerSetThumbnail {
316    /// Creates a new `SetCustomEmojiStickerSetThumbnail`.
317    ///
318    /// # Arguments
319    ///
320    /// * `name` - Sticker set name.
321    pub fn new<T>(name: T) -> Self
322    where
323        T: Into<String>,
324    {
325        Self {
326            name: name.into(),
327            custom_emoji_id: None,
328        }
329    }
330
331    /// Sets a new custom emoji ID.
332    ///
333    /// # Arguments
334    ///
335    /// * `value` - Custom emoji identifier of a sticker from the sticker set.
336    ///
337    /// Pass an empty string to drop the thumbnail and use the first sticker as the thumbnail.
338    pub fn with_custom_emoji_id<T>(mut self, value: T) -> Self
339    where
340        T: Into<String>,
341    {
342        self.custom_emoji_id = Some(value.into());
343        self
344    }
345}
346
347impl Method for SetCustomEmojiStickerSetThumbnail {
348    type Response = bool;
349
350    fn into_payload(self) -> Payload {
351        Payload::json("setCustomEmojiStickerSetThumbnail", self)
352    }
353}
354
355/// Moves a sticker in a set created by the bot to a specific position.
356#[derive(Clone, Debug, Serialize)]
357pub struct SetStickerPositionInSet {
358    position: Integer,
359    sticker: String,
360}
361
362impl SetStickerPositionInSet {
363    /// Creates a new `SetStickerPositionInSet`.
364    ///
365    /// # Arguments
366    ///
367    /// * `position` - New sticker position in the set, zero-based.
368    /// * `sticker` - File identifier of the sticker.
369    pub fn new<T>(position: Integer, sticker: T) -> Self
370    where
371        T: Into<String>,
372    {
373        Self {
374            position,
375            sticker: sticker.into(),
376        }
377    }
378}
379
380impl Method for SetStickerPositionInSet {
381    type Response = bool;
382
383    fn into_payload(self) -> Payload {
384        Payload::json("setStickerPositionInSet", self)
385    }
386}
387
388/// Sets a title of a created sticker set.
389#[derive(Clone, Debug, Serialize)]
390pub struct SetStickerSetTitle {
391    name: String,
392    title: String,
393}
394
395impl SetStickerSetTitle {
396    /// Creates a new `SetStickerSetTitle`.
397    ///
398    /// # Arguments
399    ///
400    /// * `name` - Sticker set name.
401    /// * `title` - Sticker set title; 1-64 characters.
402    pub fn new<A, B>(name: A, title: B) -> Self
403    where
404        A: Into<String>,
405        B: Into<String>,
406    {
407        Self {
408            name: name.into(),
409            title: title.into(),
410        }
411    }
412}
413
414impl Method for SetStickerSetTitle {
415    type Response = bool;
416
417    fn into_payload(self) -> Payload {
418        Payload::json("setStickerSetTitle", self)
419    }
420}
421
422/// Sets a thumbnail of a sticker set.
423#[derive(Debug)]
424pub struct SetStickerSetThumbnail {
425    form: Form,
426}
427
428impl SetStickerSetThumbnail {
429    /// Creates a new `SetStickerSetThumbnail`.
430    ///
431    /// # Arguments
432    ///
433    /// * `name` - Sticker set name.
434    /// * `user_id` - User identifier of the sticker set owner.
435    /// * `format` - Format of the thumbnail.
436    pub fn new<N>(name: N, user_id: Integer, format: StickerFormat) -> Self
437    where
438        N: Into<String>,
439    {
440        Self {
441            form: Form::from([
442                ("name", name.into().into()),
443                ("user_id", user_id.into()),
444                ("format", format.as_ref().into()),
445            ]),
446        }
447    }
448
449    /// Sets a new thumbnail.
450    ///
451    /// # Arguments
452    ///
453    /// * `value` - A WEBP or PNG image with the thumbnail.
454    ///
455    /// Must be up to 128 kilobytes in size and have a width and height of exactly 100px,
456    /// or a .TGS animation with a thumbnail up to 32 kilobytes in size
457    /// (see <https://core.telegram.org/stickers#animated-sticker-requirements> for animated sticker
458    /// technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size;
459    /// see <https://core.telegram.org/stickers#video-sticker-requirements> for video sticker
460    /// technical requirements.
461    ///
462    /// Animated and video sticker set thumbnails can't be uploaded via HTTP URL.
463    /// If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail.
464    pub fn with_thumbnail<T>(mut self, value: T) -> Self
465    where
466        T: Into<InputFile>,
467    {
468        self.form.insert_field("thumbnail", value.into());
469        self
470    }
471}
472
473impl Method for SetStickerSetThumbnail {
474    type Response = bool;
475
476    fn into_payload(self) -> Payload {
477        Payload::form("setStickerSetThumbnail", self.form)
478    }
479}