-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathItemCommandModule.cs
More file actions
101 lines (90 loc) · 5.28 KB
/
Copy pathItemCommandModule.cs
File metadata and controls
101 lines (90 loc) · 5.28 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
using Discord;
using Discord.Interactions;
using Microsoft.Extensions.DependencyInjection;
using RustPlusBot.Features.Commands.Formatting;
using RustPlusBot.Features.ItemData;
using RustPlusBot.Features.ItemData.Data;
using RustPlusBot.Features.ItemData.Lookup;
using RustPlusBot.Features.ItemData.Naming;
using RustPlusBot.Localization;
using RustPlusBot.Persistence.Workspace;
namespace RustPlusBot.Features.Commands.Modules;
/// <summary>The /item, /recycle, /craft, /research, /decay, and /upkeep slash commands.</summary>
/// <param name="scopeFactory">Creates a short-lived DI scope per interaction.</param>
public sealed class ItemCommandModule(IServiceScopeFactory scopeFactory)
: InteractionModuleBase<SocketInteractionContext>
{
/// <summary>Looks up an item's name, id, stack size, and despawn time.</summary>
/// <param name="item">The item name or id.</param>
[SlashCommand("item", "Look up an item")]
public Task ItemAsync([Summary("item", "Item name or id")] string item) =>
RespondForAsync(item, db => db.Sources.NamesAsOf, (_, _, rec, loc, culture) =>
loc.Get("command.item.ok", culture, ItemLine.Format(rec)));
/// <summary>Shows recycler output for an item.</summary>
/// <param name="item">The item name or id.</param>
[SlashCommand("recycle", "Show recycler output for an item")]
public Task RecycleAsync([Summary("item", "Item name or id")] string item) =>
RespondForAsync(item, db => db.Sources.RecycleAsOf, (_, names, rec, loc, culture) => rec.Recycle is not null
? loc.Get("command.recycle.ok", culture, RecycleLine.Format(rec, names))
: loc.Get("command.recycle.none", culture, rec.Name));
/// <summary>Shows an item's craft recipe.</summary>
/// <param name="item">The item name or id.</param>
[SlashCommand("craft", "Show an item's craft recipe")]
public Task CraftAsync([Summary("item", "Item name or id")] string item) =>
RespondForAsync(item, db => db.Sources.CraftAsOf, (_, names, rec, loc, culture) => rec.Craft is not null
? loc.Get("command.craft.ok", culture, CraftLine.Format(rec, names))
: loc.Get("command.craft.none", culture, rec.Name));
/// <summary>Shows an item's research scrap cost.</summary>
/// <param name="item">The item name or id.</param>
[SlashCommand("research", "Show an item's research scrap cost")]
public Task ResearchAsync([Summary("item", "Item name or id")] string item) =>
RespondForAsync(item, db => db.Sources.ResearchAsOf, (_, _, rec, loc, culture) => rec.Research is not null
? loc.Get("command.research.ok", culture, ResearchLine.Format(rec))
: loc.Get("command.research.none", culture, rec.Name));
/// <summary>Shows an item's decay time.</summary>
/// <param name="item">The item name or id.</param>
[SlashCommand("decay", "Show an item's decay time")]
public Task DecayAsync([Summary("item", "Item name or id")] string item) =>
RespondForAsync(item, db => db.Sources.DecayAsOf, (_, _, rec, loc, culture) => rec.Decay is not null
? loc.Get("command.decay.ok", culture, DecayLine.Format(rec))
: loc.Get("command.decay.none", culture, rec.Name));
/// <summary>Shows a building block's upkeep cost.</summary>
/// <param name="item">The item name or id.</param>
[SlashCommand("upkeep", "Show a building block's upkeep cost")]
public Task UpkeepAsync([Summary("item", "Item name or id")] string item) =>
RespondForAsync(item, db => db.Sources.UpkeepAsOf, (_, names, rec, loc, culture) => rec.Upkeep is not null
? loc.Get("command.upkeep.ok", culture, UpkeepLine.Format(rec, names))
: loc.Get("command.upkeep.none", culture, rec.Name));
private async Task RespondForAsync(
string query,
Func<IItemDatabase, DateOnly> dateSelector,
Func<IItemDatabase, IItemNameResolver, ItemRecord, ILocalizer, string, string> onFound)
{
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 db = scope.ServiceProvider.GetRequiredService<IItemDatabase>();
var names = scope.ServiceProvider.GetRequiredService<IItemNameResolver>();
var loc = scope.ServiceProvider.GetRequiredService<ILocalizer>();
var workspace = scope.ServiceProvider.GetRequiredService<IWorkspaceStore>();
var culture = await workspace.GetCultureAsync(Context.Guild.Id).ConfigureAwait(false);
var text = db.Resolve(query) switch
{
ItemMatch.Found f => onFound(db, names, f.Item, loc, culture),
ItemMatch.Ambiguous a => loc.Get("command.item.ambiguous", culture,
string.Join(", ", a.Candidates.Select(c => c.Name))),
_ => loc.Get("command.item.notfound", culture, query),
};
var embed = new EmbedBuilder()
.WithDescription(text)
.WithFooter($"data as of {dateSelector(db):yyyy-MM-dd}")
.Build();
await RespondAsync(ephemeral: true, embed: embed).ConfigureAwait(false);
}
}
}