Make role reactions configurable

This commit is contained in:
kageru 2021-11-25 21:56:33 +01:00
parent cc3aec0b9f
commit d50733c8e9
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
5 changed files with 126 additions and 31 deletions

12
Cargo.lock generated
View File

@ -939,18 +939,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.125"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.125"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
dependencies = [
"proc-macro2",
"quote",
@ -959,9 +959,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.64"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527"
dependencies = [
"itoa",
"ryu",

View File

@ -11,8 +11,8 @@ async-trait = "0.1.42"
itertools = "0.10.0"
lazy_static = "1.4.0"
redis = "0.20.0"
serde = { version = "1.0.123", features = ["derive"] }
serde_json = "1.0.62"
serde = { version = "1.0.130", features = ["derive"] }
serde_json = "1.0.72"
serenity = "0.10.5"
time = "0.2.10"
tokio = { version = "1.2.0", features = ["full"] }

View File

@ -1,3 +1,5 @@
# DIDgeridoo
A bot for people with dissociative identity disorder.
Currently only does and logs name changes and has basic inbox functionality for a single user per instance.
Now also has role assignment via reaction because feature creep.

View File

@ -6,7 +6,7 @@ use serenity::framework::standard::{
macros::{command, group},
CommandResult, StandardFramework,
};
use serenity::model::channel::{Reaction, ReactionType};
use serenity::model::channel::Reaction;
use serenity::model::{
channel::Message,
id::{ChannelId, GuildId, UserId},
@ -17,6 +17,7 @@ use std::fs::File;
use std::io::{self, BufRead, BufReader};
use time::Duration;
mod inbox;
mod reactions;
const APPLICATION_NAME: &str = "didgeridoo";
const INBOX_OWNER: UserId = UserId(354694403798990848);
@ -33,20 +34,6 @@ macro_rules! send_or_log {
};
}
macro_rules! role_action {
($reaction: expr, $ctx: expr, $action: ident) => {
$reaction
.guild_id
.unwrap()
.member(&$ctx, $reaction.user_id.unwrap())
.await
.unwrap()
.$action(&$ctx, 356421827708321795)
.await
.unwrap()
};
}
#[group]
#[commands(name, message, question, inbox)]
struct Fluff;
@ -64,18 +51,20 @@ impl EventHandler for Handler {
}
async fn reaction_add(&self, ctx: Context, reaction: Reaction) {
if reaction.message_id == 911630315376738384
&& reaction.emoji == ReactionType::Unicode(String::from("🧪"))
{
role_action!(reaction, ctx, add_role)
if let Err(e) = reactions::reaction_added(ctx, reaction).await {
eprintln!(
"Something went wrong while processing an added reaction: {:?}",
e
);
}
}
async fn reaction_remove(&self, ctx: Context, reaction: Reaction) {
if reaction.message_id == 911630315376738384
&& reaction.emoji == ReactionType::Unicode(String::from("🧪"))
{
role_action!(reaction, ctx, remove_role)
if let Err(e) = reactions::reaction_removed(ctx, reaction).await {
eprintln!(
"Something went wrong while processing an added reaction: {:?}",
e
);
}
}
}

104
src/reactions.rs Normal file
View File

@ -0,0 +1,104 @@
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)]),
},
],
);
}
}