implement random commands, dont keep the subcommands only the flags

This commit is contained in:
dusk 2025-09-26 23:56:49 +00:00
parent c00ff2f371
commit c92c3f84f0
No known key found for this signature in database
13 changed files with 82 additions and 24 deletions

View file

@ -162,6 +162,15 @@ public partial class CommandTree
Commands.SystemFronter(var param, var flags) => ctx.Execute<SystemFront>(SystemFronter, m => m.Fronter(ctx, param.target)), Commands.SystemFronter(var param, var flags) => ctx.Execute<SystemFront>(SystemFronter, m => m.Fronter(ctx, param.target)),
Commands.SystemFronterHistory(var param, var flags) => ctx.Execute<SystemFront>(SystemFrontHistory, m => m.FrontHistory(ctx, param.target, flags.clear)), Commands.SystemFronterHistory(var param, var flags) => ctx.Execute<SystemFront>(SystemFrontHistory, m => m.FrontHistory(ctx, param.target, flags.clear)),
Commands.SystemFronterPercent(var param, var flags) => ctx.Execute<SystemFront>(SystemFrontPercent, m => m.FrontPercent(ctx, param.target, flags.duration, flags.fronters_only, flags.flat)), Commands.SystemFronterPercent(var param, var flags) => ctx.Execute<SystemFront>(SystemFrontPercent, m => m.FrontPercent(ctx, param.target, flags.duration, flags.fronters_only, flags.flat)),
Commands.RandomSelf(_, var flags) =>
flags.group
? ctx.Execute<Random>(GroupRandom, m => m.Group(ctx, ctx.System, flags.all, flags.show_embed))
: ctx.Execute<Random>(MemberRandom, m => m.Member(ctx, ctx.System, flags.all, flags.show_embed)),
Commands.SystemRandom(var param, var flags) =>
flags.group
? ctx.Execute<Random>(GroupRandom, m => m.Group(ctx, param.target, flags.all, flags.show_embed))
: ctx.Execute<Random>(MemberRandom, m => m.Member(ctx, param.target, flags.all, flags.show_embed)),
Commands.GroupRandomMember(var param, var flags) => ctx.Execute<Random>(GroupMemberRandom, m => m.GroupMember(ctx, param.target, flags.all, flags.show_embed)),
_ => _ =>
// this should only ever occur when deving if commands are not implemented... // this should only ever occur when deving if commands are not implemented...
ctx.Reply( ctx.Reply(
@ -252,11 +261,6 @@ public partial class CommandTree
return HandleDebugCommand(ctx); return HandleDebugCommand(ctx);
if (ctx.Match("admin")) if (ctx.Match("admin"))
return HandleAdminCommand(ctx); return HandleAdminCommand(ctx);
if (ctx.Match("random", "rand", "r"))
if (ctx.Match("group", "g") || ctx.MatchFlag("group", "g"))
return ctx.Execute<Random>(GroupRandom, r => r.Group(ctx, ctx.System));
else
return ctx.Execute<Random>(MemberRandom, m => m.Member(ctx, ctx.System));
if (ctx.Match("dashboard", "dash")) if (ctx.Match("dashboard", "dash"))
return ctx.Execute<Help>(Dashboard, m => m.Dashboard(ctx)); return ctx.Execute<Help>(Dashboard, m => m.Dashboard(ctx));
} }
@ -416,11 +420,6 @@ public partial class CommandTree
await ctx.CheckSystem(target).Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, target)); await ctx.CheckSystem(target).Execute<Groups>(GroupList, g => g.ListSystemGroups(ctx, target));
else if (ctx.Match("id")) else if (ctx.Match("id"))
await ctx.CheckSystem(target).Execute<System>(SystemId, m => m.DisplayId(ctx, target)); await ctx.CheckSystem(target).Execute<System>(SystemId, m => m.DisplayId(ctx, target));
else if (ctx.Match("random", "rand", "r"))
if (ctx.Match("group", "g") || ctx.MatchFlag("group", "g"))
await ctx.CheckSystem(target).Execute<Random>(GroupRandom, r => r.Group(ctx, target));
else
await ctx.CheckSystem(target).Execute<Random>(MemberRandom, m => m.Member(ctx, target));
} }
private async Task HandleMemberCommand(Context ctx) private async Task HandleMemberCommand(Context ctx)

View file

@ -147,13 +147,9 @@ public static class ContextEntityArgumentsExt
return member; return member;
} }
public static async Task<PKGroup> PeekGroup(this Context ctx, SystemId? restrictToSystem = null) public static async Task<PKGroup> ParseGroup(this Context ctx, string input, bool byId, SystemId? restrictToSystem = null)
{ {
var input = ctx.PeekArgument(); if (ctx.System != null && !byId)
// see PeekMember for an explanation of the logic used here
if (ctx.System != null && !ctx.MatchFlag("id", "by-id"))
{ {
if (await ctx.Repository.GetGroupByName(ctx.System.Id, input) is { } byName) if (await ctx.Repository.GetGroupByName(ctx.System.Id, input) is { } byName)
return byName; return byName;
@ -170,6 +166,11 @@ public static class ContextEntityArgumentsExt
return null; 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) public static async Task<PKGroup> MatchGroup(this Context ctx, SystemId? restrictToSystem = null)
{ {
var group = await ctx.PeekGroup(restrictToSystem); var group = await ctx.PeekGroup(restrictToSystem);

View file

@ -28,6 +28,14 @@ public static class ContextParametersExt
); );
} }
public static async Task<PKGroup?> ParamResolveGroup(this Context ctx, string param_name)
{
return await ctx.Parameters.ResolveParameter(
ctx, param_name,
param => (param as Parameter.GroupRef)?.group
);
}
public static async Task<PKSystem?> ParamResolveSystem(this Context ctx, string param_name) public static async Task<PKSystem?> ParamResolveSystem(this Context ctx, string param_name)
{ {
return await ctx.Parameters.ResolveParameter( return await ctx.Parameters.ResolveParameter(

View file

@ -10,6 +10,7 @@ public abstract record Parameter()
{ {
public record MemberRef(PKMember member): Parameter; public record MemberRef(PKMember member): Parameter;
public record MemberRefs(List<PKMember> members): Parameter; public record MemberRefs(List<PKMember> members): Parameter;
public record GroupRef(PKGroup group): Parameter;
public record SystemRef(PKSystem system): Parameter; public record SystemRef(PKSystem system): Parameter;
public record GuildRef(Guild guild): Parameter; public record GuildRef(Guild guild): Parameter;
public record MemberPrivacyTarget(MemberPrivacySubject target): Parameter; public record MemberPrivacyTarget(MemberPrivacySubject target): Parameter;
@ -73,6 +74,11 @@ public class Parameters
?? throw new PKError(ctx.CreateNotFoundError("Member", m, byId)) ?? throw new PKError(ctx.CreateNotFoundError("Member", m, byId))
).ToListAsync() ).ToListAsync()
); );
case uniffi.commands.Parameter.GroupRef groupRef:
return new Parameter.GroupRef(
await ctx.ParseGroup(groupRef.group, byId)
?? throw new PKError(ctx.CreateNotFoundError("Group", groupRef.group))
);
case uniffi.commands.Parameter.SystemRef systemRef: case uniffi.commands.Parameter.SystemRef systemRef:
// todo: do we need byId here? // todo: do we need byId here?
return new Parameter.SystemRef( return new Parameter.SystemRef(

View file

@ -15,7 +15,7 @@ public class Random
// todo: get postgresql to return one random member/group instead of querying all members/groups // todo: get postgresql to return one random member/group instead of querying all members/groups
public async Task Member(Context ctx, PKSystem target, bool showEmbed = false) public async Task Member(Context ctx, PKSystem target, bool all, bool showEmbed = false)
{ {
if (target == null) if (target == null)
throw Errors.NoSystemError(ctx.DefaultPrefix); throw Errors.NoSystemError(ctx.DefaultPrefix);
@ -24,7 +24,7 @@ public class Random
var members = await ctx.Repository.GetSystemMembers(target.Id).ToListAsync(); var members = await ctx.Repository.GetSystemMembers(target.Id).ToListAsync();
if (!ctx.MatchFlag("all", "a")) if (!all)
members = members.Where(m => m.MemberVisibility == PrivacyLevel.Public).ToList(); members = members.Where(m => m.MemberVisibility == PrivacyLevel.Public).ToList();
else else
ctx.CheckOwnSystem(target); ctx.CheckOwnSystem(target);
@ -49,7 +49,7 @@ public class Random
components: await _embeds.CreateMemberMessageComponents(target, members[randInt], ctx.Guild, ctx.Config, ctx.LookupContextFor(target.Id), ctx.Zone)); components: await _embeds.CreateMemberMessageComponents(target, members[randInt], ctx.Guild, ctx.Config, ctx.LookupContextFor(target.Id), ctx.Zone));
} }
public async Task Group(Context ctx, PKSystem target, bool showEmbed = false) public async Task Group(Context ctx, PKSystem target, bool all, bool showEmbed = false)
{ {
if (target == null) if (target == null)
throw Errors.NoSystemError(ctx.DefaultPrefix); throw Errors.NoSystemError(ctx.DefaultPrefix);
@ -57,7 +57,7 @@ public class Random
ctx.CheckSystemPrivacy(target.Id, target.GroupListPrivacy); ctx.CheckSystemPrivacy(target.Id, target.GroupListPrivacy);
var groups = await ctx.Repository.GetSystemGroups(target.Id).ToListAsync(); var groups = await ctx.Repository.GetSystemGroups(target.Id).ToListAsync();
if (!ctx.MatchFlag("all", "a")) if (!all)
groups = groups.Where(g => g.Visibility == PrivacyLevel.Public).ToList(); groups = groups.Where(g => g.Visibility == PrivacyLevel.Public).ToList();
else else
ctx.CheckOwnSystem(target); ctx.CheckOwnSystem(target);
@ -82,7 +82,7 @@ public class Random
components: await _embeds.CreateGroupMessageComponents(ctx, target, groups.ToArray()[randInt])); components: await _embeds.CreateGroupMessageComponents(ctx, target, groups.ToArray()[randInt]));
} }
public async Task GroupMember(Context ctx, PKGroup group, bool showEmbed = false) public async Task GroupMember(Context ctx, PKGroup group, bool all, bool showEmbed = false)
{ {
ctx.CheckSystemPrivacy(group.System, group.ListPrivacy); ctx.CheckSystemPrivacy(group.System, group.ListPrivacy);
@ -96,7 +96,7 @@ public class Random
"This group has no members!" "This group has no members!"
+ (ctx.System?.Id == group.System ? " Please add at least one member to this group before using this command." : "")); + (ctx.System?.Id == group.System ? " Please add at least one member to this group before using this command." : ""));
if (!ctx.MatchFlag("all", "a")) if (!all)
members = members.Where(g => g.MemberVisibility == PrivacyLevel.Public); members = members.Where(g => g.MemberVisibility == PrivacyLevel.Public);
else else
ctx.CheckOwnGroup(group); ctx.CheckOwnGroup(group);

View file

@ -1 +1,11 @@
use command_parser::token::TokensIterator;
use super::*;
pub fn group() -> (&'static str, [&'static str; 1]) {
("group", ["g"])
}
pub fn targeted() -> TokensIterator {
tokens!(group(), GroupRef)
}

View file

@ -27,6 +27,7 @@ pub fn all() -> impl Iterator<Item = Command> {
.chain(config::cmds()) .chain(config::cmds())
.chain(fun::cmds()) .chain(fun::cmds())
.chain(switch::cmds()) .chain(switch::cmds())
.chain(random::cmds())
.map(|cmd| { .map(|cmd| {
cmd.flag(("plaintext", ["pt"])) cmd.flag(("plaintext", ["pt"]))
.flag(("raw", ["r"])) .flag(("raw", ["r"]))

View file

@ -1 +1,14 @@
use super::*;
pub fn cmds() -> impl Iterator<Item = Command> {
let random = ("random", ["rand"]);
let group = group::group();
[
command!(random => "random_self").flag(group),
command!(system::targeted(), random => "system_random").flag(group),
command!(group::targeted(), random => "group_random_member"),
]
.into_iter()
.map(|cmd| cmd.flag(("all", ["a"])))
}

View file

@ -1,12 +1,22 @@
use command_parser::token::TokensIterator;
use super::*; use super::*;
pub fn cmds() -> impl Iterator<Item = Command> { pub fn cmds() -> impl Iterator<Item = Command> {
edit() edit()
} }
pub fn system() -> (&'static str, [&'static str; 1]) {
("system", ["s"])
}
pub fn targeted() -> TokensIterator {
tokens!(system(), SystemRef)
}
pub fn edit() -> impl Iterator<Item = Command> { pub fn edit() -> impl Iterator<Item = Command> {
let system = ("system", ["s"]); let system = system();
let system_target = tokens!(system, SystemRef); let system_target = targeted();
let system_new = tokens!(system, ("new", ["n"])); let system_new = tokens!(system, ("new", ["n"]));
let system_new_cmd = [ let system_new_cmd = [

View file

@ -12,6 +12,7 @@ pub enum ParameterValue {
OpaqueString(String), OpaqueString(String),
MemberRef(String), MemberRef(String),
MemberRefs(Vec<String>), MemberRefs(Vec<String>),
GroupRef(String),
SystemRef(String), SystemRef(String),
GuildRef(String), GuildRef(String),
MemberPrivacyTarget(String), MemberPrivacyTarget(String),
@ -48,6 +49,7 @@ impl Display for Parameter {
} }
ParameterKind::MemberRef => write!(f, "<target member>"), ParameterKind::MemberRef => write!(f, "<target member>"),
ParameterKind::MemberRefs => write!(f, "<member 1> <member 2> <member 3>..."), ParameterKind::MemberRefs => write!(f, "<member 1> <member 2> <member 3>..."),
ParameterKind::GroupRef => write!(f, "<target group>"),
ParameterKind::SystemRef => write!(f, "<target system>"), ParameterKind::SystemRef => write!(f, "<target system>"),
ParameterKind::GuildRef => write!(f, "<target guild>"), ParameterKind::GuildRef => write!(f, "<target guild>"),
ParameterKind::MemberPrivacyTarget => write!(f, "<privacy target>"), ParameterKind::MemberPrivacyTarget => write!(f, "<privacy target>"),
@ -83,6 +85,7 @@ pub enum ParameterKind {
OpaqueStringRemainder, OpaqueStringRemainder,
MemberRef, MemberRef,
MemberRefs, MemberRefs,
GroupRef,
SystemRef, SystemRef,
GuildRef, GuildRef,
MemberPrivacyTarget, MemberPrivacyTarget,
@ -99,6 +102,7 @@ impl ParameterKind {
ParameterKind::OpaqueStringRemainder => "string", ParameterKind::OpaqueStringRemainder => "string",
ParameterKind::MemberRef => "target", ParameterKind::MemberRef => "target",
ParameterKind::MemberRefs => "targets", ParameterKind::MemberRefs => "targets",
ParameterKind::GroupRef => "target",
ParameterKind::SystemRef => "target", ParameterKind::SystemRef => "target",
ParameterKind::GuildRef => "target", ParameterKind::GuildRef => "target",
ParameterKind::MemberPrivacyTarget => "member_privacy_target", ParameterKind::MemberPrivacyTarget => "member_privacy_target",
@ -122,6 +126,7 @@ impl ParameterKind {
ParameterKind::OpaqueString | ParameterKind::OpaqueStringRemainder => { ParameterKind::OpaqueString | ParameterKind::OpaqueStringRemainder => {
Ok(ParameterValue::OpaqueString(input.into())) Ok(ParameterValue::OpaqueString(input.into()))
} }
ParameterKind::GroupRef => Ok(ParameterValue::GroupRef(input.into())),
ParameterKind::MemberRef => Ok(ParameterValue::MemberRef(input.into())), ParameterKind::MemberRef => Ok(ParameterValue::MemberRef(input.into())),
ParameterKind::MemberRefs => Ok(ParameterValue::MemberRefs( ParameterKind::MemberRefs => Ok(ParameterValue::MemberRefs(
input.split(' ').map(|s| s.trim().to_string()).collect(), input.split(' ').map(|s| s.trim().to_string()).collect(),

View file

@ -168,6 +168,7 @@ fn get_param_ty(kind: ParameterKind) -> &'static str {
ParameterKind::OpaqueString | ParameterKind::OpaqueStringRemainder => "string", ParameterKind::OpaqueString | ParameterKind::OpaqueStringRemainder => "string",
ParameterKind::MemberRef => "PKMember", ParameterKind::MemberRef => "PKMember",
ParameterKind::MemberRefs => "List<PKMember>", ParameterKind::MemberRefs => "List<PKMember>",
ParameterKind::GroupRef => "PKGroup",
ParameterKind::SystemRef => "PKSystem", ParameterKind::SystemRef => "PKSystem",
ParameterKind::MemberPrivacyTarget => "MemberPrivacySubject", ParameterKind::MemberPrivacyTarget => "MemberPrivacySubject",
ParameterKind::SystemPrivacyTarget => "SystemPrivacySubject", ParameterKind::SystemPrivacyTarget => "SystemPrivacySubject",
@ -183,6 +184,7 @@ fn get_param_param_ty(kind: ParameterKind) -> &'static str {
ParameterKind::OpaqueString | ParameterKind::OpaqueStringRemainder => "Opaque", ParameterKind::OpaqueString | ParameterKind::OpaqueStringRemainder => "Opaque",
ParameterKind::MemberRef => "Member", ParameterKind::MemberRef => "Member",
ParameterKind::MemberRefs => "Members", ParameterKind::MemberRefs => "Members",
ParameterKind::GroupRef => "Group",
ParameterKind::SystemRef => "System", ParameterKind::SystemRef => "System",
ParameterKind::MemberPrivacyTarget => "MemberPrivacyTarget", ParameterKind::MemberPrivacyTarget => "MemberPrivacyTarget",
ParameterKind::SystemPrivacyTarget => "SystemPrivacyTarget", ParameterKind::SystemPrivacyTarget => "SystemPrivacyTarget",

View file

@ -10,6 +10,7 @@ interface CommandResult {
interface Parameter { interface Parameter {
MemberRef(string member); MemberRef(string member);
MemberRefs(sequence<string> members); MemberRefs(sequence<string> members);
GroupRef(string group);
SystemRef(string system); SystemRef(string system);
GuildRef(string guild); GuildRef(string guild);
MemberPrivacyTarget(string target); MemberPrivacyTarget(string target);

View file

@ -24,6 +24,7 @@ pub enum CommandResult {
pub enum Parameter { pub enum Parameter {
MemberRef { member: String }, MemberRef { member: String },
MemberRefs { members: Vec<String> }, MemberRefs { members: Vec<String> },
GroupRef { group: String },
SystemRef { system: String }, SystemRef { system: String },
GuildRef { guild: String }, GuildRef { guild: String },
MemberPrivacyTarget { target: String }, MemberPrivacyTarget { target: String },
@ -39,6 +40,7 @@ impl From<ParameterValue> for Parameter {
match value { match value {
ParameterValue::MemberRef(member) => Self::MemberRef { member }, ParameterValue::MemberRef(member) => Self::MemberRef { member },
ParameterValue::MemberRefs(members) => Self::MemberRefs { members }, ParameterValue::MemberRefs(members) => Self::MemberRefs { members },
ParameterValue::GroupRef(group) => Self::GroupRef { group },
ParameterValue::SystemRef(system) => Self::SystemRef { system }, ParameterValue::SystemRef(system) => Self::SystemRef { system },
ParameterValue::MemberPrivacyTarget(target) => Self::MemberPrivacyTarget { target }, ParameterValue::MemberPrivacyTarget(target) => Self::MemberPrivacyTarget { target },
ParameterValue::SystemPrivacyTarget(target) => Self::SystemPrivacyTarget { target }, ParameterValue::SystemPrivacyTarget(target) => Self::SystemPrivacyTarget { target },