Browse Source

Add IAudioChannel.ModifyAsync API

pull/1888/head
Pawel Panek 4 years ago
parent
commit
53397978e0
10 changed files with 97 additions and 3 deletions
  1. +18
    -0
      src/Discord.Net.Core/Entities/Channels/AudioChannelProperties.cs
  2. +12
    -0
      src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs
  3. +1
    -0
      src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
  4. +1
    -0
      src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
  5. +5
    -1
      src/Discord.Net.WebSocket/DiscordSocketApiClient.cs
  6. +1
    -0
      src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs
  7. +6
    -0
      src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs
  8. +43
    -2
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
  9. +5
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs
  10. +5
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs

+ 18
- 0
src/Discord.Net.Core/Entities/Channels/AudioChannelProperties.cs View File

@@ -0,0 +1,18 @@
namespace Discord
{
/// <summary>
/// Provides properties that are used to modify an <see cref="IAudioChannel" /> with the specified changes.
/// </summary>
public class AudioChannelProperties
{
/// <summary>
/// Sets whether the user should be muted.
/// </summary>
public Optional<bool> SelfMute { get; set; }

/// <summary>
/// Sets whether the user should be deafened.
/// </summary>
public Optional<bool> SelfDeaf { get; set; }
}
}

+ 12
- 0
src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs View File

@@ -1,4 +1,5 @@
using Discord.Audio;
using System;
using System.Threading.Tasks;

namespace Discord
@@ -27,5 +28,16 @@ namespace Discord
/// A task representing the asynchronous operation for disconnecting from the audio channel.
/// </returns>
Task DisconnectAsync();

/// <summary>
/// Modifies this audio channel.
/// </summary>
/// <param name="func">The properties to modify the channel with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
/// <seealso cref="AudioChannelProperties"/>
Task ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options = null);
}
}

+ 1
- 0
src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs View File

@@ -196,6 +196,7 @@ namespace Discord.Rest
/// <exception cref="NotSupportedException">Connecting to a group channel is not supported.</exception>
Task<IAudioClient> IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); }
Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); }
Task IAudioChannel.ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options) { throw new NotSupportedException(); }

//IChannel
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)


+ 1
- 0
src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs View File

@@ -76,6 +76,7 @@ namespace Discord.Rest
/// <exception cref="NotSupportedException">Connecting to a REST-based channel is not supported.</exception>
Task<IAudioClient> IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); }
Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); }
Task IAudioChannel.ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options) { throw new NotSupportedException(); }

//IGuildChannel
/// <inheritdoc />


+ 5
- 1
src/Discord.Net.WebSocket/DiscordSocketApiClient.cs View File

@@ -284,7 +284,6 @@ namespace Discord.API
}
public async Task SendVoiceStateUpdateAsync(ulong guildId, ulong? channelId, bool selfDeaf, bool selfMute, RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);
var payload = new VoiceStateUpdateParams
{
GuildId = guildId,
@@ -294,6 +293,11 @@ namespace Discord.API
};
await SendGatewayAsync(GatewayOpCode.VoiceStateUpdate, payload, options: options).ConfigureAwait(false);
}
public async Task SendVoiceStateUpdateAsync(VoiceStateUpdateParams payload, RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);
await SendGatewayAsync(GatewayOpCode.VoiceStateUpdate, payload, options: options).ConfigureAwait(false);
}
public async Task SendGuildSyncAsync(IEnumerable<ulong> guildIds, RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);


+ 1
- 0
src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs View File

@@ -311,6 +311,7 @@ namespace Discord.WebSocket
/// <exception cref="NotSupportedException">Connecting to a group channel is not supported.</exception>
Task<IAudioClient> IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); }
Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); }
Task IAudioChannel.ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options) { throw new NotSupportedException(); }

//IChannel
/// <inheritdoc />


+ 6
- 0
src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs View File

@@ -76,6 +76,12 @@ namespace Discord.WebSocket
public async Task DisconnectAsync()
=> await Guild.DisconnectAudioAsync();

/// <inheritdoc />
public async Task ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options = null)
{
await Guild.ModifyAudioAsync(Id, func, options).ConfigureAwait(false);
}

/// <inheritdoc />
public override SocketGuildUser GetUser(ulong id)
{


+ 43
- 2
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -1,3 +1,4 @@
using Discord.API.Gateway;
using Discord.Audio;
using Discord.Rest;
using System;
@@ -39,6 +40,7 @@ namespace Discord.WebSocket
private ImmutableArray<GuildEmote> _emotes;
private ImmutableArray<string> _features;
private AudioClient _audioClient;
private VoiceStateUpdateParams _voiceStateUpdateParams;
#pragma warning restore IDISP002, IDISP006

/// <inheritdoc />
@@ -1054,11 +1056,19 @@ namespace Discord.WebSocket
promise = new TaskCompletionSource<AudioClient>();
_audioConnectPromise = promise;

_voiceStateUpdateParams = new VoiceStateUpdateParams
{
GuildId = Id,
ChannelId = channelId,
SelfDeaf = selfDeaf,
SelfMute = selfMute
};

if (external)
{
#pragma warning disable IDISP001
var _ = promise.TrySetResultAsync(null);
await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false);
await Discord.ApiClient.SendVoiceStateUpdateAsync(_voiceStateUpdateParams).ConfigureAwait(false);
return null;
#pragma warning restore IDISP001
}
@@ -1093,7 +1103,7 @@ namespace Discord.WebSocket
#pragma warning restore IDISP003
}

await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false);
await Discord.ApiClient.SendVoiceStateUpdateAsync(_voiceStateUpdateParams).ConfigureAwait(false);
}
catch
{
@@ -1140,7 +1150,38 @@ namespace Discord.WebSocket
await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, null, false, false).ConfigureAwait(false);
_audioClient?.Dispose();
_audioClient = null;
_voiceStateUpdateParams = null;
}

internal async Task ModifyAudioAsync(ulong channelId, Action<AudioChannelProperties> func, RequestOptions options)
{
await _audioLock.WaitAsync().ConfigureAwait(false);
try
{
await ModifyAudioInternalAsync(channelId, func, options).ConfigureAwait(false);
}
finally
{
_audioLock.Release();
}
}

private async Task ModifyAudioInternalAsync(ulong channelId, Action<AudioChannelProperties> func, RequestOptions options)
{
if (_voiceStateUpdateParams == null || _voiceStateUpdateParams.ChannelId != channelId)
throw new InvalidOperationException("Cannot modify properties of not connected audio channel");

var props = new AudioChannelProperties();
func(props);

if (props.SelfDeaf.IsSpecified)
_voiceStateUpdateParams.SelfDeaf = props.SelfDeaf.Value;
if (props.SelfMute.IsSpecified)
_voiceStateUpdateParams.SelfMute = props.SelfMute.Value;

await Discord.ApiClient.SendVoiceStateUpdateAsync(_voiceStateUpdateParams, options).ConfigureAwait(false);
}

internal async Task FinishConnectAudio(string url, string token)
{
//TODO: Mem Leak: Disconnected/Connected handlers arent cleaned up


+ 5
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs View File

@@ -41,6 +41,11 @@ namespace Discord
throw new NotImplementedException();
}

public Task ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options)
{
throw new NotImplementedException();
}

public IDisposable EnterTypingState(RequestOptions options = null)
{
throw new NotImplementedException();


+ 5
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs View File

@@ -58,6 +58,11 @@ namespace Discord
throw new NotImplementedException();
}

public Task ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options)
{
throw new NotImplementedException();
}

public Task<ICategoryChannel> GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();


Loading…
Cancel
Save