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