diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj
index 3155b01d9..64f5766b0 100644
--- a/src/Discord.Net.Net45/Discord.Net.csproj
+++ b/src/Discord.Net.Net45/Discord.Net.csproj
@@ -89,11 +89,11 @@
DiscordClientConfig.cs
-
- DiscordTextWebSocket.cs
+
+ DiscordDataSocket.cs
-
- DiscordTextWebSocket.Events.cs
+
+ DiscordDataSocket.Events.cs
DiscordVoiceSocket.cs
diff --git a/src/Discord.Net/DiscordClient.Events.cs b/src/Discord.Net/DiscordClient.Events.cs
index 41a8c46d8..5b022b282 100644
--- a/src/Discord.Net/DiscordClient.Events.cs
+++ b/src/Discord.Net/DiscordClient.Events.cs
@@ -2,248 +2,310 @@
namespace Discord
{
- public partial class DiscordClient
+ public enum DebugMessageType : byte
{
- //Debug
- public sealed class LogMessageEventArgs : EventArgs
+ Connection,
+ Event,
+ Cache,
+ WebSocketRawInput,
+ WebSocketUnknownInput,
+ WebSocketEvent,
+ WebSocketUnknownEvent,
+ VoiceOutput
+ }
+ public sealed class LogMessageEventArgs : EventArgs
+ {
+ public readonly DebugMessageType Type;
+ public readonly string Message;
+ internal LogMessageEventArgs(DebugMessageType type, string msg) { Type = type; Message = msg; }
+ }
+ public sealed class ServerEventArgs : EventArgs
+ {
+ public readonly Server Server;
+ internal ServerEventArgs(Server server) { Server = server; }
+ }
+ public sealed class ChannelEventArgs : EventArgs
+ {
+ public readonly Channel Channel;
+ internal ChannelEventArgs(Channel channel) { Channel = channel; }
+ }
+ public sealed class UserEventArgs : EventArgs
+ {
+ public readonly User User;
+ internal UserEventArgs(User user) { User = user; }
+ }
+ public sealed class MessageEventArgs : EventArgs
+ {
+ public readonly Message Message;
+ internal MessageEventArgs(Message msg) { Message = msg; }
+ }
+ public sealed class RoleEventArgs : EventArgs
+ {
+ public readonly Role Role;
+ internal RoleEventArgs(Role role) { Role = role; }
+ }
+ public sealed class BanEventArgs : EventArgs
+ {
+ public readonly User User;
+ public readonly Server Server;
+ internal BanEventArgs(User user, Server server)
{
- public readonly string Message;
- internal LogMessageEventArgs(string msg) { Message = msg; }
+ User = user;
+ Server = server;
}
- public event EventHandler DebugMessage;
- private void RaiseOnDebugMessage(string message)
+ }
+ public sealed class MemberEventArgs : EventArgs
+ {
+ public readonly Membership Member;
+ internal MemberEventArgs(Membership member) { Member = member; }
+ }
+ public sealed class UserTypingEventArgs : EventArgs
+ {
+ public readonly User User;
+ public readonly Channel Channel;
+ internal UserTypingEventArgs(User user, Channel channel)
{
- if (DebugMessage != null)
- DebugMessage(this, new LogMessageEventArgs(message));
+ User = user;
+ Channel = channel;
}
- public event EventHandler VoiceDebugMessage;
- private void RaiseOnVoiceDebugMessage(string message)
+ }
+ public sealed class VoiceServerUpdatedEventArgs : EventArgs
+ {
+ public readonly Server Server;
+ public readonly string Endpoint;
+ internal VoiceServerUpdatedEventArgs(Server server, string endpoint)
{
- if (VoiceDebugMessage != null)
- VoiceDebugMessage(this, new LogMessageEventArgs(message));
+ Server = server;
+ Endpoint = endpoint;
+ }
+ }
+
+
+ public partial class DiscordClient
+ {
+ //Debug
+ public event EventHandler DebugMessage;
+ internal void RaiseOnDebugMessage(DebugMessageType type, string message)
+ {
+ if (DebugMessage != null)
+ DebugMessage(this, new LogMessageEventArgs(type, message));
}
//General
public event EventHandler Connected;
private void RaiseConnected()
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"Connected");
if (Connected != null)
Connected(this, EventArgs.Empty);
}
public event EventHandler Disconnected;
private void RaiseDisconnected()
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"Disconnected");
if (Disconnected != null)
Disconnected(this, EventArgs.Empty);
}
//Server
- public sealed class ServerEventArgs : EventArgs
- {
- public readonly Server Server;
- internal ServerEventArgs(Server server) { Server = server; }
- }
public event EventHandler ServerCreated;
private void RaiseServerCreated(Server server)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"ServerCreated {server.Name} ({server.Id})");
if (ServerCreated != null)
ServerCreated(this, new ServerEventArgs(server));
}
public event EventHandler ServerDestroyed;
private void RaiseServerDestroyed(Server server)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"ServerDestroyed {server.Name} ({server.Id})");
if (ServerDestroyed != null)
ServerDestroyed(this, new ServerEventArgs(server));
}
public event EventHandler ServerUpdated;
private void RaiseServerUpdated(Server server)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"ServerUpdated {server.Name} ({server.Id})");
if (ServerUpdated != null)
ServerUpdated(this, new ServerEventArgs(server));
}
//Channel
- public sealed class ChannelEventArgs : EventArgs
- {
- public readonly Channel Channel;
- internal ChannelEventArgs(Channel channel) { Channel = channel; }
- }
-
public event EventHandler ChannelCreated;
private void RaiseChannelCreated(Channel channel)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"ChannelCreated {channel.Name} ({channel.Id})");
if (ChannelCreated != null)
ChannelCreated(this, new ChannelEventArgs(channel));
}
public event EventHandler ChannelDestroyed;
private void RaiseChannelDestroyed(Channel channel)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"ChannelDestroyed {channel.Name} ({channel.Id})");
if (ChannelDestroyed != null)
ChannelDestroyed(this, new ChannelEventArgs(channel));
}
public event EventHandler ChannelUpdated;
private void RaiseChannelUpdated(Channel channel)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"ChannelUpdated {channel.Name} ({channel.Id})");
if (ChannelUpdated != null)
ChannelUpdated(this, new ChannelEventArgs(channel));
}
//User
- public sealed class UserEventArgs : EventArgs
- {
- public readonly User User;
- internal UserEventArgs(User user) { User = user; }
- }
public event EventHandler UserUpdated;
private void RaiseUserUpdated(User user)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"UserUpdated {user.Name} ({user.Id})");
if (UserUpdated != null)
UserUpdated(this, new UserEventArgs(user));
}
//Message
- public sealed class MessageEventArgs : EventArgs
- {
- public readonly Message Message;
- internal MessageEventArgs(Message msg) { Message = msg; }
- }
-
public event EventHandler MessageCreated;
private void RaiseMessageCreated(Message msg)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MessageCreated {msg.Id}");
if (MessageCreated != null)
MessageCreated(this, new MessageEventArgs(msg));
}
public event EventHandler MessageDeleted;
private void RaiseMessageDeleted(Message msg)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MessageDeleted {msg.Id}");
if (MessageDeleted != null)
MessageDeleted(this, new MessageEventArgs(msg));
}
public event EventHandler MessageUpdated;
private void RaiseMessageUpdated(Message msg)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MessageUpdated {msg.Id}");
if (MessageUpdated != null)
MessageUpdated(this, new MessageEventArgs(msg));
}
public event EventHandler MessageRead;
private void RaiseMessageRead(Message msg)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MessageRead {msg.Id}");
if (MessageRead != null)
MessageRead(this, new MessageEventArgs(msg));
}
public event EventHandler MessageSent;
private void RaiseMessageSent(Message msg)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MessageSent {msg.Id}");
if (MessageSent != null)
MessageSent(this, new MessageEventArgs(msg));
}
//Role
- public sealed class RoleEventArgs : EventArgs
- {
- public readonly Role Role;
- internal RoleEventArgs(Role role) { Role = role; }
- }
-
public event EventHandler RoleCreated;
private void RaiseRoleCreated(Role role)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"RoleCreated {role.Name} ({role.Id})");
if (RoleCreated != null)
RoleCreated(this, new RoleEventArgs(role));
}
public event EventHandler RoleUpdated;
private void RaiseRoleDeleted(Role role)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"RoleDeleted {role.Name} ({role.Id})");
if (RoleDeleted != null)
RoleDeleted(this, new RoleEventArgs(role));
}
public event EventHandler RoleDeleted;
private void RaiseRoleUpdated(Role role)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"RoleUpdated {role.Name} ({role.Id})");
if (RoleUpdated != null)
RoleUpdated(this, new RoleEventArgs(role));
}
//Ban
- public sealed class BanEventArgs : EventArgs
- {
- public readonly User User;
- public readonly Server Server;
- internal BanEventArgs(User user, Server server)
- {
- User = user;
- Server = server;
- }
- }
-
public event EventHandler BanAdded;
private void RaiseBanAdded(User user, Server server)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"BanAdded {user.Name} ({user.Id}) on {server.Name} ({server.Id})");
if (BanAdded != null)
BanAdded(this, new BanEventArgs(user, server));
}
public event EventHandler BanRemoved;
private void RaiseBanRemoved(User user, Server server)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"BanRemoved {user.Name} ({user.Id}) on {server.Name} ({server.Id})");
if (BanRemoved != null)
BanRemoved(this, new BanEventArgs(user, server));
}
//Member
- public sealed class MemberEventArgs : EventArgs
- {
- public readonly Membership Membership;
- internal MemberEventArgs(Membership membership) { Membership = membership; }
- }
-
public event EventHandler MemberAdded;
- private void RaiseMemberAdded(Membership membership)
+ private void RaiseMemberAdded(Membership member)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MemberAdded {member.User.Name} ({member.UserId}) on {member.Server.Name} ({member.ServerId})");
if (MemberAdded != null)
- MemberAdded(this, new MemberEventArgs(membership));
+ MemberAdded(this, new MemberEventArgs(member));
}
public event EventHandler MemberRemoved;
- private void RaiseMemberRemoved(Membership membership)
+ private void RaiseMemberRemoved(Membership member)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MemberRemoved {member.User.Name} ({member.UserId}) on {member.Server.Name} ({member.ServerId})");
if (MemberRemoved != null)
- MemberRemoved(this, new MemberEventArgs(membership));
+ MemberRemoved(this, new MemberEventArgs(member));
}
public event EventHandler MemberUpdated;
- private void RaiseMemberUpdated(Membership membership)
+ private void RaiseMemberUpdated(Membership member)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"MemberUpdated {member.User.Name} ({member.UserId}) on {member.Server.Name} ({member.ServerId})");
if (MemberUpdated != null)
- MemberUpdated(this, new MemberEventArgs(membership));
+ MemberUpdated(this, new MemberEventArgs(member));
}
//Status
- public sealed class UserTypingEventArgs : EventArgs
- {
- public readonly User User;
- public readonly Channel Channel;
- internal UserTypingEventArgs(User user, Channel channel)
- {
- User = user;
- Channel = channel;
- }
- }
-
public event EventHandler PresenceUpdated;
private void RaisePresenceUpdated(Membership member)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"PresenceUpdated {member.User.Name} ({member.UserId}) on {member.Server.Name} ({member.ServerId})");
if (PresenceUpdated != null)
PresenceUpdated(this, new MemberEventArgs(member));
}
public event EventHandler VoiceStateUpdated;
private void RaiseVoiceStateUpdated(Membership member)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceStateUpdated {member.User.Name} ({member.UserId}) on {member.Server.Name} ({member.ServerId})");
if (VoiceStateUpdated != null)
VoiceStateUpdated(this, new MemberEventArgs(member));
}
public event EventHandler UserTyping;
private void RaiseUserTyping(User user, Channel channel)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceStateUpdated {user.Name} ({user.Id}) on {channel.Name} ({channel.Id})");
if (UserTyping != null)
UserTyping(this, new UserTypingEventArgs(user, channel));
}
@@ -252,29 +314,24 @@ namespace Discord
public event EventHandler VoiceConnected;
private void RaiseVoiceConnected()
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceConnected");
if (VoiceConnected != null)
VoiceConnected(this, EventArgs.Empty);
}
public event EventHandler VoiceDisconnected;
private void RaiseVoiceDisconnected()
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceDisconnected");
if (VoiceDisconnected != null)
VoiceDisconnected(this, EventArgs.Empty);
}
- public sealed class VoiceServerUpdatedEventArgs : EventArgs
- {
- public readonly Server Server;
- public readonly string Endpoint;
- internal VoiceServerUpdatedEventArgs(Server server, string endpoint)
- {
- Server = server;
- Endpoint = endpoint;
- }
- }
-
public event EventHandler VoiceServerUpdated;
private void RaiseVoiceServerUpdated(Server server, string endpoint)
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceServerUpdated {server.Name} ({server.Id})");
if (VoiceServerUpdated != null)
VoiceServerUpdated(this, new VoiceServerUpdatedEventArgs(server, endpoint));
}
diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs
index 1ea1ce479..e112e181b 100644
--- a/src/Discord.Net/DiscordClient.cs
+++ b/src/Discord.Net/DiscordClient.cs
@@ -17,8 +17,7 @@ namespace Discord
/// Provides a connection to the DiscordApp service.
public partial class DiscordClient
{
- private readonly DiscordClientConfig _config;
- private readonly DiscordTextWebSocket _webSocket;
+ private readonly DiscordDataSocket _webSocket;
#if !DNXCORE50
private readonly DiscordVoiceSocket _voiceWebSocket;
#endif
@@ -36,6 +35,9 @@ namespace Discord
public string UserId { get; private set; }
public string SessionId { get; private set; }
+ public DiscordClientConfig Config => _config;
+ private readonly DiscordClientConfig _config;
+
/// Returns a collection of all users the client can see across all servers.
/// This collection does not guarantee any ordering.
public IEnumerable Users => _users;
@@ -113,7 +115,12 @@ namespace Discord
});
_servers = new AsyncCache(
- (key, parentKey) => new Server(key, this),
+ (key, parentKey) =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Created server {key}.");
+ return new Server(key, this);
+ },
(server, model) =>
{
server.Name = model.Name;
@@ -141,12 +148,28 @@ namespace Discord
foreach (var membership in extendedModel.Presences)
server.UpdateMember(membership);
}
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Updated server {server.Name} ({server.Id}).");
},
- server => { }
+ server =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Destroyed server {server.Name} ({server.Id}).");
+ }
);
_channels = new AsyncCache(
- (key, parentKey) => new Channel(key, parentKey, this),
+ (key, parentKey) =>
+ {
+ if (_config.EnableDebug)
+ {
+ if (parentKey != null)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Created channel {key} in server {parentKey}.");
+ else
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Created private channel {key}.");
+ }
+ return new Channel(key, parentKey, this);
+ },
(channel, model) =>
{
channel.Name = model.Name;
@@ -176,6 +199,13 @@ namespace Discord
else
channel.PermissionOverwrites = null;
}
+ if (_config.EnableDebug)
+ {
+ if (channel.IsPrivate)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Updated private channel {channel.Name} ({channel.Id}).");
+ else
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Updated channel {channel.Name} ({channel.Id}) in server {channel.Server?.Name} ({channel.ServerId}).");
+ }
},
channel =>
{
@@ -184,10 +214,22 @@ namespace Discord
var user = channel.Recipient;
if (user.PrivateChannelId == channel.Id)
user.PrivateChannelId = null;
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Destroyed private channel {channel.Name} ({channel.Id}).");
+ }
+ else
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Destroyed channel {channel.Name} ({channel.Id}) in server {channel.Server?.Name} ({channel.ServerId}).");
}
});
_messages = new AsyncCache(
- (key, parentKey) => new Message(key, parentKey, this),
+ (key, parentKey) =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Created message {key} in channel {parentKey}.");
+ return new Message(key, parentKey, this);
+ },
(message, model) =>
{
if (model is API.Models.Message)
@@ -260,21 +302,44 @@ namespace Discord
if (extendedModel.Author != null)
message.UserId = extendedModel.Author.Id;
}
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Updated message {message.Id} in channel {message.Channel?.Name} ({message.ChannelId}).");
},
- message => { }
+ message =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Destroyed message {message.Id} in channel {message.Channel?.Name} ({message.ChannelId}).");
+ }
);
- _pendingMessages = new ConcurrentQueue();
+ if (_config.UseMessageQueue)
+ _pendingMessages = new ConcurrentQueue();
_roles = new AsyncCache(
- (key, parentKey) => new Role(key, parentKey, this),
+ (key, parentKey) =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Created role {key} in server {parentKey}.");
+ return new Role(key, parentKey, this);
+ },
(role, model) =>
{
role.Name = model.Name;
role.Permissions.RawValue = (uint)model.Permissions;
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Updated role {role.Name} ({role.Id}) in server {role.Server?.Name} ({role.ServerId}).");
},
- role => { }
+ role =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Destroyed role {role.Name} ({role.Id}) in server {role.Server?.Name} ({role.ServerId}).");
+ }
);
_users = new AsyncCache(
- (key, parentKey) => new User(key, this),
+ (key, parentKey) =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Created user {key}.");
+ return new User(key, this);
+ },
(user, model) =>
{
user.AvatarId = model.Avatar;
@@ -286,53 +351,94 @@ namespace Discord
user.Email = extendedModel.Email;
user.IsVerified = extendedModel.IsVerified;
}
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Updated user {user?.Name} ({user.Id}).");
},
- user => { }
+ user =>
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Cache, $"Destroyed user {user?.Name} ({user.Id}).");
+ }
);
- _webSocket = new DiscordTextWebSocket(this, _config.ConnectionTimeout, _config.WebSocketInterval);
+ _webSocket = new DiscordDataSocket(this, _config.ConnectionTimeout, _config.WebSocketInterval);
_webSocket.Connected += (s, e) => RaiseConnected();
- _webSocket.Disconnected += async (s, e) =>
+ _webSocket.Disconnected += async (s, e) =>
{
- //Reconnect if we didn't cause the disconnect
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket disconnected.");
RaiseDisconnected();
+
+ //Reconnect if we didn't cause the disconnect
while (!_disconnectToken.IsCancellationRequested)
{
try
{
await Task.Delay(_config.ReconnectDelay);
await _webSocket.ReconnectAsync();
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");
await _webSocket.Login();
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket logged in.");
break;
}
catch (Exception ex)
{
- RaiseOnDebugMessage($"Reconnect Failed: {ex.Message}");
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket reconnect failed: {ex.Message}");
//Net is down? We can keep trying to reconnect until the user runs Disconnect()
await Task.Delay(_config.FailedReconnectDelay);
}
}
};
- _webSocket.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Message);
+ if (_config.EnableDebug)
+ _webSocket.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, e.Message);
#if !DNXCORE50
if (_config.EnableVoice)
{
_voiceWebSocket = new DiscordVoiceSocket(this, _config.VoiceConnectionTimeout, _config.WebSocketInterval);
_voiceWebSocket.Connected += (s, e) => RaiseVoiceConnected();
- _voiceWebSocket.Disconnected += (s, e) =>
+ _voiceWebSocket.Disconnected += async (s, e) =>
{
- //TODO: Reconnect if we didn't cause the disconnect
- RaiseVoiceDisconnected();
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"VoiceSocket disconnected.");
+ RaiseVoiceDisconnected();
+
+ //Reconnect if we didn't cause the disconnect
+ while (!_disconnectToken.IsCancellationRequested)
+ {
+ try
+ {
+ await Task.Delay(_config.ReconnectDelay);
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"VoiceSocket connected.");
+ await _voiceWebSocket.ReconnectAsync();
+ break;
+ }
+ catch (Exception ex)
+ {
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"VoiceSocket reconnect failed: {ex.Message}");
+ //Net is down? We can keep trying to reconnect until the user runs Disconnect()
+ await Task.Delay(_config.FailedReconnectDelay);
+ }
+ }
};
- _voiceWebSocket.OnDebugMessage += (s, e) => RaiseOnVoiceDebugMessage(e.Message);
+ if (_config.EnableDebug)
+ _voiceWebSocket.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, e.Message);
}
#endif
-#pragma warning disable CS1998 //Disable unused async keyword warning
+#if !DNXCORE50
_webSocket.GotEvent += async (s, e) =>
+#else
+ _webSocket.GotEvent += (s, e) =>
+#endif
{
- switch (e.Type)
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.WebSocketEvent, $"{e.Type}: {e.Event}");
+ switch (e.Type)
{
//Global
case "READY": //Resync
@@ -610,12 +716,11 @@ namespace Discord
//Others
default:
- RaiseOnDebugMessage("Unknown WebSocket message type: " + e.Type);
+ RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownEvent, "Unknown WebSocket message type: " + e.Type);
break;
}
};
}
-#pragma warning restore CS1998 //Restore unused async keyword warning
private async Task SendAsync()
{
@@ -658,7 +763,7 @@ namespace Discord
{
await Task.Delay(-1, cancelToken);
}
- catch { }
+ catch (OperationCanceledException) { }
}
/// Returns the user with the specified id, or null if none was found.
@@ -867,12 +972,19 @@ namespace Discord
try
{
await _webSocket.ConnectAsync(url);
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");
Http.Token = token;
+
await _webSocket.Login();
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got token.");
success = true;
}
catch (InvalidOperationException) //Bad Token
{
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket had a bad token.");
if (password == null) //If we don't have an alternate login, throw this error
throw;
}
@@ -881,35 +993,51 @@ namespace Discord
{
//Open websocket while we wait for login response
Task socketTask = _webSocket.ConnectAsync(url);
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");
+
var response = await DiscordAPI.Login(emailOrUsername, password);
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got token.");
+
await socketTask;
//Wait for websocket to finish connecting, then send token
token = response.Token;
Http.Token = token;
await _webSocket.Login();
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket logged in.");
success = true;
}
if (!success && password == null) //Anonymous login
{
//Open websocket while we wait for login response
Task socketTask = _webSocket.ConnectAsync(url);
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");
+
var response = await DiscordAPI.LoginAnonymous(emailOrUsername);
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket generated anonymous token.");
+
await socketTask;
//Wait for websocket to finish connecting, then send token
token = response.Token;
Http.Token = token;
await _webSocket.Login();
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket logged in.");
success = true;
}
if (success)
{
var cancelToken = _disconnectToken.Token;
if (_config.UseMessageQueue)
- _tasks = Task.WhenAll(await Task.Factory.StartNew(SendAsync, cancelToken, TaskCreationOptions.LongRunning, TaskScheduler.Default));
+ _tasks = SendAsync();
else
- _tasks = Task.WhenAll(await Task.Factory.StartNew(EmptyAsync, cancelToken, TaskCreationOptions.LongRunning, TaskScheduler.Default));
+ _tasks = EmptyAsync();
_tasks = _tasks.ContinueWith(async x =>
{
await _webSocket.DisconnectAsync();
@@ -1347,10 +1475,13 @@ namespace Discord
/// Number of bytes in this frame.
public void SendVoicePCM(byte[] data, int count)
{
- if (!_config.EnableVoice)
+ if (!_config.EnableVoice)
throw new InvalidOperationException("Voice is not enabled for this client.");
+ if (count == 0) return;
- _voiceWebSocket.SendPCMFrame(data, count);
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.VoiceOutput, $"Queued {count} bytes for voice output.");
+ _voiceWebSocket.SendPCMFrame(data, count);
}
/// Clears the PCM buffer.
@@ -1359,6 +1490,8 @@ namespace Discord
if (!_config.EnableVoice)
throw new InvalidOperationException("Voice is not enabled for this client.");
+ if (_config.EnableDebug)
+ RaiseOnDebugMessage(DebugMessageType.VoiceOutput, $"Cleared the voice buffer.");
_voiceWebSocket.ClearPCMFrames();
}
#endif
diff --git a/src/Discord.Net/DiscordClientConfig.cs b/src/Discord.Net/DiscordClientConfig.cs
index f97405657..a90316623 100644
--- a/src/Discord.Net/DiscordClientConfig.cs
+++ b/src/Discord.Net/DiscordClientConfig.cs
@@ -7,6 +7,9 @@
/// This option requires the opus .dll or .so be in the local lib/ folder.
public bool EnableVoice { get; set; } = false;
#endif
+ /// Enables the verbose DebugMessage event handler. May hinder performance but should help debug any issues.
+ public bool EnableDebug { get; set; } = false;
+
/// Max time in milliseconds to wait for the web socket to connect.
public int ConnectionTimeout { get; set; } = 5000;
/// Max time in milliseconds to wait for the voice web socket to connect.
diff --git a/src/Discord.Net/DiscordTextWebSocket.Events.cs b/src/Discord.Net/DiscordDataSocket.Events.cs
similarity index 91%
rename from src/Discord.Net/DiscordTextWebSocket.Events.cs
rename to src/Discord.Net/DiscordDataSocket.Events.cs
index d7cbb227d..f0d8188c2 100644
--- a/src/Discord.Net/DiscordTextWebSocket.Events.cs
+++ b/src/Discord.Net/DiscordDataSocket.Events.cs
@@ -3,7 +3,7 @@ using System;
namespace Discord
{
- internal partial class DiscordTextWebSocket
+ internal partial class DiscordDataSocket
{
public event EventHandler GotEvent;
public sealed class MessageEventArgs : EventArgs
diff --git a/src/Discord.Net/DiscordTextWebSocket.cs b/src/Discord.Net/DiscordDataSocket.cs
similarity index 91%
rename from src/Discord.Net/DiscordTextWebSocket.cs
rename to src/Discord.Net/DiscordDataSocket.cs
index bd85cc996..35c067c40 100644
--- a/src/Discord.Net/DiscordTextWebSocket.cs
+++ b/src/Discord.Net/DiscordDataSocket.cs
@@ -9,11 +9,11 @@ using WebSocketMessage = Discord.API.Models.TextWebSocketCommands.WebSocketMessa
namespace Discord
{
- internal sealed partial class DiscordTextWebSocket : DiscordWebSocket
+ internal sealed partial class DiscordDataSocket : DiscordWebSocket
{
private ManualResetEventSlim _connectWaitOnLogin, _connectWaitOnLogin2;
- public DiscordTextWebSocket(DiscordClient client, int timeout, int interval)
+ public DiscordDataSocket(DiscordClient client, int timeout, int interval)
: base(client, timeout, interval)
{
_connectWaitOnLogin = new ManualResetEventSlim(false);
@@ -72,7 +72,7 @@ namespace Discord
}
break;
default:
- RaiseOnDebugMessage("Unknown WebSocket operation ID: " + msg.Operation);
+ RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownInput, "Unknown DataSocket op: " + msg.Operation);
break;
}
#if DNXCORE
diff --git a/src/Discord.Net/DiscordVoiceSocket.cs b/src/Discord.Net/DiscordVoiceSocket.cs
index 323985ec3..38bb7621b 100644
--- a/src/Discord.Net/DiscordVoiceSocket.cs
+++ b/src/Discord.Net/DiscordVoiceSocket.cs
@@ -287,7 +287,7 @@ namespace Discord
break;
#endif
default:
- RaiseOnDebugMessage("Unknown WebSocket operation ID: " + msg.Operation);
+ RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownInput, "Unknown VoiceSocket op: " + msg.Operation);
break;
}
#if DNXCORE50
diff --git a/src/Discord.Net/DiscordWebSocket.Events.cs b/src/Discord.Net/DiscordWebSocket.Events.cs
index c6d14ef90..005fe37d1 100644
--- a/src/Discord.Net/DiscordWebSocket.Events.cs
+++ b/src/Discord.Net/DiscordWebSocket.Events.cs
@@ -4,25 +4,26 @@ namespace Discord
{
internal abstract partial class DiscordWebSocket
{
+ //Debug
+ public event EventHandler OnDebugMessage;
+ protected void RaiseOnDebugMessage(DebugMessageType type, string message)
+ {
+ if (OnDebugMessage != null)
+ OnDebugMessage(this, new LogMessageEventArgs(type, message));
+ }
+
+ //Connection
public event EventHandler Connected;
private void RaiseConnected()
{
if (Connected != null)
Connected(this, EventArgs.Empty);
}
-
public event EventHandler Disconnected;
private void RaiseDisconnected()
{
if (Disconnected != null)
Disconnected(this, EventArgs.Empty);
}
-
- public event EventHandler OnDebugMessage;
- protected void RaiseOnDebugMessage(string message)
- {
- if (OnDebugMessage != null)
- OnDebugMessage(this, new DiscordClient.LogMessageEventArgs(message));
- }
}
}
diff --git a/src/Discord.Net/Server.cs b/src/Discord.Net/Server.cs
index bcab3629d..8e235376e 100644
--- a/src/Discord.Net/Server.cs
+++ b/src/Discord.Net/Server.cs
@@ -67,7 +67,12 @@ namespace Discord
_client = client;
_bans = new ConcurrentDictionary();
_members = new AsyncCache(
- (key, parentKey) => new Membership(parentKey, key, _client),
+ (key, parentKey) =>
+ {
+ if (_client.Config.EnableDebug)
+ _client.RaiseOnDebugMessage(DebugMessageType.Cache, $"Created user {key} in server {parentKey}.");
+ return new Membership(parentKey, key, _client);
+ },
(member, model) =>
{
if (model is API.Models.PresenceMemberInfo)
@@ -103,7 +108,14 @@ namespace Discord
member.IsDeafened = extendedModel.IsDeafened;
member.IsMuted = extendedModel.IsMuted;
}
- }
+ if (_client.Config.EnableDebug)
+ _client.RaiseOnDebugMessage(DebugMessageType.Cache, $"Updated user {member.User?.Name} ({member.UserId}) in server {member.Server?.Name} ({member.ServerId}).");
+ },
+ (member) =>
+ {
+ if (_client.Config.EnableDebug)
+ _client.RaiseOnDebugMessage(DebugMessageType.Cache, $"Destroyed user {member.User?.Name} ({member.UserId}) in server {member.Server?.Name} ({member.ServerId}).");
+ }
);
}