Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for message snapshots (forwarding) #126

Merged
merged 3 commits into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 referenced (forwarded) by this message.
/// </summary>
IReadOnlyList<IMessageSnapshot> MessageSnapshots { get; }
QuantumToasted marked this conversation as resolved.
Show resolved Hide resolved
}
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.Reply"/>.
/// </remarks>
public Optional<MessageReferenceType> Type { get; set; } = MessageReferenceType.Reply;

/// <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.Reply;

/// <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> MessageSnapshots
{
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>
Reply = 0,
Quahu marked this conversation as resolved.
Show resolved Hide resolved

/// <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> MessageSnapshots { 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));
MessageSnapshots = 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> MessageSnapshots
{
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
Loading