diff --git a/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs b/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs index 6f517d100..e3b51b614 100644 --- a/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs @@ -70,6 +70,51 @@ namespace Discord /// Task StopStageAsync(RequestOptions options = null); + /// + /// Indicates that the bot would like to speak within a stage channel. + /// + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous request to speak operation. + /// Task RequestToSpeak(RequestOptions options = null); + + /// + /// Makes the current user become a speaker within a stage. + /// + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous speaker modify operation. + /// + Task BecomeSpeakerAsync(RequestOptions options = null); + + /// + /// Makes the current user a listener. + /// + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous stop operation. + /// + Task StopSpeakingAsync(RequestOptions options = null); + + /// + /// Makes a user a speaker within a stage. + /// + /// The user to make the speaker. + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous move operation. + /// + Task MoveToSpeaker(IGuildUser user, RequestOptions options = null); + + /// + /// Removes a user from speaking. + /// + /// The user to remove from speaking. + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous remove operation. + /// + Task RemoveFromSpeaker(IGuildUser user, RequestOptions options = null); } } diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index e8565b678..3e9ed4393 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -646,6 +646,18 @@ namespace Discord.API await SendJsonAsync("PATCH", () => $"guilds/{guildId}/voice-states/@me", args, bucket, options: options).ConfigureAwait(false); } + public async Task ModifyUserVoiceState(ulong guildId, ulong userId, ModifyVoiceStateParams args, RequestOptions options = null) + { + Preconditions.NotEqual(guildId, 0, nameof(guildId)); + Preconditions.NotEqual(userId, 0, nameof(userId)); + + options = RequestOptions.CreateOrClone(options); + + var bucket = new BucketIds(); + + await SendJsonAsync("PATCH", () => $"guilds/{guildId}/voice-states/{userId}", args, bucket, options: options).ConfigureAwait(false); + } + // roles public async Task AddRoleAsync(ulong guildId, ulong userId, ulong roleId, RequestOptions options = null) { diff --git a/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs index 883a080f1..c5bad43da 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs @@ -105,5 +105,51 @@ namespace Discord.Rest }; return Discord.ApiClient.ModifyMyVoiceState(this.Guild.Id, args, options); } + + /// + public Task BecomeSpeakerAsync(RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = false + }; + return Discord.ApiClient.ModifyMyVoiceState(this.Guild.Id, args, options); + } + + /// + public Task StopSpeakingAsync(RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = true + }; + return Discord.ApiClient.ModifyMyVoiceState(this.Guild.Id, args, options); + } + + /// + public Task MoveToSpeaker(IGuildUser user, RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = false + }; + + return Discord.ApiClient.ModifyUserVoiceState(this.Guild.Id, user.Id, args); + } + + /// + public Task RemoveFromSpeaker(IGuildUser user, RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = true + }; + + return Discord.ApiClient.ModifyUserVoiceState(this.Guild.Id, user.Id, args); + } } } diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs index 15e49901e..fb87a0591 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs @@ -27,6 +27,12 @@ namespace Discord.WebSocket /// public bool Live { get; private set; } = false; + /// + /// Returns if the current user is a speaker within the stage, otherwise . + /// + public bool IsSpeaker + => !Guild.CurrentUser.IsSuppressed; + /// /// Gets a collection of users who are speakers within the stage. /// @@ -112,5 +118,51 @@ namespace Discord.WebSocket }; return Discord.ApiClient.ModifyMyVoiceState(this.Guild.Id, args, options); } + + /// + public Task BecomeSpeakerAsync(RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = false + }; + return Discord.ApiClient.ModifyMyVoiceState(this.Guild.Id, args, options); + } + + /// + public Task StopSpeakingAsync(RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = true + }; + return Discord.ApiClient.ModifyMyVoiceState(this.Guild.Id, args, options); + } + + /// + public Task MoveToSpeaker(IGuildUser user, RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = false + }; + + return Discord.ApiClient.ModifyUserVoiceState(this.Guild.Id, user.Id, args); + } + + /// + public Task RemoveFromSpeaker(IGuildUser user, RequestOptions options = null) + { + var args = new API.Rest.ModifyVoiceStateParams() + { + ChannelId = this.Id, + Suppressed = true + }; + + return Discord.ApiClient.ModifyUserVoiceState(this.Guild.Id, user.Id, args); + } } }