From aad93ad7d8b04ec3dc392ea9934bf886b9b8ab00 Mon Sep 17 00:00:00 2001 From: Kappeh Date: Tue, 4 Feb 2025 23:40:01 +0000 Subject: [PATCH] Add context menu commands for showing and editing profiles --- cipher_discord_bot/src/checks.rs | 2 +- cipher_discord_bot/src/commands/mod.rs | 8 +++ .../src/commands/profile/codes.rs | 52 +++++++++---------- .../src/commands/profile/mod.rs | 33 ++++++++++-- 4 files changed, 63 insertions(+), 32 deletions(-) diff --git a/cipher_discord_bot/src/checks.rs b/cipher_discord_bot/src/checks.rs index 2519435..f640f7c 100644 --- a/cipher_discord_bot/src/checks.rs +++ b/cipher_discord_bot/src/checks.rs @@ -10,7 +10,7 @@ where { let roles: Vec<_> = match ctx.author_member().await { Some(member) => member.roles.iter().map(|r| r.get()).collect(), - None => return Ok(false), + None => return Err(AppError::StaffOnly { command_name: ctx.command().qualified_name.clone() }), }; match ctx.data().repository().await?.staff_roles_contains(&roles).await { diff --git a/cipher_discord_bot/src/commands/mod.rs b/cipher_discord_bot/src/commands/mod.rs index fecb0b9..e9b5596 100644 --- a/cipher_discord_bot/src/commands/mod.rs +++ b/cipher_discord_bot/src/commands/mod.rs @@ -16,6 +16,8 @@ where help::help(), pokeapi::pokeapi(), profile::profile(), + profile::cmu_profile_show(), + profile::cmu_profile_edit(), ] } @@ -34,7 +36,13 @@ where R: RepositoryProvider, { for command in commands { + if command.slash_action.is_none() { + // Skip context-menu-only commands + continue; + } + names.push(format!("{}{}", prefix, command.qualified_name.clone())); + if !command.subcommands.is_empty() { let old_len = prefix.len(); prefix.push_str(&command.qualified_name); diff --git a/cipher_discord_bot/src/commands/profile/codes.rs b/cipher_discord_bot/src/commands/profile/codes.rs index 26dc8d1..4c2aa7a 100644 --- a/cipher_discord_bot/src/commands/profile/codes.rs +++ b/cipher_discord_bot/src/commands/profile/codes.rs @@ -220,12 +220,11 @@ where Ok(()) } -/// Edit your friend codes. -#[poise::command(slash_command, guild_only)] -async fn edit(ctx: AppContext<'_, R, R::BackendError>) -> Result<(), AppError> { - let author_id = ctx.author().id.get(); - - let embed = match execute_edit_codes_modal(ctx, author_id).await { +async fn edit_inner( + ctx: AppContext<'_, R, R::BackendError>, + user: &serenity::all::User, +) -> Result<(), AppError> { + let embed = match execute_edit_codes_modal(ctx, user.id.get()).await { Ok(()) => CreateEmbed::new() .title("Changes Saved") .description("Your changes have been saved successfully.") @@ -247,6 +246,24 @@ async fn edit(ctx: AppContext<'_, R, R::Bac Ok(()) } +#[poise::command(context_menu_command = "Edit Friend Codes", guild_only)] +pub async fn cmu_profile_edit( + ctx: AppContext<'_, R, R::BackendError>, + user: serenity::all::User, +) -> Result<(), AppError> { + if ctx.author().id != user.id && !crate::checks::is_staff(ctx.into()).await? { + return Err(AppError::StaffOnly { command_name: ctx.command().qualified_name.clone() }); + } + + edit_inner(ctx, &user).await +} + +/// Edit your friend codes. +#[poise::command(slash_command, guild_only)] +async fn edit(ctx: AppContext<'_, R, R::BackendError>) -> Result<(), AppError> { + edit_inner(ctx, ctx.author()).await +} + /// Edit any user's friend codes. #[poise::command( slash_command, @@ -259,26 +276,5 @@ async fn overwrite( #[description = "The profile to edit."] member: Member, ) -> Result<(), AppError> { - let member_id = member.user.id.get(); - - let embed = match execute_edit_codes_modal(ctx, member_id).await { - Ok(()) => CreateEmbed::new() - .title("Changes Saved") - .description("Your changes have been saved successfully.") - .color(crate::utils::bot_color(&ctx).await), - Err(EditError::ValidationError(errors)) => CreateEmbed::new() - .title("Validation Error") - .description(errors.join("\n")) - .color(Color::RED), - Err(EditError::SerenityError(err)) => return Err(AppError::from(err)), - Err(EditError::RepositoryError(err)) => return Err(AppError::from(err)), - }; - - let reply = CreateReply::default() - .embed(embed) - .ephemeral(true); - - ctx.send(reply).await?; - - Ok(()) + edit_inner(ctx, &member.user).await } diff --git a/cipher_discord_bot/src/commands/profile/mod.rs b/cipher_discord_bot/src/commands/profile/mod.rs index c28968c..d507b40 100644 --- a/cipher_discord_bot/src/commands/profile/mod.rs +++ b/cipher_discord_bot/src/commands/profile/mod.rs @@ -2,12 +2,16 @@ use cipher_core::repository::user_repository::UserRepository; use cipher_core::repository::RepositoryProvider; use poise::CreateReply; use serenity::all::CreateEmbed; +use serenity::all::Member; +use serenity::all::User; use crate::app::AppContext; use crate::app::AppError; mod codes; +pub use codes::cmu_profile_edit; + /// Edit and show profiles. #[poise::command( slash_command, @@ -22,6 +26,21 @@ pub async fn profile( Ok(()) } +#[poise::command(context_menu_command = "Show User Profile", guild_only)] +pub async fn cmu_profile_show( + ctx: AppContext<'_, R, R::BackendError>, + user: User, +) -> Result<(), AppError> { + let guild = match ctx.guild_id() { + Some(guild) => guild, + None => return Ok(()), + }; + + let member = guild.member(ctx, user.id).await?; + + show_inner(ctx, member, true).await +} + /// Show your profile or someone else's. #[poise::command(slash_command, guild_only)] async fn show( @@ -32,13 +51,21 @@ async fn show( #[description = "Hide reply from other users. Defaults to True."] ephemeral: Option, ) -> Result<(), AppError> { - let mut repo = ctx.data.repository().await?; - let member = match option_member { Some(member) => member, None => ctx.author_member().await.ok_or(AppError::UnknownCacheOrHttpError)?.into_owned(), }; + show_inner(ctx, member, ephemeral.unwrap_or(true)).await +} + +async fn show_inner( + ctx: AppContext<'_, R, R::BackendError>, + member: Member, + ephemeral: bool, +) -> Result<(), AppError> { + let mut repo = ctx.data.repository().await?; + let avatar_url = crate::utils::member_avatar_url(&member); let embed_color = match member.colour(ctx) { @@ -76,7 +103,7 @@ async fn show( let reply = CreateReply::default() .embed(embed) - .ephemeral(ephemeral.unwrap_or(true)); + .ephemeral(ephemeral); ctx.send(reply).await?;