PluralKit/PluralKit.Bot/Commands/MemberEdit.cs

512 lines
25 KiB
C#
Raw Normal View History

2020-03-04 17:13:36 +00:00
using System.Text.RegularExpressions;
2020-02-01 12:03:02 +00:00
using System.Threading.Tasks;
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
using System;
2020-02-01 12:03:02 +00:00
using Dapper;
2020-02-27 23:23:54 +00:00
using DSharpPlus.Entities;
2020-02-01 12:03:02 +00:00
using PluralKit.Core;
namespace PluralKit.Bot
2020-02-01 12:03:02 +00:00
{
public class MemberEdit
{
private readonly IDataStore _data;
2020-06-13 17:36:43 +00:00
private readonly IDatabase _db;
2020-02-01 12:03:02 +00:00
2020-06-13 17:36:43 +00:00
public MemberEdit(IDataStore data, IDatabase db)
2020-02-01 12:03:02 +00:00
{
_data = data;
_db = db;
2020-02-01 12:03:02 +00:00
}
public async Task Name(Context ctx, PKMember target) {
// TODO: this method is pretty much a 1:1 copy/paste of the above creation method, find a way to clean?
if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
var newName = ctx.RemainderOrNull() ?? throw new PKSyntaxError("You must pass a new name for the member.");
// Hard name length cap
if (newName.Length > Limits.MaxMemberNameLength) throw Errors.MemberNameTooLongError(newName.Length);
// Warn if there's already a member by this name
var existingMember = await _data.GetMemberByName(ctx.System, newName);
if (existingMember != null) {
var msg = await ctx.Reply($"{Emojis.Warn} You already have a member in your system with the name \"{existingMember.Name.SanitizeMentions()}\" (`{existingMember.Hid}`). Do you want to rename this member to that name too?");
if (!await ctx.PromptYesNo(msg)) throw new PKError("Member renaming cancelled.");
}
// Rename the member
target.Name = newName;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member renamed.");
if (newName.Contains(" ")) await ctx.Reply($"{Emojis.Note} Note that this member's name now contains spaces. You will need to surround it with \"double quotes\" when using commands referring to it.");
if (target.DisplayName != null) await ctx.Reply($"{Emojis.Note} Note that this member has a display name set ({target.DisplayName.SanitizeMentions()}), and will be proxied using that name instead.");
if (ctx.Guild != null)
{
var memberGuildConfig = await _db.Execute(c => c.QueryOrInsertMemberGuildConfig(ctx.Guild.Id, target.Id));
2020-02-01 12:03:02 +00:00
if (memberGuildConfig.DisplayName != null)
await ctx.Reply($"{Emojis.Note} Note that this member has a server name set ({memberGuildConfig.DisplayName.SanitizeMentions()}) in this server ({ctx.Guild.Name.SanitizeMentions()}), and will be proxied using that name here.");
}
}
2020-03-04 17:13:36 +00:00
private void CheckEditMemberPermission(Context ctx, PKMember target)
{
if (target.System != ctx.System?.Id) throw Errors.NotOwnMemberError;
}
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
private static bool MatchClear(Context ctx) =>
ctx.Match("clear") || ctx.MatchFlag("c", "clear");
2020-02-27 23:23:54 +00:00
2020-03-04 17:13:36 +00:00
public async Task Description(Context ctx, PKMember target) {
if (MatchClear(ctx))
2020-02-27 23:23:54 +00:00
{
2020-03-04 17:13:36 +00:00
CheckEditMemberPermission(ctx, target);
target.Description = null;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member description cleared.");
}
else if (!ctx.HasNext())
{
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
throw Errors.LookupNotAllowed;
2020-02-27 23:23:54 +00:00
if (target.Description == null)
2020-03-04 17:13:36 +00:00
if (ctx.System?.Id == target.System)
await ctx.Reply($"This member does not have a description set. To set one, type `pk;member {target.Hid} description <description>`.");
2020-02-27 23:23:54 +00:00
else
await ctx.Reply("This member does not have a description set.");
else if (ctx.MatchFlag("r", "raw"))
await ctx.Reply($"```\n{target.Description.SanitizeMentions()}\n```");
2020-02-27 23:23:54 +00:00
else
2020-04-24 19:50:28 +00:00
await ctx.Reply(embed: new DiscordEmbedBuilder()
2020-02-27 23:23:54 +00:00
.WithTitle("Member description")
.WithDescription(target.Description)
2020-03-04 17:13:36 +00:00
.AddField("\u200B", $"To print the description with formatting, type `pk;member {target.Hid} description -raw`."
+ (ctx.System?.Id == target.System ? $" To clear it, type `pk;member {target.Hid} description -clear`." : ""))
2020-02-27 23:23:54 +00:00
.Build());
}
2020-03-04 17:13:36 +00:00
else
{
CheckEditMemberPermission(ctx, target);
2020-02-27 23:23:54 +00:00
2020-03-04 17:13:36 +00:00
var description = ctx.RemainderOrNull().NormalizeLineEndSpacing();
if (description.IsLongerThan(Limits.MaxDescriptionLength))
throw Errors.DescriptionTooLongError(description.Length);
target.Description = description;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member description changed.");
}
2020-02-01 12:03:02 +00:00
}
public async Task Pronouns(Context ctx, PKMember target) {
2020-03-04 17:13:36 +00:00
if (MatchClear(ctx))
{
CheckEditMemberPermission(ctx, target);
target.Pronouns = null;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member pronouns cleared.");
}
else if (!ctx.HasNext())
{
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
if (!target.PronounPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
throw Errors.LookupNotAllowed;
2020-03-04 17:13:36 +00:00
if (target.Pronouns == null)
if (ctx.System?.Id == target.System)
await ctx.Reply($"This member does not have pronouns set. To set some, type `pk;member {target.Hid} pronouns <pronouns>`.");
else
await ctx.Reply("This member does not have pronouns set.");
else
await ctx.Reply($"**{target.Name.SanitizeMentions()}**'s pronouns are **{target.Pronouns.SanitizeMentions()}**."
+ (ctx.System?.Id == target.System ? $" To clear them, type `pk;member {target.Hid} pronouns -clear`." : ""));
}
else
{
CheckEditMemberPermission(ctx, target);
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
var pronouns = ctx.RemainderOrNull().NormalizeLineEndSpacing();
if (pronouns.IsLongerThan(Limits.MaxPronounsLength))
throw Errors.MemberPronounsTooLongError(pronouns.Length);
target.Pronouns = pronouns;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member pronouns changed.");
}
2020-02-01 12:03:02 +00:00
}
public async Task Color(Context ctx, PKMember target)
{
var color = ctx.RemainderOrNull();
2020-03-04 17:13:36 +00:00
if (MatchClear(ctx))
2020-02-01 12:03:02 +00:00
{
2020-03-04 17:13:36 +00:00
CheckEditMemberPermission(ctx, target);
target.Color = null;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member color cleared.");
2020-02-01 12:03:02 +00:00
}
2020-03-04 17:13:36 +00:00
else if (!ctx.HasNext())
{
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
if (!target.ColorPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
throw Errors.LookupNotAllowed;
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
if (target.Color == null)
if (ctx.System?.Id == target.System)
await ctx.Reply(
$"This member does not have a color set. To set one, type `pk;member {target.Hid} color <color>`.");
else
await ctx.Reply("This member does not have a color set.");
else
2020-04-24 19:50:28 +00:00
await ctx.Reply(embed: new DiscordEmbedBuilder()
2020-03-04 17:13:36 +00:00
.WithTitle("Member color")
.WithColor(target.Color.ToDiscordColor().Value)
.WithThumbnailUrl($"https://fakeimg.pl/256x256/{target.Color}/?text=%20")
.WithDescription($"This member's color is **#{target.Color}**."
+ (ctx.System?.Id == target.System ? $" To clear it, type `pk;member {target.Hid} color -clear`." : ""))
.Build());
}
else
{
CheckEditMemberPermission(ctx, target);
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
if (color.StartsWith("#")) color = color.Substring(1);
if (!Regex.IsMatch(color, "^[0-9a-fA-F]{6}$")) throw Errors.InvalidColorError(color);
target.Color = color.ToLower();
await _data.SaveMember(target);
2020-04-24 19:50:28 +00:00
await ctx.Reply(embed: new DiscordEmbedBuilder()
2020-03-04 17:13:36 +00:00
.WithTitle($"{Emojis.Success} Member color changed.")
.WithColor(target.Color.ToDiscordColor().Value)
.WithThumbnailUrl($"https://fakeimg.pl/256x256/{target.Color}/?text=%20")
.Build());
}
2020-02-01 12:03:02 +00:00
}
public async Task Birthday(Context ctx, PKMember target)
{
2020-03-04 17:13:36 +00:00
if (MatchClear(ctx))
{
CheckEditMemberPermission(ctx, target);
target.Birthday = null;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member birthdate cleared.");
}
else if (!ctx.HasNext())
2020-02-01 12:03:02 +00:00
{
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
if (!target.BirthdayPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
throw Errors.LookupNotAllowed;
2020-03-04 17:13:36 +00:00
if (target.Birthday == null)
await ctx.Reply("This member does not have a birthdate set."
+ (ctx.System?.Id == target.System ? $" To set one, type `pk;member {target.Hid} birthdate <birthdate>`." : ""));
else
await ctx.Reply($"This member's birthdate is **{target.BirthdayString}**."
+ (ctx.System?.Id == target.System ? $" To clear it, type `pk;member {target.Hid} birthdate -clear`." : ""));
}
else
{
CheckEditMemberPermission(ctx, target);
var birthdayStr = ctx.RemainderOrNull();
var birthday = DateUtils.ParseDate(birthdayStr, true);
if (birthday == null) throw Errors.BirthdayParseError(birthdayStr);
target.Birthday = birthday;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member birthdate changed.");
2020-02-01 12:03:02 +00:00
}
}
2020-03-04 17:13:36 +00:00
2020-04-24 19:50:28 +00:00
private async Task<DiscordEmbedBuilder> CreateMemberNameInfoEmbed(Context ctx, PKMember target)
2020-03-04 17:13:36 +00:00
{
MemberGuildSettings memberGuildConfig = null;
if (ctx.Guild != null)
memberGuildConfig = await _db.Execute(c => c.QueryOrInsertMemberGuildConfig(ctx.Guild.Id, target.Id));
2020-02-01 12:03:02 +00:00
2020-04-24 19:50:28 +00:00
var eb = new DiscordEmbedBuilder().WithTitle($"Member names")
2020-03-04 17:13:36 +00:00
.WithFooter($"Member ID: {target.Hid} | Active name in bold. Server name overrides display name, which overrides base name.");
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
if (target.DisplayName == null && memberGuildConfig?.DisplayName == null)
eb.AddField($"Name", $"**{target.Name}**");
2020-02-01 12:03:02 +00:00
else
2020-03-04 17:13:36 +00:00
eb.AddField("Name", target.Name);
if (target.DisplayName != null && memberGuildConfig?.DisplayName == null)
eb.AddField($"Display Name", $"**{target.DisplayName}**");
else
eb.AddField("Display Name", target.DisplayName ?? "*(none)*");
2020-02-01 12:03:02 +00:00
if (ctx.Guild != null)
{
2020-03-04 17:13:36 +00:00
if (memberGuildConfig?.DisplayName != null)
eb.AddField($"Server Name (in {ctx.Guild.Name.SanitizeMentions()})", $"**{memberGuildConfig.DisplayName}**");
else
eb.AddField($"Server Name (in {ctx.Guild.Name.SanitizeMentions()})", memberGuildConfig?.DisplayName ?? "*(none)*");
2020-02-01 12:03:02 +00:00
}
2020-03-04 17:13:36 +00:00
return eb;
2020-02-01 12:03:02 +00:00
}
2020-03-04 17:13:36 +00:00
public async Task DisplayName(Context ctx, PKMember target)
2020-02-01 12:03:02 +00:00
{
2020-03-04 17:13:36 +00:00
async Task PrintSuccess(string text)
{
var successStr = text;
if (ctx.Guild != null)
{
var memberGuildConfig = await _db.Execute(c => c.QueryOrInsertMemberGuildConfig(ctx.Guild.Id, target.Id));
2020-03-04 17:13:36 +00:00
if (memberGuildConfig.DisplayName != null)
successStr += $" However, this member has a server name set in this server ({ctx.Guild.Name.SanitizeMentions()}), and will be proxied using that name, \"{memberGuildConfig.DisplayName.SanitizeMentions()}\", here.";
}
await ctx.Reply(successStr);
}
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
if (MatchClear(ctx))
{
CheckEditMemberPermission(ctx, target);
target.DisplayName = null;
await _data.SaveMember(target);
await PrintSuccess($"{Emojis.Success} Member display name cleared. This member will now be proxied using their member name \"{target.Name.SanitizeMentions()}\".");
}
else if (!ctx.HasNext())
{
// No perms check, display name isn't covered by member privacy
var eb = await CreateMemberNameInfoEmbed(ctx, target);
if (ctx.System?.Id == target.System)
eb.WithDescription($"To change display name, type `pk;member {target.Hid} displayname <display name>`.\nTo clear it, type `pk;member {target.Hid} displayname -clear`.");
await ctx.Reply(embed: eb.Build());
}
else
{
CheckEditMemberPermission(ctx, target);
var newDisplayName = ctx.RemainderOrNull();
target.DisplayName = newDisplayName;
await _data.SaveMember(target);
await PrintSuccess($"{Emojis.Success} Member display name changed. This member will now be proxied using the name \"{newDisplayName.SanitizeMentions()}\".");
}
}
public async Task ServerName(Context ctx, PKMember target)
{
2020-02-01 12:03:02 +00:00
ctx.CheckGuildContext();
2020-03-04 17:13:36 +00:00
if (MatchClear(ctx))
{
CheckEditMemberPermission(ctx, target);
await _db.Execute(c =>
c.ExecuteAsync("update member_guild set display_name = null where member = @member and guild = @guild",
new {member = target.Id, guild = ctx.Guild.Id}));
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
if (target.DisplayName != null)
await ctx.Reply($"{Emojis.Success} Member server name cleared. This member will now be proxied using their global display name \"{target.DisplayName.SanitizeMentions()}\" in this server ({ctx.Guild.Name.SanitizeMentions()}).");
else
await ctx.Reply($"{Emojis.Success} Member server name cleared. This member will now be proxied using their member name \"{target.Name.SanitizeMentions()}\" in this server ({ctx.Guild.Name.SanitizeMentions()}).");
}
else if (!ctx.HasNext())
{
// No perms check, server name isn't covered by member privacy
var eb = await CreateMemberNameInfoEmbed(ctx, target);
if (ctx.System?.Id == target.System)
eb.WithDescription($"To change server name, type `pk;member {target.Hid} servername <server name>`.\nTo clear it, type `pk;member {target.Hid} servername -clear`.");
await ctx.Reply(embed: eb.Build());
}
2020-02-01 12:03:02 +00:00
else
2020-03-04 17:13:36 +00:00
{
CheckEditMemberPermission(ctx, target);
var newServerName = ctx.RemainderOrNull();
await _db.Execute(c =>
c.ExecuteAsync("update member_guild set display_name = @newServerName where member = @member and guild = @guild",
new {member = target.Id, guild = ctx.Guild.Id, newServerName}));
2020-02-01 12:03:02 +00:00
2020-03-04 17:13:36 +00:00
await ctx.Reply($"{Emojis.Success} Member server name changed. This member will now be proxied using the name \"{newServerName.SanitizeMentions()}\" in this server ({ctx.Guild.Name.SanitizeMentions()}).");
}
2020-02-01 12:03:02 +00:00
}
public async Task KeepProxy(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("on", "enabled", "true", "yes")) newValue = true;
else if (ctx.Match("off", "disabled", "false", "no")) newValue = false;
else if (ctx.HasNext()) throw new PKSyntaxError("You must pass either \"on\" or \"off\".");
2020-03-04 17:13:36 +00:00
else
{
if (target.KeepProxy)
await ctx.Reply("This member has keepproxy **enabled**, which means proxy tags will be **included** in the resulting message when proxying.");
else
await ctx.Reply("This member has keepproxy **disabled**, which means proxy tags will **not** be included in the resulting message when proxying.");
return;
};
2020-02-01 12:03:02 +00:00
target.KeepProxy = newValue;
await _data.SaveMember(target);
if (newValue)
await ctx.Reply($"{Emojis.Success} Member proxy tags will now be included in the resulting message when proxying.");
else
await ctx.Reply($"{Emojis.Success} Member proxy tags will now not be included in the resulting message when proxying.");
}
public async Task Privacy(Context ctx, PKMember target, PrivacyLevel? newValueFromCommand)
2020-02-01 12:03:02 +00:00
{
if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
// Display privacy settings
if (!ctx.HasNext() && newValueFromCommand == null)
2020-03-04 17:13:36 +00:00
{
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
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 DiscordEmbedBuilder()
.WithTitle($"Current privacy settings for {target.Name}")
.AddField("Name (replaces name with display name if member has one)",PrivacyLevelString(target.NamePrivacy))
.AddField("Description", PrivacyLevelString(target.DescriptionPrivacy))
.AddField("Birthday", PrivacyLevelString(target.BirthdayPrivacy))
.AddField("Pronouns", PrivacyLevelString(target.PronounPrivacy))
.AddField("Color", PrivacyLevelString(target.ColorPrivacy))
.AddField("Meta (message count, last front, last message)", PrivacyLevelString(target.MetadataPrivacy))
.AddField("Visibility", PrivacyLevelString(target.MemberVisibility))
.WithDescription("To edit privacy settings, use the command:\n`pk;member <member> privacy <subject> <level>`\n\n- `subject` is one of `name`, `description`, `birthday`, `pronouns`, `color`, `created`, `messages`, `visibility`, or `all`\n- `level` is either `public` or `private`.");
await ctx.Reply(embed: eb.Build());
2020-03-04 17:13:36 +00:00
return;
}
2020-02-01 12:03:02 +00:00
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
// Set Privacy Settings
PrivacyLevel PopPrivacyLevel(string subject, out string levelStr, out string levelExplanation)
{
if (ctx.Match("public", "show", "shown", "visible"))
{
levelStr = "public";
levelExplanation = "be shown on the member card";
return PrivacyLevel.Public;
}
if (ctx.Match("private", "hide", "hidden"))
{
levelStr = "private";
levelExplanation = "*not* be shown on the member card";
if(subject == "name") levelExplanation += " unless no display name is set";
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`).");
}
2020-02-01 12:03:02 +00:00
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
string levelStr, levelExplanation, subjectStr;
var subjectList = "`name`, `description`, `birthday`, `pronouns`, `color`, `metadata`, `visibility`, or `all`";
if(ctx.Match("name"))
{
subjectStr = "name";
target.NamePrivacy = PopPrivacyLevel("name", out levelStr, out levelExplanation);
}
else if(ctx.Match("description", "desc", "text", "info"))
{
subjectStr = "description";
target.DescriptionPrivacy = PopPrivacyLevel("description", out levelStr, out levelExplanation);
}
else if(ctx.Match("birthday", "birth", "bday"))
{
subjectStr = "birthday";
target.BirthdayPrivacy = PopPrivacyLevel("birthday", out levelStr, out levelExplanation);
}
else if(ctx.Match("pronouns", "pronoun"))
{
subjectStr = "pronouns";
target.PronounPrivacy = PopPrivacyLevel("pronouns", out levelStr, out levelExplanation);
}
else if(ctx.Match("color","colour"))
{
subjectStr = "color";
target.ColorPrivacy = PopPrivacyLevel("color", out levelStr, out levelExplanation);
}
else if(ctx.Match("meta","metadata"))
{
subjectStr = "metadata (date created, message count, last fronted, and last message)";
target.MetadataPrivacy = PopPrivacyLevel("metadata", out levelStr, out levelExplanation);
}
else if(ctx.Match("visibility","hidden","shown","visible"))
{
subjectStr = "visibility";
target.MemberVisibility = PopPrivacyLevel("visibility", out levelStr, out levelExplanation);
}
else if(ctx.Match("all") || newValueFromCommand != null){
subjectStr = "all";
PrivacyLevel level;
if(newValueFromCommand != null)
{
if(newValueFromCommand == PrivacyLevel.Public)
{
level = PrivacyLevel.Public;
levelStr = "public";
levelExplanation = "be shown on the member card";
}
else
{
level = PrivacyLevel.Private;
levelStr = "private";
levelExplanation = "*not* be shown on the member card";
}
}
else
level = PopPrivacyLevel("all", out levelStr, out levelExplanation);
target.MemberVisibility = level;
target.NamePrivacy = level;
target.DescriptionPrivacy = level;
target.BirthdayPrivacy = level;
target.PronounPrivacy = level;
target.ColorPrivacy = level;
target.MetadataPrivacy = level;
}
2020-02-01 12:03:02 +00:00
else
Feature/granular member privacy (#174) * Some reasons this needs to exist for it to run on my machine? I don't think it would hurt to have it in other machines so * Add options to member model * Add Privacy to member embed * Added member privacy display list * Update database settings * apparetnly this is nolonger needed? * Fix sql call * Fix more sql errors * Added in settings control * Add all subject to system privacy * Basic API Privacy * Name privacy in logs * update todo * remove CheckReadMemberPermission * Added name privacy to log embed * update todo * Update todo * Update api to handle privacy * update todo * Update systemlist full to respect privacy (as well as system list) * include colour as option for member privacy subject * move todo file (why was it there?) * Update TODO.md * Update TODO.md * Update TODO.md * Deleted to create pr * Update command usage and add to the command tree * Make api respect created privacy * Add editing privacy through the api * Fix pronoun privacy field in api * Fix info leak of display name in api * deprecate privacy field in api * Deprecate privacy diffrently * Update API * Update documentation * Update documentation * Remove comment in yml * Update userguide * Update migration (fix typo in 5.sql too) * Sanatize names * some full stops * Fix after merge * update migration * update schema version * update edit command * update privacy filter * fix a dumb mistake * clarify on what name privacy does * make it easier on someone else * Update docs * Comment out unused code * Add aliases for `member privacy all public` and `member privacy all private`
2020-06-17 19:31:39 +00:00
throw new PKSyntaxError($"Invalid privacy subject `{ctx.PopArgument().SanitizeMentions()}` (must be {subjectList}).");
await _data.SaveMember(target);
//Handle "all" subject
if(subjectStr == "all"){
if(levelStr == "private")
await ctx.Reply($"All {target.Name.SanitizeMentions()}'s privacy settings have been set to **{levelStr}**. Other accounts will now see nothing on the member card.");
else
await ctx.Reply($"All {target.Name.SanitizeMentions()}'s privacy settings have been set to **{levelStr}**. Other accounts will now see everything on the member card.");
}
//Handle other subjects
else
await ctx.Reply($"{target.Name.SanitizeMentions()}'s {subjectStr} has been set to **{levelStr}**. Other accounts will now {levelExplanation}.");
2020-02-01 12:03:02 +00:00
}
public async Task Delete(Context ctx, PKMember target)
{
if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
await ctx.Reply($"{Emojis.Warn} Are you sure you want to delete \"{target.Name.SanitizeMentions()}\"? If so, reply to this message with the member's ID (`{target.Hid}`). __***This cannot be undone!***__");
if (!await ctx.ConfirmWithReply(target.Hid)) throw Errors.MemberDeleteCancelled;
await _data.DeleteMember(target);
await ctx.Reply($"{Emojis.Success} Member deleted.");
}
}
}