twilight_cache_inmemory/model/
sticker.rs

1use serde::Serialize;
2use twilight_model::{
3    channel::message::{
4        sticker::{StickerFormatType, StickerType},
5        Sticker,
6    },
7    id::{
8        marker::{GuildMarker, StickerMarker, StickerPackMarker, UserMarker},
9        Id,
10    },
11};
12
13use crate::CacheableSticker;
14
15/// Representation of a cached [`Sticker`].
16///
17/// [`Sticker`]: twilight_model::channel::message::sticker::Sticker
18#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
19pub struct CachedSticker {
20    /// Whether the sticker is available.
21    pub(crate) available: bool,
22    /// Description of the sticker.
23    pub(crate) description: String,
24    /// Format type.
25    pub(crate) format_type: StickerFormatType,
26    /// ID of the guild that owns the sticker.
27    pub(crate) guild_id: Option<Id<GuildMarker>>,
28    /// Unique ID of the sticker.
29    pub(crate) id: Id<StickerMarker>,
30    /// Kind of sticker.
31    pub(crate) kind: StickerType,
32    /// Name of the sticker.
33    pub(crate) name: String,
34    /// Unique ID of the pack the sticker is in.
35    pub(crate) pack_id: Option<Id<StickerPackMarker>>,
36    /// Sticker's sort order within a pack.
37    pub(crate) sort_value: Option<u64>,
38    /// CSV list of tags the sticker is assigned to, if any.
39    pub(crate) tags: String,
40    /// ID of the user that uploaded the sticker.
41    pub(crate) user_id: Option<Id<UserMarker>>,
42}
43
44impl CachedSticker {
45    /// Whether the sticker is available.
46    pub const fn available(&self) -> bool {
47        self.available
48    }
49
50    /// Description of the sticker.
51    pub fn description(&self) -> &str {
52        &self.description
53    }
54
55    /// Format type.
56    pub const fn format_type(&self) -> StickerFormatType {
57        self.format_type
58    }
59
60    /// ID of the guild that owns the sticker.
61    pub const fn guild_id(&self) -> Option<Id<GuildMarker>> {
62        self.guild_id
63    }
64
65    /// Unique ID of the sticker.
66    pub const fn id(&self) -> Id<StickerMarker> {
67        self.id
68    }
69
70    /// Kind of sticker.
71    pub const fn kind(&self) -> StickerType {
72        self.kind
73    }
74
75    /// Name of the sticker.
76    pub fn name(&self) -> &str {
77        &self.name
78    }
79
80    /// Unique ID of the pack the sticker is in.
81    pub const fn pack_id(&self) -> Option<Id<StickerPackMarker>> {
82        self.pack_id
83    }
84
85    /// Sticker's sort order within a pack.
86    pub const fn sort_value(&self) -> Option<u64> {
87        self.sort_value
88    }
89
90    /// CSV list of tags the sticker is assigned to, if any.
91    pub fn tags(&self) -> &str {
92        &self.tags
93    }
94
95    /// ID of the user that uploaded the sticker.
96    pub const fn user_id(&self) -> Option<Id<UserMarker>> {
97        self.user_id
98    }
99}
100
101impl From<Sticker> for CachedSticker {
102    fn from(sticker: Sticker) -> Self {
103        let Sticker {
104            available,
105            description,
106            format_type,
107            guild_id,
108            id,
109            kind,
110            name,
111            pack_id,
112            sort_value,
113            tags,
114            user,
115        } = sticker;
116
117        Self {
118            available,
119            description: description.unwrap_or_default(),
120            format_type,
121            guild_id,
122            id,
123            kind,
124            name,
125            pack_id,
126            sort_value,
127            tags,
128            user_id: user.map(|user| user.id),
129        }
130    }
131}
132
133impl PartialEq<Sticker> for CachedSticker {
134    fn eq(&self, other: &Sticker) -> bool {
135        self.available == other.available
136            && self.description.as_str() == other.description.as_ref().map_or("", String::as_str)
137            && self.format_type == other.format_type
138            && self.guild_id == other.guild_id
139            && self.id == other.id
140            && self.kind == other.kind
141            && self.name == other.name
142            && self.pack_id == other.pack_id
143            && self.sort_value == other.sort_value
144            && self.tags == other.tags
145            && self.user_id == other.user.as_ref().map(|user| user.id)
146    }
147}
148
149impl CacheableSticker for CachedSticker {
150    fn id(&self) -> Id<StickerMarker> {
151        self.id
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use super::CachedSticker;
158    use serde::Serialize;
159    use static_assertions::{assert_fields, assert_impl_all};
160    use std::fmt::Debug;
161    use twilight_model::{
162        channel::message::{
163            sticker::{StickerFormatType, StickerType},
164            Sticker,
165        },
166        id::Id,
167        user::{PremiumType, User, UserFlags},
168        util::{image_hash::ImageHashParseError, ImageHash},
169    };
170
171    assert_fields!(
172        CachedSticker: available,
173        description,
174        format_type,
175        guild_id,
176        id,
177        kind,
178        name,
179        pack_id,
180        sort_value,
181        tags,
182        user_id
183    );
184    assert_impl_all!(
185        CachedSticker: Clone,
186        Debug,
187        Eq,
188        PartialEq,
189        PartialEq<Sticker>,
190        Send,
191        Serialize,
192        Sync
193    );
194
195    #[test]
196    fn eq_sticker() -> Result<(), ImageHashParseError> {
197        let avatar = ImageHash::parse(b"5bf451026c107906b4dccea015320222")?;
198
199        let sticker = Sticker {
200            available: true,
201            description: Some("sticker".into()),
202            format_type: StickerFormatType::Png,
203            guild_id: Some(Id::new(1)),
204            id: Id::new(2),
205            kind: StickerType::Guild,
206            name: "stick".into(),
207            pack_id: Some(Id::new(3)),
208            sort_value: Some(1),
209            tags: "foo,bar,baz".into(),
210            user: Some(User {
211                accent_color: None,
212                avatar: Some(avatar),
213                avatar_decoration: None,
214                avatar_decoration_data: None,
215                banner: None,
216                bot: false,
217                discriminator: 1,
218                email: Some("address@example.com".to_owned()),
219                flags: Some(UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER),
220                global_name: Some("test".to_owned()),
221                id: Id::new(1),
222                locale: Some("en-us".to_owned()),
223                mfa_enabled: Some(true),
224                name: "test".to_owned(),
225                premium_type: Some(PremiumType::Nitro),
226                public_flags: Some(
227                    UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER,
228                ),
229                system: Some(true),
230                verified: Some(true),
231            }),
232        };
233
234        let cached = CachedSticker {
235            available: true,
236            description: "sticker".into(),
237            format_type: StickerFormatType::Png,
238            guild_id: Some(Id::new(1)),
239            id: Id::new(2),
240            kind: StickerType::Guild,
241            name: "stick".into(),
242            pack_id: Some(Id::new(3)),
243            sort_value: Some(1),
244            tags: "foo,bar,baz".into(),
245            user_id: Some(Id::new(1)),
246        };
247
248        assert_eq!(cached, sticker);
249
250        Ok(())
251    }
252}