twilight_cache_inmemory/model/
sticker.rs

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