feat: implement system privacy commands (yay system edit done)

This commit is contained in:
dusk 2025-04-04 06:14:17 +09:00
parent cb0a9eaf9f
commit 3eece261fd
No known key found for this signature in database
10 changed files with 154 additions and 75 deletions

View file

@ -100,6 +100,9 @@ public partial class CommandTree
Commands.SystemShowProxy(var param, _) => ctx.Execute<SystemEdit>(SystemProxy, m => m.ShowSystemProxy(ctx, param.target)), Commands.SystemShowProxy(var param, _) => ctx.Execute<SystemEdit>(SystemProxy, m => m.ShowSystemProxy(ctx, param.target)),
Commands.SystemToggleProxyCurrent(var param, _) => ctx.Execute<SystemEdit>(SystemProxy, m => m.ToggleSystemProxy(ctx, ctx.Guild, param.toggle)), Commands.SystemToggleProxyCurrent(var param, _) => ctx.Execute<SystemEdit>(SystemProxy, m => m.ToggleSystemProxy(ctx, ctx.Guild, param.toggle)),
Commands.SystemToggleProxy(var param, _) => ctx.Execute<SystemEdit>(SystemProxy, m => m.ToggleSystemProxy(ctx, param.target, param.toggle)), Commands.SystemToggleProxy(var param, _) => ctx.Execute<SystemEdit>(SystemProxy, m => m.ToggleSystemProxy(ctx, param.target, param.toggle)),
Commands.SystemShowPrivacy(var param, _) => ctx.Execute<SystemEdit>(SystemPrivacy, m => m.ShowSystemPrivacy(ctx, ctx.System)),
Commands.SystemChangePrivacyAll(var param, _) => ctx.Execute<SystemEdit>(SystemPrivacy, m => m.ChangeSystemPrivacyAll(ctx, ctx.System, param.level)),
Commands.SystemChangePrivacy(var param, _) => ctx.Execute<SystemEdit>(SystemPrivacy, m => m.ChangeSystemPrivacy(ctx, ctx.System, param.privacy, param.level)),
_ => _ =>
// 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(
@ -363,8 +366,6 @@ public partial class CommandTree
await ctx.CheckSystem(target).Execute<SystemFront>(SystemFrontPercent, m => m.FrontPercent(ctx, system: target)); await ctx.CheckSystem(target).Execute<SystemFront>(SystemFrontPercent, m => m.FrontPercent(ctx, system: target));
else if (ctx.Match("groups", "gs")) else if (ctx.Match("groups", "gs"))
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("privacy"))
await ctx.CheckSystem(target).Execute<SystemEdit>(SystemPrivacy, m => m.SystemPrivacy(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")) else if (ctx.Match("random", "rand", "r"))

View file

@ -36,7 +36,7 @@ public static class ContextFlagsExt
); );
} }
public static async Task<string?> FlagResolvePrivacyLevel(this Context ctx, string param_name) public static async Task<PrivacyLevel?> FlagResolvePrivacyLevel(this Context ctx, string param_name)
{ {
return await ctx.Parameters.ResolveFlag( return await ctx.Parameters.ResolveFlag(
ctx, param_name, ctx, param_name,

View file

@ -36,7 +36,15 @@ public static class ContextParametersExt
); );
} }
public static async Task<string?> ParamResolvePrivacyLevel(this Context ctx, string param_name) public static async Task<SystemPrivacySubject?> ParamResolveSystemPrivacyTarget(this Context ctx, string param_name)
{
return await ctx.Parameters.ResolveParameter(
ctx, param_name,
param => (param as Parameter.SystemPrivacyTarget)?.target
);
}
public static async Task<PrivacyLevel?> ParamResolvePrivacyLevel(this Context ctx, string param_name)
{ {
return await ctx.Parameters.ResolveParameter( return await ctx.Parameters.ResolveParameter(
ctx, param_name, ctx, param_name,

View file

@ -1,4 +1,3 @@
using System.Diagnostics;
using Myriad.Types; using Myriad.Types;
using PluralKit.Core; using PluralKit.Core;
using uniffi.commands; using uniffi.commands;
@ -12,7 +11,8 @@ public abstract record 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;
public record PrivacyLevel(string level): Parameter; public record SystemPrivacyTarget(SystemPrivacySubject target): Parameter;
public record PrivacyLevel(Core.PrivacyLevel level): Parameter;
public record Toggle(bool value): Parameter; public record Toggle(bool value): Parameter;
public record Opaque(string value): Parameter; public record Opaque(string value): Parameter;
public record Avatar(ParsedImage avatar): Parameter; public record Avatar(ParsedImage avatar): Parameter;
@ -72,12 +72,16 @@ public class Parameters
); );
case uniffi.commands.Parameter.MemberPrivacyTarget memberPrivacyTarget: case uniffi.commands.Parameter.MemberPrivacyTarget memberPrivacyTarget:
// this should never really fail... // this should never really fail...
// todo: we shouldn't have *three* different MemberPrivacyTarget types (rust, ffi, c#) syncing the cases will be annoying... if (!MemberPrivacyUtils.TryParseMemberPrivacy(memberPrivacyTarget.target, out var memberPrivacy))
if (!MemberPrivacyUtils.TryParseMemberPrivacy(memberPrivacyTarget.target, out var target))
throw new PKError($"Invalid member privacy target {memberPrivacyTarget.target}"); throw new PKError($"Invalid member privacy target {memberPrivacyTarget.target}");
return new Parameter.MemberPrivacyTarget(target); return new Parameter.MemberPrivacyTarget(memberPrivacy);
case uniffi.commands.Parameter.SystemPrivacyTarget systemPrivacyTarget:
// this should never really fail...
if (!SystemPrivacyUtils.TryParseSystemPrivacy(systemPrivacyTarget.target, out var systemPrivacy))
throw new PKError($"Invalid system privacy target {systemPrivacyTarget.target}");
return new Parameter.SystemPrivacyTarget(systemPrivacy);
case uniffi.commands.Parameter.PrivacyLevel privacyLevel: case uniffi.commands.Parameter.PrivacyLevel privacyLevel:
return new Parameter.PrivacyLevel(privacyLevel.level); return new Parameter.PrivacyLevel(privacyLevel.level == "public" ? PrivacyLevel.Public : privacyLevel.level == "private" ? PrivacyLevel.Private : throw new PKError($"Invalid privacy level {privacyLevel.level}"));
case uniffi.commands.Parameter.Toggle toggle: case uniffi.commands.Parameter.Toggle toggle:
return new Parameter.Toggle(toggle.toggle); return new Parameter.Toggle(toggle.toggle);
case uniffi.commands.Parameter.OpaqueString opaque: case uniffi.commands.Parameter.OpaqueString opaque:

View file

@ -874,79 +874,72 @@ public class SystemEdit
$"Proxying in {serverText} is currently **disabled** for your system. To enable it, type `{ctx.DefaultPrefix}system proxy on`."); $"Proxying in {serverText} is currently **disabled** for your system. To enable it, type `{ctx.DefaultPrefix}system proxy on`.");
} }
public async Task SystemPrivacy(Context ctx, PKSystem target) public async Task ShowSystemPrivacy(Context ctx, PKSystem target)
{ {
ctx.CheckSystem().CheckOwnSystem(target); ctx.CheckSystem().CheckOwnSystem(target);
Task PrintEmbed() var eb = new EmbedBuilder()
.Title("Current privacy settings for your system")
.Field(new Embed.Field("Name", target.NamePrivacy.Explanation()))
.Field(new Embed.Field("Avatar", target.AvatarPrivacy.Explanation()))
.Field(new Embed.Field("Description", target.DescriptionPrivacy.Explanation()))
.Field(new Embed.Field("Banner", target.BannerPrivacy.Explanation()))
.Field(new Embed.Field("Pronouns", target.PronounPrivacy.Explanation()))
.Field(new Embed.Field("Member list", target.MemberListPrivacy.Explanation()))
.Field(new Embed.Field("Group list", target.GroupListPrivacy.Explanation()))
.Field(new Embed.Field("Current fronter(s)", target.FrontPrivacy.Explanation()))
.Field(new Embed.Field("Front/switch history", target.FrontHistoryPrivacy.Explanation()))
.Description(
$"To edit privacy settings, use the command:\n`{ctx.DefaultPrefix}system privacy <subject> <level>`\n\n- `subject` is one of `name`, `avatar`, `description`, `banner`, `pronouns`, `list`, `front`, `fronthistory`, `groups`, or `all` \n- `level` is either `public` or `private`.");
await ctx.Reply(embed: eb.Build());
}
public async Task ChangeSystemPrivacy(Context ctx, PKSystem target, SystemPrivacySubject subject, PrivacyLevel level)
{
ctx.CheckSystem().CheckOwnSystem(target);
await ctx.Repository.UpdateSystem(target.Id, new SystemPatch().WithPrivacy(subject, level));
var levelExplanation = level switch
{ {
var eb = new EmbedBuilder() PrivacyLevel.Public => "be able to query",
.Title("Current privacy settings for your system") PrivacyLevel.Private => "*not* be able to query",
.Field(new Embed.Field("Name", target.NamePrivacy.Explanation())) _ => ""
.Field(new Embed.Field("Avatar", target.AvatarPrivacy.Explanation())) };
.Field(new Embed.Field("Description", target.DescriptionPrivacy.Explanation()))
.Field(new Embed.Field("Banner", target.BannerPrivacy.Explanation()))
.Field(new Embed.Field("Pronouns", target.PronounPrivacy.Explanation()))
.Field(new Embed.Field("Member list", target.MemberListPrivacy.Explanation()))
.Field(new Embed.Field("Group list", target.GroupListPrivacy.Explanation()))
.Field(new Embed.Field("Current fronter(s)", target.FrontPrivacy.Explanation()))
.Field(new Embed.Field("Front/switch history", target.FrontHistoryPrivacy.Explanation()))
.Description(
$"To edit privacy settings, use the command:\n`{ctx.DefaultPrefix}system privacy <subject> <level>`\n\n- `subject` is one of `name`, `avatar`, `description`, `banner`, `pronouns`, `list`, `front`, `fronthistory`, `groups`, or `all` \n- `level` is either `public` or `private`.");
return ctx.Reply(embed: eb.Build());
}
async Task SetLevel(SystemPrivacySubject subject, PrivacyLevel level) var subjectStr = subject switch
{ {
await ctx.Repository.UpdateSystem(target.Id, new SystemPatch().WithPrivacy(subject, level)); SystemPrivacySubject.Name => "name",
SystemPrivacySubject.Avatar => "avatar",
SystemPrivacySubject.Description => "description",
SystemPrivacySubject.Banner => "banner",
SystemPrivacySubject.Pronouns => "pronouns",
SystemPrivacySubject.Front => "front",
SystemPrivacySubject.FrontHistory => "front history",
SystemPrivacySubject.MemberList => "member list",
SystemPrivacySubject.GroupList => "group list",
_ => ""
};
var levelExplanation = level switch var msg = $"System {subjectStr} privacy has been set to **{level.LevelName()}**. Other accounts will now {levelExplanation} your system {subjectStr}.";
{ await ctx.Reply($"{Emojis.Success} {msg}");
PrivacyLevel.Public => "be able to query", }
PrivacyLevel.Private => "*not* be able to query",
_ => ""
};
var subjectStr = subject switch public async Task ChangeSystemPrivacyAll(Context ctx, PKSystem target, PrivacyLevel level)
{ {
SystemPrivacySubject.Name => "name", ctx.CheckSystem().CheckOwnSystem(target);
SystemPrivacySubject.Avatar => "avatar",
SystemPrivacySubject.Description => "description",
SystemPrivacySubject.Banner => "banner",
SystemPrivacySubject.Pronouns => "pronouns",
SystemPrivacySubject.Front => "front",
SystemPrivacySubject.FrontHistory => "front history",
SystemPrivacySubject.MemberList => "member list",
SystemPrivacySubject.GroupList => "group list",
_ => ""
};
var msg = await ctx.Repository.UpdateSystem(target.Id, new SystemPatch().WithAllPrivacy(level));
$"System {subjectStr} privacy has been set to **{level.LevelName()}**. Other accounts will now {levelExplanation} your system {subjectStr}.";
await ctx.Reply($"{Emojis.Success} {msg}");
}
async Task SetAll(PrivacyLevel level) var msg = level switch
{ {
await ctx.Repository.UpdateSystem(target.Id, new SystemPatch().WithAllPrivacy(level)); PrivacyLevel.Private =>
$"All system privacy settings have been set to **{level.LevelName()}**. Other accounts will now not be able to view your member list, group list, front history, or system description.",
PrivacyLevel.Public =>
$"All system privacy settings have been set to **{level.LevelName()}**. Other accounts will now be able to view everything.",
_ => ""
};
var msg = level switch await ctx.Reply($"{Emojis.Success} {msg}");
{
PrivacyLevel.Private =>
$"All system privacy settings have been set to **{level.LevelName()}**. Other accounts will now not be able to view your member list, group list, front history, or system description.",
PrivacyLevel.Public =>
$"All system privacy settings have been set to **{level.LevelName()}**. Other accounts will now be able to view everything.",
_ => ""
};
await ctx.Reply($"{Emojis.Success} {msg}");
}
if (!ctx.HasNext())
await PrintEmbed();
else if (ctx.Match("all"))
await SetAll(ctx.PopPrivacyLevel());
else
await SetLevel(ctx.PopSystemPrivacySubject(), ctx.PopPrivacyLevel());
} }
} }

View file

@ -202,12 +202,25 @@ pub fn edit() -> impl Iterator<Item = Command> {
let system_proxy = tokens!(system, "proxy"); let system_proxy = tokens!(system, "proxy");
let system_proxy_cmd = [ let system_proxy_cmd = [
command!(system_proxy => "system_show_proxy_current").help("Shows your system's proxy setting for the guild you are in"), command!(system_proxy => "system_show_proxy_current")
.help("Shows your system's proxy setting for the guild you are in"),
command!(system_proxy, Toggle => "system_toggle_proxy_current") command!(system_proxy, Toggle => "system_toggle_proxy_current")
.help("Toggle your system's proxy for the guild you are in"), .help("Toggle your system's proxy for the guild you are in"),
command!(system_proxy, GuildRef => "system_show_proxy").help("Shows your system's proxy setting for a guild"), command!(system_proxy, GuildRef => "system_show_proxy")
.help("Shows your system's proxy setting for a guild"),
command!(system_proxy, GuildRef, Toggle => "system_toggle_proxy") command!(system_proxy, GuildRef, Toggle => "system_toggle_proxy")
.help("Toggle your system's proxy for a guild"), .help("Toggle your system's proxy for a guild"),
]
.into_iter();
let system_privacy = tokens!(system, ("privacy", ["priv"]));
let system_privacy_cmd = [
command!(system_privacy => "system_show_privacy")
.help("Shows your system's privacy settings"),
command!(system_privacy, ("all", ["a"]), ("level", PrivacyLevel) => "system_change_privacy_all")
.help("Changes all privacy settings for your system"),
command!(system_privacy, ("privacy", SystemPrivacyTarget), ("level", PrivacyLevel) => "system_change_privacy")
.help("Changes a specific privacy setting for your system"),
].into_iter(); ].into_iter();
system_new_cmd system_new_cmd
@ -222,6 +235,7 @@ pub fn edit() -> impl Iterator<Item = Command> {
.chain(system_server_avatar_self_cmd) .chain(system_server_avatar_self_cmd)
.chain(system_banner_self_cmd) .chain(system_banner_self_cmd)
.chain(system_delete) .chain(system_delete)
.chain(system_privacy_cmd)
.chain(system_proxy_cmd) .chain(system_proxy_cmd)
.chain(system_name_cmd) .chain(system_name_cmd)
.chain(system_server_name_cmd) .chain(system_server_name_cmd)

View file

@ -14,6 +14,7 @@ pub enum ParameterValue {
SystemRef(String), SystemRef(String),
GuildRef(String), GuildRef(String),
MemberPrivacyTarget(String), MemberPrivacyTarget(String),
SystemPrivacyTarget(String),
PrivacyLevel(String), PrivacyLevel(String),
Toggle(bool), Toggle(bool),
Avatar(String), Avatar(String),
@ -45,6 +46,7 @@ impl Display for Parameter {
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>"),
ParameterKind::SystemPrivacyTarget => write!(f, "<privacy target>"),
ParameterKind::PrivacyLevel => write!(f, "[privacy level]"), ParameterKind::PrivacyLevel => write!(f, "[privacy level]"),
ParameterKind::Toggle => write!(f, "on/off"), ParameterKind::Toggle => write!(f, "on/off"),
ParameterKind::Avatar => write!(f, "<url|@mention>"), ParameterKind::Avatar => write!(f, "<url|@mention>"),
@ -78,6 +80,7 @@ pub enum ParameterKind {
SystemRef, SystemRef,
GuildRef, GuildRef,
MemberPrivacyTarget, MemberPrivacyTarget,
SystemPrivacyTarget,
PrivacyLevel, PrivacyLevel,
Toggle, Toggle,
Avatar, Avatar,
@ -92,6 +95,7 @@ impl ParameterKind {
ParameterKind::SystemRef => "target", ParameterKind::SystemRef => "target",
ParameterKind::GuildRef => "target", ParameterKind::GuildRef => "target",
ParameterKind::MemberPrivacyTarget => "member_privacy_target", ParameterKind::MemberPrivacyTarget => "member_privacy_target",
ParameterKind::SystemPrivacyTarget => "system_privacy_target",
ParameterKind::PrivacyLevel => "privacy_level", ParameterKind::PrivacyLevel => "privacy_level",
ParameterKind::Toggle => "toggle", ParameterKind::Toggle => "toggle",
ParameterKind::Avatar => "avatar", ParameterKind::Avatar => "avatar",
@ -112,6 +116,9 @@ impl ParameterKind {
ParameterKind::SystemRef => Ok(ParameterValue::SystemRef(input.into())), ParameterKind::SystemRef => Ok(ParameterValue::SystemRef(input.into())),
ParameterKind::MemberPrivacyTarget => MemberPrivacyTargetKind::from_str(input) ParameterKind::MemberPrivacyTarget => MemberPrivacyTargetKind::from_str(input)
.map(|target| ParameterValue::MemberPrivacyTarget(target.as_ref().into())), .map(|target| ParameterValue::MemberPrivacyTarget(target.as_ref().into())),
ParameterKind::SystemPrivacyTarget => SystemPrivacyTargetKind::from_str(input).map(
|target| ParameterValue::SystemPrivacyTarget(target.as_ref().into()),
),
ParameterKind::PrivacyLevel => PrivacyLevelKind::from_str(input) ParameterKind::PrivacyLevel => PrivacyLevelKind::from_str(input)
.map(|level| ParameterValue::PrivacyLevel(level.as_ref().into())), .map(|level| ParameterValue::PrivacyLevel(level.as_ref().into())),
ParameterKind::Toggle => { ParameterKind::Toggle => {
@ -176,6 +183,53 @@ impl FromStr for MemberPrivacyTargetKind {
} }
} }
pub enum SystemPrivacyTargetKind {
Name,
Avatar,
Description,
Banner,
Pronouns,
MemberList,
GroupList,
Front,
FrontHistory,
}
impl AsRef<str> for SystemPrivacyTargetKind {
fn as_ref(&self) -> &str {
match self {
Self::Name => "name",
Self::Avatar => "avatar",
Self::Description => "description",
Self::Banner => "banner",
Self::Pronouns => "pronouns",
Self::MemberList => "members",
Self::GroupList => "groups",
Self::Front => "front",
Self::FrontHistory => "fronthistory",
}
}
}
impl FromStr for SystemPrivacyTargetKind {
type Err = SmolStr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"name" => Ok(Self::Name),
"avatar" | "pfp" | "pic" | "icon" => Ok(Self::Avatar),
"description" | "desc" | "bio" | "info" => Ok(Self::Description),
"banner" | "splash" | "cover" => Ok(Self::Banner),
"pronouns" | "prns" | "pn" => Ok(Self::Pronouns),
"members" | "memberlist" | "list" => Ok(Self::MemberList),
"groups" | "gs" => Ok(Self::GroupList),
"front" | "fronter" | "fronters" => Ok(Self::Front),
"fronthistory" | "fh" | "switches" => Ok(Self::FrontHistory),
_ => Err("invalid system privacy target".into()),
}
}
}
pub enum PrivacyLevelKind { pub enum PrivacyLevelKind {
Public, Public,
Private, Private,

View file

@ -169,7 +169,8 @@ fn get_param_ty(kind: ParameterKind) -> &'static str {
ParameterKind::MemberRef => "PKMember", ParameterKind::MemberRef => "PKMember",
ParameterKind::SystemRef => "PKSystem", ParameterKind::SystemRef => "PKSystem",
ParameterKind::MemberPrivacyTarget => "MemberPrivacySubject", ParameterKind::MemberPrivacyTarget => "MemberPrivacySubject",
ParameterKind::PrivacyLevel => "string", ParameterKind::SystemPrivacyTarget => "SystemPrivacySubject",
ParameterKind::PrivacyLevel => "PrivacyLevel",
ParameterKind::Toggle => "bool", ParameterKind::Toggle => "bool",
ParameterKind::Avatar => "ParsedImage", ParameterKind::Avatar => "ParsedImage",
ParameterKind::GuildRef => "Guild", ParameterKind::GuildRef => "Guild",
@ -182,6 +183,7 @@ fn get_param_param_ty(kind: ParameterKind) -> &'static str {
ParameterKind::MemberRef => "Member", ParameterKind::MemberRef => "Member",
ParameterKind::SystemRef => "System", ParameterKind::SystemRef => "System",
ParameterKind::MemberPrivacyTarget => "MemberPrivacyTarget", ParameterKind::MemberPrivacyTarget => "MemberPrivacyTarget",
ParameterKind::SystemPrivacyTarget => "SystemPrivacyTarget",
ParameterKind::PrivacyLevel => "PrivacyLevel", ParameterKind::PrivacyLevel => "PrivacyLevel",
ParameterKind::Toggle => "Toggle", ParameterKind::Toggle => "Toggle",
ParameterKind::Avatar => "Avatar", ParameterKind::Avatar => "Avatar",

View file

@ -12,6 +12,7 @@ interface Parameter {
SystemRef(string system); SystemRef(string system);
GuildRef(string guild); GuildRef(string guild);
MemberPrivacyTarget(string target); MemberPrivacyTarget(string target);
SystemPrivacyTarget(string target);
PrivacyLevel(string level); PrivacyLevel(string level);
OpaqueString(string raw); OpaqueString(string raw);
Toggle(boolean toggle); Toggle(boolean toggle);

View file

@ -26,6 +26,7 @@ pub enum Parameter {
SystemRef { system: String }, SystemRef { system: String },
GuildRef { guild: String }, GuildRef { guild: String },
MemberPrivacyTarget { target: String }, MemberPrivacyTarget { target: String },
SystemPrivacyTarget { target: String },
PrivacyLevel { level: String }, PrivacyLevel { level: String },
OpaqueString { raw: String }, OpaqueString { raw: String },
Toggle { toggle: bool }, Toggle { toggle: bool },
@ -38,6 +39,7 @@ impl From<ParameterValue> for Parameter {
ParameterValue::MemberRef(member) => Self::MemberRef { member }, ParameterValue::MemberRef(member) => Self::MemberRef { member },
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::PrivacyLevel(level) => Self::PrivacyLevel { level }, ParameterValue::PrivacyLevel(level) => Self::PrivacyLevel { level },
ParameterValue::OpaqueString(raw) => Self::OpaqueString { raw }, ParameterValue::OpaqueString(raw) => Self::OpaqueString { raw },
ParameterValue::Toggle(toggle) => Self::Toggle { toggle }, ParameterValue::Toggle(toggle) => Self::Toggle { toggle },