Restructure the rest of the commands

This commit is contained in:
Ske 2020-03-04 18:13:36 +01:00
parent 1169669cf1
commit 373423e6c5
4 changed files with 324 additions and 135 deletions

View File

@ -20,6 +20,21 @@ namespace PluralKit.Bot
{ {
var guildData = ctx.Guild != null ? await _data.GetMemberGuildSettings(target, ctx.Guild.Id) : null; var guildData = ctx.Guild != null ? await _data.GetMemberGuildSettings(target, ctx.Guild.Id) : null;
if (ctx.Match("clear", "remove", "reset") || ctx.MatchFlag("c", "clear"))
{
if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
target.AvatarUrl = null;
await _data.SaveMember(target);
if (guildData?.AvatarUrl != null)
await ctx.Reply($"{Emojis.Success} Member avatar cleared. Note that this member has a server-specific avatar set here, type `pk;member {target.Hid} serveravatar clear` if you wish to clear that too.");
else
await ctx.Reply($"{Emojis.Success} Member avatar cleared.");
return;
}
if (ctx.RemainderOrNull() == null && ctx.Message.Attachments.Count == 0) if (ctx.RemainderOrNull() == null && ctx.Message.Attachments.Count == 0)
{ {
if ((target.AvatarUrl?.Trim() ?? "").Length > 0) if ((target.AvatarUrl?.Trim() ?? "").Length > 0)
@ -28,7 +43,7 @@ namespace PluralKit.Bot
.WithTitle($"{target.Name.SanitizeMentions()}'s avatar") .WithTitle($"{target.Name.SanitizeMentions()}'s avatar")
.WithImageUrl(target.AvatarUrl); .WithImageUrl(target.AvatarUrl);
if (target.System == ctx.System?.Id) if (target.System == ctx.System?.Id)
eb.WithDescription($"To clear, use `pk;member {target.Hid} avatar clear`."); eb.WithDescription($"To clear, use `pk;member {target.Hid} avatar -clear`.");
await ctx.Reply(embed: eb.Build()); await ctx.Reply(embed: eb.Build());
} }
else else
@ -44,16 +59,6 @@ namespace PluralKit.Bot
if (ctx.System == null) throw Errors.NoSystemError; if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError; if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
if (ctx.Match("clear", "remove", "reset"))
{
target.AvatarUrl = null;
await _data.SaveMember(target);
if (guildData?.AvatarUrl != null)
await ctx.Reply($"{Emojis.Success} Member avatar cleared. Note that this member has a server-specific avatar set here, type `pk;member {target.Hid} serveravatar clear` if you wish to clear that too.");
else
await ctx.Reply($"{Emojis.Success} Member avatar cleared.");
}
else if (await ctx.MatchUser() is IUser user) else if (await ctx.MatchUser() is IUser user)
{ {
if (user.AvatarId == null) throw Errors.UserHasNoAvatar; if (user.AvatarId == null) throw Errors.UserHasNoAvatar;
@ -90,6 +95,20 @@ namespace PluralKit.Bot
ctx.CheckGuildContext(); ctx.CheckGuildContext();
var guildData = await _data.GetMemberGuildSettings(target, ctx.Guild.Id); var guildData = await _data.GetMemberGuildSettings(target, ctx.Guild.Id);
if (ctx.Match("clear", "remove", "reset") || ctx.MatchFlag("c", "clear"))
{
if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
guildData.AvatarUrl = null;
await _data.SetMemberGuildSettings(target, ctx.Guild.Id, guildData);
if (target.AvatarUrl != null)
await ctx.Reply($"{Emojis.Success} Member server avatar cleared. This member will now use the global avatar in this server (**{ctx.Guild.Name}**).");
else
await ctx.Reply($"{Emojis.Success} Member server avatar cleared. This member now has no avatar.");
}
if (ctx.RemainderOrNull() == null && ctx.Message.Attachments.Count == 0) if (ctx.RemainderOrNull() == null && ctx.Message.Attachments.Count == 0)
{ {
if ((guildData.AvatarUrl?.Trim() ?? "").Length > 0) if ((guildData.AvatarUrl?.Trim() ?? "").Length > 0)
@ -110,17 +129,7 @@ namespace PluralKit.Bot
if (ctx.System == null) throw Errors.NoSystemError; if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError; if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
if (ctx.Match("clear", "remove", "reset")) if (await ctx.MatchUser() is IUser user)
{
guildData.AvatarUrl = null;
await _data.SetMemberGuildSettings(target, ctx.Guild.Id, guildData);
if (target.AvatarUrl != null)
await ctx.Reply($"{Emojis.Success} Member server avatar cleared. This member will now use the global avatar in this server (**{ctx.Guild.Name}**).");
else
await ctx.Reply($"{Emojis.Success} Member server avatar cleared. This member now has no avatar.");
}
else if (await ctx.MatchUser() is IUser user)
{ {
if (user.AvatarId == null) throw Errors.UserHasNoAvatar; if (user.AvatarId == null) throw Errors.UserHasNoAvatar;
guildData.AvatarUrl = user.GetAvatarUrl(ImageFormat.Png, size: 256); guildData.AvatarUrl = user.GetAvatarUrl(ImageFormat.Png, size: 256);

View File

@ -1,4 +1,5 @@
using System.Text.RegularExpressions; using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord; using Discord;
@ -51,17 +52,35 @@ namespace PluralKit.Bot
} }
} }
public async Task Description(Context ctx, PKMember target) { private void CheckReadMemberPermission(Context ctx, PKMember target)
var description = ctx.RemainderOrNull()?.NormalizeLineEndSpacing(); {
if (!target.MemberPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
throw Errors.LookupNotAllowed;
}
var lookupContext = ctx.LookupContextFor(target.System); private void CheckEditMemberPermission(Context ctx, PKMember target)
if (description == null) {
if (target.System != ctx.System?.Id) throw Errors.NotOwnMemberError;
}
private static bool MatchClear(Context ctx) =>
ctx.Match("clear") || ctx.MatchFlag("c", "clear");
public async Task Description(Context ctx, PKMember target) {
if (MatchClear(ctx))
{ {
if (!target.MemberPrivacy.CanAccess(lookupContext)) CheckEditMemberPermission(ctx, target);
throw Errors.LookupNotAllowed; target.Description = null;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member description cleared.");
}
else if (!ctx.HasNext())
{
CheckReadMemberPermission(ctx, target);
if (target.Description == null) if (target.Description == null)
if (lookupContext == LookupContext.ByOwner) if (ctx.System?.Id == target.System)
await ctx.Reply("This member does not have a description set. To set one, type `pk;s description <description>`."); await ctx.Reply($"This member does not have a description set. To set one, type `pk;member {target.Hid} description <description>`.");
else else
await ctx.Reply("This member does not have a description set."); await ctx.Reply("This member does not have a description set.");
else if (ctx.MatchFlag("r", "raw")) else if (ctx.MatchFlag("r", "raw"))
@ -70,125 +89,245 @@ namespace PluralKit.Bot
await ctx.Reply(embed: new EmbedBuilder() await ctx.Reply(embed: new EmbedBuilder()
.WithTitle("Member description") .WithTitle("Member description")
.WithDescription(target.Description) .WithDescription(target.Description)
.WithFooter($"To print the description with formatting, type `pk;m {target.Hid} description -raw`." .AddField("\u200B", $"To print the description with formatting, type `pk;member {target.Hid} description -raw`."
+ (lookupContext == LookupContext.ByOwner ? $" To clear it, type `pk;m {target.Hid} description -clear`." : "")) + (ctx.System?.Id == target.System ? $" To clear it, type `pk;member {target.Hid} description -clear`." : ""))
.Build()); .Build());
return;
} }
else
{
CheckEditMemberPermission(ctx, target);
if (ctx.System == null) throw Errors.NoSystemError; var description = ctx.RemainderOrNull().NormalizeLineEndSpacing();
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError; if (description.IsLongerThan(Limits.MaxDescriptionLength))
throw Errors.DescriptionTooLongError(description.Length);
target.Description = description;
if (ctx.MatchFlag("c", "clear") || ctx.Match("clear")) await _data.SaveMember(target);
target.Description = null; await ctx.Reply($"{Emojis.Success} Member description changed.");
else if (description.IsLongerThan(Limits.MaxDescriptionLength)) }
throw Errors.DescriptionTooLongError(description.Length);
else target.Description = description;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member description {(target.Description == null ? "cleared" : "changed")}.");
} }
public async Task Pronouns(Context ctx, PKMember target) { public async Task Pronouns(Context ctx, PKMember target) {
if (ctx.System == null) throw Errors.NoSystemError; if (MatchClear(ctx))
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError; {
CheckEditMemberPermission(ctx, target);
target.Pronouns = null;
var pronouns = ctx.RemainderOrNull(); await _data.SaveMember(target);
if (pronouns.IsLongerThan(Limits.MaxPronounsLength)) throw Errors.MemberPronounsTooLongError(pronouns.Length); await ctx.Reply($"{Emojis.Success} Member pronouns cleared.");
}
else if (!ctx.HasNext())
{
CheckReadMemberPermission(ctx, target);
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);
target.Pronouns = pronouns; var pronouns = ctx.RemainderOrNull().NormalizeLineEndSpacing();
await _data.SaveMember(target); if (pronouns.IsLongerThan(Limits.MaxPronounsLength))
throw Errors.MemberPronounsTooLongError(pronouns.Length);
target.Pronouns = pronouns;
await ctx.Reply($"{Emojis.Success} Member pronouns {(pronouns == null ? "cleared" : "changed")}."); await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member pronouns changed.");
}
} }
public async Task Color(Context ctx, PKMember target) public async Task Color(Context ctx, PKMember target)
{ {
if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
var color = ctx.RemainderOrNull(); var color = ctx.RemainderOrNull();
if (color != null) if (MatchClear(ctx))
{ {
CheckEditMemberPermission(ctx, target);
target.Color = null;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member color cleared.");
}
else if (!ctx.HasNext())
{
CheckReadMemberPermission(ctx, target);
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
await ctx.Reply(embed: new EmbedBuilder()
.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);
if (color.StartsWith("#")) color = color.Substring(1); if (color.StartsWith("#")) color = color.Substring(1);
if (!Regex.IsMatch(color, "^[0-9a-fA-F]{6}$")) throw Errors.InvalidColorError(color); if (!Regex.IsMatch(color, "^[0-9a-fA-F]{6}$")) throw Errors.InvalidColorError(color);
target.Color = color.ToLower();
await _data.SaveMember(target);
await ctx.Reply(embed: new EmbedBuilder()
.WithTitle($"{Emojis.Success} Member color changed.")
.WithColor(target.Color.ToDiscordColor().Value)
.WithThumbnailUrl($"https://fakeimg.pl/256x256/{target.Color}/?text=%20")
.Build());
} }
target.Color = color?.ToLower();
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member color {(color == null ? "cleared" : "changed")}.");
} }
public async Task Birthday(Context ctx, PKMember target) public async Task Birthday(Context ctx, PKMember target)
{ {
if (ctx.System == null) throw Errors.NoSystemError; if (MatchClear(ctx))
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
LocalDate? date = null;
var birthday = ctx.RemainderOrNull();
if (birthday != null)
{ {
date = DateUtils.ParseDate(birthday, true); CheckEditMemberPermission(ctx, target);
if (date == null) throw Errors.BirthdayParseError(birthday); target.Birthday = null;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member birthdate cleared.");
}
else if (!ctx.HasNext())
{
CheckReadMemberPermission(ctx, target);
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.");
}
}
private async Task<EmbedBuilder> CreateMemberNameInfoEmbed(Context ctx, PKMember target)
{
MemberGuildSettings memberGuildConfig = null;
if (ctx.Guild != null)
memberGuildConfig = await _data.GetMemberGuildSettings(target, ctx.Guild.Id);
var eb = new EmbedBuilder().WithTitle($"Member names")
.WithFooter($"Member ID: {target.Hid} | Active name in bold. Server name overrides display name, which overrides base name.");
if (target.DisplayName == null && memberGuildConfig?.DisplayName == null)
eb.AddField($"Name", $"**{target.Name}**");
else
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)*");
if (ctx.Guild != null)
{
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)*");
} }
target.Birthday = date; return eb;
await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Member birthdate {(date == null ? "cleared" : $"changed to {target.BirthdayString}")}.");
} }
public async Task DisplayName(Context ctx, PKMember target) public async Task DisplayName(Context ctx, PKMember target)
{ {
if (ctx.System == null) throw Errors.NoSystemError; async Task PrintSuccess(string text)
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
var newDisplayName = ctx.RemainderOrNull();
target.DisplayName = newDisplayName;
await _data.SaveMember(target);
var successStr = $"{Emojis.Success} ";
if (newDisplayName != null)
successStr += $"Member display name changed. This member will now be proxied using the name \"{newDisplayName.SanitizeMentions()}\".";
else
successStr += $"Member display name cleared. This member will now be proxied using their member name \"{target.Name.SanitizeMentions()}\".";
if (ctx.Guild != null)
{ {
var memberGuildConfig = await _data.GetMemberGuildSettings(target, ctx.Guild.Id); var successStr = text;
if (memberGuildConfig.DisplayName != null) if (ctx.Guild != 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."; {
var memberGuildConfig = await _data.GetMemberGuildSettings(target, ctx.Guild.Id);
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);
} }
await ctx.Reply(successStr); 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) public async Task ServerName(Context ctx, PKMember target)
{ {
if (ctx.System == null) throw Errors.NoSystemError;
if (target.System != ctx.System.Id) throw Errors.NotOwnMemberError;
// TODO: allow setting server names for different servers/in DMs by ID
ctx.CheckGuildContext(); ctx.CheckGuildContext();
var newServerName = ctx.RemainderOrNull();
var guildSettings = await _data.GetMemberGuildSettings(target, ctx.Guild.Id); var guildSettings = await _data.GetMemberGuildSettings(target, ctx.Guild.Id);
guildSettings.DisplayName = newServerName;
await _data.SetMemberGuildSettings(target, ctx.Guild.Id, guildSettings);
var successStr = $"{Emojis.Success} "; if (MatchClear(ctx))
if (newServerName != null) {
successStr += $"Member server name changed. This member will now be proxied using the name \"{newServerName.SanitizeMentions()}\" in this server ({ctx.Guild.Name.SanitizeMentions()})."; CheckEditMemberPermission(ctx, target);
else if (target.DisplayName != null)
successStr += $"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()})."; guildSettings.DisplayName = null;
await _data.SetMemberGuildSettings(target, ctx.Guild.Id, guildSettings);
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());
}
else else
successStr += $"Member server name cleared. This member will now be proxied using their member name \"{target.Name.SanitizeMentions()}\" in this server ({ctx.Guild.Name.SanitizeMentions()})."; {
CheckEditMemberPermission(ctx, target);
await ctx.Reply(successStr); var newServerName = ctx.RemainderOrNull();
guildSettings.DisplayName = newServerName;
await _data.SetMemberGuildSettings(target, ctx.Guild.Id, guildSettings);
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()}).");
}
} }
public async Task KeepProxy(Context ctx, PKMember target) public async Task KeepProxy(Context ctx, PKMember target)
@ -200,7 +339,14 @@ namespace PluralKit.Bot
if (ctx.Match("on", "enabled", "true", "yes")) newValue = true; if (ctx.Match("on", "enabled", "true", "yes")) newValue = true;
else if (ctx.Match("off", "disabled", "false", "no")) newValue = false; else if (ctx.Match("off", "disabled", "false", "no")) newValue = false;
else if (ctx.HasNext()) throw new PKSyntaxError("You must pass either \"on\" or \"off\"."); else if (ctx.HasNext()) throw new PKSyntaxError("You must pass either \"on\" or \"off\".");
else newValue = !target.KeepProxy; 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;
};
target.KeepProxy = newValue; target.KeepProxy = newValue;
await _data.SaveMember(target); await _data.SaveMember(target);
@ -220,8 +366,17 @@ namespace PluralKit.Bot
if (ctx.Match("private", "hide", "hidden", "on", "enable", "yes")) newValue = PrivacyLevel.Private; if (ctx.Match("private", "hide", "hidden", "on", "enable", "yes")) newValue = PrivacyLevel.Private;
else if (ctx.Match("public", "show", "shown", "displayed", "off", "disable", "no")) newValue = PrivacyLevel.Public; else if (ctx.Match("public", "show", "shown", "displayed", "off", "disable", "no")) newValue = PrivacyLevel.Public;
else if (ctx.HasNext()) throw new PKSyntaxError("You must pass either \"private\" or \"public\"."); else if (ctx.HasNext()) throw new PKSyntaxError("You must pass either \"private\" or \"public\".");
// If we're getting a value from command (eg. "pk;m <name> private" == always private, "pk;m <name> public == always public"), use that instead of parsing/toggling // If we're getting a value from command (eg. "pk;m <name> private" == always private, "pk;m <name> public == always public"), use that instead of parsing
else newValue = newValueFromCommand ?? (target.MemberPrivacy != PrivacyLevel.Private ? PrivacyLevel.Private : PrivacyLevel.Public); else if (newValueFromCommand != null) newValue = newValueFromCommand.Value;
else
{
if (target.MemberPrivacy == PrivacyLevel.Public)
await ctx.Reply("This member's privacy is currently set to **public**. This member will not show up in member lists and will return limited information when queried by other accounts.");
else
await ctx.Reply("This member's privacy is currently set to **private**. This member will show up in member lists and will return all information when queried by other accounts.");
return;
}
target.MemberPrivacy = newValue; target.MemberPrivacy = newValue;
await _data.SaveMember(target); await _data.SaveMember(target);

View File

@ -42,9 +42,8 @@ namespace PluralKit.Bot
return await ctx.PromptYesNo(msg); return await ctx.PromptYesNo(msg);
} }
// "Sub"command: no arguments clearing // "Sub"command: clear flag
// Also matches the pseudo-subcommand "text" which is equivalent to empty proxy tags on both sides. if (ctx.Match("clear", "purge", "clean", "removeall", "text") || ctx.MatchFlag("c", "clear"))
if (!ctx.HasNext(skipFlags: false) || ctx.Match("clear", "purge", "clean", "removeall"))
{ {
// If we already have multiple tags, this would clear everything, so prompt that // If we already have multiple tags, this would clear everything, so prompt that
if (target.ProxyTags.Count > 1) if (target.ProxyTags.Count > 1)
@ -60,6 +59,17 @@ namespace PluralKit.Bot
await _data.SaveMember(target); await _data.SaveMember(target);
await ctx.Reply($"{Emojis.Success} Proxy tags cleared."); await ctx.Reply($"{Emojis.Success} Proxy tags cleared.");
} }
// "Sub"command: no arguments; will print proxy tags
else if (!ctx.HasNext(skipFlags: false))
{
if (target.ProxyTags.Count == 0)
await ctx.Reply("This member does not have any proxy tags.");
else
{
var tags = string.Join("\n", target.ProxyTags.Select(t => $"`{t.ProxyString}`".SanitizeMentions()));
await ctx.Reply($"This member's proxy tags are:\n{tags}");
}
}
// Subcommand: "add" // Subcommand: "add"
else if (ctx.Match("add", "append")) else if (ctx.Match("add", "append"))
{ {
@ -100,8 +110,6 @@ namespace PluralKit.Bot
// Subcommand: bare proxy tag given // Subcommand: bare proxy tag given
else else
{ {
if (!ctx.HasNext(skipFlags: false)) throw new PKSyntaxError("You must pass an example proxy to set (eg. `[text]` or `J:text`).");
var requestedTag = ParseProxyTags(ctx.RemainderOrNull(skipFlags: false)); var requestedTag = ParseProxyTags(ctx.RemainderOrNull(skipFlags: false));
if (requestedTag.IsEmpty) throw Errors.EmptyProxyTags(target); if (requestedTag.IsEmpty) throw Errors.EmptyProxyTags(target);

View File

@ -27,12 +27,28 @@ namespace PluralKit.Bot
{ {
ctx.CheckSystem(); ctx.CheckSystem();
var newSystemName = ctx.RemainderOrNull(); if (ctx.MatchFlag("c", "clear") || ctx.Match("clear"))
if (newSystemName != null && newSystemName.Length > Limits.MaxSystemNameLength) throw Errors.SystemNameTooLongError(newSystemName.Length); {
ctx.System.Name = null;
await _data.SaveSystem(ctx.System);
await ctx.Reply($"{Emojis.Success} System name cleared.");
return;
}
var newSystemName = ctx.RemainderOrNull();
if (newSystemName == null)
{
if (ctx.System.Name != null)
await ctx.Reply($"Your system's name is currently **{ctx.System.Name.SanitizeMentions()}**. Type `pk;system name -clear` to clear it.");
else
await ctx.Reply("Your system currently does not have a name. Type `pk;system name <name>` to set one.");
return;
}
if (newSystemName != null && newSystemName.Length > Limits.MaxSystemNameLength) throw Errors.SystemNameTooLongError(newSystemName.Length);
ctx.System.Name = newSystemName; ctx.System.Name = newSystemName;
await _data.SaveSystem(ctx.System); await _data.SaveSystem(ctx.System);
await ctx.Reply($"{Emojis.Success} System name {(newSystemName != null ? "changed" : "cleared")}."); await ctx.Reply($"{Emojis.Success} System name changed.");
} }
public async Task Description(Context ctx) { public async Task Description(Context ctx) {
@ -52,7 +68,7 @@ namespace PluralKit.Bot
if (ctx.System.Description == null) if (ctx.System.Description == null)
await ctx.Reply("Your system does not have a description set. To set one, type `pk;s description <description>`."); await ctx.Reply("Your system does not have a description set. To set one, type `pk;s description <description>`.");
else if (ctx.MatchFlag("r", "raw")) else if (ctx.MatchFlag("r", "raw"))
await ctx.Reply($"```\n{ctx.System.Description}\n```"); await ctx.Reply($"```\n{ctx.System.Description.SanitizeMentions()}\n```");
else else
await ctx.Reply(embed: new EmbedBuilder() await ctx.Reply(embed: new EmbedBuilder()
.WithTitle("System description") .WithTitle("System description")
@ -101,7 +117,14 @@ namespace PluralKit.Bot
{ {
ctx.CheckSystem(); ctx.CheckSystem();
if (ctx.RemainderOrNull() == null && ctx.Message.Attachments.Count == 0) if (ctx.Match("clear") || ctx.MatchFlag("c", "clear"))
{
ctx.System.AvatarUrl = null;
await _data.SaveSystem(ctx.System);
await ctx.Reply($"{Emojis.Success} System avatar cleared.");
return;
}
else if (ctx.RemainderOrNull() == null && ctx.Message.Attachments.Count == 0)
{ {
if ((ctx.System.AvatarUrl?.Trim() ?? "").Length > 0) if ((ctx.System.AvatarUrl?.Trim() ?? "").Length > 0)
{ {
@ -128,12 +151,6 @@ namespace PluralKit.Bot
await ctx.Reply( await ctx.Reply(
$"{Emojis.Success} System avatar changed to {member.Username}'s avatar! {Emojis.Warn} Please note that if {member.Username} changes their avatar, the system's avatar will need to be re-set.", embed: embed); $"{Emojis.Success} System avatar changed to {member.Username}'s avatar! {Emojis.Warn} Please note that if {member.Username} changes their avatar, the system's avatar will need to be re-set.", embed: embed);
} }
else if (ctx.Match("clear"))
{
ctx.System.AvatarUrl = null;
await _data.SaveSystem(ctx.System);
await ctx.Reply($"{Emojis.Success} System avatar cleared.");
}
else else
{ {
// They can't both be null - otherwise we would've hit the conditional at the very top // They can't both be null - otherwise we would've hit the conditional at the very top
@ -194,7 +211,7 @@ namespace PluralKit.Bot
{ {
ctx.System.UiTz = "UTC"; ctx.System.UiTz = "UTC";
await _data.SaveSystem(ctx.System); await _data.SaveSystem(ctx.System);
await ctx.Reply($"{Emojis.Success} System time zone cleared."); await ctx.Reply($"{Emojis.Success} System time zone cleared (set to UTC).");
return; return;
} }