@@ -148,11 +148,11 @@ namespace Discord | |||||
MessageApplication Application { get; } | MessageApplication Application { get; } | ||||
/// <summary> | /// <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> | /// </summary> | ||||
/// <remarks> | /// <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> | /// </remarks> | ||||
/// <returns> | /// <returns> | ||||
/// A message's reference, if any is associated. | /// A message's reference, if any is associated. | ||||
@@ -1,5 +1,4 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord | namespace Discord | ||||
@@ -9,6 +8,14 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
public interface IUserMessage : IMessage | 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> | /// <summary> | ||||
/// Modifies this message. | /// Modifies this message. | ||||
/// </summary> | /// </summary> | ||||
@@ -17,9 +17,10 @@ namespace Discord | |||||
/// Gets the Channel ID of the original message. | /// Gets the Channel ID of the original message. | ||||
/// </summary> | /// </summary> | ||||
/// <remarks> | /// <remarks> | ||||
/// If there is no referenced channel id, it will be the default value (zero). | |||||
/// It only will be the default value (zero) if it was instantiated with a <see langword="null"/> in the constructor. | |||||
/// </remarks> | /// </remarks> | ||||
public ulong ChannelId { get; internal set; } | |||||
public ulong ChannelId { get => InternalChannelId.GetValueOrDefault(); } | |||||
internal Optional<ulong> InternalChannelId; | |||||
/// <summary> | /// <summary> | ||||
/// Gets the Guild ID of the original message. | /// Gets the Guild ID of the original message. | ||||
@@ -41,7 +42,7 @@ namespace Discord | |||||
public MessageReference(ulong? messageId = null, ulong? channelId = null, ulong? guildId = null) | public MessageReference(ulong? messageId = null, ulong? channelId = null, ulong? guildId = null) | ||||
{ | { | ||||
MessageId = messageId ?? Optional.Create<ulong>(); | MessageId = messageId ?? Optional.Create<ulong>(); | ||||
ChannelId = channelId ?? default(ulong); | |||||
InternalChannelId = channelId ?? Optional.Create<ulong>(); | |||||
GuildId = guildId ?? Optional.Create<ulong>(); | GuildId = guildId ?? Optional.Create<ulong>(); | ||||
} | } | ||||
@@ -63,6 +63,6 @@ namespace Discord | |||||
/// <remarks> | /// <remarks> | ||||
/// Only available in API v8. | /// Only available in API v8. | ||||
/// </remarks> | /// </remarks> | ||||
InlineReply = 19, | |||||
Reply = 19, | |||||
} | } | ||||
} | } |
@@ -71,5 +71,25 @@ namespace Discord | |||||
foreach (var rxn in reactions) | foreach (var rxn in reactions) | ||||
await msg.RemoveReactionAsync(rxn, user, options).ConfigureAwait(false); | 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); | |||||
} | |||||
} | } | ||||
} | } |
@@ -8,7 +8,7 @@ namespace Discord.API | |||||
public Optional<ulong> MessageId { get; set; } | public Optional<ulong> MessageId { get; set; } | ||||
[JsonProperty("channel_id")] | [JsonProperty("channel_id")] | ||||
public Optional<ulong> ChannelId { get; set; } | |||||
public Optional<ulong> ChannelId { get; set; } // Optional when sending, always present when receiving | |||||
[JsonProperty("guild_id")] | [JsonProperty("guild_id")] | ||||
public Optional<ulong> GuildId { get; set; } | public Optional<ulong> GuildId { get; set; } | ||||
@@ -282,7 +282,7 @@ namespace Discord.Rest | |||||
public static MessageSource GetSource(Model msg) | public static MessageSource GetSource(Model msg) | ||||
{ | { | ||||
if (msg.Type != MessageType.Default) | |||||
if (msg.Type != MessageType.Default && msg.Type != MessageType.Reply) | |||||
return MessageSource.System; | return MessageSource.System; | ||||
else if (msg.WebhookId.IsSpecified) | else if (msg.WebhookId.IsSpecified) | ||||
return MessageSource.Webhook; | return MessageSource.Webhook; | ||||
@@ -77,7 +77,7 @@ namespace Discord.Rest | |||||
} | } | ||||
internal static RestMessage Create(BaseDiscordClient discord, IMessageChannel channel, IUser author, Model model) | 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); | return RestUserMessage.Create(discord, channel, author, model); | ||||
else | else | ||||
return RestSystemMessage.Create(discord, channel, author, model); | return RestSystemMessage.Create(discord, channel, author, model); | ||||
@@ -119,7 +119,7 @@ namespace Discord.Rest | |||||
Reference = new MessageReference | Reference = new MessageReference | ||||
{ | { | ||||
GuildId = model.Reference.Value.GuildId, | GuildId = model.Reference.Value.GuildId, | ||||
ChannelId = model.Reference.Value.ChannelId.GetValueOrDefault(), | |||||
InternalChannelId = model.Reference.Value.ChannelId, | |||||
MessageId = model.Reference.Value.MessageId | MessageId = model.Reference.Value.MessageId | ||||
}; | }; | ||||
} | } | ||||
@@ -15,6 +15,7 @@ namespace Discord.Rest | |||||
{ | { | ||||
private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed; | private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed; | ||||
private long? _editedTimestampTicks; | private long? _editedTimestampTicks; | ||||
private IUserMessage _referencedMessage; | |||||
private ImmutableArray<Attachment> _attachments = ImmutableArray.Create<Attachment>(); | private ImmutableArray<Attachment> _attachments = ImmutableArray.Create<Attachment>(); | ||||
private ImmutableArray<Embed> _embeds = ImmutableArray.Create<Embed>(); | private ImmutableArray<Embed> _embeds = ImmutableArray.Create<Embed>(); | ||||
private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | ||||
@@ -43,6 +44,8 @@ namespace Discord.Rest | |||||
public override IReadOnlyCollection<RestUser> MentionedUsers => _userMentions; | public override IReadOnlyCollection<RestUser> MentionedUsers => _userMentions; | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public override IReadOnlyCollection<ITag> Tags => _tags; | public override IReadOnlyCollection<ITag> Tags => _tags; | ||||
/// <inheritdoc /> | |||||
public IUserMessage ReferencedMessage => _referencedMessage; | |||||
internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source) | internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source) | ||||
: base(discord, id, channel, author, source) | : base(discord, id, channel, author, source) | ||||
@@ -126,6 +129,9 @@ namespace Discord.Rest | |||||
_tags = MessageHelper.ParseTags(text, null, guild, _userMentions); | _tags = MessageHelper.ParseTags(text, null, guild, _userMentions); | ||||
model.Content = text; | model.Content = text; | ||||
} | } | ||||
if (model.ReferencedMessage.IsSpecified && model.ReferencedMessage.Value != null) | |||||
_referencedMessage = RestUserMessage.Create(Discord, Channel, Author, model.ReferencedMessage.Value); | |||||
} | } | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
@@ -75,7 +75,7 @@ namespace Discord.Rest | |||||
{ | { | ||||
return new API.MessageReference() | return new API.MessageReference() | ||||
{ | { | ||||
ChannelId = entity.ChannelId == default(ulong) ? Optional.Create<ulong>() : entity.ChannelId, | |||||
ChannelId = entity.InternalChannelId, | |||||
GuildId = entity.GuildId, | GuildId = entity.GuildId, | ||||
MessageId = entity.MessageId, | MessageId = entity.MessageId, | ||||
}; | }; | ||||
@@ -151,7 +151,6 @@ namespace Discord.WebSocket | |||||
} | } | ||||
private int _maxWaitForGuildAvailable = 10000; | private int _maxWaitForGuildAvailable = 10000; | ||||
/// <summary> | |||||
/// Gets or sets gateway intents to limit what events are sent from Discord. Allows for more granular control than the <see cref="GuildSubscriptions"/> property. | /// Gets or sets gateway intents to limit what events are sent from Discord. Allows for more granular control than the <see cref="GuildSubscriptions"/> property. | ||||
/// </summary> | /// </summary> | ||||
/// <remarks> | /// <remarks> | ||||
@@ -110,7 +110,7 @@ namespace Discord.WebSocket | |||||
} | } | ||||
internal static SocketMessage Create(DiscordSocketClient discord, ClientState state, SocketUser author, ISocketMessageChannel channel, Model model) | 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); | return SocketUserMessage.Create(discord, state, author, channel, model); | ||||
else | else | ||||
return SocketSystemMessage.Create(discord, state, author, channel, model); | return SocketSystemMessage.Create(discord, state, author, channel, model); | ||||
@@ -17,6 +17,7 @@ namespace Discord.WebSocket | |||||
{ | { | ||||
private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed; | private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed; | ||||
private long? _editedTimestampTicks; | private long? _editedTimestampTicks; | ||||
private IUserMessage _referencedMessage; | |||||
private ImmutableArray<Attachment> _attachments = ImmutableArray.Create<Attachment>(); | private ImmutableArray<Attachment> _attachments = ImmutableArray.Create<Attachment>(); | ||||
private ImmutableArray<Embed> _embeds = ImmutableArray.Create<Embed>(); | private ImmutableArray<Embed> _embeds = ImmutableArray.Create<Embed>(); | ||||
private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | ||||
@@ -45,6 +46,8 @@ namespace Discord.WebSocket | |||||
public override IReadOnlyCollection<SocketRole> MentionedRoles => _roleMentions; | public override IReadOnlyCollection<SocketRole> MentionedRoles => _roleMentions; | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public override IReadOnlyCollection<SocketUser> MentionedUsers => _userMentions; | public override IReadOnlyCollection<SocketUser> MentionedUsers => _userMentions; | ||||
/// <inheritdoc /> | |||||
public IUserMessage ReferencedMessage => _referencedMessage; | |||||
internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source) | internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source) | ||||
: base(discord, id, channel, author, source) | : base(discord, id, channel, author, source) | ||||
@@ -131,6 +134,9 @@ namespace Discord.WebSocket | |||||
_tags = MessageHelper.ParseTags(text, Channel, guild, _userMentions); | _tags = MessageHelper.ParseTags(text, Channel, guild, _userMentions); | ||||
model.Content = text; | model.Content = text; | ||||
} | } | ||||
if (model.ReferencedMessage.IsSpecified && model.ReferencedMessage.Value != null) | |||||
_referencedMessage = RestUserMessage.Create(Discord, Channel, Author, model.ReferencedMessage.Value); | |||||
} | } | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||