Skip to content

Commit a5ba711

Browse files
committed
add feature to give roles on adding reactions
1 parent afc3fc9 commit a5ba711

File tree

2 files changed

+92
-14
lines changed

2 files changed

+92
-14
lines changed

src/commands.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ You should have received a copy of the GNU General Public License
1616
along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818
use crate::Data;
19-
20-
type Context<'a> = poise::Context<'a, Data, Error>;
21-
type Error = Box<dyn std::error::Error + Send + Sync>;
19+
use crate::Error;
20+
use crate::Context;
2221

2322
#[poise::command(prefix_command)]
2423
async fn amdctl(ctx: Context<'_>) -> Result<(), Error> {
@@ -27,7 +26,5 @@ async fn amdctl(ctx: Context<'_>) -> Result<(), Error> {
2726
}
2827

2928
pub fn get_commands() -> Vec<poise::Command<Data, Error>> {
30-
vec![
31-
amdctl(),
32-
]
29+
vec![amdctl()]
3330
}

src/main.rs

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,28 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
1818
mod commands;
1919

2020
use anyhow::Context as _;
21+
use std::collections::HashMap;
2122

22-
struct Data {}
23+
use poise::{Context as PoiseContext, Framework, FrameworkOptions, PrefixFrameworkOptions};
24+
use serenity::{
25+
client::Context as SerenityContext,
26+
client::FullEvent,
27+
model::{
28+
channel::ReactionType,
29+
gateway::GatewayIntents,
30+
id::{MessageId, RoleId},
31+
},
32+
};
33+
34+
type Context<'a> = PoiseContext<'a, Data, Error>;
35+
type Error = Box<dyn std::error::Error + Send + Sync>;
36+
37+
struct Data {
38+
reaction_roles: HashMap<MessageId, (ReactionType, RoleId)>,
39+
}
40+
41+
const ARCHIVE_MESSAGE_ID: u64 = 1295815208689733703;
42+
const ARCHIVE_ROLE_ID: u64 = 1208457364274028574;
2343

2444
#[shuttle_runtime::main]
2545
async fn main(
@@ -29,31 +49,92 @@ async fn main(
2949
.get("DISCORD_TOKEN")
3050
.context("'DISCORD_TOKEN' was not found")?;
3151

32-
let framework = poise::Framework::builder()
33-
.options(poise::FrameworkOptions {
52+
let framework = Framework::builder()
53+
.options(FrameworkOptions {
3454
commands: commands::get_commands(),
35-
prefix_options: poise::PrefixFrameworkOptions {
36-
prefix: Option::Some(String::from("$")),
55+
event_handler: |ctx, event, framework, data| {
56+
Box::pin(event_handler(ctx, event, framework, data))
57+
},
58+
prefix_options: PrefixFrameworkOptions {
59+
prefix: Some(String::from("$")),
3760
..Default::default()
3861
},
3962
..Default::default()
4063
})
4164
.setup(|ctx, _ready, framework| {
4265
Box::pin(async move {
4366
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
44-
Ok(Data {})
67+
68+
let mut data = Data {
69+
reaction_roles: HashMap::new(),
70+
};
71+
72+
let message_id = MessageId::new(ARCHIVE_MESSAGE_ID);
73+
let role_id = RoleId::new(ARCHIVE_ROLE_ID);
74+
75+
data.reaction_roles.insert(
76+
message_id,
77+
(ReactionType::Unicode("📁".to_string()), role_id),
78+
);
79+
80+
Ok(data)
4581
})
4682
})
4783
.build();
4884

4985
let client = serenity::client::ClientBuilder::new(
5086
discord_token,
51-
serenity::model::gateway::GatewayIntents::non_privileged()
52-
| serenity::model::gateway::GatewayIntents::MESSAGE_CONTENT,
87+
GatewayIntents::non_privileged() | GatewayIntents::MESSAGE_CONTENT,
5388
)
5489
.framework(framework)
5590
.await
5691
.map_err(shuttle_runtime::CustomError::new)?;
5792

5893
Ok(client.into())
5994
}
95+
96+
async fn event_handler(
97+
ctx: &SerenityContext,
98+
event: &FullEvent,
99+
_framework: poise::FrameworkContext<'_, Data, Error>,
100+
data: &Data,
101+
) -> Result<(), Error> {
102+
match event {
103+
FullEvent::ReactionAdd { add_reaction } => {
104+
if let Some((expected_reaction, role_id)) =
105+
data.reaction_roles.get(&add_reaction.message_id)
106+
{
107+
if &add_reaction.emoji == expected_reaction {
108+
if let Some(guild_id) = add_reaction.guild_id {
109+
// TODO: Use try_join to await concurrently?
110+
if let Ok(member) =
111+
guild_id.member(ctx, add_reaction.user_id.unwrap()).await
112+
{
113+
let _ = member.add_role(&ctx.http, *role_id).await;
114+
}
115+
}
116+
}
117+
}
118+
}
119+
120+
FullEvent::ReactionRemove { removed_reaction } => {
121+
if let Some((expected_reaction, role_id)) =
122+
data.reaction_roles.get(&removed_reaction.message_id)
123+
{
124+
if &removed_reaction.emoji == expected_reaction {
125+
if let Some(guild_id) = removed_reaction.guild_id {
126+
if let Ok(member) = guild_id
127+
.member(ctx, removed_reaction.user_id.unwrap())
128+
.await
129+
{
130+
let _ = member.remove_role(&ctx.http, *role_id).await;
131+
}
132+
}
133+
}
134+
}
135+
}
136+
_ => {}
137+
}
138+
139+
Ok(())
140+
}

0 commit comments

Comments
 (0)