Add system and member privacy support

This commit is contained in:
Ske
2020-01-11 16:49:20 +01:00
parent f0cc5c5961
commit 98613c4287
17 changed files with 317 additions and 59 deletions

View File

@@ -29,7 +29,7 @@ namespace PluralKit.Bot.Commands
public async Task Query(Context ctx, PKSystem system) {
if (system == null) throw Errors.NoSystemError;
await ctx.Reply(embed: await _embeds.CreateSystemEmbed(system));
await ctx.Reply(embed: await _embeds.CreateSystemEmbed(system, ctx.LookupContextFor(system)));
}
public async Task New(Context ctx)
@@ -149,27 +149,57 @@ namespace PluralKit.Bot.Commands
public async Task MemberShortList(Context ctx, PKSystem system) {
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.MemberListPrivacy);
var authCtx = ctx.LookupContextFor(system);
var shouldShowPrivate = authCtx == LookupContext.ByOwner && ctx.Match("all", "everyone", "private");
var members = await _data.GetSystemMembers(system);
var members = (await _data.GetSystemMembers(system)).ToList();
var embedTitle = system.Name != null ? $"Members of {system.Name.SanitizeMentions()} (`{system.Hid}`)" : $"Members of `{system.Hid}`";
await ctx.Paginate<PKMember>(
members.OrderBy(m => m.Name, StringComparer.InvariantCultureIgnoreCase).ToList(),
var membersToDisplay = members
.Where(m => m.MemberPrivacy == PrivacyLevel.Public || shouldShowPrivate)
.OrderBy(m => m.Name, StringComparer.InvariantCultureIgnoreCase).ToList();
var anyMembersHidden = members.Any(m => m.MemberPrivacy == PrivacyLevel.Private && !shouldShowPrivate);
await ctx.Paginate(
membersToDisplay,
25,
embedTitle,
(eb, ms) => eb.Description = string.Join("\n", ms.Select((m) => {
if (m.HasProxyTags) return $"[`{m.Hid}`] **{m.Name.SanitizeMentions()}** *({m.ProxyTagsString().SanitizeMentions()})*";
return $"[`{m.Hid}`] **{m.Name.SanitizeMentions()}**";
}))
);
(eb, ms) =>
{
eb.Description = string.Join("\n", ms.Select((m) =>
{
if (m.HasProxyTags)
return
$"[`{m.Hid}`] **{m.Name.SanitizeMentions()}** *({m.ProxyTagsString().SanitizeMentions()})*";
return $"[`{m.Hid}`] **{m.Name.SanitizeMentions()}**";
}));
var footer = $"{membersToDisplay.Count} total.";
if (anyMembersHidden && authCtx == LookupContext.ByOwner)
footer += "Private members have been hidden. type \"pk;system list all\" to include them.";
eb.WithFooter(footer);
});
}
public async Task MemberLongList(Context ctx, PKSystem system) {
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.MemberListPrivacy);
var authCtx = ctx.LookupContextFor(system);
var shouldShowPrivate = authCtx == LookupContext.ByOwner && ctx.Match("all", "everyone", "private");
var members = await _data.GetSystemMembers(system);
var members = (await _data.GetSystemMembers(system)).ToList();
var embedTitle = system.Name != null ? $"Members of {system.Name} (`{system.Hid}`)" : $"Members of `{system.Hid}`";
await ctx.Paginate<PKMember>(
members.OrderBy(m => m.Name, StringComparer.InvariantCultureIgnoreCase).ToList(),
var membersToDisplay = members
.Where(m => m.MemberPrivacy == PrivacyLevel.Public || shouldShowPrivate)
.OrderBy(m => m.Name, StringComparer.InvariantCultureIgnoreCase).ToList();
var anyMembersHidden = members.Any(m => m.MemberPrivacy == PrivacyLevel.Private && !shouldShowPrivate);
await ctx.Paginate(
membersToDisplay,
5,
embedTitle,
(eb, ms) => {
@@ -179,8 +209,16 @@ namespace PluralKit.Bot.Commands
if (m.Birthday != null) profile += $"\n**Birthdate**: {m.BirthdayString}";
if (m.ProxyTags.Count > 0) profile += $"\n**Proxy tags:** {m.ProxyTagsString()}";
if (m.Description != null) profile += $"\n\n{m.Description}";
if (m.MemberPrivacy == PrivacyLevel.Private)
profile += "*(this member is private)*";
eb.AddField(m.Name, profile.Truncate(1024));
}
var footer = $"{membersToDisplay.Count} total.";
if (anyMembersHidden && authCtx == LookupContext.ByOwner)
footer += " Private members have been hidden. type \"pk;system list full all\" to include them.";
eb.WithFooter(footer);
}
);
}
@@ -188,6 +226,7 @@ namespace PluralKit.Bot.Commands
public async Task SystemFronter(Context ctx, PKSystem system)
{
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.FrontPrivacy);
var sw = await _data.GetLatestSwitch(system);
if (sw == null) throw Errors.NoRegisteredSwitches;
@@ -198,6 +237,7 @@ namespace PluralKit.Bot.Commands
public async Task SystemFrontHistory(Context ctx, PKSystem system)
{
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy);
var sws = (await _data.GetSwitches(system, 10)).ToList();
if (sws.Count == 0) throw Errors.NoRegisteredSwitches;
@@ -208,6 +248,7 @@ namespace PluralKit.Bot.Commands
public async Task SystemFrontPercent(Context ctx, PKSystem system)
{
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy);
string durationStr = ctx.RemainderOrNull() ?? "30d";
@@ -267,6 +308,80 @@ namespace PluralKit.Bot.Commands
await ctx.Reply($"System time zone changed to {zone.Id}.");
}
public async Task SystemPrivacy(Context ctx)
{
ctx.CheckSystem();
if (!ctx.HasNext())
{
string PrivacyLevelString(PrivacyLevel level) => level switch
{
PrivacyLevel.Private => "**Private** (visible only when queried by you)",
PrivacyLevel.Public => "**Public** (visible to everyone)",
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
var eb = new EmbedBuilder()
.WithTitle("Current privacy settings for your system")
.AddField("Description", PrivacyLevelString(ctx.System.DescriptionPrivacy))
.AddField("Member list", PrivacyLevelString(ctx.System.MemberListPrivacy))
.AddField("Current fronter(s)", PrivacyLevelString(ctx.System.FrontPrivacy))
.AddField("Front/switch history", PrivacyLevelString(ctx.System.FrontHistoryPrivacy))
.WithDescription("To edit privacy settings, use the command:\n`pk;system privacy <subject> <level>`\n\n- `subject` is one of `description`, `list`, `front` or `fronthistory`\n- `level` is either `public` or `private`.");
await ctx.Reply(embed: eb.Build());
return;
}
PrivacyLevel PopPrivacyLevel(string subject, out string levelStr, out string levelExplanation)
{
if (ctx.Match("public", "show", "shown", "visible"))
{
levelStr = "public";
levelExplanation = "be able to query";
return PrivacyLevel.Public;
}
if (ctx.Match("private", "hide", "hidden"))
{
levelStr = "private";
levelExplanation = "*not* be able to query";
return PrivacyLevel.Private;
}
if (!ctx.HasNext())
throw new PKSyntaxError($"You must pass a privacy level for `{subject}` (`public` or `private`)");
throw new PKSyntaxError($"Invalid privacy level `{ctx.PopArgument().SanitizeMentions()}` (must be `public` or `private`).");
}
string levelStr, levelExplanation, subjectStr;
var subjectList = "`description`, `members`, `front` or `fronthistory`";
if (ctx.Match("description", "desc", "text", "info"))
{
subjectStr = "description";
ctx.System.DescriptionPrivacy = PopPrivacyLevel("description", out levelStr, out levelExplanation);
}
else if (ctx.Match("members", "memberlist", "list", "mlist"))
{
subjectStr = "member list";
ctx.System.MemberListPrivacy = PopPrivacyLevel("members", out levelStr, out levelExplanation);
}
else if (ctx.Match("front", "fronter"))
{
subjectStr = "fronter(s)";
ctx.System.FrontPrivacy = PopPrivacyLevel("front", out levelStr, out levelExplanation);
}
else if (ctx.Match("switch", "switches", "fronthistory", "fh"))
{
subjectStr = "front history";
ctx.System.FrontHistoryPrivacy = PopPrivacyLevel("fronthistory", out levelStr, out levelExplanation);
}
else
throw new PKSyntaxError($"Invalid privacy subject `{ctx.PopArgument().SanitizeMentions()}` (must be {subjectList}).");
await _data.SaveSystem(ctx.System);
await ctx.Reply($"System {subjectStr} privacy has been set to **{levelStr}**. Other accounts will now {levelExplanation} your system {subjectStr}.");
}
public async Task<DateTimeZone> FindTimeZone(Context ctx, string zoneStr) {
// First, if we're given a flag emoji, we extract the flag emoji code from it.
zoneStr = PluralKit.Utils.ExtractCountryFlag(zoneStr) ?? zoneStr;