twilight_model/channel/message/sticker/
mod.rs

1//! Message stickers.
2//!
3//! See the [Discord Docs/Sticker Object].
4//!
5//! [Discord Docs/Sticker Object]: https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-structure
6
7mod format_type;
8mod kind;
9mod message;
10mod pack;
11
12pub use self::{
13    format_type::StickerFormatType, kind::StickerType, message::MessageSticker, pack::StickerPack,
14};
15
16use crate::{
17    id::{
18        marker::{GuildMarker, StickerMarker, StickerPackMarker},
19        Id,
20    },
21    user::User,
22    util::is_false,
23};
24use serde::{Deserialize, Serialize};
25
26/// Message sticker.
27#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
28pub struct Sticker {
29    /// Whether the sticker is available.
30    #[serde(default, skip_serializing_if = "is_false")]
31    pub available: bool,
32    /// Description of the sticker.
33    pub description: Option<String>,
34    /// Format type.
35    pub format_type: StickerFormatType,
36    /// ID of the guild that owns the sticker.
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub guild_id: Option<Id<GuildMarker>>,
39    /// Unique ID of the sticker.
40    pub id: Id<StickerMarker>,
41    /// Kind of sticker.
42    #[serde(rename = "type")]
43    pub kind: StickerType,
44    /// Name of the sticker.
45    pub name: String,
46    /// Unique ID of the pack the sticker is in.
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub pack_id: Option<Id<StickerPackMarker>>,
49    /// Sticker's sort order within a pack.
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub sort_value: Option<u64>,
52    /// CSV list of tags the sticker is assigned to, if any.
53    pub tags: String,
54    /// ID of the user that uploaded the sticker.
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub user: Option<User>,
57}
58
59#[cfg(test)]
60mod tests {
61    use super::{Sticker, StickerFormatType, StickerType, User};
62    use crate::{
63        id::Id,
64        test::image_hash,
65        user::{PremiumType, UserFlags},
66    };
67    use serde::{Deserialize, Serialize};
68    use serde_test::Token;
69    use static_assertions::{assert_fields, assert_impl_all};
70    use std::{fmt::Debug, hash::Hash};
71
72    assert_fields!(
73        Sticker: available,
74        description,
75        format_type,
76        guild_id,
77        id,
78        kind,
79        name,
80        pack_id,
81        sort_value,
82        tags,
83        user
84    );
85
86    assert_impl_all!(
87        Sticker: Clone,
88        Debug,
89        Deserialize<'static>,
90        Eq,
91        Hash,
92        PartialEq,
93        Send,
94        Serialize,
95        Sync,
96    );
97
98    #[test]
99    fn minimal() {
100        let value = Sticker {
101            available: false,
102            description: Some("foo2".to_owned()),
103            format_type: StickerFormatType::Png,
104            guild_id: None,
105            id: Id::new(1),
106            kind: StickerType::Standard,
107            name: "sticker name".to_owned(),
108            pack_id: None,
109            sort_value: None,
110            tags: "foo,bar,baz".to_owned(),
111            user: None,
112        };
113
114        serde_test::assert_tokens(
115            &value,
116            &[
117                Token::Struct {
118                    name: "Sticker",
119                    len: 6,
120                },
121                Token::Str("description"),
122                Token::Some,
123                Token::Str("foo2"),
124                Token::Str("format_type"),
125                Token::U8(StickerFormatType::Png.into()),
126                Token::Str("id"),
127                Token::NewtypeStruct { name: "Id" },
128                Token::Str("1"),
129                Token::Str("type"),
130                Token::U8(1),
131                Token::Str("name"),
132                Token::Str("sticker name"),
133                Token::Str("tags"),
134                Token::Str("foo,bar,baz"),
135                Token::StructEnd,
136            ],
137        );
138    }
139
140    #[allow(clippy::too_many_lines)]
141    #[test]
142    fn full() {
143        let value = Sticker {
144            available: true,
145            description: Some("sticker".into()),
146            format_type: StickerFormatType::Png,
147            guild_id: Some(Id::new(1)),
148            id: Id::new(2),
149            kind: StickerType::Guild,
150            name: "stick".into(),
151            pack_id: Some(Id::new(3)),
152            sort_value: Some(1),
153            tags: "foo,bar,baz".into(),
154            user: Some(User {
155                accent_color: None,
156                avatar: Some(image_hash::AVATAR),
157                avatar_decoration: None,
158                avatar_decoration_data: None,
159                banner: None,
160                bot: false,
161                discriminator: 1,
162                email: Some("address@example.com".to_owned()),
163                flags: Some(UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER),
164                global_name: Some("test".to_owned()),
165                id: Id::new(1),
166                locale: Some("en-us".to_owned()),
167                mfa_enabled: Some(true),
168                name: "test".to_owned(),
169                premium_type: Some(PremiumType::Nitro),
170                public_flags: Some(
171                    UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER,
172                ),
173                system: Some(true),
174                verified: Some(true),
175            }),
176        };
177
178        serde_test::assert_tokens(
179            &value,
180            &[
181                Token::Struct {
182                    name: "Sticker",
183                    len: 11,
184                },
185                Token::Str("available"),
186                Token::Bool(true),
187                Token::Str("description"),
188                Token::Some,
189                Token::Str("sticker"),
190                Token::Str("format_type"),
191                Token::U8(StickerFormatType::Png.into()),
192                Token::Str("guild_id"),
193                Token::Some,
194                Token::NewtypeStruct { name: "Id" },
195                Token::Str("1"),
196                Token::Str("id"),
197                Token::NewtypeStruct { name: "Id" },
198                Token::Str("2"),
199                Token::Str("type"),
200                Token::U8(2),
201                Token::Str("name"),
202                Token::Str("stick"),
203                Token::Str("pack_id"),
204                Token::Some,
205                Token::NewtypeStruct { name: "Id" },
206                Token::Str("3"),
207                Token::Str("sort_value"),
208                Token::Some,
209                Token::U64(1),
210                Token::Str("tags"),
211                Token::Str("foo,bar,baz"),
212                Token::Str("user"),
213                Token::Some,
214                Token::Struct {
215                    name: "User",
216                    len: 18,
217                },
218                Token::Str("accent_color"),
219                Token::None,
220                Token::Str("avatar"),
221                Token::Some,
222                Token::Str(image_hash::AVATAR_INPUT),
223                Token::Str("avatar_decoration"),
224                Token::None,
225                Token::Str("avatar_decoration_data"),
226                Token::None,
227                Token::Str("banner"),
228                Token::None,
229                Token::Str("bot"),
230                Token::Bool(false),
231                Token::Str("discriminator"),
232                Token::Str("0001"),
233                Token::Str("email"),
234                Token::Some,
235                Token::Str("address@example.com"),
236                Token::Str("flags"),
237                Token::Some,
238                Token::U64(131_584),
239                Token::Str("global_name"),
240                Token::Some,
241                Token::Str("test"),
242                Token::Str("id"),
243                Token::NewtypeStruct { name: "Id" },
244                Token::Str("1"),
245                Token::Str("locale"),
246                Token::Some,
247                Token::Str("en-us"),
248                Token::Str("mfa_enabled"),
249                Token::Some,
250                Token::Bool(true),
251                Token::Str("username"),
252                Token::Str("test"),
253                Token::Str("premium_type"),
254                Token::Some,
255                Token::U8(2),
256                Token::Str("public_flags"),
257                Token::Some,
258                Token::U64(131_584),
259                Token::Str("system"),
260                Token::Some,
261                Token::Bool(true),
262                Token::Str("verified"),
263                Token::Some,
264                Token::Bool(true),
265                Token::StructEnd,
266                Token::StructEnd,
267            ],
268        );
269    }
270}