tulpje_cache/models/
sticker.rs1use std::collections::HashSet;
2
3use serde::{Deserialize, Serialize};
4use twilight_model::{
5 channel::message::{
6 Sticker,
7 sticker::{StickerFormatType, StickerType},
8 },
9 id::{
10 Id,
11 marker::{GuildMarker, StickerMarker, StickerPackMarker, UserMarker},
12 },
13};
14
15use crate::{Cache, Error, GuildResource};
16
17#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
18pub struct CachedSticker {
19 available: bool,
20 description: String,
21 format_type: StickerFormatType,
22 guild_id: Option<Id<GuildMarker>>,
23 id: Id<StickerMarker>,
24 kind: StickerType,
25 name: String,
26 pack_id: Option<Id<StickerPackMarker>>,
27 sort_value: Option<u64>,
28 tags: String,
29 user_id: Option<Id<UserMarker>>,
30}
31
32impl From<Sticker> for CachedSticker {
33 fn from(sticker: Sticker) -> Self {
34 let Sticker {
35 available,
36 description,
37 format_type,
38 guild_id,
39 id,
40 kind,
41 name,
42 pack_id,
43 sort_value,
44 tags,
45 user,
46 } = sticker;
47
48 Self {
49 available,
50 description: description.unwrap_or_default(),
51 format_type,
52 guild_id,
53 id,
54 kind,
55 name,
56 pack_id,
57 sort_value,
58 tags,
59 user_id: user.map(|user| user.id),
60 }
61 }
62}
63
64impl PartialEq<Sticker> for CachedSticker {
65 fn eq(&self, other: &Sticker) -> bool {
66 self.available == other.available
67 && self.description.as_str() == other.description.as_ref().map_or("", String::as_str)
68 && self.format_type == other.format_type
69 && self.guild_id == other.guild_id
70 && self.id == other.id
71 && self.kind == other.kind
72 && self.name == other.name
73 && self.pack_id == other.pack_id
74 && self.sort_value == other.sort_value
75 && self.tags == other.tags
76 && self.user_id == other.user.as_ref().map(|user| user.id)
77 }
78}
79
80impl Cache {
81 pub(crate) async fn cache_stickers(
82 &self,
83 guild_id: Id<GuildMarker>,
84 stickers: Vec<Sticker>,
85 ) -> Result<(), Error> {
86 let guild_stickers = self.guild_stickers.members(&guild_id).await?;
87 if !guild_stickers.is_empty() {
88 let incoming: HashSet<_> = stickers.iter().map(|sticker| sticker.id).collect();
89
90 let removal_filter: Vec<_> = guild_stickers
91 .iter()
92 .copied()
93 .filter(|sticker| !incoming.contains(sticker))
94 .collect();
95
96 self.guild_stickers
97 .remove_multi(&guild_id, &removal_filter)
98 .await?;
99
100 self.stickers.remove_multi(&removal_filter).await?;
101 }
102
103 for sticker in stickers {
104 self.cache_sticker(guild_id, sticker).await?;
105 }
106
107 Ok(())
108 }
109
110 pub(crate) async fn cache_sticker(
111 &self,
112 guild_id: Id<GuildMarker>,
113 sticker: Sticker,
114 ) -> Result<(), Error> {
115 if let Some(cached_sticker) = self.stickers.get(&sticker.id).await?
116 && cached_sticker.value == sticker
117 {
118 return Ok(());
119 }
120
121 if let Some(user) = &sticker.user {
122 self.cache_user(user, Some(guild_id)).await?;
123 }
124
125 self.guild_stickers.insert(&guild_id, &sticker.id).await?;
126 self.stickers
127 .insert(
128 &sticker.id.clone(),
129 &GuildResource {
130 guild_id,
131 value: sticker.into(),
132 },
133 )
134 .await?;
135
136 Ok(())
137 }
138}