diff options
Diffstat (limited to 'src/commands')
| -rw-r--r-- | src/commands/reactionroles.rs | 132 | 
1 files changed, 125 insertions, 7 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) +} | 
