Browse Source

feature: Add inline replies (#1659)

* Add inline replies

* Missed a few things

* Change xml docs, IUserMessage, and other changes

* Missed one when changing

* Fix referencedMessage author
tags/2.3.0
Paulo GitHub 4 years ago
parent
commit
e3850e1e8f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 239 additions and 132 deletions
  1. +3
    -2
      src/Discord.Net.Commands/ModuleBase.cs
  2. +6
    -3
      src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
  3. +8
    -0
      src/Discord.Net.Core/Entities/Messages/AllowedMentions.cs
  4. +3
    -3
      src/Discord.Net.Core/Entities/Messages/IMessage.cs
  5. +8
    -1
      src/Discord.Net.Core/Entities/Messages/IUserMessage.cs
  6. +25
    -2
      src/Discord.Net.Core/Entities/Messages/MessageReference.cs
  7. +7
    -0
      src/Discord.Net.Core/Entities/Messages/MessageType.cs
  8. +1
    -1
      src/Discord.Net.Core/Entities/Users/IGuildUser.cs
  9. +20
    -0
      src/Discord.Net.Core/Extensions/MessageExtensions.cs
  10. +2
    -0
      src/Discord.Net.Rest/API/Common/Message.cs
  11. +1
    -1
      src/Discord.Net.Rest/API/Common/MessageReference.cs
  12. +2
    -0
      src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs
  13. +1
    -0
      src/Discord.Net.Rest/API/Rest/UploadFileParams.cs
  14. +9
    -21
      src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
  15. +8
    -5
      src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs
  16. +12
    -12
      src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
  17. +12
    -12
      src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
  18. +12
    -12
      src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
  19. +2
    -0
      src/Discord.Net.Rest/Entities/Messages/AllowedMentions.cs
  20. +12
    -1
      src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
  21. +2
    -2
      src/Discord.Net.Rest/Entities/Messages/RestMessage.cs
  22. +12
    -2
      src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
  23. +10
    -0
      src/Discord.Net.Rest/Extensions/EntityExtensions.cs
  24. +8
    -5
      src/Discord.Net.WebSocket/Entities/Channels/ISocketMessageChannel.cs
  25. +12
    -12
      src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs
  26. +12
    -12
      src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs
  27. +12
    -12
      src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
  28. +2
    -2
      src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs
  29. +6
    -0
      src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs
  30. +3
    -3
      test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs
  31. +3
    -3
      test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs
  32. +3
    -3
      test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs

+ 3
- 2
src/Discord.Net.Commands/ModuleBase.cs View File

@@ -35,9 +35,10 @@ namespace Discord.Commands
/// Specifies if notifications are sent for mentioned users and roles in the <paramref name="message"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
protected virtual async Task<IUserMessage> ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
protected virtual async Task<IUserMessage> ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
return await Context.Channel.SendMessageAsync(message, isTTS, embed, options, allowedMentions).ConfigureAwait(false);
return await Context.Channel.SendMessageAsync(message, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);
}
/// <summary>
/// The method to execute before executing the command.


+ 6
- 3
src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs View File

@@ -27,11 +27,12 @@ namespace Discord
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null);
Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
/// <summary>
/// Sends a file to this message channel with an optional caption.
/// </summary>
@@ -63,11 +64,12 @@ namespace Discord
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null);
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
/// <summary>
/// Sends a file to this message channel with an optional caption.
/// </summary>
@@ -96,11 +98,12 @@ namespace Discord
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null);
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);

/// <summary>
/// Gets a message from this message channel.


+ 8
- 0
src/Discord.Net.Core/Entities/Messages/AllowedMentions.cs View File

@@ -49,6 +49,14 @@ namespace Discord
/// </summary>
public List<ulong> UserIds { get; set; } = new List<ulong>();

/// <summary>
/// Gets or sets whether to mention the author of the message you are replying to or not.
/// </summary>
/// <remarks>
/// Specifically for inline replies.
/// </remarks>
public bool? MentionRepliedUser { get; set; } = null;

/// <summary>
/// Initializes a new instance of the <see cref="AllowedMentions"/> class.
/// </summary>


+ 3
- 3
src/Discord.Net.Core/Entities/Messages/IMessage.cs View File

@@ -148,11 +148,11 @@ namespace Discord
MessageApplication Application { get; }

/// <summary>
/// Gets the reference to the original message if it was crossposted.
/// Gets the reference to the original message if it is a crosspost, channel follow add, pin, or reply message.
/// </summary>
/// <remarks>
/// Sent with Cross-posted messages, meaning they were published from news channels
/// and received by subscriber channels.
/// Sent with cross-posted messages, meaning they were published from news channels
/// and received by subscriber channels, channel follow adds, pins, and message replies.
/// </remarks>
/// <returns>
/// A message's reference, if any is associated.


+ 8
- 1
src/Discord.Net.Core/Entities/Messages/IUserMessage.cs View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Discord
@@ -9,6 +8,14 @@ namespace Discord
/// </summary>
public interface IUserMessage : IMessage
{
/// <summary>
/// Gets the referenced message if it is a crosspost, channel follow add, pin, or reply message.
/// </summary>
/// <returns>
/// The referenced message, if any is associated and still exists.
/// </returns>
IUserMessage ReferencedMessage { get; }

/// <summary>
/// Modifies this message.
/// </summary>


+ 25
- 2
src/Discord.Net.Core/Entities/Messages/MessageReference.cs View File

@@ -3,7 +3,7 @@ using System.Diagnostics;
namespace Discord
{
/// <summary>
/// Contains the IDs sent from a crossposted message.
/// Contains the IDs sent from a crossposted message or inline reply.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class MessageReference
@@ -16,13 +16,36 @@ namespace Discord
/// <summary>
/// Gets the Channel ID of the original message.
/// </summary>
public ulong ChannelId { get; internal set; }
/// <remarks>
/// It only will be the default value (zero) if it was instantiated with a <see langword="null"/> in the constructor.
/// </remarks>
public ulong ChannelId { get => InternalChannelId.GetValueOrDefault(); }
internal Optional<ulong> InternalChannelId;

/// <summary>
/// Gets the Guild ID of the original message.
/// </summary>
public Optional<ulong> GuildId { get; internal set; }

/// <summary>
/// Initializes a new instance of the <see cref="MessageReference"/> class.
/// </summary>
/// <param name="messageId">
/// The ID of the message that will be referenced. Used to reply to specific messages and the only parameter required for it.
/// </param>
/// <param name="channelId">
/// The ID of the channel that will be referenced. It will be validated if sent.
/// </param>
/// <param name="guildId">
/// The ID of the guild that will be referenced. It will be validated if sent.
/// </param>
public MessageReference(ulong? messageId = null, ulong? channelId = null, ulong? guildId = null)
{
MessageId = messageId ?? Optional.Create<ulong>();
InternalChannelId = channelId ?? Optional.Create<ulong>();
GuildId = guildId ?? Optional.Create<ulong>();
}

private string DebuggerDisplay
=> $"Channel ID: ({ChannelId}){(GuildId.IsSpecified ? $", Guild ID: ({GuildId.Value})" : "")}" +
$"{(MessageId.IsSpecified ? $", Message ID: ({MessageId.Value})" : "")}";


+ 7
- 0
src/Discord.Net.Core/Entities/Messages/MessageType.cs View File

@@ -57,5 +57,12 @@ namespace Discord
/// The message for when a news channel subscription is added to a text channel.
/// </summary>
ChannelFollowAdd = 12,
/// <summary>
/// The message is an inline reply.
/// </summary>
/// <remarks>
/// Only available in API v8.
/// </remarks>
Reply = 19,
}
}

+ 1
- 1
src/Discord.Net.Core/Entities/Users/IGuildUser.cs View File

@@ -73,7 +73,7 @@ namespace Discord
/// </summary>
/// <example>
/// <para>The following example checks if the current user has the ability to send a message with attachment in
/// this channel; if so, uploads a file via <see cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions)"/>.</para>
/// this channel; if so, uploads a file via <see cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference)"/>.</para>
/// <code language="cs">
/// if (currentUser?.GetPermissions(targetChannel)?.AttachFiles)
/// await targetChannel.SendFileAsync("fortnite.png");


+ 20
- 0
src/Discord.Net.Core/Extensions/MessageExtensions.cs View File

@@ -71,5 +71,25 @@ namespace Discord
foreach (var rxn in reactions)
await msg.RemoveReactionAsync(rxn, user, options).ConfigureAwait(false);
}

/// <summary>
/// Sends an inline reply that references a message.
/// </summary>
/// <param name="text">The message to be sent.</param>
/// <param name="isTTS">Determines whether the message should be read aloud by Discord or not.</param>
/// <param name="embed">The <see cref="Discord.EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
/// <param name="allowedMentions">
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
public static async Task<IUserMessage> ReplyAsync(this IUserMessage msg, string text = null, bool isTTS = false, Embed embed = null, AllowedMentions allowedMentions = null, RequestOptions options = null)
{
return await msg.Channel.SendMessageAsync(text, isTTS, embed, options, allowedMentions, new MessageReference(messageId: msg.Id)).ConfigureAwait(false);
}
}
}

+ 2
- 0
src/Discord.Net.Rest/API/Common/Message.cs View File

@@ -56,5 +56,7 @@ namespace Discord.API
public Optional<MessageFlags> Flags { get; set; }
[JsonProperty("allowed_mentions")]
public Optional<AllowedMentions> AllowedMentions { get; set; }
[JsonProperty("referenced_message")]
public Optional<Message> ReferencedMessage { get; set; }
}
}

+ 1
- 1
src/Discord.Net.Rest/API/Common/MessageReference.cs View File

@@ -8,7 +8,7 @@ namespace Discord.API
public Optional<ulong> MessageId { get; set; }

[JsonProperty("channel_id")]
public ulong ChannelId { get; set; }
public Optional<ulong> ChannelId { get; set; } // Optional when sending, always present when receiving

[JsonProperty("guild_id")]
public Optional<ulong> GuildId { get; set; }


+ 2
- 0
src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs View File

@@ -17,6 +17,8 @@ namespace Discord.API.Rest
public Optional<Embed> Embed { get; set; }
[JsonProperty("allowed_mentions")]
public Optional<AllowedMentions> AllowedMentions { get; set; }
[JsonProperty("message_reference")]
public Optional<MessageReference> MessageReference { get; set; }

public CreateMessageParams(string content)
{


+ 1
- 0
src/Discord.Net.Rest/API/Rest/UploadFileParams.cs View File

@@ -20,6 +20,7 @@ namespace Discord.API.Rest
public Optional<bool> IsTTS { get; set; }
public Optional<Embed> Embed { get; set; }
public Optional<AllowedMentions> AllowedMentions { get; set; }
public Optional<MessageReference> MessageReference { get; set; }
public bool IsSpoiler { get; set; } = false;

public UploadFileParams(Stream file)


+ 9
- 21
src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs View File

@@ -6,7 +6,6 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Model = Discord.API.Channel;
using UserModel = Discord.API.User;

namespace Discord.Rest
{
@@ -130,7 +129,7 @@ namespace Discord.Rest
var model = await client.ApiClient.GetChannelMessageAsync(channel.Id, id, options).ConfigureAwait(false);
if (model == null)
return null;
var author = GetAuthor(client, guild, model.Author.Value, model.WebhookId.ToNullable());
var author = MessageHelper.GetAuthor(client, guild, model.Author.Value, model.WebhookId.ToNullable());
return RestMessage.Create(client, channel, author, model);
}
public static IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessageChannel channel, BaseDiscordClient client,
@@ -165,7 +164,7 @@ namespace Discord.Rest
var builder = ImmutableArray.CreateBuilder<RestMessage>();
foreach (var model in models)
{
var author = GetAuthor(client, guild, model.Author.Value, model.WebhookId.ToNullable());
var author = MessageHelper.GetAuthor(client, guild, model.Author.Value, model.WebhookId.ToNullable());
builder.Add(RestMessage.Create(client, channel, author, model));
}
return builder.ToImmutable();
@@ -193,7 +192,7 @@ namespace Discord.Rest
var builder = ImmutableArray.CreateBuilder<RestMessage>();
foreach (var model in models)
{
var author = GetAuthor(client, guild, model.Author.Value, model.WebhookId.ToNullable());
var author = MessageHelper.GetAuthor(client, guild, model.Author.Value, model.WebhookId.ToNullable());
builder.Add(RestMessage.Create(client, channel, author, model));
}
return builder.ToImmutable();
@@ -201,7 +200,7 @@ namespace Discord.Rest

/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public static async Task<RestUserMessage> SendMessageAsync(IMessageChannel channel, BaseDiscordClient client,
string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, RequestOptions options)
string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, RequestOptions options)
{
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed.");
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed.");
@@ -222,7 +221,7 @@ namespace Discord.Rest
}
}

var args = new CreateMessageParams(text) { IsTTS = isTTS, Embed = embed?.ToModel(), AllowedMentions = allowedMentions?.ToModel() };
var args = new CreateMessageParams(text) { IsTTS = isTTS, Embed = embed?.ToModel(), AllowedMentions = allowedMentions?.ToModel(), MessageReference = messageReference?.ToModel() };
var model = await client.ApiClient.CreateMessageAsync(channel.Id, args, options).ConfigureAwait(false);
return RestUserMessage.Create(client, channel, client.CurrentUser, model);
}
@@ -252,16 +251,16 @@ namespace Discord.Rest
/// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client,
string filePath, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, RequestOptions options, bool isSpoiler)
string filePath, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, RequestOptions options, bool isSpoiler)
{
string filename = Path.GetFileName(filePath);
using (var file = File.OpenRead(filePath))
return await SendFileAsync(channel, client, file, filename, text, isTTS, embed, allowedMentions, options, isSpoiler).ConfigureAwait(false);
return await SendFileAsync(channel, client, file, filename, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler).ConfigureAwait(false);
}

/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client,
Stream stream, string filename, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, RequestOptions options, bool isSpoiler)
Stream stream, string filename, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, RequestOptions options, bool isSpoiler)
{
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed.");
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed.");
@@ -282,7 +281,7 @@ namespace Discord.Rest
}
}

var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS, Embed = embed?.ToModel() ?? Optional<API.Embed>.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, IsSpoiler = isSpoiler };
var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS, Embed = embed?.ToModel() ?? Optional<API.Embed>.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, MessageReference = messageReference?.ToModel() ?? Optional<API.MessageReference>.Unspecified, IsSpoiler = isSpoiler };
var model = await client.ApiClient.UploadFileAsync(channel.Id, args, options).ConfigureAwait(false);
return RestUserMessage.Create(client, channel, client.CurrentUser, model);
}
@@ -450,16 +449,5 @@ namespace Discord.Rest
};
await client.ApiClient.ModifyGuildChannelAsync(channel.Id, apiArgs, options).ConfigureAwait(false);
}

//Helpers
private static IUser GetAuthor(BaseDiscordClient client, IGuild guild, UserModel model, ulong? webhookId)
{
IUser author = null;
if (guild != null)
author = guild.GetUserAsync(model.Id, CacheMode.CacheOnly).Result;
if (author == null)
author = RestUser.Create(client, guild, model, webhookId);
return author;
}
}
}

+ 8
- 5
src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs View File

@@ -24,17 +24,18 @@ namespace Discord.Rest
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null);
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
/// <summary>
/// Sends a file to this message channel with an optional caption.
/// </summary>
/// <remarks>
/// This method follows the same behavior as described in
/// <see cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions)"/>. Please visit
/// <see cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference)"/>. Please visit
/// its documentation for more details on this method.
/// </remarks>
/// <param name="filePath">The file path of the file.</param>
@@ -47,16 +48,17 @@ namespace Discord.Rest
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null);
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
/// <summary>
/// Sends a file to this message channel with an optional caption.
/// </summary>
/// <remarks>
/// This method follows the same behavior as described in <see cref="IMessageChannel.SendFileAsync(Stream, string, string, bool, Embed, RequestOptions, bool, AllowedMentions)"/>.
/// This method follows the same behavior as described in <see cref="IMessageChannel.SendFileAsync(Stream, string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference)"/>.
/// Please visit its documentation for more details on this method.
/// </remarks>
/// <param name="stream">The <see cref="Stream" /> of the file to be sent.</param>
@@ -70,11 +72,12 @@ namespace Discord.Rest
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null);
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);

/// <summary>
/// Gets a message from this message channel.


+ 12
- 12
src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs View File

@@ -93,8 +93,8 @@ namespace Discord.Rest

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, options);
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, options);

/// <inheritdoc />
/// <exception cref="ArgumentException">
@@ -121,12 +121,12 @@ namespace Discord.Rest
/// <exception cref="NotSupportedException"><paramref name="filePath" /> is in an invalid format.</exception>
/// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);
/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);

/// <inheritdoc />
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
@@ -200,14 +200,14 @@ namespace Discord.Rest
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);

//IChannel
/// <inheritdoc />


+ 12
- 12
src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs View File

@@ -95,8 +95,8 @@ namespace Discord.Rest

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, options);
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, options);

/// <inheritdoc />
/// <exception cref="ArgumentException">
@@ -123,12 +123,12 @@ namespace Discord.Rest
/// <exception cref="NotSupportedException"><paramref name="filePath" /> is in an invalid format.</exception>
/// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);
/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);

/// <inheritdoc />
public Task TriggerTypingAsync(RequestOptions options = null)
@@ -178,14 +178,14 @@ namespace Discord.Rest
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);

async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);

async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);

async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);

//IAudioChannel
/// <inheritdoc />


+ 12
- 12
src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs View File

@@ -102,8 +102,8 @@ namespace Discord.Rest

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, options);
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, options);

/// <inheritdoc />
/// <exception cref="ArgumentException">
@@ -130,13 +130,13 @@ namespace Discord.Rest
/// <exception cref="NotSupportedException"><paramref name="filePath" /> is in an invalid format.</exception>
/// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);

/// <inheritdoc />
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
@@ -267,15 +267,15 @@ namespace Discord.Rest
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);

/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);

/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);

//IGuildChannel
/// <inheritdoc />


+ 2
- 0
src/Discord.Net.Rest/Entities/Messages/AllowedMentions.cs View File

@@ -11,5 +11,7 @@ namespace Discord.API
public Optional<ulong[]> Roles { get; set; }
[JsonProperty("users")]
public Optional<ulong[]> Users { get; set; }
[JsonProperty("replied_user")]
public Optional<bool> RepliedUser { get; set; }
}
}

+ 12
- 1
src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Model = Discord.API.Message;
using UserModel = Discord.API.User;

namespace Discord.Rest
{
@@ -290,7 +291,7 @@ namespace Discord.Rest

public static MessageSource GetSource(Model msg)
{
if (msg.Type != MessageType.Default)
if (msg.Type != MessageType.Default && msg.Type != MessageType.Reply)
return MessageSource.System;
else if (msg.WebhookId.IsSpecified)
return MessageSource.Webhook;
@@ -307,5 +308,15 @@ namespace Discord.Rest
{
await client.ApiClient.CrosspostAsync(channelId, msgId, options).ConfigureAwait(false);
}

public static IUser GetAuthor(BaseDiscordClient client, IGuild guild, UserModel model, ulong? webhookId)
{
IUser author = null;
if (guild != null)
author = guild.GetUserAsync(model.Id, CacheMode.CacheOnly).Result;
if (author == null)
author = RestUser.Create(client, guild, model, webhookId);
return author;
}
}
}

+ 2
- 2
src/Discord.Net.Rest/Entities/Messages/RestMessage.cs View File

@@ -77,7 +77,7 @@ namespace Discord.Rest
}
internal static RestMessage Create(BaseDiscordClient discord, IMessageChannel channel, IUser author, Model model)
{
if (model.Type == MessageType.Default)
if (model.Type == MessageType.Default || model.Type == MessageType.Reply)
return RestUserMessage.Create(discord, channel, author, model);
else
return RestSystemMessage.Create(discord, channel, author, model);
@@ -119,7 +119,7 @@ namespace Discord.Rest
Reference = new MessageReference
{
GuildId = model.Reference.Value.GuildId,
ChannelId = model.Reference.Value.ChannelId,
InternalChannelId = model.Reference.Value.ChannelId,
MessageId = model.Reference.Value.MessageId
};
}


+ 12
- 2
src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs View File

@@ -15,6 +15,7 @@ namespace Discord.Rest
{
private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed;
private long? _editedTimestampTicks;
private IUserMessage _referencedMessage;
private ImmutableArray<Attachment> _attachments = ImmutableArray.Create<Attachment>();
private ImmutableArray<Embed> _embeds = ImmutableArray.Create<Embed>();
private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>();
@@ -43,6 +44,8 @@ namespace Discord.Rest
public override IReadOnlyCollection<RestUser> MentionedUsers => _userMentions;
/// <inheritdoc />
public override IReadOnlyCollection<ITag> Tags => _tags;
/// <inheritdoc />
public IUserMessage ReferencedMessage => _referencedMessage;

internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source)
: base(discord, id, channel, author, source)
@@ -118,14 +121,21 @@ namespace Discord.Rest
}
}

var guildId = (Channel as IGuildChannel)?.GuildId;
var guild = guildId != null ? (Discord as IDiscordClient).GetGuildAsync(guildId.Value, CacheMode.CacheOnly).Result : null;
if (model.Content.IsSpecified)
{
var text = model.Content.Value;
var guildId = (Channel as IGuildChannel)?.GuildId;
var guild = guildId != null ? (Discord as IDiscordClient).GetGuildAsync(guildId.Value, CacheMode.CacheOnly).Result : null;
_tags = MessageHelper.ParseTags(text, null, guild, _userMentions);
model.Content = text;
}

if (model.ReferencedMessage.IsSpecified && model.ReferencedMessage.Value != null)
{
var refMsg = model.ReferencedMessage.Value;
IUser refMsgAuthor = MessageHelper.GetAuthor(Discord, guild, refMsg.Author.Value, refMsg.WebhookId.ToNullable());
_referencedMessage = RestUserMessage.Create(Discord, Channel, refMsgAuthor, refMsg);
}
}

/// <inheritdoc />


+ 10
- 0
src/Discord.Net.Rest/Extensions/EntityExtensions.cs View File

@@ -68,6 +68,16 @@ namespace Discord.Rest
Parse = entity.AllowedTypes?.EnumerateMentionTypes().ToArray(),
Roles = entity.RoleIds?.ToArray(),
Users = entity.UserIds?.ToArray(),
RepliedUser = entity.MentionRepliedUser ?? Optional.Create<bool>(),
};
}
public static API.MessageReference ToModel(this MessageReference entity)
{
return new API.MessageReference()
{
ChannelId = entity.InternalChannelId,
GuildId = entity.GuildId,
MessageId = entity.MessageId,
};
}
public static IEnumerable<string> EnumerateMentionTypes(this AllowedMentionTypes mentionTypes)


+ 8
- 5
src/Discord.Net.WebSocket/Entities/Channels/ISocketMessageChannel.cs View File

@@ -33,16 +33,17 @@ namespace Discord.WebSocket
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null);
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
/// <summary>
/// Sends a file to this message channel with an optional caption.
/// </summary>
/// <remarks>
/// This method follows the same behavior as described in <see cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions)"/>.
/// This method follows the same behavior as described in <see cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference)"/>.
/// Please visit its documentation for more details on this method.
/// </remarks>
/// <param name="filePath">The file path of the file.</param>
@@ -55,16 +56,17 @@ namespace Discord.WebSocket
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null);
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
/// <summary>
/// Sends a file to this message channel with an optional caption.
/// </summary>
/// <remarks>
/// This method follows the same behavior as described in <see cref="IMessageChannel.SendFileAsync(Stream, string, string, bool, Embed, RequestOptions, bool, AllowedMentions)"/>.
/// This method follows the same behavior as described in <see cref="IMessageChannel.SendFileAsync(Stream, string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference)"/>.
/// Please visit its documentation for more details on this method.
/// </remarks>
/// <param name="stream">The <see cref="Stream" /> of the file to be sent.</param>
@@ -78,11 +80,12 @@ namespace Discord.WebSocket
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
/// If <c>null</c>, all mentioned roles and users will be notified.
/// </param>
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
/// <returns>
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null);
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);

/// <summary>
/// Gets a cached message from this channel.


+ 12
- 12
src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs View File

@@ -135,16 +135,16 @@ namespace Discord.WebSocket

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, options);
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, options);

/// <inheritdoc />
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);
/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);
/// <inheritdoc />
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
=> ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options);
@@ -229,14 +229,14 @@ namespace Discord.WebSocket
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);

//IChannel
/// <inheritdoc />


+ 12
- 12
src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs View File

@@ -163,15 +163,15 @@ namespace Discord.WebSocket

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, options);
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, options);

/// <inheritdoc />
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);
/// <inheritdoc />
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);

/// <inheritdoc />
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
@@ -293,14 +293,14 @@ namespace Discord.WebSocket
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);

/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);

//IAudioChannel
/// <inheritdoc />


+ 12
- 12
src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs View File

@@ -161,17 +161,17 @@ namespace Discord.WebSocket

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, options);
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, options);

/// <inheritdoc />
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);

/// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, options, isSpoiler);
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, options, isSpoiler);

/// <inheritdoc />
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
@@ -302,14 +302,14 @@ namespace Discord.WebSocket
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);

/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference).ConfigureAwait(false);
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);

// INestedChannel
/// <inheritdoc />


+ 2
- 2
src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs View File

@@ -110,7 +110,7 @@ namespace Discord.WebSocket
}
internal static SocketMessage Create(DiscordSocketClient discord, ClientState state, SocketUser author, ISocketMessageChannel channel, Model model)
{
if (model.Type == MessageType.Default)
if (model.Type == MessageType.Default || model.Type == MessageType.Reply)
return SocketUserMessage.Create(discord, state, author, channel, model);
else
return SocketSystemMessage.Create(discord, state, author, channel, model);
@@ -152,7 +152,7 @@ namespace Discord.WebSocket
Reference = new MessageReference
{
GuildId = model.Reference.Value.GuildId,
ChannelId = model.Reference.Value.ChannelId,
InternalChannelId = model.Reference.Value.ChannelId,
MessageId = model.Reference.Value.MessageId
};
}


+ 6
- 0
src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs View File

@@ -17,6 +17,7 @@ namespace Discord.WebSocket
{
private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed;
private long? _editedTimestampTicks;
private IUserMessage _referencedMessage;
private ImmutableArray<Attachment> _attachments = ImmutableArray.Create<Attachment>();
private ImmutableArray<Embed> _embeds = ImmutableArray.Create<Embed>();
private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>();
@@ -45,6 +46,8 @@ namespace Discord.WebSocket
public override IReadOnlyCollection<SocketRole> MentionedRoles => _roleMentions;
/// <inheritdoc />
public override IReadOnlyCollection<SocketUser> MentionedUsers => _userMentions;
/// <inheritdoc />
public IUserMessage ReferencedMessage => _referencedMessage;

internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source)
: base(discord, id, channel, author, source)
@@ -131,6 +134,9 @@ namespace Discord.WebSocket
_tags = MessageHelper.ParseTags(text, Channel, guild, _userMentions);
model.Content = text;
}

if (model.ReferencedMessage.IsSpecified && model.ReferencedMessage.Value != null)
_referencedMessage = RestUserMessage.Create(Discord, Channel, Author, model.ReferencedMessage.Value);
}

/// <inheritdoc />


+ 3
- 3
test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs View File

@@ -73,17 +73,17 @@ namespace Discord
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}


+ 3
- 3
test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs View File

@@ -81,17 +81,17 @@ namespace Discord
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}


+ 3
- 3
test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs View File

@@ -167,17 +167,17 @@ namespace Discord
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
{
throw new NotImplementedException();
}


Loading…
Cancel
Save