feat(commands): add cs codegen to statically use params and flags in bot code, remove Any

This commit is contained in:
dusk 2025-01-21 12:36:54 +09:00
parent 0c012e98b5
commit 07e8a4851a
No known key found for this signature in database
20 changed files with 297 additions and 417 deletions

View file

@ -4,24 +4,26 @@ namespace PluralKit.Bot;
public partial class CommandTree
{
public Task ExecuteCommand(Context ctx)
public Task ExecuteCommand(Context ctx, Commands command)
{
return ctx.Parameters.Callback() switch
return command switch
{
"help" => ctx.Execute<Help>(Help, m => m.HelpRoot(ctx)),
"help_commands" => ctx.Reply(
Commands.Help => ctx.Execute<Help>(Help, m => m.HelpRoot(ctx)),
Commands.HelpCommands => ctx.Reply(
"For the list of commands, see the website: <https://pluralkit.me/commands>"),
"help_proxy" => ctx.Reply(
Commands.HelpProxy => ctx.Reply(
"The proxy help page has been moved! See the website: https://pluralkit.me/guide#proxying"),
"member_show" => ctx.Execute<Member>(MemberInfo, m => m.ViewMember(ctx)),
"member_new" => ctx.Execute<Member>(MemberNew, m => m.NewMember(ctx)),
"member_soulscream" => ctx.Execute<Member>(MemberInfo, m => m.Soulscream(ctx)),
"cfg_ap_account_show" => ctx.Execute<Config>(null, m => m.ViewAutoproxyAccount(ctx)),
"cfg_ap_account_update" => ctx.Execute<Config>(null, m => m.EditAutoproxyAccount(ctx)),
"cfg_ap_timeout_show" => ctx.Execute<Config>(null, m => m.ViewAutoproxyTimeout(ctx)),
"cfg_ap_timeout_update" => ctx.Execute<Config>(null, m => m.EditAutoproxyTimeout(ctx)),
"fun_thunder" => ctx.Execute<Fun>(null, m => m.Thunder(ctx)),
"fun_meow" => ctx.Execute<Fun>(null, m => m.Meow(ctx)),
Commands.MemberShow(MemberShowParams param, _) => ctx.Execute<Member>(MemberInfo, m => m.ViewMember(ctx, param.target)),
Commands.MemberNew(MemberNewParams param, _) => ctx.Execute<Member>(MemberNew, m => m.NewMember(ctx, param.name)),
Commands.MemberSoulscream(MemberSoulscreamParams param, _) => ctx.Execute<Member>(MemberInfo, m => m.Soulscream(ctx, param.target)),
Commands.CfgApAccountShow => ctx.Execute<Config>(null, m => m.ViewAutoproxyAccount(ctx)),
Commands.CfgApAccountUpdate(CfgApAccountUpdateParams param, _) => ctx.Execute<Config>(null, m => m.EditAutoproxyAccount(ctx, param.toggle)),
Commands.CfgApTimeoutShow => ctx.Execute<Config>(null, m => m.ViewAutoproxyTimeout(ctx)),
Commands.CfgApTimeoutOff => ctx.Execute<Config>(null, m => m.DisableAutoproxyTimeout(ctx)),
Commands.CfgApTimeoutReset => ctx.Execute<Config>(null, m => m.ResetAutoproxyTimeout(ctx)),
Commands.CfgApTimeoutUpdate(CfgApTimeoutUpdateParams param, _) => ctx.Execute<Config>(null, m => m.EditAutoproxyTimeout(ctx, param.timeout)),
Commands.FunThunder => ctx.Execute<Fun>(null, m => m.Thunder(ctx)),
Commands.FunMeow => ctx.Execute<Fun>(null, m => m.Meow(ctx)),
_ =>
// this should only ever occur when deving if commands are not implemented...
ctx.Reply(

View file

@ -197,10 +197,9 @@ public class Config
await ctx.Reply($"Autoproxy is currently **{EnabledDisabled(allowAutoproxy)}** for account <@{ctx.Author.Id}>.");
}
public async Task EditAutoproxyAccount(Context ctx)
public async Task EditAutoproxyAccount(Context ctx, bool allow)
{
var allowAutoproxy = await ctx.Repository.GetAutoproxyEnabled(ctx.Author.Id);
var allow = await ctx.ParamResolveToggle("toggle") ?? throw new PKSyntaxError("You need to specify whether to enable or disable autoproxy for this account.");
var statusString = EnabledDisabled(allow);
if (allowAutoproxy == allow)
@ -227,41 +226,44 @@ public class Config
await ctx.Reply($"The current latch timeout duration for your system is {timeout.Value.ToTimeSpan().Humanize(4)}.");
}
public async Task EditAutoproxyTimeout(Context ctx)
public async Task DisableAutoproxyTimeout(Context ctx)
{
var _newTimeout = await ctx.ParamResolveOpaque("timeout");
var _reset = await ctx.ParamResolveToggle("reset");
var _toggle = await ctx.ParamResolveToggle("toggle");
await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { LatchTimeout = (int)Duration.Zero.TotalSeconds });
Duration? newTimeout;
await ctx.Reply($"{Emojis.Success} Latch timeout disabled. Latch mode autoproxy will never time out.");
}
public async Task ResetAutoproxyTimeout(Context ctx)
{
await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { LatchTimeout = null });
await ctx.Reply($"{Emojis.Success} Latch timeout reset to default ({ProxyMatcher.DefaultLatchExpiryTime.ToTimeSpan().Humanize(4)}).");
}
public async Task EditAutoproxyTimeout(Context ctx, string timeout)
{
Duration newTimeout;
Duration overflow = Duration.Zero;
if (_toggle == false) newTimeout = Duration.Zero;
else if (_reset == true) newTimeout = null;
else
// todo: we should parse date in the command parser
var timeoutStr = timeout;
var timeoutPeriod = DateUtils.ParsePeriod(timeoutStr)
?? throw new PKError($"Could not parse '{timeoutStr}' as a valid duration. Try using a syntax such as \"3h5m\" (i.e. 3 hours and 5 minutes).");
if (timeoutPeriod.TotalHours > 100000)
{
// todo: we should parse date in the command parser
var timeoutStr = _newTimeout;
var timeoutPeriod = DateUtils.ParsePeriod(timeoutStr);
if (timeoutPeriod == null) throw new PKError($"Could not parse '{timeoutStr}' as a valid duration. Try using a syntax such as \"3h5m\" (i.e. 3 hours and 5 minutes).");
if (timeoutPeriod.Value.TotalHours > 100000)
{
// sanity check to prevent seconds overflow if someone types in 999999999
overflow = timeoutPeriod.Value;
newTimeout = Duration.Zero;
}
else newTimeout = timeoutPeriod;
// sanity check to prevent seconds overflow if someone types in 999999999
overflow = timeoutPeriod;
newTimeout = Duration.Zero;
}
else newTimeout = timeoutPeriod;
await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { LatchTimeout = (int?)newTimeout?.TotalSeconds });
await ctx.Repository.UpdateSystemConfig(ctx.System.Id, new() { LatchTimeout = (int?)newTimeout.TotalSeconds });
if (newTimeout == null)
await ctx.Reply($"{Emojis.Success} Latch timeout reset to default ({ProxyMatcher.DefaultLatchExpiryTime.ToTimeSpan().Humanize(4)}).");
else if (newTimeout == Duration.Zero && overflow != Duration.Zero)
if (newTimeout == Duration.Zero && overflow != Duration.Zero)
await ctx.Reply($"{Emojis.Success} Latch timeout disabled. Latch mode autoproxy will never time out. ({overflow.ToTimeSpan().Humanize(4)} is too long)");
else if (newTimeout == Duration.Zero)
await ctx.Reply($"{Emojis.Success} Latch timeout disabled. Latch mode autoproxy will never time out.");
else
await ctx.Reply($"{Emojis.Success} Latch timeout set to {newTimeout.Value!.ToTimeSpan().Humanize(4)}.");
await ctx.Reply($"{Emojis.Success} Latch timeout set to {newTimeout.ToTimeSpan().Humanize(4)}.");
}
public async Task SystemTimezone(Context ctx)

View file

@ -28,10 +28,8 @@ public class Member
_avatarHosting = avatarHosting;
}
public async Task NewMember(Context ctx)
public async Task NewMember(Context ctx, string? memberName)
{
var memberName = await ctx.ParamResolveOpaque("name");
if (ctx.System == null) throw Errors.NoSystemError(ctx.DefaultPrefix);
memberName = memberName ?? throw new PKSyntaxError("You must pass a member name.");
@ -122,19 +120,17 @@ public class Member
await ctx.Reply(replyStr);
}
public async Task ViewMember(Context ctx)
public async Task ViewMember(Context ctx, PKMember target)
{
var target = await ctx.ParamResolveMember("target");
var system = await ctx.Repository.GetSystem(target.System);
await ctx.Reply(
embed: await _embeds.CreateMemberEmbed(system, target, ctx.Guild, ctx.Config, ctx.LookupContextFor(system.Id), ctx.Zone));
}
public async Task Soulscream(Context ctx)
public async Task Soulscream(Context ctx, PKMember target)
{
// this is for a meme, please don't take this code seriously. :)
var target = await ctx.ParamResolveMember("target");
var name = target.NameFor(ctx.LookupContextFor(target.System));
var encoded = HttpUtility.UrlEncode(name);

View file

@ -159,7 +159,19 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
}
var ctx = new Context(_services, shardId, guild, channel, evt, cmdStart, system, config, guildConfig, _config.Prefixes ?? BotConfig.DefaultPrefixes, parameters);
await _tree.ExecuteCommand(ctx);
Commands command;
try
{
command = await Commands.FromContext(ctx);
}
catch (PKError e)
{
await ctx.Reply($"{Emojis.Error} {e.Message}");
throw;
}
await _tree.ExecuteCommand(ctx, command);
}
catch (PKError)
{