95 lines
2.6 KiB
Rust
95 lines
2.6 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_else(|_| "[]".to_string()),
|
|
)
|
|
.expect("Could not read reaction config");
|
|
eprintln!("Read reaction config: {:?}", c);
|
|
c
|
|
};
|
|
}
|
|
|
|
macro_rules! role_action {
|
|
($reaction: expr, $ctx: expr, $action: ident) => {
|
|
if let ReactionType::Unicode(emoji) = &$reaction.emoji {
|
|
if let Some(&role_id) = ROLE_CONFIG
|
|
.iter()
|
|
.find(|c| $reaction.message_id == c.message_id)
|
|
.and_then(|rm| rm.roles.get(emoji))
|
|
{
|
|
$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<()> {
|
|
role_action!(reaction, ctx, add_role);
|
|
Ok(())
|
|
}
|
|
pub(crate) async fn reaction_removed(ctx: Context, reaction: Reaction) -> serenity::Result<()> {
|
|
role_action!(reaction, ctx, remove_role);
|
|
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)]),
|
|
},
|
|
],
|
|
);
|
|
}
|
|
}
|