mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-06-05 09:13:44 -04:00
Add support for replies (#455)
This commit is contained in:
parent
097a75e326
commit
07ac805677
8 changed files with 151 additions and 5 deletions
|
@ -18,7 +18,8 @@ namespace DiscordChatExporter.Domain.Discord.Models
|
||||||
ChannelNameChange,
|
ChannelNameChange,
|
||||||
ChannelIconChange,
|
ChannelIconChange,
|
||||||
ChannelPinnedMessage,
|
ChannelPinnedMessage,
|
||||||
GuildMemberJoin
|
GuildMemberJoin,
|
||||||
|
Reply = 19
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://discord.com/developers/docs/resources/channel#message-object
|
// https://discord.com/developers/docs/resources/channel#message-object
|
||||||
|
@ -48,6 +49,10 @@ namespace DiscordChatExporter.Domain.Discord.Models
|
||||||
|
|
||||||
public IReadOnlyList<User> MentionedUsers { get; }
|
public IReadOnlyList<User> MentionedUsers { get; }
|
||||||
|
|
||||||
|
public MessageReference? Reference {get; }
|
||||||
|
|
||||||
|
public Message? ReferencedMessage {get; }
|
||||||
|
|
||||||
public Message(
|
public Message(
|
||||||
Snowflake id,
|
Snowflake id,
|
||||||
MessageType type,
|
MessageType type,
|
||||||
|
@ -60,7 +65,9 @@ namespace DiscordChatExporter.Domain.Discord.Models
|
||||||
IReadOnlyList<Attachment> attachments,
|
IReadOnlyList<Attachment> attachments,
|
||||||
IReadOnlyList<Embed> embeds,
|
IReadOnlyList<Embed> embeds,
|
||||||
IReadOnlyList<Reaction> reactions,
|
IReadOnlyList<Reaction> reactions,
|
||||||
IReadOnlyList<User> mentionedUsers)
|
IReadOnlyList<User> mentionedUsers,
|
||||||
|
MessageReference? messageReference,
|
||||||
|
Message? referencedMessage)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Type = type;
|
Type = type;
|
||||||
|
@ -74,6 +81,8 @@ namespace DiscordChatExporter.Domain.Discord.Models
|
||||||
Embeds = embeds;
|
Embeds = embeds;
|
||||||
Reactions = reactions;
|
Reactions = reactions;
|
||||||
MentionedUsers = mentionedUsers;
|
MentionedUsers = mentionedUsers;
|
||||||
|
Reference = messageReference;
|
||||||
|
ReferencedMessage = referencedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => Content;
|
public override string ToString() => Content;
|
||||||
|
@ -90,6 +99,8 @@ namespace DiscordChatExporter.Domain.Discord.Models
|
||||||
var callEndedTimestamp = json.GetPropertyOrNull("call")?.GetPropertyOrNull("ended_timestamp")?.GetDateTimeOffset();
|
var callEndedTimestamp = json.GetPropertyOrNull("call")?.GetPropertyOrNull("ended_timestamp")?.GetDateTimeOffset();
|
||||||
var type = (MessageType) json.GetProperty("type").GetInt32();
|
var type = (MessageType) json.GetProperty("type").GetInt32();
|
||||||
var isPinned = json.GetPropertyOrNull("pinned")?.GetBoolean() ?? false;
|
var isPinned = json.GetPropertyOrNull("pinned")?.GetBoolean() ?? false;
|
||||||
|
var messageReference = json.GetPropertyOrNull("message_reference")?.Pipe(MessageReference.Parse);
|
||||||
|
var referencedMessage = json.GetPropertyOrNull("referenced_message")?.Pipe(Message.Parse);
|
||||||
|
|
||||||
var content = type switch
|
var content = type switch
|
||||||
{
|
{
|
||||||
|
@ -132,7 +143,9 @@ namespace DiscordChatExporter.Domain.Discord.Models
|
||||||
attachments,
|
attachments,
|
||||||
embeds,
|
embeds,
|
||||||
reactions,
|
reactions,
|
||||||
mentionedUsers
|
mentionedUsers,
|
||||||
|
messageReference,
|
||||||
|
referencedMessage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using JsonExtensions.Reading;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Domain.Discord.Models
|
||||||
|
{
|
||||||
|
// reference data sent with crossposted messages and replies
|
||||||
|
// https://discord.com/developers/docs/resources/channel#message-object-message-reference-structure
|
||||||
|
public partial class MessageReference
|
||||||
|
{
|
||||||
|
public string? MessageId { get; }
|
||||||
|
|
||||||
|
public string? ChannelId { get; }
|
||||||
|
|
||||||
|
public string? GuildId { get; }
|
||||||
|
|
||||||
|
public MessageReference(string? message_id, string? channel_id, string? guild_id)
|
||||||
|
{
|
||||||
|
MessageId = message_id;
|
||||||
|
ChannelId = channel_id;
|
||||||
|
GuildId = guild_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => MessageId ?? "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class MessageReference
|
||||||
|
{
|
||||||
|
public static MessageReference Parse(JsonElement json)
|
||||||
|
{
|
||||||
|
var message_id = json.GetPropertyOrNull("message_id")?.GetString();
|
||||||
|
var channel_id = json.GetPropertyOrNull("channel_id")?.GetString();
|
||||||
|
var guild_id = json.GetPropertyOrNull("guild_id")?.GetString();
|
||||||
|
|
||||||
|
return new MessageReference(message_id, channel_id, guild_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -211,6 +211,39 @@ img {
|
||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chatlog__reference-symbol {
|
||||||
|
grid-column: 1;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 2px 0 0 2px;
|
||||||
|
border-radius: 8px 0 0 0;
|
||||||
|
margin-left: 16px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__reference {
|
||||||
|
grid-column: 2;
|
||||||
|
margin-left: 1.2em;
|
||||||
|
font-size: smaller;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__reference-avatar {
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__reference-name {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__reference-content {
|
||||||
|
margin-left: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
.chatlog__author-avatar-container {
|
.chatlog__author-avatar-container {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
|
|
@ -46,6 +46,14 @@ a {
|
||||||
border-color: rgba(255, 255, 255, 0.1);
|
border-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chatlog__reference-symbol {
|
||||||
|
border-color: #4f545c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__reference {
|
||||||
|
color: #b5b6b8;
|
||||||
|
}
|
||||||
|
|
||||||
.chatlog__author-name {
|
.chatlog__author-name {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,14 @@ a {
|
||||||
border-color: #eceeef;
|
border-color: #eceeef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chatlog__reference-symbol {
|
||||||
|
border-color: #c7ccd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chatlog__reference {
|
||||||
|
color: #5f5f60;
|
||||||
|
}
|
||||||
|
|
||||||
.chatlog__author-name {
|
.chatlog__author-name {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #2f3136;
|
color: #2f3136;
|
||||||
|
|
|
@ -14,10 +14,21 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html
|
||||||
|
|
||||||
public IReadOnlyList<Message> Messages { get; }
|
public IReadOnlyList<Message> Messages { get; }
|
||||||
|
|
||||||
public MessageGroup(User author, DateTimeOffset timestamp, IReadOnlyList<Message> messages)
|
public MessageReference? Reference { get; }
|
||||||
|
|
||||||
|
public Message? ReferencedMessage {get; }
|
||||||
|
|
||||||
|
public MessageGroup(
|
||||||
|
User author,
|
||||||
|
DateTimeOffset timestamp,
|
||||||
|
MessageReference? reference,
|
||||||
|
Message? referenced_message,
|
||||||
|
IReadOnlyList<Message> messages)
|
||||||
{
|
{
|
||||||
Author = author;
|
Author = author;
|
||||||
Timestamp = timestamp;
|
Timestamp = timestamp;
|
||||||
|
Reference = reference;
|
||||||
|
ReferencedMessage = referenced_message;
|
||||||
Messages = messages;
|
Messages = messages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +38,8 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html
|
||||||
public static bool CanJoin(Message message1, Message message2) =>
|
public static bool CanJoin(Message message1, Message message2) =>
|
||||||
message1.Author.Id == message2.Author.Id &&
|
message1.Author.Id == message2.Author.Id &&
|
||||||
string.Equals(message1.Author.FullName, message2.Author.FullName, StringComparison.Ordinal) &&
|
string.Equals(message1.Author.FullName, message2.Author.FullName, StringComparison.Ordinal) &&
|
||||||
(message2.Timestamp - message1.Timestamp).Duration().TotalMinutes <= 7;
|
(message2.Timestamp - message1.Timestamp).Duration().TotalMinutes <= 7 &&
|
||||||
|
message2.Reference is null;
|
||||||
|
|
||||||
public static MessageGroup Join(IReadOnlyList<Message> messages)
|
public static MessageGroup Join(IReadOnlyList<Message> messages)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +48,8 @@ namespace DiscordChatExporter.Domain.Exporting.Writers.Html
|
||||||
return new MessageGroup(
|
return new MessageGroup(
|
||||||
first.Author,
|
first.Author,
|
||||||
first.Timestamp,
|
first.Timestamp,
|
||||||
|
first.Reference,
|
||||||
|
first.ReferencedMessage,
|
||||||
messages
|
messages
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
var userMember = Model.ExportContext.TryGetMember(Model.MessageGroup.Author.Id);
|
var userMember = Model.ExportContext.TryGetMember(Model.MessageGroup.Author.Id);
|
||||||
var userColor = Model.ExportContext.TryGetUserColor(Model.MessageGroup.Author.Id);
|
var userColor = Model.ExportContext.TryGetUserColor(Model.MessageGroup.Author.Id);
|
||||||
var userNick = Model.MessageGroup.Author.IsBot ? Model.MessageGroup.Author.Name : userMember?.Nick ?? Model.MessageGroup.Author.Name;
|
var userNick = Model.MessageGroup.Author.IsBot ? Model.MessageGroup.Author.Name : userMember?.Nick ?? Model.MessageGroup.Author.Name;
|
||||||
|
var referencedUserNick = Model.MessageGroup.Author.IsBot ? Model.MessageGroup.Author.Name : userMember?.Nick ?? Model.MessageGroup.Author.Name;
|
||||||
|
|
||||||
var userColorStyle = userColor != null
|
var userColorStyle = userColor != null
|
||||||
? $"color: rgb({userColor?.R},{userColor?.G},{userColor?.B})"
|
? $"color: rgb({userColor?.R},{userColor?.G},{userColor?.B})"
|
||||||
|
@ -23,6 +24,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="chatlog__message-group">
|
<div class="chatlog__message-group">
|
||||||
|
@if (Model.MessageGroup.Reference != null)
|
||||||
|
{
|
||||||
|
<div class="chatlog__reference-symbol">
|
||||||
|
</div>
|
||||||
|
<div class="chatlog__reference">
|
||||||
|
@if (Model.MessageGroup.ReferencedMessage != null)
|
||||||
|
{
|
||||||
|
<img class="chatlog__reference-avatar" src="@await ResolveUrlAsync(Model.MessageGroup.ReferencedMessage.Author.AvatarUrl)" alt="Avatar">
|
||||||
|
<span class="chatlog__reference-name" title="@Model.MessageGroup.ReferencedMessage.Author.FullName" data-user-id="@Model.MessageGroup.ReferencedMessage.Author.Id">@Model.MessageGroup.ReferencedMessage.Author.FullName</span>
|
||||||
|
<span class="chatlog__reference-content">
|
||||||
|
@Raw(FormatMarkdown(Model.MessageGroup.ReferencedMessage.Content))
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="chatlog__reference-unknown">
|
||||||
|
In reply to an unknown message
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="chatlog__author-avatar-container">
|
<div class="chatlog__author-avatar-container">
|
||||||
<img class="chatlog__author-avatar" src="@await ResolveUrlAsync(Model.MessageGroup.Author.AvatarUrl)" alt="Avatar">
|
<img class="chatlog__author-avatar" src="@await ResolveUrlAsync(Model.MessageGroup.Author.AvatarUrl)" alt="Avatar">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -263,6 +263,17 @@ namespace DiscordChatExporter.Domain.Exporting.Writers
|
||||||
|
|
||||||
_writer.WriteEndArray();
|
_writer.WriteEndArray();
|
||||||
|
|
||||||
|
// Reference
|
||||||
|
|
||||||
|
if (message.Reference is not null)
|
||||||
|
{
|
||||||
|
_writer.WriteStartObject("reference");
|
||||||
|
_writer.WriteString("messageId", message.Reference.MessageId);
|
||||||
|
_writer.WriteString("channelId", message.Reference.ChannelId);
|
||||||
|
_writer.WriteString("guildId", message.Reference.GuildId);
|
||||||
|
_writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
_writer.WriteEndObject();
|
_writer.WriteEndObject();
|
||||||
await _writer.FlushAsync();
|
await _writer.FlushAsync();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue