From 5a62ba1af49d48c427242b5ec4fd57c700ca294c Mon Sep 17 00:00:00 2001 From: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:54:18 +0300 Subject: [PATCH] [Feature] Allow switching voice channels without disconnecting (external clients only) (#2866) * eh well it should work * fix issues * make sure an external client is used --- src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs | 3 ++- src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs | 2 +- src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs | 2 +- .../Entities/Channels/SocketGroupChannel.cs | 2 +- .../Entities/Channels/SocketVoiceChannel.cs | 4 ++-- src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs | 5 +++-- .../MockedEntities/MockedGroupChannel.cs | 2 +- .../MockedEntities/MockedVoiceChannel.cs | 2 +- 8 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs b/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs index a52d41b3..dba706bc 100644 --- a/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs @@ -23,11 +23,12 @@ namespace Discord /// Determines whether the client should deaf itself upon connection. /// Determines whether the client should mute itself upon connection. /// Determines whether the audio client is an external one or not. + /// Determines whether the client should send a disconnect call before sending the new voice state. /// /// A task representing the asynchronous connection operation. The task result contains the /// responsible for the connection. /// - Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false); + Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false, bool disconnect = true); /// /// Disconnects from this audio channel. diff --git a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs index 2ae3a017..c65cdfad 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs @@ -261,7 +261,7 @@ namespace Discord.Rest #region IAudioChannel /// /// Connecting to a group channel is not supported. - Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); } + Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external, bool disconnect) { throw new NotSupportedException(); } Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); } Task IAudioChannel.ModifyAsync(Action func, RequestOptions options) { throw new NotSupportedException(); } #endregion diff --git a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs index 3e979eaf..98ce3d5c 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs @@ -89,7 +89,7 @@ namespace Discord.Rest #region IAudioChannel /// /// Connecting to a REST-based channel is not supported. - Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); } + Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external, bool disconnect) { throw new NotSupportedException(); } Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); } Task IAudioChannel.ModifyAsync(Action func, RequestOptions options) { throw new NotSupportedException(); } #endregion diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs index 517b7b03..bc160e1b 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs @@ -387,7 +387,7 @@ namespace Discord.WebSocket #region IAudioChannel /// /// Connecting to a group channel is not supported. - Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); } + Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external, bool disconnect) { throw new NotSupportedException(); } Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); } Task IAudioChannel.ModifyAsync(Action func, RequestOptions options) { throw new NotSupportedException(); } #endregion diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs index 4cfe1801..4711b3db 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs @@ -89,8 +89,8 @@ namespace Discord.WebSocket => ChannelHelper.ModifyAsync(this, Discord, func, options); /// - public Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false) - => Guild.ConnectAudioAsync(Id, selfDeaf, selfMute, external); + public Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false, bool disconnect = true) + => Guild.ConnectAudioAsync(Id, selfDeaf, selfMute, external, disconnect); /// public Task DisconnectAsync() diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index 34e5e6c2..ea131cd1 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -1723,14 +1723,15 @@ namespace Discord.WebSocket { return _audioClient?.GetInputStream(userId); } - internal async Task ConnectAudioAsync(ulong channelId, bool selfDeaf, bool selfMute, bool external) + internal async Task ConnectAudioAsync(ulong channelId, bool selfDeaf, bool selfMute, bool external, bool disconnect = true) { TaskCompletionSource promise; await _audioLock.WaitAsync().ConfigureAwait(false); try { - await DisconnectAudioInternalAsync().ConfigureAwait(false); + if (disconnect || !external) + await DisconnectAudioInternalAsync().ConfigureAwait(false); promise = new TaskCompletionSource(); _audioConnectPromise = promise; diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs index 74dc5ee9..8d911727 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs @@ -18,7 +18,7 @@ namespace Discord public string RTCRegion => throw new NotImplementedException(); - public Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false) + public Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false, bool disconnect = true) { throw new NotImplementedException(); } diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs index 4e725bf1..c2e34af6 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs @@ -53,7 +53,7 @@ namespace Discord 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 ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false, bool disconnect = true) => 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();