diff --git a/PluralKit.Bot/Services/EmbedService.cs b/PluralKit.Bot/Services/EmbedService.cs index 49c39f1d..a3e0d843 100644 --- a/PluralKit.Bot/Services/EmbedService.cs +++ b/PluralKit.Bot/Services/EmbedService.cs @@ -34,13 +34,13 @@ namespace PluralKit.Bot { .WithTitle(system.Name ?? null) .WithThumbnailUrl(system.AvatarUrl ?? null) .WithFooter($"System ID: {system.Hid}"); - + var latestSwitch = await _switches.GetLatestSwitch(system); if (latestSwitch != null) { var switchMembers = (await _switches.GetSwitchMembers(latestSwitch)).ToList(); if (switchMembers.Count > 0) - eb.AddField("Fronter".ToQuantity(switchMembers.Count(), ShowQuantityAs.None), + eb.AddField("Fronter".ToQuantity(switchMembers.Count(), ShowQuantityAs.None), string.Join(", ", switchMembers.Select(m => m.Name))); } @@ -49,7 +49,7 @@ namespace PluralKit.Bot { eb.AddField($"Members ({memberCount})", $"(see `pk;system {system.Hid} list` or `pk;system {system.Hid} list full`)", true); if (system.Description != null) eb.AddField("Description", system.Description.Truncate(1024), false); - + return eb.Build(); } @@ -68,7 +68,7 @@ namespace PluralKit.Bot { { var name = member.Name; if (system.Name != null) name = $"{member.Name} ({system.Name})"; - + var color = member.Color?.ToDiscordColor() ?? Color.Default; var messageCount = await _members.MessageCount(member); @@ -85,7 +85,7 @@ namespace PluralKit.Bot { if (member.Birthday != null) eb.AddField("Birthdate", member.BirthdayString, true); if (member.Pronouns != null) eb.AddField("Pronouns", member.Pronouns, true); if (messageCount > 0) eb.AddField("Message Count", messageCount, true); - if (member.HasProxyTags) eb.AddField("Proxy Tags", $"{member.Prefix}text{member.Suffix}", true); + if (member.HasProxyTags) eb.AddField("Proxy Tags", $"{member.Prefix.EscapeMarkdown()}text{member.Suffix.EscapeMarkdown()}", true); if (member.Color != null) eb.AddField("Color", $"#{member.Color}", true); if (member.Description != null) eb.AddField("Description", member.Description, false); @@ -115,7 +115,7 @@ namespace PluralKit.Bot { var membersStr = members.Any() ? string.Join(", ", members.Select(m => m.Name)) : "no fronter"; var switchSince = SystemClock.Instance.GetCurrentInstant() - sw.Timestamp; - + // If this isn't the latest switch, we also show duration if (lastSw != null) { @@ -130,7 +130,7 @@ namespace PluralKit.Bot { lastSw = sw; } - + return new EmbedBuilder() .WithTitle("Past switches") .WithDescription(outputStr) @@ -147,7 +147,7 @@ namespace PluralKit.Bot { var user = await _client.GetUserAsync(msg.Message.Sender); var userStr = user.NameAndMention() ?? $"*(deleted user {msg.Message.Sender})*"; - + return new EmbedBuilder() .WithAuthor(msg.Member.Name, msg.Member.AvatarUrl) .WithDescription(serverMsg?.Content ?? "*(message contents deleted or inaccessible)*") @@ -170,9 +170,9 @@ namespace PluralKit.Bot { // We convert to a list of pairs so we can add the no-fronter value // Dictionary doesn't allow for null keys so we instead have a pair with a null key ;) var pairs = frontpercent.MemberSwitchDurations.ToList(); - if (frontpercent.NoFronterDuration != Duration.Zero) + if (frontpercent.NoFronterDuration != Duration.Zero) pairs.Add(new KeyValuePair(null, frontpercent.NoFronterDuration)); - + var membersOrdered = pairs.OrderByDescending(pair => pair.Value).Take(maxEntriesToDisplay).ToList(); foreach (var pair in membersOrdered) { diff --git a/PluralKit.Bot/Utils.cs b/PluralKit.Bot/Utils.cs index 4458a6ce..e6a1e4fa 100644 --- a/PluralKit.Bot/Utils.cs +++ b/PluralKit.Bot/Utils.cs @@ -49,7 +49,7 @@ namespace PluralKit.Bot { throw Errors.InvalidUrl(url); } - + var response = await client.GetAsync(uri); if (!response.IsSuccessStatusCode) // Check status code throw Errors.AvatarServerError(response.StatusCode); @@ -63,11 +63,11 @@ namespace PluralKit.Bot // Parse the image header in a worker var stream = await response.Content.ReadAsStreamAsync(); var image = await Task.Run(() => Image.Identify(stream)); - if (image.Width > Limits.AvatarDimensionLimit || image.Height > Limits.AvatarDimensionLimit) // Check image size + if (image.Width > Limits.AvatarDimensionLimit || image.Height > Limits.AvatarDimensionLimit) // Check image size throw Errors.AvatarDimensionsTooLarge(image.Width, image.Height); } } - + public static bool HasMentionPrefix(string content, ref int argPos) { // Roughly ported from Discord.Commands.MessageExtensions.HasMentionPrefix @@ -82,10 +82,17 @@ namespace PluralKit.Bot public static string Sanitize(this string input) => Regex.Replace(Regex.Replace(input, "<@[!&]?(\\d{17,19})>", "<\\@$1>"), "@(everyone|here)", "@\u200B$1"); - - public static string SanitizeEveryone(this string input) => + + public static string SanitizeEveryone(this string input) => Regex.Replace(input, "@(everyone|here)", "@\u200B$1"); + public static string EscapeMarkdown(this string input) + { + Regex pattern = new Regex(@"[*_~>`(||)\\]", RegexOptions.Multiline); + if (input != null) return pattern.Replace(input, @"\$&"); + else return input; + } + public static async Task PermissionsIn(this IChannel channel) { switch (channel) diff --git a/docs/2-command-list.md b/docs/2-command-list.md index 14b61656..6d2f4b41 100644 --- a/docs/2-command-list.md +++ b/docs/2-command-list.md @@ -11,7 +11,7 @@ Words in \ are *required parameters*. Words in [square brackets] ## System commands - `pk;system [id]` - Shows information about a system. - `pk;system new [name]` - Creates a new system registered to your account. -- `pk;system rename [new name]` - Changes the description of your system. +- `pk;system rename [new name]` - Changes the name of your system. - `pk;system description [description]` - Changes the description of your system. - `pk;system avatar [avatar url]` - Changes the avatar of your system. - `pk;system tag [tag]` - Changes the system tag of your system. diff --git a/docs/3-api-documentation.md b/docs/3-api-documentation.md index ccc9d68d..3f8a5ec4 100644 --- a/docs/3-api-documentation.md +++ b/docs/3-api-documentation.md @@ -110,7 +110,7 @@ Queries a system's member list by its 5-character ID. If the system doesn't exis #### Example request GET https://api.pluralkit.me/v1/s/abcde/members - + #### Example response ```json [ @@ -189,7 +189,7 @@ Edits your own system's information. Missing fields will be set to `null`. Will #### Example request PATCH https://api.pluralkit.me/v1/s - + ```json { "name": "New System Name", @@ -220,7 +220,7 @@ Registers a new switch to your own system given a list of member IDs. #### Example request POST https://api.pluralkit.me/v1/s/switches - + ```json { "members": ["qwert", "yuiop"] @@ -252,14 +252,14 @@ Queries a member's information by its 5-character member ID. If the member does } ``` -### PATCH /m/\ +### POST /m **Requires authentication.** -Edits a member's information. Missing fields will be set to `null`. Will return the new member object. Member must (obviously) belong to your own system. +Creates a new member with the information given. Missing fields (except for name) will be set to `null`. Will return the new member object. Member must (obviously) belong to your own system. #### Example request - PATCH https://api.pluralkit.me/v1/m/qwert - + POST https://api.pluralkit.me/v1/m + ```json { "name": "Craig Peterson", @@ -271,7 +271,44 @@ Edits a member's information. Missing fields will be set to `null`. Will return "prefix": "[" } ``` -(note the absence of a `suffix` field, which is set to null in the response) +(note the absence of a `suffix` field, which is set to null in the response) + +#### Example response +```json +{ + "id": "qwert", + "name": "Craig Peterson", + "color": null, + "avatar_url": "https://path/to/new/image.png", + "birthday": "1997-07-14", + "pronouns": "they/them", + "description": "I am Craig, cooler example user extraordinaire.", + "prefix": "[", + "suffix": null, + "created": "2019-01-01T15:00:00.654321Z" +} +``` + +### PATCH /m/\ +**Requires authentication.** + +Edits a member's information. Missing fields will be set to `null`. Will return the new member object. Member must (obviously) belong to your own system. + +#### Example request + PATCH https://api.pluralkit.me/v1/m/qwert + +```json +{ + "name": "Craig Peterson", + "color": null, + "avatar_url": "https://path/to/new/image.png", + "birthday": "1997-07-14", + "pronouns": "they/them", + "description": "I am Craig, cooler example user extraordinaire.", + "prefix": "[" +} +``` +(note the absence of a `suffix` field, which is set to null in the response) #### Example response ```json