Browse Source

Prep work for isolating audio package.

tags/docs-0.9
RogueException 9 years ago
parent
commit
1721f6f4d6
28 changed files with 99 additions and 381 deletions
  1. +2
    -3
      src/Discord.Net.Commands/CommandServiceConfig.cs
  2. +0
    -2
      src/Discord.Net.Commands/project.json
  3. +2
    -0
      src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj
  4. +1
    -4
      src/Discord.Net.Modules/ModuleManager.cs
  5. +0
    -2
      src/Discord.Net.Modules/project.json
  6. +0
    -33
      src/Discord.Net.Net45/Discord.Net.csproj
  7. +0
    -18
      src/Discord.Net/Audio/IDiscordVoiceClient.cs
  8. +1
    -7
      src/Discord.Net/DiscordClient.Users.cs
  9. +3
    -56
      src/Discord.Net/DiscordClient.cs
  10. +0
    -6
      src/Discord.Net/DiscordClientConfig.cs
  11. +4
    -34
      src/Discord.Net/DiscordWSClient.Events.cs
  12. +0
    -54
      src/Discord.Net/DiscordWSClient.Voice.cs
  13. +4
    -55
      src/Discord.Net/DiscordWSClient.cs
  14. +0
    -30
      src/Discord.Net/DiscordWSClientConfig.cs
  15. +1
    -7
      src/Discord.Net/Helpers/BitHelper.cs
  16. +33
    -0
      src/Discord.Net/Helpers/CollectionExtensions.cs
  17. +10
    -7
      src/Discord.Net/Helpers/Mention.cs
  18. +0
    -0
      src/Discord.Net/Helpers/Shared/IdConvert.cs
  19. +2
    -26
      src/Discord.Net/Helpers/Shared/TaskExtensions.cs
  20. +0
    -0
      src/Discord.Net/Helpers/Shared/TaskHelper.cs
  21. +1
    -0
      src/Discord.Net/IService.cs
  22. +3
    -3
      src/Discord.Net/Net/WebSockets/DataWebSocket.cs
  23. +2
    -2
      src/Discord.Net/Net/WebSockets/DataWebSockets.Events.cs
  24. +3
    -3
      src/Discord.Net/Net/WebSockets/IWebSocketEngine.cs
  25. +1
    -1
      src/Discord.Net/Net/WebSockets/WebSocket.Events.cs
  26. +2
    -2
      src/Discord.Net/Net/WebSockets/WebSocket.cs
  27. +3
    -3
      src/Discord.Net/Net/WebSockets/WebSocketSharpEngine.cs
  28. +21
    -23
      src/Discord.Net/project.json

+ 2
- 3
src/Discord.Net.Commands/CommandServiceConfig.cs View File

@@ -1,5 +1,4 @@
using Discord.Commands.Permissions;
using System;
using System;

namespace Discord.Commands
{
@@ -40,7 +39,7 @@ namespace Discord.Commands
protected void SetValue<T>(ref T storage, T value)
{
if (_isLocked)
throw new InvalidOperationException("Unable to modify a discord client's configuration after it has been created.");
throw new InvalidOperationException("Unable to modify a service's configuration after it has been created.");
storage = value;
}
}


+ 0
- 2
src/Discord.Net.Commands/project.json View File

@@ -18,7 +18,5 @@
"frameworks": {
"net45": { },
"dotnet5.4": { }
},
"configurations": {
}
}

+ 2
- 0
src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj View File

@@ -22,6 +22,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -32,6 +33,7 @@
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>6</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />


+ 1
- 4
src/Discord.Net.Modules/ModuleManager.cs View File

@@ -35,7 +35,6 @@ namespace Discord.Modules
public event EventHandler<UserEventArgs> UserPresenceUpdated;
public event EventHandler<UserEventArgs> UserVoiceStateUpdated;
public event EventHandler<UserChannelEventArgs> UserIsTypingUpdated;
public event EventHandler<UserIsSpeakingEventArgs> UserIsSpeakingUpdated;

public event EventHandler<MessageEventArgs> MessageReceived;
public event EventHandler<MessageEventArgs> MessageSent;
@@ -77,9 +76,7 @@ namespace Discord.Modules
if (_allowAll || _useServerWhitelist) //Server-only events
{
client.ChannelCreated += (s, e) => { if (ChannelCreated != null && HasServer(e.Server)) ChannelCreated(s, e); };

client.UserVoiceStateUpdated += (s, e) => { if (UserVoiceStateUpdated != null && HasServer(e.Server)) UserVoiceStateUpdated(s, e); };
client.UserIsSpeakingUpdated += (s, e) => { if (UserIsSpeakingUpdated != null && HasServer(e.Server)) UserIsSpeakingUpdated(s, e); };
}

client.ChannelDestroyed += (s, e) => { if (ChannelDestroyed != null && HasChannel(e.Channel)) ChannelDestroyed(s, e); };
@@ -103,7 +100,7 @@ namespace Discord.Modules
client.UserJoined += (s, e) => { if (UserJoined != null && HasIndirectServer(e.Server)) UserJoined(s, e); };
client.UserLeft += (s, e) => { if (UserLeft != null && HasIndirectServer(e.Server)) UserLeft(s, e); };
client.UserUpdated += (s, e) => { if (UserUpdated != null && HasIndirectServer(e.Server)) UserUpdated(s, e); };
client.UserIsTypingUpdated += (s, e) => { if (UserIsSpeakingUpdated != null && HasChannel(e.Channel)) UserIsTypingUpdated(s, e); };
client.UserIsTypingUpdated += (s, e) => { if (UserIsTypingUpdated != null && HasChannel(e.Channel)) UserIsTypingUpdated(s, e); };
//TODO: We aren't getting events from UserPresence if AllowPrivate is enabled, but the server we know that user through isn't on the whitelist
client.UserPresenceUpdated += (s, e) => { if (UserPresenceUpdated != null && HasIndirectServer(e.Server)) UserPresenceUpdated(s, e); };
client.UserBanned += (s, e) => { if (UserBanned != null && HasIndirectServer(e.Server)) UserBanned(s, e); };


+ 0
- 2
src/Discord.Net.Modules/project.json View File

@@ -19,7 +19,5 @@
"frameworks": {
"net45": { },
"dotnet5.4": { }
},
"configurations": {
}
}

+ 0
- 33
src/Discord.Net.Net45/Discord.Net.csproj View File

@@ -134,27 +134,6 @@
<Compile Include="..\Discord.Net\API\WebSockets.cs">
<Link>API\WebSockets.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\IDiscordVoiceBuffer.cs">
<Link>Audio\IDiscordVoiceBuffer.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\IDiscordVoiceClient.cs">
<Link>Audio\IDiscordVoiceClient.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\Opus.cs">
<Link>Audio\Opus.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\OpusDecoder.cs">
<Link>Audio\OpusDecoder.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\OpusEncoder.cs">
<Link>Audio\OpusEncoder.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\Sodium.cs">
<Link>Audio\Sodium.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\VoiceBuffer.cs">
<Link>Audio\VoiceBuffer.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordAPIClient.cs">
<Link>DiscordAPIClient.cs</Link>
</Compile>
@@ -185,9 +164,6 @@
<Compile Include="..\Discord.Net\DiscordClient.Users.cs">
<Link>DiscordClient.Users.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordClient.Voice.cs">
<Link>DiscordClient.Voice.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordClientConfig.cs">
<Link>DiscordClientConfig.cs</Link>
</Compile>
@@ -197,9 +173,6 @@
<Compile Include="..\Discord.Net\DiscordWSClient.Events.cs">
<Link>DiscordWSClient.Events.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordWSClient.Voice.cs">
<Link>DiscordWSClient.Voice.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordWSClientConfig.cs">
<Link>DiscordWSClientConfig.cs</Link>
</Compile>
@@ -290,12 +263,6 @@
<Compile Include="..\Discord.Net\Net\WebSockets\IWebSocketEngine.cs">
<Link>Net\WebSockets\IWebSocketEngine.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Net\WebSockets\VoiceWebSocket.cs">
<Link>Net\WebSockets\VoiceWebSocket.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Net\WebSockets\VoiceWebSocket.Events.cs">
<Link>Net\WebSockets\VoiceWebSocket.Events.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Net\WebSockets\WebSocket.cs">
<Link>Net\WebSockets\WebSocket.cs</Link>
</Compile>


+ 0
- 18
src/Discord.Net/Audio/IDiscordVoiceClient.cs View File

@@ -1,18 +0,0 @@
using System.Threading.Tasks;

namespace Discord.Audio
{
public interface IDiscordVoiceClient
{
long? ChannelId { get; }
long? ServerId { get; }
IDiscordVoiceBuffer OutputBuffer { get; }

Task JoinChannel(long channelId);

void SendVoicePCM(byte[] data, int count);
void ClearVoicePCM();

Task WaitVoice();
}
}

+ 1
- 7
src/Discord.Net/DiscordClient.Users.cs View File

@@ -105,12 +105,6 @@ namespace Discord
if (UserIsTypingUpdated != null)
RaiseEvent(nameof(UserIsTypingUpdated), () => UserIsTypingUpdated(this, new UserChannelEventArgs(user, channel)));
}
public event EventHandler<UserIsSpeakingEventArgs> UserIsSpeakingUpdated;
private void RaiseUserIsSpeaking(User user, Channel channel, bool isSpeaking)
{
if (UserIsSpeakingUpdated != null)
RaiseEvent(nameof(UserIsSpeakingUpdated), () => UserIsSpeakingUpdated(this, new UserIsSpeakingEventArgs(user, channel, isSpeaking)));
}
public event EventHandler ProfileUpdated;
private void RaiseProfileUpdated()
{
@@ -278,7 +272,7 @@ namespace Discord
{
if (server == null) throw new ArgumentNullException(nameof(server));

_dataSocket.SendGetUsers(server.Id);
_dataSocket.SendRequestUsers(server.Id);
}

public async Task EditProfile(string currentPassword = "",


+ 3
- 56
src/Discord.Net/DiscordClient.cs View File

@@ -19,10 +19,8 @@ namespace Discord
private readonly Random _rand;
private readonly JsonSerializer _messageImporter;
private readonly ConcurrentQueue<Message> _pendingMessages;
private readonly ConcurrentDictionary<long, DiscordWSClient> _voiceClients;
private readonly Dictionary<Type, object> _singletons;
private bool _sentInitialLog;
private uint _nextVoiceClientId;
private UserStatus _status;
private int? _gameId;

@@ -40,8 +38,6 @@ namespace Discord
_api = new DiscordAPIClient(_config);
if (Config.UseMessageQueue)
_pendingMessages = new ConcurrentQueue<Message>();
if (Config.EnableVoiceMultiserver)
_voiceClients = new ConcurrentDictionary<long, DiscordWSClient>();

object cacheLock = new object();
_channels = new Channels(this, cacheLock);
@@ -59,22 +55,6 @@ namespace Discord
_api.CancelToken = _cancelToken;
await SendStatus().ConfigureAwait(false);
};

VoiceDisconnected += (s, e) =>
{
var server = _servers[e.ServerId];
if (server != null)
{
foreach (var member in server.Members)
{
if (member.IsSpeaking)
{
member.IsSpeaking = false;
RaiseUserIsSpeaking(member, _channels[_voiceSocket.CurrentChannelId], false);
}
}
}
};
if (_config.LogLevel >= LogMessageSeverity.Info)
{
@@ -169,27 +149,6 @@ namespace Discord
_messageImporter = new JsonSerializer();
_messageImporter.ContractResolver = new Message.ImportResolver();
}
internal override VoiceWebSocket CreateVoiceSocket()
{
var socket = base.CreateVoiceSocket();
socket.IsSpeaking += (s, e) =>
{
if (_voiceSocket.State == WebSocketState.Connected)
{
var user = _users[e.UserId, socket.CurrentServerId];
bool value = e.IsSpeaking;
if (user.IsSpeaking != value)
{
user.IsSpeaking = value;
var channel = _channels[_voiceSocket.CurrentChannelId];
RaiseUserIsSpeaking(user, channel, value);
if (Config.TrackActivity)
user.UpdateActivity();
}
}
};
return socket;
}

/// <summary> Connects to the Discord server with the provided email and password. </summary>
/// <returns> Returns a token for future connections. </returns>
@@ -242,18 +201,6 @@ namespace Discord
{
await base.Cleanup().ConfigureAwait(false);

if (_config.VoiceMode != DiscordVoiceMode.Disabled)
{
if (Config.EnableVoiceMultiserver)
{
var tasks = _voiceClients
.Select(x => x.Value.Disconnect())
.ToArray();
_voiceClients.Clear();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}

if (Config.UseMessageQueue)
{
Message ignored;
@@ -309,7 +256,7 @@ namespace Discord
return base.GetTasks();
}
internal override async Task OnReceivedEvent(WebSocketEventEventArgs e)
protected override async Task OnReceivedEvent(WebSocketEventEventArgs e)
{
try
{
@@ -623,12 +570,12 @@ namespace Discord
var user = _users[data.UserId, data.GuildId];
if (user != null)
{
var voiceChannel = user.VoiceChannel;
/*var voiceChannel = user.VoiceChannel;
if (voiceChannel != null && data.ChannelId != voiceChannel.Id && user.IsSpeaking)
{
user.IsSpeaking = false;
RaiseUserIsSpeaking(user, _channels[voiceChannel.Id], false);
}
}*/
user.Update(data);
RaiseUserVoiceStateUpdated(user);
}


+ 0
- 6
src/Discord.Net/DiscordClientConfig.cs View File

@@ -10,9 +10,6 @@
private int _messageCacheLength = 100;

//Experimental Features
/// <summary> (Experimental) Enables the client to be simultaneously connected to multiple channels at once (Discord still limits you to one channel per server). </summary>
public bool EnableVoiceMultiserver { get { return _enableVoiceMultiserver; } set { SetValue(ref _enableVoiceMultiserver, value); } }
private bool _enableVoiceMultiserver = false;
/// <summary> (Experimental) Enables or disables the internal message queue. This will allow SendMessage to return immediately and handle messages internally. Messages will set the IsQueued and HasFailed properties to show their progress. </summary>
public bool UseMessageQueue { get { return _useMessageQueue; } set { SetValue(ref _useMessageQueue, value); } }
private bool _useMessageQueue = false;
@@ -23,9 +20,6 @@
public bool AckMessages { get { return _ackMessages; } set { SetValue(ref _ackMessages, value); } }
private bool _ackMessages = false;

//Internal
internal override bool EnableVoice => (base.EnableVoice && !EnableVoiceMultiserver) || base.VoiceOnly;

public new DiscordClientConfig Clone()
{
var config = MemberwiseClone() as DiscordClientConfig;


+ 4
- 34
src/Discord.Net/DiscordWSClient.Events.cs View File

@@ -26,22 +26,12 @@ namespace Discord
public readonly bool WasUnexpected;
public readonly Exception Error;

internal DisconnectedEventArgs(bool wasUnexpected, Exception error)
public DisconnectedEventArgs(bool wasUnexpected, Exception error)
{
WasUnexpected = wasUnexpected;
Error = error;
}
}
public class VoiceDisconnectedEventArgs : DisconnectedEventArgs
{
public readonly long ServerId;

internal VoiceDisconnectedEventArgs(long serverId, DisconnectedEventArgs e)
: base(e.WasUnexpected, e.Error)
{
ServerId = serverId;
}
}
public sealed class LogMessageEventArgs : EventArgs
{
public LogMessageSeverity Severity { get; }
@@ -49,7 +39,7 @@ namespace Discord
public string Message { get; }
public Exception Exception { get; }

internal LogMessageEventArgs(LogMessageSeverity severity, LogMessageSource source, string msg, Exception exception)
public LogMessageEventArgs(LogMessageSeverity severity, LogMessageSource source, string msg, Exception exception)
{
Severity = severity;
Source = source;
@@ -66,7 +56,7 @@ namespace Discord
public int Offset { get; }
public int Count { get; }

internal VoicePacketEventArgs(long userId, long channelId, byte[] buffer, int offset, int count)
public VoicePacketEventArgs(long userId, long channelId, byte[] buffer, int offset, int count)
{
UserId = userId;
Buffer = buffer;
@@ -90,30 +80,10 @@ namespace Discord
RaiseEvent(nameof(Disconnected), () => Disconnected(this, e));
}
public event EventHandler<LogMessageEventArgs> LogMessage;
internal void RaiseOnLog(LogMessageSeverity severity, LogMessageSource source, string message, Exception exception = null)
protected void RaiseOnLog(LogMessageSeverity severity, LogMessageSource source, string message, Exception exception = null)
{
if (LogMessage != null)
RaiseEvent(nameof(LogMessage), () => LogMessage(this, new LogMessageEventArgs(severity, source, message, exception)));
}

public event EventHandler VoiceConnected;
private void RaiseVoiceConnected()
{
if (VoiceConnected != null)
RaiseEvent(nameof(VoiceConnected), () => VoiceConnected(this, EventArgs.Empty));
}
public event EventHandler<VoiceDisconnectedEventArgs> VoiceDisconnected;
private void RaiseVoiceDisconnected(long serverId, DisconnectedEventArgs e)
{
if (VoiceDisconnected != null)
RaiseEvent(nameof(VoiceDisconnected), () => VoiceDisconnected(this, new VoiceDisconnectedEventArgs(serverId, e)));
}

public event EventHandler<VoicePacketEventArgs> OnVoicePacket;
internal void RaiseOnVoicePacket(VoicePacketEventArgs e)
{
if (OnVoicePacket != null)
OnVoicePacket(this, e);
}
}
}

+ 0
- 54
src/Discord.Net/DiscordWSClient.Voice.cs View File

@@ -1,54 +0,0 @@
using Discord.Audio;
using System;
using System.Threading.Tasks;

namespace Discord
{
public partial class DiscordWSClient : IDiscordVoiceClient
{
IDiscordVoiceBuffer IDiscordVoiceClient.OutputBuffer => _voiceSocket.OutputBuffer;
long? IDiscordVoiceClient.ServerId => _voiceSocket.CurrentServerId;
long? IDiscordVoiceClient.ChannelId => _voiceSocket.CurrentChannelId;

async Task IDiscordVoiceClient.JoinChannel(long channelId)
{
CheckReady(checkVoice: true);
if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId));
await _voiceSocket.Disconnect().ConfigureAwait(false);
await _voiceSocket.SetChannel(_voiceServerId.Value, channelId).ConfigureAwait(false);
_dataSocket.SendJoinVoice(_voiceServerId.Value, channelId);
await _voiceSocket.WaitForConnection(_config.ConnectionTimeout).ConfigureAwait(false);
}

/// <summary> Sends a PCM frame to the voice server. Will block until space frees up in the outgoing buffer. </summary>
/// <param name="data">PCM frame to send. This must be a single or collection of uncompressed 48Kz monochannel 20ms PCM frames. </param>
/// <param name="count">Number of bytes in this frame. </param>
void IDiscordVoiceClient.SendVoicePCM(byte[] data, int count)
{
if (data == null) throw new ArgumentException(nameof(data));
if (count < 0) throw new ArgumentOutOfRangeException(nameof(count));
CheckReady(checkVoice: true);

if (count != 0)
_voiceSocket.SendPCMFrames(data, count);
}
/// <summary> Clears the PCM buffer. </summary>
void IDiscordVoiceClient.ClearVoicePCM()
{
CheckReady(checkVoice: true);

_voiceSocket.ClearPCMFrames();
}

/// <summary> Returns a task that completes once the voice output buffer is empty. </summary>
async Task IDiscordVoiceClient.WaitVoice()
{
CheckReady(checkVoice: true);

_voiceSocket.WaitForQueue();
await TaskHelper.CompletedTask.ConfigureAwait(false);
}
}
}

+ 4
- 55
src/Discord.Net/DiscordWSClient.cs View File

@@ -24,10 +24,9 @@ namespace Discord
protected readonly ManualResetEvent _disconnectedEvent;
protected readonly ManualResetEventSlim _connectedEvent;
protected ExceptionDispatchInfo _disconnectReason;
internal readonly DataWebSocket _dataSocket;
internal readonly VoiceWebSocket _voiceSocket;
protected readonly DataWebSocket _dataSocket;
protected string _gateway, _token;
protected long? _userId, _voiceServerId;
protected long? _userId;
private Task _runTask;
private bool _wasDisconnectUnexpected;

@@ -86,13 +85,6 @@ namespace Discord
#endif

_dataSocket = CreateDataSocket();
if (_config.EnableVoice)
_voiceSocket = CreateVoiceSocket();
}
internal DiscordWSClient(DiscordWSClientConfig config = null, long? voiceServerId = null)
: this(config)
{
_voiceServerId = voiceServerId;
}

internal virtual DataWebSocket CreateDataSocket()
@@ -120,26 +112,6 @@ namespace Discord
socket.ReceivedEvent += async (s, e) => await OnReceivedEvent(e).ConfigureAwait(false);
return socket;
}
internal virtual VoiceWebSocket CreateVoiceSocket()
{
var socket = new VoiceWebSocket(this);
socket.Connected += (s, e) => RaiseVoiceConnected();
socket.Disconnected += async (s, e) =>
{
RaiseVoiceDisconnected(socket.CurrentServerId.Value, e);
if (e.WasUnexpected)
await socket.Reconnect().ConfigureAwait(false);
};

socket.LogMessage += (s, e) => RaiseOnLog(e.Severity, LogMessageSource.VoiceWebSocket, e.Message, e.Exception);
if (_config.LogLevel >= LogMessageSeverity.Info)
{
socket.Connected += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.VoiceWebSocket, "Connected");
socket.Disconnected += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.VoiceWebSocket, "Disconnected");
}

return socket;
}

//Connection
public async Task<string> Connect(string gateway, string token)
@@ -160,8 +132,6 @@ namespace Discord

_dataSocket.Host = gateway;
_dataSocket.ParentCancelToken = _cancelToken;
if (_config.EnableVoice)
_voiceSocket.ParentCancelToken = _cancelToken;
await _dataSocket.Login(token).ConfigureAwait(false);

_runTask = RunTasks();
@@ -268,13 +238,6 @@ namespace Discord

protected virtual async Task Cleanup()
{
if (_config.EnableVoice)
{
var voiceServerId = _voiceSocket.CurrentServerId;
if (voiceServerId != null)
_dataSocket.SendLeaveVoice(voiceServerId.Value);
await _voiceSocket.Disconnect().ConfigureAwait(false);
}
await _dataSocket.Disconnect().ConfigureAwait(false);

_userId = null;
@@ -310,9 +273,6 @@ namespace Discord
case (int)DiscordClientState.Connecting:
throw new InvalidOperationException("The client is connecting.");
}
if (checkVoice && _config.VoiceMode == DiscordVoiceMode.Disabled)
throw new InvalidOperationException("Voice is not enabled for this client.");
}
protected void RaiseEvent(string name, Action action)
{
@@ -325,7 +285,7 @@ namespace Discord
}
}

internal virtual async Task OnReceivedEvent(WebSocketEventEventArgs e)
protected virtual Task OnReceivedEvent(WebSocketEventEventArgs e)
{
try
{
@@ -334,24 +294,13 @@ namespace Discord
case "READY":
_userId = IdConvert.ToLong(e.Payload["user"].Value<string>("id"));
break;
case "VOICE_SERVER_UPDATE":
{
long guildId = IdConvert.ToLong(e.Payload.Value<string>("guild_id"));

if (_config.EnableVoice && guildId == _voiceSocket.CurrentServerId)
{
string token = e.Payload.Value<string>("token");
_voiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
await _voiceSocket.Login(_userId.Value, _dataSocket.SessionId, token, _cancelToken).ConfigureAwait(false);
}
}
break;
}
}
catch (Exception ex)
{
RaiseOnLog(LogMessageSeverity.Error, LogMessageSource.Client, $"Error handling {e.Type} event: {ex.GetBaseException().Message}");
}
return TaskHelper.CompletedTask;
}
}
}

+ 0
- 30
src/Discord.Net/DiscordWSClientConfig.cs View File

@@ -3,15 +3,6 @@ using System.Reflection;

namespace Discord
{
[Flags]
public enum DiscordVoiceMode
{
Disabled = 0x00,
Incoming = 0x01,
Outgoing = 0x02,
Both = Outgoing | Incoming
}

public class DiscordWSClientConfig : DiscordAPIClientConfig
{
/// <summary> Max time in milliseconds to wait for DiscordClient to connect and initialize. </summary>
@@ -23,36 +14,15 @@ namespace Discord
/// <summary> Gets or sets the time (in milliseconds) to wait after an reconnect fails before retrying. </summary>
public int FailedReconnectDelay { get { return _failedReconnectDelay; } set { SetValue(ref _failedReconnectDelay, value); } }
private int _failedReconnectDelay = 10000;

/// <summary> Gets or sets the time (in milliseconds) to wait when the websocket's message queue is empty before checking again. </summary>
public int WebSocketInterval { get { return _webSocketInterval; } set { SetValue(ref _webSocketInterval, value); } }
private int _webSocketInterval = 100;
/// <summary> Gets or sets the max buffer length (in milliseconds) for outgoing voice packets. This value is the target maximum but is not guaranteed, the buffer will often go slightly above this value. </summary>
public int VoiceBufferLength { get { return _voiceBufferLength; } set { SetValue(ref _voiceBufferLength, value); } }
private int _voiceBufferLength = 1000;
/// <summary> Gets or sets the bitrate used (in kbit/s, between 1 and 512 inclusively) for outgoing voice packets. A null value will use default Opus settings. </summary>
public int? VoiceBitrate { get { return _voiceBitrate; } set { SetValue(ref _voiceBitrate, value); } }
private int? _voiceBitrate = null;

//Experimental Features
/// <summary> (Experimental) Enables the voice websocket and UDP client and specifies how it will be used. Any option other than Disabled requires the opus .dll or .so be in the local or system folder. </summary>
public DiscordVoiceMode VoiceMode { get { return _voiceMode; } set { SetValue(ref _voiceMode, value); } }
private DiscordVoiceMode _voiceMode = DiscordVoiceMode.Disabled;
/// <summary> (Experimental) Enables the voice websocket and UDP client. This option requires the libsodium .dll or .so be in the local or system folder. </summary>
public bool EnableVoiceEncryption { get { return _enableVoiceEncryption; } set { SetValue(ref _enableVoiceEncryption, value); } }
private bool _enableVoiceEncryption = true;
/// <summary> (Experimental) Instructs Discord to not send send information about offline users, for servers with more than 50 users. </summary>
public bool UseLargeThreshold { get { return _useLargeThreshold; } set { SetValue(ref _useLargeThreshold, value); } }
private bool _useLargeThreshold = false;

//Internals
internal bool VoiceOnly { get { return _voiceOnly; } set { SetValue(ref _voiceOnly, value); } }
private bool _voiceOnly;
internal uint VoiceClientId { get { return _voiceClientId; } set { SetValue(ref _voiceClientId, value); } }
private uint _voiceClientId;

internal virtual bool EnableVoice => _voiceMode != DiscordVoiceMode.Disabled;

public new DiscordWSClientConfig Clone()
{
var config = MemberwiseClone() as DiscordWSClientConfig;


+ 1
- 7
src/Discord.Net/Helpers/BitHelper.cs View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
namespace Discord
{
internal static class BitHelper
{


+ 33
- 0
src/Discord.Net/Helpers/CollectionExtensions.cs View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Discord
{
public enum EditMode : byte
{
Set,
Add,
Remove
}

internal static class Extensions
{
public static IEnumerable<T> Modify<T>(this IEnumerable<T> original, IEnumerable<T> modified, EditMode mode)
{
if (original == null) return null;
switch (mode)
{
case EditMode.Set:
default:
return modified;
case EditMode.Add:
return original.Concat(modified);
case EditMode.Remove:
return original.Except(modified);
}
}
}
}

+ 10
- 7
src/Discord.Net/Helpers/Mention.cs View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Discord
@@ -10,17 +9,21 @@ namespace Discord
private static readonly Regex _userRegex = new Regex(@"<@([0-9]+?)>", RegexOptions.Compiled);
private static readonly Regex _channelRegex = new Regex(@"<#([0-9]+?)>", RegexOptions.Compiled);
private static readonly Regex _roleRegex = new Regex(@"@everyone", RegexOptions.Compiled);
/// <summary> Returns the string used to create a user mention. </summary>
[Obsolete("Use User.Mention instead")]
public static string User(User user)
=> $"<@{user.Id}>";
/// <summary> Returns the string used to create a user mention. </summary>
[Obsolete("Use GlobalUser.Mention instead")]
public static string User(GlobalUser user)
=> $"<@{user.Id}>";
/// <summary> Returns the string used to create a channel mention. </summary>
[Obsolete("Use Channel.Mention instead")]
public static string Channel(Channel channel)
=> $"<#{channel.Id}>";
/// <summary> Returns the string used to create a mention to everyone in a channel. </summary>
[Obsolete("Use Role.Mention instead")]
public static string Everyone()
=> $"@everyone";

@@ -72,7 +75,7 @@ namespace Discord
if (source == null) throw new ArgumentNullException(nameof(source));
if (text == null) throw new ArgumentNullException(nameof(text));

return Resolve(source?.Server, text);
return Resolve(source.Server, text);
}

/// <summary>Resolves all mentions in a provided string to those users, channels or roles' names.</summary>
@@ -80,12 +83,12 @@ namespace Discord
{
if (text == null) throw new ArgumentNullException(nameof(text));

var client = server.Client;
text = Mention.CleanUserMentions(client, server, text);
var client = server?.Client;
text = CleanUserMentions(client, server, text);
if (server != null)
{
text = Mention.CleanChannelMentions(client, server, text);
//text = Mention.CleanRoleMentions(_client, User, channel, text);
text = CleanChannelMentions(client, server, text);
//text = CleanRoleMentions(_client, User, channel, text);
}
return text;
}


src/Discord.Net/Helpers/IdConvert.cs → src/Discord.Net/Helpers/Shared/IdConvert.cs View File


src/Discord.Net/Helpers/Extensions.cs → src/Discord.Net/Helpers/Shared/TaskExtensions.cs View File

@@ -1,19 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Discord
{
public enum EditMode : byte
{
Set,
Add,
Remove
}

internal static class Extensions
public static class TaskExtensions
{
public static async Task Timeout(this Task task, int milliseconds)
{
@@ -73,20 +64,5 @@ namespace Discord
try { await Task.Delay(-1, token).ConfigureAwait(false); }
catch (OperationCanceledException) { } //Expected
}

public static IEnumerable<T> Modify<T>(this IEnumerable<T> original, IEnumerable<T> modified, EditMode mode)
{
if (original == null) return null;
switch (mode)
{
case EditMode.Set:
default:
return modified;
case EditMode.Add:
return original.Concat(modified);
case EditMode.Remove:
return original.Except(modified);
}
}
}
}
}

src/Discord.Net/Helpers/TaskHelper.cs → src/Discord.Net/Helpers/Shared/TaskHelper.cs View File


+ 1
- 0
src/Discord.Net/IService.cs View File

@@ -2,6 +2,7 @@
{
public interface IService
{

void Install(DiscordClient client);
}
}

+ 3
- 3
src/Discord.Net/Net/WebSockets/DataWebSocket.cs View File

@@ -6,9 +6,9 @@ using System.Threading.Tasks;

namespace Discord.Net.WebSockets
{
internal partial class DataWebSocket : WebSocket
public partial class DataWebSocket : WebSocket
{
public enum OpCodes : byte
internal enum OpCodes : byte
{
Dispatch = 0,
Heartbeat = 1,
@@ -155,7 +155,7 @@ namespace Discord.Net.WebSockets
leaveVoice.Payload.ServerId = serverId;
QueueMessage(leaveVoice);
}
public void SendGetUsers(long serverId, string query = "", int limit = 0)
public void SendRequestUsers(long serverId, string query = "", int limit = 0)
{
var getOfflineUsers = new GetUsersCommand();
getOfflineUsers.Payload.ServerId = serverId;


+ 2
- 2
src/Discord.Net/Net/WebSockets/DataWebSockets.Events.cs View File

@@ -3,7 +3,7 @@ using System;

namespace Discord.Net.WebSockets
{
internal sealed class WebSocketEventEventArgs : EventArgs
public sealed class WebSocketEventEventArgs : EventArgs
{
public readonly string Type;
public readonly JToken Payload;
@@ -14,7 +14,7 @@ namespace Discord.Net.WebSockets
}
}

internal partial class DataWebSocket
public partial class DataWebSocket
{
internal event EventHandler<WebSocketEventEventArgs> ReceivedEvent;
private void RaiseReceivedEvent(string type, JToken payload)


+ 3
- 3
src/Discord.Net/Net/WebSockets/IWebSocketEngine.cs View File

@@ -5,18 +5,18 @@ using System.Threading.Tasks;

namespace Discord.Net.WebSockets
{
internal class WebSocketBinaryMessageEventArgs : EventArgs
public class WebSocketBinaryMessageEventArgs : EventArgs
{
public readonly byte[] Data;
public WebSocketBinaryMessageEventArgs(byte[] data) { Data = data; }
}
internal class WebSocketTextMessageEventArgs : EventArgs
public class WebSocketTextMessageEventArgs : EventArgs
{
public readonly string Message;
public WebSocketTextMessageEventArgs(string msg) { Message = msg; }
}

internal interface IWebSocketEngine
public interface IWebSocketEngine
{
event EventHandler<WebSocketBinaryMessageEventArgs> BinaryMessage;
event EventHandler<WebSocketTextMessageEventArgs> TextMessage;


+ 1
- 1
src/Discord.Net/Net/WebSockets/WebSocket.Events.cs View File

@@ -2,7 +2,7 @@

namespace Discord.Net.WebSockets
{
internal abstract partial class WebSocket
public abstract partial class WebSocket
{
public event EventHandler Connected;
private void RaiseConnected()


+ 2
- 2
src/Discord.Net/Net/WebSockets/WebSocket.cs View File

@@ -10,7 +10,7 @@ using System.Threading.Tasks;

namespace Discord.Net.WebSockets
{
internal enum WebSocketState : byte
public enum WebSocketState : byte
{
Disconnected,
Connecting,
@@ -18,7 +18,7 @@ namespace Discord.Net.WebSockets
Disconnecting
}

internal abstract partial class WebSocket
public abstract partial class WebSocket
{
protected readonly IWebSocketEngine _engine;
protected readonly DiscordWSClient _client;


+ 3
- 3
src/Discord.Net/Net/WebSockets/WebSocketSharpEngine.cs View File

@@ -4,7 +4,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using WSSharpNWebSocket = WebSocketSharp.WebSocket;
using WSSharpWebSocket = WebSocketSharp.WebSocket;

namespace Discord.Net.WebSockets
{
@@ -13,7 +13,7 @@ namespace Discord.Net.WebSockets
private readonly DiscordWSClientConfig _config;
private readonly ConcurrentQueue<string> _sendQueue;
private readonly WebSocket _parent;
private WSSharpNWebSocket _webSocket;
private WSSharpWebSocket _webSocket;

public event EventHandler<WebSocketBinaryMessageEventArgs> BinaryMessage;
public event EventHandler<WebSocketTextMessageEventArgs> TextMessage;
@@ -37,7 +37,7 @@ namespace Discord.Net.WebSockets

public Task Connect(string host, CancellationToken cancelToken)
{
_webSocket = new WSSharpNWebSocket(host);
_webSocket = new WSSharpWebSocket(host);
_webSocket.EmitOnPing = false;
_webSocket.EnableRedirection = true;
_webSocket.Compression = WebSocketSharp.CompressionMethod.Deflate;


+ 21
- 23
src/Discord.Net/project.json View File

@@ -1,32 +1,30 @@
{
"version": "0.8.1-beta2",
"description": "An unofficial .Net API wrapper for the Discord client.",
"authors": [
"RogueException"
],
"version": "0.8.1-beta2",
"description": "An unofficial .Net API wrapper for the Discord client.",
"authors": [
"RogueException"
],
"tags": [
"discord",
"discordapp"
],
"projectUrl": "https://github.com/RogueException/Discord.Net",
"licenseUrl": "http://opensource.org/licenses/MIT",
"repository": {
"type": "git",
"url": "git://github.com/RogueException/Discord.Net"
},
"compilationOptions": {
"allowUnsafe": true
},
"projectUrl": "https://github.com/RogueException/Discord.Net",
"licenseUrl": "http://opensource.org/licenses/MIT",
"repository": {
"type": "git",
"url": "git://github.com/RogueException/Discord.Net"
},

"configurations": {
"TestResponses": {
"compilationOptions": {
"define": [
"DEBUG",
"TRACE",
"TEST_RESPONSES"
]
}
}
"TestResponses": {
"compilationOptions": {
"define": [
"DEBUG",
"TRACE",
"TEST_RESPONSES"
]
}
}
},

"dependencies": {


Loading…
Cancel
Save