-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCommandSurfaceModule.cs
More file actions
167 lines (147 loc) · 7.11 KB
/
Copy pathCommandSurfaceModule.cs
File metadata and controls
167 lines (147 loc) · 7.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
using System.Globalization;
using Discord;
using Discord.Interactions;
using Microsoft.Extensions.DependencyInjection;
using RustPlusBot.Abstractions.Formatting;
using RustPlusBot.Features.Commands.Help;
using RustPlusBot.Features.Commands.Hosting;
using RustPlusBot.Features.Commands.Leader;
using RustPlusBot.Localization;
using RustPlusBot.Persistence.Commands;
using RustPlusBot.Persistence.Servers;
using RustPlusBot.Persistence.Workspace;
namespace RustPlusBot.Features.Commands.Modules;
/// <summary>The /help, /uptime, and /leader slash commands.</summary>
/// <param name="scopeFactory">Creates a short-lived DI scope per interaction.</param>
public sealed class CommandSurfaceModule(IServiceScopeFactory scopeFactory)
: InteractionModuleBase<SocketInteractionContext>
{
/// <summary>The custom-id prefix for the /leader server-pick select.</summary>
public const string LeaderServerSelectId = "leader-server";
/// <summary>The custom-id prefix for the /leader member-pick select (suffixed with the server id).</summary>
public const string LeaderPromotePrefix = "leader-promote:";
/// <summary>Lists the available in-game and slash commands.</summary>
[SlashCommand("help", "Show the available commands")]
public async Task HelpAsync()
{
if (Context.Guild is null)
{
await RespondAsync("This command must be used in a server.", ephemeral: true).ConfigureAwait(false);
return;
}
await DeferAsync(ephemeral: true).ConfigureAwait(false);
var scope = scopeFactory.CreateAsyncScope();
await using (scope.ConfigureAwait(false))
{
var workspace = scope.ServiceProvider.GetRequiredService<IWorkspaceStore>();
var servers = scope.ServiceProvider.GetRequiredService<IServerService>();
var muteStore = scope.ServiceProvider.GetRequiredService<IMuteStore>();
var renderer = scope.ServiceProvider.GetRequiredService<HelpEmbedRenderer>();
var culture = await workspace.GetCultureAsync(Context.Guild.Id).ConfigureAwait(false);
var known = await servers.ListAsync(Context.Guild.Id).ConfigureAwait(false);
var prefix = "!";
var showNote = false;
if (known.Count == 1)
{
prefix = await muteStore.GetPrefixAsync(Context.Guild.Id, known[0].Id).ConfigureAwait(false);
}
else if (known.Count > 1)
{
showNote = true;
}
var embed = renderer.Render(prefix, culture, showNote);
await FollowupAsync(ephemeral: true, embed: embed).ConfigureAwait(false);
}
}
/// <summary>Reports the bot process uptime.</summary>
[SlashCommand("uptime", "Show how long the bot has been running")]
public async Task UptimeAsync()
{
if (Context.Guild is null)
{
await RespondAsync("This command must be used in a server.", ephemeral: true).ConfigureAwait(false);
return;
}
var scope = scopeFactory.CreateAsyncScope();
await using (scope.ConfigureAwait(false))
{
var workspace = scope.ServiceProvider.GetRequiredService<IWorkspaceStore>();
var localizer = scope.ServiceProvider.GetRequiredService<ILocalizer>();
var uptime = scope.ServiceProvider.GetRequiredService<BotUptime>();
var culture = await workspace.GetCultureAsync(Context.Guild.Id).ConfigureAwait(false);
var text = localizer.Get("uptime.ok", culture, DurationFormat.Compact(uptime.Elapsed));
await RespondAsync(text, ephemeral: true).ConfigureAwait(false);
}
}
/// <summary>Transfers in-game team leadership (ManageGuild). Opens a server or member select.</summary>
[SlashCommand("leader", "Transfer in-game team leadership")]
[RequireUserPermission(GuildPermission.ManageGuild)]
public async Task LeaderAsync()
{
if (Context.Guild is null)
{
await RespondAsync("This command must be used in a server.", ephemeral: true).ConfigureAwait(false);
return;
}
await DeferAsync(ephemeral: true).ConfigureAwait(false);
var scope = scopeFactory.CreateAsyncScope();
await using (scope.ConfigureAwait(false))
{
var workspace = scope.ServiceProvider.GetRequiredService<IWorkspaceStore>();
var servers = scope.ServiceProvider.GetRequiredService<IServerService>();
var leader = scope.ServiceProvider.GetRequiredService<LeaderService>();
var localizer = scope.ServiceProvider.GetRequiredService<ILocalizer>();
var culture = await workspace.GetCultureAsync(Context.Guild.Id).ConfigureAwait(false);
var known = await servers.ListAsync(Context.Guild.Id).ConfigureAwait(false);
if (known.Count == 0)
{
await FollowupAsync(localizer.Get("leader.noserver", culture), ephemeral: true).ConfigureAwait(false);
return;
}
if (known.Count > 1)
{
var serverSelect = new SelectMenuBuilder()
.WithCustomId(LeaderServerSelectId)
.WithPlaceholder(localizer.Get("leader.pickserver", culture));
foreach (var server in known.Take(SelectMenuBuilder.MaxOptionCount))
{
serverSelect.AddOption(server.Name, server.Id.ToString());
}
var components = new ComponentBuilder().WithSelectMenu(serverSelect).Build();
await FollowupAsync(localizer.Get("leader.pickserver", culture), ephemeral: true,
components: components).ConfigureAwait(false);
return;
}
await ShowMemberSelectAsync(scope.ServiceProvider, leader, localizer, Context.Guild.Id, known[0].Id,
culture).ConfigureAwait(false);
}
}
private async Task ShowMemberSelectAsync(
IServiceProvider provider,
LeaderService leader,
ILocalizer localizer,
ulong guildId,
Guid serverId,
string culture)
{
_ = provider;
var result = await leader.GetMembersAsync(guildId, serverId, culture, CancellationToken.None)
.ConfigureAwait(false);
if (result.ErrorMessage is { } error)
{
await FollowupAsync(error, ephemeral: true).ConfigureAwait(false);
return;
}
var select = new SelectMenuBuilder()
.WithCustomId(string.Create(CultureInfo.InvariantCulture, $"{LeaderPromotePrefix}{serverId}"))
.WithPlaceholder(localizer.Get("leader.pickmember", culture));
foreach (var member in result.Members.Take(SelectMenuBuilder.MaxOptionCount))
{
select.AddOption(member.Name, member.SteamId.ToString(CultureInfo.InvariantCulture),
isDefault: member.IsLeader);
}
var components = new ComponentBuilder().WithSelectMenu(select).Build();
await FollowupAsync(localizer.Get("leader.pickmember", culture), ephemeral: true, components: components)
.ConfigureAwait(false);
}
}