Add context menu commands for showing and editing profiles

This commit is contained in:
2025-02-04 23:40:01 +00:00
parent c843fec323
commit aad93ad7d8
4 changed files with 63 additions and 32 deletions

View File

@@ -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 {

View File

@@ -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);

View File

@@ -220,12 +220,11 @@ where
Ok(())
}
/// Edit your friend codes.
#[poise::command(slash_command, guild_only)]
async fn edit<R: RepositoryProvider + Send + Sync>(ctx: AppContext<'_, R, R::BackendError>) -> Result<(), AppError<R::BackendError>> {
let author_id = ctx.author().id.get();
let embed = match execute_edit_codes_modal(ctx, author_id).await {
async fn edit_inner<R: RepositoryProvider + Send + Sync>(
ctx: AppContext<'_, R, R::BackendError>,
user: &serenity::all::User,
) -> Result<(), AppError<R::BackendError>> {
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<R: RepositoryProvider + Send + Sync>(ctx: AppContext<'_, R, R::Bac
Ok(())
}
#[poise::command(context_menu_command = "Edit Friend Codes", guild_only)]
pub async fn cmu_profile_edit<R: RepositoryProvider + Send + Sync>(
ctx: AppContext<'_, R, R::BackendError>,
user: serenity::all::User,
) -> Result<(), AppError<R::BackendError>> {
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<R: RepositoryProvider + Send + Sync>(ctx: AppContext<'_, R, R::BackendError>) -> Result<(), AppError<R::BackendError>> {
edit_inner(ctx, ctx.author()).await
}
/// Edit any user's friend codes.
#[poise::command(
slash_command,
@@ -259,26 +276,5 @@ async fn overwrite<R: RepositoryProvider + Send + Sync>(
#[description = "The profile to edit."]
member: Member,
) -> Result<(), AppError<R::BackendError>> {
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
}

View File

@@ -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<R: RepositoryProvider + Send + Sync>(
Ok(())
}
#[poise::command(context_menu_command = "Show User Profile", guild_only)]
pub async fn cmu_profile_show<R: RepositoryProvider + Send + Sync>(
ctx: AppContext<'_, R, R::BackendError>,
user: User,
) -> Result<(), AppError<R::BackendError>> {
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<R: RepositoryProvider + Send + Sync>(
@@ -32,13 +51,21 @@ async fn show<R: RepositoryProvider + Send + Sync>(
#[description = "Hide reply from other users. Defaults to True."]
ephemeral: Option<bool>,
) -> Result<(), AppError<R::BackendError>> {
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<R: RepositoryProvider + Send + Sync>(
ctx: AppContext<'_, R, R::BackendError>,
member: Member,
ephemeral: bool,
) -> Result<(), AppError<R::BackendError>> {
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<R: RepositoryProvider + Send + Sync>(
let reply = CreateReply::default()
.embed(embed)
.ephemeral(ephemeral.unwrap_or(true));
.ephemeral(ephemeral);
ctx.send(reply).await?;