implement admin commands

This commit is contained in:
dusk 2025-10-04 01:57:48 +00:00
parent 5198f7d83b
commit a268f75d32
No known key found for this signature in database
15 changed files with 263 additions and 287 deletions

View file

@ -18,37 +18,6 @@ public static class ContextEntityArgumentsExt
return null;
}
public static async Task<User> MatchUser(this Context ctx)
{
var text = ctx.PeekArgument();
if (text.TryParseMention(out var id))
{
var user = await ctx.Cache.GetOrFetchUser(ctx.Rest, id);
if (user != null) ctx.PopArgument();
return user;
}
return null;
}
public static bool MatchUserRaw(this Context ctx, out ulong id)
{
id = 0;
var text = ctx.PeekArgument();
if (text.TryParseMention(out var mentionId))
id = mentionId;
return id != 0;
}
public static Task<PKSystem> PeekSystem(this Context ctx) => throw new NotImplementedException();
public static async Task<PKSystem> MatchSystem(this Context ctx)
{
throw new NotImplementedException();
}
public static async Task<PKSystem> ParseSystem(this Context ctx, string input)
{
// System references can take three forms:
@ -67,7 +36,7 @@ public static class ContextEntityArgumentsExt
return null;
}
public static async Task<PKMember> ParseMember(this Context ctx, string input, bool byId, SystemId? restrictToSystem = null)
public static async Task<PKMember?> ParseMember(this Context ctx, string input, bool byId)
{
// Member references can have one of three forms, depending on
// whether you're in a system or not:
@ -100,53 +69,22 @@ public static class ContextEntityArgumentsExt
// If we are supposed to restrict it to a system anyway we can just do that
PKMember memberByHid = null;
if (restrictToSystem != null)
{
memberByHid = await ctx.Repository.GetMemberByHid(hid, restrictToSystem);
if (memberByHid != null)
return memberByHid;
}
// otherwise we try the querier's system and if that doesn't work we do global
else
{
memberByHid = await ctx.Repository.GetMemberByHid(hid, ctx.System?.Id);
if (memberByHid != null)
return memberByHid;
memberByHid = await ctx.Repository.GetMemberByHid(hid, ctx.System?.Id);
if (memberByHid != null)
return memberByHid;
// ff ctx.System was null then this would be a duplicate of above and we don't want to run it again
if (ctx.System != null)
{
memberByHid = await ctx.Repository.GetMemberByHid(hid);
if (memberByHid != null)
return memberByHid;
}
// ff ctx.System was null then this would be a duplicate of above and we don't want to run it again
if (ctx.System != null)
{
memberByHid = await ctx.Repository.GetMemberByHid(hid);
if (memberByHid != null)
return memberByHid;
}
// We didn't find anything, so we return null.
return null;
}
public static async Task<PKMember> PeekMember(this Context ctx, SystemId? restrictToSystem = null)
{
throw new NotImplementedException();
}
/// <summary>
/// Attempts to pop a member descriptor from the stack, returning it if present. If a member could not be
/// resolved by the next word in the argument stack, does *not* touch the stack, and returns null.
/// </summary>
public static async Task<PKMember> MatchMember(this Context ctx, SystemId? restrictToSystem = null)
{
// First, peek a member
var member = await ctx.PeekMember(restrictToSystem);
// If the peek was successful, we've used up the next argument, so we pop that just to get rid of it.
if (member != null) ctx.PopArgument();
// Finally, we return the member value.
return member;
}
public static async Task<PKGroup> ParseGroup(this Context ctx, string input, bool byId, SystemId? restrictToSystem = null)
{
if (ctx.System != null && !byId)
@ -166,18 +104,6 @@ public static class ContextEntityArgumentsExt
return null;
}
public static async Task<PKGroup> PeekGroup(this Context ctx, SystemId? restrictToSystem = null)
{
throw new NotImplementedException();
}
public static async Task<PKGroup> MatchGroup(this Context ctx, SystemId? restrictToSystem = null)
{
var group = await ctx.PeekGroup(restrictToSystem);
if (group != null) ctx.PopArgument();
return group;
}
public static string CreateNotFoundError(this Context ctx, string entity, string input, bool byId = false)
{
var isIDOnlyQuery = ctx.System == null || byId;

View file

@ -1,4 +1,5 @@
using PluralKit.Core;
using Myriad.Types;
namespace PluralKit.Bot;
@ -12,6 +13,14 @@ public static class ContextParametersExt
);
}
public static async Task<int?> ParamResolveNumber(this Context ctx, string param_name)
{
return await ctx.Parameters.ResolveParameter(
ctx, param_name,
param => (param as Parameter.Number)?.value
);
}
public static async Task<PKMember?> ParamResolveMember(this Context ctx, string param_name)
{
return await ctx.Parameters.ResolveParameter(
@ -52,6 +61,14 @@ public static class ContextParametersExt
);
}
public static async Task<User?> ParamResolveUser(this Context ctx, string param_name)
{
return await ctx.Parameters.ResolveParameter(
ctx, param_name,
param => (param as Parameter.UserRef)?.user
);
}
public static async Task<MemberPrivacySubject?> ParamResolveMemberPrivacyTarget(this Context ctx, string param_name)
{
return await ctx.Parameters.ResolveParameter(

View file

@ -1,5 +1,6 @@
using Humanizer;
using Myriad.Types;
using Myriad.Extensions;
using PluralKit.Core;
using uniffi.commands;
@ -13,6 +14,7 @@ public abstract record Parameter()
public record GroupRef(PKGroup group): Parameter;
public record GroupRefs(List<PKGroup> groups): Parameter;
public record SystemRef(PKSystem system): Parameter;
public record UserRef(User user): Parameter;
public record MessageRef(Message.Reference message): Parameter;
public record ChannelRef(Channel channel): Parameter;
public record GuildRef(Guild guild): Parameter;
@ -22,6 +24,7 @@ public abstract record Parameter()
public record PrivacyLevel(Core.PrivacyLevel level): Parameter;
public record Toggle(bool value): Parameter;
public record Opaque(string value): Parameter;
public record Number(int value): Parameter;
public record Avatar(ParsedImage avatar): Parameter;
}
@ -96,6 +99,11 @@ public class Parameters
await ctx.ParseSystem(systemRef.system)
?? throw new PKError(ctx.CreateNotFoundError("System", systemRef.system))
);
case uniffi.commands.Parameter.UserRef(var userId):
return new Parameter.UserRef(
await ctx.Cache.GetOrFetchUser(ctx.Rest, userId)
?? throw new PKError(ctx.CreateNotFoundError("User", userId.ToString()))
);
// todo(dusk): ideally generate enums for these from rust code in the cs glue
case uniffi.commands.Parameter.MemberPrivacyTarget memberPrivacyTarget:
// this should never really fail...
@ -118,6 +126,8 @@ public class Parameters
return new Parameter.Toggle(toggle.toggle);
case uniffi.commands.Parameter.OpaqueString opaque:
return new Parameter.Opaque(opaque.raw);
case uniffi.commands.Parameter.OpaqueInt number:
return new Parameter.Number(number.raw);
case uniffi.commands.Parameter.Avatar avatar:
return new Parameter.Avatar(await ctx.GetUserPfp(avatar.avatar) ?? ctx.ParseImage(avatar.avatar));
case uniffi.commands.Parameter.MessageRef(var guildId, var channelId, var messageId):