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        Id,
19        marker::{GuildMarker, StickerMarker, StickerPackMarker},
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::user::PrimaryGuild;
63    use crate::{
64        id::Id,
65        test::image_hash,
66        user::{PremiumType, UserFlags},
67    };
68    use serde::{Deserialize, Serialize};
69    use serde_test::Token;
70    use static_assertions::{assert_fields, assert_impl_all};
71    use std::{fmt::Debug, hash::Hash};
72
73    assert_fields!(
74        Sticker: available,
75        description,
76        format_type,
77        guild_id,
78        id,
79        kind,
80        name,
81        pack_id,
82        sort_value,
83        tags,
84        user
85    );
86
87    assert_impl_all!(
88        Sticker: Clone,
89        Debug,
90        Deserialize<'static>,
91        Eq,
92        Hash,
93        PartialEq,
94        Send,
95        Serialize,
96        Sync,
97    );
98
99    #[test]
100    fn minimal() {
101        let value = Sticker {
102            available: false,
103            description: Some("foo2".to_owned()),
104            format_type: StickerFormatType::Png,
105            guild_id: None,
106            id: Id::new(1),
107            kind: StickerType::Standard,
108            name: "sticker name".to_owned(),
109            pack_id: None,
110            sort_value: None,
111            tags: "foo,bar,baz".to_owned(),
112            user: None,
113        };
114
115        serde_test::assert_tokens(
116            &value,
117            &[
118                Token::Struct {
119                    name: "Sticker",
120                    len: 6,
121                },
122                Token::Str("description"),
123                Token::Some,
124                Token::Str("foo2"),
125                Token::Str("format_type"),
126                Token::U8(StickerFormatType::Png.into()),
127                Token::Str("id"),
128                Token::NewtypeStruct { name: "Id" },
129                Token::Str("1"),
130                Token::Str("type"),
131                Token::U8(1),
132                Token::Str("name"),
133                Token::Str("sticker name"),
134                Token::Str("tags"),
135                Token::Str("foo,bar,baz"),
136                Token::StructEnd,
137            ],
138        );
139    }
140
141    #[allow(clippy::too_many_lines)]
142    #[test]
143    fn full() {
144        let value = Sticker {
145            available: true,
146            description: Some("sticker".into()),
147            format_type: StickerFormatType::Png,
148            guild_id: Some(Id::new(1)),
149            id: Id::new(2),
150            kind: StickerType::Guild,
151            name: "stick".into(),
152            pack_id: Some(Id::new(3)),
153            sort_value: Some(1),
154            tags: "foo,bar,baz".into(),
155            user: Some(User {
156                accent_color: None,
157                avatar: Some(image_hash::AVATAR),
158                avatar_decoration: None,
159                avatar_decoration_data: None,
160                banner: None,
161                bot: false,
162                discriminator: 1,
163                email: Some("address@example.com".to_owned()),
164                flags: Some(UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER),
165                global_name: Some("test".to_owned()),
166                id: Id::new(1),
167                locale: Some("en-us".to_owned()),
168                mfa_enabled: Some(true),
169                name: "test".to_owned(),
170                premium_type: Some(PremiumType::Nitro),
171                primary_guild: Some(PrimaryGuild {
172                    identity_guild_id: Some(Id::new(169_256_939_211_980_800)),
173                    identity_enabled: Some(true),
174                    tag: Some("DISC".to_owned()),
175                    badge: Some("1269e74af4df7417b13759eae50c83dc".parse().unwrap()),
176                }),
177                public_flags: Some(
178                    UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER,
179                ),
180                system: Some(true),
181                verified: Some(true),
182            }),
183        };
184
185        serde_test::assert_tokens(
186            &value,
187            &[
188                Token::Struct {
189                    name: "Sticker",
190                    len: 11,
191                },
192                Token::Str("available"),
193                Token::Bool(true),
194                Token::Str("description"),
195                Token::Some,
196                Token::Str("sticker"),
197                Token::Str("format_type"),
198                Token::U8(StickerFormatType::Png.into()),
199                Token::Str("guild_id"),
200                Token::Some,
201                Token::NewtypeStruct { name: "Id" },
202                Token::Str("1"),
203                Token::Str("id"),
204                Token::NewtypeStruct { name: "Id" },
205                Token::Str("2"),
206                Token::Str("type"),
207                Token::U8(2),
208                Token::Str("name"),
209                Token::Str("stick"),
210                Token::Str("pack_id"),
211                Token::Some,
212                Token::NewtypeStruct { name: "Id" },
213                Token::Str("3"),
214                Token::Str("sort_value"),
215                Token::Some,
216                Token::U64(1),
217                Token::Str("tags"),
218                Token::Str("foo,bar,baz"),
219                Token::Str("user"),
220                Token::Some,
221                Token::Struct {
222                    name: "User",
223                    len: 19,
224                },
225                Token::Str("accent_color"),
226                Token::None,
227                Token::Str("avatar"),
228                Token::Some,
229                Token::Str(image_hash::AVATAR_INPUT),
230                Token::Str("avatar_decoration"),
231                Token::None,
232                Token::Str("avatar_decoration_data"),
233                Token::None,
234                Token::Str("banner"),
235                Token::None,
236                Token::Str("bot"),
237                Token::Bool(false),
238                Token::Str("discriminator"),
239                Token::Str("0001"),
240                Token::Str("email"),
241                Token::Some,
242                Token::Str("address@example.com"),
243                Token::Str("flags"),
244                Token::Some,
245                Token::U64(131_584),
246                Token::Str("global_name"),
247                Token::Some,
248                Token::Str("test"),
249                Token::Str("id"),
250                Token::NewtypeStruct { name: "Id" },
251                Token::Str("1"),
252                Token::Str("locale"),
253                Token::Some,
254                Token::Str("en-us"),
255                Token::Str("mfa_enabled"),
256                Token::Some,
257                Token::Bool(true),
258                Token::Str("username"),
259                Token::Str("test"),
260                Token::Str("premium_type"),
261                Token::Some,
262                Token::U8(2),
263                Token::Str("primary_guild"),
264                Token::Some,
265                Token::Struct {
266                    name: "PrimaryGuild",
267                    len: 4,
268                },
269                Token::Str("identity_guild_id"),
270                Token::Some,
271                Token::NewtypeStruct { name: "Id" },
272                Token::Str("169256939211980800"),
273                Token::Str("identity_enabled"),
274                Token::Some,
275                Token::Bool(true),
276                Token::Str("tag"),
277                Token::Some,
278                Token::Str("DISC"),
279                Token::Str("badge"),
280                Token::Some,
281                Token::Str("1269e74af4df7417b13759eae50c83dc"),
282                Token::StructEnd,
283                Token::Str("public_flags"),
284                Token::Some,
285                Token::U64(131_584),
286                Token::Str("system"),
287                Token::Some,
288                Token::Bool(true),
289                Token::Str("verified"),
290                Token::Some,
291                Token::Bool(true),
292                Token::StructEnd,
293                Token::StructEnd,
294            ],
295        );
296    }
297}