diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/commands/reactionroles.rs | 132 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/models.rs | 2 |
3 files changed, 127 insertions, 9 deletions
diff --git a/src/commands/reactionroles.rs b/src/commands/reactionroles.rs index 8d448ed..65de61a 100644 --- a/src/commands/reactionroles.rs +++ b/src/commands/reactionroles.rs @@ -1,8 +1,10 @@ use std::{str::FromStr, time::Duration}; use crate::{models::ReactionRole, Context, Error}; -use ::serenity::framework::standard::{Args, Delimiter}; -use poise::serenity_prelude::{self as serenity, ArgumentConvert, Emoji, ReactionType}; +use ::serenity::{ + model::{guild::Role, id::ChannelId}, +}; +use poise::serenity_prelude::{self as serenity, ArgumentConvert, Emoji, ReactionType, RoleId}; #[cfg(debug_assertions)] async fn allowed_to_create_roles(ctx: Context<'_>) -> Result<bool, Error> { @@ -174,11 +176,8 @@ pub async fn init( ) .fetch_all(&pool) .await?; - let mut rolelist_formatted = - String::from("Choose the appropriate reaction to gain the role!\n\n"); - for r in reactions { - rolelist_formatted.push_str(&format!("{} - <@&{}>\n", r.reaction, r.role_id)); - } + + let rolelist_formatted = gen_reaction_list(reactions); let title = rolemenu_msg.clone().embeds[0] .title @@ -204,6 +203,95 @@ pub async fn init( Ok(()) } +/// Adds a reaction role to the message +/// +/// Usage: +/// ~rroles add <Message ID> <emoji> <role> +#[poise::command(prefix_command, check = "allowed_to_create_roles")] +pub async fn add( + ctx: Context<'_>, + #[description = "The Message ID"] message_id: u64, + #[description = "The emoji to assign to the role"] emoji: ReactionType, + #[description = "The role to assign to the emoji"] role_name: String, +) -> Result<(), Error> { + { + let pool = ctx.data().pg.lock().unwrap().clone(); + // Make sure the emoji doesn't already exist + if let Ok(_) = sqlx::query!("SELECT * FROM reaction_roles WHERE message_id=$1 AND reaction=$2", message_id.to_string(), emoji.to_string()).fetch_one(&pool).await { + ctx.say("Whoops! That emoji already has something assigned to it! Try either removing it or picking a different emoji").await?; + return Ok(()); + } + let role_menu = sqlx::query_as!( + ReactionRole, + "SELECT * FROM reaction_roles WHERE message_id=$1", + message_id.to_string() + ) + .fetch_one(&pool) + .await?; + let guild = ctx.guild().unwrap(); + let role = guild.role_by_name(&role_name).clone(); + if let Some(r) = role.clone() { + let r = r.clone(); + let channel_id = ChannelId(role_menu.channel_id.parse::<u64>()?); + sqlx::query!("INSERT INTO reaction_roles (channel_id, message_id, guild_id, reaction, role_id) VALUES ($1, $2, $3, $4, $5)", role_menu.channel_id.to_string(), role_menu.message_id.to_string(), ctx.guild_id().unwrap().0.to_string(), emoji.to_string(), r.id.to_string()).execute(&pool).await?; + let all_reactions = sqlx::query_as!( + ReactionRole, + "SELECT * FROM reaction_roles WHERE message_id=$1", + message_id.to_string() + ) + .fetch_all(&pool) + .await?; + let channel = channel_id.to_channel(&ctx.discord()).await?; + let mut menu_msg = channel + .guild() + .unwrap() + .message(ctx.discord(), role_menu.message_id.parse::<u64>()?) + .await?; + + update_menu(ctx, menu_msg).await?; + + ctx.say("Done! I've added that to the list for you").await?; + } else { + ctx.say("Whoops! That role doesn't exist!").await?; + return Ok(()); + } + } + + Ok(()) +} + +/// Removes a reaction from the menu +/// +/// Usage: +/// ~rroles del <Message ID> <emoji> +#[poise::command(prefix_command, check = "allowed_to_create_roles")] +pub async fn del(ctx: Context<'_>, + #[description = "The Message ID of the menu"] + message_id: u64, + #[description = "The emoji you want to remove"] + emoji: ReactionType, + ) -> Result<(), Error> { + { + let pool = ctx.data().pg.lock().unwrap().clone(); + let reaction_with_menu = sqlx::query_as!(ReactionRole, "SELECT * FROM reaction_roles WHERE message_id=$1 AND reaction=$2", message_id.to_string(), emoji.to_string()).fetch_one(&pool).await?; + let channel_id = ChannelId(reaction_with_menu.channel_id.parse::<u64>()?); + let channel = channel_id.to_channel(ctx.discord()).await?; + let mut message = channel.guild().unwrap().message(ctx.discord(), message_id).await?; + + // Delete from DB + // We can just use `ReactionRole.id` here to avoid having to do more complex conditionals + sqlx::query!("DELETE FROM reaction_roles WHERE id=$1", reaction_with_menu.id).execute(&pool).await?; + + message.delete_reaction_emoji(ctx.discord(), emoji).await?; + + update_menu(ctx, message).await?; + } + + ctx.say("Alright! I've removed that emoji from the menu.").await?; + + Ok(()) +} + fn get_reactiontype_display(rt: &ReactionType) -> String { match rt { ReactionType::Unicode(emote) => emote.clone(), @@ -217,3 +305,33 @@ fn get_reactiontype_display(rt: &ReactionType) -> String { _ => String::new(), } } + +fn gen_reaction_list(reacts: Vec<ReactionRole>) -> String { + let mut rolelist_formatted = + String::from("Choose the appropriate reaction to gain the role!\n\n"); + for r in reacts { + rolelist_formatted.push_str(&format!("{} - <@&{}>\n", r.reaction, r.role_id)); + } + rolelist_formatted +} + +async fn update_menu(ctx: Context<'_>, mut msg: serenity::Message) -> Result<serenity::Message, Error> { + { + let pool = ctx.data().pg.lock().unwrap().clone(); + let all_reactions = sqlx::query_as!(ReactionRole, "SELECT * FROM reaction_roles WHERE message_id=$1", msg.id.0.to_string()).fetch_all(&pool).await?; + let rolelist_formatted = gen_reaction_list(all_reactions.clone()); + let title = msg.clone().embeds[0].title.clone().unwrap(); + msg.edit(ctx.discord(), |m| { + m.embed(|e| { + e.title(title); + e.description(rolelist_formatted) + }) + }).await?; + + for r in all_reactions.iter() { + msg.react(ctx.discord(), ReactionType::from_str(&r.reaction)?).await?; + } + } + + Ok(msg) +} diff --git a/src/main.rs b/src/main.rs index 4698fb1..bfd39c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,7 +70,7 @@ async fn main() { commands::osu::osup(), commands::osu::osubm(), poise::Command { - subcommands: vec![commands::reactionroles::init()], + subcommands: vec![commands::reactionroles::init(), commands::reactionroles::add(), commands::reactionroles::del(),], ..commands::reactionroles::rroles() }, ], diff --git a/src/models.rs b/src/models.rs index 4b2e7bb..431204a 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,4 +1,4 @@ -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ReactionRole { pub id: i32, pub channel_id: String, |