-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathItemCommandModule.cs
More file actions
140 lines (124 loc) · 7.16 KB
/
Copy pathItemCommandModule.cs
File metadata and controls
140 lines (124 loc) · 7.16 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
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, /upkeep, and /durability 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));
/// <summary>Lists the explosives needed to destroy a target.</summary>
/// <param name="target">The item, building block, or vehicle name.</param>
[SlashCommand("durability", "Show the explosives needed to destroy a target")]
public Task DurabilityAsync([Summary("target", "Item, wall/door, or vehicle name")] string target) =>
RespondForRaidAsync(target);
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);
}
}
private async Task RespondForRaidAsync(string query)
{
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.ResolveRaidTarget(query) switch
{
RaidMatch.Found f => loc.Get("command.durability.ok", culture, DurabilityLine.Format(f.Target, names)),
RaidMatch.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 {db.Sources.DurabilityAsOf:yyyy-MM-dd}")
.Build();
await RespondAsync(ephemeral: true, embed: embed).ConfigureAwait(false);
}
}
}