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
132
133
134
135
136
137
|
use crate::{storage, utils, Data};
use storage::ReactBoardEntry;
use color_eyre::eyre::{eyre, Context as _, Result};
use log::*;
use poise::serenity_prelude::{Context, GuildId, Message, MessageReaction, Reaction};
pub async fn handle(ctx: &Context, reaction: &Reaction, data: &Data) -> Result<()> {
let msg = reaction
.message(&ctx.http)
.await
.wrap_err_with(|| "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 target = if let Some(target) = settings.reactboard_channel {
target
} 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
);
ctx.http
.get_message(
*old_entry.posted_channel_id.as_u64(),
*old_entry.posted_message_id.as_u64(),
)
.await
.wrap_err_with(|| {
format!(
"Couldn't get previous message from ReactBoardEntry {} in Redis DB!",
old_entry.original_message_id
)
})?
.edit(ctx, |m| m.content(content))
.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 resp = target
.send_message(ctx, |m| {
m.allowed_mentions(|am| am.empty_parse())
.content(content)
.set_embed(embed)
})
.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(())
}
|