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