2021-11-25 21:56:33 +01:00
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 (
2021-11-25 22:29:25 +01:00
& std ::fs ::read_to_string ( " reaction_config.json " ) . unwrap_or_else ( | _ | " [] " . to_string ( ) ) ,
2021-11-25 21:56:33 +01:00
)
. expect ( " Could not read reaction config " ) ;
2021-11-25 22:19:04 +01:00
eprintln! ( " Read reaction config: {:?} " , c ) ;
2021-11-25 21:56:33 +01:00
c
} ;
}
macro_rules ! role_action {
2021-11-25 22:05:46 +01:00
( $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 ?
}
}
2021-11-25 21:56:33 +01:00
} ;
}
pub ( crate ) async fn reaction_added ( ctx : Context , reaction : Reaction ) -> serenity ::Result < ( ) > {
2021-11-25 22:29:25 +01:00
role_action! ( reaction , ctx , add_role ) ;
Ok ( ( ) )
2021-11-25 21:56:33 +01:00
}
pub ( crate ) async fn reaction_removed ( ctx : Context , reaction : Reaction ) -> serenity ::Result < ( ) > {
2021-11-25 22:29:25 +01:00
role_action! ( reaction , ctx , remove_role ) ;
Ok ( ( ) )
2021-11-25 21:56:33 +01:00
}
#[ 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 ) ] ) ,
} ,
] ,
) ;
}
}