From f28d662a71b64b454206311a78800ad14f76cfd6 Mon Sep 17 00:00:00 2001 From: gan-of-culture <53971163+gan-of-culture@users.noreply.github.com> Date: Sat, 10 Sep 2022 22:48:52 +0200 Subject: [PATCH] Support GIF embeds when exporting to HTML (#919) --- .../Discord/Data/Embeds/Embed.cs | 10 +++++++++ .../Discord/Data/Embeds/EmbedVideo.cs | 22 +++++++++++++++++++ .../Data/Embeds/GifvEmbedProjection.cs | 21 ++++++++++++++++++ .../Writers/Html/MessageGroupTemplate.cshtml | 14 +++++++++++- 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 DiscordChatExporter.Core/Discord/Data/Embeds/EmbedVideo.cs create mode 100644 DiscordChatExporter.Core/Discord/Data/Embeds/GifvEmbedProjection.cs diff --git a/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs b/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs index 3e8363c..524b0b8 100644 --- a/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs +++ b/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs @@ -11,6 +11,7 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds; // https://discord.com/developers/docs/resources/channel#embed-object public partial record Embed( string? Title, + string? Type, string? Url, DateTimeOffset? Timestamp, Color? Color, @@ -19,6 +20,7 @@ public partial record Embed( IReadOnlyList Fields, EmbedImage? Thumbnail, IReadOnlyList Images, + EmbedVideo? Video, EmbedFooter? Footer) { public PlainImageEmbedProjection? TryGetPlainImage() => @@ -29,6 +31,9 @@ public partial record Embed( public YouTubeVideoEmbedProjection? TryGetYouTubeVideo() => YouTubeVideoEmbedProjection.TryResolve(this); + + public GifvEmbedProjection? TryGetGifv() => + GifvEmbedProjection.TryResolve(this); } public partial record Embed @@ -36,6 +41,7 @@ public partial record Embed public static Embed Parse(JsonElement json) { var title = json.GetPropertyOrNull("title")?.GetStringOrNull(); + var type = json.GetPropertyOrNull("type")?.GetStringOrNull(); var url = json.GetPropertyOrNull("url")?.GetNonWhiteSpaceStringOrNull(); var timestamp = json.GetPropertyOrNull("timestamp")?.GetDateTimeOffset(); var color = json.GetPropertyOrNull("color")?.GetInt32OrNull()?.Pipe(System.Drawing.Color.FromArgb).ResetAlpha(); @@ -59,10 +65,13 @@ public partial record Embed json.GetPropertyOrNull("image")?.Pipe(EmbedImage.Parse).Enumerate().ToArray() ?? Array.Empty(); + var video = json.GetPropertyOrNull("video")?.Pipe(EmbedVideo.Parse); + var footer = json.GetPropertyOrNull("footer")?.Pipe(EmbedFooter.Parse); return new Embed( title, + type, url, timestamp, color, @@ -71,6 +80,7 @@ public partial record Embed fields, thumbnail, images, + video, footer ); } diff --git a/DiscordChatExporter.Core/Discord/Data/Embeds/EmbedVideo.cs b/DiscordChatExporter.Core/Discord/Data/Embeds/EmbedVideo.cs new file mode 100644 index 0000000..6a48e81 --- /dev/null +++ b/DiscordChatExporter.Core/Discord/Data/Embeds/EmbedVideo.cs @@ -0,0 +1,22 @@ +using JsonExtensions.Reading; +using System.Text.Json; + +namespace DiscordChatExporter.Core.Discord.Data.Embeds; + +// https://discord.com/developers/docs/resources/channel#embed-object-embed-video-structure +public record EmbedVideo( + string? Url, + string? ProxyUrl, + int? Width, + int? Height) +{ + public static EmbedVideo Parse(JsonElement json) + { + var url = json.GetPropertyOrNull("url")?.GetNonWhiteSpaceStringOrNull(); + var proxyUrl = json.GetPropertyOrNull("proxy_url")?.GetNonWhiteSpaceStringOrNull(); + var width = json.GetPropertyOrNull("width")?.GetInt32OrNull(); + var height = json.GetPropertyOrNull("height")?.GetInt32OrNull(); + + return new EmbedVideo(url, proxyUrl, width, height); + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Core/Discord/Data/Embeds/GifvEmbedProjection.cs b/DiscordChatExporter.Core/Discord/Data/Embeds/GifvEmbedProjection.cs new file mode 100644 index 0000000..2ef8cb7 --- /dev/null +++ b/DiscordChatExporter.Core/Discord/Data/Embeds/GifvEmbedProjection.cs @@ -0,0 +1,21 @@ +using System; +using System.Text.RegularExpressions; + +namespace DiscordChatExporter.Core.Discord.Data.Embeds; + +public partial record GifvEmbedProjection(string Url) +{ + public static GifvEmbedProjection? TryResolve(Embed embed) + { + if (string.IsNullOrWhiteSpace(embed.Url)) + return null; + + if (embed.Video is null || string.IsNullOrWhiteSpace(embed.Video.Url)) + return null; + + if (!string.Equals(embed.Type, "gifv", StringComparison.OrdinalIgnoreCase)) + return null; + + return new GifvEmbedProjection(embed.Url); + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Core/Exporting/Writers/Html/MessageGroupTemplate.cshtml b/DiscordChatExporter.Core/Exporting/Writers/Html/MessageGroupTemplate.cshtml index ffa4295..0e4d583 100644 --- a/DiscordChatExporter.Core/Exporting/Writers/Html/MessageGroupTemplate.cshtml +++ b/DiscordChatExporter.Core/Exporting/Writers/Html/MessageGroupTemplate.cshtml @@ -208,8 +208,20 @@ @{/* Embeds */} @foreach (var embed in message.Embeds) { + // Gifv embed + if (embed.TryGetGifv() is { } gifvEmbed) + { + @if (embed.Video is not null && !string.IsNullOrWhiteSpace(embed.Video.Url) && embed.Thumbnail is not null) + { +
+ +
+ } + } // Plain image embed - if (embed.TryGetPlainImage() is { } plainImageEmbed) + else if (embed.TryGetPlainImage() is { } plainImageEmbed) {