Skip to content

Commit ac7ec7a

Browse files
committed
feat(connections): #info remove-server button with confirm
1 parent cd10f82 commit ac7ec7a

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using Discord;
2+
using Discord.Interactions;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using RustPlusBot.Features.Connections.Removal;
5+
using RustPlusBot.Features.Workspace;
6+
7+
namespace RustPlusBot.Features.Connections.Modules;
8+
9+
/// <summary>Handles the #info "Remove server" button and its confirmation (ManageGuild).</summary>
10+
/// <param name="scopeFactory">Creates a short-lived DI scope per interaction.</param>
11+
public sealed class ServerRemovalModule(IServiceScopeFactory scopeFactory)
12+
: InteractionModuleBase<SocketInteractionContext>
13+
{
14+
private const string RemoveConfirmPrefix = "connections:server:remove:confirm:";
15+
private const string RemoveCancelId = "connections:server:remove:cancel";
16+
17+
/// <summary>Opens an ephemeral confirmation for removing the server.</summary>
18+
/// <param name="serverIdRaw">The server id captured from the custom id.</param>
19+
[ComponentInteraction(WorkspaceComponentIds.ServerInfoRemovePrefix + "*")]
20+
[RequireUserPermission(GuildPermission.ManageGuild)]
21+
public async Task RemovePromptAsync(string serverIdRaw)
22+
{
23+
if (Context.Guild is null)
24+
{
25+
await RespondAsync("This control must be used in a server.", ephemeral: true).ConfigureAwait(false);
26+
return;
27+
}
28+
29+
if (!Guid.TryParse(serverIdRaw, out var serverId))
30+
{
31+
await RespondAsync("That selection wasn't valid.", ephemeral: true).ConfigureAwait(false);
32+
return;
33+
}
34+
35+
var components = new ComponentBuilder()
36+
.WithButton("Remove server", $"{RemoveConfirmPrefix}{serverId}", ButtonStyle.Danger)
37+
.WithButton("Cancel", RemoveCancelId, ButtonStyle.Secondary)
38+
.Build();
39+
await RespondAsync(
40+
"This permanently deletes the category, all channels, and stored credentials for this server. Continue?",
41+
ephemeral: true, components: components)
42+
.ConfigureAwait(false);
43+
}
44+
45+
/// <summary>Removes the server after confirmation.</summary>
46+
/// <param name="serverIdRaw">The server id captured from the custom id.</param>
47+
[ComponentInteraction(RemoveConfirmPrefix + "*")]
48+
[RequireUserPermission(GuildPermission.ManageGuild)]
49+
public async Task RemoveConfirmAsync(string serverIdRaw)
50+
{
51+
if (Context.Guild is null)
52+
{
53+
await RespondAsync("This control must be used in a server.", ephemeral: true).ConfigureAwait(false);
54+
return;
55+
}
56+
57+
if (!Guid.TryParse(serverIdRaw, out var serverId))
58+
{
59+
await RespondAsync("That selection wasn't valid.", ephemeral: true).ConfigureAwait(false);
60+
return;
61+
}
62+
63+
await DeferAsync(ephemeral: true).ConfigureAwait(false);
64+
65+
var scope = scopeFactory.CreateAsyncScope();
66+
await using (scope.ConfigureAwait(false))
67+
{
68+
var removal = scope.ServiceProvider.GetRequiredService<IServerRemovalService>();
69+
var removed = await removal.RemoveServerAsync(Context.Guild.Id, serverId).ConfigureAwait(false);
70+
await FollowupAsync(removed ? "Server removed." : "That server no longer exists.", ephemeral: true)
71+
.ConfigureAwait(false);
72+
}
73+
}
74+
75+
/// <summary>Cancels the removal.</summary>
76+
[ComponentInteraction(RemoveCancelId)]
77+
public async Task RemoveCancelAsync() =>
78+
await RespondAsync("Cancelled.", ephemeral: true).ConfigureAwait(false);
79+
}

0 commit comments

Comments
 (0)