From 23656e844ee45f4f3a37b3da887f10fb3e6b9a37 Mon Sep 17 00:00:00 2001
From: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date: Mon, 9 May 2022 22:57:28 -0300
Subject: [PATCH] feature: Text-In-Voice (#2269)
* Initial implementation
* Remove blocking webhooks
* add safeguard for tiv
* fix tests
---
.../Entities/Channels/IVoiceChannel.cs | 2 +-
.../Entities/Channels/RestStageChannel.cs | 8 +-
.../Entities/Channels/RestTextChannel.cs | 98 +++----
.../Entities/Channels/RestVoiceChannel.cs | 218 ++++++++++++---
.../Entities/Channels/SocketGuildChannel.cs | 2 +
.../Entities/Channels/SocketStageChannel.cs | 9 +-
.../Entities/Channels/SocketTextChannel.cs | 42 +--
.../Entities/Channels/SocketVoiceChannel.cs | 255 +++++++++++++++---
.../MockedEntities/MockedVoiceChannel.cs | 148 +++-------
9 files changed, 521 insertions(+), 261 deletions(-)
diff --git a/src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs b/src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs
index 1d36a41b9..d921a2474 100644
--- a/src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs
+++ b/src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs
@@ -6,7 +6,7 @@ namespace Discord
///
/// Represents a generic voice channel in a guild.
///
- public interface IVoiceChannel : INestedChannel, IAudioChannel, IMentionable
+ public interface IVoiceChannel : IMessageChannel, INestedChannel, IAudioChannel, IMentionable
{
///
/// Gets the bit-rate that the clients in this voice channel are requested to use.
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 76c75ab6e..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);
///
@@ -231,38 +231,6 @@ namespace Discord.Rest
public virtual Task> GetWebhooksAsync(RequestOptions options = null)
=> ChannelHelper.GetWebhooksAsync(this, Discord, options);
- ///
- /// Gets the parent (category) channel of this channel.
- ///
- /// The options to be used when sending the request.
- ///
- /// A task that represents the asynchronous get operation. The task result contains the category channel
- /// representing the parent of this channel; null if none is set.
- ///
- public virtual Task GetCategoryAsync(RequestOptions options = null)
- => ChannelHelper.GetCategoryAsync(this, Discord, options);
- ///
- public Task SyncPermissionsAsync(RequestOptions options = null)
- => ChannelHelper.SyncPermissionsAsync(this, Discord, options);
- #endregion
-
- #region Invites
- ///
- public virtual 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 virtual async Task CreateInviteToApplicationAsync(ulong applicationId, 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, applicationId, options);
- ///
- 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 virtual Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
- => throw new NotImplementedException();
- ///
- public virtual async Task> GetInvitesAsync(RequestOptions options = null)
- => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false);
-
- private string DebuggerDisplay => $"{Name} ({Id}, Text)";
-
///
/// Creates a thread within this .
///
@@ -299,6 +267,38 @@ namespace Discord.Rest
var model = await ThreadHelper.CreateThreadAsync(Discord, this, name, type, autoArchiveDuration, message, invitable, slowmode, options);
return RestThreadChannel.Create(Discord, Guild, model);
}
+
+ ///
+ /// Gets the parent (category) channel of this channel.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains the category channel
+ /// representing the parent of this channel; null if none is set.
+ ///
+ public virtual Task GetCategoryAsync(RequestOptions options = null)
+ => ChannelHelper.GetCategoryAsync(this, Discord, options);
+ ///
+ public Task SyncPermissionsAsync(RequestOptions options = null)
+ => ChannelHelper.SyncPermissionsAsync(this, Discord, options);
+ #endregion
+
+ #region Invites
+ ///
+ public virtual 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 virtual async Task CreateInviteToApplicationAsync(ulong applicationId, 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, applicationId, options);
+ ///
+ 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 virtual Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
+ => throw new NotImplementedException();
+ ///
+ public virtual async Task> GetInvitesAsync(RequestOptions options = null)
+ => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false);
+
+ private string DebuggerDisplay => $"{Name} ({Id}, Text)";
#endregion
#region ITextChannel
diff --git a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
index bcf03a5bc..31d313a48 100644
--- a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
@@ -2,6 +2,7 @@ using Discord.Audio;
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Model = Discord.API.Channel;
@@ -12,21 +13,21 @@ namespace Discord.Rest
/// Represents a REST-based voice channel in a guild.
///
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
- public class RestVoiceChannel : RestGuildChannel, IVoiceChannel, IRestAudioChannel
+ 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; }
///
public int? UserLimit { get; private set; }
- ///
- public ulong? CategoryId { get; private set; }
///
public string RTCRegion { get; private set; }
- ///
- public string Mention => MentionUtils.MentionChannel(Id);
-
internal RestVoiceChannel(BaseDiscordClient discord, IGuild guild, ulong id)
: base(discord, guild, id)
{
@@ -41,7 +42,6 @@ namespace Discord.Rest
internal override void Update(Model model)
{
base.Update(model);
- CategoryId = model.CategoryId;
if(model.Bitrate.IsSpecified)
Bitrate = model.Bitrate.Value;
@@ -59,41 +59,185 @@ namespace Discord.Rest
Update(model);
}
- ///
- /// Gets the parent (category) channel of this channel.
- ///
- /// The options to be used when sending the request.
- ///
- /// A task that represents the asynchronous get operation. The task result contains the category channel
- /// representing the parent of this channel; null if none is set.
- ///
- public Task GetCategoryAsync(RequestOptions options = null)
- => ChannelHelper.GetCategoryAsync(this, Discord, options);
- ///
- public Task SyncPermissionsAsync(RequestOptions options = null)
- => ChannelHelper.SyncPermissionsAsync(this, Discord, options);
- #endregion
+ ///
+ /// Cannot modify text channel properties of a voice channel.
+ public override Task ModifyAsync(Action func, RequestOptions options = null)
+ => throw new InvalidOperationException("Cannot modify text channel properties of a voice channel");
- #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);
+ ///
+ /// Cannot create a thread within a voice channel.
+ 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("Cannot create a thread within a voice channel");
+
+ #endregion
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.WebSocket/Entities/Channels/SocketGuildChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
index 79f02fe1c..6d9e759b4 100644
--- a/src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
+++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
@@ -222,6 +222,8 @@ namespace Discord.WebSocket
#region IChannel
///
+ string IChannel.Name => Name;
+ ///
IAsyncEnumerable> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> ImmutableArray.Create>(Users).ToAsyncEnumerable(); //Overridden in Text/Voice
///
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 00003d4ed..5fc99c3f1 100644
--- a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs
+++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Model = Discord.API.Channel;
@@ -14,33 +15,21 @@ namespace Discord.WebSocket
/// Represents a WebSocket-based voice channel in a guild.
///
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
- public class SocketVoiceChannel : SocketGuildChannel, IVoiceChannel, ISocketAudioChannel
+ 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.
@@ -48,7 +37,7 @@ namespace Discord.WebSocket
///
/// A read-only collection of users that are currently connected to this voice channel.
///
- public override IReadOnlyCollection Users
+ public IReadOnlyCollection ConnectedUsers
=> Guild.Users.Where(x => x.VoiceChannel?.Id == Id).ToImmutableArray();
internal SocketVoiceChannel(DiscordSocketClient discord, ulong id, SocketGuild guild)
@@ -65,7 +54,6 @@ namespace Discord.WebSocket
internal override void Update(ClientState state, Model model)
{
base.Update(state, model);
- CategoryId = model.CategoryId;
Bitrate = model.Bitrate.Value;
UserLimit = model.UserLimit.Value != 0 ? model.UserLimit.Value : (int?)null;
RTCRegion = model.RTCRegion.GetValueOrDefault(null);
@@ -99,28 +87,215 @@ namespace Discord.WebSocket
return user;
return null;
}
-#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);
+ /// 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 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 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
///
diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
index 533b1b1b5..fdbdeda5e 100644
--- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
+++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Text;
using System.Threading.Tasks;
using Discord.Audio;
@@ -12,8 +13,6 @@ namespace Discord
public int? UserLimit => throw new NotImplementedException();
- public string Mention => throw new NotImplementedException();
-
public ulong? CategoryId => throw new NotImplementedException();
public int Position => throw new NotImplementedException();
@@ -24,116 +23,53 @@ namespace Discord
public IReadOnlyCollection PermissionOverwrites => throw new NotImplementedException();
+ public string RTCRegion => throw new NotImplementedException();
+
public string Name => throw new NotImplementedException();
public DateTimeOffset CreatedAt => throw new NotImplementedException();
- public ulong Id => throw new NotImplementedException();
-
- public string RTCRegion => throw new NotImplementedException();
- public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
+ public ulong Id => throw new NotImplementedException();
- public Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false)
- {
- throw new NotImplementedException();
- }
+ public string Mention => throw new NotImplementedException();
- public Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
- public Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
- => throw new NotImplementedException();
+ public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null) => throw new NotImplementedException();
+ public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null) => throw new NotImplementedException();
+ public Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false) => throw new NotImplementedException();
+ public Task CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException();
+ public Task CreateInviteToApplicationAsync(ulong applicationId, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException();
public Task CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException();
- public Task CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
- => throw new NotImplementedException();
-
- public Task DeleteAsync(RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task DisconnectAsync()
- {
- throw new NotImplementedException();
- }
-
- public Task ModifyAsync(Action func, RequestOptions options)
- {
- throw new NotImplementedException();
- }
-
- public Task GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task> GetInvitesAsync(RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public OverwritePermissions? GetPermissionOverwrite(IRole role)
- {
- throw new NotImplementedException();
- }
-
- public OverwritePermissions? GetPermissionOverwrite(IUser user)
- {
- throw new NotImplementedException();
- }
-
- public Task GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public IAsyncEnumerable> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task ModifyAsync(Action func, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task ModifyAsync(Action func, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- public Task SyncPermissionsAsync(RequestOptions options = null)
- {
- throw new NotImplementedException();
- }
-
- Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
- {
- throw new NotImplementedException();
- }
-
- IAsyncEnumerable> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
- {
- throw new NotImplementedException();
- }
+ public Task CreateInviteToStreamAsync(IUser user, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException();
+ public Task DeleteAsync(RequestOptions options = null) => throw new NotImplementedException();
+ public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) => throw new NotImplementedException();
+ public Task DeleteMessageAsync(IMessage message, RequestOptions options = null) => throw new NotImplementedException();
+ public Task DisconnectAsync() => throw new NotImplementedException();
+ public IDisposable EnterTypingState(RequestOptions options = null) => throw new NotImplementedException();
+ public Task GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
+ public Task> GetInvitesAsync(RequestOptions options = null) => throw new NotImplementedException();
+ public Task GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
+ public IAsyncEnumerable> GetMessagesAsync(int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
+ public IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
+ public IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
+ public OverwritePermissions? GetPermissionOverwrite(IRole role) => throw new NotImplementedException();
+ public OverwritePermissions? GetPermissionOverwrite(IUser user) => throw new NotImplementedException();
+ public Task> GetPinnedMessagesAsync(RequestOptions options = null) => throw new NotImplementedException();
+ public Task GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
+ public IAsyncEnumerable> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
+ public Task ModifyAsync(Action func, RequestOptions options = null) => throw new NotImplementedException();
+ public Task ModifyAsync(Action func, RequestOptions options = null) => throw new NotImplementedException();
+ public Task ModifyAsync(Action func, RequestOptions options = null) => throw new NotImplementedException();
+ public Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) => throw new NotImplementedException();
+ public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null) => throw new NotImplementedException();
+ public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null) => throw new NotImplementedException();
+ public Task SendFileAsync(string filePath, string text = null, 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) => throw new NotImplementedException();
+ public Task 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, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
+ public Task SendFileAsync(FileAttachment attachment, 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) => throw new NotImplementedException();
+ public Task SendFilesAsync(IEnumerable attachments, 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) => throw new NotImplementedException();
+ public 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) => throw new NotImplementedException();
+ public Task SyncPermissionsAsync(RequestOptions options = null) => throw new NotImplementedException();
+ public Task TriggerTypingAsync(RequestOptions options = null) => throw new NotImplementedException();
+ Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => throw new NotImplementedException();
+ IAsyncEnumerable> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) => throw new NotImplementedException();
}
}