diff --git a/ModularAssistentForDiscordServer/Commands/AutoCompletion/ReminderAutoCompletion.cs b/ModularAssistentForDiscordServer/Commands/AutoCompletion/ReminderAutoCompletion.cs index c91aca3..c4ea887 100644 --- a/ModularAssistentForDiscordServer/Commands/AutoCompletion/ReminderAutoCompletion.cs +++ b/ModularAssistentForDiscordServer/Commands/AutoCompletion/ReminderAutoCompletion.cs @@ -12,15 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; +using DSharpPlus.Commands.Processors.SlashCommands; +using DSharpPlus.Commands.Processors.SlashCommands.ArgumentModifiers; using MADS.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace MADS.Commands.AutoCompletion; -public class ReminderAutoCompletion : IAutocompleteProvider +public class ReminderAutoCompletion : IAutoCompleteProvider { private readonly IDbContextFactory _factory; @@ -29,15 +29,15 @@ public ReminderAutoCompletion(IServiceProvider services) _factory = services.GetRequiredService>(); } - public async Task> Provider(AutocompleteContext ctx) + public async ValueTask> AutoCompleteAsync(AutoCompleteContext context) { await using MadsContext db = await _factory.CreateDbContextAsync(); - IEnumerable choices = db.Reminders - .Where(x => x.UserId == ctx.User.Id) - .Select(x => x.Id.ToString()) + Dictionary choices = db.Reminders + .Where(x => x.UserId == context.User.Id) + .Select(x => x.Id) + .Where(x => x.ToString().StartsWith(context.UserInput)) .Take(25) - .Select(x => new DiscordAutoCompleteChoice(x, x)) - .ToList(); + .ToDictionary(x => x.ToString(), x => (object) x); return choices; } diff --git a/ModularAssistentForDiscordServer/Commands/AutoCompletion/TargetLanguageAutoCompletion.cs b/ModularAssistentForDiscordServer/Commands/AutoCompletion/TargetLanguageAutoCompletion.cs index 7fe3f8d..fe76463 100644 --- a/ModularAssistentForDiscordServer/Commands/AutoCompletion/TargetLanguageAutoCompletion.cs +++ b/ModularAssistentForDiscordServer/Commands/AutoCompletion/TargetLanguageAutoCompletion.cs @@ -14,12 +14,12 @@ using DeepL; using DeepL.Model; -using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; +using DSharpPlus.Commands.Processors.SlashCommands; +using DSharpPlus.Commands.Processors.SlashCommands.ArgumentModifiers; namespace MADS.Commands.AutoCompletion; -public class TargetLanguageAutoCompletion : IAutocompleteProvider +public class TargetLanguageAutoCompletion : IAutoCompleteProvider { private readonly Translator _translator; @@ -28,12 +28,15 @@ public TargetLanguageAutoCompletion(Translator translator) _translator = translator; } - public async Task> Provider(AutocompleteContext ctx) + public async ValueTask> AutoCompleteAsync(AutoCompleteContext context) { TargetLanguage[] sourceLangs = await _translator.GetTargetLanguagesAsync(); - IEnumerable choices = sourceLangs - .Select(x => new DiscordAutoCompleteChoice(x.Name, x.Code)) - .Take(25); + Dictionary choices = sourceLangs + .Where(x => x.ToString().StartsWith(context.UserInput)) + .Take(25) + .Select(x => x.ToString()) + .ToDictionary(x => x, x => (object) x); + return choices; } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/AutoCompletion/VoiceAlertAutoCompletion.cs b/ModularAssistentForDiscordServer/Commands/AutoCompletion/VoiceAlertAutoCompletion.cs index d7c991a..53231b2 100644 --- a/ModularAssistentForDiscordServer/Commands/AutoCompletion/VoiceAlertAutoCompletion.cs +++ b/ModularAssistentForDiscordServer/Commands/AutoCompletion/VoiceAlertAutoCompletion.cs @@ -12,15 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +using DSharpPlus.Commands.Processors.SlashCommands; +using DSharpPlus.Commands.Processors.SlashCommands.ArgumentModifiers; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using MADS.Entities; using MADS.Services; using Microsoft.Extensions.DependencyInjection; namespace MADS.Commands.AutoCompletion; -public class VoiceAlertAutoCompletion : IAutocompleteProvider +public class VoiceAlertAutoCompletion : IAutoCompleteProvider { private readonly VoiceAlertService _voiceAlertService; @@ -29,18 +30,22 @@ public VoiceAlertAutoCompletion(IServiceProvider services) _voiceAlertService = services.GetRequiredService(); } - public async Task> Provider(AutocompleteContext ctx) + public async ValueTask> AutoCompleteAsync(AutoCompleteContext context) { - IEnumerable choices = await _voiceAlertService.GetVoiceAlerts(ctx.User.Id); - - List result = new(); + IEnumerable choices = await _voiceAlertService.GetVoiceAlerts(context.User.Id); + List result = new(); foreach (VoiceAlert choice in choices) { - DiscordChannel chn = await ctx.Guild.GetChannelAsync(choice.ChannelId); - result.Add(new DiscordAutoCompleteChoice(chn.Name, choice.ChannelId.ToString())); + DiscordChannel channel = await context.Client.GetChannelAsync(choice.ChannelId); + result.Add(channel); } - return result; + Dictionary dict = result + .Where(x => x.Name.StartsWith(context.UserInput)) + .Take(25) + .ToDictionary(x => x.Name, x => (object) x.Id); + + return dict; } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/ContextMenu/StealEmojiMessage.cs b/ModularAssistentForDiscordServer/Commands/ContextMenu/StealEmojiMessage.cs index 7c75c87..1368c9e 100644 --- a/ModularAssistentForDiscordServer/Commands/ContextMenu/StealEmojiMessage.cs +++ b/ModularAssistentForDiscordServer/Commands/ContextMenu/StealEmojiMessage.cs @@ -14,9 +14,6 @@ using System.Text.RegularExpressions; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; -using DSharpPlus.SlashCommands.Attributes; -using MADS.Extensions; namespace MADS.Commands.ContextMenu; diff --git a/ModularAssistentForDiscordServer/Commands/ContextMenu/TranslateMessage.cs b/ModularAssistentForDiscordServer/Commands/ContextMenu/TranslateMessage.cs index 6b79ff5..67cd89a 100644 --- a/ModularAssistentForDiscordServer/Commands/ContextMenu/TranslateMessage.cs +++ b/ModularAssistentForDiscordServer/Commands/ContextMenu/TranslateMessage.cs @@ -15,9 +15,7 @@ using DeepL; using DeepL.Model; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using MADS.CustomComponents; -using MADS.Extensions; using MADS.Services; using Quartz.Util; diff --git a/ModularAssistentForDiscordServer/Commands/ContextMenu/UserInfoUser.cs b/ModularAssistentForDiscordServer/Commands/ContextMenu/UserInfoUser.cs index c272b07..0147063 100644 --- a/ModularAssistentForDiscordServer/Commands/ContextMenu/UserInfoUser.cs +++ b/ModularAssistentForDiscordServer/Commands/ContextMenu/UserInfoUser.cs @@ -15,9 +15,7 @@ using DSharpPlus; using DSharpPlus.Entities; using DSharpPlus.Exceptions; -using DSharpPlus.SlashCommands; using Humanizer; -using MADS.Extensions; namespace MADS.Commands.ContextMenu; diff --git a/ModularAssistentForDiscordServer/Commands/Slash/About.cs b/ModularAssistentForDiscordServer/Commands/Slash/About.cs index 8350734..ff58b5d 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/About.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/About.cs @@ -12,17 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; +using DSharpPlus.Commands; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using Humanizer; -using MADS.Extensions; +using MADS.Services; namespace MADS.Commands.Slash; -public sealed class About : MadsBaseApplicationCommand +public sealed class About { - [SlashCommand("about", "Infos about the bot")] - public async Task AboutCommand(InteractionContext ctx) + private readonly DiscordClientService DiscordService; + + public About(DiscordClientService service) + { + DiscordService = service; + } + + [Command("about"), Description("Infos about the bot")] + public async Task AboutCommand(CommandContext ctx) { DiscordEmbedBuilder discordEmbedBuilder = new(); DiscordInteractionResponseBuilder discordMessageBuilder = new(); @@ -30,7 +38,7 @@ public async Task AboutCommand(InteractionContext ctx) DiscordOAuthScope.ApplicationsCommands); string addMe = $"[Click here!]({inviteUri.Replace(" ", "%20")})"; - TimeSpan diff = DateTime.Now - CommandService.StartTime; + TimeSpan diff = DateTime.Now - DiscordService.StartTime; string date = $"{diff.Days} days {diff.Hours} hours {diff.Minutes} minutes"; discordEmbedBuilder @@ -52,6 +60,6 @@ public async Task AboutCommand(InteractionContext ctx) "Feedback")); discordMessageBuilder.AsEphemeral(); - await ctx.CreateResponseAsync(DiscordInteractionResponseType.ChannelMessageWithSource, discordMessageBuilder); + await ctx.RespondAsync(discordMessageBuilder); } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/Slash/BotStats.cs b/ModularAssistentForDiscordServer/Commands/Slash/BotStats.cs index 77891a7..798e981 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/BotStats.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/BotStats.cs @@ -12,18 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using System.Diagnostics; using DSharpPlus; +using DSharpPlus.Commands; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using Humanizer; using MADS.Entities; -using MADS.Extensions; using Microsoft.EntityFrameworkCore; namespace MADS.Commands.Slash; -public sealed class BotStats : MadsBaseApplicationCommand +public sealed class BotStats { private readonly IDbContextFactory _contextFactory; private readonly DiscordRestClient _discordRestClient; @@ -34,8 +34,8 @@ public BotStats(IDbContextFactory contextFactory, DiscordRestClient _discordRestClient = discordRestClient; } - [SlashCommand("botstats", "Get statistics about the bot")] - public async Task GetBotStatsAsync(InteractionContext ctx) + [Command("botstats"), Description("Get statistics about the bot")] + public async Task GetBotStatsAsync(CommandContext ctx) { await using MadsContext db = await _contextFactory.CreateDbContextAsync(); Stopwatch swDb = new(); @@ -73,7 +73,10 @@ public async Task GetBotStatsAsync(InteractionContext ctx) .AddField("Uptime:", $"{DateTimeOffset.UtcNow.Subtract(process.StartTime).Humanize(3, minUnit: TimeUnit.Millisecond, maxUnit: TimeUnit.Day)}", true); + + DiscordInteractionResponseBuilder responseBuilder = new(); + responseBuilder.AddEmbed(embed).AsEphemeral(); - await ctx.CreateResponseAsync(embed, true); + await ctx.RespondAsync(responseBuilder); } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/Slash/Jumpad.cs b/ModularAssistentForDiscordServer/Commands/Slash/Jumpad.cs index 1b09bf4..7bada4d 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/Jumpad.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/Jumpad.cs @@ -12,26 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; +using DSharpPlus.Commands.Processors.SlashCommands.ArgumentModifiers; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using MADS.CustomComponents; -using MADS.Extensions; using Quartz.Util; namespace MADS.Commands.Slash; -[GuildOnly] -public sealed class Jumppad : MadsBaseApplicationCommand +public sealed class Jumppad { - [SlashCommand("jumppad", "Create a jumppad button"), SlashCommandPermissions(DiscordPermissions.MoveMembers)] + [Command("jumppad"), Description("Create a jumppad button"), RequireGuild, RequirePermissions(DiscordPermissions.MoveMembers)] public async Task Test ( - InteractionContext ctx, - [Option("originChannel", "Channel where the users will be moved out"), ChannelTypes(DiscordChannelType.Voice)] + CommandContext ctx, + [Description("Channel where the users will be moved out"), SlashChannelTypes(DiscordChannelType.Voice, DiscordChannelType.Stage)] DiscordChannel originChannel, - [Option("targetChannel", "Channel where the users will be put in"), ChannelTypes(DiscordChannelType.Voice)] + [Description("Channel where the users will be put in"), SlashChannelTypes(DiscordChannelType.Voice, DiscordChannelType.Stage)] DiscordChannel targetChannel, - [Option("message", "Message to be sent")] + [Description("Message to be sent")] string? content = null ) { @@ -43,6 +44,6 @@ public async Task Test message.AddComponents(newButton); message.WithContent(!content.IsNullOrWhiteSpace() ? content! : "Jumppad"); - await ctx.CreateResponseAsync(DiscordInteractionResponseType.ChannelMessageWithSource, message); + await ctx.RespondAsync(message); } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/Slash/MessageSnipe.cs b/ModularAssistentForDiscordServer/Commands/Slash/MessageSnipe.cs index d8da93f..d04655e 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/MessageSnipe.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/MessageSnipe.cs @@ -12,16 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using DSharpPlus; +using DSharpPlus.Commands; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using MADS.CustomComponents; using MADS.Extensions; using MADS.Services; namespace MADS.Commands.Slash; -public sealed class MessageSnipe : MadsBaseApplicationCommand +public sealed class MessageSnipe { private readonly MessageSnipeService _messageSnipeService; @@ -30,21 +31,21 @@ public MessageSnipe(MessageSnipeService messageSnipeService) _messageSnipeService = messageSnipeService; } - [SlashCommand("snipe", "Snipes the last deleted message.")] - public async Task SnipeAsync(InteractionContext ctx) + [Command("snipe"), Description("Snipes the last deleted message.")] + public async Task SnipeAsync(CommandContext ctx) { await DoSnipeAsync(ctx, false); } - [SlashCommand("snipeedit", "Snipes the last edited message.")] - public async Task SnipeEditAsync(InteractionContext ctx) + [Command("snipeedit"), Description("Snipes the last edited message.")] + public async Task SnipeEditAsync(CommandContext ctx) { await DoSnipeAsync(ctx, true); } - private async Task DoSnipeAsync(InteractionContext ctx, bool edit) + private async Task DoSnipeAsync(CommandContext ctx, bool edit) { - await ctx.DeferAsync(true); + await ctx.DeferResponseAsync(); bool result = !edit ? _messageSnipeService.TryGetMessage(ctx.Channel.Id, out DiscordMessage? message) @@ -52,7 +53,8 @@ private async Task DoSnipeAsync(InteractionContext ctx, bool edit) if (!result || message is null) { - await EditResponse_Error("⚠️ No message to snipe! Either nothing was deleted, or the message has expired (12 hours)!"); + await ctx.EditResponse_Error( + "⚠️ No message to snipe! Either nothing was deleted, or the message has expired (12 hours)!"); return; } @@ -115,12 +117,13 @@ private async Task DoSnipeAsync(InteractionContext ctx, bool edit) await ctx.EditResponseAsync(response); } - [SlashCommand("deletesnipe", "Deletes cached messages for this channel.")] - public async Task DeleteSnipeAsync(InteractionContext ctx) + [Command("deletesnipe"), Description("Deletes cached messages for this channel.")] + public async Task DeleteSnipeAsync(CommandContext ctx) { await ctx.DeferAsync(true); _messageSnipeService.DeleteMessage(ctx.Channel.Id); _messageSnipeService.DeleteEditedMessage(ctx.Channel.Id); - await EditResponse_Success("✅ Snipe cache cleared!"); + + await ctx.EditResponse_Success("✅ Snipe cache cleared!"); } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/Slash/Ping.cs b/ModularAssistentForDiscordServer/Commands/Slash/Ping.cs index 7677b4a..d323cd6 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/Ping.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/Ping.cs @@ -12,18 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using System.Diagnostics; +using DSharpPlus.Commands; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using Humanizer; -using MADS.Extensions; namespace MADS.Commands.Slash; -public sealed class Ping : MadsBaseApplicationCommand +public sealed class Ping { - [SlashCommand("ping", "Get the bot's ping")] - public async Task PingCommand(InteractionContext ctx) + [Command("ping"), Description("Get the bot's ping")] + public async Task PingCommand(CommandContext ctx) { using Process process = Process.GetCurrentProcess(); @@ -34,7 +34,10 @@ public async Task PingCommand(InteractionContext ctx) .WithColor(new DiscordColor(0, 255, 194)) .AddField("Uptime", $"{DateTimeOffset.UtcNow.Subtract(process.StartTime).Humanize(3, minUnit: TimeUnit.Millisecond, maxUnit: TimeUnit.Day)}") .AddField("Websocket ping", $"{ctx.Client.Ping} ms"); + + DiscordInteractionResponseBuilder responseBuilder = new(); + responseBuilder.AddEmbed(discordEmbedBuilder).AsEphemeral(); - await ctx.CreateResponseAsync(discordEmbedBuilder, true); + await ctx.RespondAsync(responseBuilder); } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/Slash/Purge.cs b/ModularAssistentForDiscordServer/Commands/Slash/Purge.cs index ae131d3..a8e2c55 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/Purge.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/Purge.cs @@ -12,32 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; -using DSharpPlus.SlashCommands.Attributes; using MADS.Extensions; namespace MADS.Commands.Slash; -public sealed class Purge : MadsBaseApplicationCommand +public sealed class Purge { - [SlashCommand("purge", "Purges messages"), - SlashRequirePermissions(DiscordPermissions.ManageMessages), - SlashRequireGuild] + [Command("purge"), Description("Purges messages"), + RequirePermissions(DiscordPermissions.ManageMessages), + RequireGuild] public async Task PurgeMessages ( - InteractionContext ctx, [Option("amount", "Delete a bunch of messages")] long amount = 100 + CommandContext ctx, [Description("Amount of messages to delete")] long amount = 100 ) { if (amount > 100) { - await CreateResponse_Error("You cannot purge more than 100 messages at once", true); + await ctx.CreateResponse_Error("You cannot purge more than 100 messages at once", true); return; } - await ctx.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMessageWithSource, - new DiscordInteractionResponseBuilder()); - DiscordMessage response = await ctx.GetOriginalResponseAsync(); + await ctx.DeferAsync(); + DiscordMessage? response = await ctx.GetResponseAsync()!; List messages = []; await foreach (DiscordMessage msg in ctx.Channel.GetMessagesAsync((int) amount)) @@ -46,12 +46,12 @@ await ctx.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMess } messages.RemoveAll(x => (DateTime.UtcNow - x.Timestamp).TotalDays >= 14); - messages.Remove(response); + messages.Remove(response!); await ctx.Channel.DeleteMessagesAsync(messages); await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"{messages.Count} messages deleted")); - await IntendedWait(10_000); + await Task.Delay(10_000); await ctx.DeleteResponseAsync(); } diff --git a/ModularAssistentForDiscordServer/Commands/Slash/Quotes.cs b/ModularAssistentForDiscordServer/Commands/Slash/Quotes.cs index a2ec45d..5f3fb42 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/Quotes.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/Quotes.cs @@ -12,17 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; -using DSharpPlus.SlashCommands.Attributes; using MADS.Entities; using MADS.Extensions; using MADS.Services; namespace MADS.Commands.Slash; -[SlashCommandGroup("Quotes", "Commands related to adding and retrieving quotes"), SlashRequireGuild] -public sealed class Quotes : MadsBaseApplicationCommand +[Command("Quotes"), Description("Commands related to adding and retrieving quotes"), RequireGuild] +public sealed class Quotes { private readonly QuotesService _quotesService; @@ -31,12 +32,12 @@ public Quotes(QuotesService quotesService) _quotesService = quotesService; } - [SlashCommand("add", "Add a quote form a user")] + [Command("add"), Description("Add a quote form a user")] public async Task AddQuoteUser ( - InteractionContext ctx, - [Option("User", "User who is quoted")] DiscordUser user, - [Option("Content", "Quoted content")] string content + CommandContext ctx, + [Description("User who is quoted")] DiscordUser user, + [Description("Quoted content")] string content ) { await ctx.DeferAsync(true); @@ -46,7 +47,7 @@ public async Task AddQuoteUser { Content = content, CreatedAt = DateTime.Now, - DiscordGuildId = ctx.Guild.Id, + DiscordGuildId = ctx.Guild!.Id, QuotedUserId = user.Id, UserId = ctx.User.Id }; @@ -59,15 +60,15 @@ public async Task AddQuoteUser await ctx.EditResponseAsync(new DiscordWebhookBuilder().AddEmbed(embed)); } - [SlashCommand("getRandom", "Get a random quote from this server")] + [Command("getRandom"), Description("Get a random quote from this server")] public async Task GetRndQuote ( - InteractionContext ctx + CommandContext ctx ) { await ctx.DeferAsync(true); - QuoteDbEntity quote = await _quotesService.GetRndGuildAsync(ctx.Guild.Id); + QuoteDbEntity quote = await _quotesService.GetRndGuildAsync(ctx.Guild!.Id); DiscordEmbed embed = await quote.GetEmbedAsync(ctx.Client); diff --git a/ModularAssistentForDiscordServer/Commands/Slash/Reminder.cs b/ModularAssistentForDiscordServer/Commands/Slash/Reminder.cs index 02f73b7..7412a9a 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/Reminder.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/Reminder.cs @@ -12,10 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using System.Text; using DSharpPlus; +using DSharpPlus.Commands; +using DSharpPlus.Commands.Processors.SlashCommands.ArgumentModifiers; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using Humanizer; using MADS.Commands.AutoCompletion; using MADS.Entities; @@ -24,8 +26,8 @@ namespace MADS.Commands.Slash; -[SlashCommandGroup("reminder", "mangage reminders")] -public sealed class Reminder : MadsBaseApplicationCommand +[Command("reminder"), Description("mangage reminders")] +public sealed class Reminder { private readonly ReminderService _reminderService; private readonly UserManagerService _userManagerService; @@ -36,14 +38,14 @@ public Reminder(ReminderService reminderService, UserManagerService userManagerS _userManagerService = userManagerService; } - [SlashCommand("add", "add new reminder")] + [Command("add"), Description("add new reminder")] public async Task AddReminder ( - InteractionContext ctx, - [Option("timespan", "when the reminder should trigger")] + CommandContext ctx, + [Description("when the reminder should trigger")] TimeSpan? timeSpan, - [Option("text", "text")] string text, - [Option("private", "Sets if the reminder should be executed in your DMs")] + [Description("text")] string text, + [Description("Sets if the reminder should be executed in your DMs")] bool isPrivate = false ) { @@ -51,7 +53,7 @@ public async Task AddReminder if (timeSpan is null) { - await EditResponse_Error("Invalid timespan (5s, 3m, 7h, 2d)"); + await ctx.EditResponse_Error("Invalid timespan (5s, 3m, 7h, 2d)"); return; } @@ -69,13 +71,13 @@ public async Task AddReminder ReminderDbEntity reminder = await _reminderService.AddReminder(newReminder); - await EditResponse_Success($"Reminder created with id `{reminder.Id}`. I will remind you in {Formatter.Timestamp(timeSpan.Value)}"); + await ctx.EditResponse_Success($"Reminder created with id `{reminder.Id}`. I will remind you in {Formatter.Timestamp(timeSpan.Value)}"); } - [SlashCommand("list", "list your Reminder")] + [Command("list"), Description("list your Reminder")] public async Task ListReminder ( - InteractionContext ctx + CommandContext ctx ) { await ctx.DeferAsync(true); @@ -94,12 +96,12 @@ InteractionContext ctx await ctx.EditResponseAsync(new DiscordWebhookBuilder().AddEmbed(embed)); } - [SlashCommand("delete", "delete a reminder based on its id")] + [Command("delete"), Description("delete a reminder based on its id")] public async Task DeleteById ( - InteractionContext ctx, - [Autocomplete(typeof(ReminderAutoCompletion)), - Option("id", "id of the given reminder which should be deleted", true)] + CommandContext ctx, + [SlashAutoCompleteProvider(typeof(ReminderAutoCompletion)), + Description("id of the given reminder which should be deleted")] long id ) { @@ -108,7 +110,7 @@ long id if (reminder is null) { - await EditResponse_Error("Reminder does not exists"); + await ctx.EditResponse_Error("Reminder does not exists"); return; } @@ -116,7 +118,7 @@ long id if (!success) { - await EditResponse_Error("Something went wrong. Are you sure you own this reminder?"); + await ctx.EditResponse_Error("Something went wrong. Are you sure you own this reminder?"); return; } diff --git a/ModularAssistentForDiscordServer/Commands/Slash/RoleSelection.cs b/ModularAssistentForDiscordServer/Commands/Slash/RoleSelection.cs index e96e303..02c1a6e 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/RoleSelection.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/RoleSelection.cs @@ -12,41 +12,34 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; using DSharpPlus.Entities; using DSharpPlus.EventArgs; using DSharpPlus.Interactivity; using DSharpPlus.Interactivity.Extensions; -using DSharpPlus.SlashCommands; -using DSharpPlus.SlashCommands.Attributes; using MADS.Extensions; namespace MADS.Commands.Slash; -public sealed class RoleSelection : MadsBaseApplicationCommand +public sealed class RoleSelection { - [SlashCommand("RoleSelection", "Use this command in the channel the message should be posted"), - SlashRequirePermissions(DiscordPermissions.ManageRoles), - SlashRequireGuild] + [Command("RoleSelection"), Description("Use this command in the channel the message should be posted"), + RequirePermissions(DiscordPermissions.ManageRoles), + RequireGuild] public async Task RoleSelectionCreation ( - InteractionContext ctx, - [Option("MessageContent", "Message which should be above the menu")] + CommandContext ctx, + [Description("Message which should be above the menu")] string messageContent = "" ) { //show we are processing - await ctx.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMessageWithSource, - new DiscordInteractionResponseBuilder().AsEphemeral()); - - //check if the command was not triggered in a guild and if so abort - if (ctx.Guild is null) - { - await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Only possible in guilds")); - return; - } + await ctx.DeferAsync(true); //check if the user has the required permissons - if (!ctx.Member.Permissions.HasPermission(DiscordPermissions.ManageRoles)) + if (ctx.Member is null || !ctx.Member.Permissions.HasPermission(DiscordPermissions.ManageRoles)) { await ctx.EditResponseAsync( new DiscordWebhookBuilder().WithContent( @@ -56,7 +49,7 @@ await ctx.EditResponseAsync( //get all roles and Create a list of select menu options IEnumerable options = []; - List roles = ctx.Guild.Roles.Values.ToList(); + List roles = ctx.Guild!.Roles.Values.ToList(); //remove all roles from bots etc roles.RemoveAll(x => x.IsManaged); @@ -73,8 +66,8 @@ await ctx.EditResponseAsync( await ctx.EditResponseAsync(new DiscordWebhookBuilder().AddComponents(select)); //Get the initial response an wait for a component interaction - DiscordMessage response = await ctx.GetOriginalResponseAsync(); - InteractivityResult selectResponse = await response.WaitForSelectAsync(ctx.Member, "roleSelectionStart-" + ctx.Channel.Id, + DiscordMessage? response = await ctx.GetResponseAsync(); + InteractivityResult selectResponse = await response!.WaitForSelectAsync(ctx.Member, "roleSelectionStart-" + ctx.Channel.Id, TimeSpan.FromSeconds(60 * 3)); //Notify the user when the interaction times out and abort @@ -103,7 +96,8 @@ await ctx.EditResponseAsync(new DiscordWebhookBuilder List selectedRoles = new(); selectedRoles = selectResponse.Result.Values.Select(ulong.Parse) .Select(roleId => ctx.Guild.GetRole(roleId)) - .Select(role => new DiscordSelectComponentOption(role.Name, role.Id.ToString())) + .Where(x => x is not null) + .Select(role => new DiscordSelectComponentOption(role!.Name, role.Id.ToString())) .Aggregate(selectedRoles, (current, option) => current.Append(option).ToList()); //Create the final select menu and send it in the channel diff --git a/ModularAssistentForDiscordServer/Commands/Slash/StarboardConfig.cs b/ModularAssistentForDiscordServer/Commands/Slash/StarboardConfig.cs index fbca794..38baf31 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/StarboardConfig.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/StarboardConfig.cs @@ -12,17 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using System.Text.RegularExpressions; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; -using DSharpPlus.SlashCommands.Attributes; using MADS.Entities; using MADS.Extensions; using Microsoft.EntityFrameworkCore; namespace MADS.Commands.Slash; -public sealed class StarboardConfig : MadsBaseApplicationCommand +public sealed class StarboardConfig { private static readonly Regex EmoteRegex = new(@"^<(?a)?:(?[a-zA-Z0-9_]+?):(?\d+?)>$", RegexOptions.ECMAScript | RegexOptions.Compiled); @@ -34,17 +35,17 @@ public StarboardConfig(IDbContextFactory contextFactory) _contextFactory = contextFactory; } - [SlashCommand("Starboard", "Configure Starboard"), - SlashRequirePermissions(DiscordPermissions.ManageGuild), - SlashRequireGuild] + [Command("Starboard"), Description("Configure Starboard"), + RequirePermissions(DiscordPermissions.ManageGuild), + RequireGuild] public async Task StarboardConfigCommand ( - InteractionContext ctx, - [Option("Channel", "Channel for starboard messages")] + CommandContext ctx, + [Description("Channel for starboard messages")] DiscordChannel channel, - [Option("Emoji", "Emoji which is used as star (default: :star:)")] + [Description("Emoji which is used as star (default: :star:)")] string emojiString = "⭐", - [Option("Threshold", "Number of stars required for message (default: 3)")] + [Description("Number of stars required for message (default: 3)")] long threshhold = 3 ) { diff --git a/ModularAssistentForDiscordServer/Commands/Slash/Translation.cs b/ModularAssistentForDiscordServer/Commands/Slash/Translation.cs index ecb2270..4b766cd 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/Translation.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/Translation.cs @@ -12,18 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using DeepL; using DeepL.Model; +using DSharpPlus.Commands; +using DSharpPlus.Commands.Processors.SlashCommands.ArgumentModifiers; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using MADS.Commands.AutoCompletion; using MADS.Extensions; using MADS.Services; namespace MADS.Commands.Slash; -[SlashCommandGroup("translation", "Commands for translation")] -public class Translation : MadsBaseApplicationCommand +[Command("translation"), Description("Commands for translation")] +public class Translation { private readonly TranslateInformationService _translationUserInfo; private readonly Translator _translator; @@ -34,19 +36,17 @@ public Translation(TranslateInformationService translationUserInfo, Translator t _translator = translator; } - [SlashCommand("setLanguage", "Set your preferred language")] + [Command("setLanguage"), Description("Set your preferred language")] public async Task SetLanguageAsync ( - InteractionContext ctx, - [Option("language", "The language you want to get (default: en)", true), Autocomplete(typeof(TargetLanguageAutoCompletion))] + CommandContext ctx, + [Description("The language you want to get (default: en)"), SlashAutoCompleteProvider(typeof(TargetLanguageAutoCompletion))] string language = "en" ) { if (string.IsNullOrWhiteSpace(language)) { - await ctx.CreateResponseAsync(DiscordInteractionResponseType.ChannelMessageWithSource, - new DiscordInteractionResponseBuilder() - .WithContent("⚠️ Language can't be empty!")); + await ctx.CreateResponse_Error("⚠️ Language can't be empty!"); return; } @@ -54,20 +54,18 @@ await ctx.CreateResponseAsync(DiscordInteractionResponseType.ChannelMessageWithS _translationUserInfo.SetPreferredLanguage(ctx.User.Id, code); - await ctx.CreateResponseAsync(DiscordInteractionResponseType.ChannelMessageWithSource, - new DiscordInteractionResponseBuilder() - .WithContent($"✅ Language set to {code}")); + await ctx.CreateResponse_Success($"✅ Language set to {code}"); } - [SlashCommand("translate", "Translate a text")] + [Command("translate"), Description("Translate a text")] public async Task TranslateText ( - InteractionContext ctx, - [Option("text", "The text you want to translate")] + CommandContext ctx, + [Description("The text you want to translate")] string text, - [Option("language", "The language you want to get (default: en)", true), Autocomplete(typeof(TargetLanguageAutoCompletion))] + [Description("The language you want to get (default: en)"), SlashAutoCompleteProvider(typeof(TargetLanguageAutoCompletion))] string language = "en", - [Option("publicResult", "Weather the result should be public or not (default: false)")] + [Description("Weather the result should be public or not (default: false)")] bool publicResult = false ) { @@ -87,7 +85,10 @@ await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithColor(new DiscordColor(0, 255, 194)) .WithFooter($"Translated from {translatedText.DetectedSourceLanguageCode} to {language}") .WithTimestamp(DateTime.Now); + + DiscordInteractionResponseBuilder responseBuilder = new(); + responseBuilder.AddEmbed(embed).AsEphemeral(!publicResult); - await ctx.CreateResponseAsync(embed, publicResult); + await ctx.RespondAsync(responseBuilder); } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/Slash/VoiceAlerts.cs b/ModularAssistentForDiscordServer/Commands/Slash/VoiceAlerts.cs index 9d76ce8..5dc71bb 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/VoiceAlerts.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/VoiceAlerts.cs @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using System.Text; +using DSharpPlus.Commands; +using DSharpPlus.Commands.Processors.SlashCommands.ArgumentModifiers; using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; using MADS.Commands.AutoCompletion; using MADS.Entities; using MADS.Extensions; @@ -22,8 +24,8 @@ namespace MADS.Commands.Slash; -[SlashCommandGroup("voicealerts", "mangage voicealerts")] -public sealed class VoiceAlerts : MadsBaseApplicationCommand +[Command("voicealerts"), Description("mangage voicealerts")] +public sealed class VoiceAlerts { private readonly VoiceAlertService _voiceAlertService; @@ -32,72 +34,72 @@ public VoiceAlerts(VoiceAlertService voiceAlertService) _voiceAlertService = voiceAlertService; } - [SlashCommand("add", "add a voicealert")] + [Command("add"), Description("add a voicealert")] public async Task AddAlert ( - InteractionContext ctx, - [Option("channel", "channel which will be monitored"), ChannelTypes(DiscordChannelType.Voice, DiscordChannelType.Stage)] + CommandContext ctx, + [Description("channel which will be monitored"), SlashChannelTypes(DiscordChannelType.Voice, DiscordChannelType.Stage)] DiscordChannel channel, - [Option("minTimeBetween", "time which has to pass between alerts")] + [Description("time which has to pass between alerts")] TimeSpan? minTimeBetween, - [Option("repeat", "repeat the alert")] + [Description("If the alert should be repeated or one shot. (Defaults to false (one shot))")] bool repeat = false ) { if (channel.Type is not (DiscordChannelType.Voice or DiscordChannelType.Stage)) { - await CreateResponse_Error($"<#{channel.Id}> is not a voice channel", true); + await ctx.CreateResponse_Error($"<#{channel.Id}> is not a voice channel", true); return; } if (minTimeBetween is null) { - await CreateResponse_Error("Invalid timespan (5s, 3m, 7h, 2d) - Use 0s if you want to get a alert everytime (Warning: This could lead to Spam)", true); + await ctx.CreateResponse_Error("Invalid timespan (5s, 3m, 7h, 2d) - Use 0s if you want to get a alert everytime (Warning: This could lead to Spam)", true); return; } IEnumerable currentAlerts = await _voiceAlertService.GetVoiceAlerts(ctx.User.Id); if (currentAlerts.Any(x => x.ChannelId == channel.Id)) { - await CreateResponse_Error($"<#{channel.Id}> is already in your VoiceAlerts", true); + await ctx.CreateResponse_Error($"<#{channel.Id}> is already in your VoiceAlerts", true); return; } await _voiceAlertService.AddVoiceAlertAsync(ctx.User.Id, channel.Id, ctx.Guild.Id, repeat, minTimeBetween.Value); - await CreateResponse_Success($"Added <#{channel.Id}> to your VoiceAlerts", true); + await ctx.CreateResponse_Success($"Added <#{channel.Id}> to your VoiceAlerts", true); } - [SlashCommand("delete", "delete a voicealerts")] + [Command("delete"), Description("delete a voicealerts")] public async Task RemoveAlert ( - InteractionContext ctx, - [Option("channel", "channel which will not be monitored anymore", true), - Autocomplete(typeof(VoiceAlertAutoCompletion))] + CommandContext ctx, + [Description("channel which will not be monitored anymore"), + SlashAutoCompleteProvider(typeof(VoiceAlertAutoCompletion))] string channel ) { bool isId = ulong.TryParse(channel, out ulong id); if (!isId) { - await CreateResponse_Error($"**{channel}** is not a valid id", true); + await ctx.CreateResponse_Error($"**{channel}** is not a valid id", true); return; } IEnumerable currentAlerts = await _voiceAlertService.GetVoiceAlerts(ctx.User.Id); if (!currentAlerts.Any(x => x.ChannelId == id)) { - await CreateResponse_Error($"<#{id}> is not in your VoiceAlerts", true); + await ctx.CreateResponse_Error($"<#{id}> is not in your VoiceAlerts", true); return; } await _voiceAlertService.RemoveVoiceAlert(ctx.User.Id, id, ctx.Guild.Id); - await CreateResponse_Success($"Removed <#{channel}> from your VoiceAlerts", true); + await ctx.CreateResponse_Success($"Removed <#{channel}> from your VoiceAlerts", true); } - [SlashCommand("list", "list all voicealerts")] - public async Task ListAlerts(InteractionContext ctx) + [Command("list"), Description("list all voicealerts")] + public async Task ListAlerts(CommandContext ctx) { IEnumerable alerts = await _voiceAlertService.GetVoiceAlerts(ctx.User.Id); StringBuilder builder = new(); @@ -110,7 +112,10 @@ public async Task ListAlerts(InteractionContext ctx) { builder.AppendLine("You have no VoiceAlerts"); } + + DiscordInteractionResponseBuilder responseBuilder = new(); + responseBuilder.WithContent(builder.ToString()).AsEphemeral(); - await ctx.CreateResponseAsync(builder.ToString(), true); + await ctx.RespondAsync(responseBuilder); } } \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Commands/Slash/moveEmoji.cs b/ModularAssistentForDiscordServer/Commands/Slash/moveEmoji.cs index c5092c8..5181e67 100644 --- a/ModularAssistentForDiscordServer/Commands/Slash/moveEmoji.cs +++ b/ModularAssistentForDiscordServer/Commands/Slash/moveEmoji.cs @@ -12,33 +12,33 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using System.Text.RegularExpressions; using DSharpPlus; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; using DSharpPlus.Entities; using DSharpPlus.EventArgs; using DSharpPlus.Exceptions; using DSharpPlus.Interactivity; using DSharpPlus.Interactivity.Extensions; -using DSharpPlus.SlashCommands; -using DSharpPlus.SlashCommands.Attributes; using MADS.Extensions; namespace MADS.Commands.Slash; -public sealed partial class MoveEmoji : MadsBaseApplicationCommand +public sealed partial class MoveEmoji { - [SlashCommand("MoveEmoji", "Move emoji to your guild"), SlashRequirePermissions(DiscordPermissions.ManageEmojis)] + [Command("MoveEmoji"), Description("Move emoji to your guild"), RequirePermissions(DiscordPermissions.ManageEmojis)] public async Task MoveEmojiAsync - (InteractionContext ctx, [Option("Emoji", "Emoji which should be moved")] string pEmoji) + (CommandContext ctx, [Description("Emoji which should be moved")] string emoji) { - await ctx.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMessageWithSource, - new DiscordInteractionResponseBuilder().AsEphemeral()); + await ctx.DeferAsync(true); - MatchCollection matches = EmojiRegex().Matches(pEmoji); + MatchCollection matches = EmojiRegex().Matches(emoji); if (!matches.Any()) { - await EditResponse_Error("There are no emojis in your input"); + await ctx.EditResponse_Error("There are no emojis in your input"); return; } @@ -48,7 +48,7 @@ await ctx.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMess if (!ulong.TryParse(split, out ulong emojiId)) { - await EditResponse_Error("⚠️ Failed to fetch your new emoji."); + await ctx.EditResponse_Error("⚠️ Failed to fetch your new emoji."); return; } @@ -71,7 +71,7 @@ await ctx.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMess if (!guilds.Any()) { - await EditResponse_Error("There are no guilds where you are able to add emojis"); + await ctx.EditResponse_Error("There are no guilds where you are able to add emojis"); return; } @@ -83,8 +83,8 @@ await ctx.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMess await ctx.EditResponseAsync(new DiscordWebhookBuilder().AddComponents(select)); //Get the initial response an wait for a component interaction - DiscordMessage response = await ctx.GetOriginalResponseAsync(); - InteractivityResult selectResponse = await response.WaitForSelectAsync(ctx.Member, "moveEmojiChooseGuild-" + ctx.User.Id, + DiscordMessage? response = await ctx.GetResponseAsync(); + InteractivityResult selectResponse = await response!.WaitForSelectAsync(ctx.Member, "moveEmojiChooseGuild-" + ctx.User.Id, TimeSpan.FromSeconds(60)); //Notify the user when the interaction times out and abort @@ -111,7 +111,7 @@ await ctx.EditResponseAsync(new DiscordWebhookBuilder await CopyEmoji(ctx.Client, emojiName, emojiId, animated, guildId); } - await EditResponse_Success("Emoji moved"); + await ctx.EditResponse_Success("Emoji moved"); } private static async Task CopyEmoji(DiscordClient client, string name, ulong id, bool animated, ulong targetGuild) diff --git a/ModularAssistentForDiscordServer/Commands/Text/Base/Eval.cs b/ModularAssistentForDiscordServer/Commands/Text/Base/Eval.cs index d4990b6..38417b4 100644 --- a/ModularAssistentForDiscordServer/Commands/Text/Base/Eval.cs +++ b/ModularAssistentForDiscordServer/Commands/Text/Base/Eval.cs @@ -12,21 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using DSharpPlus; -using DSharpPlus.CommandsNext; -using DSharpPlus.CommandsNext.Attributes; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ArgumentModifiers; +using DSharpPlus.Commands.Processors.TextCommands; using DSharpPlus.Entities; -using MADS.Extensions; using MADS.Services; using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; namespace MADS.Commands.Text.Base; -[RequireOwner, Hidden] -public class Eval : MadsBaseCommand +[RequireOwner] +public class Eval { - [Command("eval"), Description("Evaluate the result of c# code"), Hidden] + private DiscordClientService _service; + + public Eval(DiscordClientService service) + { + _service = service; + } + + [Command("eval"), Description("Evaluate the result of c# code")] public async Task EvalCommand(CommandContext ctx, [RemainingText] string code) { int codeStart = code.IndexOf("```", StringComparison.Ordinal) + 3; @@ -40,14 +48,16 @@ public async Task EvalCommand(CommandContext ctx, [RemainingText] string code) string csCode = code[codeStart..codeEnd]; - DiscordMessage message = await ctx.RespondAsync(new DiscordEmbedBuilder() + await ctx.RespondAsync(new DiscordEmbedBuilder() .WithColor(new DiscordColor("#FF007F")) .WithDescription("💭 Evaluating...") .Build()); + + DiscordMessage? message = await ctx.GetResponseAsync(); try { - TestVariables globalVariables = new(ctx.Message, ctx.Client, ctx, CommandService); + TestVariables globalVariables = new(ctx.Client, ctx, _service); ScriptOptions? scriptOptions = ScriptOptions.Default; scriptOptions = scriptOptions.WithImports("System", "System.Collections.Generic", "System.Linq", @@ -96,14 +106,14 @@ await message.ModifyAsync(new DiscordEmbedBuilder public class TestVariables { - public TestVariables(DiscordMessage msg, DiscordClient client, CommandContext ctx, DiscordClientService mdb) + public TestVariables(DiscordClient client, CommandContext ctx, DiscordClientService mdb) { Client = client; ClientService = mdb; - Message = msg; - Channel = msg.Channel; + Message = ctx is TextCommandContext txtCtx ? txtCtx.Message : null; + Channel = ctx.Channel; Guild = Channel?.Guild; - User = Message.Author; + User = ctx.User; if (Guild is not null && User is not null) { Member = Guild.GetMemberAsync(User.Id).GetAwaiter().GetResult(); @@ -112,7 +122,7 @@ public TestVariables(DiscordMessage msg, DiscordClient client, CommandContext ct Context = ctx; } - public DiscordMessage Message { get; private set; } + public DiscordMessage? Message { get; private set; } public DiscordChannel? Channel { get; private set; } public DiscordGuild? Guild { get; private set; } public DiscordUser? User { get; private set; } diff --git a/ModularAssistentForDiscordServer/Commands/Text/Base/ExitGuild.cs b/ModularAssistentForDiscordServer/Commands/Text/Base/ExitGuild.cs index 158a529..8467df5 100644 --- a/ModularAssistentForDiscordServer/Commands/Text/Base/ExitGuild.cs +++ b/ModularAssistentForDiscordServer/Commands/Text/Base/ExitGuild.cs @@ -12,14 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -using DSharpPlus.CommandsNext; -using DSharpPlus.CommandsNext.Attributes; +using System.ComponentModel; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; using DSharpPlus.Entities; -using MADS.Extensions; namespace MADS.Commands.Text.Base; -public class ExitGuild : MadsBaseCommand +public class ExitGuild { [Command("exit"), Description("Exit the bot"), RequirePermissions(DiscordPermissions.ManageGuild), RequireGuild] public async Task ExitGuildCommand(CommandContext ctx) diff --git a/ModularAssistentForDiscordServer/EventListeners/EventListener.Errors.cs b/ModularAssistentForDiscordServer/EventListeners/EventListener.Errors.cs index fffad78..04b5bce 100644 --- a/ModularAssistentForDiscordServer/EventListeners/EventListener.Errors.cs +++ b/ModularAssistentForDiscordServer/EventListeners/EventListener.Errors.cs @@ -13,16 +13,14 @@ // limitations under the License. using DSharpPlus; -using DSharpPlus.CommandsNext; -using DSharpPlus.CommandsNext.Exceptions; +using DSharpPlus.Commands; +using DSharpPlus.Commands.EventArgs; +using DSharpPlus.Commands.Exceptions; using DSharpPlus.Entities; using DSharpPlus.EventArgs; using DSharpPlus.Exceptions; using DSharpPlus.Interactivity; using DSharpPlus.Interactivity.Enums; -using DSharpPlus.Interactivity.Extensions; -using DSharpPlus.SlashCommands; -using DSharpPlus.SlashCommands.EventArgs; namespace MADS.EventListeners; @@ -72,7 +70,7 @@ await e.Context.Interaction.EditOriginalResponseAsync( await e.Context.Channel.SendMessageAsync(discordEmbed); } - internal static async Task OnCNextErrored(CommandsNextExtension sender, CommandErrorEventArgs e) + internal static async Task OnCommandsErrored(CommandsExtension sender, CommandErroredEventArgs e) { Type typeOfException = e.Exception.GetType(); if (typeOfException == typeof(ChecksFailedException) || typeOfException == typeof(ArgumentException) @@ -81,8 +79,8 @@ internal static async Task OnCNextErrored(CommandsNextExtension sender, CommandE return; } - await e.Context.Message.RespondAsync($"OOPS your command just errored... \n {e.Exception.Message}"); - await e.Context.Message.RespondAsync(e.Exception.InnerException?.Message ?? "no inner exception"); + await e.Context.RespondAsync($"OOPS your command just errored... \n {e.Exception.Message}"); + await e.Context.RespondAsync(e.Exception.InnerException?.Message ?? "no inner exception"); } internal static async Task OnClientErrored(DiscordClient sender, ClientErrorEventArgs e) diff --git a/ModularAssistentForDiscordServer/Extensions/ContextExtensions.cs b/ModularAssistentForDiscordServer/Extensions/ContextExtensions.cs new file mode 100644 index 0000000..416983c --- /dev/null +++ b/ModularAssistentForDiscordServer/Extensions/ContextExtensions.cs @@ -0,0 +1,86 @@ +// Copyright 2023 Plerx2493 +// +// Licensed under the Apache License, Version 2.0 (the "License") +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using DSharpPlus.Commands; +using DSharpPlus.Commands.Processors.SlashCommands; +using DSharpPlus.Entities; + +namespace MADS.Extensions; + +public static class ContextExtensions +{ + public static async ValueTask DeferAsync(this CommandContext ctx, bool ephemeral = false) + { + if (ctx is SlashCommandContext slashContext) + { + await slashContext.DeferResponseAsync(ephemeral); + } + + await ctx.DeferResponseAsync(); + } + + public static async ValueTask CreateResponse_Error(this CommandContext ctx, string message, bool isEphemeral = false) + { + DiscordEmbedBuilder embed = new DiscordEmbedBuilder() + .WithTitle("Error") + .WithDescription(message) + .WithColor(DiscordColor.Red); + + DiscordInteractionResponseBuilder response = new DiscordInteractionResponseBuilder() + .AddEmbed(embed) + .AsEphemeral(isEphemeral); + + await ctx.RespondAsync(response); + } + + public static async ValueTask CreateResponse_Success(this CommandContext ctx, string message, bool isEphemeral = false) + { + DiscordEmbedBuilder embed = new DiscordEmbedBuilder() + .WithTitle("Success") + .WithDescription(message) + .WithColor(DiscordColor.Green); + + DiscordInteractionResponseBuilder response = new DiscordInteractionResponseBuilder() + .AddEmbed(embed) + .AsEphemeral(isEphemeral); + + await ctx.RespondAsync(response); + } + + public static async ValueTask EditResponse_Error(this CommandContext ctx, string message) + { + DiscordEmbedBuilder embed = new DiscordEmbedBuilder() + .WithTitle("Error") + .WithDescription(message) + .WithColor(DiscordColor.Red); + + DiscordWebhookBuilder response = new DiscordWebhookBuilder() + .AddEmbed(embed); + + await ctx.EditResponseAsync(response); + } + + public static async ValueTask EditResponse_Success(this CommandContext ctx, string message) + { + DiscordEmbedBuilder embed = new DiscordEmbedBuilder() + .WithTitle("Success") + .WithDescription(message) + .WithColor(DiscordColor.Green); + + DiscordWebhookBuilder response = new DiscordWebhookBuilder() + .AddEmbed(embed); + + await ctx.EditResponseAsync(response); + } +} \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Extensions/MadsBaseApplicationCommand.cs b/ModularAssistentForDiscordServer/Extensions/MadsBaseApplicationCommand.cs deleted file mode 100644 index 105d486..0000000 --- a/ModularAssistentForDiscordServer/Extensions/MadsBaseApplicationCommand.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2023 Plerx2493 -// -// Licensed under the Apache License, Version 2.0 (the "License") -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Diagnostics; -using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; -using MADS.Services; -using Microsoft.Extensions.DependencyInjection; - -namespace MADS.Extensions; - -[SlashModuleLifespan(SlashModuleLifespan.Transient)] -public class MadsBaseApplicationCommand : ApplicationCommandModule -{ - private InteractionContext? _ctx; - private readonly Stopwatch _executionTimer = new(); - protected DiscordClientService CommandService => ModularDiscordBot.Services.GetRequiredService(); - - public override Task BeforeSlashExecutionAsync(InteractionContext ctx) - { - _ctx = ctx; - _executionTimer.Restart(); - - return Task.FromResult(true); - } - - public override Task AfterSlashExecutionAsync(InteractionContext ctx) - { - _executionTimer.Stop(); - - _ = CommandService.Logging.LogCommandExecutionAsync(ctx, _executionTimer.Elapsed); - - - return Task.CompletedTask; - } - - public override Task BeforeContextMenuExecutionAsync(ContextMenuContext ctx) - { - _executionTimer.Restart(); - - return Task.FromResult(true); - } - - public override Task AfterContextMenuExecutionAsync(ContextMenuContext ctx) - { - _executionTimer.Stop(); - - _ = CommandService.Logging.LogCommandExecutionAsync(ctx, _executionTimer.Elapsed); - - return Task.FromResult(true); - } - - public async Task IntendedWait(int milliseconds) - { - _executionTimer.Stop(); - - await Task.Delay(milliseconds); - - _executionTimer.Start(); - } - - protected async Task CreateResponse_Error(string message, bool isEphemeral = false) - { - DiscordEmbedBuilder embed = new DiscordEmbedBuilder() - .WithTitle("Error") - .WithDescription(message) - .WithColor(DiscordColor.Red); - - DiscordInteractionResponseBuilder response = new DiscordInteractionResponseBuilder() - .AddEmbed(embed) - .AsEphemeral(isEphemeral); - - await _ctx!.CreateResponseAsync(response); - } - - protected async Task CreateResponse_Success(string message, bool isEphemeral = false) - { - DiscordEmbedBuilder embed = new DiscordEmbedBuilder() - .WithTitle("Success") - .WithDescription(message) - .WithColor(DiscordColor.Green); - - DiscordInteractionResponseBuilder response = new DiscordInteractionResponseBuilder() - .AddEmbed(embed) - .AsEphemeral(isEphemeral); - - await _ctx!.CreateResponseAsync(response); - } - - protected async Task EditResponse_Error(string message) - { - DiscordEmbedBuilder embed = new DiscordEmbedBuilder() - .WithTitle("Error") - .WithDescription(message) - .WithColor(DiscordColor.Red); - - DiscordWebhookBuilder response = new DiscordWebhookBuilder() - .AddEmbed(embed); - - await _ctx!.EditResponseAsync(response); - } - - protected async Task EditResponse_Success(string message) - { - DiscordEmbedBuilder embed = new DiscordEmbedBuilder() - .WithTitle("Success") - .WithDescription(message) - .WithColor(DiscordColor.Green); - - DiscordWebhookBuilder response = new DiscordWebhookBuilder() - .AddEmbed(embed); - - await _ctx!.EditResponseAsync(response); - } -} \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Extensions/MadsBaseCommand.cs b/ModularAssistentForDiscordServer/Extensions/MadsBaseCommand.cs deleted file mode 100644 index ea4015e..0000000 --- a/ModularAssistentForDiscordServer/Extensions/MadsBaseCommand.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2023 Plerx2493 -// -// Licensed under the Apache License, Version 2.0 (the "License") -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Diagnostics; -using DSharpPlus.CommandsNext; -using MADS.Services; -using Microsoft.Extensions.DependencyInjection; - -namespace MADS.Extensions; - -public class MadsBaseCommand : BaseCommandModule -{ - private readonly Stopwatch _executionTimer = new(); - public DiscordClientService CommandService => ModularDiscordBot.Services.GetRequiredService(); - - public override Task BeforeExecutionAsync(CommandContext ctx) - { - _executionTimer.Restart(); - - return Task.FromResult(true); - } - - public override Task AfterExecutionAsync(CommandContext ctx) - { - _executionTimer.Stop(); - - _ = CommandService.Logging.LogCommandExecutionAsync(ctx, _executionTimer.Elapsed); - - - return Task.FromResult(true); - } - - public async Task IntendedWait(int milliseconds) - { - _executionTimer.Stop(); - - await Task.Delay(milliseconds); - - _executionTimer.Start(); - } -} \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/Extensions/SlashCommandsAttributes.cs b/ModularAssistentForDiscordServer/Extensions/SlashCommandsAttributes.cs deleted file mode 100644 index 18f9a50..0000000 --- a/ModularAssistentForDiscordServer/Extensions/SlashCommandsAttributes.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2023 Plerx2493 -// -// Licensed under the Apache License, Version 2.0 (the "License") -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using DSharpPlus.Entities; -using DSharpPlus.SlashCommands; - -namespace MADS.Extensions; - -public sealed class SlashRequireOwnerAttribute : SlashCheckBaseAttribute -{ - public override Task ExecuteChecksAsync(InteractionContext ctx) - { - DiscordApplication? app = ctx.Client.CurrentApplication; - DiscordUser me = ctx.Client.CurrentUser; - - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - return app is not null - ? Task.FromResult(app.Owners?.Any(x => x.Id == ctx.User.Id) ?? false) - : Task.FromResult(ctx.User.Id == me.Id); - } -} \ No newline at end of file diff --git a/ModularAssistentForDiscordServer/ModularAssistentForDiscordServer.csproj b/ModularAssistentForDiscordServer/ModularAssistentForDiscordServer.csproj index 660077c..65931f7 100644 --- a/ModularAssistentForDiscordServer/ModularAssistentForDiscordServer.csproj +++ b/ModularAssistentForDiscordServer/ModularAssistentForDiscordServer.csproj @@ -26,10 +26,9 @@ - + - diff --git a/ModularAssistentForDiscordServer/Services/DiscordClientService.cs b/ModularAssistentForDiscordServer/Services/DiscordClientService.cs index 5d68b9d..9767556 100644 --- a/ModularAssistentForDiscordServer/Services/DiscordClientService.cs +++ b/ModularAssistentForDiscordServer/Services/DiscordClientService.cs @@ -12,17 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. - using System.Diagnostics; using System.Reflection; using DSharpPlus; -using DSharpPlus.CommandsNext; +using DSharpPlus.Commands; using DSharpPlus.Entities; using DSharpPlus.EventArgs; using DSharpPlus.Interactivity; using DSharpPlus.Interactivity.Enums; using DSharpPlus.Interactivity.Extensions; -using DSharpPlus.SlashCommands; using MADS.Entities; using MADS.EventListeners; using Microsoft.EntityFrameworkCore; @@ -36,10 +34,9 @@ namespace MADS.Services; public class DiscordClientService : IHostedService { private readonly IDbContextFactory _dbContextFactory; - public readonly CommandsNextExtension CommandsNext; + public readonly CommandsExtension Commands; public readonly DiscordClient DiscordClient; public readonly LoggingService Logging; - public readonly SlashCommandsExtension SlashCommands; public DateTime StartTime; private static ILogger _logger = Log.ForContext(); @@ -75,33 +72,21 @@ LoggingService loggingService DiscordClient.GuildAvailable += EventListener.OnGuildAvailable; DiscordClient.ComponentInteractionCreated += EventListener.ActionButtons; DiscordClient.ComponentInteractionCreated += EventListener.OnRoleSelection; + DiscordClient.SocketErrored += EventListener.OnSocketErrored; Assembly asm = Assembly.GetExecutingAssembly(); - - //CNext - CommandsNextConfiguration cnextConfig = new() + + CommandsConfiguration cnextConfig = new() { - CaseSensitive = false, - DmHelp = false, - EnableDms = true, - EnableMentionPrefix = true + ServiceProvider = ModularDiscordBot.Services, +#if !RELEASE + DebugGuildId = 938120155974750288 +#endif }; - CommandsNext = DiscordClient.UseCommandsNext(cnextConfig); - CommandsNext.RegisterCommands(asm); - CommandsNext.CommandErrored += EventListener.OnCNextErrored; + Commands = DiscordClient.UseCommands(cnextConfig); + Commands.AddCommands(asm); + Commands.CommandErrored += EventListener.OnCommandsErrored; - //Slashcommands - SlashCommandsConfiguration slashConfig = new() - { - Services = ModularDiscordBot.Services - }; - SlashCommands = DiscordClient.UseSlashCommands(slashConfig); -#if RELEASE - SlashCommands.RegisterCommands(asm); -#else - _logger.Warning("SlashCommands are registered in debug mode"); - SlashCommands.RegisterCommands(asm, 938120155974750288); -#endif SlashCommands.SlashCommandErrored += EventListener.OnSlashCommandErrored; SlashCommands.AutocompleteErrored += EventListener.OnAutocompleteError; diff --git a/ModularAssistentForDiscordServer/Services/LoggingService.cs b/ModularAssistentForDiscordServer/Services/LoggingService.cs index b07420f..a1834eb 100644 --- a/ModularAssistentForDiscordServer/Services/LoggingService.cs +++ b/ModularAssistentForDiscordServer/Services/LoggingService.cs @@ -16,10 +16,9 @@ using System.Text; using System.Text.RegularExpressions; using DSharpPlus; -using DSharpPlus.CommandsNext; +using DSharpPlus.Commands; using DSharpPlus.Entities; using DSharpPlus.Exceptions; -using DSharpPlus.SlashCommands; using MADS.Entities; using MADS.Extensions; using Microsoft.Extensions.DependencyInjection;