mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-03-31 09:33:03 -06:00
Clean up after last PR
This commit is contained in:
parent
532470e3db
commit
b660edfe78
|
|
@ -27,10 +27,16 @@ public partial record Message(
|
||||||
IReadOnlyList<User> MentionedUsers,
|
IReadOnlyList<User> MentionedUsers,
|
||||||
MessageReference? Reference,
|
MessageReference? Reference,
|
||||||
Message? ReferencedMessage,
|
Message? ReferencedMessage,
|
||||||
Interaction? Interaction,
|
MessageSnapshot? ForwardedMessage,
|
||||||
MessageSnapshot? ForwardedMessage
|
Interaction? Interaction
|
||||||
) : IHasId
|
) : IHasId
|
||||||
{
|
{
|
||||||
|
public bool IsEmpty { get; } =
|
||||||
|
string.IsNullOrWhiteSpace(Content)
|
||||||
|
&& !Attachments.Any()
|
||||||
|
&& !Embeds.Any()
|
||||||
|
&& !Stickers.Any();
|
||||||
|
|
||||||
public bool IsSystemNotification { get; } =
|
public bool IsSystemNotification { get; } =
|
||||||
Kind is >= MessageKind.RecipientAdd and <= MessageKind.ThreadCreated;
|
Kind is >= MessageKind.RecipientAdd and <= MessageKind.ThreadCreated;
|
||||||
|
|
||||||
|
|
@ -39,15 +45,8 @@ public partial record Message(
|
||||||
// App interactions are rendered as replies in the Discord client, but they are not actually replies
|
// App interactions are rendered as replies in the Discord client, but they are not actually replies
|
||||||
public bool IsReplyLike => IsReply || Interaction is not null;
|
public bool IsReplyLike => IsReply || Interaction is not null;
|
||||||
|
|
||||||
// A message is a forward if its reference type is Forward
|
|
||||||
public bool IsForwarded { get; } = Reference?.Kind == MessageReferenceKind.Forward;
|
public bool IsForwarded { get; } = Reference?.Kind == MessageReferenceKind.Forward;
|
||||||
|
|
||||||
public bool IsEmpty { get; } =
|
|
||||||
string.IsNullOrWhiteSpace(Content)
|
|
||||||
&& !Attachments.Any()
|
|
||||||
&& !Embeds.Any()
|
|
||||||
&& !Stickers.Any();
|
|
||||||
|
|
||||||
public IEnumerable<User> GetReferencedUsers()
|
public IEnumerable<User> GetReferencedUsers()
|
||||||
{
|
{
|
||||||
yield return Author;
|
yield return Author;
|
||||||
|
|
@ -175,16 +174,19 @@ public partial record Message
|
||||||
|
|
||||||
var messageReference = json.GetPropertyOrNull("message_reference")
|
var messageReference = json.GetPropertyOrNull("message_reference")
|
||||||
?.Pipe(MessageReference.Parse);
|
?.Pipe(MessageReference.Parse);
|
||||||
var referencedMessage = json.GetPropertyOrNull("referenced_message")?.Pipe(Parse);
|
|
||||||
var interaction = json.GetPropertyOrNull("interaction")?.Pipe(Interaction.Parse);
|
|
||||||
|
|
||||||
// Parse message snapshots for forwarded messages
|
var referencedMessage = json.GetPropertyOrNull("referenced_message")?.Pipe(Parse);
|
||||||
|
|
||||||
// Currently Discord only supports 1 snapshot per forward
|
// Currently Discord only supports 1 snapshot per forward
|
||||||
var forwardedMessage = json.GetPropertyOrNull("message_snapshots")
|
var forwardedMessage = json.GetPropertyOrNull("message_snapshots")
|
||||||
?.EnumerateArrayOrNull()
|
?.EnumerateArrayOrNull()
|
||||||
?.Select(MessageSnapshot.Parse)
|
?.Select(j => j.GetPropertyOrNull("message"))
|
||||||
|
.WhereNotNull()
|
||||||
|
.Select(MessageSnapshot.Parse)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
var interaction = json.GetPropertyOrNull("interaction")?.Pipe(Interaction.Parse);
|
||||||
|
|
||||||
return new Message(
|
return new Message(
|
||||||
id,
|
id,
|
||||||
kind,
|
kind,
|
||||||
|
|
@ -202,8 +204,8 @@ public partial record Message
|
||||||
mentionedUsers,
|
mentionedUsers,
|
||||||
messageReference,
|
messageReference,
|
||||||
referencedMessage,
|
referencedMessage,
|
||||||
interaction,
|
forwardedMessage,
|
||||||
forwardedMessage
|
interaction
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,17 @@ namespace DiscordChatExporter.Core.Discord.Data;
|
||||||
|
|
||||||
// https://discord.com/developers/docs/resources/channel#message-object-message-reference-structure
|
// https://discord.com/developers/docs/resources/channel#message-object-message-reference-structure
|
||||||
public record MessageReference(
|
public record MessageReference(
|
||||||
|
MessageReferenceKind Kind,
|
||||||
Snowflake? MessageId,
|
Snowflake? MessageId,
|
||||||
Snowflake? ChannelId,
|
Snowflake? ChannelId,
|
||||||
Snowflake? GuildId,
|
Snowflake? GuildId)
|
||||||
MessageReferenceKind Kind
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
public static MessageReference Parse(JsonElement json)
|
public static MessageReference Parse(JsonElement json)
|
||||||
{
|
{
|
||||||
|
var kind =
|
||||||
|
json.GetPropertyOrNull("type")?.GetInt32OrNull()?.Pipe(t => (MessageReferenceKind)t)
|
||||||
|
?? MessageReferenceKind.Default;
|
||||||
|
|
||||||
var messageId = json.GetPropertyOrNull("message_id")
|
var messageId = json.GetPropertyOrNull("message_id")
|
||||||
?.GetNonWhiteSpaceStringOrNull()
|
?.GetNonWhiteSpaceStringOrNull()
|
||||||
?.Pipe(Snowflake.Parse);
|
?.Pipe(Snowflake.Parse);
|
||||||
|
|
@ -26,10 +29,6 @@ public record MessageReference(
|
||||||
?.GetNonWhiteSpaceStringOrNull()
|
?.GetNonWhiteSpaceStringOrNull()
|
||||||
?.Pipe(Snowflake.Parse);
|
?.Pipe(Snowflake.Parse);
|
||||||
|
|
||||||
var kind =
|
return new MessageReference(kind, messageId, channelId, guildId);
|
||||||
json.GetPropertyOrNull("type")?.GetInt32OrNull()?.Pipe(t => (MessageReferenceKind)t)
|
|
||||||
?? MessageReferenceKind.Default;
|
|
||||||
|
|
||||||
return new MessageReference(messageId, channelId, guildId, kind);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,31 +3,34 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DiscordChatExporter.Core.Discord.Data.Embeds;
|
using DiscordChatExporter.Core.Discord.Data.Embeds;
|
||||||
using DiscordChatExporter.Core.Utils.Extensions;
|
|
||||||
using JsonExtensions.Reading;
|
using JsonExtensions.Reading;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Core.Discord.Data;
|
namespace DiscordChatExporter.Core.Discord.Data;
|
||||||
|
|
||||||
// https://discord.com/developers/docs/resources/channel#message-snapshot-object
|
// https://docs.discord.com/developers/resources/message#message-snapshot-object
|
||||||
// Message snapshots contain a subset of message fields for forwarded messages
|
// Message snapshots contain a subset of message fields for forwarded messages
|
||||||
public record MessageSnapshot(
|
public record MessageSnapshot(
|
||||||
|
DateTimeOffset Timestamp,
|
||||||
|
DateTimeOffset? EditedTimestamp,
|
||||||
string Content,
|
string Content,
|
||||||
IReadOnlyList<Attachment> Attachments,
|
IReadOnlyList<Attachment> Attachments,
|
||||||
IReadOnlyList<Embed> Embeds,
|
IReadOnlyList<Embed> Embeds,
|
||||||
IReadOnlyList<Sticker> Stickers,
|
IReadOnlyList<Sticker> Stickers)
|
||||||
DateTimeOffset Timestamp,
|
|
||||||
DateTimeOffset? EditedTimestamp
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
public static MessageSnapshot Parse(JsonElement json)
|
public static MessageSnapshot Parse(JsonElement json)
|
||||||
{
|
{
|
||||||
// The message snapshot has a "message" property containing the actual message data
|
var timestamp =
|
||||||
var messageJson = json.GetPropertyOrNull("message") ?? json;
|
json.GetPropertyOrNull("timestamp")?.GetDateTimeOffsetOrNull()
|
||||||
|
?? DateTimeOffset.MinValue;
|
||||||
|
|
||||||
var content = messageJson.GetPropertyOrNull("content")?.GetStringOrNull() ?? "";
|
var editedTimestamp = json
|
||||||
|
.GetPropertyOrNull("edited_timestamp")
|
||||||
|
?.GetDateTimeOffsetOrNull();
|
||||||
|
|
||||||
|
var content = json.GetPropertyOrNull("content")?.GetStringOrNull() ?? "";
|
||||||
|
|
||||||
var attachments =
|
var attachments =
|
||||||
messageJson
|
json
|
||||||
.GetPropertyOrNull("attachments")
|
.GetPropertyOrNull("attachments")
|
||||||
?.EnumerateArrayOrNull()
|
?.EnumerateArrayOrNull()
|
||||||
?.Select(Attachment.Parse)
|
?.Select(Attachment.Parse)
|
||||||
|
|
@ -35,7 +38,7 @@ public record MessageSnapshot(
|
||||||
?? [];
|
?? [];
|
||||||
|
|
||||||
var embeds =
|
var embeds =
|
||||||
messageJson
|
json
|
||||||
.GetPropertyOrNull("embeds")
|
.GetPropertyOrNull("embeds")
|
||||||
?.EnumerateArrayOrNull()
|
?.EnumerateArrayOrNull()
|
||||||
?.Select(Embed.Parse)
|
?.Select(Embed.Parse)
|
||||||
|
|
@ -43,28 +46,14 @@ public record MessageSnapshot(
|
||||||
?? [];
|
?? [];
|
||||||
|
|
||||||
var stickers =
|
var stickers =
|
||||||
messageJson
|
json
|
||||||
.GetPropertyOrNull("sticker_items")
|
.GetPropertyOrNull("sticker_items")
|
||||||
?.EnumerateArrayOrNull()
|
?.EnumerateArrayOrNull()
|
||||||
?.Select(Sticker.Parse)
|
?.Select(Sticker.Parse)
|
||||||
.ToArray()
|
.ToArray()
|
||||||
?? [];
|
?? [];
|
||||||
|
|
||||||
var timestamp =
|
return new MessageSnapshot(timestamp,
|
||||||
messageJson.GetPropertyOrNull("timestamp")?.GetDateTimeOffsetOrNull()
|
editedTimestamp, content, attachments, embeds, stickers);
|
||||||
?? DateTimeOffset.MinValue;
|
|
||||||
|
|
||||||
var editedTimestamp = messageJson
|
|
||||||
.GetPropertyOrNull("edited_timestamp")
|
|
||||||
?.GetDateTimeOffsetOrNull();
|
|
||||||
|
|
||||||
return new MessageSnapshot(
|
|
||||||
content,
|
|
||||||
attachments,
|
|
||||||
embeds,
|
|
||||||
stickers,
|
|
||||||
timestamp,
|
|
||||||
editedTimestamp
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -539,22 +539,20 @@ internal class JsonMessageWriter(Stream stream, ExportContext context)
|
||||||
{
|
{
|
||||||
_writer.WriteStartObject("forwardedMessage");
|
_writer.WriteStartObject("forwardedMessage");
|
||||||
|
|
||||||
_writer.WriteString(
|
|
||||||
"content",
|
|
||||||
await FormatMarkdownAsync(message.ForwardedMessage.Content, cancellationToken)
|
|
||||||
);
|
|
||||||
|
|
||||||
_writer.WriteString(
|
_writer.WriteString(
|
||||||
"timestamp",
|
"timestamp",
|
||||||
message.ForwardedMessage.Timestamp != DateTimeOffset.MinValue
|
Context.NormalizeDate(message.ForwardedMessage.Timestamp)
|
||||||
? Context.NormalizeDate(message.ForwardedMessage.Timestamp)
|
|
||||||
: null
|
|
||||||
);
|
);
|
||||||
|
|
||||||
_writer.WriteString(
|
_writer.WriteString(
|
||||||
"timestampEdited",
|
"timestampEdited",
|
||||||
message.ForwardedMessage.EditedTimestamp?.Pipe(Context.NormalizeDate)
|
message.ForwardedMessage.EditedTimestamp?.Pipe(Context.NormalizeDate)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
_writer.WriteString(
|
||||||
|
"content",
|
||||||
|
await FormatMarkdownAsync(message.ForwardedMessage.Content, cancellationToken)
|
||||||
|
);
|
||||||
|
|
||||||
// Forwarded attachments
|
// Forwarded attachments
|
||||||
_writer.WriteStartArray("attachments");
|
_writer.WriteStartArray("attachments");
|
||||||
|
|
|
||||||
|
|
@ -263,9 +263,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@* Forwarded message content *@
|
@* Forwarded message content *@
|
||||||
@if (message.IsForwarded && message.ForwardedMessage is not null)
|
@if (message is { IsForwarded: true, ForwardedMessage: not null })
|
||||||
{
|
{
|
||||||
var fwd = message.ForwardedMessage;
|
|
||||||
<div class="chatlog__forwarded">
|
<div class="chatlog__forwarded">
|
||||||
<div class="chatlog__forwarded-header">
|
<div class="chatlog__forwarded-header">
|
||||||
<svg class="chatlog__forwarded-icon">
|
<svg class="chatlog__forwarded-icon">
|
||||||
|
|
@ -275,18 +274,18 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@* Forwarded text content *@
|
@* Forwarded text content *@
|
||||||
@if (!string.IsNullOrWhiteSpace(fwd.Content))
|
@if (!string.IsNullOrWhiteSpace(message.ForwardedMessage.Content))
|
||||||
{
|
{
|
||||||
<div class="chatlog__forwarded-content chatlog__markdown">
|
<div class="chatlog__forwarded-content chatlog__markdown">
|
||||||
<span class="chatlog__markdown-preserve"><!--wmm:ignore-->@Html.Raw(await FormatMarkdownAsync(fwd.Content))<!--/wmm:ignore--></span>
|
<span class="chatlog__markdown-preserve"><!--wmm:ignore-->@Html.Raw(await FormatMarkdownAsync(message.ForwardedMessage.Content))<!--/wmm:ignore--></span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@* Forwarded attachments *@
|
@* Forwarded attachments *@
|
||||||
@if (fwd.Attachments.Any())
|
@if (message.ForwardedMessage.Attachments.Any())
|
||||||
{
|
{
|
||||||
<div class="chatlog__forwarded-attachments">
|
<div class="chatlog__forwarded-attachments">
|
||||||
@foreach (var attachment in fwd.Attachments)
|
@foreach (var attachment in message.ForwardedMessage.Attachments)
|
||||||
{
|
{
|
||||||
@if (attachment.IsImage)
|
@if (attachment.IsImage)
|
||||||
{
|
{
|
||||||
|
|
@ -327,7 +326,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@* Forwarded stickers *@
|
@* Forwarded stickers *@
|
||||||
@foreach (var sticker in fwd.Stickers)
|
@foreach (var sticker in message.ForwardedMessage.Stickers)
|
||||||
{
|
{
|
||||||
<div class="chatlog__sticker" title="@sticker.Name">
|
<div class="chatlog__sticker" title="@sticker.Name">
|
||||||
@if (sticker.IsImage)
|
@if (sticker.IsImage)
|
||||||
|
|
@ -343,10 +342,10 @@
|
||||||
|
|
||||||
@* Forwarded timestamp *@
|
@* Forwarded timestamp *@
|
||||||
<div class="chatlog__forwarded-timestamp">
|
<div class="chatlog__forwarded-timestamp">
|
||||||
<span title="@FormatDate(fwd.Timestamp, "f")">Originally sent: @FormatDate(fwd.Timestamp)</span>
|
<span title="@FormatDate(message.ForwardedMessage.Timestamp, "f")">Originally sent: @FormatDate(message.ForwardedMessage.Timestamp)</span>
|
||||||
@if (fwd.EditedTimestamp is not null)
|
@if (message.ForwardedMessage.EditedTimestamp is not null)
|
||||||
{
|
{
|
||||||
<span title="@FormatDate(fwd.EditedTimestamp.Value, "f")"> (edited)</span>
|
<span title="@FormatDate(message.ForwardedMessage.EditedTimestamp.Value, "f")"> (edited)</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -239,12 +239,9 @@ internal class PlainTextMessageWriter(Stream stream, ExportContext context)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forwardedMessage.Timestamp != DateTimeOffset.MinValue)
|
|
||||||
{
|
|
||||||
await _writer.WriteLineAsync(
|
await _writer.WriteLineAsync(
|
||||||
$"Originally sent: {Context.FormatDate(forwardedMessage.Timestamp)}"
|
$"Originally sent: {Context.FormatDate(forwardedMessage.Timestamp)}"
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
await WriteAttachmentsAsync(forwardedMessage.Attachments, cancellationToken);
|
await WriteAttachmentsAsync(forwardedMessage.Attachments, cancellationToken);
|
||||||
await WriteEmbedsAsync(forwardedMessage.Embeds, cancellationToken);
|
await WriteEmbedsAsync(forwardedMessage.Embeds, cancellationToken);
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,17 @@ public static class CollectionExtensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension<T>(IEnumerable<T?> source)
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
public IEnumerable<T> WhereNotNull()
|
||||||
|
{
|
||||||
|
foreach (var o in source)
|
||||||
|
{
|
||||||
|
if (o is not null)
|
||||||
|
yield return o.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue