1use serde::{Deserialize, Serialize};
2
3pub use self::{input::*, mask::*, set::*};
4use crate::{
5 api::{Form, Method, Payload},
6 types::{
7 ChatId,
8 File,
9 InputFile,
10 Integer,
11 Message,
12 PhotoSize,
13 ReplyMarkup,
14 ReplyMarkupError,
15 ReplyParameters,
16 ReplyParametersError,
17 },
18};
19
20#[cfg(test)]
21mod tests;
22
23mod input;
24mod mask;
25mod set;
26
27#[serde_with::skip_serializing_none]
29#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
30pub struct Sticker {
31 pub file_id: String,
35 pub file_unique_id: String,
40 pub height: Integer,
42 pub is_animated: bool,
44 pub is_video: bool,
46 #[serde(rename = "type")]
51 pub sticker_type: StickerType,
52 pub width: Integer,
54 pub custom_emoji_id: Option<String>,
56 pub emoji: Option<String>,
58 pub file_size: Option<Integer>,
60 pub mask_position: Option<MaskPosition>,
62 pub needs_repainting: Option<bool>,
66 pub premium_animation: Option<File>,
68 pub set_name: Option<String>,
70 pub thumbnail: Option<PhotoSize>,
72}
73
74impl Sticker {
75 pub fn new<A, B>(file_id: A, file_unique_id: B, sticker_type: StickerType, height: Integer, width: Integer) -> Self
85 where
86 A: Into<String>,
87 B: Into<String>,
88 {
89 Self {
90 file_id: file_id.into(),
91 file_unique_id: file_unique_id.into(),
92 height,
93 is_animated: false,
94 is_video: false,
95 sticker_type,
96 width,
97 custom_emoji_id: None,
98 emoji: None,
99 file_size: None,
100 mask_position: None,
101 needs_repainting: None,
102 premium_animation: None,
103 set_name: None,
104 thumbnail: None,
105 }
106 }
107
108 pub fn with_is_animated(mut self, value: bool) -> Self {
114 self.is_animated = value;
115 self
116 }
117
118 pub fn with_is_video(mut self, value: bool) -> Self {
124 self.is_video = value;
125 self
126 }
127
128 pub fn with_custom_emoji_id<T>(mut self, value: T) -> Self
134 where
135 T: Into<String>,
136 {
137 self.custom_emoji_id = Some(value.into());
138 self
139 }
140
141 pub fn with_emoji<T>(mut self, value: T) -> Self
147 where
148 T: Into<String>,
149 {
150 self.emoji = Some(value.into());
151 self
152 }
153
154 pub fn with_file_size(mut self, value: Integer) -> Self {
160 self.file_size = Some(value);
161 self
162 }
163
164 pub fn with_mask_position(mut self, value: MaskPosition) -> Self {
170 self.mask_position = Some(value);
171 self
172 }
173 pub fn with_needs_repainting(mut self, value: bool) -> Self {
179 self.needs_repainting = Some(value);
180 self
181 }
182
183 pub fn with_premium_animation(mut self, value: File) -> Self {
189 self.premium_animation = Some(value);
190 self
191 }
192
193 pub fn with_set_name<T>(mut self, value: T) -> Self
199 where
200 T: Into<String>,
201 {
202 self.set_name = Some(value.into());
203 self
204 }
205
206 pub fn with_thumbnail(mut self, value: PhotoSize) -> Self {
212 self.thumbnail = Some(value);
213 self
214 }
215}
216
217#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
219#[serde(rename_all = "snake_case")]
220pub enum StickerFormat {
221 Static,
223 Animated,
225 Video,
227}
228
229impl AsRef<str> for StickerFormat {
230 fn as_ref(&self) -> &str {
231 match self {
232 Self::Static => "static",
233 Self::Animated => "animated",
234 Self::Video => "video",
235 }
236 }
237}
238
239#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
241#[serde(rename_all = "snake_case")]
242pub enum StickerType {
243 CustomEmoji,
245 Mask,
247 Regular,
249}
250
251impl AsRef<str> for StickerType {
252 fn as_ref(&self) -> &str {
253 match self {
254 Self::CustomEmoji => "custom_emoji",
255 Self::Mask => "mask",
256 Self::Regular => "regular",
257 }
258 }
259}
260
261#[derive(Clone, Debug, Serialize)]
263pub struct GetCustomEmojiStickers {
264 custom_emoji_ids: Vec<String>,
265}
266
267impl GetCustomEmojiStickers {
268 pub fn new<A, B>(custom_emoji_ids: A) -> Self
274 where
275 A: IntoIterator<Item = B>,
276 B: Into<String>,
277 {
278 Self {
279 custom_emoji_ids: custom_emoji_ids.into_iter().map(Into::into).collect(),
280 }
281 }
282}
283
284impl Method for GetCustomEmojiStickers {
285 type Response = Vec<Sticker>;
286
287 fn into_payload(self) -> Payload {
288 Payload::json("getCustomEmojiStickers", self)
289 }
290}
291
292#[derive(Debug)]
294pub struct SendSticker {
295 form: Form,
296}
297
298impl SendSticker {
299 pub fn new<A, B>(chat_id: A, sticker: B) -> Self
306 where
307 A: Into<ChatId>,
308 B: Into<InputFile>,
309 {
310 Self {
311 form: Form::from([("chat_id", chat_id.into().into()), ("sticker", sticker.into().into())]),
312 }
313 }
314
315 pub fn with_allow_paid_broadcast(mut self, value: bool) -> Self {
323 self.form.insert_field("allow_paid_broadcast", value);
324 self
325 }
326
327 pub fn with_business_connection_id<T>(mut self, value: T) -> Self
333 where
334 T: Into<String>,
335 {
336 self.form.insert_field("business_connection_id", value.into());
337 self
338 }
339
340 pub fn with_disable_notification(mut self, value: bool) -> Self {
347 self.form.insert_field("disable_notification", value);
348 self
349 }
350
351 pub fn with_emoji<T>(mut self, value: T) -> Self
357 where
358 T: Into<String>,
359 {
360 self.form.insert_field("emoji", value.into());
361 self
362 }
363
364 pub fn with_message_effect_id<T>(mut self, value: T) -> Self
370 where
371 T: Into<String>,
372 {
373 self.form.insert_field("message_effect_id", value.into());
374 self
375 }
376
377 pub fn with_message_thread_id(mut self, value: Integer) -> Self {
384 self.form.insert_field("message_thread_id", value);
385 self
386 }
387
388 pub fn with_protect_content(mut self, value: bool) -> Self {
395 self.form.insert_field("protect_content", value.to_string());
396 self
397 }
398
399 pub fn with_reply_markup<T>(mut self, value: T) -> Result<Self, ReplyMarkupError>
405 where
406 T: Into<ReplyMarkup>,
407 {
408 let value = value.into();
409 self.form.insert_field("reply_markup", value.serialize()?);
410 Ok(self)
411 }
412
413 pub fn with_reply_parameters(mut self, value: ReplyParameters) -> Result<Self, ReplyParametersError> {
419 self.form.insert_field("reply_parameters", value.serialize()?);
420 Ok(self)
421 }
422}
423
424impl Method for SendSticker {
425 type Response = Message;
426
427 fn into_payload(self) -> Payload {
428 Payload::form("sendSticker", self.form)
429 }
430}
431
432#[derive(Clone, Debug, Serialize)]
436pub struct SetStickerEmojiList {
437 sticker: String,
438 emoji_list: Vec<String>,
439}
440
441impl SetStickerEmojiList {
442 pub fn new<A, B, C>(sticker: A, emoji_list: B) -> Self
447 where
448 A: Into<String>,
449 B: IntoIterator<Item = C>,
450 C: Into<String>,
451 {
452 Self {
453 sticker: sticker.into(),
454 emoji_list: emoji_list.into_iter().map(Into::into).collect(),
455 }
456 }
457}
458
459impl Method for SetStickerEmojiList {
460 type Response = bool;
461
462 fn into_payload(self) -> Payload {
463 Payload::json("setStickerEmojiList", self)
464 }
465}
466
467#[derive(Clone, Debug, Serialize)]
471pub struct SetStickerKeywords {
472 sticker: String,
473 keywords: Vec<String>,
474}
475
476impl SetStickerKeywords {
477 pub fn new<A, B, C>(sticker: A, keywords: B) -> Self
483 where
484 A: Into<String>,
485 B: IntoIterator<Item = C>,
486 C: Into<String>,
487 {
488 Self {
489 sticker: sticker.into(),
490 keywords: keywords.into_iter().map(Into::into).collect(),
491 }
492 }
493}
494
495impl Method for SetStickerKeywords {
496 type Response = bool;
497
498 fn into_payload(self) -> Payload {
499 Payload::json("setStickerKeywords", self)
500 }
501}
502
503#[serde_with::skip_serializing_none]
507#[derive(Clone, Debug, Serialize)]
508pub struct SetStickerMaskPosition {
509 sticker: String,
510 mask_position: Option<MaskPosition>,
511}
512
513impl SetStickerMaskPosition {
514 pub fn new<T>(sticker: T) -> Self
518 where
519 T: Into<String>,
520 {
521 Self {
522 sticker: sticker.into(),
523 mask_position: None,
524 }
525 }
526
527 pub fn with_mask_position(mut self, value: MaskPosition) -> Self {
535 self.mask_position = Some(value);
536 self
537 }
538}
539
540impl Method for SetStickerMaskPosition {
541 type Response = bool;
542
543 fn into_payload(self) -> Payload {
544 Payload::json("setStickerMaskPosition", self)
545 }
546}
547
548#[derive(Debug)]
553pub struct UploadStickerFile {
554 form: Form,
555}
556
557impl UploadStickerFile {
558 pub fn new<T>(user_id: Integer, sticker: T, sticker_format: StickerFormat) -> Self
566 where
567 T: Into<InputFile>,
568 {
569 Self {
570 form: Form::from([
571 ("user_id", user_id.into()),
572 ("sticker", sticker.into().into()),
573 ("sticker_format", sticker_format.as_ref().into()),
574 ]),
575 }
576 }
577}
578
579impl Method for UploadStickerFile {
580 type Response = File;
581
582 fn into_payload(self) -> Payload {
583 Payload::form("uploadStickerFile", self.form)
584 }
585}