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 = { 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, } #[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::>(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)]), }, ], ); } }