105 lines
2.8 KiB
Rust
105 lines
2.8 KiB
Rust
|
use lazy_static::lazy_static;
|
||
|
use serde::Deserialize;
|
||
|
use serenity::{
|
||
|
client::Context,
|
||
|
model::channel::{Reaction, ReactionType},
|
||
|
};
|
||
|
use std::collections::HashMap;
|
||
|
|
||
|
lazy_static! {
|
||
|
static ref ROLE_CONFIG: Vec<ReactableMessage> = {
|
||
|
let c = serde_json::from_str(
|
||
|
&std::fs::read_to_string("reaction_config.json").unwrap_or("[]".to_string()),
|
||
|
)
|
||
|
.expect("Could not read reaction config");
|
||
|
println!("Read reaction config: {:?}", c);
|
||
|
c
|
||
|
};
|
||
|
}
|
||
|
|
||
|
macro_rules! role_action {
|
||
|
($reaction: expr, $ctx: expr, $action: ident, $role_id: expr) => {
|
||
|
$reaction
|
||
|
.guild_id
|
||
|
.expect("Configured message id is not in a guild")
|
||
|
.member(&$ctx, $reaction.user_id.unwrap())
|
||
|
.await?
|
||
|
.$action(&$ctx, $role_id)
|
||
|
.await?
|
||
|
};
|
||
|
}
|
||
|
|
||
|
pub(crate) async fn reaction_added(ctx: Context, reaction: Reaction) -> serenity::Result<()> {
|
||
|
if let Some(rm) = ROLE_CONFIG
|
||
|
.iter()
|
||
|
.find(|c| reaction.message_id == c.message_id)
|
||
|
{
|
||
|
if let ReactionType::Unicode(emoji) = &reaction.emoji {
|
||
|
if let Some(role_id) = rm.roles.get(emoji) {
|
||
|
role_action!(reaction, ctx, add_role, *role_id);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Ok(())
|
||
|
}
|
||
|
pub(crate) async fn reaction_removed(ctx: Context, reaction: Reaction) -> serenity::Result<()> {
|
||
|
if let Some(rm) = ROLE_CONFIG
|
||
|
.iter()
|
||
|
.find(|c| reaction.message_id == c.message_id)
|
||
|
{
|
||
|
if let ReactionType::Unicode(emoji) = &reaction.emoji {
|
||
|
if let Some(role_id) = rm.roles.get(emoji) {
|
||
|
role_action!(reaction, ctx, remove_role, *role_id);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||
|
struct ReactableMessage {
|
||
|
// I hate how this sounds like a Java interface name…
|
||
|
message_id: u64,
|
||
|
roles: HashMap<String, u64>,
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
|
||
|
const TEST_JSON: &str = r#"
|
||
|
[
|
||
|
{
|
||
|
"message_id": 12345,
|
||
|
"roles": {
|
||
|
"💤": 1,
|
||
|
"🐑": 2
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
"message_id": 54321,
|
||
|
"roles": {
|
||
|
"💙": 3,
|
||
|
"♻": 4
|
||
|
}
|
||
|
}
|
||
|
]"#;
|
||
|
|
||
|
#[test]
|
||
|
fn test_role_config_parsing() {
|
||
|
assert_eq!(
|
||
|
serde_json::from_str::<Vec<ReactableMessage>>(TEST_JSON).unwrap(),
|
||
|
[
|
||
|
ReactableMessage {
|
||
|
message_id: 12345,
|
||
|
roles: HashMap::from([("💤".to_string(), 1), ("🐑".to_string(), 2)]),
|
||
|
},
|
||
|
ReactableMessage {
|
||
|
message_id: 54321,
|
||
|
roles: HashMap::from([("💙".to_string(), 3), ("♻".to_string(), 4)]),
|
||
|
},
|
||
|
],
|
||
|
);
|
||
|
}
|
||
|
}
|