|
| 1 | +using Discord; |
| 2 | +using Discord.Interactions; |
| 3 | +using Microsoft.Extensions.DependencyInjection; |
| 4 | +using Microsoft.Extensions.Options; |
| 5 | +using RustPlusBot.Persistence.Maintenance; |
| 6 | + |
| 7 | +namespace RustPlusBot.Features.Commands.Modules; |
| 8 | + |
| 9 | +/// <summary>Dangerous, danger-gated bot maintenance commands.</summary> |
| 10 | +/// <param name="scopeFactory">Creates a short-lived DI scope per interaction.</param> |
| 11 | +/// <param name="options">Gates the command behind the danger flag.</param> |
| 12 | +[Group("admin", "Bot maintenance (dangerous)")] |
| 13 | +[RequireUserPermission(GuildPermission.ManageGuild)] |
| 14 | +public sealed class MaintenanceModule( |
| 15 | + IServiceScopeFactory scopeFactory, |
| 16 | + IOptions<MaintenanceOptions> options) : InteractionModuleBase<SocketInteractionContext> |
| 17 | +{ |
| 18 | + /// <summary>Wipes all bot data across all guilds after a typed confirmation.</summary> |
| 19 | + /// <param name="confirm">Must equal the literal "RESET" to proceed.</param> |
| 20 | + [SlashCommand("reset-database", "Wipe ALL bot data across ALL servers (dangerous)")] |
| 21 | + public async Task ResetDatabaseAsync( |
| 22 | + [Summary("confirm", "Type RESET to confirm")] |
| 23 | + string confirm) |
| 24 | + { |
| 25 | + if (Context.Guild is null) |
| 26 | + { |
| 27 | + await RespondAsync("This command must be used in a server.", ephemeral: true).ConfigureAwait(false); |
| 28 | + return; |
| 29 | + } |
| 30 | + |
| 31 | + if (!options.Value.EnableDangerCommands) |
| 32 | + { |
| 33 | + await RespondAsync("Developer commands are disabled.", ephemeral: true).ConfigureAwait(false); |
| 34 | + return; |
| 35 | + } |
| 36 | + |
| 37 | + if (!string.Equals(confirm, "RESET", StringComparison.Ordinal)) |
| 38 | + { |
| 39 | + await RespondAsync("Type `RESET` exactly to confirm the database wipe.", ephemeral: true) |
| 40 | + .ConfigureAwait(false); |
| 41 | + return; |
| 42 | + } |
| 43 | + |
| 44 | + await DeferAsync(ephemeral: true).ConfigureAwait(false); |
| 45 | + var scope = scopeFactory.CreateAsyncScope(); |
| 46 | + try |
| 47 | + { |
| 48 | + var maintenance = scope.ServiceProvider.GetRequiredService<IDatabaseMaintenanceService>(); |
| 49 | + await maintenance.ClearAllAsync().ConfigureAwait(false); |
| 50 | + await FollowupAsync("Database cleared. **Restart the bot** for a clean state.", ephemeral: true) |
| 51 | + .ConfigureAwait(false); |
| 52 | + } |
| 53 | + finally |
| 54 | + { |
| 55 | + await scope.DisposeAsync().ConfigureAwait(false); |
| 56 | + } |
| 57 | + } |
| 58 | +} |
0 commit comments