From 86cd3e6bf0c45e29538cd0003f5264bf81cb19fb Mon Sep 17 00:00:00 2001
From: Daniel Jarski <30324210+QuantumToasted@users.noreply.github.com>
Date: Fri, 8 Nov 2024 12:13:48 -0600
Subject: [PATCH] Initial message snapshots commit
---
.../Core/Message/User/IMessageReference.cs | 5 ++
.../Core/Message/User/IMessageSnapshot.cs | 62 ++++++++++++++++
.../Core/Message/User/IUserMessage.cs | 5 ++
.../LocalMessageReferenceExtensions.cs | 7 ++
.../Local/Message/LocalMessageReference.cs | 10 +++
.../Transient/Message/TransientMessage.cs | 2 +-
.../Message/User/TransientMessageReference.cs | 3 +
.../Message/User/TransientMessageSnapshot.cs | 72 +++++++++++++++++++
.../Message/User/TransientUserMessage.cs | 13 +++-
.../Enums/MessageReferenceType.cs | 17 +++++
.../Models/Message/MessageJsonModel.cs | 5 +-
.../Message/MessageReferenceJsonModel.cs | 3 +
.../Message/MessageSnapshotJsonModel.cs | 9 +++
.../Entities/Cached/Message/CachedMessage.cs | 4 +-
.../Cached/Message/User/CachedUserMessage.cs | 3 +
.../Message/TransientGatewayMessage.cs | 6 +-
.../User/TransientGatewayUserMessage.cs | 12 ++++
17 files changed, 230 insertions(+), 8 deletions(-)
create mode 100644 src/Disqord.Core/Entities/Core/Message/User/IMessageSnapshot.cs
create mode 100644 src/Disqord.Core/Entities/Transient/Message/User/TransientMessageSnapshot.cs
create mode 100644 src/Disqord.Core/Enums/MessageReferenceType.cs
create mode 100644 src/Disqord.Core/Models/Message/MessageSnapshotJsonModel.cs
diff --git a/src/Disqord.Core/Entities/Core/Message/User/IMessageReference.cs b/src/Disqord.Core/Entities/Core/Message/User/IMessageReference.cs
index b636025c4..aa9d20c4e 100644
--- a/src/Disqord.Core/Entities/Core/Message/User/IMessageReference.cs
+++ b/src/Disqord.Core/Entities/Core/Message/User/IMessageReference.cs
@@ -5,6 +5,11 @@
///
public interface IMessageReference : IChannelEntity, IPossiblyGuildEntity
{
+ ///
+ /// Gets the reference type of the referenced message.
+ ///
+ MessageReferenceType Type { get; }
+
///
/// Gets the ID of the referenced message.
///
diff --git a/src/Disqord.Core/Entities/Core/Message/User/IMessageSnapshot.cs b/src/Disqord.Core/Entities/Core/Message/User/IMessageSnapshot.cs
new file mode 100644
index 000000000..0e13a67df
--- /dev/null
+++ b/src/Disqord.Core/Entities/Core/Message/User/IMessageSnapshot.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+
+namespace Disqord;
+
+public interface IMessageSnapshot : IEntity
+{
+ ///
+ /// Gets the of this message snapshot.
+ ///
+ UserMessageType Type { get; }
+
+ ///
+ /// Gets the content of this message snapshot.
+ ///
+ string Content { get; }
+
+ ///
+ /// Gets the mentioned users of this message snapshot.
+ ///
+ IReadOnlyList MentionedUsers { get; }
+
+ ///
+ /// Gets the mentioned role IDs of this message snapshot.
+ ///
+ IReadOnlyList MentionedRoleIds { get; }
+
+ ///
+ /// Gets the attachments of this message snapshot.
+ ///
+ IReadOnlyList Attachments { get; }
+
+ ///
+ /// Gets the embeds of this message snapshot.
+ ///
+ IReadOnlyList Embeds { get; }
+
+ ///
+ /// Gets the timestamp of when the snapshotted message was created.
+ ///
+ DateTimeOffset Timestamp { get; }
+
+ ///
+ /// Gets the edit date of this message snapshot.
+ ///
+ DateTimeOffset? EditedAt { get; }
+
+ ///
+ /// Gets the flags of this message snapshot.
+ ///
+ MessageFlags Flags { get; }
+
+ ///
+ /// Gets the stickers sent with this message snapshot.
+ ///
+ IReadOnlyList Stickers { get; }
+
+ ///
+ /// Gets the components of this message snapshot.
+ ///
+ IReadOnlyList Components { get; }
+}
\ No newline at end of file
diff --git a/src/Disqord.Core/Entities/Core/Message/User/IUserMessage.cs b/src/Disqord.Core/Entities/Core/Message/User/IUserMessage.cs
index b40546249..5a07f5e9d 100644
--- a/src/Disqord.Core/Entities/Core/Message/User/IUserMessage.cs
+++ b/src/Disqord.Core/Entities/Core/Message/User/IUserMessage.cs
@@ -118,4 +118,9 @@ public interface IUserMessage : IMessage
/// Gets the poll of this message.
///
IPoll? Poll { get; }
+
+ ///
+ /// Gets the message snapshots referenced (forwarded) by this message.
+ ///
+ IReadOnlyList MessageSnapshots { get; }
}
diff --git a/src/Disqord.Core/Entities/Local/Message/Extensions/LocalMessageReferenceExtensions.cs b/src/Disqord.Core/Entities/Local/Message/Extensions/LocalMessageReferenceExtensions.cs
index 9b597850d..75ee1b14f 100644
--- a/src/Disqord.Core/Entities/Local/Message/Extensions/LocalMessageReferenceExtensions.cs
+++ b/src/Disqord.Core/Entities/Local/Message/Extensions/LocalMessageReferenceExtensions.cs
@@ -8,6 +8,13 @@ namespace Disqord;
[EditorBrowsable(EditorBrowsableState.Never)]
public static class LocalMessageReferenceExtensions
{
+ public static TMessageReference WithType(this TMessageReference messageReference, MessageReferenceType type)
+ where TMessageReference : LocalMessageReference
+ {
+ messageReference.Type = type;
+ return messageReference;
+ }
+
///
/// Sets the ID of the referenced message.
///
diff --git a/src/Disqord.Core/Entities/Local/Message/LocalMessageReference.cs b/src/Disqord.Core/Entities/Local/Message/LocalMessageReference.cs
index a331e933e..788896e43 100644
--- a/src/Disqord.Core/Entities/Local/Message/LocalMessageReference.cs
+++ b/src/Disqord.Core/Entities/Local/Message/LocalMessageReference.cs
@@ -9,6 +9,14 @@ namespace Disqord;
///
public class LocalMessageReference : ILocalConstruct, IJsonConvertible
{
+ ///
+ /// Gets or sets the type of way this message will be referenced.
+ ///
+ ///
+ /// This property defaults to .
+ ///
+ public Optional Type { get; set; } = MessageReferenceType.Reply;
+
///
/// Gets or sets the ID of the referenced message.
///
@@ -65,6 +73,7 @@ public virtual MessageReferenceJsonModel ToModel()
{
return new MessageReferenceJsonModel
{
+ Type = Type,
MessageId = MessageId,
ChannelId = ChannelId,
GuildId = GuildId,
@@ -87,6 +96,7 @@ public static LocalMessageReference CreateFrom(IMessageReference reference)
{
return new LocalMessageReference
{
+ Type = reference.Type,
MessageId = Optional.FromNullable(reference.MessageId),
ChannelId = reference.ChannelId,
GuildId = Optional.FromNullable(reference.GuildId)
diff --git a/src/Disqord.Core/Entities/Transient/Message/TransientMessage.cs b/src/Disqord.Core/Entities/Transient/Message/TransientMessage.cs
index cb77cdf27..20f11f684 100644
--- a/src/Disqord.Core/Entities/Transient/Message/TransientMessage.cs
+++ b/src/Disqord.Core/Entities/Transient/Message/TransientMessage.cs
@@ -15,7 +15,7 @@ public abstract class TransientMessage : TransientClientEntity
public Snowflake ChannelId => Model.ChannelId;
///
- public IUser Author => _author ??= new TransientUser(Client, Model.Author);
+ public IUser Author => _author ??= new TransientUser(Client, Model.Author.Value);
private IUser? _author;
diff --git a/src/Disqord.Core/Entities/Transient/Message/User/TransientMessageReference.cs b/src/Disqord.Core/Entities/Transient/Message/User/TransientMessageReference.cs
index 6dd04baaa..2933b4d5b 100644
--- a/src/Disqord.Core/Entities/Transient/Message/User/TransientMessageReference.cs
+++ b/src/Disqord.Core/Entities/Transient/Message/User/TransientMessageReference.cs
@@ -5,6 +5,9 @@ namespace Disqord;
public class TransientMessageReference : TransientEntity, IMessageReference
{
+ ///
+ public MessageReferenceType Type => Model.Type.GetValueOrNullable() ?? MessageReferenceType.Reply;
+
///
public Snowflake? MessageId => Model.MessageId.GetValueOrNullable();
diff --git a/src/Disqord.Core/Entities/Transient/Message/User/TransientMessageSnapshot.cs b/src/Disqord.Core/Entities/Transient/Message/User/TransientMessageSnapshot.cs
new file mode 100644
index 000000000..11395c291
--- /dev/null
+++ b/src/Disqord.Core/Entities/Transient/Message/User/TransientMessageSnapshot.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using Disqord.Models;
+using Qommon.Collections.ReadOnly;
+
+namespace Disqord;
+
+public class TransientMessageSnapshot : TransientClientEntity, IMessageSnapshot
+{
+ ///
+ public UserMessageType Type => Model.Message.Type;
+
+ ///
+ public string Content => Model.Message.Content;
+
+ ///
+ public IReadOnlyList MentionedUsers => _mentionedUsers ??= Model.Message.Mentions.ToReadOnlyList(Client, (model, client) => new TransientUser(client, model));
+
+ private IReadOnlyList? _mentionedUsers;
+
+ ///
+ public IReadOnlyList MentionedRoleIds => Model.Message.MentionRoles;
+
+ ///
+ public IReadOnlyList Attachments => _attachments ??= Model.Message.Attachments.ToReadOnlyList(model => new TransientAttachment(model));
+
+ private IReadOnlyList? _attachments;
+
+ ///
+ public IReadOnlyList Embeds => _embeds ??= Model.Message.Embeds.ToReadOnlyList(model => new TransientEmbed(model));
+
+ private IReadOnlyList? _embeds;
+
+ ///
+ public DateTimeOffset Timestamp { get; }
+
+ ///
+ public DateTimeOffset? EditedAt { get; }
+
+ ///
+ public MessageFlags Flags { get; }
+
+ ///
+ public IReadOnlyList Stickers
+ {
+ get
+ {
+ if (!Model.Message.StickerItems.HasValue)
+ return Array.Empty();
+
+ return _stickers ??= Model.Message.StickerItems.Value.ToReadOnlyList(model => new TransientMessageSticker(model));
+ }
+ }
+
+ private IReadOnlyList? _stickers;
+
+ public IReadOnlyList Components
+ {
+ get
+ {
+ if (!Model.Message.Components.HasValue)
+ return Array.Empty();
+
+ return _components ??= Model.Message.Components.Value.ToReadOnlyList(Client, (model, client) => new TransientRowComponent(client, model));
+ }
+ }
+ private IReadOnlyList? _components;
+
+ public TransientMessageSnapshot(IClient client, MessageSnapshotJsonModel model)
+ : base(client, model)
+ { }
+}
\ No newline at end of file
diff --git a/src/Disqord.Core/Entities/Transient/Message/User/TransientUserMessage.cs b/src/Disqord.Core/Entities/Transient/Message/User/TransientUserMessage.cs
index 24cd307d0..8bb59f161 100644
--- a/src/Disqord.Core/Entities/Transient/Message/User/TransientUserMessage.cs
+++ b/src/Disqord.Core/Entities/Transient/Message/User/TransientUserMessage.cs
@@ -125,7 +125,6 @@ public IReadOnlyList Stickers
return _stickers ??= Model.StickerItems.Value.ToReadOnlyList(model => new TransientMessageSticker(model));
}
}
-
private IReadOnlyList? _stickers;
///
@@ -133,6 +132,18 @@ public IReadOnlyList Stickers
private IPoll? _poll;
+ public IReadOnlyList MessageSnapshots
+ {
+ get
+ {
+ if (!Model.MessageSnapshots.HasValue)
+ return Array.Empty();
+
+ return _messageSnapshots ??= Model.MessageSnapshots.Value.ToReadOnlyList(Client, (model, client) => new TransientMessageSnapshot(client, model));
+ }
+ }
+ private IReadOnlyList? _messageSnapshots;
+
public TransientUserMessage(IClient client, MessageJsonModel model)
: base(client, model)
{ }
diff --git a/src/Disqord.Core/Enums/MessageReferenceType.cs b/src/Disqord.Core/Enums/MessageReferenceType.cs
new file mode 100644
index 000000000..c92feb9d4
--- /dev/null
+++ b/src/Disqord.Core/Enums/MessageReferenceType.cs
@@ -0,0 +1,17 @@
+namespace Disqord;
+
+///
+/// Represents the type of a message reference.
+///
+public enum MessageReferenceType
+{
+ ///
+ /// A standard reference used by replies.
+ ///
+ Reply = 0,
+
+ ///
+ /// A reference used to point to a message at a point in time.
+ ///
+ Forward = 1
+}
\ No newline at end of file
diff --git a/src/Disqord.Core/Models/Message/MessageJsonModel.cs b/src/Disqord.Core/Models/Message/MessageJsonModel.cs
index 57184e066..1eb20a9fb 100644
--- a/src/Disqord.Core/Models/Message/MessageJsonModel.cs
+++ b/src/Disqord.Core/Models/Message/MessageJsonModel.cs
@@ -17,7 +17,7 @@ public class MessageJsonModel : JsonModel
public Optional GuildId;
[JsonProperty("author")]
- public UserJsonModel Author = null!;
+ public Optional Author;
[JsonProperty("member")]
public Optional Member;
@@ -79,6 +79,9 @@ public class MessageJsonModel : JsonModel
[JsonProperty("message_reference")]
public Optional MessageReference;
+ [JsonProperty("message_snapshots")]
+ public Optional MessageSnapshots;
+
[JsonProperty("flags")]
public Optional Flags;
diff --git a/src/Disqord.Core/Models/Message/MessageReferenceJsonModel.cs b/src/Disqord.Core/Models/Message/MessageReferenceJsonModel.cs
index ac03f54de..33bdc2556 100644
--- a/src/Disqord.Core/Models/Message/MessageReferenceJsonModel.cs
+++ b/src/Disqord.Core/Models/Message/MessageReferenceJsonModel.cs
@@ -5,6 +5,9 @@ namespace Disqord.Models;
public class MessageReferenceJsonModel : JsonModel
{
+ [JsonProperty("type")]
+ public Optional Type;
+
[JsonProperty("message_id")]
public Optional MessageId;
diff --git a/src/Disqord.Core/Models/Message/MessageSnapshotJsonModel.cs b/src/Disqord.Core/Models/Message/MessageSnapshotJsonModel.cs
new file mode 100644
index 000000000..d8efb6c66
--- /dev/null
+++ b/src/Disqord.Core/Models/Message/MessageSnapshotJsonModel.cs
@@ -0,0 +1,9 @@
+using Disqord.Serialization.Json;
+
+namespace Disqord.Models;
+
+public class MessageSnapshotJsonModel : JsonModel
+{
+ [JsonProperty("message")]
+ public MessageJsonModel Message = null!;
+}
\ No newline at end of file
diff --git a/src/Disqord.Gateway/Entities/Cached/Message/CachedMessage.cs b/src/Disqord.Gateway/Entities/Cached/Message/CachedMessage.cs
index 302a4f665..f7ad14563 100644
--- a/src/Disqord.Gateway/Entities/Cached/Message/CachedMessage.cs
+++ b/src/Disqord.Gateway/Entities/Cached/Message/CachedMessage.cs
@@ -53,7 +53,7 @@ protected CachedMessage(IGatewayClient client, CachedMember? author, MessageJson
}
else
{
- _author = new TransientUser(Client, model.Author);
+ _author = new TransientUser(Client, model.Author.Value);
}
}
@@ -72,7 +72,7 @@ public virtual void Update(MessageJsonModel model)
}
else
{
- _author = new TransientUser(Client, model.Author);
+ _author = new TransientUser(Client, model.Author.Value);
}
}
diff --git a/src/Disqord.Gateway/Entities/Cached/Message/User/CachedUserMessage.cs b/src/Disqord.Gateway/Entities/Cached/Message/User/CachedUserMessage.cs
index ddec37414..af273a25e 100644
--- a/src/Disqord.Gateway/Entities/Cached/Message/User/CachedUserMessage.cs
+++ b/src/Disqord.Gateway/Entities/Cached/Message/User/CachedUserMessage.cs
@@ -67,6 +67,8 @@ public class CachedUserMessage : CachedMessage, IGatewayUserMessage, IJsonUpdata
///
public IPoll? Poll { get; private set; }
+ public IReadOnlyList MessageSnapshots { get; private set; } = null!;
+
public CachedUserMessage(IGatewayClient client, CachedMember? author, MessageJsonModel model)
: base(client, author, model)
{
@@ -96,6 +98,7 @@ public override void Update(MessageJsonModel model)
Components = Optional.ConvertOrDefault(model.Components, (models, client) => models.ToReadOnlyList(client, (model, client) => new TransientRowComponent(client, model) as IRowComponent), Client) ?? Array.Empty();
Stickers = Optional.ConvertOrDefault(model.StickerItems, models => models.ToReadOnlyList(model => new TransientMessageSticker(model) as IMessageSticker), Array.Empty());
Poll = Optional.ConvertOrDefault(model.Poll, model => new TransientPoll(model));
+ MessageSnapshots = Optional.ConvertOrDefault(model.MessageSnapshots, models => models.ToReadOnlyList(Client, (model, client) => new TransientMessageSnapshot(client, model) as IMessageSnapshot)) ?? Array.Empty();
}
public void Update(MessageUpdateJsonModel model)
diff --git a/src/Disqord.Gateway/Entities/Transient/Message/TransientGatewayMessage.cs b/src/Disqord.Gateway/Entities/Transient/Message/TransientGatewayMessage.cs
index 560f4251a..549198f42 100644
--- a/src/Disqord.Gateway/Entities/Transient/Message/TransientGatewayMessage.cs
+++ b/src/Disqord.Gateway/Entities/Transient/Message/TransientGatewayMessage.cs
@@ -25,14 +25,14 @@ public IUser Author
var guildId = Model.GuildId;
if (!guildId.HasValue || !Model.Member.HasValue)
{
- var user = Client.GetUser(Model.Author.Id);
+ var user = Client.GetUser(Model.Author.Value.Id);
if (user != null)
return user;
- return _author ??= new TransientUser(Client, Model.Author);
+ return _author ??= new TransientUser(Client, Model.Author.Value);
}
- var member = Client.GetMember(guildId.Value, Model.Author.Id);
+ var member = Client.GetMember(guildId.Value, Model.Author.Value.Id);
if (member != null)
return member;
diff --git a/src/Disqord.Gateway/Entities/Transient/Message/User/TransientGatewayUserMessage.cs b/src/Disqord.Gateway/Entities/Transient/Message/User/TransientGatewayUserMessage.cs
index d0af45326..60e523119 100644
--- a/src/Disqord.Gateway/Entities/Transient/Message/User/TransientGatewayUserMessage.cs
+++ b/src/Disqord.Gateway/Entities/Transient/Message/User/TransientGatewayUserMessage.cs
@@ -105,6 +105,18 @@ public IReadOnlyList Stickers
public IPoll? Poll => _poll ??= Optional.ConvertOrDefault(Model.Poll, poll => new TransientPoll(poll));
private IPoll? _poll;
+
+ public IReadOnlyList MessageSnapshots
+ {
+ get
+ {
+ if (!Model.MessageSnapshots.HasValue)
+ return Array.Empty();
+
+ return _messageSnapshots ??= Model.MessageSnapshots.Value.ToReadOnlyList(Client, (model, client) => new TransientMessageSnapshot(client, model));
+ }
+ }
+ private IReadOnlyList? _messageSnapshots;
public TransientGatewayUserMessage(IClient client, MessageJsonModel model)
: base(client, model)