diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index c77e3db6..871f5cfa 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -489,6 +489,8 @@ public partial class CommandTree return ctx.Execute(null, m => m.MemberDefaultPrivacy(ctx)); if (ctx.Match("gp")) return ctx.Execute(null, m => m.GroupDefaultPrivacy(ctx)); + if (ctx.MatchMultiple(new[] { "show" }, new[] { "private" }) || ctx.Match("sp")) + return ctx.Execute(null, m => m.ShowPrivateInfo(ctx)); // todo: maybe add the list of configuration keys here? return ctx.Reply($"{Emojis.Error} Could not find a setting with that name. Please see `pk;commands config` for the list of possible config settings."); diff --git a/PluralKit.Bot/CommandSystem/Context/Context.cs b/PluralKit.Bot/CommandSystem/Context/Context.cs index 52bd586e..b80fe257 100644 --- a/PluralKit.Bot/CommandSystem/Context/Context.cs +++ b/PluralKit.Bot/CommandSystem/Context/Context.cs @@ -141,7 +141,7 @@ public class Context if (hasPrivateOverride && hasPublicOverride) throw new PKError("Cannot match both public and private flags at the same time."); - if (System.Id != systemId) + if (System?.Id != systemId) { if (hasPrivateOverride) throw Errors.NotOwnInfo; @@ -153,8 +153,9 @@ public class Context if (hasPublicOverride) return LookupContext.ByNonOwner; - // todo: add config defaults - return LookupContext.ByOwner; + return Config.ShowPrivateInfo + ? LookupContext.ByOwner + : LookupContext.ByNonOwner; } public IComponentContext Services => _provider; diff --git a/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs b/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs index 64fa8194..b1a7a318 100644 --- a/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs +++ b/PluralKit.Bot/CommandSystem/Context/ContextChecksExt.cs @@ -24,7 +24,7 @@ public static class ContextChecksExt public static Context CheckSystemPrivacy(this Context ctx, PKSystem target, PrivacyLevel level) { if (level.CanAccess(ctx.LookupContextFor(target.Id))) return ctx; - throw new PKError("You do not have permission to access this information."); + throw target.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; } public static Context CheckOwnSystem(this Context ctx, PKSystem system) diff --git a/PluralKit.Bot/Commands/Config.cs b/PluralKit.Bot/Commands/Config.cs index d1233d29..9aa0100b 100644 --- a/PluralKit.Bot/Commands/Config.cs +++ b/PluralKit.Bot/Commands/Config.cs @@ -72,6 +72,13 @@ public class Config "disabled" )); + items.Add(new( + "show private", + "Whether private information is shown to linked accounts by default", + ctx.Config.ShowPrivateInfo.ToString().ToLower(), + "true" + )); + items.Add(new( "Member limit", "The maximum number of registered members for your system", @@ -345,7 +352,7 @@ public class Config if (!ctx.HasNext()) { - if (ctx.Config.MemberDefaultPrivate) { await ctx.Reply("Newly created groups will currently have their privacy settings set to private. To change this, type `pk;config private group off`"); } + if (ctx.Config.GroupDefaultPrivate) { await ctx.Reply("Newly created groups will currently have their privacy settings set to private. To change this, type `pk;config private group off`"); } else { await ctx.Reply("Newly created groups will currently have their privacy settings set to public. To automatically set new groups' privacy settings to private, type `pk;config private group on`"); } } else @@ -364,4 +371,30 @@ public class Config } } } + + public async Task ShowPrivateInfo(Context ctx) + { + ctx.CheckSystem(); + + if (!ctx.HasNext()) + { + if (ctx.Config.ShowPrivateInfo) await ctx.Reply("Private information is currently **shown** when looking up your own info. Use the `-public` flag to hide it."); + else await ctx.Reply("Private information is currently **hidden** when looking up your own info. Use the `-private` flag to show it."); + return; + } + + if (ctx.Match("true")) + { + await _repo.UpdateSystemConfig(ctx.System.Id, new() { ShowPrivateInfo = true }); + + await ctx.Reply("Private information will now be **shown** when looking up your own info. Use the `-public` flag to hide it."); + } + else if (ctx.Match("false")) + { + await _repo.UpdateSystemConfig(ctx.System.Id, new() { ShowPrivateInfo = false }); + + await ctx.Reply("Private information will now be **hidden** when looking up your own info. Use the `-private` flag to show it."); + } + else throw new PKError("You must pass 'true' or 'false' to this command."); + } } \ No newline at end of file diff --git a/PluralKit.Bot/Commands/Groups.cs b/PluralKit.Bot/Commands/Groups.cs index fbb250d5..c87f977d 100644 --- a/PluralKit.Bot/Commands/Groups.cs +++ b/PluralKit.Bot/Commands/Groups.cs @@ -190,7 +190,7 @@ public class Groups public async Task GroupDescription(Context ctx, PKGroup target) { if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw Errors.LookupNotAllowed; + throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; var noDescriptionSetMessage = "This group does not have a description set."; if (ctx.System?.Id == target.System) @@ -282,7 +282,8 @@ public class Groups async Task ShowIcon() { if (!target.IconPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw Errors.LookupNotAllowed; + throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + if ((target.Icon?.Trim() ?? "").Length > 0) { var eb = new EmbedBuilder() @@ -346,7 +347,8 @@ public class Groups async Task ShowBannerImage() { if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw Errors.LookupNotAllowed; + throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; + if ((target.BannerImage?.Trim() ?? "").Length > 0) { var eb = new EmbedBuilder() @@ -440,7 +442,7 @@ public class Groups if (system.Id == ctx.System.Id) pctx = LookupContext.ByOwner; else - throw new PKError("You do not have permission to access this information."); + throw system.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; } var groups = (await _db.Execute(conn => conn.QueryGroupList(system.Id))) diff --git a/PluralKit.Bot/Commands/Lists/ContextListExt.cs b/PluralKit.Bot/Commands/Lists/ContextListExt.cs index 77cfbbeb..24c10d53 100644 --- a/PluralKit.Bot/Commands/Lists/ContextListExt.cs +++ b/PluralKit.Bot/Commands/Lists/ContextListExt.cs @@ -54,8 +54,7 @@ public static class ContextListExt // Privacy filter (default is public only) if (ctx.MatchFlag("a", "all")) p.PrivacyFilter = null; - if (ctx.MatchFlag("private-only", "private", "priv")) p.PrivacyFilter = PrivacyLevel.Private; - if (ctx.MatchFlag("public-only", "public", "pub")) p.PrivacyFilter = PrivacyLevel.Public; + if (ctx.MatchFlag("private-only", "po")) p.PrivacyFilter = PrivacyLevel.Private; // PERM CHECK: If we're trying to access non-public members of another system, error if (p.PrivacyFilter != PrivacyLevel.Public && lookupCtx != LookupContext.ByOwner) diff --git a/PluralKit.Bot/Commands/MemberEdit.cs b/PluralKit.Bot/Commands/MemberEdit.cs index a3b0798b..3b370ff8 100644 --- a/PluralKit.Bot/Commands/MemberEdit.cs +++ b/PluralKit.Bot/Commands/MemberEdit.cs @@ -69,7 +69,7 @@ public class MemberEdit $" To set one, type `pk;member {target.Reference()} description `."; if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw Errors.LookupNotAllowed; + throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; if (ctx.MatchRaw()) { @@ -125,7 +125,7 @@ public class MemberEdit noPronounsSetMessage += $"To set some, type `pk;member {target.Reference()} pronouns `."; if (!target.PronounPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw Errors.LookupNotAllowed; + throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; if (ctx.MatchRaw()) { @@ -293,7 +293,7 @@ public class MemberEdit else if (!ctx.HasNext()) { if (!target.BirthdayPrivacy.CanAccess(ctx.LookupContextFor(target.System))) - throw Errors.LookupNotAllowed; + throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; if (target.Birthday == null) await ctx.Reply("This member does not have a birthdate set." diff --git a/PluralKit.Bot/Errors.cs b/PluralKit.Bot/Errors.cs index cec1208b..baeff67c 100644 --- a/PluralKit.Bot/Errors.cs +++ b/PluralKit.Bot/Errors.cs @@ -90,6 +90,8 @@ 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)."); diff --git a/PluralKit.Core/Database/Migrations/23.sql b/PluralKit.Core/Database/Migrations/23.sql new file mode 100644 index 00000000..cb9b2e65 --- /dev/null +++ b/PluralKit.Core/Database/Migrations/23.sql @@ -0,0 +1,6 @@ +-- schema version 23 +-- show/hide private information when looked up by linked accounts + +alter table system_config add column show_private_info bool default true; + +update info set schema_version = 23; \ No newline at end of file diff --git a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs index a9e990c8..0688ce09 100644 --- a/PluralKit.Core/Database/Utils/DatabaseMigrator.cs +++ b/PluralKit.Core/Database/Utils/DatabaseMigrator.cs @@ -9,7 +9,7 @@ namespace PluralKit.Core; internal class DatabaseMigrator { private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files - private const int TargetSchemaVersion = 22; + private const int TargetSchemaVersion = 23; private readonly ILogger _logger; public DatabaseMigrator(ILogger logger) diff --git a/PluralKit.Core/Models/Patch/SystemConfigPatch.cs b/PluralKit.Core/Models/Patch/SystemConfigPatch.cs index 2c32b41e..a65ee1a8 100644 --- a/PluralKit.Core/Models/Patch/SystemConfigPatch.cs +++ b/PluralKit.Core/Models/Patch/SystemConfigPatch.cs @@ -13,6 +13,7 @@ public class SystemConfigPatch: PatchObject public Partial LatchTimeout { get; set; } public Partial MemberDefaultPrivate { get; set; } public Partial GroupDefaultPrivate { get; set; } + public Partial ShowPrivateInfo { get; set; } public Partial MemberLimitOverride { get; set; } public Partial GroupLimitOverride { get; set; } @@ -22,6 +23,7 @@ public class SystemConfigPatch: PatchObject .With("latch_timeout", LatchTimeout) .With("member_default_private", MemberDefaultPrivate) .With("group_default_private", GroupDefaultPrivate) + .With("show_private_info", ShowPrivateInfo) .With("member_limit_override", MemberLimitOverride) .With("group_limit_override", GroupLimitOverride) ); @@ -51,6 +53,9 @@ public class SystemConfigPatch: PatchObject if (GroupDefaultPrivate.IsPresent) o.Add("group_default_private", GroupDefaultPrivate.Value); + if (ShowPrivateInfo.IsPresent) + o.Add("show_private_info", ShowPrivateInfo.Value); + if (MemberLimitOverride.IsPresent) o.Add("member_limit", MemberLimitOverride.Value); diff --git a/PluralKit.Core/Models/SystemConfig.cs b/PluralKit.Core/Models/SystemConfig.cs index 1f7f5875..905a3162 100644 --- a/PluralKit.Core/Models/SystemConfig.cs +++ b/PluralKit.Core/Models/SystemConfig.cs @@ -12,6 +12,7 @@ public class SystemConfig public int? LatchTimeout { get; } public bool MemberDefaultPrivate { get; } public bool GroupDefaultPrivate { get; } + public bool ShowPrivateInfo { get; } public int? MemberLimitOverride { get; } public int? GroupLimitOverride { get; } @@ -29,6 +30,7 @@ public static class SystemConfigExt o.Add("latch_timeout", cfg.LatchTimeout); o.Add("member_default_private", cfg.MemberDefaultPrivate); o.Add("group_default_private", cfg.GroupDefaultPrivate); + o.Add("show_private_info", cfg.ShowPrivateInfo); o.Add("member_limit", cfg.MemberLimitOverride ?? Limits.MaxMemberCount); o.Add("group_limit", cfg.GroupLimitOverride ?? Limits.MaxGroupCount); diff --git a/docs/content/api/models.md b/docs/content/api/models.md index a2cf3e10..480675dd 100644 --- a/docs/content/api/models.md +++ b/docs/content/api/models.md @@ -108,6 +108,7 @@ Every PluralKit entity has two IDs: a short (5-character) ID and a longer UUID. |latch_timeout|int?| |member_default_private*|bool|whether members created through the bot have privacy settings set to private by default| |group_default_private*|bool|whether groups created through the bot have privacy settings set to private by default| +|show_private_info|bool|whether the bot shows the system's own private information without a `-private` flag| |member_limit|int|read-only, defaults to 1000| |group_limit|int|read-only, defaults to 250| diff --git a/docs/content/tips-and-tricks.md b/docs/content/tips-and-tricks.md index b22198c3..8095982d 100644 --- a/docs/content/tips-and-tricks.md +++ b/docs/content/tips-and-tricks.md @@ -49,8 +49,7 @@ There are a number of option flags that can be added to the `pk;system list` com |Flag|Aliases|Description| |---|---|---| |-all|-a|Show all members, including private members| -|-public-only|-public, -pub|Only show public members (default)| -|-private-only|-private, -priv|Only show private members| +|-private-only|-po|Only show private members| ::: warning You cannot look up private members of another system. @@ -80,4 +79,6 @@ These flags only work with the full member list (`pk;system list full`). |pk;group \ frontpercent|-flat||Show "flat" frontpercent - percentages add up to 100%| |Most commands|-all|-a|Show hidden/private information| |Most commands|-raw|-r|Show text with formatting, for easier copy-pasting| +|All commands|-private|-priv|Show private information| +|All commands|-public|-pub|Hide private information| |All commands, except `delete`|-y|-yes|Skip confirmation prompt|