tulpje_cache/event/
reaction.rs1use 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}