diff options
| author | Fuwn <[email protected]> | 2021-06-25 03:55:45 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-06-25 03:55:45 -0700 |
| commit | c6df8a46d4f62739318a1b7bfe7b744244cd9138 (patch) | |
| tree | a6b42f316f4f21de43909f07051db9fc8cf0a1d6 | |
| parent | feat(cmds): say command (diff) | |
| download | dos-bot-c6df8a46d4f62739318a1b7bfe7b744244cd9138.tar.xz dos-bot-c6df8a46d4f62739318a1b7bfe7b744244cd9138.zip | |
feat(cmds): create, remove, and count commands
| -rw-r--r-- | Cargo.toml | 5 | ||||
| -rw-r--r-- | src/commands.rs | 116 | ||||
| -rw-r--r-- | src/config.rs | 9 | ||||
| -rw-r--r-- | src/database.rs | 58 | ||||
| -rw-r--r-- | src/main.rs | 24 |
5 files changed, 189 insertions, 23 deletions
@@ -18,13 +18,16 @@ serenity = { version = "0.10.8", features = ["cache", "framework", "standard_fra dotenv = "0.15.0" tokio = { version = "1.7.1", features = ["macros", "signal", "rt-multi-thread"] } config = "0.11.0" +lazy_static = "1.4.0" +simple-error = "0.2.3" +array_tool = "1.0.3" # Serialization serde = "1.0.126" serde_derive = "1.0.126" # Database -redis = "0.20.2" +simplebase = "0.3.35" # Logging log = "0.4.14" diff --git a/src/commands.rs b/src/commands.rs index fb31f14..26dbfbc 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,6 +1,7 @@ // Copyright (C) 2021-2021 Fuwn // SPDX-License-Identifier: GPL-3.0-only +use array_tool::vec::Intersect; use serenity::{ framework::standard::{macros::command, Args, CommandResult}, model::prelude::*, @@ -25,8 +26,12 @@ pub async fn help(ctx: &Context, msg: &Message) -> CommandResult { commands ======== -help - you are here -ping - pong! +help - you are here +ping - pong! + +create - create a role reaction +remove - remove a role reaction +count - count the role reactions information =========== @@ -62,3 +67,110 @@ pub async fn say(ctx: &Context, msg: &Message, args: Args) -> CommandResult { Ok(()) } + +#[command] +pub async fn create(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { + if msg + .guild(&ctx.cache) + .await + .unwrap() + .member(&ctx.http, msg.author.id) + .await? + .roles + .intersect( + crate::config::Config::get() + .admin_roles + .iter() + .map(|r| RoleId(*r)) + .collect(), + ) + .is_empty() + { + msg + .channel_id + .say(&ctx.http, "invalid permissions!") + .await?; + + return Ok(()); + } + + crate::database::Database::new() + .create_reaction_role(args.single::<u64>()?, args.single::<u64>()?); + + msg + .channel_id + .say(&ctx.http, "created created role reaction") + .await?; + + Ok(()) +} + +#[command] +pub async fn remove(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { + if msg + .guild(&ctx.cache) + .await + .unwrap() + .member(&ctx.http, msg.author.id) + .await? + .roles + .intersect( + crate::config::Config::get() + .admin_roles + .iter() + .map(|r| RoleId(*r)) + .collect(), + ) + .is_empty() + { + msg + .channel_id + .say(&ctx.http, "invalid permissions!") + .await?; + + return Ok(()); + } + + crate::database::Database::new().remove_reaction_role(args.single::<u64>()?); + + msg + .channel_id + .say(&ctx.http, "removed role reaction") + .await?; + + Ok(()) +} + +#[command] +pub async fn count(ctx: &Context, msg: &Message) -> CommandResult { + if msg + .guild(&ctx.cache) + .await + .unwrap() + .member(&ctx.http, msg.author.id) + .await? + .roles + .intersect( + crate::config::Config::get() + .admin_roles + .iter() + .map(|r| RoleId(*r)) + .collect(), + ) + .is_empty() + { + msg + .channel_id + .say(&ctx.http, "invalid permissions!") + .await?; + + return Ok(()); + } + + msg + .channel_id + .say(&ctx.http, crate::database::Database::new().count()) + .await?; + + Ok(()) +} diff --git a/src/config.rs b/src/config.rs index afdba2d..57fc823 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,14 +5,9 @@ use config::ConfigError; use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] -pub struct RolesRole { - pub message: u64, - pub role: u64, -} -#[derive(Serialize, Deserialize, Debug)] pub struct Config { - pub token: String, - pub roles: Vec<RolesRole>, + pub token: String, + pub admin_roles: Vec<u64>, } impl Config { #[allow(future_prelude_collision)] diff --git a/src/database.rs b/src/database.rs new file mode 100644 index 0000000..9dc9f5a --- /dev/null +++ b/src/database.rs @@ -0,0 +1,58 @@ +// Copyright (C) 2021-2021 Fuwn +// SPDX-License-Identifier: GPL-3.0-only + +use simple_error::SimpleResult; +#[allow(clippy::wildcard_imports)] +use simplebase::engine::*; + +pub struct Database(pub RecordData); +impl Database { + #[must_use] + pub fn new() -> Self { + if std::path::Path::new(".dos-bot/db.txt").exists() { + Self(load_hash_database(".dos-bot/db.txt")) + } else { + Self(new_empty_database()) + } + } + + pub fn create_reaction_role(&mut self, message: u64, role: u64) { + self + .0 + .add_record_with_key(message.to_string(), role.to_string()); + + self.0.save_database(".dos-bot/db.txt"); + } + + /// # Panics + /// if the record index is unable to be parsed. + pub fn remove_reaction_role(&mut self, message: u64) { + self.0.delete_record( + self.0.find_key(message.to_string().as_str())[0] + .parse::<usize>() + .unwrap(), + ); + + self.0.save_database(".dos-bot/db.txt"); + } + + /// # Errors + /// if no record is found for the given `message`. + /// + /// # Panics + /// if the record is unable to be parsed. + pub fn get_reaction_role(&self, message: u64) -> SimpleResult<u64> { + let record = self.0.find_key(message.to_string().as_str()); + if record.is_empty() { + simple_error::bail!("no record found"); + } + + Ok(record[1].clone().parse::<u64>().unwrap()) + } + + #[must_use] + pub fn count(&self) -> String { self.0.record_counter.to_string() } +} +impl Default for Database { + fn default() -> Self { Self::new() } +} diff --git a/src/main.rs b/src/main.rs index 7a938e9..3e2bfb7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ pub mod commands; pub mod config; +pub mod database; #[macro_use] extern crate log; @@ -59,16 +60,12 @@ struct Handler; impl EventHandler for Handler { async fn reaction_add(&self, ctx: Context, reaction: Reaction) { if let Some(guild) = reaction.guild_id { - if let Some(c) = config::Config::get() - .roles - .iter() - .find(|x| x.message == reaction.message_id.0) - { + if let Ok(role) = database::Database::new().get_reaction_role(reaction.message_id.0) { guild .member(&ctx, reaction.user_id.expect("unable to locate user id")) .await .expect("unable to locate member") - .add_role(&ctx, c.role) + .add_role(&ctx, role) .await .expect("unable to add role to member"); } @@ -77,16 +74,12 @@ impl EventHandler for Handler { async fn reaction_remove(&self, ctx: Context, reaction: Reaction) { if let Some(guild) = reaction.guild_id { - if let Some(c) = config::Config::get() - .roles - .iter() - .find(|x| x.message == reaction.message_id.0) - { + if let Ok(role) = database::Database::new().get_reaction_role(reaction.message_id.0) { guild .member(&ctx, reaction.user_id.expect("unable to locate user id")) .await .expect("unable to locate member") - .remove_role(&ctx, c.role) + .remove_role(&ctx, role) .await .expect("unable to add role to member"); } @@ -106,6 +99,10 @@ impl EventHandler for Handler { #[commands(ping, help, say)] struct General; +#[group] +#[commands(create, remove, count)] +struct RoleReactions; + #[tokio::main] async fn main() { dotenv::dotenv().ok(); @@ -127,7 +124,8 @@ async fn main() { let framework = StandardFramework::new() .configure(|c| c.owners(owners).prefix(">")) - .group(&GENERAL_GROUP); + .group(&GENERAL_GROUP) + .group(&ROLEREACTIONS_GROUP); let mut client = Client::builder(Config::get().token.as_str()) .framework(framework) |