-
-
Notifications
You must be signed in to change notification settings - Fork 995
Add action row support #1484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: prime
Are you sure you want to change the base?
Add action row support #1484
Changes from 7 commits
fcf58f5
231857e
a54e011
09f9f38
1a671b3
0414da2
2bf8b86
08524e9
b889603
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| using System; | ||
| using System.Text.Json; | ||
| using DiscordChatExporter.Core.Discord.Data.Common; | ||
| using DiscordChatExporter.Core.Utils.Extensions; | ||
| using JsonExtensions.Reading; | ||
|
|
||
| namespace DiscordChatExporter.Core.Discord.Data.Components; | ||
|
|
||
| // https://discord.com/developers/docs/components/reference#button | ||
| public partial record ButtonComponent( | ||
| ButtonStyle Style, | ||
| string? Label, | ||
| Emoji? Emoji, | ||
| string? Url, | ||
| string? CustomId, | ||
| Snowflake? SkuId, | ||
| bool IsDisabled | ||
| ) | ||
| { | ||
| public bool IsUrlButton => !string.IsNullOrWhiteSpace(Url); | ||
| } | ||
|
|
||
| public partial record ButtonComponent | ||
| { | ||
| public static ButtonComponent Parse(JsonElement json) | ||
| { | ||
| var style = | ||
| json.GetPropertyOrNull("style") | ||
| ?.GetInt32OrNull() | ||
| ?.Pipe(s => | ||
| Enum.IsDefined(typeof(ButtonStyle), s) ? (ButtonStyle)s : (ButtonStyle?)null | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can just do |
||
| ) | ||
| ?? ButtonStyle.Secondary; | ||
|
|
||
| var label = json.GetPropertyOrNull("label")?.GetStringOrNull(); | ||
| var emoji = json.GetPropertyOrNull("emoji")?.Pipe(Emoji.Parse); | ||
|
|
||
| var url = json.GetPropertyOrNull("url")?.GetNonWhiteSpaceStringOrNull(); | ||
| var customId = json.GetPropertyOrNull("custom_id")?.GetNonWhiteSpaceStringOrNull(); | ||
| var skuId = json.GetPropertyOrNull("sku_id") | ||
| ?.GetNonWhiteSpaceStringOrNull() | ||
| ?.Pipe(Snowflake.Parse); | ||
|
|
||
| var isDisabled = json.GetPropertyOrNull("disabled")?.GetBooleanOrNull() ?? false; | ||
|
|
||
| return new ButtonComponent(style, label, emoji, url, customId, skuId, isDisabled); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| namespace DiscordChatExporter.Core.Discord.Data.Components; | ||
|
|
||
| // https://discord.com/developers/docs/components/reference#button-button-styles | ||
| public enum ButtonStyle | ||
| { | ||
| Primary = 1, | ||
| Secondary = 2, | ||
| Success = 3, | ||
| Danger = 4, | ||
| Link = 5, | ||
| Premium = 6, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text.Json; | ||
| using DiscordChatExporter.Core.Utils.Extensions; | ||
| using JsonExtensions.Reading; | ||
|
|
||
| namespace DiscordChatExporter.Core.Discord.Data.Components; | ||
|
|
||
| // https://docs.discord.com/developers/components/reference#component-object | ||
|
solareon marked this conversation as resolved.
|
||
| public partial record MessageComponent( | ||
|
Tyrrrz marked this conversation as resolved.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The design I was thinking about was more like this:
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The rendering code would then pattern match via: component switch
{
ButtonMessageComponent button => ...
ActionRowComponent actionRow => ...
} |
||
| MessageComponentType Kind, | ||
| IReadOnlyList<MessageComponent> Components, | ||
| ButtonComponent? Button | ||
| ) | ||
| { | ||
| public bool HasButtons => Button is not null || Components.Any(c => c.HasButtons); | ||
|
|
||
| public IReadOnlyList<ButtonComponent> Buttons => | ||
| Components.Select(c => c.Button).WhereNotNull().ToArray(); | ||
| } | ||
|
|
||
| public partial record MessageComponent | ||
| { | ||
| public static MessageComponent? Parse(JsonElement json) | ||
| { | ||
| var rawType = json.GetPropertyOrNull("type")?.GetInt32OrNull(); | ||
| if (rawType is null) | ||
| return null; | ||
|
|
||
| var type = rawType.Value; | ||
| if (!Enum.IsDefined(typeof(MessageComponentType), type)) | ||
| return null; | ||
|
Comment on lines
+32
to
+33
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure this check is necessary? If that value is not defined in the enum, your current logic would flow through to |
||
|
|
||
| return Parse((MessageComponentType)type, json); | ||
| } | ||
|
|
||
| private static MessageComponent Parse(MessageComponentType type, JsonElement json) | ||
| { | ||
| return type switch | ||
| { | ||
| MessageComponentType.Button => ParseButton(json), | ||
| _ => ParseDefault(type, json), | ||
| }; | ||
| } | ||
|
|
||
| private static MessageComponent ParseDefault(MessageComponentType type, JsonElement json) | ||
| { | ||
| var components = ParseComponents(json); | ||
|
|
||
| return new MessageComponent(type, components, null); | ||
| } | ||
|
|
||
| private static MessageComponent ParseButton(JsonElement json) | ||
| { | ||
| var components = ParseComponents(json); | ||
| var button = ButtonComponent.Parse(json); | ||
|
|
||
| return new MessageComponent(MessageComponentType.Button, components, button); | ||
| } | ||
|
|
||
| private static MessageComponent[] ParseComponents(JsonElement json) | ||
| { | ||
| return json.GetPropertyOrNull("components") | ||
| ?.EnumerateArrayOrNull() | ||
| ?.Select(Parse) | ||
| .WhereNotNull() | ||
| .ToArray() | ||
| ?? []; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| namespace DiscordChatExporter.Core.Discord.Data.Components; | ||
|
|
||
| // https://discord.com/developers/docs/components/reference#component-object-component-types | ||
| public enum MessageComponentType | ||
| { | ||
| ActionRow = 1, | ||
| Button = 2, | ||
| StringSelect = 3, | ||
| TextInput = 4, | ||
| UserSelect = 5, | ||
| RoleSelect = 6, | ||
| MentionableSelect = 7, | ||
| ChannelSelect = 8, | ||
| Section = 9, | ||
| TextDisplay = 10, | ||
| Thumbnail = 11, | ||
| MediaGallery = 12, | ||
| File = 13, | ||
| Separator = 14, | ||
| Container = 17, | ||
| Label = 18, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.