diff --git a/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs index c01df96fd..b34afd027 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs @@ -12,7 +12,11 @@ namespace Discord.Rest public class RestStageChannel : RestVoiceChannel, IStageChannel { /// - public string Topic { get; private set; } + /// + /// This field is always false for stage channels. + /// + public override bool IsTextInVoice + => false; /// public StagePrivacyLevel? PrivacyLevel { get; private set; } @@ -37,13 +41,11 @@ namespace Discord.Rest IsLive = isLive; if(isLive) { - Topic = model.Topic; PrivacyLevel = model.PrivacyLevel; IsDiscoverableDisabled = model.DiscoverableDisabled; } else { - Topic = null; PrivacyLevel = null; IsDiscoverableDisabled = null; } diff --git a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs index b3add4d81..a73bda334 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs @@ -86,25 +86,25 @@ namespace Discord.Rest => ChannelHelper.GetUsersAsync(this, Guild, Discord, null, null, options); /// - public Task GetMessageAsync(ulong id, RequestOptions options = null) + public virtual Task GetMessageAsync(ulong id, RequestOptions options = null) => ChannelHelper.GetMessageAsync(this, Discord, id, options); /// - public IAsyncEnumerable> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) + public virtual IAsyncEnumerable> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) => ChannelHelper.GetMessagesAsync(this, Discord, null, Direction.Before, limit, options); /// - public IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) + public virtual IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) => ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, options); /// - public IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) + public virtual IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) => ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, options); /// - public Task> GetPinnedMessagesAsync(RequestOptions options = null) + public virtual Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, + public virtual Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, @@ -136,7 +136,7 @@ namespace Discord.Rest /// An I/O error occurred while opening the file. /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, + public virtual Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) @@ -146,7 +146,7 @@ namespace Discord.Rest /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, + public virtual Task 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, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) @@ -156,7 +156,7 @@ namespace Discord.Rest /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, + public virtual Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) @@ -166,35 +166,35 @@ namespace Discord.Rest /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false, + public virtual Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, messageReference, components, stickers, options, embeds, flags); /// - public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) + public virtual Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); /// - public Task DeleteMessageAsync(IMessage message, RequestOptions options = null) + public virtual Task DeleteMessageAsync(IMessage message, RequestOptions options = null) => ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options); /// - public Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null) + public virtual Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null) => ChannelHelper.DeleteMessagesAsync(this, Discord, messages.Select(x => x.Id), options); /// - public Task DeleteMessagesAsync(IEnumerable messageIds, RequestOptions options = null) + public virtual Task DeleteMessagesAsync(IEnumerable messageIds, RequestOptions options = null) => ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options); /// - public async Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) + public virtual async Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) => await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false); /// - public Task TriggerTypingAsync(RequestOptions options = null) + public virtual Task TriggerTypingAsync(RequestOptions options = null) => ChannelHelper.TriggerTypingAsync(this, Discord, options); /// - public IDisposable EnterTypingState(RequestOptions options = null) + public virtual IDisposable EnterTypingState(RequestOptions options = null) => ChannelHelper.EnterTypingState(this, Discord, options); /// diff --git a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs index ec52f0e86..31d313a48 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs @@ -16,6 +16,11 @@ namespace Discord.Rest public class RestVoiceChannel : RestTextChannel, IVoiceChannel, IRestAudioChannel { #region RestVoiceChannel + /// + /// Gets whether or not the guild has Text-In-Voice enabled and the voice channel is a TiV channel. + /// + public virtual bool IsTextInVoice + => Guild.Features.HasTextInVoice; /// public int Bitrate { get; private set; } /// @@ -66,26 +71,173 @@ namespace Discord.Rest #endregion - #region Invites - /// - public async Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); - /// - public async Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false); - /// - public virtual async Task CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, (ulong)application, options); - /// - public async Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false); - /// - public async Task> GetInvitesAsync(RequestOptions options = null) - => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); - private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; + + #region TextOverrides + + /// This function is only supported in Text-In-Voice channels. + public override Task GetMessageAsync(ulong id, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessageAsync(id, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessageAsync(IMessage message, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessageAsync(message, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessageAsync(messageId, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessagesAsync(messages, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessagesAsync(IEnumerable messageIds, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessagesAsync(messageIds, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override IDisposable EnterTypingState(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.EnterTypingState(options); + } + + /// This function is only supported in Text-In-Voice channels. + public override IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessagesAsync(fromMessage, dir, limit, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override IAsyncEnumerable> GetMessagesAsync(int limit = 100, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessagesAsync(limit, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessagesAsync(fromMessageId, dir, limit, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task> GetPinnedMessagesAsync(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetPinnedMessagesAsync(options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task GetWebhookAsync(ulong id, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetWebhookAsync(id, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task> GetWebhooksAsync(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetWebhooksAsync(options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.CreateWebhookAsync(name, avatar, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.ModifyMessageAsync(messageId, func, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task 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, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task TriggerTypingAsync(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.TriggerTypingAsync(options); + } + #endregion + #region IAudioChannel /// /// Connecting to a REST-based channel is not supported. diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 92d598466..974ea69ad 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -1161,7 +1161,6 @@ namespace Discord.Rest /// in order to use this property. /// /// - /// A collection of speakers for the event. /// The location of the event; links are supported /// The optional banner image for the event. /// The options to be used when sending the request. diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs index 8a8921abe..b8c0f961d 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs @@ -333,7 +333,6 @@ namespace Discord.Rest => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); /// Task IDiscordInteraction.RespondWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); - /// #if NETCOREAPP3_0_OR_GREATER != true /// Task IDiscordInteraction.RespondWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); diff --git a/src/Discord.Net.Rest/Entities/Roles/RestRole.cs b/src/Discord.Net.Rest/Entities/Roles/RestRole.cs index a2ad4fd77..dc7cbaf1c 100644 --- a/src/Discord.Net.Rest/Entities/Roles/RestRole.cs +++ b/src/Discord.Net.Rest/Entities/Roles/RestRole.cs @@ -25,7 +25,7 @@ namespace Discord.Rest public string Name { get; private set; } /// public string Icon { get; private set; } - /// /> + /// public Emoji Emoji { get; private set; } /// public GuildPermissions Permissions { get; private set; } diff --git a/src/Discord.Net.Rest/Net/ED25519/CryptoBytes.cs b/src/Discord.Net.Rest/Net/ED25519/CryptoBytes.cs index cfd64104d..43cd3f902 100644 --- a/src/Discord.Net.Rest/Net/ED25519/CryptoBytes.cs +++ b/src/Discord.Net.Rest/Net/ED25519/CryptoBytes.cs @@ -243,7 +243,7 @@ namespace Discord.Net.ED25519 /// /// // Decode a base58-encoded string into byte array /// - /// Base58 data string + /// Base58 data string /// Byte array public static byte[] Base58Decode(string input) { diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs index 75e79eec2..4915a5c39 100644 --- a/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs +++ b/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs @@ -60,14 +60,9 @@ namespace Discord.Net.Queue _clearToken?.Cancel(); _clearToken?.Dispose(); _clearToken = new CancellationTokenSource(); - if (_parentToken != null) - { - _requestCancelTokenSource?.Dispose(); - _requestCancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_clearToken.Token, _parentToken); - _requestCancelToken = _requestCancelTokenSource.Token; - } - else - _requestCancelToken = _clearToken.Token; + _requestCancelTokenSource?.Dispose(); + _requestCancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_clearToken.Token, _parentToken); + _requestCancelToken = _requestCancelTokenSource.Token; } finally { _tokenLock.Release(); } } diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs index 91bca5054..56cd92185 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs @@ -15,7 +15,11 @@ namespace Discord.WebSocket public class SocketStageChannel : SocketVoiceChannel, IStageChannel { /// - public string Topic { get; private set; } + /// + /// This field is always false for stage channels. + /// + public override bool IsTextInVoice + => false; /// public StagePrivacyLevel? PrivacyLevel { get; private set; } @@ -49,19 +53,16 @@ namespace Discord.WebSocket entity.Update(state, model); return entity; } - internal void Update(StageInstance model, bool isLive = false) { IsLive = isLive; if (isLive) { - Topic = model.Topic; PrivacyLevel = model.PrivacyLevel; IsDiscoverableDisabled = model.DiscoverableDisabled; } else { - Topic = null; PrivacyLevel = null; IsDiscoverableDisabled = null; } diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs index e4a299edc..e8454ecf8 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -128,7 +128,7 @@ namespace Discord.WebSocket #region Messages /// - public SocketMessage GetCachedMessage(ulong id) + public virtual SocketMessage GetCachedMessage(ulong id) => _messages?.Get(id); /// /// Gets a message from this message channel. @@ -143,7 +143,7 @@ namespace Discord.WebSocket /// A task that represents an asynchronous get operation for retrieving the message. The task result contains /// the retrieved message; null if no message is found with the specified identifier. /// - public async Task GetMessageAsync(ulong id, RequestOptions options = null) + public virtual async Task GetMessageAsync(ulong id, RequestOptions options = null) { IMessage msg = _messages?.Get(id); if (msg == null) @@ -163,7 +163,7 @@ namespace Discord.WebSocket /// /// Paged collection of messages. /// - public IAsyncEnumerable> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) + public virtual IAsyncEnumerable> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options); /// /// Gets a collection of messages in this channel. @@ -179,7 +179,7 @@ namespace Discord.WebSocket /// /// Paged collection of messages. /// - public IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) + public virtual IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options); /// /// Gets a collection of messages in this channel. @@ -195,25 +195,25 @@ namespace Discord.WebSocket /// /// Paged collection of messages. /// - public IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) + public virtual IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options); /// - public IReadOnlyCollection GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch) + public virtual IReadOnlyCollection GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch) => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, null, Direction.Before, limit); /// - public IReadOnlyCollection GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) + public virtual IReadOnlyCollection GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessageId, dir, limit); /// - public IReadOnlyCollection GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) + public virtual IReadOnlyCollection GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessage.Id, dir, limit); /// - public Task> GetPinnedMessagesAsync(RequestOptions options = null) + public virtual Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, + public virtual Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, @@ -221,7 +221,7 @@ namespace Discord.WebSocket /// /// The only valid are and . - public Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, + public virtual Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) @@ -230,7 +230,7 @@ namespace Discord.WebSocket /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, + public virtual Task 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, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) @@ -239,7 +239,7 @@ namespace Discord.WebSocket /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, + public virtual Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) @@ -248,7 +248,7 @@ namespace Discord.WebSocket /// /// Message content is too long, length must be less or equal to . /// The only valid are and . - public Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false, + public virtual Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) @@ -256,28 +256,28 @@ namespace Discord.WebSocket messageReference, components, stickers, options, embeds, flags); /// - public Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null) + public virtual Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null) => ChannelHelper.DeleteMessagesAsync(this, Discord, messages.Select(x => x.Id), options); /// - public Task DeleteMessagesAsync(IEnumerable messageIds, RequestOptions options = null) + public virtual Task DeleteMessagesAsync(IEnumerable messageIds, RequestOptions options = null) => ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options); /// - public async Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) + public virtual async Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) => await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false); /// - public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) + public virtual Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); /// - public Task DeleteMessageAsync(IMessage message, RequestOptions options = null) + public virtual Task DeleteMessageAsync(IMessage message, RequestOptions options = null) => ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options); /// - public Task TriggerTypingAsync(RequestOptions options = null) + public virtual Task TriggerTypingAsync(RequestOptions options = null) => ChannelHelper.TriggerTypingAsync(this, Discord, options); /// - public IDisposable EnterTypingState(RequestOptions options = null) + public virtual IDisposable EnterTypingState(RequestOptions options = null) => ChannelHelper.EnterTypingState(this, Discord, options); internal void AddMessage(SocketMessage msg) diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs index fc7fe7e41..5fc99c3f1 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs @@ -18,30 +18,18 @@ namespace Discord.WebSocket public class SocketVoiceChannel : SocketTextChannel, IVoiceChannel, ISocketAudioChannel { #region SocketVoiceChannel - /// - public int Bitrate { get; private set; } - /// - public int? UserLimit { get; private set; } - /// - public string RTCRegion { get; private set; } - - /// - public ulong? CategoryId { get; private set; } /// - /// Gets the parent (category) channel of this channel. + /// Gets whether or not the guild has Text-In-Voice enabled and the voice channel is a TiV channel. /// - /// - /// A category channel representing the parent of this channel; null if none is set. - /// - public ICategoryChannel Category - => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; + public virtual bool IsTextInVoice + => Guild.Features.HasTextInVoice; /// - public string Mention => MentionUtils.MentionChannel(Id); - + public int Bitrate { get; private set; } + /// + public int? UserLimit { get; private set; } /// - public Task SyncPermissionsAsync(RequestOptions options = null) - => ChannelHelper.SyncPermissionsAsync(this, Discord, options); + public string RTCRegion { get; private set; } /// /// Gets a collection of users that are currently connected to this voice channel. @@ -100,38 +88,214 @@ namespace Discord.WebSocket return null; } - /// - /// Cannot create threads in voice channels. + /// Cannot create threads in voice channels. public override Task CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null) => throw new InvalidOperationException("Voice channels cannot contain threads."); - - /// - /// Cannot modify text channel properties within a voice channel. + + /// Cannot modify text channel properties for voice channels. public override Task ModifyAsync(Action func, RequestOptions options = null) => throw new InvalidOperationException("Cannot modify text channel properties for voice channels."); - + #endregion - #region Invites - /// - public async Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); - /// - public async Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false); - /// - public virtual async Task CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, (ulong)application, options); - /// - public async Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) - => await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false); - /// - public async Task> GetInvitesAsync(RequestOptions options = null) - => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); + #region TextOverrides + + /// This function is only supported in Text-In-Voice channels. + public override Task GetMessageAsync(ulong id, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessageAsync(id, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessageAsync(IMessage message, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessageAsync(message, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessageAsync(messageId, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessagesAsync(messages, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task DeleteMessagesAsync(IEnumerable messageIds, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.DeleteMessagesAsync(messageIds, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override IDisposable EnterTypingState(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.EnterTypingState(options); + } + + /// This function is only supported in Text-In-Voice channels. + public override SocketMessage GetCachedMessage(ulong id) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetCachedMessage(id); + } + + /// This function is only supported in Text-In-Voice channels. + public override IReadOnlyCollection GetCachedMessages(IMessage fromMessage, Direction dir, int limit = 100) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetCachedMessages(fromMessage, dir, limit); + } + + /// This function is only supported in Text-In-Voice channels. + public override IReadOnlyCollection GetCachedMessages(int limit = 100) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetCachedMessages(limit); + } + + /// This function is only supported in Text-In-Voice channels. + public override IReadOnlyCollection GetCachedMessages(ulong fromMessageId, Direction dir, int limit = 100) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetCachedMessages(fromMessageId, dir, limit); + } + + /// This function is only supported in Text-In-Voice channels. + public override IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessagesAsync(fromMessage, dir, limit, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override IAsyncEnumerable> GetMessagesAsync(int limit = 100, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessagesAsync(limit, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetMessagesAsync(fromMessageId, dir, limit, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task> GetPinnedMessagesAsync(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetPinnedMessagesAsync(options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task GetWebhookAsync(ulong id, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetWebhookAsync(id, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task> GetWebhooksAsync(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.GetWebhooksAsync(options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.CreateWebhookAsync(name, avatar, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.ModifyMessageAsync(messageId, func, options); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task 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, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags); + } + + /// This function is only supported in Text-In-Voice channels. + public override Task TriggerTypingAsync(RequestOptions options = null) + { + if (!IsTextInVoice) + throw new NotSupportedException("This function is only supported in Text-In-Voice channels"); + return base.TriggerTypingAsync(options); + } + + #endregion private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; internal new SocketVoiceChannel Clone() => MemberwiseClone() as SocketVoiceChannel; - #endregion #region IGuildChannel ///