diff --git a/PluralKit.Bot/CommandSystem/Context.cs b/PluralKit.Bot/CommandSystem/Context.cs index 5b285b2a..99854d41 100644 --- a/PluralKit.Bot/CommandSystem/Context.cs +++ b/PluralKit.Bot/CommandSystem/Context.cs @@ -166,12 +166,12 @@ namespace PluralKit.Bot.CommandSystem if (input.Length == 5) { if (_senderSystem != null) - return $"Member with ID or name `{input}` not found."; - return $"Member with ID `{input}` not found."; // Accounts without systems can't query by name + return $"Member with ID or name \"{input.SanitizeMentions()}\" not found."; + return $"Member with ID \"{input.SanitizeMentions()}\" not found."; // Accounts without systems can't query by name } if (_senderSystem != null) - return $"Member with name `{input}` not found. Note that a member ID is 5 characters long."; + return $"Member with name \"{input.SanitizeMentions()}\" not found. Note that a member ID is 5 characters long."; return $"Member not found. Note that a member ID is 5 characters long."; } diff --git a/PluralKit.Bot/Commands/CommandTree.cs b/PluralKit.Bot/Commands/CommandTree.cs index 3c92d3af..2e114a5f 100644 --- a/PluralKit.Bot/Commands/CommandTree.cs +++ b/PluralKit.Bot/Commands/CommandTree.cs @@ -101,7 +101,7 @@ namespace PluralKit.Bot.Commands return ctx.Execute(PermCheck, m => m.PermCheckGuild(ctx)); ctx.Reply( - $"{Emojis.Error} Unknown command `{ctx.PeekArgument().Sanitize()}`. For a list of possible commands, see ."); + $"{Emojis.Error} Unknown command `{ctx.PeekArgument().SanitizeMentions()}`. For a list of possible commands, see ."); return Task.CompletedTask; } diff --git a/PluralKit.Bot/Commands/MemberCommands.cs b/PluralKit.Bot/Commands/MemberCommands.cs index 4ec176d6..8961b1f0 100644 --- a/PluralKit.Bot/Commands/MemberCommands.cs +++ b/PluralKit.Bot/Commands/MemberCommands.cs @@ -41,7 +41,7 @@ namespace PluralKit.Bot.Commands // Warn if there's already a member by this name var existingMember = await _members.GetByName(ctx.System, memberName); if (existingMember != null) { - var msg = await ctx.Reply($"{Emojis.Warn} You already have a member in your system with the name \"{existingMember.Name.Sanitize()}\" (with ID `{existingMember.Hid}`). Do you want to create another member with the same name?"); + var msg = await ctx.Reply($"{Emojis.Warn} You already have a member in your system with the name \"{existingMember.Name.SanitizeMentions()}\" (with ID `{existingMember.Hid}`). Do you want to create another member with the same name?"); if (!await ctx.PromptYesNo(msg)) throw new PKError("Member creation cancelled."); } @@ -49,7 +49,7 @@ namespace PluralKit.Bot.Commands var member = await _members.Create(ctx.System, memberName); // Send confirmation and space hint - await ctx.Reply($"{Emojis.Success} Member \"{memberName.Sanitize()}\" (`{member.Hid}`) registered! See the user guide for commands for editing this member: https://pluralkit.me/guide#member-management"); + await ctx.Reply($"{Emojis.Success} Member \"{memberName.SanitizeMentions()}\" (`{member.Hid}`) registered! See the user guide for commands for editing this member: https://pluralkit.me/guide#member-management"); if (memberName.Contains(" ")) await ctx.Reply($"{Emojis.Note} Note that this member's name contains spaces. You will need to surround it with \"double quotes\" when using commands referring to it, or just use the member's 5-character ID (which is `{member.Hid}`)."); await _proxyCache.InvalidateResultsForSystem(ctx.System); @@ -74,7 +74,7 @@ namespace PluralKit.Bot.Commands // Warn if there's already a member by this name var existingMember = await _members.GetByName(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.Sanitize()}\" (`{existingMember.Hid}`). Do you want to rename this member to that name too?"); + 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."); } @@ -84,7 +84,7 @@ namespace PluralKit.Bot.Commands 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}`), and will be proxied using that name instead."); + 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."); await _proxyCache.InvalidateResultsForSystem(ctx.System); } @@ -178,7 +178,7 @@ namespace PluralKit.Bot.Commands target.Prefix = prefixAndSuffix[0].Length > 0 ? prefixAndSuffix[0] : null; target.Suffix = prefixAndSuffix[1].Length > 0 ? prefixAndSuffix[1] : null; await _members.Save(target); - await ctx.Reply($"{Emojis.Success} Member proxy tags changed to `{target.ProxyString.Sanitize()}`. Try proxying now!"); + await ctx.Reply($"{Emojis.Success} Member proxy tags changed to `{target.ProxyString.SanitizeMentions()}`. Try proxying now!"); await _proxyCache.InvalidateResultsForSystem(ctx.System); } @@ -188,7 +188,7 @@ namespace PluralKit.Bot.Commands 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.Sanitize()}\"? If so, reply to this message with the member's ID (`{target.Hid}`). __***This cannot be undone!***__"); + 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 _members.Delete(target); await ctx.Reply($"{Emojis.Success} Member deleted."); @@ -257,7 +257,7 @@ namespace PluralKit.Bot.Commands if (newDisplayName != null) { successStr += - $"Member display name changed. This member will now be proxied using the name `{newDisplayName}`."; + $"Member display name changed. This member will now be proxied using the name \"{newDisplayName.SanitizeMentions()}\"."; } else { @@ -268,7 +268,7 @@ namespace PluralKit.Bot.Commands successStr += $" {Emojis.Warn} This member's actual name is too long ({target.Name.Length} > {ctx.System.MaxMemberNameLength} characters), and thus cannot be proxied."; else - successStr += $"This member will now be proxied using their member name `{target.Name}."; + successStr += $"This member will now be proxied using their member name \"{target.Name.SanitizeMentions()}\"."; } await ctx.Reply(successStr); diff --git a/PluralKit.Bot/Commands/MiscCommands.cs b/PluralKit.Bot/Commands/MiscCommands.cs index da69e555..4ddf56e3 100644 --- a/PluralKit.Bot/Commands/MiscCommands.cs +++ b/PluralKit.Bot/Commands/MiscCommands.cs @@ -59,7 +59,7 @@ namespace PluralKit.Bot.Commands { public async Task PermCheckGuild(Context ctx) { var guildIdStr = ctx.PopArgument() ?? throw new PKSyntaxError("You must pass a server ID."); - if (!ulong.TryParse(guildIdStr, out var guildId)) throw new PKSyntaxError($"Could not parse `{guildIdStr}` as an ID."); + if (!ulong.TryParse(guildIdStr, out var guildId)) throw new PKSyntaxError($"Could not parse `{guildIdStr.SanitizeMentions()}` as an ID."); // TODO: will this call break for sharding if you try to request a guild on a different bot instance? var guild = ctx.Client.GetGuild(guildId) as IGuild; @@ -97,7 +97,7 @@ namespace PluralKit.Bot.Commands { // Generate the output embed var eb = new EmbedBuilder() - .WithTitle($"Permission check for **{guild.Name}**"); + .WithTitle($"Permission check for **{guild.Name.SanitizeMentions()}**"); if (permissionsMissing.Count == 0) { diff --git a/PluralKit.Bot/Commands/ModCommands.cs b/PluralKit.Bot/Commands/ModCommands.cs index 19624640..df7c89fb 100644 --- a/PluralKit.Bot/Commands/ModCommands.cs +++ b/PluralKit.Bot/Commands/ModCommands.cs @@ -31,7 +31,7 @@ namespace PluralKit.Bot.Commands await _logChannels.SetLogChannel(ctx.Guild, channel); if (channel != null) - await ctx.Reply($"{Emojis.Success} Proxy logging channel set to #{channel.Name.Sanitize()}."); + await ctx.Reply($"{Emojis.Success} Proxy logging channel set to #{channel.Name.SanitizeMentions()}."); else await ctx.Reply($"{Emojis.Success} Proxy logging channel cleared."); } diff --git a/PluralKit.Bot/Commands/SwitchCommands.cs b/PluralKit.Bot/Commands/SwitchCommands.cs index 788309fc..d026c733 100644 --- a/PluralKit.Bot/Commands/SwitchCommands.cs +++ b/PluralKit.Bot/Commands/SwitchCommands.cs @@ -69,7 +69,7 @@ namespace PluralKit.Bot.Commands if (members.Count == 0) await ctx.Reply($"{Emojis.Success} Switch-out registered."); else - await ctx.Reply($"{Emojis.Success} Switch registered. Current fronter is now {string.Join(", ", members.Select(m => m.Name)).Sanitize()}."); + await ctx.Reply($"{Emojis.Success} Switch registered. Current fronter is now {string.Join(", ", members.Select(m => m.Name)).SanitizeMentions()}."); } public async Task SwitchMove(Context ctx) @@ -108,7 +108,7 @@ namespace PluralKit.Bot.Commands var newSwitchDeltaStr = Formats.DurationFormat.Format(SystemClock.Instance.GetCurrentInstant() - time.ToInstant()); // yeet - var msg = await ctx.Reply($"{Emojis.Warn} This will move the latest switch ({lastSwitchMemberStr.Sanitize()}) from {lastSwitchTimeStr} ({lastSwitchDeltaStr} ago) to {newSwitchTimeStr} ({newSwitchDeltaStr} ago). Is this OK?"); + var msg = await ctx.Reply($"{Emojis.Warn} This will move the latest switch ({lastSwitchMemberStr.SanitizeMentions()}) from {lastSwitchTimeStr} ({lastSwitchDeltaStr} ago) to {newSwitchTimeStr} ({newSwitchDeltaStr} ago). Is this OK?"); if (!await ctx.PromptYesNo(msg)) throw Errors.SwitchMoveCancelled; // aaaand *now* we do the move @@ -132,7 +132,7 @@ namespace PluralKit.Bot.Commands if (lastTwoSwitches.Length == 1) { msg = await ctx.Reply( - $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr.Sanitize()}, {lastSwitchDeltaStr} ago). You have no other switches logged. Is this okay?"); + $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr.SanitizeMentions()}, {lastSwitchDeltaStr} ago). You have no other switches logged. Is this okay?"); } else { @@ -140,7 +140,7 @@ namespace PluralKit.Bot.Commands var secondSwitchMemberStr = string.Join(", ", secondSwitchMembers.Select(m => m.Name)); var secondSwitchDeltaStr = Formats.DurationFormat.Format(SystemClock.Instance.GetCurrentInstant() - lastTwoSwitches[1].Timestamp); msg = await ctx.Reply( - $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr.Sanitize()}, {lastSwitchDeltaStr} ago). The next latest switch is {secondSwitchMemberStr.Sanitize()} ({secondSwitchDeltaStr} ago). Is this okay?"); + $"{Emojis.Warn} This will delete the latest switch ({lastSwitchMemberStr.SanitizeMentions()}, {lastSwitchDeltaStr} ago). The next latest switch is {secondSwitchMemberStr.SanitizeMentions()} ({secondSwitchDeltaStr} ago). Is this okay?"); } if (!await ctx.PromptYesNo(msg)) throw Errors.SwitchDeleteCancelled; diff --git a/PluralKit.Bot/Commands/SystemCommands.cs b/PluralKit.Bot/Commands/SystemCommands.cs index 7c3f554f..dbb61a6d 100644 --- a/PluralKit.Bot/Commands/SystemCommands.cs +++ b/PluralKit.Bot/Commands/SystemCommands.cs @@ -85,7 +85,7 @@ namespace PluralKit.Bot.Commands if (unproxyableMembers.Count > 0) { var msg = await ctx.Reply( - $"{Emojis.Warn} Changing your system tag to '{newTag}' will result in the following members being unproxyable, since the tag would bring their name over {Limits.MaxProxyNameLength} characters:\n**{string.Join(", ", unproxyableMembers.Select((m) => m.Name))}**\nDo you want to continue anyway?"); + $"{Emojis.Warn} Changing your system tag to '{newTag.SanitizeMentions()}' will result in the following members being unproxyable, since the tag would bring their name over {Limits.MaxProxyNameLength} characters:\n**{string.Join(", ", unproxyableMembers.Select((m) => m.Name.SanitizeMentions()))}**\nDo you want to continue anyway?"); if (!await ctx.PromptYesNo(msg)) throw new PKError("Tag change cancelled."); } } @@ -143,14 +143,14 @@ namespace PluralKit.Bot.Commands if (system == null) throw Errors.NoSystemError; var members = await _members.GetBySystem(system); - var embedTitle = system.Name != null ? $"Members of {system.Name} (`{system.Hid}`)" : $"Members of `{system.Hid}`"; + var embedTitle = system.Name != null ? $"Members of {system.Name.SanitizeMentions()} (`{system.Hid}`)" : $"Members of `{system.Hid}`"; await ctx.Paginate( members.OrderBy(m => m.Name).ToList(), 25, embedTitle, (eb, ms) => eb.Description = string.Join("\n", ms.Select((m) => { - if (m.HasProxyTags) return $"[`{m.Hid}`] **{m.Name}** *({m.ProxyString})*"; - return $"[`{m.Hid}`] **{m.Name}**"; + if (m.HasProxyTags) return $"[`{m.Hid}`] **{m.Name.SanitizeMentions()}** *({m.ProxyString.SanitizeMentions()})*"; + return $"[`{m.Hid}`] **{m.Name.SanitizeMentions()}**"; })) ); } diff --git a/PluralKit.Bot/Errors.cs b/PluralKit.Bot/Errors.cs index 241f986d..2d5d79ed 100644 --- a/PluralKit.Bot/Errors.cs +++ b/PluralKit.Bot/Errors.cs @@ -23,15 +23,15 @@ namespace PluralKit.Bot { public static PKError MemberNameTooLongError(int length) => new PKError($"Member name too long ({length}/{Limits.MaxMemberNameLength} characters)."); public static PKError MemberPronounsTooLongError(int length) => new PKError($"Member pronouns too long ({length}/{Limits.MaxMemberNameLength} characters)."); - public static PKError InvalidColorError(string color) => new PKError($"\"{color.Sanitize()}\" is not a valid color. Color must be in 6-digit RGB hex format (eg. #ff0000)."); - public static PKError BirthdayParseError(string birthday) => new PKError($"\"{birthday.Sanitize()}\" could not be parsed as a valid date. Try a format like \"2016-12-24\" or \"May 3 1996\"."); + public static PKError InvalidColorError(string color) => new PKError($"\"{color.SanitizeMentions()}\" is not a valid color. Color must be in 6-digit RGB hex format (eg. #ff0000)."); + public static PKError BirthdayParseError(string birthday) => new PKError($"\"{birthday.SanitizeMentions()}\" could not be parsed as a valid date. Try a format like \"2016-12-24\" or \"May 3 1996\"."); public static PKError ProxyMustHaveText => new PKSyntaxError("Example proxy message must contain the string 'text'."); public static PKError ProxyMultipleText => new PKSyntaxError("Example proxy message must contain the string 'text' exactly once."); public static PKError MemberDeleteCancelled => new PKError($"Member deletion cancelled. Stay safe! {Emojis.ThumbsUp}"); public static PKError AvatarServerError(HttpStatusCode statusCode) => new PKError($"Server responded with status code {(int) statusCode}, are you sure your link is working?"); public static PKError AvatarFileSizeLimit(long size) => new PKError($"File size too large ({size.Bytes().ToString("#.#")} > {Limits.AvatarFileSizeLimit.Bytes().ToString("#.#")}), try shrinking or compressing the image."); - public static PKError AvatarNotAnImage(string mimeType) => new PKError($"The given link does not point to an image{(mimeType != null ? $" ({mimeType.Sanitize()})" : "")}. Make sure you're using a direct link (ending in .jpg, .png, .gif)."); + public static PKError AvatarNotAnImage(string mimeType) => new PKError($"The given link does not point to an image{(mimeType != null ? $" ({mimeType.SanitizeMentions()})" : "")}. Make sure you're using a direct link (ending in .jpg, .png, .gif)."); public static PKError AvatarDimensionsTooLarge(int width, int height) => new PKError($"Image too large ({width}x{height} > {Limits.AvatarDimensionLimit}x{Limits.AvatarDimensionLimit}), try resizing the image."); public static PKError UserHasNoAvatar => new PKError("The given user has no avatar set."); public static PKError InvalidUrl(string url) => new PKError($"The given URL is invalid."); @@ -46,38 +46,38 @@ namespace PluralKit.Bot { public static PKError SameSwitch(ICollection members) { if (members.Count == 0) return new PKError("There's already no one in front."); - if (members.Count == 1) return new PKError($"Member {members.First().Name.Sanitize()} is already fronting."); - return new PKError($"Members {string.Join(", ", members.Select(m => m.Name.Sanitize()))} are already fronting."); + if (members.Count == 1) return new PKError($"Member {members.First().Name.SanitizeMentions()} is already fronting."); + return new PKError($"Members {string.Join(", ", members.Select(m => m.Name.SanitizeMentions()))} are already fronting."); } public static PKError DuplicateSwitchMembers => new PKError("Duplicate members in member list."); public static PKError SwitchMemberNotInSystem => new PKError("One or more switch members aren't in your own system."); - public static PKError InvalidDateTime(string str) => new PKError($"Could not parse '{str.Sanitize()}' as a valid date/time. Try using a syntax such as \"May 21, 12:30 PM\" or \"3d12h\" (ie. 3 days, 12 hours ago)."); + public static PKError InvalidDateTime(string str) => new PKError($"Could not parse '{str.SanitizeMentions()}' as a valid date/time. Try using a syntax such as \"May 21, 12:30 PM\" or \"3d12h\" (ie. 3 days, 12 hours ago)."); public static PKError SwitchTimeInFuture => new PKError("Can't move switch to a time in the future."); public static PKError NoRegisteredSwitches => new PKError("There are no registered switches for this system."); public static PKError SwitchMoveBeforeSecondLast(ZonedDateTime time) => new PKError($"Can't move switch to before last switch time ({Formats.ZonedDateTimeFormat.Format(time)}), as it would cause conflicts."); public static PKError SwitchMoveCancelled => new PKError("Switch move cancelled."); public static PKError SwitchDeleteCancelled => new PKError("Switch deletion cancelled."); - public static PKError TimezoneParseError(string timezone) => new PKError($"Could not parse timezone offset {timezone.Sanitize()}. Offset must be a value like 'UTC+5' or 'GMT-4:30'."); + public static PKError TimezoneParseError(string timezone) => new PKError($"Could not parse timezone offset {timezone.SanitizeMentions()}. Offset must be a value like 'UTC+5' or 'GMT-4:30'."); - public static PKError InvalidTimeZone(string zoneStr) => new PKError($"Invalid time zone ID '{zoneStr.Sanitize()}'. To find your time zone ID, use the following website: "); + public static PKError InvalidTimeZone(string zoneStr) => new PKError($"Invalid time zone ID '{zoneStr.SanitizeMentions()}'. To find your time zone ID, use the following website: "); public static PKError TimezoneChangeCancelled => new PKError("Time zone change cancelled."); - public static PKError AmbiguousTimeZone(string zoneStr, int count) => new PKError($"The time zone query '{zoneStr.Sanitize()}' resulted in **{count}** different time zone regions. Try being more specific - e.g. pass an exact time zone specifier from the following website: "); + public static PKError AmbiguousTimeZone(string zoneStr, int count) => new PKError($"The time zone query '{zoneStr.SanitizeMentions()}' resulted in **{count}** different time zone regions. Try being more specific - e.g. pass an exact time zone specifier from the following website: "); public static PKError NoImportFilePassed => new PKError("You must either pass an URL to a file as a command parameter, or as an attachment to the message containing the command."); public static PKError InvalidImportFile => new PKError("Imported data file invalid. Make sure this is a .json file directly exported from PluralKit or Tupperbox."); public static PKError ImportCancelled => new PKError("Import cancelled."); public static PKError MessageNotFound(ulong id) => new PKError($"Message with ID '{id}' not found. Are you sure it's a message proxied by PluralKit?"); - public static PKError DurationParseError(string durationStr) => new PKError($"Could not parse '{durationStr.Sanitize()}' as a valid duration. Try a format such as `30d`, `1d3h` or `20m30s`."); + public static PKError DurationParseError(string durationStr) => new PKError($"Could not parse '{durationStr.SanitizeMentions()}' as a valid duration. Try a format such as `30d`, `1d3h` or `20m30s`."); public static PKError FrontPercentTimeInFuture => new PKError("Cannot get the front percent between now and a time in the future."); public static PKError GuildNotFound(ulong guildId) => new PKError($"Guild with ID {guildId} not found."); public static PKError DisplayNameTooLong(string displayName, int maxLength) => new PKError( $"Display name too long ({displayName.Length} > {maxLength} characters). Use a shorter display name, or shorten your system tag."); - public static PKError ProxyNameTooShort(string name) => new PKError($"The webhook's name, `{name}`, is shorter than two characters, and thus cannot be proxied. Please change the member name or use a longer system tag."); - public static PKError ProxyNameTooLong(string name) => new PKError($"The webhook's name, `{name}`, is too long ({name.Length} > {Limits.MaxProxyNameLength} characters), and thus cannot be proxied. Please change the member name or use a shorter system tag."); + public static PKError ProxyNameTooShort(string name) => new PKError($"The webhook's name, `{name.SanitizeMentions()}`, is shorter than two characters, and thus cannot be proxied. Please change the member name or use a longer system tag."); + public static PKError ProxyNameTooLong(string name) => new PKError($"The webhook's name, {name.SanitizeMentions()}, is too long ({name.Length} > {Limits.MaxProxyNameLength} characters), and thus cannot be proxied. Please change the member name or use a shorter system tag."); } } \ No newline at end of file diff --git a/PluralKit.Bot/Utils.cs b/PluralKit.Bot/Utils.cs index b7c3cd9c..3bac36fa 100644 --- a/PluralKit.Bot/Utils.cs +++ b/PluralKit.Bot/Utils.cs @@ -86,8 +86,8 @@ namespace PluralKit.Bot return false; } - public static string Sanitize(this string input) => - Regex.Replace(Regex.Replace(input, "<@[!&]?(\\d{17,19})>", "<\\@$1>"), "@(everyone|here)", "@\u200B$1"); + public static string SanitizeMentions(this string input) => + Regex.Replace(Regex.Replace(input, "<@[!&]?(\\d{17,19})>", "<\u200B@$1>"), "@(everyone|here)", "@\u200B$1"); public static string SanitizeEveryone(this string input) => Regex.Replace(input, "@(everyone|here)", "@\u200B$1");