diff --git a/PluralKit.API/Controllers/v1/JsonModelExt.cs b/PluralKit.API/Controllers/v1/JsonModelExt.cs index ee2c4132..1e10d6d3 100644 --- a/PluralKit.API/Controllers/v1/JsonModelExt.cs +++ b/PluralKit.API/Controllers/v1/JsonModelExt.cs @@ -14,7 +14,7 @@ namespace PluralKit.API var o = new JObject(); o.Add("id", system.Hid); o.Add("name", system.Name); - o.Add("description", system.DescriptionPrivacy.CanAccess(ctx) ? system.Description : null); + o.Add("description", system.DescriptionFor(ctx)); o.Add("tag", system.Tag); o.Add("avatar_url", system.AvatarUrl); o.Add("created", DateTimeFormats.TimestampExportFormat.Format(system.Created)); @@ -22,7 +22,7 @@ namespace PluralKit.API o.Add("description_privacy", ctx == LookupContext.ByOwner ? system.DescriptionPrivacy.ToJsonString() : null); o.Add("member_list_privacy", ctx == LookupContext.ByOwner ? system.MemberListPrivacy.ToJsonString() : null); o.Add("front_privacy", ctx == LookupContext.ByOwner ? system.FrontPrivacy.ToJsonString() : null); - o.Add("front_history_privacy", ctx == LookupContext.ByOwner ? ctx == LookupContext.ByOwner ? system.FrontHistoryPrivacy.ToJsonString() : null : null); + o.Add("front_history_privacy", ctx == LookupContext.ByOwner ? system.FrontHistoryPrivacy.ToJsonString() : null); return o; } @@ -42,16 +42,20 @@ namespace PluralKit.API public static JObject ToJson(this PKMember member, LookupContext ctx) { + var bday = member.BirthdayFor(ctx); + var created = member.CreatedFor(ctx); + var includePrivacy = ctx == LookupContext.ByOwner; + var o = new JObject(); o.Add("id", member.Hid); o.Add("name", member.NameFor(ctx)); // o.Add("color", member.ColorPrivacy.CanAccess(ctx) ? member.Color : null); o.Add("color", member.Color); o.Add("display_name", member.NamePrivacy.CanAccess(ctx) ? member.DisplayName : null); - o.Add("birthday", member.BirthdayPrivacy.CanAccess(ctx) && member.Birthday.HasValue ? DateTimeFormats.DateExportFormat.Format(member.Birthday.Value) : null); - o.Add("pronouns", member.PronounPrivacy.CanAccess(ctx) ? member.Pronouns : null); - o.Add("avatar_url", member.AvatarPrivacy.CanAccess(ctx) ? member.AvatarUrl : null); - o.Add("description", member.DescriptionPrivacy.CanAccess(ctx) ? member.Description : null); + o.Add("birthday", bday.HasValue ? DateTimeFormats.DateExportFormat.Format(bday.Value) : null); + o.Add("pronouns", member.PronounsFor(ctx)); + o.Add("avatar_url", member.AvatarFor(ctx)); + o.Add("description", member.DescriptionFor(ctx)); var tagArray = new JArray(); foreach (var tag in member.ProxyTags) @@ -59,23 +63,19 @@ namespace PluralKit.API o.Add("proxy_tags", tagArray); o.Add("keep_proxy", member.KeepProxy); - - o.Add("privacy", ctx == LookupContext.ByOwner ? (member.MemberVisibility == PrivacyLevel.Private ? "private" : "public") : null); - - o.Add("visibility", ctx == LookupContext.ByOwner ? (member.MemberVisibility == PrivacyLevel.Private ? "private" : "public") : null); - o.Add("name_privacy", ctx == LookupContext.ByOwner ? (member.NamePrivacy == PrivacyLevel.Private ? "private" : "public") : null); - o.Add("description_privacy", ctx == LookupContext.ByOwner ? (member.DescriptionPrivacy == PrivacyLevel.Private ? "private" : "public") : null); - o.Add("birthday_privacy", ctx == LookupContext.ByOwner ? (member.BirthdayPrivacy == PrivacyLevel.Private ? "private" : "public") : null); - o.Add("pronoun_privacy", ctx == LookupContext.ByOwner ? (member.PronounPrivacy == PrivacyLevel.Private ? "private" : "public") : null); - o.Add("avatar_privacy", ctx == LookupContext.ByOwner ? (member.AvatarPrivacy == PrivacyLevel.Private ? "private" : "public") : null); - // o.Add("color_privacy", ctx == LookupContext.ByOwner ? (member.ColorPrivacy == PrivacyLevel.Private ? "private" : "public") : null); - o.Add("metadata_privacy", ctx == LookupContext.ByOwner ? (member.MetadataPrivacy == PrivacyLevel.Private ? "private" : "public") : null); - - if(member.MetadataPrivacy.CanAccess(ctx)) - o.Add("created", DateTimeFormats.TimestampExportFormat.Format(member.Created)); - else - o.Add("created", null); + o.Add("privacy", includePrivacy ? (member.MemberVisibility.LevelName()) : null); + + o.Add("visibility", includePrivacy ? (member.MemberVisibility.LevelName()) : null); + o.Add("name_privacy", includePrivacy ? (member.NamePrivacy.LevelName()) : null); + o.Add("description_privacy", includePrivacy ? (member.DescriptionPrivacy.LevelName()) : null); + o.Add("birthday_privacy", includePrivacy ? (member.BirthdayPrivacy.LevelName()) : null); + o.Add("pronoun_privacy", includePrivacy ? (member.PronounPrivacy.LevelName()) : null); + o.Add("avatar_privacy", includePrivacy ? (member.AvatarPrivacy.LevelName()) : null); + // o.Add("color_privacy", ctx == LookupContext.ByOwner ? (member.ColorPrivacy.LevelName()) : null); + o.Add("metadata_privacy", includePrivacy ? (member.MetadataPrivacy.LevelName()) : null); + + o.Add("created", created.HasValue ? DateTimeFormats.TimestampExportFormat.Format(created.Value) : null); if (member.ProxyTags.Count > 0) { @@ -150,7 +150,7 @@ namespace PluralKit.API return input; } - private static string ToJsonString(this PrivacyLevel level) => level == PrivacyLevel.Private ? "private" : "public"; + private static string ToJsonString(this PrivacyLevel level) => level.LevelName(); private static PrivacyLevel ParsePrivacy(this string input, string errorName) { diff --git a/PluralKit.Bot/Commands/MemberEdit.cs b/PluralKit.Bot/Commands/MemberEdit.cs index 6f3aecdd..c109902e 100644 --- a/PluralKit.Bot/Commands/MemberEdit.cs +++ b/PluralKit.Bot/Commands/MemberEdit.cs @@ -455,7 +455,7 @@ namespace PluralKit.Bot _ => throw new InvalidOperationException($"Invalid subject/level tuple ({subject}, {newLevel})") }; - await ctx.Reply($"{Emojis.Success} {target.NameFor(ctx)}'s {subject.Name()} has been set to **{newLevel.Name()}**. {explanation}"); + await ctx.Reply($"{Emojis.Success} {target.NameFor(ctx)}'s {subject.Name()} has been set to **{newLevel.LevelName()}**. {explanation}"); } else if (ctx.Match("all") || newValueFromCommand != null) { @@ -464,9 +464,9 @@ namespace PluralKit.Bot await _data.SaveMember(target); if(newLevel == PrivacyLevel.Private) - await ctx.Reply($"All {target.NameFor(ctx)}'s privacy settings have been set to **{newLevel.Name()}**. Other accounts will now see nothing on the member card."); + await ctx.Reply($"All {target.NameFor(ctx)}'s privacy settings have been set to **{newLevel.LevelName()}**. Other accounts will now see nothing on the member card."); else - await ctx.Reply($"All {target.NameFor(ctx)}'s privacy settings have been set to **{newLevel.Name()}**. Other accounts will now see everything on the member card."); + await ctx.Reply($"All {target.NameFor(ctx)}'s privacy settings have been set to **{newLevel.LevelName()}**. Other accounts will now see everything on the member card."); } else { diff --git a/PluralKit.Bot/Lists/LongRenderer.cs b/PluralKit.Bot/Lists/LongRenderer.cs index 1f9cd318..b677f573 100644 --- a/PluralKit.Bot/Lists/LongRenderer.cs +++ b/PluralKit.Bot/Lists/LongRenderer.cs @@ -28,15 +28,14 @@ namespace PluralKit.Bot { var profile = $"**ID**: {m.Hid}"; if (_fields.ShowDisplayName && m.DisplayName != null && m.NamePrivacy.CanAccess(ctx)) profile += $"\n**Display name**: {m.DisplayName}"; - if (_fields.ShowPronouns && m.Pronouns != null && m.PronounPrivacy.CanAccess(ctx)) profile += $"\n**Pronouns**: {m.Pronouns}"; - if (_fields.ShowBirthday && m.Birthday != null && m.BirthdayPrivacy.CanAccess(ctx)) profile += $"\n**Birthdate**: {m.BirthdayString}"; + if (_fields.ShowPronouns && m.PronounsFor(ctx) is {} pronouns) profile += $"\n**Pronouns**: {pronouns}"; + if (_fields.ShowBirthday && m.BirthdayFor(ctx) != null) profile += $"\n**Birthdate**: {m.BirthdayString}"; if (_fields.ShowProxyTags && m.ProxyTags.Count > 0) profile += $"\n**Proxy tags:** {m.ProxyTagsString()}"; - if (_fields.ShowMessageCount && m.MessageCount > 0 && m.MetadataPrivacy.CanAccess(ctx)) profile += $"\n**Message count:** {m.MessageCount}"; - if (_fields.ShowLastMessage && m.LastMessage != null && m.MetadataPrivacy.CanAccess(ctx)) profile += $"\n**Last message:** {FormatTimestamp(DiscordUtils.SnowflakeToInstant(m.LastMessage.Value))}"; - if (_fields.ShowLastSwitch && m.LastSwitchTime != null && m.MetadataPrivacy.CanAccess(ctx)) profile += $"\n**Last switched in:** {FormatTimestamp(m.LastSwitchTime.Value)}"; - if (_fields.ShowDescription && m.Description != null && m.DescriptionPrivacy.CanAccess(ctx)) profile += $"\n\n{m.Description}"; - if (_fields.ShowPrivacy && m.MemberVisibility == PrivacyLevel.Private) - profile += "\n*(this member is hidden)*"; + if (_fields.ShowMessageCount && m.MessageCountFor(ctx) is {} count && count > 0) profile += $"\n**Message count:** {count}"; + if (_fields.ShowLastMessage && m.MetadataPrivacy.TryGet(ctx, m.LastMessage, out var lastMsg)) profile += $"\n**Last message:** {FormatTimestamp(DiscordUtils.SnowflakeToInstant(lastMsg.Value))}"; + if (_fields.ShowLastSwitch && m.MetadataPrivacy.TryGet(ctx, m.LastSwitchTime, out var lastSw)) profile += $"\n**Last switched in:** {FormatTimestamp(lastSw.Value)}"; + if (_fields.ShowDescription && m.DescriptionFor(ctx) is {} desc) profile += $"\n\n{desc}"; + if (_fields.ShowPrivacy && m.MemberVisibility == PrivacyLevel.Private) profile += "\n*(this member is hidden)*"; eb.AddField(m.NameFor(ctx), profile.Truncate(1024)); } diff --git a/PluralKit.Bot/Services/EmbedService.cs b/PluralKit.Bot/Services/EmbedService.cs index dd964411..f95aa9c6 100644 --- a/PluralKit.Bot/Services/EmbedService.cs +++ b/PluralKit.Bot/Services/EmbedService.cs @@ -61,8 +61,8 @@ namespace PluralKit.Bot { eb.AddField($"Members ({memberCount})", "Add one with `pk;member new`!", true); } - if (system.Description != null && system.DescriptionPrivacy.CanAccess(ctx)) - eb.AddField("Description", system.Description.NormalizeLineEndSpacing().Truncate(1024), false); + if (system.DescriptionFor(ctx) is { } desc) + eb.AddField("Description", desc.NormalizeLineEndSpacing().Truncate(1024), false); return eb.Build(); } @@ -127,9 +127,9 @@ namespace PluralKit.Bot { if (!member.DisplayName.EmptyOrNull() && member.NamePrivacy.CanAccess(ctx)) eb.AddField("Display Name", member.DisplayName.Truncate(1024), true); if (guild != null && guildDisplayName != null) eb.AddField($"Server Nickname (for {guild.Name})", guildDisplayName.Truncate(1024), true); - if (member.Birthday != null && member.BirthdayPrivacy.CanAccess(ctx)) eb.AddField("Birthdate", member.BirthdayString, true); - if (!member.Pronouns.EmptyOrNull() && member.PronounPrivacy.CanAccess(ctx)) eb.AddField("Pronouns", member.Pronouns.Truncate(1024), true); - if (member.MessageCount > 0 && member.MetadataPrivacy.CanAccess(ctx)) eb.AddField("Message Count", member.MessageCount.ToString(), true); + if (member.BirthdayFor(ctx) != null) eb.AddField("Birthdate", member.BirthdayString, true); + if (member.PronounsFor(ctx) is {} pronouns) eb.AddField("Pronouns", pronouns.Truncate(1024), true); + if (member.MessageCountFor(ctx) is {} count && count > 0) eb.AddField("Message Count", member.MessageCount.ToString(), true); if (member.HasProxyTags) eb.AddField("Proxy Tags", string.Join('\n', proxyTagsStr).Truncate(1024), true); // --- For when this gets added to the member object itself or however they get added // if (member.LastMessage != null && member.MetadataPrivacy.CanAccess(ctx)) eb.AddField("Last message:" FormatTimestamp(DiscordUtils.SnowflakeToInstant(m.LastMessage.Value))); @@ -137,7 +137,7 @@ namespace PluralKit.Bot { // if (!member.Color.EmptyOrNull() && member.ColorPrivacy.CanAccess(ctx)) eb.AddField("Color", $"#{member.Color}", true); if (!member.Color.EmptyOrNull()) eb.AddField("Color", $"#{member.Color}", true); - if (!member.Description.EmptyOrNull() && member.DescriptionPrivacy.CanAccess(ctx)) eb.AddField("Description", member.Description.NormalizeLineEndSpacing(), false); + if (member.DescriptionFor(ctx) is {} desc) eb.AddField("Description", member.Description.NormalizeLineEndSpacing(), false); return eb.Build(); } diff --git a/PluralKit.Core/Models/ModelExtensions.cs b/PluralKit.Core/Models/ModelExtensions.cs index 47d2cc61..6092fa24 100644 --- a/PluralKit.Core/Models/ModelExtensions.cs +++ b/PluralKit.Core/Models/ModelExtensions.cs @@ -1,11 +1,31 @@ -namespace PluralKit.Core +using NodaTime; + +namespace PluralKit.Core { public static class ModelExtensions { - public static string NameFor(this PKMember member, LookupContext ctx) => - member.NamePrivacy.CanAccess(ctx) ? member.Name : member.DisplayName ?? member.Name; + public static string DescriptionFor(this PKSystem system, LookupContext ctx) => + system.DescriptionPrivacy.Get(ctx, system.Description); + + public static string NameFor(this PKMember member, LookupContext ctx) => + member.NamePrivacy.Get(ctx, member.Name, member.DisplayName ?? member.Name); public static string AvatarFor(this PKMember member, LookupContext ctx) => - member.AvatarPrivacy.CanAccess(ctx) ? member.AvatarUrl : null; + member.AvatarPrivacy.Get(ctx, member.AvatarUrl); + + public static string DescriptionFor(this PKMember member, LookupContext ctx) => + member.DescriptionPrivacy.Get(ctx, member.Description); + + public static LocalDate? BirthdayFor(this PKMember member, LookupContext ctx) => + member.BirthdayPrivacy.Get(ctx, member.Birthday); + + public static string PronounsFor(this PKMember member, LookupContext ctx) => + member.PronounPrivacy.Get(ctx, member.Pronouns); + + public static Instant? CreatedFor(this PKMember member, LookupContext ctx) => + member.MetadataPrivacy.Get(ctx, (Instant?) member.Created); + + public static int MessageCountFor(this PKMember member, LookupContext ctx) => + member.MetadataPrivacy.Get(ctx, member.MessageCount); } } \ No newline at end of file diff --git a/PluralKit.Core/Models/Privacy.cs b/PluralKit.Core/Models/Privacy.cs index 54579a98..dcd32e5e 100644 --- a/PluralKit.Core/Models/Privacy.cs +++ b/PluralKit.Core/Models/Privacy.cs @@ -11,8 +11,23 @@ public static bool CanAccess(this PrivacyLevel level, LookupContext ctx) => level == PrivacyLevel.Public || ctx == LookupContext.ByOwner; - public static string Name(this PrivacyLevel level) => + public static string LevelName(this PrivacyLevel level) => level == PrivacyLevel.Public ? "public" : "private"; + + public static T Get(this PrivacyLevel level, LookupContext ctx, T input, T fallback = default) => + level.CanAccess(ctx) ? input : fallback; + + public static bool TryGet(this PrivacyLevel level, LookupContext ctx, T input, out T output, T absentValue = default) + { + output = default; + if (!level.CanAccess(ctx)) + return false; + if (Equals(input, absentValue)) + return false; + + output = input; + return true; + } } public enum LookupContext diff --git a/PluralKit.Core/Utils/PrivacyUtils.cs b/PluralKit.Core/Utils/PrivacyUtils.cs index 8cbe079b..c3b7312b 100644 --- a/PluralKit.Core/Utils/PrivacyUtils.cs +++ b/PluralKit.Core/Utils/PrivacyUtils.cs @@ -75,6 +75,8 @@ namespace PluralKit.Core case "birthday": case "birth": case "bday": + case "birthdate": + case "bdate": subject = MemberPrivacySubject.Birthday; break; case "pronouns":