Skip to main content

rustigram_types/
sticker.rs

1use crate::file::PhotoSize;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5/// A Telegram sticker.
6pub struct Sticker {
7    /// Telegram file identifier.
8    pub file_id: String,
9    /// Unique file identifier, stable across bots and time.
10    pub file_unique_id: String,
11    /// Sticker type.
12    #[serde(rename = "type")]
13    pub kind: StickerType,
14    /// Sticker width in pixels.
15    pub width: u32,
16    /// Sticker height in pixels.
17    pub height: u32,
18    /// `true` if the sticker is animated (TGS format).
19    pub is_animated: bool,
20    /// `true` if the sticker is a video sticker (WEBM format).
21    pub is_video: bool,
22    /// Sticker thumbnail.
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub thumbnail: Option<PhotoSize>,
25    /// Emoji associated with the sticker.
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub emoji: Option<String>,
28    /// Name of the sticker set this sticker belongs to.
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub set_name: Option<String>,
31    /// Premium animation for the sticker.
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub premium_animation: Option<crate::file::File>,
34    /// Mask position for mask stickers.
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub mask_position: Option<MaskPosition>,
37    /// Custom emoji identifier for custom emoji stickers.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub custom_emoji_id: Option<String>,
40    /// `true` if the sticker must be repainted to a text color in messages.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub needs_repainting: Option<bool>,
43    /// File size in bytes.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub file_size: Option<u64>,
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
49#[serde(rename_all = "snake_case")]
50/// The type of sticker.
51pub enum StickerType {
52    /// A regular image sticker.
53    Regular,
54    /// A mask sticker (placed on photos).
55    Mask,
56    /// A custom emoji sticker.
57    CustomEmoji,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61/// The position of a mask sticker on a face.
62pub struct MaskPosition {
63    /// The part of the face where the mask is placed.
64    pub point: MaskPoint,
65    /// Shift by X-axis measured in widths of the mask, scaled to the face size.
66    pub x_shift: f64,
67    /// Shift by Y-axis measured in heights of the mask, scaled to the face size.
68    pub y_shift: f64,
69    /// Mask scaling coefficient.
70    pub scale: f64,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
74#[serde(rename_all = "snake_case")]
75/// The specific point on a face where the mask is placed.
76pub enum MaskPoint {
77    /// Placed on the forehead.
78    Forehead,
79    /// Placed over the eyes.
80    Eyes,
81    /// Placed over the mouth.
82    Mouth,
83    /// Placed on the chin.
84    Chin,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
88/// A sticker set (collection of stickers).
89pub struct StickerSet {
90    /// Sticker set name.
91    pub name: String,
92    /// Sticker set title.
93    pub title: String,
94    /// Type of stickers in the set.
95    pub sticker_type: StickerType,
96    /// List of stickers in the set.
97    pub stickers: Vec<Sticker>,
98    /// Sticker set thumbnail.
99    #[serde(skip_serializing_if = "Option::is_none")]
100    pub thumbnail: Option<PhotoSize>,
101}
102
103/// Input sticker for creating or extending sticker sets.
104///
105/// `sticker` holds a `file_id`, HTTP URL, or `attach://<name>` reference.
106/// Raw bytes are handled at the API layer via multipart — this type is
107/// serialisable so it can be embedded in JSON request bodies.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct InputSticker {
110    /// File identifier, URL, or `attach://<n>` reference.
111    pub sticker: String,
112    /// Format of the sticker.
113    pub format: StickerFormat,
114    /// List of 1–20 emoji associated with the sticker.
115    pub emoji_list: Vec<String>,
116    /// Mask position for mask stickers.
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub mask_position: Option<MaskPosition>,
119    /// List of 0–20 search keywords for the sticker.
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub keywords: Option<Vec<String>>,
122}
123
124impl InputSticker {
125    /// Creates an `InputSticker` from a `file_id` or URL.
126    pub fn new(
127        sticker: impl Into<String>,
128        format: StickerFormat,
129        emoji_list: Vec<impl Into<String>>,
130    ) -> Self {
131        Self {
132            sticker: sticker.into(),
133            format,
134            emoji_list: emoji_list.into_iter().map(Into::into).collect(),
135            mask_position: None,
136            keywords: None,
137        }
138    }
139    /// Sets the mask position for this sticker.
140    pub fn mask_position(mut self, mp: MaskPosition) -> Self {
141        self.mask_position = Some(mp);
142        self
143    }
144    /// Sets the search keywords for this sticker.
145    pub fn keywords(mut self, kw: Vec<impl Into<String>>) -> Self {
146        self.keywords = Some(kw.into_iter().map(Into::into).collect());
147        self
148    }
149}
150
151/// The encoding format of a sticker file.
152#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
153#[serde(rename_all = "snake_case")]
154pub enum StickerFormat {
155    /// A static WEBP sticker.
156    Static,
157    /// An animated TGS sticker.
158    Animated,
159    /// A video WEBM sticker.
160    Video,
161}