diff --git a/PluralKit.Bot/CommandSystem/Context/Context.cs b/PluralKit.Bot/CommandSystem/Context/Context.cs index b80fe257..eca831a8 100644 --- a/PluralKit.Bot/CommandSystem/Context/Context.cs +++ b/PluralKit.Bot/CommandSystem/Context/Context.cs @@ -133,6 +133,12 @@ public class Context await Reply($"{Emojis.Warn} This command is deprecated and will be removed soon. In the future, please use `pk;{commandDef.Key}`."); } + /// + /// Same as LookupContextFor, but skips flags / config checks. + /// + public LookupContext DirectLookupContextFor(SystemId systemId) + => System?.Id == systemId ? LookupContext.ByOwner : LookupContext.ByNonOwner; + public LookupContext LookupContextFor(SystemId systemId) { var hasPrivateOverride = this.MatchFlag("private", "priv"); diff --git a/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs b/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs index b1a7a318..1d48e057 100644 --- a/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs +++ b/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs @@ -21,10 +21,10 @@ public static class ContextChecksExt throw new PKError("This command must be run in a DM."); } - public static Context CheckSystemPrivacy(this Context ctx, PKSystem target, PrivacyLevel level) + public static Context CheckSystemPrivacy(this Context ctx, SystemId target, PrivacyLevel level) { - if (level.CanAccess(ctx.LookupContextFor(target.Id))) return ctx; - throw target.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + if (level.CanAccess(ctx.DirectLookupContextFor(target))) return ctx; + throw Errors.LookupNotAllowed; } public static Context CheckOwnSystem(this Context ctx, PKSystem system) diff --git a/PluralKit.Bot/Commands/GroupMember.cs b/PluralKit.Bot/Commands/GroupMember.cs index 04fefe9d..5e4786c3 100644 --- a/PluralKit.Bot/Commands/GroupMember.cs +++ b/PluralKit.Bot/Commands/GroupMember.cs @@ -129,10 +129,12 @@ public class GroupMember public async Task ListGroupMembers(Context ctx, PKGroup target) { - var targetSystem = await GetGroupSystem(ctx, target); - ctx.CheckSystemPrivacy(targetSystem, target.ListPrivacy); + // see global system list for explanation of how privacy settings are used here - var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(target.System)); + var targetSystem = await GetGroupSystem(ctx, target); + ctx.CheckSystemPrivacy(targetSystem.Id, target.ListPrivacy); + + var opts = ctx.ParseMemberListOptions(ctx.DirectLookupContextFor(target.System)); opts.GroupFilter = target.Id; var title = new StringBuilder($"Members of {target.DisplayName ?? target.Name} (`{target.Hid}`) in "); diff --git a/PluralKit.Bot/Commands/Groups.cs b/PluralKit.Bot/Commands/Groups.cs index c87f977d..9b6c65ba 100644 --- a/PluralKit.Bot/Commands/Groups.cs +++ b/PluralKit.Bot/Commands/Groups.cs @@ -189,8 +189,7 @@ public class Groups public async Task GroupDescription(Context ctx, PKGroup target) { - if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); var noDescriptionSetMessage = "This group does not have a description set."; if (ctx.System?.Id == target.System) @@ -281,8 +280,7 @@ public class Groups async Task ShowIcon() { - if (!target.IconPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + ctx.CheckSystemPrivacy(target.System, target.IconPrivacy); if ((target.Icon?.Trim() ?? "").Length > 0) { @@ -346,8 +344,7 @@ public class Groups async Task ShowBannerImage() { - if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); if ((target.BannerImage?.Trim() ?? "").Length > 0) { @@ -432,7 +429,7 @@ public class Groups system = ctx.System; } - ctx.CheckSystemPrivacy(system, system.GroupListPrivacy); + ctx.CheckSystemPrivacy(system.Id, system.GroupListPrivacy); // TODO: integrate with the normal "search" system @@ -442,7 +439,7 @@ public class Groups if (system.Id == ctx.System.Id) pctx = LookupContext.ByOwner; else - throw system.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + throw Errors.LookupNotAllowed; } var groups = (await _db.Execute(conn => conn.QueryGroupList(system.Id))) @@ -577,7 +574,7 @@ public class Groups public async Task GroupFrontPercent(Context ctx, PKGroup target) { var targetSystem = await GetGroupSystem(ctx, target); - ctx.CheckSystemPrivacy(targetSystem, targetSystem.FrontHistoryPrivacy); + ctx.CheckSystemPrivacy(targetSystem.Id, targetSystem.FrontHistoryPrivacy); var totalSwitches = await _repo.GetSwitchCount(targetSystem.Id); if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; diff --git a/PluralKit.Bot/Commands/MemberAvatar.cs b/PluralKit.Bot/Commands/MemberAvatar.cs index 53460080..4b3ceebd 100644 --- a/PluralKit.Bot/Commands/MemberAvatar.cs +++ b/PluralKit.Bot/Commands/MemberAvatar.cs @@ -41,9 +41,12 @@ public class MemberAvatar private async Task AvatarShow(AvatarLocation location, Context ctx, PKMember target, MemberGuildSettings? guildData) { + // todo: this privacy code is really confusing + // for now, we skip privacy flag/config parsing for this, but it would be good to fix that at some point + var currentValue = location == AvatarLocation.Member ? target.AvatarUrl : guildData?.AvatarUrl; var canAccess = location != AvatarLocation.Member || - target.AvatarPrivacy.CanAccess(ctx.LookupContextFor(target.System)); + target.AvatarPrivacy.CanAccess(ctx.DirectLookupContextFor(target.System)); if (string.IsNullOrEmpty(currentValue) || !canAccess) { if (location == AvatarLocation.Member) diff --git a/PluralKit.Bot/Commands/MemberEdit.cs b/PluralKit.Bot/Commands/MemberEdit.cs index 3b370ff8..5f8be171 100644 --- a/PluralKit.Bot/Commands/MemberEdit.cs +++ b/PluralKit.Bot/Commands/MemberEdit.cs @@ -63,14 +63,13 @@ public class MemberEdit public async Task Description(Context ctx, PKMember target) { + ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); + var noDescriptionSetMessage = "This member does not have a description set."; if (ctx.System?.Id == target.System) noDescriptionSetMessage += $" To set one, type `pk;member {target.Reference()} description `."; - if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; - if (ctx.MatchRaw()) { if (target.Description == null) @@ -124,8 +123,7 @@ public class MemberEdit if (ctx.System?.Id == target.System) noPronounsSetMessage += $"To set some, type `pk;member {target.Reference()} pronouns `."; - if (!target.PronounPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + ctx.CheckSystemPrivacy(target.System, target.PronounPrivacy); if (ctx.MatchRaw()) { @@ -292,8 +290,7 @@ public class MemberEdit } else if (!ctx.HasNext()) { - if (!target.BirthdayPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + ctx.CheckSystemPrivacy(target.System, target.BirthdayPrivacy); if (target.Birthday == null) await ctx.Reply("This member does not have a birthdate set." diff --git a/PluralKit.Bot/Commands/Random.cs b/PluralKit.Bot/Commands/Random.cs index fd8b4c68..adcc859a 100644 --- a/PluralKit.Bot/Commands/Random.cs +++ b/PluralKit.Bot/Commands/Random.cs @@ -55,7 +55,7 @@ public class Random public async Task GroupMember(Context ctx, PKGroup group) { - var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(group.System)); + var opts = ctx.ParseMemberListOptions(ctx.DirectLookupContextFor(group.System)); opts.GroupFilter = group.Id; await using var conn = await _db.Obtain(); diff --git a/PluralKit.Bot/Commands/SystemFront.cs b/PluralKit.Bot/Commands/SystemFront.cs index 32291f35..f0606626 100644 --- a/PluralKit.Bot/Commands/SystemFront.cs +++ b/PluralKit.Bot/Commands/SystemFront.cs @@ -22,7 +22,7 @@ public class SystemFront public async Task SystemFronter(Context ctx, PKSystem system) { if (system == null) throw Errors.NoSystemError; - ctx.CheckSystemPrivacy(system, system.FrontPrivacy); + ctx.CheckSystemPrivacy(system.Id, system.FrontPrivacy); var sw = await _repo.GetLatestSwitch(system.Id); if (sw == null) throw Errors.NoRegisteredSwitches; @@ -33,7 +33,7 @@ public class SystemFront public async Task SystemFrontHistory(Context ctx, PKSystem system) { if (system == null) throw Errors.NoSystemError; - ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy); + ctx.CheckSystemPrivacy(system.Id, system.FrontHistoryPrivacy); var totalSwitches = await _repo.GetSwitchCount(system.Id); if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; @@ -98,7 +98,7 @@ public class SystemFront public async Task SystemFrontPercent(Context ctx, PKSystem system) { if (system == null) throw Errors.NoSystemError; - ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy); + ctx.CheckSystemPrivacy(system.Id, system.FrontHistoryPrivacy); var totalSwitches = await _repo.GetSwitchCount(system.Id); if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; diff --git a/PluralKit.Bot/Commands/SystemList.cs b/PluralKit.Bot/Commands/SystemList.cs index d6157031..9f8c694b 100644 --- a/PluralKit.Bot/Commands/SystemList.cs +++ b/PluralKit.Bot/Commands/SystemList.cs @@ -9,9 +9,13 @@ public class SystemList public async Task MemberList(Context ctx, PKSystem target) { if (target == null) throw Errors.NoSystemError; - ctx.CheckSystemPrivacy(target, target.MemberListPrivacy); + ctx.CheckSystemPrivacy(target.Id, target.MemberListPrivacy); - var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(target.Id)); + // explanation of privacy lookup here: + // - ParseMemberListOptions checks list access privacy and sets the privacy filter (which members show up in list) + // - RenderMemberList checks the indivual privacy for each member (NameFor, etc) + // the own system is always allowed to look up their list + var opts = ctx.ParseMemberListOptions(ctx.DirectLookupContextFor(target.Id)); await ctx.RenderMemberList( ctx.LookupContextFor(target.Id), target.Id, diff --git a/PluralKit.Bot/Errors.cs b/PluralKit.Bot/Errors.cs index baeff67c..cec1208b 100644 --- a/PluralKit.Bot/Errors.cs +++ b/PluralKit.Bot/Errors.cs @@ -90,8 +90,6 @@ public static class Errors new("Cannot get the front percent between now and a time in the future."); public static PKError LookupNotAllowed => new("You do not have permission to access this information."); - public static PKError LookupHidden => - new("This information is private and you have chosen to hide private information by default. Add the `-private` flag to this command to show it."); public static PKError StringTooLongError(string name, int length, int maxLength) => new($"{name} too long ({length}/{maxLength} characters).");