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 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}