From 976f8d85f633eb92b93c5d819c2ad76d633cf0cd Mon Sep 17 00:00:00 2001 From: Velvet Toroyashi <42438262+VelvetToroyashi@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:07:35 -0400 Subject: [PATCH 1/4] fix(core)!: Make IMessageUpdate inherit IMessage This commit changes the IMessageUpdate interface (and subsequently, its implementation)to implement the IMessageInterface instead of the IPartialMessage interface. This change is due to Discord returning a full message object on MESSAGE_UPDATE. BREAKING-CHANGE: IMessageUpdate now implements IMessage (which implements IPartialMessage), `Mentions` is no longer optional. The ad-hoc implementation for IPartialMessage was kept out of convenience (and to avoid further breaking changes) --- .../Gateway/Events/Messages/IMessageUpdate.cs | 9 ++-- .../Gateway/Events/Messages/MessageUpdate.cs | 40 +++++++------- .../MESSAGE_UPDATE.optionals.json | 54 +++++++++++++++++++ 3 files changed, 80 insertions(+), 23 deletions(-) diff --git a/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs b/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs index a1d84cc62f..2ca5d880e7 100644 --- a/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs +++ b/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs @@ -31,7 +31,7 @@ namespace Remora.Discord.API.Abstractions.Gateway.Events; /// Represents the creation of a message. /// [PublicAPI] -public interface IMessageUpdate : IPartialMessage, IGatewayEvent +public interface IMessageUpdate : IMessage, IGatewayEvent { /// /// Gets the ID of the guild the message was sent in. @@ -48,8 +48,11 @@ public interface IMessageUpdate : IPartialMessage, IGatewayEvent /// /// Gets a list of users mentioned in the message. /// - new Optional> Mentions { get; } + new IReadOnlyList Mentions { get; } /// - Optional> IPartialMessage.Mentions => this.Mentions.Map>(u => u); + IReadOnlyList IMessage.Mentions => this.Mentions; + + /// + Optional> IPartialMessage.Mentions => this.Mentions.AsOptional().Map>(u => u); } diff --git a/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs b/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs index d24794476d..9f6da096f5 100644 --- a/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs +++ b/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs @@ -34,26 +34,26 @@ namespace Remora.Discord.API.Gateway.Events; [PublicAPI] public record MessageUpdate ( - Optional GuildID = default, - Optional Member = default, - Optional> Mentions = default, - Optional ID = default, - Optional ChannelID = default, - Optional Author = default, - Optional Content = default, - Optional Timestamp = default, - Optional EditedTimestamp = default, - Optional IsTTS = default, - Optional MentionsEveryone = default, - Optional> MentionedRoles = default, - Optional> MentionedChannels = default, - Optional> Attachments = default, - Optional> Embeds = default, - Optional> Reactions = default, - Optional Nonce = default, - Optional IsPinned = default, - Optional WebhookID = default, - Optional Type = default, + Optional GuildID, + Optional Member, + IReadOnlyList Mentions, + Snowflake ID, + Snowflake ChannelID, + IUser Author, + string Content, + DateTimeOffset Timestamp, + DateTimeOffset? EditedTimestamp, + bool IsTTS, + bool MentionsEveryone, + IReadOnlyList MentionedRoles, + Optional> MentionedChannels, + IReadOnlyList Attachments, + IReadOnlyList Embeds, + Optional> Reactions, + Optional Nonce, + bool IsPinned, + Optional WebhookID, + MessageType Type, Optional Activity = default, Optional Application = default, Optional ApplicationID = default, diff --git a/Tests/Remora.Discord.Tests/Samples/Gateway/Events/MESSAGE_UPDATE/MESSAGE_UPDATE.optionals.json b/Tests/Remora.Discord.Tests/Samples/Gateway/Events/MESSAGE_UPDATE/MESSAGE_UPDATE.optionals.json index 4beb30d839..67581ffec6 100644 --- a/Tests/Remora.Discord.Tests/Samples/Gateway/Events/MESSAGE_UPDATE/MESSAGE_UPDATE.optionals.json +++ b/Tests/Remora.Discord.Tests/Samples/Gateway/Events/MESSAGE_UPDATE/MESSAGE_UPDATE.optionals.json @@ -6,6 +6,60 @@ "id": "999999999999999999", "channel_id": "999999999999999999", "guild_id": "999999999999999999", + "author": { + "username": "none", + "discriminator": "9999", + "id": "999999999999999999", + "avatar": "68b329da9893e34099c7d8ad5cb9c940" + }, + "content": "none", + "timestamp": "1970-01-01T00:00:00.000000+00:00", + "edited_timestamp": "1970-01-01T00:00:00.000000+00:00", + "tts": true, + "mention_everyone": true, + "mention_roles": [ + "999999999999999999" + ], + "mention_channels": [ + { + "id": "999999999999999999", + "guild_id": "999999999999999999", + "type": 1, + "name": "none" + } + ], + "attachments": [ + { + "id": "999999999999999999", + "filename": "file.png", + "size": 0, + "url": "https://www.example.org", + "proxy_url": "https://www.example.org" + } + ], + "embeds": [ + {} + ], + "reactions": [ + { + "count": 1, + "count_details": { + "burst": 1, + "normal": 2 + }, + "me": true, + "me_burst": true, + "emoji": { }, + "burst_colors": [ + "#ffffff", + "#e30f8a" + ] + } + ], + "nonce": "none", + "pinned": true, + "webhook_id": "999999999999999999", + "type": 1, "mentions": [ { "id": "999999999999999999", From 0bda8d2ba436198fca4afaaea5d36db0133c808d Mon Sep 17 00:00:00 2001 From: Velvet Toroyashi <42438262+VelvetToroyashi@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:13:06 -0400 Subject: [PATCH 2/4] fix: Update in accordance to breaking changes --- Remora.Discord.Commands/Responders/CommandResponder.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Remora.Discord.Commands/Responders/CommandResponder.cs b/Remora.Discord.Commands/Responders/CommandResponder.cs index 6563bba690..aeb7809851 100644 --- a/Remora.Discord.Commands/Responders/CommandResponder.cs +++ b/Remora.Discord.Commands/Responders/CommandResponder.cs @@ -128,7 +128,7 @@ public virtual async Task RespondAsync CancellationToken ct = default ) { - if (!gatewayEvent.Content.TryGet(out var content)) + if (string.IsNullOrEmpty(gatewayEvent.Content)) { return Result.FromSuccess(); } @@ -150,7 +150,7 @@ public virtual async Task RespondAsync return Result.FromSuccess(); } - if (gatewayEvent.EditedTimestamp.IsDefined(out var edited)) + if (gatewayEvent.EditedTimestamp is { } edited) { // Check if the edit happened in the last three seconds; if so, we'll assume this isn't some other // change made to the message object @@ -166,7 +166,7 @@ public virtual async Task RespondAsync return Result.FromSuccess(); } - return await ExecuteCommandAsync(content, context, ct); + return await ExecuteCommandAsync(gatewayEvent.Content, context, ct); } /// From 1830265a748384347ca5dfe177f758cc75c6a9e1 Mon Sep 17 00:00:00 2001 From: Velvet Toroyashi <42438262+VelvetToroyashi@users.noreply.github.com> Date: Sun, 3 Nov 2024 01:47:28 -0500 Subject: [PATCH 3/4] refactor!: Drop explicit implementations --- .../API/Gateway/Events/Messages/IMessageUpdate.cs | 11 ----------- .../API/Gateway/Events/Messages/MessageUpdate.cs | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs b/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs index 2ca5d880e7..d6c2343e44 100644 --- a/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs +++ b/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs @@ -44,15 +44,4 @@ public interface IMessageUpdate : IMessage, IGatewayEvent /// without requiring bots to keep member state in memory. /// Optional Member { get; } - - /// - /// Gets a list of users mentioned in the message. - /// - new IReadOnlyList Mentions { get; } - - /// - IReadOnlyList IMessage.Mentions => this.Mentions; - - /// - Optional> IPartialMessage.Mentions => this.Mentions.AsOptional().Map>(u => u); } diff --git a/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs b/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs index 9f6da096f5..b6daa539af 100644 --- a/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs +++ b/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs @@ -36,7 +36,7 @@ public record MessageUpdate ( Optional GuildID, Optional Member, - IReadOnlyList Mentions, + IReadOnlyList Mentions, Snowflake ID, Snowflake ChannelID, IUser Author, From 2258871fcbe5fd7e688f80c976bbcbdb9bc0e65e Mon Sep 17 00:00:00 2001 From: Velvet Toroyashi <42438262+VelvetToroyashi@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:05:04 -0500 Subject: [PATCH 4/4] fix: Re-add explicit implementation for mentions Apparently it isn't enough to simply use `new` with a different type, at least in C#12 --- .../API/Gateway/Events/Messages/IMessageUpdate.cs | 8 ++++++++ .../API/Gateway/Events/Messages/MessageUpdate.cs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs b/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs index d6c2343e44..50c7d09754 100644 --- a/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs +++ b/Backend/Remora.Discord.API.Abstractions/API/Gateway/Events/Messages/IMessageUpdate.cs @@ -44,4 +44,12 @@ public interface IMessageUpdate : IMessage, IGatewayEvent /// without requiring bots to keep member state in memory. /// Optional Member { get; } + + /// + /// Gets a list of users mentioned in the message. + /// + new IReadOnlyList Mentions { get; } + + /// + IReadOnlyList IMessage.Mentions => this.Mentions; } diff --git a/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs b/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs index b6daa539af..9f6da096f5 100644 --- a/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs +++ b/Backend/Remora.Discord.API/API/Gateway/Events/Messages/MessageUpdate.cs @@ -36,7 +36,7 @@ public record MessageUpdate ( Optional GuildID, Optional Member, - IReadOnlyList Mentions, + IReadOnlyList Mentions, Snowflake ID, Snowflake ChannelID, IUser Author,