didgeridoo/src/reactions.rs

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)]),
},
],
);
}
}