tulpje_cache/event/
reaction.rs

1use twilight_model::{
2    channel::message::{EmojiReactionType, Reaction, ReactionCountDetails},
3    gateway::payload::incoming::{
4        ReactionAdd, ReactionRemove, ReactionRemoveAll, ReactionRemoveEmoji,
5    },
6};
7
8use crate::{Cache, Error, UpdateCache};
9
10impl UpdateCache for ReactionAdd {
11    async fn update(&self, cache: &Cache) -> Result<(), Error> {
12        let key = self.0.message_id;
13
14        let Some(mut message) = cache.messages.get(&key).await? else {
15            return Ok(());
16        };
17
18        if let Some(reaction) = message
19            .reactions
20            .iter_mut()
21            .find(|r| reactions_eq(&r.emoji, &self.0.emoji))
22        {
23            if !reaction.me
24                && let Some(current_user) = cache.current_user.get().await?
25                && current_user.id == self.0.user_id
26            {
27                reaction.me = true;
28            }
29
30            reaction.count += 1;
31        } else {
32            let me = cache
33                .current_user
34                .get()
35                .await?
36                .is_some_and(|user| user.id == self.0.user_id);
37
38            message.reactions.push(Reaction {
39                burst_colors: Vec::new(),
40                count: 1,
41                count_details: ReactionCountDetails {
42                    burst: 0,
43                    normal: 1,
44                },
45                emoji: self.0.emoji.clone(),
46                me,
47                me_burst: false,
48            });
49        }
50
51        cache.messages.insert(&message.id, &message).await?;
52
53        Ok(())
54    }
55}
56
57impl UpdateCache for ReactionRemove {
58    async fn update(&self, cache: &Cache) -> Result<(), Error> {
59        let Some(mut message) = cache.messages.get(&self.0.message_id).await? else {
60            return Ok(());
61        };
62
63        if let Some(reaction) = message
64            .reactions
65            .iter_mut()
66            .find(|r| reactions_eq(&r.emoji, &self.0.emoji))
67        {
68            if reaction.me
69                && let Some(current_user) = cache.current_user.get().await?
70                && current_user.id == self.0.user_id
71            {
72                reaction.me = false;
73            }
74
75            if reaction.count > 1 {
76                reaction.count -= 1;
77            } else {
78                message
79                    .reactions
80                    .retain(|e| !(reactions_eq(&e.emoji, &self.0.emoji)));
81            }
82        }
83
84        cache.messages.insert(&message.id, &message).await?;
85
86        Ok(())
87    }
88}
89
90impl UpdateCache for ReactionRemoveAll {
91    async fn update(&self, cache: &Cache) -> Result<(), Error> {
92        let Some(mut message) = cache.messages.get(&self.message_id).await? else {
93            return Ok(());
94        };
95
96        message.reactions.clear();
97        cache.messages.insert(&message.id, &message).await?;
98
99        Ok(())
100    }
101}
102
103impl UpdateCache for ReactionRemoveEmoji {
104    async fn update(&self, cache: &Cache) -> Result<(), Error> {
105        let Some(mut message) = cache.messages.get(&self.message_id).await? else {
106            return Ok(());
107        };
108
109        let maybe_index = message
110            .reactions
111            .iter()
112            .position(|r| reactions_eq(&r.emoji, &self.emoji));
113
114        if let Some(index) = maybe_index {
115            message.reactions.remove(index);
116        }
117
118        cache.messages.insert(&message.id, &message).await?;
119
120        Ok(())
121    }
122}
123
124fn reactions_eq(a: &EmojiReactionType, b: &EmojiReactionType) -> bool {
125    match (a, b) {
126        (
127            EmojiReactionType::Custom { id: id_a, .. },
128            EmojiReactionType::Custom { id: id_b, .. },
129        ) => id_a == id_b,
130        (
131            EmojiReactionType::Unicode { name: name_a },
132            EmojiReactionType::Unicode { name: name_b },
133        ) => name_a == name_b,
134        _ => false,
135    }
136}