apparently you can only have 5 context menu commands per type

This commit is contained in:
13xforever
2025-03-24 20:19:35 +05:00
parent 252d24bbd8
commit d3d1570111
7 changed files with 180 additions and 242 deletions

View File

@@ -1,71 +0,0 @@
using CompatBot.Database.Providers;
using DSharpPlus.Commands.Processors.UserCommands;
namespace CompatBot.Commands;
[Description("Used to manage bot moderators"), RequiresBotSudoerRole]
internal static class Mod
{
[Command("💛 Give bot mod permissions"), SlashCommandTypes(DiscordApplicationCommandType.UserContextMenu)]
public static async ValueTask Add(UserCommandContext ctx, DiscordUser user)
{
if (await ModProvider.AddAsync(user.Id).ConfigureAwait(false))
{
var response = new DiscordInteractionResponseBuilder()
.WithContent($"{Config.Reactions.Success} {user.Mention} was successfully added as moderator!")
.AddMention(UserMention.All);
await ctx.RespondAsync(response).ConfigureAwait(false);
}
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {user.Mention} is already a moderator", ephemeral: true).ConfigureAwait(false);
}
[Command("💔 Remove bot mod permissions"), SlashCommandTypes(DiscordApplicationCommandType.UserContextMenu)]
public static async ValueTask Remove(UserCommandContext ctx, DiscordUser user)
{
if (ctx.Client.CurrentApplication.Owners?.Any(u => u.Id == user.Id) ?? false)
{
await ctx.RespondAsync($"{Config.Reactions.Denied} Why would you even try this?! Alerting {user.Mention}").ConfigureAwait(false);
var dm = await user.CreateDmChannelAsync().ConfigureAwait(false);
await dm.SendMessageAsync($@"Just letting you know that {ctx.User.Mention} just tried to strip you off of your mod role ¯\\\_(ツ)\_/¯").ConfigureAwait(false);
}
else if (await ModProvider.RemoveAsync(user.Id).ConfigureAwait(false))
await ctx.RespondAsync($"{Config.Reactions.Success} {user.Mention} removed as bot moderator", ephemeral: true).ConfigureAwait(false);
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {user.Mention} is not a bot moderator", ephemeral: true).ConfigureAwait(false);
}
[Command("💜 Give bot admin permissions"), SlashCommandTypes(DiscordApplicationCommandType.UserContextMenu)]
public static async ValueTask Sudo(UserCommandContext ctx, DiscordUser moderator)
{
if (ModProvider.IsMod(moderator.Id))
{
if (await ModProvider.MakeSudoerAsync(moderator.Id).ConfigureAwait(false))
await ctx.RespondAsync($"{Config.Reactions.Success} {moderator.Mention} is now a sudoer").ConfigureAwait(false);
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {moderator.Mention} is already a sudoer", ephemeral: true).ConfigureAwait(false);
}
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {moderator.Mention} is not a moderator (yet)", ephemeral: true).ConfigureAwait(false);
}
[Command("💔 Remove bot admin permissions"), SlashCommandTypes(DiscordApplicationCommandType.UserContextMenu)]
public static async ValueTask Unsudo(UserCommandContext ctx, DiscordUser sudoer)
{
if (ctx.Client.CurrentApplication.Owners?.Any(u => u.Id == sudoer.Id) ?? false)
{
await ctx.RespondAsync($"{Config.Reactions.Denied} Why would you even try this?! Alerting {sudoer.Mention}").ConfigureAwait(false);
var dm = await sudoer.CreateDmChannelAsync().ConfigureAwait(false);
await dm.SendMessageAsync($@"Just letting you know that {ctx.User.Mention} just tried to strip you off of your bot admin permissions ¯\\_(ツ)_/¯").ConfigureAwait(false);
}
else if (ModProvider.IsMod(sudoer.Id))
{
if (await ModProvider.UnmakeSudoerAsync(sudoer.Id).ConfigureAwait(false))
await ctx.RespondAsync($"{Config.Reactions.Success} {sudoer.Mention} is no longer a bot admin", ephemeral: true).ConfigureAwait(false);
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {sudoer.Mention} is not a bot admin", ephemeral: true).ConfigureAwait(false);
}
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {sudoer.Mention} is not even a bot mod!", ephemeral: true).ConfigureAwait(false);
}
}

View File

@@ -11,6 +11,8 @@ namespace CompatBot.Commands;
[Description("Manage users who has forced nickname.")]
internal static class ForcedNicknames
{
// limited to 5 commands per menu
[Command("📛 Enforce nickname"), RequiresBotModRole, SlashCommandTypes(DiscordApplicationCommandType.UserContextMenu)]
[Description("Enforce specific nickname for a particular user permanently")]
public static async ValueTask Rename(UserCommandContext ctx, DiscordUser discordUser)

View File

@@ -16,7 +16,9 @@ internal static class MessageMenuCommands
[Description("12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901")]
public async ValueTask AnalyzerTest(){}
*/
// limited to 5 commands per menu
// anyone can use this
[Command("💬 Explain"), SlashCommandTypes(DiscordApplicationCommandType.MessageContextMenu)]
public static async ValueTask ShowToUser(MessageCommandContext ctx, DiscordMessage replyTo)
@@ -125,6 +127,7 @@ internal static class MessageMenuCommands
}
/*
[Command("🔇 Shut up bot"), RequiresWhitelistedRole, SlashCommandTypes(DiscordApplicationCommandType.MessageContextMenu)]
public static async ValueTask Shutup(MessageCommandContext ctx, DiscordMessage message)
{
@@ -141,7 +144,7 @@ internal static class MessageMenuCommands
await ctx.RespondAsync($"{Config.Reactions.Failure} Message is too old to remove", ephemeral: true).ConfigureAwait(false);
return;
}
*/
#1#
try
{
@@ -154,6 +157,7 @@ internal static class MessageMenuCommands
await ctx.RespondAsync($"{Config.Reactions.Failure} Failed to remove bot message: {e.Message}".Trim(EmbedPager.MaxMessageLength), ephemeral: true).ConfigureAwait(false);
}
}
*/
// only bot mods can use this
[Command("👎 Toggle bad update"), RequiresBotModRole, SlashCommandTypes(DiscordApplicationCommandType.MessageContextMenu)]

View File

@@ -0,0 +1,92 @@
using CompatBot.Database.Providers;
namespace CompatBot.Commands;
internal static partial class Sudo
{
[Command("mod"), RequiresBotSudoerRole]
[Description("Used to manage bot moderators")]
internal static class Mod
{
[Command("add")]
public static async ValueTask Add(SlashCommandContext ctx, DiscordUser user)
{
if (await ModProvider.AddAsync(user.Id).ConfigureAwait(false))
{
var response = new DiscordInteractionResponseBuilder()
.WithContent($"{Config.Reactions.Success} {user.Mention} was successfully added as moderator!")
.AddMention(UserMention.All);
await ctx.RespondAsync(response).ConfigureAwait(false);
}
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {user.Mention} is already a moderator", ephemeral: true).ConfigureAwait(false);
}
[Command("remove")]
public static async ValueTask Remove(SlashCommandContext ctx, DiscordUser user)
{
if (ctx.Client.CurrentApplication.Owners?.Any(u => u.Id == user.Id) ?? false)
{
await ctx.RespondAsync($"{Config.Reactions.Denied} Why would you even try this?! Alerting {user.Mention}").ConfigureAwait(false);
var dm = await user.CreateDmChannelAsync().ConfigureAwait(false);
await dm.SendMessageAsync($@"Just letting you know that {ctx.User.Mention} just tried to strip you off of your mod role ¯\\\_(ツ)\_/¯").ConfigureAwait(false);
}
else if (await ModProvider.RemoveAsync(user.Id).ConfigureAwait(false))
await ctx.RespondAsync($"{Config.Reactions.Success} {user.Mention} removed as bot moderator", ephemeral: true).ConfigureAwait(false);
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {user.Mention} is not a bot moderator", ephemeral: true).ConfigureAwait(false);
}
[Command("sudo")]
public static async ValueTask Sudo(SlashCommandContext ctx, DiscordUser moderator)
{
if (ModProvider.IsMod(moderator.Id))
{
if (await ModProvider.MakeSudoerAsync(moderator.Id).ConfigureAwait(false))
await ctx.RespondAsync($"{Config.Reactions.Success} {moderator.Mention} is now a sudoer").ConfigureAwait(false);
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {moderator.Mention} is already a sudoer", ephemeral: true).ConfigureAwait(false);
}
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {moderator.Mention} is not a moderator (yet)", ephemeral: true).ConfigureAwait(false);
}
[Command("unsudo")]
public static async ValueTask Unsudo(SlashCommandContext ctx, DiscordUser sudoer)
{
if (ctx.Client.CurrentApplication.Owners?.Any(u => u.Id == sudoer.Id) ?? false)
{
await ctx.RespondAsync($"{Config.Reactions.Denied} Why would you even try this?! Alerting {sudoer.Mention}").ConfigureAwait(false);
var dm = await sudoer.CreateDmChannelAsync().ConfigureAwait(false);
await dm.SendMessageAsync($@"Just letting you know that {ctx.User.Mention} just tried to strip you off of your bot admin permissions ¯\\_(ツ)_/¯").ConfigureAwait(false);
}
else if (ModProvider.IsMod(sudoer.Id))
{
if (await ModProvider.UnmakeSudoerAsync(sudoer.Id).ConfigureAwait(false))
await ctx.RespondAsync($"{Config.Reactions.Success} {sudoer.Mention} is no longer a bot admin", ephemeral: true).ConfigureAwait(false);
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {sudoer.Mention} is not a bot admin", ephemeral: true).ConfigureAwait(false);
}
else
await ctx.RespondAsync($"{Config.Reactions.Failure} {sudoer.Mention} is not even a bot mod!", ephemeral: true).ConfigureAwait(false);
}
[Command("list")]
[Description("List all bot moderators")]
public static async ValueTask List(SlashCommandContext ctx)
{
var ephemeral = !ctx.Channel.IsSpamChannel();
await ctx.DeferResponseAsync(ephemeral).ConfigureAwait(false);
var table = new AsciiTable(
new AsciiColumn( "Username", maxWidth: 32),
new AsciiColumn("Sudo")
);
foreach (var mod in ModProvider.Mods.Values.OrderByDescending(m => m.Sudoer))
table.Add(await ctx.GetUserNameAsync(mod.DiscordId), mod.Sudoer ? "✅" :"");
var pages = AutosplitResponseHelper.AutosplitMessage(table.ToString());
await ctx.RespondAsync(pages[0], ephemeral: ephemeral).ConfigureAwait(false);
foreach (var page in pages.Skip(1).Take(4))
await ctx.FollowupAsync(page, ephemeral: ephemeral).ConfigureAwait(false);
}
}
}

View File

@@ -2,7 +2,6 @@
using System.Net.Http;
using CompatApiClient.Compression;
using CompatBot.Commands.Converters;
using CompatBot.Database.Providers;
using DSharpPlus.Commands.Processors.TextCommands;
using DSharpPlus.Commands.Processors.TextCommands.Parsing;
using Microsoft.Extensions.DependencyInjection;
@@ -139,23 +138,6 @@ internal static partial class Sudo
await Bot.Configuration.Set(ctx, nameof(Config.CryptoSalt), Convert.ToBase64String(salt)).ConfigureAwait(false);
}
[Command("mod"), LimitedToSpamChannel]
internal static class Mod
{
[Command("list")]
[Description("List all bot moderators")]
public static async ValueTask List(TextCommandContext ctx)
{
var table = new AsciiTable(
new AsciiColumn( "Username", maxWidth: 32),
new AsciiColumn("Sudo")
);
foreach (var mod in ModProvider.Mods.Values.OrderByDescending(m => m.Sudoer))
table.Add(await ctx.GetUserNameAsync(mod.DiscordId), mod.Sudoer ? "✅" :"");
await ctx.SendAutosplitMessageAsync(table.ToString()).ConfigureAwait(false);
}
}
private static async ValueTask<DiscordChannel?> ParseChannelNameAsync(this TextCommandContext ctx, string channelName)
{
await using var scope = ctx.Extension.ServiceProvider.CreateAsyncScope();

View File

@@ -0,0 +1,80 @@
using CompatApiClient.Utils;
using DSharpPlus.Interactivity;
using Microsoft.Extensions.DependencyInjection;
namespace CompatBot.Commands;
internal static class WarningsContextMenus
{
[Command("❗ Warn user"), RequiresBotModRole]
[SlashCommandTypes(DiscordApplicationCommandType.MessageContextMenu, DiscordApplicationCommandType.UserContextMenu)]
[Description("Give user a warning")]
public static async ValueTask Warn(SlashCommandContext ctx, DiscordMessage? message = null, DiscordUser? user = null)
{
var interactivity = ctx.Extension.ServiceProvider.GetService<InteractivityExtension>();
if (interactivity is null)
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't get interactivity extension").ConfigureAwait(false);
return;
}
var interaction = ctx.Interaction;
var modal = new DiscordInteractionResponseBuilder()
.AsEphemeral()
.WithCustomId($"modal:warn:{Guid.NewGuid():n}")
.WithTitle("Issue new warning")
.AddComponents(
new DiscordTextInputComponent(
"Warning reason",
"warning",
"Rule #2",
min_length: 2
)
);
await ctx.RespondWithModalAsync(modal).ConfigureAwait(false);
try
{
InteractivityResult<ModalSubmittedEventArgs> modalResult;
string reason;
do
{
modalResult = await interactivity.WaitForModalAsync(modal.CustomId, ctx.User).ConfigureAwait(false);
if (modalResult.TimedOut)
return;
} while (!modalResult.Result.Values.TryGetValue("warning", out reason!));
interaction = modalResult.Result.Interaction;
await interaction.CreateResponseAsync(
DiscordInteractionResponseType.DeferredChannelMessageWithSource,
new DiscordInteractionResponseBuilder().AsEphemeral()
).ConfigureAwait(false);
user ??= message?.Author!;
var (saved, suppress, recent, total) = await Warnings.AddAsync(user.Id, ctx.User, reason, message?.Content.Sanitize()).ConfigureAwait(false);
if (!saved)
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't save the warning, please try again", ephemeral: true).ConfigureAwait(false);
return;
}
if (!suppress)
{
var userMsgContent = $"{Config.Reactions.Success} User warning saved, {user.Mention} has {recent} recent warning{StringUtils.GetSuffix(recent)} ({total} total)";
var userMsg = new DiscordMessageBuilder()
.WithContent(userMsgContent)
.AddMention(UserMention.All);
await ctx.Channel.SendMessageAsync(userMsg).ConfigureAwait(false);
}
await Warnings.ListUserWarningsAsync(ctx.Client, ctx.Interaction, user.Id, user.Username.Sanitize()).ConfigureAwait(false);
}
catch (Exception e)
{
Config.Log.Error(e);
var msg = new DiscordInteractionResponseBuilder()
.AsEphemeral()
.WithContent($"{Config.Reactions.Failure} Failed to change nickname, check bot's permissions");
await interaction.EditOriginalResponseAsync(new(msg)).ConfigureAwait(false);
}
}
}

View File

@@ -1,151 +0,0 @@
using CompatApiClient.Utils;
using DSharpPlus.Commands.Processors.MessageCommands;
using DSharpPlus.Commands.Processors.UserCommands;
using DSharpPlus.Interactivity;
using Microsoft.Extensions.DependencyInjection;
namespace CompatBot.Commands;
internal static class WarningsContextMenus
{
[Command("❗ Warn user"), RequiresBotModRole, SlashCommandTypes(DiscordApplicationCommandType.UserContextMenu)]
[Description("Give user a warning")]
public static async ValueTask Warn(UserCommandContext ctx, DiscordUser user)
{
var interactivity = ctx.Extension.ServiceProvider.GetService<InteractivityExtension>();
if (interactivity is null)
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't get interactivity extension").ConfigureAwait(false);
return;
}
var interaction = ctx.Interaction;
var modal = new DiscordInteractionResponseBuilder()
.AsEphemeral()
.WithCustomId($"modal:warn:{Guid.NewGuid():n}")
.WithTitle("Issue new warning")
.AddComponents(
new DiscordTextInputComponent(
"Warning reason",
"warning",
"Rule #2",
min_length: 2
)
);
await ctx.RespondWithModalAsync(modal).ConfigureAwait(false);
try
{
InteractivityResult<ModalSubmittedEventArgs> modalResult;
string reason;
do
{
modalResult = await interactivity.WaitForModalAsync(modal.CustomId, ctx.User).ConfigureAwait(false);
if (modalResult.TimedOut)
return;
} while (!modalResult.Result.Values.TryGetValue("warning", out reason!));
interaction = modalResult.Result.Interaction;
await interaction.CreateResponseAsync(
DiscordInteractionResponseType.DeferredChannelMessageWithSource,
new DiscordInteractionResponseBuilder().AsEphemeral()
).ConfigureAwait(false);
var (saved, suppress, recent, total) = await Warnings.AddAsync(user.Id, ctx.User, reason).ConfigureAwait(false);
if (!saved)
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't save the warning, please try again", ephemeral: true).ConfigureAwait(false);
return;
}
if (!suppress)
{
var userMsgContent = $"{Config.Reactions.Success} User warning saved, {user.Mention} has {recent} recent warning{StringUtils.GetSuffix(recent)} ({total} total)";
var userMsg = new DiscordMessageBuilder()
.WithContent(userMsgContent)
.AddMention(UserMention.All);
await ctx.Channel.SendMessageAsync(userMsg).ConfigureAwait(false);
}
await Warnings.ListUserWarningsAsync(ctx.Client, ctx.Interaction, user.Id, user.Username.Sanitize()).ConfigureAwait(false);
}
catch (Exception e)
{
Config.Log.Error(e);
var msg = new DiscordInteractionResponseBuilder()
.AsEphemeral()
.WithContent($"{Config.Reactions.Failure} Failed to change nickname, check bot's permissions");
await interaction.EditOriginalResponseAsync(new(msg)).ConfigureAwait(false);
}
}
[Command("❗ Warn user"), RequiresBotModRole, SlashCommandTypes(DiscordApplicationCommandType.MessageContextMenu)]
[Description("Give user a warning")]
public static async ValueTask Warn(MessageCommandContext ctx, DiscordMessage message)
{
var interactivity = ctx.Extension.ServiceProvider.GetService<InteractivityExtension>();
if (interactivity is null)
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't get interactivity extension").ConfigureAwait(false);
return;
}
var interaction = ctx.Interaction;
var modal = new DiscordInteractionResponseBuilder()
.AsEphemeral()
.WithCustomId($"modal:warn:{Guid.NewGuid():n}")
.WithTitle("Issue new warning")
.AddComponents(
new DiscordTextInputComponent(
"Warning reason",
"warning",
"Rule #2",
min_length: 2
)
);
await ctx.RespondWithModalAsync(modal).ConfigureAwait(false);
try
{
InteractivityResult<ModalSubmittedEventArgs> modalResult;
string reason;
do
{
modalResult = await interactivity.WaitForModalAsync(modal.CustomId, ctx.User).ConfigureAwait(false);
if (modalResult.TimedOut)
return;
} while (!modalResult.Result.Values.TryGetValue("warning", out reason!));
interaction = modalResult.Result.Interaction;
await interaction.CreateResponseAsync(
DiscordInteractionResponseType.DeferredChannelMessageWithSource,
new DiscordInteractionResponseBuilder().AsEphemeral()
).ConfigureAwait(false);
var user = message.Author!;
var (saved, suppress, recent, total) = await Warnings.AddAsync(user.Id, ctx.User, reason, message.Content.Sanitize()).ConfigureAwait(false);
if (!saved)
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't save the warning, please try again", ephemeral: true).ConfigureAwait(false);
return;
}
if (!suppress)
{
var userMsgContent = $"{Config.Reactions.Success} User warning saved, {user.Mention} has {recent} recent warning{StringUtils.GetSuffix(recent)} ({total} total)";
var userMsg = new DiscordMessageBuilder()
.WithContent(userMsgContent)
.AddMention(UserMention.All);
await ctx.Channel.SendMessageAsync(userMsg).ConfigureAwait(false);
}
await Warnings.ListUserWarningsAsync(ctx.Client, ctx.Interaction, user.Id, user.Username.Sanitize()).ConfigureAwait(false);
}
catch (Exception e)
{
Config.Log.Error(e);
var msg = new DiscordInteractionResponseBuilder()
.AsEphemeral()
.WithContent($"{Config.Reactions.Failure} Failed to change nickname, check bot's permissions");
await interaction.EditOriginalResponseAsync(new(msg)).ConfigureAwait(false);
}
}
}