mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-02-14 07:43:31 -07:00
Add HTML formatting for system messages (#926)
This commit is contained in:
parent
57c849d0f8
commit
8612d2c84a
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -5,6 +5,7 @@
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
.idea/
|
.idea/
|
||||||
.vs/
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
# Build results
|
# Build results
|
||||||
[Dd]ebug/
|
[Dd]ebug/
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
namespace DiscordChatExporter.Core.Discord.Data;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Discord.Data;
|
||||||
|
|
||||||
// https://discord.com/developers/docs/resources/channel#message-object-message-types
|
// https://discord.com/developers/docs/resources/channel#message-object-message-types
|
||||||
public enum MessageKind
|
public enum MessageKind
|
||||||
|
|
@ -13,3 +15,13 @@ public enum MessageKind
|
||||||
GuildMemberJoin = 7,
|
GuildMemberJoin = 7,
|
||||||
Reply = 19
|
Reply = 19
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class MessageKindExtensions
|
||||||
|
{
|
||||||
|
public static bool IsSystemMessage(this MessageKind c) =>
|
||||||
|
c is not MessageKind.Default and not MessageKind.Reply;
|
||||||
|
|
||||||
|
public static string ToCssIdFormat(this MessageKind c) =>
|
||||||
|
string.Join("-", Regex.Split(c.ToString(), @"(?<!^)(?=[A-Z])")).ToLowerInvariant();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -46,13 +46,19 @@
|
||||||
<div class="chatlog__message-group">
|
<div class="chatlog__message-group">
|
||||||
@foreach (var (message, i) in Model.Messages.WithIndex())
|
@foreach (var (message, i) in Model.Messages.WithIndex())
|
||||||
{
|
{
|
||||||
|
var isSystemMessage = message.Kind.IsSystemMessage();
|
||||||
|
|
||||||
var isFirst = i == 0;
|
var isFirst = i == 0;
|
||||||
|
|
||||||
<div id="chatlog__message-container-@message.Id" class="chatlog__message-container @(message.IsPinned ? "chatlog__message-container--pinned" : null)" data-message-id="@message.Id">
|
<div id="chatlog__message-container-@message.Id" class="chatlog__message-container @(message.IsPinned ? "chatlog__message-container--pinned" : null)" data-message-id="@message.Id">
|
||||||
<div class="chatlog__message">
|
<div class="chatlog__message">
|
||||||
@{/* Left side */}
|
@{/* Left side */}
|
||||||
<div class="chatlog__message-aside">
|
<div class="chatlog__message-aside">
|
||||||
@if (isFirst)
|
@if (isSystemMessage)
|
||||||
|
{
|
||||||
|
<svg class=chatlog__system-message-icon><use href="#@message.Kind.ToCssIdFormat()-icon"></use></svg>
|
||||||
|
}
|
||||||
|
else if(isFirst)
|
||||||
{
|
{
|
||||||
// Reference symbol
|
// Reference symbol
|
||||||
if (message.Reference is not null)
|
if (message.Reference is not null)
|
||||||
|
|
@ -71,7 +77,38 @@
|
||||||
|
|
||||||
@{/* Right side */}
|
@{/* Right side */}
|
||||||
<div class="chatlog__message-primary">
|
<div class="chatlog__message-primary">
|
||||||
@if (isFirst)
|
@if (isSystemMessage)
|
||||||
|
{
|
||||||
|
|
||||||
|
// system messages are grouped even if the message author is different
|
||||||
|
// that's why we have to update the user values with the author of the current message
|
||||||
|
userMember = Model.ExportContext.TryGetMember(message.Author.Id);
|
||||||
|
|
||||||
|
userColor = Model.ExportContext.TryGetUserColor(message.Author.Id);
|
||||||
|
|
||||||
|
userNick = message.Author.IsBot
|
||||||
|
? message.Author.Name
|
||||||
|
: userMember?.Nick ?? message.Author.Name;
|
||||||
|
|
||||||
|
<div class="chatlog__header">
|
||||||
|
@{/* Author name */}
|
||||||
|
<span class="chatlog__author" style="@(userColor is not null ? $"color: rgb({userColor.Value.R}, {userColor.Value.G}, {userColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@userNick</span>
|
||||||
|
|
||||||
|
@{/* System message content */}
|
||||||
|
@if(message.Kind == MessageKind.ChannelPinnedMessage)
|
||||||
|
{
|
||||||
|
<span class="chatlog__system-message"> pinned</span><span class="chatlog__system-message-reference-link chatlog__reference-link" onclick="scrollToMessage(event, @message.Reference.MessageId)"> a message</span><span class="chatlog__system-message"> to this channel.</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="chatlog__system-message"> <!--wmm:ignore-->@Raw(FormatMarkdown(Char.ToLowerInvariant(message.Content[0]) + message.Content.Substring(1)))<!--/wmm:ignore--></span>
|
||||||
|
}
|
||||||
|
|
||||||
|
@{/* Timestamp */}
|
||||||
|
<span class="chatlog__timestamp"><a href="#chatlog__message-container-@message.Id">@FormatDate(message.Timestamp)</a></span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else if (isFirst)
|
||||||
{
|
{
|
||||||
// Reference
|
// Reference
|
||||||
if (message.Reference is not null)
|
if (message.Reference is not null)
|
||||||
|
|
@ -130,21 +167,24 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@{/* Content */}
|
@{/* Content */}
|
||||||
@if (!string.IsNullOrWhiteSpace(message.Content) || message.EditedTimestamp is not null)
|
@if (!isSystemMessage)
|
||||||
{
|
{
|
||||||
<div class="chatlog__content chatlog__markdown">
|
@if (!string.IsNullOrWhiteSpace(message.Content) || message.EditedTimestamp is not null)
|
||||||
@{/* Text */}
|
{
|
||||||
@if (!message.IsContentHidden())
|
<div class="chatlog__content chatlog__markdown">
|
||||||
{
|
@{/* Text */}
|
||||||
<span class="chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatMarkdown(message.Content))<!--/wmm:ignore--></span>
|
@if (!message.IsContentHidden())
|
||||||
}
|
{
|
||||||
|
<span class="chatlog__markdown-preserve"><!--wmm:ignore-->@Raw(FormatMarkdown(message.Content))<!--/wmm:ignore--></span>
|
||||||
|
}
|
||||||
|
|
||||||
@{/* Edited timestamp */}
|
@{/* Edited timestamp */}
|
||||||
@if (message.EditedTimestamp is not null)
|
@if (message.EditedTimestamp is not null)
|
||||||
{
|
{
|
||||||
<span class="chatlog__edited-timestamp" title="@FormatDate(message.EditedTimestamp.Value)">(edited)</span>
|
<span class="chatlog__edited-timestamp" title="@FormatDate(message.EditedTimestamp.Value)">(edited)</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@{/* Attachments */}
|
@{/* Attachments */}
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,21 @@
|
||||||
unicode-bidi: bidi-override;
|
unicode-bidi: bidi-override;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chatlog__system-message{
|
||||||
|
color: #96989D
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__system-message-reference-link{
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__system-message-icon{
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.chatlog__header {
|
.chatlog__header {
|
||||||
margin-bottom: 0.1rem;
|
margin-bottom: 0.1rem;
|
||||||
}
|
}
|
||||||
|
|
@ -786,13 +801,27 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@{/* Icons */}
|
@{/* Icons */}
|
||||||
<svg style="display: none">
|
<svg style="display: none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<symbol id="attachment-icon" viewBox="0 0 720 960">
|
<defs>
|
||||||
<path fill="#f4f5fb" d="M50,935a25,25,0,0,1-25-25V50A25,25,0,0,1,50,25H519.6L695,201.32V910a25,25,0,0,1-25,25Z"/>
|
<symbol id="attachment-icon" viewBox="0 0 720 960">
|
||||||
<path fill="#7789c4" d="M509.21,50,670,211.63V910H50V50H509.21M530,0H50A50,50,0,0,0,0,50V910a50,50,0,0,0,50,50H670a50,50,0,0,0,50-50h0V191Z"/>
|
<path fill="#f4f5fb" d="M50,935a25,25,0,0,1-25-25V50A25,25,0,0,1,50,25H519.6L695,201.32V910a25,25,0,0,1-25,25Z"/>
|
||||||
<path fill="#f4f5fb" d="M530,215a25,25,0,0,1-25-25V50a25,25,0,0,1,16.23-23.41L693.41,198.77A25,25,0,0,1,670,215Z"/>
|
<path fill="#7789c4" d="M509.21,50,670,211.63V910H50V50H509.21M530,0H50A50,50,0,0,0,0,50V910a50,50,0,0,0,50,50H670a50,50,0,0,0,50-50h0V191Z"/>
|
||||||
<path fill="#7789c4" d="M530,70.71,649.29,190H530V70.71M530,0a50,50,0,0,0-50,50V190a50,50,0,0,0,50,50H670a50,50,0,0,0,50-50Z"/>
|
<path fill="#f4f5fb" d="M530,215a25,25,0,0,1-25-25V50a25,25,0,0,1,16.23-23.41L693.41,198.77A25,25,0,0,1,670,215Z"/>
|
||||||
</symbol>
|
<path fill="#7789c4" d="M530,70.71,649.29,190H530V70.71M530,0a50,50,0,0,0-50,50V190a50,50,0,0,0,50,50H670a50,50,0,0,0,50-50Z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="channel-pinned-message-icon" fill="none" viewBox="0 0 17 17">
|
||||||
|
<path d="m16.908 8.39684-8.29587-8.295827-1.18584 1.184157 1.18584 1.18584-4.14834 4.1475v.00167l-1.18583-1.18583-1.185 1.18583 3.55583 3.55502-4.740831 4.74 1.185001 1.185 4.74083-4.74 3.55581 3.555 1.185-1.185-1.185-1.185 4.1475-4.14836h.0009l1.185 1.185z" fill="#b9bbbe"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="call-icon" viewBox="0 0 18 18">
|
||||||
|
<path fill="#3ba55c" fill-rule="evenodd" d="M17.7163041 15.36645368c-.0190957.02699568-1.9039523 2.6680735-2.9957762 2.63320406-3.0676659-.09785935-6.6733809-3.07188394-9.15694343-5.548738C3.08002193 9.9740657.09772497 6.3791404 0 3.3061316v-.024746C0 2.2060575 2.61386252.3152347 2.64082114.2972376c.7110335-.4971705 1.4917101-.3149497 1.80959713.1372281.19320342.2744561 2.19712724 3.2811005 2.42290565 3.6489167.09884826.1608492.14714912.3554431.14714912.5702838 0 .2744561-.07975258.5770327-.23701117.8751101-.1527655.2902036-.65262318 1.1664385-.89862055 1.594995.2673396.3768148.94804468 1.26429792 2.351016 2.66357424 1.39173858 1.39027775 2.28923588 2.07641807 2.67002628 2.34187563.4302146-.2452108 1.3086162-.74238132 1.5972981-.89423205.5447887-.28682915 1.0907006-.31944893 1.4568885-.08661115.3459689.2182151 3.3383754 2.21027167 3.6225641 2.41611376.2695862.19234426.4144887.5399137.4144887.91672846 0 .2969525-.089862.61190215-.2808189.88523346"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="guild-member-join-icon" viewBox="0 0 18 18">
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<path d="m18 0h-18v18h18z"/>
|
||||||
|
<path d="m0 8h14.2l-3.6-3.6 1.4-1.4 6 6-6 6-1.4-1.4 3.6-3.6h-14.2" fill="#3ba55c"/>
|
||||||
|
</g>
|
||||||
|
</symbol>
|
||||||
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,23 @@ internal class HtmlMessageWriter : MessageWriter
|
||||||
_themeName = themeName;
|
_themeName = themeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanJoinGroup(Message message) =>
|
private bool CanJoinGroup(Message message)
|
||||||
|
{
|
||||||
// First message in the group can always join
|
// First message in the group can always join
|
||||||
_messageGroup.LastOrDefault() is not { } lastMessage ||
|
if(_messageGroup.LastOrDefault() is not { } lastMessage)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group system messages with other system messages, regardless of author
|
||||||
|
if (message.Kind.IsSystemMessage())
|
||||||
|
{
|
||||||
|
return lastMessage.Kind.IsSystemMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
// Must be a non system message
|
||||||
|
!message.Kind.IsSystemMessage() &&
|
||||||
// Must be from the same author
|
// Must be from the same author
|
||||||
lastMessage.Author.Id == message.Author.Id &&
|
lastMessage.Author.Id == message.Author.Id &&
|
||||||
// Author's name must not have changed between messages
|
// Author's name must not have changed between messages
|
||||||
|
|
@ -36,6 +50,7 @@ internal class HtmlMessageWriter : MessageWriter
|
||||||
(message.Timestamp - lastMessage.Timestamp).Duration().TotalMinutes <= 7 &&
|
(message.Timestamp - lastMessage.Timestamp).Duration().TotalMinutes <= 7 &&
|
||||||
// Other message must not be a reply
|
// Other message must not be a reply
|
||||||
message.Reference is null;
|
message.Reference is null;
|
||||||
|
}
|
||||||
|
|
||||||
// Use <!--wmm:ignore--> to preserve blocks of code inside the templates
|
// Use <!--wmm:ignore--> to preserve blocks of code inside the templates
|
||||||
private string Minify(string html) => _minifier
|
private string Minify(string html) => _minifier
|
||||||
|
|
@ -77,7 +92,7 @@ internal class HtmlMessageWriter : MessageWriter
|
||||||
await base.WriteMessageAsync(message, cancellationToken);
|
await base.WriteMessageAsync(message, cancellationToken);
|
||||||
|
|
||||||
// If the message can be grouped, buffer it for now
|
// If the message can be grouped, buffer it for now
|
||||||
if (CanJoinGroup( message))
|
if (CanJoinGroup(message))
|
||||||
{
|
{
|
||||||
_messageGroup.Add(message);
|
_messageGroup.Add(message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue