1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
use crate::{storage, utils, Data};
use storage::ReactBoardEntry;
use eyre::{eyre, Context as _, Result};
use log::debug;
use poise::serenity_prelude::{
Context, CreateMessage, EditMessage, GuildId, Message, MessageReaction, Reaction,
};
pub async fn handle(ctx: &Context, reaction: &Reaction, data: &Data) -> Result<()> {
let msg = reaction
.message(&ctx.http)
.await
.wrap_err("Couldn't get reaction from message!")?;
let matched = msg
.clone()
.reactions
.into_iter()
.find(|r| r.reaction_type == reaction.emoji)
.ok_or_else(|| {
eyre!(
"Couldn't find any matching reactions for {} in message {}!",
reaction.emoji.as_data(),
msg.id
)
})?;
send_to_reactboard(
ctx,
&matched,
&msg,
&reaction.guild_id.unwrap_or_default(),
data,
)
.await?;
Ok(())
}
async fn send_to_reactboard(
ctx: &Context,
reaction: &MessageReaction,
msg: &Message,
guild_id: &GuildId,
data: &Data,
) -> Result<()> {
let storage = &data.storage;
let settings = storage.get_guild_settings(guild_id).await?;
// make sure everything is in order...
if !settings.reactboard_enabled {
debug!("ReactBoard is disabled in {guild_id}, ignoring");
return Ok(());
}
let Some(target) = settings.reactboard_channel else {
debug!("ReactBoard is disabled in {guild_id}, ignoring");
return Ok(());
};
if !settings.can_use_reaction(&reaction.reaction_type) {
debug!("Reaction {} can't be used!", reaction.reaction_type);
return Ok(());
}
if reaction.count < settings.reactboard_requirement.unwrap_or(5) {
debug!(
"Ignoring message {} on ReactBoard, not enough reactions",
msg.id
);
return Ok(());
}
let content = format!("{} **#{}**", reaction.reaction_type, reaction.count);
// bump reaction count if previous entry exists
if storage.reactboard_entry_exists(guild_id, &msg.id).await? {
let old_entry = storage.get_reactboard_entry(guild_id, &msg.id).await?;
// bail if we don't need to edit anything
if old_entry.reaction_count >= reaction.count {
debug!("Message {} doesn't need updating", msg.id);
return Ok(());
}
debug!(
"Bumping {} reaction count from {} to {}",
msg.id, old_entry.reaction_count, reaction.count
);
let edited = EditMessage::new().content(content);
ctx.http
.get_message(old_entry.posted_channel_id, old_entry.posted_message_id)
.await
.wrap_err_with(|| {
format!(
"Couldn't get previous message from ReactBoardEntry {} in Redis DB!",
old_entry.original_message_id
)
})?
.edit(ctx, edited)
.await?;
// update reaction count in redis
let mut new_entry = old_entry.clone();
new_entry.reaction_count = reaction.count;
debug!("Updating ReactBoard entry\nOld entry:\n{old_entry:#?}\n\nNew:\n{new_entry:#?}\n",);
storage.create_reactboard_entry(guild_id, new_entry).await?;
// make new message and add entry to redis otherwise
} else {
let embed = utils::resolve_message_to_embed(ctx, msg).await;
let message = CreateMessage::default().content(content).embed(embed);
let resp = target.send_message(ctx, message).await?;
let entry = ReactBoardEntry {
original_message_id: msg.id,
reaction_count: reaction.count,
posted_channel_id: resp.channel_id,
posted_message_id: resp.id,
};
debug!("Creating new ReactBoard entry:\n{entry:#?}");
storage.create_reactboard_entry(guild_id, entry).await?;
}
Ok(())
}
|