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).");