tulpje_cache/models/
emoji.rs

1use serde::{Deserialize, Serialize};
2use twilight_model::{
3    guild::Emoji,
4    id::{
5        Id,
6        marker::{EmojiMarker, GuildMarker, RoleMarker, UserMarker},
7    },
8};
9
10use crate::{Cache, Error, GuildResource};
11
12#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
13pub struct CachedEmoji {
14    pub animated: bool,
15    pub available: bool,
16    pub id: Id<EmojiMarker>,
17    pub managed: bool,
18    pub name: String,
19    pub require_colons: bool,
20    pub roles: Vec<Id<RoleMarker>>,
21    pub user_id: Option<Id<UserMarker>>,
22}
23
24impl From<Emoji> for CachedEmoji {
25    fn from(emoji: Emoji) -> Self {
26        let Emoji {
27            animated,
28            available,
29            id,
30            managed,
31            name,
32            require_colons,
33            roles,
34            user,
35        } = emoji;
36
37        Self {
38            animated,
39            available,
40            id,
41            managed,
42            name,
43            require_colons,
44            roles,
45            user_id: user.map(|user| user.id),
46        }
47    }
48}
49
50impl PartialEq<Emoji> for CachedEmoji {
51    fn eq(&self, other: &Emoji) -> bool {
52        self.id == other.id
53            && self.animated == other.animated
54            && self.managed == other.managed
55            && self.name == other.name
56            && self.require_colons == other.require_colons
57            && self.roles == other.roles
58            && self.user_id == other.user.as_ref().map(|user| user.id)
59            && self.available == other.available
60    }
61}
62
63impl Cache {
64    pub(crate) async fn cache_emojis(
65        &self,
66        guild_id: Id<GuildMarker>,
67        emojis: Vec<Emoji>,
68    ) -> Result<(), Error> {
69        let guild_emojis = self.guild_emojis.members(&guild_id).await?;
70        if !guild_emojis.is_empty() {
71            let incoming: Vec<_> = emojis.iter().map(|e| e.id).collect();
72
73            let removal_filter: Vec<_> = guild_emojis
74                .iter()
75                .copied()
76                .filter(|e| !incoming.contains(e))
77                .collect();
78
79            self.guild_emojis
80                .remove_multi(&guild_id, &removal_filter)
81                .await?;
82
83            self.emojis.remove_multi(&removal_filter).await?;
84        }
85
86        for emoji in &emojis {
87            self.cache_emoji(guild_id, emoji).await?;
88        }
89
90        Ok(())
91    }
92
93    pub(crate) async fn cache_emoji(
94        &self,
95        guild_id: Id<GuildMarker>,
96        emoji: &Emoji,
97    ) -> Result<(), Error> {
98        if let Some(user) = emoji.user.as_ref() {
99            self.cache_user(user, Some(guild_id)).await?;
100        }
101
102        if let Some(cached_emoji) = self.emojis.get(&emoji.id).await?
103            && cached_emoji.value == *emoji
104        {
105            return Ok(());
106        }
107
108        let emoji_id = emoji.id;
109        let cached = CachedEmoji::from(emoji.clone());
110
111        self.emojis
112            .insert(
113                &emoji_id,
114                &GuildResource {
115                    guild_id,
116                    value: cached,
117                },
118            )
119            .await?;
120
121        self.guild_emojis.insert(&guild_id, &emoji_id).await?;
122
123        Ok(())
124    }
125}