Add system and member privacy support
This commit is contained in:
@@ -22,6 +22,7 @@ namespace PluralKit.Bot.Commands
|
||||
public static Command SystemFronter = new Command("system fronter", "system [system] fronter", "Shows a system's fronter(s)");
|
||||
public static Command SystemFrontHistory = new Command("system fronthistory", "system [system] fronthistory", "Shows a system's front history");
|
||||
public static Command SystemFrontPercent = new Command("system frontpercent", "system [system] frontpercent [timespan]", "Shows a system's front breakdown");
|
||||
public static Command SystemPrivacy = new Command("system privacy", "system [system] privacy <description|members|fronter|fronthistory> <public|private>", "Changes your system's privacy settings");
|
||||
public static Command MemberInfo = new Command("member", "member <member>", "Looks up information about a member");
|
||||
public static Command MemberNew = new Command("member new", "member new <name>", "Creates a new member");
|
||||
public static Command MemberRename = new Command("member rename", "member <member> rename <new name>", "Renames a member");
|
||||
@@ -36,6 +37,7 @@ namespace PluralKit.Bot.Commands
|
||||
public static Command MemberServerName = new Command("member servername", "member <member> servername [server name]", "Changes a member's display name in the current server");
|
||||
public static Command MemberKeepProxy = new Command("member keepproxy", "member <member> keepproxy [on|off]", "Sets whether to include a member's proxy tags when proxying");
|
||||
public static Command MemberRandom = new Command("random", "random", "Gets a random member from your system");
|
||||
public static Command MemberPrivacy = new Command("member privacy", "member <member> privacy [on|off]", "Sets whether a member is private or public");
|
||||
public static Command Switch = new Command("switch", "switch <member> [member 2] [member 3...]", "Registers a switch");
|
||||
public static Command SwitchOut = new Command("switch out", "switch out", "Registers a switch with no members");
|
||||
public static Command SwitchMove = new Command("switch move", "switch move <date/time>", "Moves the latest switch in time");
|
||||
@@ -58,7 +60,7 @@ namespace PluralKit.Bot.Commands
|
||||
|
||||
public static Command[] SystemCommands = {
|
||||
SystemInfo, SystemNew, SystemRename, SystemTag, SystemDesc, SystemAvatar, SystemDelete, SystemTimezone,
|
||||
SystemList, SystemFronter, SystemFrontHistory, SystemFrontPercent
|
||||
SystemList, SystemFronter, SystemFrontHistory, SystemFrontPercent, SystemPrivacy
|
||||
};
|
||||
|
||||
public static Command[] MemberCommands = {
|
||||
@@ -185,6 +187,8 @@ namespace PluralKit.Bot.Commands
|
||||
await ctx.Execute<SystemCommands>(SystemFrontHistory, m => m.SystemFrontHistory(ctx, ctx.System));
|
||||
else if (ctx.Match("fp", "frontpercent", "front%", "frontbreakdown"))
|
||||
await ctx.Execute<SystemCommands>(SystemFrontPercent, m => m.SystemFrontPercent(ctx, ctx.System));
|
||||
else if (ctx.Match("privacy"))
|
||||
await ctx.Execute<SystemCommands>(SystemPrivacy, m => m.SystemPrivacy(ctx));
|
||||
else if (ctx.Match("commands", "help"))
|
||||
await PrintCommandList(ctx, "systems", SystemCommands);
|
||||
else if (!ctx.HasNext()) // Bare command
|
||||
@@ -272,6 +276,8 @@ namespace PluralKit.Bot.Commands
|
||||
await ctx.Execute<MemberCommands>(MemberServerName, m => m.MemberServerName(ctx, target));
|
||||
else if (ctx.Match("keepproxy", "keeptags", "showtags"))
|
||||
await ctx.Execute<MemberCommands>(MemberKeepProxy, m => m.MemberKeepProxy(ctx, target));
|
||||
else if (ctx.Match("private", "privacy", "hidden"))
|
||||
await ctx.Execute<MemberCommands>(MemberPrivacy, m => m.MemberPrivacy(ctx, target));
|
||||
else if (!ctx.HasNext()) // Bare command
|
||||
await ctx.Execute<MemberCommands>(MemberInfo, m => m.ViewMember(ctx, target));
|
||||
else
|
||||
|
@@ -38,7 +38,7 @@ namespace PluralKit.Bot.Commands
|
||||
}
|
||||
|
||||
// Enforce per-system member limit
|
||||
var memberCount = await _data.GetSystemMemberCount(ctx.System);
|
||||
var memberCount = await _data.GetSystemMemberCount(ctx.System, true);
|
||||
if (memberCount >= Limits.MaxMemberCount)
|
||||
throw Errors.MemberLimitReachedError;
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace PluralKit.Bot.Commands
|
||||
if (members == null || !members.Any())
|
||||
throw Errors.NoMembersError;
|
||||
var randInt = randGen.Next(members.Count);
|
||||
await ctx.Reply(embed: await _embeds.CreateMemberEmbed(ctx.System, members[randInt], ctx.Guild));
|
||||
await ctx.Reply(embed: await _embeds.CreateMemberEmbed(ctx.System, members[randInt], ctx.Guild, ctx.LookupContextFor(ctx.System)));
|
||||
|
||||
}
|
||||
|
||||
@@ -429,11 +429,31 @@ namespace PluralKit.Bot.Commands
|
||||
await ctx.Reply($"{Emojis.Success} Member proxy tags will now not be included in the resulting message when proxying.");
|
||||
await _proxyCache.InvalidateResultsForSystem(ctx.System);
|
||||
}
|
||||
|
||||
|
||||
public async Task MemberPrivacy(Context ctx, PKMember target)
|
||||
{
|
||||
if (ctx.System == null) throw Errors.NoSystemError;
|
||||
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
|
||||
|
||||
bool newValue;
|
||||
if (ctx.Match("private", "hide", "hidden", "on", "enable", "yes")) newValue = true;
|
||||
else if (ctx.Match("public", "show", "shown", "displayed", "off", "disable", "no")) newValue = false;
|
||||
else if (ctx.HasNext()) throw new PKSyntaxError("You must pass either \"private\" or \"public\".");
|
||||
else newValue = target.MemberPrivacy != PrivacyLevel.Private;
|
||||
|
||||
target.MemberPrivacy = newValue ? PrivacyLevel.Private : PrivacyLevel.Public;
|
||||
await _data.SaveMember(target);
|
||||
|
||||
if (newValue)
|
||||
await ctx.Reply($"{Emojis.Success} Member privacy set to **private**. This member will no longer show up in member lists and will return limited information when queried by other accounts.");
|
||||
else
|
||||
await ctx.Reply($"{Emojis.Success} Member privacy set to **public**. This member will now show up in member lists and will return all information when queried by other accounts.");
|
||||
}
|
||||
|
||||
public async Task ViewMember(Context ctx, PKMember target)
|
||||
{
|
||||
var system = await _data.GetSystemById(target.System);
|
||||
await ctx.Reply(embed: await _embeds.CreateMemberEmbed(system, target, ctx.Guild));
|
||||
await ctx.Reply(embed: await _embeds.CreateMemberEmbed(system, target, ctx.Guild, ctx.LookupContextFor(system)));
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user