Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev/Sub command groups and stuff #84

Merged
merged 14 commits into from
May 20, 2024
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
dotnet_naming_symbols.static_fields.applicable_accessibilities = public, private, internal, private_protected
dotnet_naming_style.static_prefix_style.capitalization = pascal_case

# internal and private fields should be _camelCase
Expand Down
1 change: 1 addition & 0 deletions AzzyBot-Next/AzzyBot-Next.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<NoWarn>$(NoWarn);CA1812;CA2007</NoWarn>
<Configurations>Debug;Release;Docker;Docker-debug</Configurations>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<StartupObject>AzzyBot.Startup</StartupObject>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand Down
176 changes: 100 additions & 76 deletions AzzyBot-Next/Commands/AdminCommands.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
Expand All @@ -19,121 +21,143 @@

namespace AzzyBot.Commands;

internal sealed class AdminCommands
[SuppressMessage("Design", "CA1034:Nested types should not be visible", Justification = "DSharpPlus best practice")]
public sealed class AdminCommands
{
[Command("admin"), RequireGuild, RequireApplicationOwner, RequirePermissions(DiscordPermissions.None, DiscordPermissions.Administrator)]
internal sealed class Admin(DbActions dbActions, DiscordBotService botService, DiscordBotServiceHost botServiceHost, ILogger<Admin> logger)
public sealed class AdminGroup(DiscordBotServiceHost botServiceHost, ILogger<AdminGroup> logger)
{
private readonly DbActions _dbActions = dbActions;
private readonly DiscordBotService _botService = botService;
private readonly DiscordBotServiceHost _botServiceHost = botServiceHost;
private readonly ILogger<Admin> _logger = logger;
private readonly ILogger<AdminGroup> _logger = logger;

[Command("change-bot-status"), Description("Change the global bot status according to your likes.")]
public async ValueTask CoreChangeStatusAsync
public async ValueTask ChangeStatusAsync
(
CommandContext context,
[Description("Choose the activity type which the bot should have."), SlashChoiceProvider<BotActivityProvider>] int activity,
[Description("Choose the status type which the bot should have."), SlashChoiceProvider<BotStatusProvider>] int status,
[Description("Enter a custom doing which is added after the activity type."), MinMaxLength(0, 128)] string doing,
[Description("Enter a custom url. Only usable when having activity type streaming or watching!")] string? url = null,
[Description("Choose the activity type which the bot should have."), SlashChoiceProvider<BotActivityProvider>] int activity = 1,
[Description("Choose the status type which the bot should have."), SlashChoiceProvider<BotStatusProvider>] int status = 2,
[Description("Enter a custom doing which is added after the activity type."), MinMaxLength(0, 128)] string doing = "Music",
[Description("Enter a custom url. Only usable when having activity type streaming or watching!")] Uri? url = null,
[Description("Reset the status to default.")] bool reset = false
)
{
_logger.CommandRequested(nameof(CoreChangeStatusAsync), context.User.GlobalName);
ArgumentNullException.ThrowIfNull(context, nameof(context));

_logger.CommandRequested(nameof(ChangeStatusAsync), context.User.GlobalName);

await context.DeferResponseAsync();

await _botServiceHost.SetBotStatusAsync(status, activity, doing, url, reset);

await context.EditResponseAsync("Bot status has been updated!");
}

[Command("get-debug-servers"), Description("Displays all servers which can execute debug commands.")]
public async ValueTask AdminGetDebugGuildsAsync(CommandContext context)
{
_logger.CommandRequested(nameof(AdminGetDebugGuildsAsync), context.User.GlobalName);

await context.DeferResponseAsync();

List<GuildsEntity> dbGuilds = await _dbActions.GetGuildEntitiesWithDebugAsync();
if (dbGuilds.Count == 0)
if (reset)
{
await context.EditResponseAsync("No debug servers found.");
return;
await context.EditResponseAsync("Bot status has been reset!");
}

Dictionary<ulong, DiscordGuild> clientGuilds = _botService.GetDiscordGuilds();
StringBuilder stringBuilder = new();
stringBuilder.AppendLine("I found the following Debug servers:");
foreach (GuildsEntity guild in dbGuilds.Where(g => clientGuilds.ContainsKey(g.UniqueId)))
else
{
stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"- {clientGuilds[guild.UniqueId].Name}");
await context.EditResponseAsync("Bot status has been updated!");
}

await context.EditResponseAsync(stringBuilder.ToString());
}

[Command("remove-debug-server"), Description("Removes the permission to execute debug commands from a server.")]
public async ValueTask AdminRemoveDebugGuildsAsync(CommandContext context, [Description("Select the server you want to remove."), SlashAutoCompleteProvider<GuildsAutocomplete>] string serverId = "")
[Command("debug-servers")]
public sealed class AdminDebugServers(DbActions dbActions, DiscordBotService botService, ILogger<AdminDebugServers> logger)
{
_logger.CommandRequested(nameof(AdminRemoveDebugGuildsAsync), context.User.GlobalName);
private readonly DbActions _dbActions = dbActions;
private readonly DiscordBotService _botService = botService;
private readonly ILogger<AdminDebugServers> _logger = logger;

if (!ulong.TryParse(serverId, out ulong guildIdValue))
[Command("add-server"), Description("Adds the permission to execute debug commands to a server.")]
public async ValueTask AddDebugGuildsAsync(CommandContext context, [Description("Select the server you want to add."), SlashAutoCompleteProvider<GuildsAutocomplete>] string serverId = "")
{
await context.RespondAsync("Invalid server id.");
return;
}
ArgumentNullException.ThrowIfNull(context, nameof(context));

await context.DeferResponseAsync();
_logger.CommandRequested(nameof(AddDebugGuildsAsync), context.User.GlobalName);

GuildsEntity? guildEntity = await _dbActions.GetGuildEntityAsync(guildIdValue);
if (guildEntity is null)
{
await context.EditResponseAsync("Server not found in the database.");
return;
}
if (!ulong.TryParse(serverId, out ulong guildIdValue))
{
await context.RespondAsync("Invalid server id.");
return;
}

if (!guildEntity.IsDebugAllowed)
{
await context.EditResponseAsync("Server is not specified as debug.");
return;
}
await context.DeferResponseAsync();

await _dbActions.SetGuildEntityAsync(guildIdValue, 0, false);
GuildsEntity? guildEntity = await _dbActions.GetGuildEntityAsync(guildIdValue);
if (guildEntity is null)
{
await context.EditResponseAsync("Server not found in the database.");
return;
}

await context.EditResponseAsync($"{await _botService.GetDiscordGuildAsync(guildIdValue)} removed from debug servers.");
}
if (guildEntity.IsDebugAllowed)
{
await context.EditResponseAsync("Server is already specified as debug.");
return;
}

[Command("set-debug-server"), Description("Adds the permission to execute debug commands to a server.")]
public async ValueTask AdminSetDebugGuildsAsync(CommandContext context, [Description("Select the server you want to add."), SlashAutoCompleteProvider<GuildsAutocomplete>] string serverId = "")
{
_logger.CommandRequested(nameof(AdminSetDebugGuildsAsync), context.User.GlobalName);
await _dbActions.SetGuildEntityAsync(guildIdValue, 0, true);

if (!ulong.TryParse(serverId, out ulong guildIdValue))
{
await context.RespondAsync("Invalid server id.");
return;
await context.EditResponseAsync($"{await _botService.GetDiscordGuildAsync(guildIdValue)} added to debug servers.");
}

await context.DeferResponseAsync();

GuildsEntity? guildEntity = await _dbActions.GetGuildEntityAsync(guildIdValue);
if (guildEntity is null)
[Command("get-servers"), Description("Displays all servers which can execute debug commands.")]
public async ValueTask GetDebugGuildsAsync(CommandContext context)
{
await context.EditResponseAsync("Server not found in the database.");
return;
ArgumentNullException.ThrowIfNull(context, nameof(context));

_logger.CommandRequested(nameof(GetDebugGuildsAsync), context.User.GlobalName);

await context.DeferResponseAsync();

List<GuildsEntity> dbGuilds = await _dbActions.GetGuildEntitiesWithDebugAsync();
if (dbGuilds.Count == 0)
{
await context.EditResponseAsync("No debug servers found.");
return;
}

Dictionary<ulong, DiscordGuild> clientGuilds = _botService.GetDiscordGuilds();
StringBuilder stringBuilder = new();
stringBuilder.AppendLine("I found the following Debug servers:");
foreach (GuildsEntity guild in dbGuilds.Where(g => clientGuilds.ContainsKey(g.UniqueId)))
{
stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"- {clientGuilds[guild.UniqueId].Name}");
}

await context.EditResponseAsync(stringBuilder.ToString());
}

if (guildEntity.IsDebugAllowed)
[Command("remove-server"), Description("Removes the permission to execute debug commands from a server.")]
public async ValueTask RemoveDebugGuildsAsync(CommandContext context, [Description("Select the server you want to remove."), SlashAutoCompleteProvider<GuildsAutocomplete>] string serverId = "")
{
await context.EditResponseAsync("Server is already specified as debug.");
return;
}
ArgumentNullException.ThrowIfNull(context, nameof(context));

_logger.CommandRequested(nameof(RemoveDebugGuildsAsync), context.User.GlobalName);

if (!ulong.TryParse(serverId, out ulong guildIdValue))
{
await context.RespondAsync("Invalid server id.");
return;
}

await _dbActions.SetGuildEntityAsync(guildIdValue, 0, true);
await context.DeferResponseAsync();

await context.EditResponseAsync($"{await _botService.GetDiscordGuildAsync(guildIdValue)} added to debug servers.");
GuildsEntity? guildEntity = await _dbActions.GetGuildEntityAsync(guildIdValue);
if (guildEntity is null)
{
await context.EditResponseAsync("Server not found in the database.");
return;
}

if (!guildEntity.IsDebugAllowed)
{
await context.EditResponseAsync("Server is not specified as debug.");
return;
}

await _dbActions.SetGuildEntityAsync(guildIdValue, 0, false);

await context.EditResponseAsync($"{await _botService.GetDiscordGuildAsync(guildIdValue)} removed from debug servers.");
}
}
}
}
4 changes: 3 additions & 1 deletion AzzyBot-Next/Commands/Autocompletes/AzzyHelpAutocomplete.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@

namespace AzzyBot.Commands.Autocompletes;

internal sealed class AzzyHelpAutocomplete(AzzyBotSettingsRecord settings, DbActions dbActions) : IAutoCompleteProvider
public sealed class AzzyHelpAutocomplete(AzzyBotSettingsRecord settings, DbActions dbActions) : IAutoCompleteProvider
{
private readonly AzzyBotSettingsRecord _settings = settings;
private readonly DbActions _dbActions = dbActions;

public async ValueTask<IReadOnlyDictionary<string, object>> AutoCompleteAsync(AutoCompleteContext context)
{
ArgumentNullException.ThrowIfNull(context, nameof(context));

Dictionary<string, object> results = [];

IEnumerable<DiscordUser> botOwners = context.Client.CurrentApplication.Owners ?? throw new InvalidOperationException("Invalid bot owners");
Expand Down
7 changes: 5 additions & 2 deletions AzzyBot-Next/Commands/Autocompletes/GuildsAutocomplete.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -12,13 +13,15 @@

namespace AzzyBot.Commands.Autocompletes;

internal sealed class GuildsAutocomplete(DiscordBotService botService, IDbContextFactory<AzzyDbContext> dbContextFactory) : IAutoCompleteProvider
public sealed class GuildsAutocomplete(DiscordBotService botService, IDbContextFactory<AzzyDbContext> dbContextFactory) : IAutoCompleteProvider
{
private readonly DiscordBotService _botService = botService;
private readonly IDbContextFactory<AzzyDbContext> _dbContextFactory = dbContextFactory;

public async ValueTask<IReadOnlyDictionary<string, object>> AutoCompleteAsync(AutoCompleteContext context)
{
ArgumentNullException.ThrowIfNull(context, nameof(context));

await using AzzyDbContext dbContext = await _dbContextFactory.CreateDbContextAsync();
List<GuildsEntity> guildsInDb = [];
Dictionary<ulong, DiscordGuild> guilds = _botService.GetDiscordGuilds();
Expand Down
2 changes: 1 addition & 1 deletion AzzyBot-Next/Commands/Choices/BotActivityProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace AzzyBot.Commands.Choices;

internal sealed class BotActivityProvider : IChoiceProvider
public sealed class BotActivityProvider : IChoiceProvider
{
private readonly IReadOnlyDictionary<string, object> _botActivity = new Dictionary<string, object>()
{
Expand Down
2 changes: 1 addition & 1 deletion AzzyBot-Next/Commands/Choices/BotStatusProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace AzzyBot.Commands.Choices;

internal sealed class BotStatusProvider : IChoiceProvider
public sealed class BotStatusProvider : IChoiceProvider
{
private readonly IReadOnlyDictionary<string, object> _botStatus = new Dictionary<string, object>()
{
Expand Down
2 changes: 1 addition & 1 deletion AzzyBot-Next/Commands/Choices/ViewAddRemove.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace AzzyBot.Commands.Choices;

internal sealed class ViewAddRemove : IChoiceProvider
public sealed class ViewAddRemove : IChoiceProvider
{
private readonly IReadOnlyDictionary<string, object> _botStatus = new Dictionary<string, object>()
{
Expand Down
Loading