From 2416a28b090c4a7bc94bcda0a9f5a9a5e383390c Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Mon, 14 Jun 2021 12:58:00 +0200 Subject: [PATCH 1/4] can almost create message --- Cargo.lock | 28 -------------------- Cargo.toml | 2 -- rustfmt.toml | 1 + src/autorole.rs | 68 ++++++++++++++++++++++++++++++++----------------- src/commands.rs | 7 +---- src/main.rs | 8 +++--- 6 files changed, 51 insertions(+), 63 deletions(-) create mode 100644 rustfmt.toml diff --git a/Cargo.lock b/Cargo.lock index cc065dc..edad3d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,15 +6,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - [[package]] name = "async-trait" version = "0.1.50" @@ -465,8 +456,6 @@ dependencies = [ name = "killjoy_turret" version = "0.1.0" dependencies = [ - "lazy_static", - "regex", "serde", "serde_json", "serenity", @@ -719,23 +708,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - [[package]] name = "reqwest" version = "0.11.3" diff --git a/Cargo.toml b/Cargo.toml index 8e298a6..973882c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,6 @@ edition = "2018" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -regex = "1.5.4" -lazy_static = "1.4.0" [dependencies.serenity] version = "0.10.7" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..866c756 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 \ No newline at end of file diff --git a/src/autorole.rs b/src/autorole.rs index 8305dfe..41f0fff 100644 --- a/src/autorole.rs +++ b/src/autorole.rs @@ -5,15 +5,6 @@ use serenity::framework::standard::{ }; use serenity::model::prelude::*; use serenity::prelude::*; -use serenity::{ - async_trait, - collector::MessageCollectorBuilder, - framework::standard::{help_commands, CommandGroup, HelpOptions, StandardFramework}, - futures::stream::StreamExt, - http::Http, - model::prelude::*, - prelude::*, -}; use std::collections::HashMap; use std::time::Duration; @@ -28,13 +19,26 @@ impl TypeMapKey for AutoRoleDataKey { #[description = "Auto role related commands"] struct AutoRole; +const DEFAULT_MESSAGE: &'static str = "Select your role"; + #[command] +#[aliases("a")] #[description = "Add auto assign roles"] #[usage = "sdakhnfj"] -async fn autorole(ctx: &Context, msg: &Message, args: Args) -> CommandResult { +async fn autorole(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { let http = &ctx.http; - let mut data = ctx.data.write().await; - let mut auto_roles = data.get_mut::(); + + let target_channel = args.single::(); + args.quoted(); + let message = args.single::().unwrap_or(DEFAULT_MESSAGE.to_string()); + + if let Err(_) = target_channel { + msg.channel_id + .say(http, "You need to mention the channel the message should be sent in") + .await?; + return Ok(()); + } + let target_channel = target_channel.unwrap(); msg.channel_id .send_message(http, |m| { @@ -51,22 +55,40 @@ async fn autorole(ctx: &Context, msg: &Message, args: Args) -> CommandResult { }) .await?; - while let Some(answer) = &msg - .author - .await_reply(&ctx) - .timeout(Duration::from_secs(30)) - .await - { - if let Some(emote) = answer.content.split(' ').next() { - lazy_static! { + let mut roles = vec![]; + while let Some(answer) = &msg.author.await_reply(&ctx).timeout(Duration::from_secs(30)).await { + if answer.content.contains("cancel") { + return Ok(()); + } + if let Some(role) = answer.mention_roles.get(0) { + if let Some(emote) = answer.content.split(' ').next() { + println!("should add emote: {} for role {}", emote, role.0); + answer.react(http, '☑').await?; + + roles.push((emote.to_string(), role.0)); + } else { + break; } - - println!("should add emote: {}", emote); - answer.react(http, '☑').await?; + } else { + break; } } + msg.channel_id.say(http, "done").await?; + + target_channel + .send_message(http, |m| { + m.embed(|e| { + e.title(message); + e.field("neutral", "same", false) + }) + }) + .await?; + + let mut data = ctx.data.write().await; + let mut auto_roles = data.get_mut::().unwrap(); + Ok(()) } diff --git a/src/commands.rs b/src/commands.rs index 466621e..3c9c6cf 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,14 +1,9 @@ use std::collections::HashSet; use serenity::client::Context; -use serenity::framework::standard::{ - help_commands, - macros::{command, group, help}, - Args, CommandGroup, CommandResult, HelpOptions, -}; +use serenity::framework::standard::{help_commands, macros::help, Args, CommandGroup, CommandResult, HelpOptions}; use serenity::model::channel::Message; use serenity::model::id::UserId; -use serenity::utils::{content_safe, ContentSafeOptions}; #[help] #[individual_command_tip = "Killjoy Turret Command Info"] diff --git a/src/main.rs b/src/main.rs index 40bb034..53533fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,16 +2,16 @@ mod autorole; mod commands; mod general; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::fs; +use crate::autorole::{AutoRoleData, AutoRoleDataKey, AUTOROLE_GROUP}; +use crate::commands::MY_HELP; use serenity::client::Context; use serenity::framework::StandardFramework; use serenity::http::Http; -use serenity::model::id::{ChannelId, UserId}; +use serenity::model::id::UserId; use serenity::{async_trait, model::gateway::Ready, prelude::*}; -use crate::autorole::{AUTOROLE_GROUP, AutoRoleDataKey, AutoRoleData}; -use crate::commands::MY_HELP; struct Handler; From 9e34b1a6a0f26bd1bea2d73edb359688c4f86f68 Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Tue, 15 Jun 2021 13:42:34 +0200 Subject: [PATCH 2/4] sends the message --- src/autorole.rs | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/autorole.rs b/src/autorole.rs index 41f0fff..866233f 100644 --- a/src/autorole.rs +++ b/src/autorole.rs @@ -6,6 +6,7 @@ use serenity::framework::standard::{ use serenity::model::prelude::*; use serenity::prelude::*; use std::collections::HashMap; +use std::str::FromStr; use std::time::Duration; pub struct AutoRoleDataKey; @@ -65,8 +66,20 @@ async fn autorole(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult if let Some(emote) = answer.content.split(' ').next() { println!("should add emote: {} for role {}", emote, role.0); answer.react(http, '☑').await?; - - roles.push((emote.to_string(), role.0)); + match role.to_role_cached(&ctx).await { + Some(role) => match EmojiIdentifier::from_str(emote) { + Ok(emojiIdent) => roles.push((emojiIdent, role)), + Err(_) => { + answer.channel_id.say(http, "Could not find emoji").await?; + } + }, + None => { + answer + .channel_id + .say(http, "Could not find role, try again or use another role") + .await?; + } + } } else { break; } @@ -75,17 +88,29 @@ async fn autorole(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult } } + if roles.len() == 0 { + msg.channel_id.say(http, "No roles were entered.").await?; + return Ok(()); + } + msg.channel_id.say(http, "done").await?; - target_channel + let reaction_message = target_channel .send_message(http, |m| { m.embed(|e| { - e.title(message); - e.field("neutral", "same", false) + e.title(message).fields( + roles + .iter() + .map(|(emote, role)| (&role.name, format!("<:{}:{}>", emote.name, emote.id), true)), + ) }) }) .await?; + for data in roles { + reaction_message.react(http, data.0).await?; + } + let mut data = ctx.data.write().await; let mut auto_roles = data.get_mut::().unwrap(); From c41c3ff851a1c917cf6566c0b16cec7057ef81af Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Tue, 15 Jun 2021 13:53:08 +0200 Subject: [PATCH 3/4] does stuff --- src/autorole.rs | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/autorole.rs b/src/autorole.rs index 866233f..6532370 100644 --- a/src/autorole.rs +++ b/src/autorole.rs @@ -107,37 +107,32 @@ async fn autorole(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult }) .await?; - for data in roles { - reaction_message.react(http, data.0).await?; + for data in &roles { + reaction_message.react(http, data.0.clone()).await?; } let mut data = ctx.data.write().await; let mut auto_roles = data.get_mut::().unwrap(); + roles + .iter() + .map(|(emoji, role)| ((emoji.id, reaction_message.id), role.id)) + .for_each(|(key, value)| { + auto_roles.messages.insert(key, value); + }); + Ok(()) } #[derive(Serialize, Deserialize)] pub struct AutoRoleData { - messages: Vec>, + messages: HashMap<(EmojiId, MessageId), RoleId>, } impl Default for AutoRoleData { fn default() -> Self { Self { - messages: Vec::default(), + messages: HashMap::default(), } } } - -#[derive(Serialize, Deserialize, Eq, PartialEq, Hash)] -struct DEmote { - name: String, - id: String, -} - -#[derive(Serialize, Deserialize, Eq, PartialEq)] -struct DRole { - name: String, - id: String, -} From 51ecb30f61faf4eb7e0619bb5f1aa4008a54f51e Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Mon, 21 Jun 2021 13:49:11 +0200 Subject: [PATCH 4/4] reaction listener --- src/autorole.rs | 22 ++++++++++++++++++++++ src/main.rs | 18 ++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/autorole.rs b/src/autorole.rs index 6532370..cd2f6f3 100644 --- a/src/autorole.rs +++ b/src/autorole.rs @@ -1,8 +1,10 @@ +use crate::Handler; use serde::{Deserialize, Serialize}; use serenity::framework::standard::{ macros::{command, group}, Args, CommandResult, }; +use serenity::model::channel::ReactionType::Custom; use serenity::model::prelude::*; use serenity::prelude::*; use std::collections::HashMap; @@ -124,6 +126,26 @@ async fn autorole(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult Ok(()) } +// listener + +pub async fn handle_reaction(ctx: &Context, reaction: &Reaction) { + let data = ctx.data.read().await; + let mut auto_roles = data.get::().unwrap(); + if let Custom { animated, id, name } = &reaction.emoji { + if let Some(role) = auto_roles.messages.get(&(*id, reaction.message_id)) { + match &reaction.member { + None => { + println!("Missing member on reaction"); + // remove reaction + } + Some(member) => { + // add role + } + } + } + } +} + #[derive(Serialize, Deserialize)] pub struct AutoRoleData { messages: HashMap<(EmojiId, MessageId), RoleId>, diff --git a/src/main.rs b/src/main.rs index 53533fe..d41dae8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,28 @@ -mod autorole; -mod commands; -mod general; - use std::collections::HashSet; use std::fs; -use crate::autorole::{AutoRoleData, AutoRoleDataKey, AUTOROLE_GROUP}; -use crate::commands::MY_HELP; use serenity::client::Context; use serenity::framework::StandardFramework; use serenity::http::Http; use serenity::model::id::UserId; +use serenity::model::prelude::*; use serenity::{async_trait, model::gateway::Ready, prelude::*}; +use crate::autorole::{AutoRoleData, AutoRoleDataKey, AUTOROLE_GROUP}; +use crate::commands::MY_HELP; + +mod autorole; +mod commands; +mod general; + struct Handler; #[async_trait] impl EventHandler for Handler { + async fn reaction_add(&self, ctx: Context, add_reaction: Reaction) { + autorole::handle_reaction(&ctx, &add_reaction) + } + async fn ready(&self, _: Context, ready: Ready) { println!("{} is connected!", ready.user.name); }