Skip to content

Commit cdd50c4

Browse files
HandyS11claude
andcommitted
feat(commands): add /decay + /upkeep slash commands + per-section footer (6b)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ac469dd commit cdd50c4

5 files changed

Lines changed: 38 additions & 7 deletions

File tree

src/RustPlusBot.Features.Commands/Help/CommandHelpCatalog.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,7 @@ internal static class CommandHelpCatalog
4343
new("recycle", CommandGroup.ItemDb, "help.slash.recycle"),
4444
new("craft", CommandGroup.ItemDb, "help.slash.craft"),
4545
new("research", CommandGroup.ItemDb, "help.slash.research"),
46+
new("decay", CommandGroup.ItemDb, "help.slash.decay"),
47+
new("upkeep", CommandGroup.ItemDb, "help.slash.upkeep"),
4648
];
4749
}

src/RustPlusBot.Features.Commands/Modules/ItemCommandModule.cs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace RustPlusBot.Features.Commands.Modules;
1313

14-
/// <summary>The /item, /recycle, /craft, and /research slash commands.</summary>
14+
/// <summary>The /item, /recycle, /craft, /research, /decay, and /upkeep slash commands.</summary>
1515
/// <param name="scopeFactory">Creates a short-lived DI scope per interaction.</param>
1616
public sealed class ItemCommandModule(IServiceScopeFactory scopeFactory)
1717
: InteractionModuleBase<SocketInteractionContext>
@@ -20,35 +20,52 @@ public sealed class ItemCommandModule(IServiceScopeFactory scopeFactory)
2020
/// <param name="item">The item name or id.</param>
2121
[SlashCommand("item", "Look up an item")]
2222
public Task ItemAsync([Summary("item", "Item name or id")] string item) =>
23-
RespondForAsync(item, (_, _, rec, loc, culture) =>
23+
RespondForAsync(item, db => db.Sources.NamesAsOf, (_, _, rec, loc, culture) =>
2424
loc.Get("command.item.ok", culture, ItemLine.Format(rec)));
2525

2626
/// <summary>Shows recycler output for an item.</summary>
2727
/// <param name="item">The item name or id.</param>
2828
[SlashCommand("recycle", "Show recycler output for an item")]
2929
public Task RecycleAsync([Summary("item", "Item name or id")] string item) =>
30-
RespondForAsync(item, (_, names, rec, loc, culture) => rec.Recycle is not null
30+
RespondForAsync(item, db => db.Sources.RecycleAsOf, (_, names, rec, loc, culture) => rec.Recycle is not null
3131
? loc.Get("command.recycle.ok", culture, RecycleLine.Format(rec, names))
3232
: loc.Get("command.recycle.none", culture, rec.Name));
3333

3434
/// <summary>Shows an item's craft recipe.</summary>
3535
/// <param name="item">The item name or id.</param>
3636
[SlashCommand("craft", "Show an item's craft recipe")]
3737
public Task CraftAsync([Summary("item", "Item name or id")] string item) =>
38-
RespondForAsync(item, (_, names, rec, loc, culture) => rec.Craft is not null
38+
RespondForAsync(item, db => db.Sources.CraftAsOf, (_, names, rec, loc, culture) => rec.Craft is not null
3939
? loc.Get("command.craft.ok", culture, CraftLine.Format(rec, names))
4040
: loc.Get("command.craft.none", culture, rec.Name));
4141

4242
/// <summary>Shows an item's research scrap cost.</summary>
4343
/// <param name="item">The item name or id.</param>
4444
[SlashCommand("research", "Show an item's research scrap cost")]
4545
public Task ResearchAsync([Summary("item", "Item name or id")] string item) =>
46-
RespondForAsync(item, (_, _, rec, loc, culture) => rec.Research is not null
46+
RespondForAsync(item, db => db.Sources.ResearchAsOf, (_, _, rec, loc, culture) => rec.Research is not null
4747
? loc.Get("command.research.ok", culture, ResearchLine.Format(rec))
4848
: loc.Get("command.research.none", culture, rec.Name));
4949

50+
/// <summary>Shows an item's decay time.</summary>
51+
/// <param name="item">The item name or id.</param>
52+
[SlashCommand("decay", "Show an item's decay time")]
53+
public Task DecayAsync([Summary("item", "Item name or id")] string item) =>
54+
RespondForAsync(item, db => db.Sources.DecayAsOf, (_, _, rec, loc, culture) => rec.Decay is not null
55+
? loc.Get("command.decay.ok", culture, DecayLine.Format(rec))
56+
: loc.Get("command.decay.none", culture, rec.Name));
57+
58+
/// <summary>Shows a building block's upkeep cost.</summary>
59+
/// <param name="item">The item name or id.</param>
60+
[SlashCommand("upkeep", "Show a building block's upkeep cost")]
61+
public Task UpkeepAsync([Summary("item", "Item name or id")] string item) =>
62+
RespondForAsync(item, db => db.Sources.UpkeepAsOf, (_, names, rec, loc, culture) => rec.Upkeep is not null
63+
? loc.Get("command.upkeep.ok", culture, UpkeepLine.Format(rec, names))
64+
: loc.Get("command.upkeep.none", culture, rec.Name));
65+
5066
private async Task RespondForAsync(
5167
string query,
68+
Func<IItemDatabase, DateOnly> dateSelector,
5269
Func<IItemDatabase, IItemNameResolver, ItemRecord, ILocalizer, string, string> onFound)
5370
{
5471
if (Context.Guild is null)
@@ -76,7 +93,7 @@ private async Task RespondForAsync(
7693

7794
var embed = new EmbedBuilder()
7895
.WithDescription(text)
79-
.WithFooter($"data as of {db.Sources.NamesAsOf:yyyy-MM-dd}")
96+
.WithFooter($"data as of {dateSelector(db):yyyy-MM-dd}")
8097
.Build();
8198
await RespondAsync(ephemeral: true, embed: embed).ConfigureAwait(false);
8299
}

src/RustPlusBot.Localization/Strings.fr.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@
414414
<data name="help.research" xml:space="preserve">
415415
<value>Afficher le coût de recherche (ferraille) d'un objet</value>
416416
</data>
417+
<data name="help.slash.decay" xml:space="preserve">
418+
<value>Affiche le temps de dégradation d'un objet</value>
419+
</data>
417420
<data name="help.slash.help" xml:space="preserve">
418421
<value>Afficher ce message d'aide.</value>
419422
</data>
@@ -432,6 +435,9 @@
432435
<data name="help.slash.research" xml:space="preserve">
433436
<value>Afficher le coût de recherche (ferraille) d'un objet.</value>
434437
</data>
438+
<data name="help.slash.upkeep" xml:space="preserve">
439+
<value>Affiche le coût d'entretien d'un bloc de construction</value>
440+
</data>
435441
<data name="help.slash.uptime" xml:space="preserve">
436442
<value>Afficher la disponibilité du bot.</value>
437443
</data>

src/RustPlusBot.Localization/Strings.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@
414414
<data name="help.research" xml:space="preserve">
415415
<value>Show an item's research scrap cost</value>
416416
</data>
417+
<data name="help.slash.decay" xml:space="preserve">
418+
<value>Show an item's decay time</value>
419+
</data>
417420
<data name="help.slash.help" xml:space="preserve">
418421
<value>Show this help message.</value>
419422
</data>
@@ -432,6 +435,9 @@
432435
<data name="help.slash.research" xml:space="preserve">
433436
<value>Show an item's research scrap cost.</value>
434437
</data>
438+
<data name="help.slash.upkeep" xml:space="preserve">
439+
<value>Show a building block's upkeep cost</value>
440+
</data>
435441
<data name="help.slash.uptime" xml:space="preserve">
436442
<value>Show the bot's uptime.</value>
437443
</data>

tests/RustPlusBot.Localization.Tests/StringsResourceParityTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ public void English_covers_every_french_key()
4242
[Fact]
4343
public void Catalog_has_expected_key_count()
4444
{
45-
Assert.Equal(236, EnglishKeys().Count);
45+
Assert.Equal(238, EnglishKeys().Count);
4646
}
4747
}

0 commit comments

Comments
 (0)