Skip to content

Commit

Permalink
Add support for message snapshots (forwarding) (#126)
Browse files Browse the repository at this point in the history
* Initial message snapshots commit

* Rename MessageSnapshots -> Snapshots

* Rename MessageReferenceType.Reply -> Default
  • Loading branch information
QuantumToasted authored Nov 16, 2024
1 parent 5af2e00 commit 824b08b
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
/// </summary>
public interface IMessageReference : IChannelEntity, IPossiblyGuildEntity
{
/// <summary>
/// Gets the reference type of the referenced message.
/// </summary>
MessageReferenceType Type { get; }

/// <summary>
/// Gets the ID of the referenced message.
/// </summary>
Expand Down
62 changes: 62 additions & 0 deletions src/Disqord.Core/Entities/Core/Message/User/IMessageSnapshot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;

namespace Disqord;

public interface IMessageSnapshot : IEntity
{
/// <summary>
/// Gets the <see cref="UserMessageType"/> of this message snapshot.
/// </summary>
UserMessageType Type { get; }

/// <summary>
/// Gets the content of this message snapshot.
/// </summary>
string Content { get; }

/// <summary>
/// Gets the mentioned users of this message snapshot.
/// </summary>
IReadOnlyList<IUser> MentionedUsers { get; }

/// <summary>
/// Gets the mentioned role IDs of this message snapshot.
/// </summary>
IReadOnlyList<Snowflake> MentionedRoleIds { get; }

/// <summary>
/// Gets the attachments of this message snapshot.
/// </summary>
IReadOnlyList<IAttachment> Attachments { get; }

/// <summary>
/// Gets the embeds of this message snapshot.
/// </summary>
IReadOnlyList<IEmbed> Embeds { get; }

/// <summary>
/// Gets the timestamp of when the snapshotted message was created.
/// </summary>
DateTimeOffset Timestamp { get; }

/// <summary>
/// Gets the edit date of this message snapshot.
/// </summary>
DateTimeOffset? EditedAt { get; }

/// <summary>
/// Gets the flags of this message snapshot.
/// </summary>
MessageFlags Flags { get; }

/// <summary>
/// Gets the stickers sent with this message snapshot.
/// </summary>
IReadOnlyList<IMessageSticker> Stickers { get; }

/// <summary>
/// Gets the components of this message snapshot.
/// </summary>
IReadOnlyList<IRowComponent> Components { get; }
}
5 changes: 5 additions & 0 deletions src/Disqord.Core/Entities/Core/Message/User/IUserMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,9 @@ public interface IUserMessage : IMessage
/// Gets the poll of this message.
/// </summary>
IPoll? Poll { get; }

/// <summary>
/// Gets the message snapshots of this message.
/// </summary>
IReadOnlyList<IMessageSnapshot> Snapshots { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ namespace Disqord;
[EditorBrowsable(EditorBrowsableState.Never)]
public static class LocalMessageReferenceExtensions
{
public static TMessageReference WithType<TMessageReference>(this TMessageReference messageReference, MessageReferenceType type)
where TMessageReference : LocalMessageReference
{
messageReference.Type = type;
return messageReference;
}

/// <summary>
/// Sets the ID of the referenced message.
/// </summary>
Expand Down
10 changes: 10 additions & 0 deletions src/Disqord.Core/Entities/Local/Message/LocalMessageReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ namespace Disqord;
/// </summary>
public class LocalMessageReference : ILocalConstruct<LocalMessageReference>, IJsonConvertible<MessageReferenceJsonModel>
{
/// <summary>
/// Gets or sets the type of way this message will be referenced.
/// </summary>
/// <remarks>
/// This property defaults to <see cref="MessageReferenceType.Default"/>.
/// </remarks>
public Optional<MessageReferenceType> Type { get; set; } = MessageReferenceType.Default;

/// <summary>
/// Gets or sets the ID of the referenced message.
/// </summary>
Expand Down Expand Up @@ -65,6 +73,7 @@ public virtual MessageReferenceJsonModel ToModel()
{
return new MessageReferenceJsonModel
{
Type = Type,
MessageId = MessageId,
ChannelId = ChannelId,
GuildId = GuildId,
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public abstract class TransientMessage : TransientClientEntity<MessageJsonModel>
public Snowflake ChannelId => Model.ChannelId;

/// <inheritdoc/>
public IUser Author => _author ??= new TransientUser(Client, Model.Author);
public IUser Author => _author ??= new TransientUser(Client, Model.Author.Value);

private IUser? _author;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ namespace Disqord;

public class TransientMessageReference : TransientEntity<MessageReferenceJsonModel>, IMessageReference
{
/// <inheritdoc/>
public MessageReferenceType Type => Model.Type.GetValueOrNullable() ?? MessageReferenceType.Default;

/// <inheritdoc/>
public Snowflake? MessageId => Model.MessageId.GetValueOrNullable();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using Disqord.Models;
using Qommon.Collections.ReadOnly;

namespace Disqord;

public class TransientMessageSnapshot : TransientClientEntity<MessageSnapshotJsonModel>, IMessageSnapshot
{
/// <inheritdoc/>
public UserMessageType Type => Model.Message.Type;

/// <inheritdoc/>
public string Content => Model.Message.Content;

/// <inheritdoc/>
public IReadOnlyList<IUser> MentionedUsers => _mentionedUsers ??= Model.Message.Mentions.ToReadOnlyList(Client, (model, client) => new TransientUser(client, model));

private IReadOnlyList<IUser>? _mentionedUsers;

/// <inheritdoc/>
public IReadOnlyList<Snowflake> MentionedRoleIds => Model.Message.MentionRoles;

/// <inheritdoc/>
public IReadOnlyList<IAttachment> Attachments => _attachments ??= Model.Message.Attachments.ToReadOnlyList(model => new TransientAttachment(model));

private IReadOnlyList<IAttachment>? _attachments;

/// <inheritdoc/>
public IReadOnlyList<IEmbed> Embeds => _embeds ??= Model.Message.Embeds.ToReadOnlyList(model => new TransientEmbed(model));

private IReadOnlyList<IEmbed>? _embeds;

/// <inheritdoc/>
public DateTimeOffset Timestamp { get; }

/// <inheritdoc/>
public DateTimeOffset? EditedAt { get; }

/// <inheritdoc/>
public MessageFlags Flags { get; }

/// <inheritdoc/>
public IReadOnlyList<IMessageSticker> Stickers
{
get
{
if (!Model.Message.StickerItems.HasValue)
return Array.Empty<IMessageSticker>();

return _stickers ??= Model.Message.StickerItems.Value.ToReadOnlyList(model => new TransientMessageSticker(model));
}
}

private IReadOnlyList<IMessageSticker>? _stickers;

public IReadOnlyList<IRowComponent> Components
{
get
{
if (!Model.Message.Components.HasValue)
return Array.Empty<IRowComponent>();

return _components ??= Model.Message.Components.Value.ToReadOnlyList(Client, (model, client) => new TransientRowComponent(client, model));
}
}
private IReadOnlyList<IRowComponent>? _components;

public TransientMessageSnapshot(IClient client, MessageSnapshotJsonModel model)
: base(client, model)
{ }
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,25 @@ public IReadOnlyList<IMessageSticker> Stickers
return _stickers ??= Model.StickerItems.Value.ToReadOnlyList(model => new TransientMessageSticker(model));
}
}

private IReadOnlyList<IMessageSticker>? _stickers;

/// <inheritdoc/>
public IPoll? Poll => _poll ??= Optional.ConvertOrDefault(Model.Poll, poll => new TransientPoll(poll));

private IPoll? _poll;

public IReadOnlyList<IMessageSnapshot> Snapshots
{
get
{
if (!Model.MessageSnapshots.HasValue)
return Array.Empty<IMessageSnapshot>();

return _messageSnapshots ??= Model.MessageSnapshots.Value.ToReadOnlyList(Client, (model, client) => new TransientMessageSnapshot(client, model));
}
}
private IReadOnlyList<IMessageSnapshot>? _messageSnapshots;

public TransientUserMessage(IClient client, MessageJsonModel model)
: base(client, model)
{ }
Expand Down
17 changes: 17 additions & 0 deletions src/Disqord.Core/Enums/MessageReferenceType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Disqord;

/// <summary>
/// Represents the type of a message reference.
/// </summary>
public enum MessageReferenceType
{
/// <summary>
/// A standard reference used by replies.
/// </summary>
Default = 0,

/// <summary>
/// A reference used to point to a message at a point in time.
/// </summary>
Forward = 1
}
5 changes: 4 additions & 1 deletion src/Disqord.Core/Models/Message/MessageJsonModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class MessageJsonModel : JsonModel
public Optional<Snowflake> GuildId;

[JsonProperty("author")]
public UserJsonModel Author = null!;
public Optional<UserJsonModel> Author;

[JsonProperty("member")]
public Optional<MemberJsonModel> Member;
Expand Down Expand Up @@ -79,6 +79,9 @@ public class MessageJsonModel : JsonModel
[JsonProperty("message_reference")]
public Optional<MessageReferenceJsonModel> MessageReference;

[JsonProperty("message_snapshots")]
public Optional<MessageSnapshotJsonModel[]> MessageSnapshots;

[JsonProperty("flags")]
public Optional<MessageFlags> Flags;

Expand Down
3 changes: 3 additions & 0 deletions src/Disqord.Core/Models/Message/MessageReferenceJsonModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ namespace Disqord.Models;

public class MessageReferenceJsonModel : JsonModel
{
[JsonProperty("type")]
public Optional<MessageReferenceType> Type;

[JsonProperty("message_id")]
public Optional<Snowflake> MessageId;

Expand Down
9 changes: 9 additions & 0 deletions src/Disqord.Core/Models/Message/MessageSnapshotJsonModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Disqord.Serialization.Json;

namespace Disqord.Models;

public class MessageSnapshotJsonModel : JsonModel
{
[JsonProperty("message")]
public MessageJsonModel Message = null!;
}
4 changes: 2 additions & 2 deletions src/Disqord.Gateway/Entities/Cached/Message/CachedMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -72,7 +72,7 @@ public virtual void Update(MessageJsonModel model)
}
else
{
_author = new TransientUser(Client, model.Author);
_author = new TransientUser(Client, model.Author.Value);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public class CachedUserMessage : CachedMessage, IGatewayUserMessage, IJsonUpdata
/// <inheritdoc/>
public IPoll? Poll { get; private set; }

public IReadOnlyList<IMessageSnapshot> Snapshots { get; private set; } = null!;

public CachedUserMessage(IGatewayClient client, CachedMember? author, MessageJsonModel model)
: base(client, author, model)
{
Expand Down Expand Up @@ -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<IRowComponent>();
Stickers = Optional.ConvertOrDefault(model.StickerItems, models => models.ToReadOnlyList(model => new TransientMessageSticker(model) as IMessageSticker), Array.Empty<IMessageSticker>());
Poll = Optional.ConvertOrDefault(model.Poll, model => new TransientPoll(model));
Snapshots = Optional.ConvertOrDefault(model.MessageSnapshots, models => models.ToReadOnlyList(Client, (model, client) => new TransientMessageSnapshot(client, model) as IMessageSnapshot)) ?? Array.Empty<IMessageSnapshot>();
}

public void Update(MessageUpdateJsonModel model)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ public IReadOnlyList<IMessageSticker> Stickers
public IPoll? Poll => _poll ??= Optional.ConvertOrDefault(Model.Poll, poll => new TransientPoll(poll));

private IPoll? _poll;

public IReadOnlyList<IMessageSnapshot> Snapshots
{
get
{
if (!Model.MessageSnapshots.HasValue)
return Array.Empty<IMessageSnapshot>();

return _messageSnapshots ??= Model.MessageSnapshots.Value.ToReadOnlyList(Client, (model, client) => new TransientMessageSnapshot(client, model));
}
}
private IReadOnlyList<IMessageSnapshot>? _messageSnapshots;

public TransientGatewayUserMessage(IClient client, MessageJsonModel model)
: base(client, model)
Expand Down

0 comments on commit 824b08b

Please sign in to comment.