1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use super::{InputFile, MaskPosition};

use serde::Serialize;
use serde_with::skip_serializing_none;

/// This object describes a sticker to be added to a sticker set.
/// # Documentation
/// <https://core.telegram.org/bots/api#inputsticker>
#[skip_serializing_none]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct InputSticker<'a> {
    /// The added sticker. Pass a `file_id` as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, upload a new one using `multipart/form-data`, or pass `attach://<file_attach_name>` to upload a new one using `multipart/form-data` under <file_attach_name> name. Animated and video stickers can't be uploaded via HTTP URL. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files).
    pub sticker: InputFile<'a>,
    /// Format of the added sticker, must be one of "static" for a **.WEBP** or **.PNG** image, "animated" for a **.TGS** animation, "video" for a **WEBM** video
    pub format: String,
    /// List of 1-20 emoji associated with the sticker
    pub emoji_list: Vec<String>,
    /// Position where the mask should be placed on faces. For "mask" stickers only.
    pub mask_position: Option<MaskPosition>,
    /// List of 0-20 search keywords for the sticker with total length of up to 64 characters. For "regular" and "custom_emoji" stickers only.
    pub keywords: Option<Vec<String>>,
}

impl<'a> InputSticker<'a> {
    #[must_use]
    pub fn new(sticker: impl Into<InputFile<'a>>, format: impl Into<String>) -> Self {
        Self {
            sticker: sticker.into(),
            format: format.into(),
            emoji_list: vec![],
            mask_position: None,
            keywords: None,
        }
    }

    #[must_use]
    pub fn sticker(self, val: impl Into<InputFile<'a>>) -> Self {
        Self {
            sticker: val.into(),
            ..self
        }
    }

    #[must_use]
    pub fn format(self, val: impl Into<String>) -> Self {
        Self {
            format: val.into(),
            ..self
        }
    }

    #[must_use]
    pub fn emoji(self, val: impl Into<String>) -> Self {
        Self {
            emoji_list: self
                .emoji_list
                .into_iter()
                .chain(Some(val.into()))
                .collect(),
            ..self
        }
    }

    #[must_use]
    pub fn emoji_list<T, I>(self, val: I) -> Self
    where
        T: Into<String>,
        I: IntoIterator<Item = T>,
    {
        Self {
            emoji_list: self
                .emoji_list
                .into_iter()
                .chain(val.into_iter().map(Into::into))
                .collect(),
            ..self
        }
    }

    /// Alias to [`InputSticker::emoji_list`] method
    #[must_use]
    pub fn emojis<T, I>(self, val: I) -> Self
    where
        T: Into<String>,
        I: IntoIterator<Item = T>,
    {
        self.emoji_list(val)
    }

    #[must_use]
    pub fn mask_position(self, val: MaskPosition) -> Self {
        Self {
            mask_position: Some(val),
            ..self
        }
    }

    #[must_use]
    pub fn keyword(self, val: impl Into<String>) -> Self {
        Self {
            keywords: Some(
                self.keywords
                    .unwrap_or_default()
                    .into_iter()
                    .chain(Some(val.into()))
                    .collect(),
            ),
            ..self
        }
    }

    #[must_use]
    pub fn keywords<T, I>(self, val: I) -> Self
    where
        T: Into<String>,
        I: IntoIterator<Item = T>,
    {
        Self {
            keywords: Some(
                self.keywords
                    .unwrap_or_default()
                    .into_iter()
                    .chain(val.into_iter().map(Into::into))
                    .collect(),
            ),
            ..self
        }
    }
}

impl<'a> InputSticker<'a> {
    #[must_use]
    pub fn mask_position_option(self, val: Option<MaskPosition>) -> Self {
        Self {
            mask_position: val,
            ..self
        }
    }

    #[must_use]
    pub fn keywords_option<T, I>(self, val: Option<I>) -> Self
    where
        T: Into<String>,
        I: IntoIterator<Item = T>,
    {
        Self {
            keywords: val.map(|val| {
                self.keywords
                    .unwrap_or_default()
                    .into_iter()
                    .chain(val.into_iter().map(Into::into))
                    .collect()
            }),
            ..self
        }
    }
}