diff --git a/DiscordChatExporter.Core/Discord/Data/Attachment.cs b/DiscordChatExporter.Core/Discord/Data/Attachment.cs index 8d7c671..74a70f7 100644 --- a/DiscordChatExporter.Core/Discord/Data/Attachment.cs +++ b/DiscordChatExporter.Core/Discord/Data/Attachment.cs @@ -1,9 +1,9 @@ using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.Json; using DiscordChatExporter.Core.Discord.Data.Common; +using DiscordChatExporter.Core.Utils; using DiscordChatExporter.Core.Utils.Extensions; using JsonExtensions.Reading; @@ -24,11 +24,11 @@ namespace DiscordChatExporter.Core.Discord.Data public int? Height { get; } - public bool IsImage => ImageFileExtensions.Contains(FileExtension); + public bool IsImage => FileFormat.IsImage(FileExtension); - public bool IsVideo => VideoFileExtensions.Contains(FileExtension); + public bool IsVideo => FileFormat.IsVideo(FileExtension); - public bool IsAudio => AudioFileExtensions.Contains(FileExtension); + public bool IsAudio => FileFormat.IsAudio(FileExtension); public bool IsSpoiler => FileName.StartsWith("SPOILER_", StringComparison.Ordinal); @@ -56,15 +56,6 @@ namespace DiscordChatExporter.Core.Discord.Data public partial class Attachment { - private static readonly HashSet ImageFileExtensions = new(StringComparer.OrdinalIgnoreCase) - { ".jpg", ".jpeg", ".png", ".gif", ".gifv", ".bmp", ".webp" }; - - private static readonly HashSet VideoFileExtensions = new(StringComparer.OrdinalIgnoreCase) - { ".mp4", ".webm", ".mov" }; - - private static readonly HashSet AudioFileExtensions = new(StringComparer.OrdinalIgnoreCase) - { ".mp3", ".wav", ".ogg", ".flac", ".m4a" }; - public static Attachment Parse(JsonElement json) { var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); diff --git a/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs b/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs index e826267..510d5c5 100644 --- a/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs +++ b/DiscordChatExporter.Core/Discord/Data/Embeds/Embed.cs @@ -56,6 +56,8 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds Footer = footer; } + public PlainImageEmbedProjection? TryGetPlainImage() => PlainImageEmbedProjection.TryResolve(this); + public SpotifyTrackEmbedProjection? TryGetSpotifyTrack() => SpotifyTrackEmbedProjection.TryResolve(this); public YouTubeVideoEmbedProjection? TryGetYouTubeVideo() => YouTubeVideoEmbedProjection.TryResolve(this); diff --git a/DiscordChatExporter.Core/Discord/Data/Embeds/PlainImageEmbedProjection.cs b/DiscordChatExporter.Core/Discord/Data/Embeds/PlainImageEmbedProjection.cs new file mode 100644 index 0000000..b520eac --- /dev/null +++ b/DiscordChatExporter.Core/Discord/Data/Embeds/PlainImageEmbedProjection.cs @@ -0,0 +1,45 @@ +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using DiscordChatExporter.Core.Utils; + +namespace DiscordChatExporter.Core.Discord.Data.Embeds +{ + public partial class PlainImageEmbedProjection + { + public string Url { get; } + + public PlainImageEmbedProjection(string url) => Url = url; + + [ExcludeFromCodeCoverage] + public override string ToString() => Url; + } + + public partial class PlainImageEmbedProjection + { + public static PlainImageEmbedProjection? TryResolve(Embed embed) + { + if (string.IsNullOrWhiteSpace(embed.Url)) + return null; + + // Has to be an embed without any data (except URL and image) + if (!string.IsNullOrWhiteSpace(embed.Title) || + embed.Timestamp is not null || + embed.Author is not null || + !string.IsNullOrWhiteSpace(embed.Description) || + embed.Fields.Any() || + embed.Footer is not null) + { + return null; + } + + // Has to be an image file + var fileName = Regex.Match(embed.Url, @".+/([^?]*)").Groups[1].Value; + if (string.IsNullOrWhiteSpace(fileName) || !FileFormat.IsImage(Path.GetExtension(fileName))) + return null; + + return new PlainImageEmbedProjection(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 e34709c..07c14ba 100644 --- a/DiscordChatExporter.Core/Exporting/Writers/Html/MessageGroupTemplate.cshtml +++ b/DiscordChatExporter.Core/Exporting/Writers/Html/MessageGroupTemplate.cshtml @@ -176,8 +176,17 @@ @{/* Embeds */} @foreach (var embed in message.Embeds) { + // Plain image embed + if (embed.TryGetPlainImage() is { } plainImageEmbed) + { +
+ + Embedded image + +
+ } // Spotify embed - if (embed.TryGetSpotifyTrack() is { } spotifyTrackEmbed) + else if (embed.TryGetSpotifyTrack() is { } spotifyTrackEmbed) {
diff --git a/DiscordChatExporter.Core/Exporting/Writers/Html/PreambleTemplate.cshtml b/DiscordChatExporter.Core/Exporting/Writers/Html/PreambleTemplate.cshtml index 0bcda39..7f678b0 100644 --- a/DiscordChatExporter.Core/Exporting/Writers/Html/PreambleTemplate.cshtml +++ b/DiscordChatExporter.Core/Exporting/Writers/Html/PreambleTemplate.cshtml @@ -563,6 +563,13 @@ font-weight: 500; } + .chatlog__embed-plainimage { + vertical-align: top; + max-width: 45vw; + max-height: 500px; + border-radius: 3px; + } + .chatlog__embed-spotify { border: 0; } diff --git a/DiscordChatExporter.Core/Utils/FileFormat.cs b/DiscordChatExporter.Core/Utils/FileFormat.cs new file mode 100644 index 0000000..80b78e1 --- /dev/null +++ b/DiscordChatExporter.Core/Utils/FileFormat.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace DiscordChatExporter.Core.Utils +{ + public static class FileFormat + { + private static readonly HashSet ImageFormats = new(StringComparer.OrdinalIgnoreCase) + { + ".jpg", + ".jpeg", + ".png", + ".gif", + ".gifv", + ".bmp", + ".webp" + }; + + public static bool IsImage(string format) => ImageFormats.Contains(format); + + private static readonly HashSet VideoFormats = new(StringComparer.OrdinalIgnoreCase) + { + ".mp4", + ".webm", + ".mov" + }; + + public static bool IsVideo(string format) => VideoFormats.Contains(format); + + private static readonly HashSet AudioFormats = new(StringComparer.OrdinalIgnoreCase) + { + ".mp3", + ".wav", + ".ogg", + ".flac", + ".m4a" + }; + + public static bool IsAudio(string format) => AudioFormats.Contains(format); + } +} \ No newline at end of file