Browse Source

Added EnableDebug option and a lot of debug events

tags/docs-0.9
RogueException 9 years ago
parent
commit
2e85ed2899
9 changed files with 341 additions and 135 deletions
  1. +4
    -4
      src/Discord.Net.Net45/Discord.Net.csproj
  2. +143
    -86
      src/Discord.Net/DiscordClient.Events.cs
  3. +163
    -30
      src/Discord.Net/DiscordClient.cs
  4. +3
    -0
      src/Discord.Net/DiscordClientConfig.cs
  5. +1
    -1
      src/Discord.Net/DiscordDataSocket.Events.cs
  6. +3
    -3
      src/Discord.Net/DiscordDataSocket.cs
  7. +1
    -1
      src/Discord.Net/DiscordVoiceSocket.cs
  8. +9
    -8
      src/Discord.Net/DiscordWebSocket.Events.cs
  9. +14
    -2
      src/Discord.Net/Server.cs

+ 4
- 4
src/Discord.Net.Net45/Discord.Net.csproj View File

@@ -89,11 +89,11 @@
<Compile Include="..\Discord.Net\DiscordClientConfig.cs"> <Compile Include="..\Discord.Net\DiscordClientConfig.cs">
<Link>DiscordClientConfig.cs</Link> <Link>DiscordClientConfig.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\DiscordTextWebSocket.cs">
<Link>DiscordTextWebSocket.cs</Link>
<Compile Include="..\Discord.Net\DiscordDataSocket.cs">
<Link>DiscordDataSocket.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\DiscordTextWebSocket.Events.cs">
<Link>DiscordTextWebSocket.Events.cs</Link>
<Compile Include="..\Discord.Net\DiscordDataSocket.Events.cs">
<Link>DiscordDataSocket.Events.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\DiscordVoiceSocket.cs"> <Compile Include="..\Discord.Net\DiscordVoiceSocket.cs">
<Link>DiscordVoiceSocket.cs</Link> <Link>DiscordVoiceSocket.cs</Link>


+ 143
- 86
src/Discord.Net/DiscordClient.Events.cs View File

@@ -2,248 +2,310 @@


namespace Discord 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<LogMessageEventArgs> 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<LogMessageEventArgs> 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<LogMessageEventArgs> DebugMessage;
internal void RaiseOnDebugMessage(DebugMessageType type, string message)
{
if (DebugMessage != null)
DebugMessage(this, new LogMessageEventArgs(type, message));
} }


//General //General
public event EventHandler Connected; public event EventHandler Connected;
private void RaiseConnected() private void RaiseConnected()
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"Connected");
if (Connected != null) if (Connected != null)
Connected(this, EventArgs.Empty); Connected(this, EventArgs.Empty);
} }
public event EventHandler Disconnected; public event EventHandler Disconnected;
private void RaiseDisconnected() private void RaiseDisconnected()
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"Disconnected");
if (Disconnected != null) if (Disconnected != null)
Disconnected(this, EventArgs.Empty); Disconnected(this, EventArgs.Empty);
} }


//Server //Server
public sealed class ServerEventArgs : EventArgs
{
public readonly Server Server;
internal ServerEventArgs(Server server) { Server = server; }
}


public event EventHandler<ServerEventArgs> ServerCreated; public event EventHandler<ServerEventArgs> ServerCreated;
private void RaiseServerCreated(Server server) private void RaiseServerCreated(Server server)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"ServerCreated {server.Name} ({server.Id})");
if (ServerCreated != null) if (ServerCreated != null)
ServerCreated(this, new ServerEventArgs(server)); ServerCreated(this, new ServerEventArgs(server));
} }
public event EventHandler<ServerEventArgs> ServerDestroyed; public event EventHandler<ServerEventArgs> ServerDestroyed;
private void RaiseServerDestroyed(Server server) private void RaiseServerDestroyed(Server server)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"ServerDestroyed {server.Name} ({server.Id})");
if (ServerDestroyed != null) if (ServerDestroyed != null)
ServerDestroyed(this, new ServerEventArgs(server)); ServerDestroyed(this, new ServerEventArgs(server));
} }
public event EventHandler<ServerEventArgs> ServerUpdated; public event EventHandler<ServerEventArgs> ServerUpdated;
private void RaiseServerUpdated(Server server) private void RaiseServerUpdated(Server server)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"ServerUpdated {server.Name} ({server.Id})");
if (ServerUpdated != null) if (ServerUpdated != null)
ServerUpdated(this, new ServerEventArgs(server)); ServerUpdated(this, new ServerEventArgs(server));
} }


//Channel //Channel
public sealed class ChannelEventArgs : EventArgs
{
public readonly Channel Channel;
internal ChannelEventArgs(Channel channel) { Channel = channel; }
}

public event EventHandler<ChannelEventArgs> ChannelCreated; public event EventHandler<ChannelEventArgs> ChannelCreated;
private void RaiseChannelCreated(Channel channel) private void RaiseChannelCreated(Channel channel)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"ChannelCreated {channel.Name} ({channel.Id})");
if (ChannelCreated != null) if (ChannelCreated != null)
ChannelCreated(this, new ChannelEventArgs(channel)); ChannelCreated(this, new ChannelEventArgs(channel));
} }
public event EventHandler<ChannelEventArgs> ChannelDestroyed; public event EventHandler<ChannelEventArgs> ChannelDestroyed;
private void RaiseChannelDestroyed(Channel channel) private void RaiseChannelDestroyed(Channel channel)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"ChannelDestroyed {channel.Name} ({channel.Id})");
if (ChannelDestroyed != null) if (ChannelDestroyed != null)
ChannelDestroyed(this, new ChannelEventArgs(channel)); ChannelDestroyed(this, new ChannelEventArgs(channel));
} }
public event EventHandler<ChannelEventArgs> ChannelUpdated; public event EventHandler<ChannelEventArgs> ChannelUpdated;
private void RaiseChannelUpdated(Channel channel) private void RaiseChannelUpdated(Channel channel)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"ChannelUpdated {channel.Name} ({channel.Id})");
if (ChannelUpdated != null) if (ChannelUpdated != null)
ChannelUpdated(this, new ChannelEventArgs(channel)); ChannelUpdated(this, new ChannelEventArgs(channel));
} }


//User //User
public sealed class UserEventArgs : EventArgs
{
public readonly User User;
internal UserEventArgs(User user) { User = user; }
}
public event EventHandler<UserEventArgs> UserUpdated; public event EventHandler<UserEventArgs> UserUpdated;
private void RaiseUserUpdated(User user) private void RaiseUserUpdated(User user)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"UserUpdated {user.Name} ({user.Id})");
if (UserUpdated != null) if (UserUpdated != null)
UserUpdated(this, new UserEventArgs(user)); UserUpdated(this, new UserEventArgs(user));
} }


//Message //Message
public sealed class MessageEventArgs : EventArgs
{
public readonly Message Message;
internal MessageEventArgs(Message msg) { Message = msg; }
}

public event EventHandler<MessageEventArgs> MessageCreated; public event EventHandler<MessageEventArgs> MessageCreated;
private void RaiseMessageCreated(Message msg) private void RaiseMessageCreated(Message msg)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"MessageCreated {msg.Id}");
if (MessageCreated != null) if (MessageCreated != null)
MessageCreated(this, new MessageEventArgs(msg)); MessageCreated(this, new MessageEventArgs(msg));
} }
public event EventHandler<MessageEventArgs> MessageDeleted; public event EventHandler<MessageEventArgs> MessageDeleted;
private void RaiseMessageDeleted(Message msg) private void RaiseMessageDeleted(Message msg)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"MessageDeleted {msg.Id}");
if (MessageDeleted != null) if (MessageDeleted != null)
MessageDeleted(this, new MessageEventArgs(msg)); MessageDeleted(this, new MessageEventArgs(msg));
} }
public event EventHandler<MessageEventArgs> MessageUpdated; public event EventHandler<MessageEventArgs> MessageUpdated;
private void RaiseMessageUpdated(Message msg) private void RaiseMessageUpdated(Message msg)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"MessageUpdated {msg.Id}");
if (MessageUpdated != null) if (MessageUpdated != null)
MessageUpdated(this, new MessageEventArgs(msg)); MessageUpdated(this, new MessageEventArgs(msg));
} }
public event EventHandler<MessageEventArgs> MessageRead; public event EventHandler<MessageEventArgs> MessageRead;
private void RaiseMessageRead(Message msg) private void RaiseMessageRead(Message msg)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"MessageRead {msg.Id}");
if (MessageRead != null) if (MessageRead != null)
MessageRead(this, new MessageEventArgs(msg)); MessageRead(this, new MessageEventArgs(msg));
} }
public event EventHandler<MessageEventArgs> MessageSent; public event EventHandler<MessageEventArgs> MessageSent;
private void RaiseMessageSent(Message msg) private void RaiseMessageSent(Message msg)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"MessageSent {msg.Id}");
if (MessageSent != null) if (MessageSent != null)
MessageSent(this, new MessageEventArgs(msg)); MessageSent(this, new MessageEventArgs(msg));
} }


//Role //Role
public sealed class RoleEventArgs : EventArgs
{
public readonly Role Role;
internal RoleEventArgs(Role role) { Role = role; }
}

public event EventHandler<RoleEventArgs> RoleCreated; public event EventHandler<RoleEventArgs> RoleCreated;
private void RaiseRoleCreated(Role role) private void RaiseRoleCreated(Role role)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"RoleCreated {role.Name} ({role.Id})");
if (RoleCreated != null) if (RoleCreated != null)
RoleCreated(this, new RoleEventArgs(role)); RoleCreated(this, new RoleEventArgs(role));
} }
public event EventHandler<RoleEventArgs> RoleUpdated; public event EventHandler<RoleEventArgs> RoleUpdated;
private void RaiseRoleDeleted(Role role) private void RaiseRoleDeleted(Role role)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"RoleDeleted {role.Name} ({role.Id})");
if (RoleDeleted != null) if (RoleDeleted != null)
RoleDeleted(this, new RoleEventArgs(role)); RoleDeleted(this, new RoleEventArgs(role));
} }
public event EventHandler<RoleEventArgs> RoleDeleted; public event EventHandler<RoleEventArgs> RoleDeleted;
private void RaiseRoleUpdated(Role role) private void RaiseRoleUpdated(Role role)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"RoleUpdated {role.Name} ({role.Id})");
if (RoleUpdated != null) if (RoleUpdated != null)
RoleUpdated(this, new RoleEventArgs(role)); RoleUpdated(this, new RoleEventArgs(role));
} }


//Ban //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<BanEventArgs> BanAdded; public event EventHandler<BanEventArgs> BanAdded;
private void RaiseBanAdded(User user, Server server) 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) if (BanAdded != null)
BanAdded(this, new BanEventArgs(user, server)); BanAdded(this, new BanEventArgs(user, server));
} }
public event EventHandler<BanEventArgs> BanRemoved; public event EventHandler<BanEventArgs> BanRemoved;
private void RaiseBanRemoved(User user, Server server) 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) if (BanRemoved != null)
BanRemoved(this, new BanEventArgs(user, server)); BanRemoved(this, new BanEventArgs(user, server));
} }


//Member //Member
public sealed class MemberEventArgs : EventArgs
{
public readonly Membership Membership;
internal MemberEventArgs(Membership membership) { Membership = membership; }
}

public event EventHandler<MemberEventArgs> MemberAdded; public event EventHandler<MemberEventArgs> 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) if (MemberAdded != null)
MemberAdded(this, new MemberEventArgs(membership));
MemberAdded(this, new MemberEventArgs(member));
} }
public event EventHandler<MemberEventArgs> MemberRemoved; public event EventHandler<MemberEventArgs> 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) if (MemberRemoved != null)
MemberRemoved(this, new MemberEventArgs(membership));
MemberRemoved(this, new MemberEventArgs(member));
} }
public event EventHandler<MemberEventArgs> MemberUpdated; public event EventHandler<MemberEventArgs> 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) if (MemberUpdated != null)
MemberUpdated(this, new MemberEventArgs(membership));
MemberUpdated(this, new MemberEventArgs(member));
} }


//Status //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<MemberEventArgs> PresenceUpdated; public event EventHandler<MemberEventArgs> PresenceUpdated;
private void RaisePresenceUpdated(Membership member) 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) if (PresenceUpdated != null)
PresenceUpdated(this, new MemberEventArgs(member)); PresenceUpdated(this, new MemberEventArgs(member));
} }
public event EventHandler<MemberEventArgs> VoiceStateUpdated; public event EventHandler<MemberEventArgs> VoiceStateUpdated;
private void RaiseVoiceStateUpdated(Membership member) 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) if (VoiceStateUpdated != null)
VoiceStateUpdated(this, new MemberEventArgs(member)); VoiceStateUpdated(this, new MemberEventArgs(member));
} }
public event EventHandler<UserTypingEventArgs> UserTyping; public event EventHandler<UserTypingEventArgs> UserTyping;
private void RaiseUserTyping(User user, Channel channel) 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) if (UserTyping != null)
UserTyping(this, new UserTypingEventArgs(user, channel)); UserTyping(this, new UserTypingEventArgs(user, channel));
} }
@@ -252,29 +314,24 @@ namespace Discord
public event EventHandler VoiceConnected; public event EventHandler VoiceConnected;
private void RaiseVoiceConnected() private void RaiseVoiceConnected()
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceConnected");
if (VoiceConnected != null) if (VoiceConnected != null)
VoiceConnected(this, EventArgs.Empty); VoiceConnected(this, EventArgs.Empty);
} }
public event EventHandler VoiceDisconnected; public event EventHandler VoiceDisconnected;
private void RaiseVoiceDisconnected() private void RaiseVoiceDisconnected()
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceDisconnected");
if (VoiceDisconnected != null) if (VoiceDisconnected != null)
VoiceDisconnected(this, EventArgs.Empty); 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<VoiceServerUpdatedEventArgs> VoiceServerUpdated; public event EventHandler<VoiceServerUpdatedEventArgs> VoiceServerUpdated;
private void RaiseVoiceServerUpdated(Server server, string endpoint) private void RaiseVoiceServerUpdated(Server server, string endpoint)
{ {
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Event, $"VoiceServerUpdated {server.Name} ({server.Id})");
if (VoiceServerUpdated != null) if (VoiceServerUpdated != null)
VoiceServerUpdated(this, new VoiceServerUpdatedEventArgs(server, endpoint)); VoiceServerUpdated(this, new VoiceServerUpdatedEventArgs(server, endpoint));
} }


+ 163
- 30
src/Discord.Net/DiscordClient.cs View File

@@ -17,8 +17,7 @@ namespace Discord
/// <summary> Provides a connection to the DiscordApp service. </summary> /// <summary> Provides a connection to the DiscordApp service. </summary>
public partial class DiscordClient public partial class DiscordClient
{ {
private readonly DiscordClientConfig _config;
private readonly DiscordTextWebSocket _webSocket;
private readonly DiscordDataSocket _webSocket;
#if !DNXCORE50 #if !DNXCORE50
private readonly DiscordVoiceSocket _voiceWebSocket; private readonly DiscordVoiceSocket _voiceWebSocket;
#endif #endif
@@ -36,6 +35,9 @@ namespace Discord
public string UserId { get; private set; } public string UserId { get; private set; }
public string SessionId { get; private set; } public string SessionId { get; private set; }


public DiscordClientConfig Config => _config;
private readonly DiscordClientConfig _config;

/// <summary> Returns a collection of all users the client can see across all servers. </summary> /// <summary> Returns a collection of all users the client can see across all servers. </summary>
/// <remarks> This collection does not guarantee any ordering. </remarks> /// <remarks> This collection does not guarantee any ordering. </remarks>
public IEnumerable<User> Users => _users; public IEnumerable<User> Users => _users;
@@ -113,7 +115,12 @@ namespace Discord
}); });


_servers = new AsyncCache<Server, API.Models.ServerReference>( _servers = new AsyncCache<Server, API.Models.ServerReference>(
(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, model) =>
{ {
server.Name = model.Name; server.Name = model.Name;
@@ -141,12 +148,28 @@ namespace Discord
foreach (var membership in extendedModel.Presences) foreach (var membership in extendedModel.Presences)
server.UpdateMember(membership); 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<Channel, API.Models.ChannelReference>( _channels = new AsyncCache<Channel, API.Models.ChannelReference>(
(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, model) =>
{ {
channel.Name = model.Name; channel.Name = model.Name;
@@ -176,6 +199,13 @@ namespace Discord
else else
channel.PermissionOverwrites = null; 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 => channel =>
{ {
@@ -184,10 +214,22 @@ namespace Discord
var user = channel.Recipient; var user = channel.Recipient;
if (user.PrivateChannelId == channel.Id) if (user.PrivateChannelId == channel.Id)
user.PrivateChannelId = null; 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<Message, API.Models.MessageReference>( _messages = new AsyncCache<Message, API.Models.MessageReference>(
(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) => (message, model) =>
{ {
if (model is API.Models.Message) if (model is API.Models.Message)
@@ -260,21 +302,44 @@ namespace Discord
if (extendedModel.Author != null) if (extendedModel.Author != null)
message.UserId = extendedModel.Author.Id; 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<Message>();
if (_config.UseMessageQueue)
_pendingMessages = new ConcurrentQueue<Message>();
_roles = new AsyncCache<Role, API.Models.Role>( _roles = new AsyncCache<Role, API.Models.Role>(
(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, model) =>
{ {
role.Name = model.Name; role.Name = model.Name;
role.Permissions.RawValue = (uint)model.Permissions; 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<User, API.Models.UserReference>( _users = new AsyncCache<User, API.Models.UserReference>(
(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, model) =>
{ {
user.AvatarId = model.Avatar; user.AvatarId = model.Avatar;
@@ -286,53 +351,94 @@ namespace Discord
user.Email = extendedModel.Email; user.Email = extendedModel.Email;
user.IsVerified = extendedModel.IsVerified; 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.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(); RaiseDisconnected();

//Reconnect if we didn't cause the disconnect
while (!_disconnectToken.IsCancellationRequested) while (!_disconnectToken.IsCancellationRequested)
{ {
try try
{ {
await Task.Delay(_config.ReconnectDelay); await Task.Delay(_config.ReconnectDelay);
await _webSocket.ReconnectAsync(); await _webSocket.ReconnectAsync();
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");
await _webSocket.Login(); await _webSocket.Login();
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket logged in.");
break; break;
} }
catch (Exception ex) 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() //Net is down? We can keep trying to reconnect until the user runs Disconnect()
await Task.Delay(_config.FailedReconnectDelay); 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 !DNXCORE50
if (_config.EnableVoice) if (_config.EnableVoice)
{ {
_voiceWebSocket = new DiscordVoiceSocket(this, _config.VoiceConnectionTimeout, _config.WebSocketInterval); _voiceWebSocket = new DiscordVoiceSocket(this, _config.VoiceConnectionTimeout, _config.WebSocketInterval);
_voiceWebSocket.Connected += (s, e) => RaiseVoiceConnected(); _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 #endif


#pragma warning disable CS1998 //Disable unused async keyword warning
#if !DNXCORE50
_webSocket.GotEvent += async (s, e) => _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 //Global
case "READY": //Resync case "READY": //Resync
@@ -610,12 +716,11 @@ namespace Discord


//Others //Others
default: default:
RaiseOnDebugMessage("Unknown WebSocket message type: " + e.Type);
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownEvent, "Unknown WebSocket message type: " + e.Type);
break; break;
} }
}; };
} }
#pragma warning restore CS1998 //Restore unused async keyword warning


private async Task SendAsync() private async Task SendAsync()
{ {
@@ -658,7 +763,7 @@ namespace Discord
{ {
await Task.Delay(-1, cancelToken); await Task.Delay(-1, cancelToken);
} }
catch { }
catch (OperationCanceledException) { }
} }


/// <summary> Returns the user with the specified id, or null if none was found. </summary> /// <summary> Returns the user with the specified id, or null if none was found. </summary>
@@ -867,12 +972,19 @@ namespace Discord
try try
{ {
await _webSocket.ConnectAsync(url); await _webSocket.ConnectAsync(url);
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");
Http.Token = token; Http.Token = token;

await _webSocket.Login(); await _webSocket.Login();
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got token.");
success = true; success = true;
} }
catch (InvalidOperationException) //Bad Token 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 if (password == null) //If we don't have an alternate login, throw this error
throw; throw;
} }
@@ -881,35 +993,51 @@ namespace Discord
{ {
//Open websocket while we wait for login response //Open websocket while we wait for login response
Task socketTask = _webSocket.ConnectAsync(url); Task socketTask = _webSocket.ConnectAsync(url);
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");

var response = await DiscordAPI.Login(emailOrUsername, password); var response = await DiscordAPI.Login(emailOrUsername, password);
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got token.");

await socketTask; await socketTask;


//Wait for websocket to finish connecting, then send token //Wait for websocket to finish connecting, then send token
token = response.Token; token = response.Token;
Http.Token = token; Http.Token = token;
await _webSocket.Login(); await _webSocket.Login();
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket logged in.");
success = true; success = true;
} }
if (!success && password == null) //Anonymous login if (!success && password == null) //Anonymous login
{ {
//Open websocket while we wait for login response //Open websocket while we wait for login response
Task socketTask = _webSocket.ConnectAsync(url); Task socketTask = _webSocket.ConnectAsync(url);
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket connected.");

var response = await DiscordAPI.LoginAnonymous(emailOrUsername); var response = await DiscordAPI.LoginAnonymous(emailOrUsername);
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket generated anonymous token.");

await socketTask; await socketTask;


//Wait for websocket to finish connecting, then send token //Wait for websocket to finish connecting, then send token
token = response.Token; token = response.Token;
Http.Token = token; Http.Token = token;
await _webSocket.Login(); await _webSocket.Login();
if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket logged in.");
success = true; success = true;
} }
if (success) if (success)
{ {
var cancelToken = _disconnectToken.Token; var cancelToken = _disconnectToken.Token;
if (_config.UseMessageQueue) if (_config.UseMessageQueue)
_tasks = Task.WhenAll(await Task.Factory.StartNew(SendAsync, cancelToken, TaskCreationOptions.LongRunning, TaskScheduler.Default));
_tasks = SendAsync();
else else
_tasks = Task.WhenAll(await Task.Factory.StartNew(EmptyAsync, cancelToken, TaskCreationOptions.LongRunning, TaskScheduler.Default));
_tasks = EmptyAsync();
_tasks = _tasks.ContinueWith(async x => _tasks = _tasks.ContinueWith(async x =>
{ {
await _webSocket.DisconnectAsync(); await _webSocket.DisconnectAsync();
@@ -1347,10 +1475,13 @@ namespace Discord
/// <param name="count">Number of bytes in this frame. </param> /// <param name="count">Number of bytes in this frame. </param>
public void SendVoicePCM(byte[] data, int count) public void SendVoicePCM(byte[] data, int count)
{ {
if (!_config.EnableVoice)
if (!_config.EnableVoice)
throw new InvalidOperationException("Voice is not enabled for this client."); 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);
} }


/// <summary> Clears the PCM buffer. </summary> /// <summary> Clears the PCM buffer. </summary>
@@ -1359,6 +1490,8 @@ namespace Discord
if (!_config.EnableVoice) if (!_config.EnableVoice)
throw new InvalidOperationException("Voice is not enabled for this client."); throw new InvalidOperationException("Voice is not enabled for this client.");


if (_config.EnableDebug)
RaiseOnDebugMessage(DebugMessageType.VoiceOutput, $"Cleared the voice buffer.");
_voiceWebSocket.ClearPCMFrames(); _voiceWebSocket.ClearPCMFrames();
} }
#endif #endif


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

@@ -7,6 +7,9 @@
/// <remarks> This option requires the opus .dll or .so be in the local lib/ folder. </remarks> /// <remarks> This option requires the opus .dll or .so be in the local lib/ folder. </remarks>
public bool EnableVoice { get; set; } = false; public bool EnableVoice { get; set; } = false;
#endif #endif
/// <summary> Enables the verbose DebugMessage event handler. May hinder performance but should help debug any issues. </summary>
public bool EnableDebug { get; set; } = false;

/// <summary> Max time in milliseconds to wait for the web socket to connect. </summary> /// <summary> Max time in milliseconds to wait for the web socket to connect. </summary>
public int ConnectionTimeout { get; set; } = 5000; public int ConnectionTimeout { get; set; } = 5000;
/// <summary> Max time in milliseconds to wait for the voice web socket to connect. </summary> /// <summary> Max time in milliseconds to wait for the voice web socket to connect. </summary>


src/Discord.Net/DiscordTextWebSocket.Events.cs → src/Discord.Net/DiscordDataSocket.Events.cs View File

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


namespace Discord namespace Discord
{ {
internal partial class DiscordTextWebSocket
internal partial class DiscordDataSocket
{ {
public event EventHandler<MessageEventArgs> GotEvent; public event EventHandler<MessageEventArgs> GotEvent;
public sealed class MessageEventArgs : EventArgs public sealed class MessageEventArgs : EventArgs

src/Discord.Net/DiscordTextWebSocket.cs → src/Discord.Net/DiscordDataSocket.cs View File

@@ -9,11 +9,11 @@ using WebSocketMessage = Discord.API.Models.TextWebSocketCommands.WebSocketMessa


namespace Discord namespace Discord
{ {
internal sealed partial class DiscordTextWebSocket : DiscordWebSocket
internal sealed partial class DiscordDataSocket : DiscordWebSocket
{ {
private ManualResetEventSlim _connectWaitOnLogin, _connectWaitOnLogin2; private ManualResetEventSlim _connectWaitOnLogin, _connectWaitOnLogin2;


public DiscordTextWebSocket(DiscordClient client, int timeout, int interval)
public DiscordDataSocket(DiscordClient client, int timeout, int interval)
: base(client, timeout, interval) : base(client, timeout, interval)
{ {
_connectWaitOnLogin = new ManualResetEventSlim(false); _connectWaitOnLogin = new ManualResetEventSlim(false);
@@ -72,7 +72,7 @@ namespace Discord
} }
break; break;
default: default:
RaiseOnDebugMessage("Unknown WebSocket operation ID: " + msg.Operation);
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownInput, "Unknown DataSocket op: " + msg.Operation);
break; break;
} }
#if DNXCORE #if DNXCORE

+ 1
- 1
src/Discord.Net/DiscordVoiceSocket.cs View File

@@ -287,7 +287,7 @@ namespace Discord
break; break;
#endif #endif
default: default:
RaiseOnDebugMessage("Unknown WebSocket operation ID: " + msg.Operation);
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownInput, "Unknown VoiceSocket op: " + msg.Operation);
break; break;
} }
#if DNXCORE50 #if DNXCORE50


+ 9
- 8
src/Discord.Net/DiscordWebSocket.Events.cs View File

@@ -4,25 +4,26 @@ namespace Discord
{ {
internal abstract partial class DiscordWebSocket internal abstract partial class DiscordWebSocket
{ {
//Debug
public event EventHandler<LogMessageEventArgs> OnDebugMessage;
protected void RaiseOnDebugMessage(DebugMessageType type, string message)
{
if (OnDebugMessage != null)
OnDebugMessage(this, new LogMessageEventArgs(type, message));
}

//Connection
public event EventHandler Connected; public event EventHandler Connected;
private void RaiseConnected() private void RaiseConnected()
{ {
if (Connected != null) if (Connected != null)
Connected(this, EventArgs.Empty); Connected(this, EventArgs.Empty);
} }

public event EventHandler Disconnected; public event EventHandler Disconnected;
private void RaiseDisconnected() private void RaiseDisconnected()
{ {
if (Disconnected != null) if (Disconnected != null)
Disconnected(this, EventArgs.Empty); Disconnected(this, EventArgs.Empty);
} }

public event EventHandler<DiscordClient.LogMessageEventArgs> OnDebugMessage;
protected void RaiseOnDebugMessage(string message)
{
if (OnDebugMessage != null)
OnDebugMessage(this, new DiscordClient.LogMessageEventArgs(message));
}
} }
} }

+ 14
- 2
src/Discord.Net/Server.cs View File

@@ -67,7 +67,12 @@ namespace Discord
_client = client; _client = client;
_bans = new ConcurrentDictionary<string, bool>(); _bans = new ConcurrentDictionary<string, bool>();
_members = new AsyncCache<Membership, API.Models.MemberInfo>( _members = new AsyncCache<Membership, API.Models.MemberInfo>(
(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) => (member, model) =>
{ {
if (model is API.Models.PresenceMemberInfo) if (model is API.Models.PresenceMemberInfo)
@@ -103,7 +108,14 @@ namespace Discord
member.IsDeafened = extendedModel.IsDeafened; member.IsDeafened = extendedModel.IsDeafened;
member.IsMuted = extendedModel.IsMuted; 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}).");
}
); );
} }




Loading…
Cancel
Save