コード例 #1
0
		//Constructor
		/// <summary> Initializes a new instance of the DiscordClient class. </summary>
		public DiscordClient(DiscordClientConfig config = null)
		{
			_blockEvent = new ManualResetEventSlim(true);
			_config = config ?? new DiscordClientConfig();
			_isDebugMode = config.EnableDebug;
			_rand = new Random();
			
			_serializer = new JsonSerializer();
#if TEST_RESPONSES
			_serializer.CheckAdditionalContent = true;
			_serializer.MissingMemberHandling = MissingMemberHandling.Error;
#endif

			_userRegex = new Regex(@"<@\d+?>", RegexOptions.Compiled);
			_channelRegex = new Regex(@"<#\d+?>", RegexOptions.Compiled);
			_userRegexEvaluator = new MatchEvaluator(e =>
			{
				string id = e.Value.Substring(2, e.Value.Length - 3);
				var user = _users[id];
				if (user != null)
					return '@' + user.Name;
				else //User not found
					return e.Value;
			});
			_channelRegexEvaluator = new MatchEvaluator(e =>
			{
				string id = e.Value.Substring(2, e.Value.Length - 3);
				var channel = _channels[id];
				if (channel != null)
					return channel.Name;
				else //Channel not found
					return e.Value;
			});

			if (_config.UseMessageQueue)
				_pendingMessages = new ConcurrentQueue<Message>();

			_http = new JsonHttpClient(config.EnableDebug);
			_api = new DiscordAPI(_http);
			if (_isDebugMode)
				_http.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, e.Message);

			CreateCaches();

			_webSocket = new DiscordDataSocket(this, config.ConnectionTimeout, config.WebSocketInterval, config.EnableDebug);
			_webSocket.Connected += (s, e) => RaiseConnected();
			_webSocket.Disconnected += async (s, e) =>
			{
				RaiseDisconnected();

				//Reconnect if we didn't cause the disconnect
				if (e.WasUnexpected)
				{
					while (!_disconnectToken.IsCancellationRequested)
					{
						try
						{
							await Task.Delay(_config.ReconnectDelay);
							await _webSocket.ReconnectAsync();
							if (_http.Token != null)
								await _webSocket.Login(_http.Token);
							break;
						}
						catch (Exception ex)
						{
							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);
						}
					}
				}
			};
			if (_isDebugMode)
				_webSocket.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, $"DataSocket: {e.Message}");

#if !DNXCORE50
			if (_config.EnableVoice)
			{
				_voiceWebSocket = new DiscordVoiceSocket(this, _config.VoiceConnectionTimeout, _config.WebSocketInterval, config.EnableDebug);
				_voiceWebSocket.Connected += (s, e) => RaiseVoiceConnected();
				_voiceWebSocket.Disconnected += async (s, e) =>
				{
					RaiseVoiceDisconnected();

					//Reconnect if we didn't cause the disconnect
					if (e.WasUnexpected)
					{
						while (!_disconnectToken.IsCancellationRequested)
						{
							try
							{
								await Task.Delay(_config.ReconnectDelay);
								await _voiceWebSocket.ReconnectAsync();
								await _voiceWebSocket.Login(_currentVoiceServerId, _myId, _sessionId, _currentVoiceToken);
								break;
							}
							catch (Exception ex)
							{
								if (_isDebugMode)
									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);
							}
						}
					}
				};
				if (_isDebugMode)
					_voiceWebSocket.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, $"VoiceSocket: {e.Message}");
			}
#endif

#if !DNXCORE50
			_webSocket.GotEvent += async (s, e) =>
#else
			_webSocket.GotEvent += (s, e) =>
#endif
			{
                switch (e.Type)
				{
					//Global
					case "READY": //Resync
						{
							var data = e.Event.ToObject<TextWebSocketEvents.Ready>(_serializer);

							_servers.Clear();
							_channels.Clear();
							_users.Clear();

							_myId = data.User.Id;
#if !DNXCORE50
							_sessionId = data.SessionId;
#endif
							_user = _users.Update(data.User.Id, data.User);
							foreach (var server in data.Guilds)
								_servers.Update(server.Id, server);
							foreach (var channel in data.PrivateChannels)
								_channels.Update(channel.Id, null, channel);
						}
						break;

					//Servers
					case "GUILD_CREATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildCreate>(_serializer);
							var server = _servers.Update(data.Id, data);
							try { RaiseServerCreated(server); } catch { }
						}
						break;
					case "GUILD_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildUpdate>(_serializer);
							var server = _servers.Update(data.Id, data);
							try { RaiseServerUpdated(server); } catch { }
						}
						break;
					case "GUILD_DELETE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildDelete>(_serializer);
							var server = _servers.Remove(data.Id);
							if (server != null)
								try { RaiseServerDestroyed(server); } catch { }
						}
						break;

					//Channels
					case "CHANNEL_CREATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.ChannelCreate>(_serializer);
							var channel = _channels.Update(data.Id, data.GuildId, data);
							try { RaiseChannelCreated(channel); } catch { }
						}
						break;
					case "CHANNEL_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.ChannelUpdate>(_serializer);
							var channel = _channels.Update(data.Id, data.GuildId, data);
							try { RaiseChannelUpdated(channel); } catch { }
						}
						break;
					case "CHANNEL_DELETE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.ChannelDelete>(_serializer);
							var channel = _channels.Remove(data.Id);
							if (channel != null)
								try { RaiseChannelDestroyed(channel); } catch { }
						}
						break;

					//Members
					case "GUILD_MEMBER_ADD":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildMemberAdd>(_serializer);
							var user = _users.Update(data.User.Id, data.User);
							var server = _servers[data.ServerId];
							if (server != null)
							{
								var member = server.UpdateMember(data);
								try { RaiseMemberAdded(member); } catch { }
							}
						}
						break;
					case "GUILD_MEMBER_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildMemberUpdate>(_serializer);
							var user = _users.Update(data.User.Id, data.User);
							var server = _servers[data.ServerId];
							if (server != null)
							{
								var member = server.UpdateMember(data);
								try { RaiseMemberUpdated(member); } catch { }
							}
						}
						break;
					case "GUILD_MEMBER_REMOVE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildMemberRemove>(_serializer);
							var server = _servers[data.ServerId];
							if (server != null)
							{
								var member = server.RemoveMember(data.User.Id);
								if (member != null)
									try { RaiseMemberRemoved(member); } catch { }
							}
						}
						break;

					//Roles
					case "GUILD_ROLE_CREATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildRoleCreateUpdate>(_serializer);
							var role = _roles.Update(data.Role.Id, data.ServerId, data.Role);
							try { RaiseRoleCreated(role); } catch { }
						}
						break;
					case "GUILD_ROLE_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildRoleCreateUpdate>(_serializer);
							var role = _roles.Update(data.Role.Id, data.ServerId, data.Role);
							try { RaiseRoleUpdated(role); } catch { }
						}
						break;
					case "GUILD_ROLE_DELETE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildRoleDelete>(_serializer);
							var role = _roles.Remove(data.RoleId);
							if (role != null)
								try { RaiseRoleDeleted(role); } catch { }
						}
						break;

					//Bans
					case "GUILD_BAN_ADD":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildBanAddRemove>(_serializer);
							var user = _users.Update(data.User.Id, data.User);
							var server = _servers[data.ServerId];
							try { RaiseBanAdded(user, server); } catch { }
						}
						break;
					case "GUILD_BAN_REMOVE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.GuildBanAddRemove>(_serializer);
							var user = _users.Update(data.User.Id, data.User);
							var server = _servers[data.ServerId];
							if (server != null && server.RemoveBan(user.Id))
							{
								try { RaiseBanRemoved(user, server); } catch { }
							}
						}
						break;

					//Messages
					case "MESSAGE_CREATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.MessageCreate>(_serializer);
							Message msg = null;
							bool wasLocal = _config.UseMessageQueue && data.Author.Id == _myId && data.Nonce != null;
                            if (wasLocal)
							{
								msg = _messages.Remap("nonce" + data.Nonce, data.Id);
								if (msg != null)
								{
									msg.IsQueued = false;
									msg.Id = data.Id;
								}
							}
							msg = _messages.Update(data.Id, data.ChannelId, data);
							msg.User.UpdateActivity(data.Timestamp);
							if (wasLocal)
							{
								try { RaiseMessageSent(msg); } catch { }
							}
							try { RaiseMessageCreated(msg); } catch { }
						}
						break;
					case "MESSAGE_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.MessageUpdate>(_serializer);
							var msg = _messages.Update(data.Id, data.ChannelId, data);
							try { RaiseMessageUpdated(msg); } catch { }
						}
						break;
					case "MESSAGE_DELETE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.MessageDelete>(_serializer);
							var msg = GetMessage(data.MessageId);
							if (msg != null)
							{
								_messages.Remove(msg.Id);
								try { RaiseMessageDeleted(msg); } catch { }
							}
						}
						break;
					case "MESSAGE_ACK":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.MessageAck>(_serializer);
							var msg = GetMessage(data.MessageId);
							if (msg != null)
								try { RaiseMessageRead(msg); } catch { }
						}
						break;

					//Statuses
					case "PRESENCE_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.PresenceUpdate>(_serializer);
							var user = _users.Update(data.User.Id, data.User);
							var server = _servers[data.ServerId];
							if (server != null)
							{
								var member = server.UpdateMember(data);
								try { RaisePresenceUpdated(member); } catch { }
							}
						}
						break;
					case "VOICE_STATE_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.VoiceStateUpdate>(_serializer);
							var server = _servers[data.ServerId];
							if (server != null)
							{
								var member = server.UpdateMember(data);
								if (member != null)
									try { RaiseVoiceStateUpdated(member); } catch { }
							}
						}
						break;
					case "TYPING_START":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.TypingStart>(_serializer);
							var channel = _channels[data.ChannelId];
							var user = _users[data.UserId];
							if (user != null)
							{
								user.UpdateActivity(DateTime.UtcNow);
								if (channel != null)
									try { RaiseUserTyping(user, channel); } catch { }
							}
						}
						break;

					//Voice
					case "VOICE_SERVER_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.VoiceServerUpdate>(_serializer);
							var server = _servers[data.ServerId];
							server.VoiceServer = data.Endpoint;
                            try { RaiseVoiceServerUpdated(server, data.Endpoint); } catch { }

#if !DNXCORE50
							if (_config.EnableVoice && data.ServerId == _currentVoiceServerId)
							{
								_currentVoiceToken = data.Token;
								await _voiceWebSocket.ConnectAsync("wss://" + data.Endpoint.Split(':')[0]);
								await _voiceWebSocket.Login(_currentVoiceServerId, _myId, _myId, data.Token);
							}
#endif
						}
						break;

					//Settings
					case "USER_UPDATE":
						{
							var data = e.Event.ToObject<TextWebSocketEvents.UserUpdate>(_serializer);
							var user = _users.Update(data.Id, data);
							try { RaiseUserUpdated(user); } catch { }
						}
						break;
					case "USER_SETTINGS_UPDATE":
						{
							//TODO: Process this
						}
						break;

					//Others
					default:
						RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownEvent, "Unknown WebSocket message type: " + e.Type);
						break;
				}
			};
		}
コード例 #2
0
        //Constructor
        /// <summary> Initializes a new instance of the DiscordClient class. </summary>
        public DiscordClient(DiscordClientConfig config = null)
        {
            _blockEvent  = new ManualResetEventSlim(true);
            _config      = config ?? new DiscordClientConfig();
            _isDebugMode = config.EnableDebug;
            _rand        = new Random();

            _serializer = new JsonSerializer();
#if TEST_RESPONSES
            _serializer.CheckAdditionalContent = true;
            _serializer.MissingMemberHandling  = MissingMemberHandling.Error;
#endif

            _userRegex          = new Regex(@"<@\d+?>", RegexOptions.Compiled);
            _channelRegex       = new Regex(@"<#\d+?>", RegexOptions.Compiled);
            _userRegexEvaluator = new MatchEvaluator(e =>
            {
                string id = e.Value.Substring(2, e.Value.Length - 3);
                var user  = _users[id];
                if (user != null)
                {
                    return('@' + user.Name);
                }
                else                 //User not found
                {
                    return(e.Value);
                }
            });
            _channelRegexEvaluator = new MatchEvaluator(e =>
            {
                string id   = e.Value.Substring(2, e.Value.Length - 3);
                var channel = _channels[id];
                if (channel != null)
                {
                    return(channel.Name);
                }
                else                 //Channel not found
                {
                    return(e.Value);
                }
            });

            if (_config.UseMessageQueue)
            {
                _pendingMessages = new ConcurrentQueue <Message>();
            }

            _http = new JsonHttpClient(config.EnableDebug);
            _api  = new DiscordAPI(_http);
            if (_isDebugMode)
            {
                _http.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, e.Message);
            }

            CreateCaches();

            _webSocket               = new DiscordDataSocket(this, config.ConnectionTimeout, config.WebSocketInterval, config.EnableDebug);
            _webSocket.Connected    += (s, e) => RaiseConnected();
            _webSocket.Disconnected += async(s, e) =>
            {
                RaiseDisconnected();

                //Reconnect if we didn't cause the disconnect
                if (e.WasUnexpected)
                {
                    while (!_disconnectToken.IsCancellationRequested)
                    {
                        try
                        {
                            await Task.Delay(_config.ReconnectDelay);

                            await _webSocket.ReconnectAsync();

                            if (_http.Token != null)
                            {
                                await _webSocket.Login(_http.Token);
                            }
                            break;
                        }
                        catch (Exception ex)
                        {
                            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);
                        }
                    }
                }
            };
            if (_isDebugMode)
            {
                _webSocket.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, $"DataSocket: {e.Message}");
            }

#if !DNXCORE50
            if (_config.EnableVoice)
            {
                _voiceWebSocket               = new DiscordVoiceSocket(this, _config.VoiceConnectionTimeout, _config.WebSocketInterval, config.EnableDebug);
                _voiceWebSocket.Connected    += (s, e) => RaiseVoiceConnected();
                _voiceWebSocket.Disconnected += async(s, e) =>
                {
                    RaiseVoiceDisconnected();

                    //Reconnect if we didn't cause the disconnect
                    if (e.WasUnexpected)
                    {
                        while (!_disconnectToken.IsCancellationRequested)
                        {
                            try
                            {
                                await Task.Delay(_config.ReconnectDelay);

                                await _voiceWebSocket.ReconnectAsync();

                                await _voiceWebSocket.Login(_currentVoiceServerId, _myId, _sessionId, _currentVoiceToken);

                                break;
                            }
                            catch (Exception ex)
                            {
                                if (_isDebugMode)
                                {
                                    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);
                            }
                        }
                    }
                };
                if (_isDebugMode)
                {
                    _voiceWebSocket.OnDebugMessage += (s, e) => RaiseOnDebugMessage(e.Type, $"VoiceSocket: {e.Message}");
                }
            }
#endif

#if !DNXCORE50
            _webSocket.GotEvent += async(s, e) =>
#else
            _webSocket.GotEvent += (s, e) =>
#endif
            {
                switch (e.Type)
                {
                //Global
                case "READY":                         //Resync
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.Ready>(_serializer);

                    _servers.Clear();
                    _channels.Clear();
                    _users.Clear();

                    _myId = data.User.Id;
#if !DNXCORE50
                    _sessionId = data.SessionId;
#endif
                    _user = _users.Update(data.User.Id, data.User);
                    foreach (var server in data.Guilds)
                    {
                        _servers.Update(server.Id, server);
                    }
                    foreach (var channel in data.PrivateChannels)
                    {
                        _channels.Update(channel.Id, null, channel);
                    }
                }
                break;

                //Servers
                case "GUILD_CREATE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildCreate>(_serializer);
                    var server = _servers.Update(data.Id, data);
                    try { RaiseServerCreated(server); } catch { }
                }
                break;

                case "GUILD_UPDATE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildUpdate>(_serializer);
                    var server = _servers.Update(data.Id, data);
                    try { RaiseServerUpdated(server); } catch { }
                }
                break;

                case "GUILD_DELETE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildDelete>(_serializer);
                    var server = _servers.Remove(data.Id);
                    if (server != null)
                    {
                        try { RaiseServerDestroyed(server); } catch { }
                    }
                }
                break;

                //Channels
                case "CHANNEL_CREATE":
                {
                    var data    = e.Event.ToObject <TextWebSocketEvents.ChannelCreate>(_serializer);
                    var channel = _channels.Update(data.Id, data.GuildId, data);
                    try { RaiseChannelCreated(channel); } catch { }
                }
                break;

                case "CHANNEL_UPDATE":
                {
                    var data    = e.Event.ToObject <TextWebSocketEvents.ChannelUpdate>(_serializer);
                    var channel = _channels.Update(data.Id, data.GuildId, data);
                    try { RaiseChannelUpdated(channel); } catch { }
                }
                break;

                case "CHANNEL_DELETE":
                {
                    var data    = e.Event.ToObject <TextWebSocketEvents.ChannelDelete>(_serializer);
                    var channel = _channels.Remove(data.Id);
                    if (channel != null)
                    {
                        try { RaiseChannelDestroyed(channel); } catch { }
                    }
                }
                break;

                //Members
                case "GUILD_MEMBER_ADD":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildMemberAdd>(_serializer);
                    var user   = _users.Update(data.User.Id, data.User);
                    var server = _servers[data.ServerId];
                    if (server != null)
                    {
                        var member = server.UpdateMember(data);
                        try { RaiseMemberAdded(member); } catch { }
                    }
                }
                break;

                case "GUILD_MEMBER_UPDATE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildMemberUpdate>(_serializer);
                    var user   = _users.Update(data.User.Id, data.User);
                    var server = _servers[data.ServerId];
                    if (server != null)
                    {
                        var member = server.UpdateMember(data);
                        try { RaiseMemberUpdated(member); } catch { }
                    }
                }
                break;

                case "GUILD_MEMBER_REMOVE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildMemberRemove>(_serializer);
                    var server = _servers[data.ServerId];
                    if (server != null)
                    {
                        var member = server.RemoveMember(data.User.Id);
                        if (member != null)
                        {
                            try { RaiseMemberRemoved(member); } catch { }
                        }
                    }
                }
                break;

                //Roles
                case "GUILD_ROLE_CREATE":
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.GuildRoleCreateUpdate>(_serializer);
                    var role = _roles.Update(data.Role.Id, data.ServerId, data.Role);
                    try { RaiseRoleCreated(role); } catch { }
                }
                break;

                case "GUILD_ROLE_UPDATE":
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.GuildRoleCreateUpdate>(_serializer);
                    var role = _roles.Update(data.Role.Id, data.ServerId, data.Role);
                    try { RaiseRoleUpdated(role); } catch { }
                }
                break;

                case "GUILD_ROLE_DELETE":
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.GuildRoleDelete>(_serializer);
                    var role = _roles.Remove(data.RoleId);
                    if (role != null)
                    {
                        try { RaiseRoleDeleted(role); } catch { }
                    }
                }
                break;

                //Bans
                case "GUILD_BAN_ADD":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildBanAddRemove>(_serializer);
                    var user   = _users.Update(data.User.Id, data.User);
                    var server = _servers[data.ServerId];
                    try { RaiseBanAdded(user, server); } catch { }
                }
                break;

                case "GUILD_BAN_REMOVE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.GuildBanAddRemove>(_serializer);
                    var user   = _users.Update(data.User.Id, data.User);
                    var server = _servers[data.ServerId];
                    if (server != null && server.RemoveBan(user.Id))
                    {
                        try { RaiseBanRemoved(user, server); } catch { }
                    }
                }
                break;

                //Messages
                case "MESSAGE_CREATE":
                {
                    var     data     = e.Event.ToObject <TextWebSocketEvents.MessageCreate>(_serializer);
                    Message msg      = null;
                    bool    wasLocal = _config.UseMessageQueue && data.Author.Id == _myId && data.Nonce != null;
                    if (wasLocal)
                    {
                        msg = _messages.Remap("nonce" + data.Nonce, data.Id);
                        if (msg != null)
                        {
                            msg.IsQueued = false;
                            msg.Id       = data.Id;
                        }
                    }
                    msg = _messages.Update(data.Id, data.ChannelId, data);
                    msg.User.UpdateActivity(data.Timestamp);
                    if (wasLocal)
                    {
                        try { RaiseMessageSent(msg); } catch { }
                    }
                    try { RaiseMessageCreated(msg); } catch { }
                }
                break;

                case "MESSAGE_UPDATE":
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.MessageUpdate>(_serializer);
                    var msg  = _messages.Update(data.Id, data.ChannelId, data);
                    try { RaiseMessageUpdated(msg); } catch { }
                }
                break;

                case "MESSAGE_DELETE":
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.MessageDelete>(_serializer);
                    var msg  = GetMessage(data.MessageId);
                    if (msg != null)
                    {
                        _messages.Remove(msg.Id);
                        try { RaiseMessageDeleted(msg); } catch { }
                    }
                }
                break;

                case "MESSAGE_ACK":
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.MessageAck>(_serializer);
                    var msg  = GetMessage(data.MessageId);
                    if (msg != null)
                    {
                        try { RaiseMessageRead(msg); } catch { }
                    }
                }
                break;

                //Statuses
                case "PRESENCE_UPDATE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.PresenceUpdate>(_serializer);
                    var user   = _users.Update(data.User.Id, data.User);
                    var server = _servers[data.ServerId];
                    if (server != null)
                    {
                        var member = server.UpdateMember(data);
                        try { RaisePresenceUpdated(member); } catch { }
                    }
                }
                break;

                case "VOICE_STATE_UPDATE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.VoiceStateUpdate>(_serializer);
                    var server = _servers[data.ServerId];
                    if (server != null)
                    {
                        var member = server.UpdateMember(data);
                        if (member != null)
                        {
                            try { RaiseVoiceStateUpdated(member); } catch { }
                        }
                    }
                }
                break;

                case "TYPING_START":
                {
                    var data    = e.Event.ToObject <TextWebSocketEvents.TypingStart>(_serializer);
                    var channel = _channels[data.ChannelId];
                    var user    = _users[data.UserId];
                    if (user != null)
                    {
                        user.UpdateActivity(DateTime.UtcNow);
                        if (channel != null)
                        {
                            try { RaiseUserTyping(user, channel); } catch { }
                        }
                    }
                }
                break;

                //Voice
                case "VOICE_SERVER_UPDATE":
                {
                    var data   = e.Event.ToObject <TextWebSocketEvents.VoiceServerUpdate>(_serializer);
                    var server = _servers[data.ServerId];
                    server.VoiceServer = data.Endpoint;
                    try { RaiseVoiceServerUpdated(server, data.Endpoint); } catch { }

#if !DNXCORE50
                    if (_config.EnableVoice && data.ServerId == _currentVoiceServerId)
                    {
                        _currentVoiceToken = data.Token;
                        await _voiceWebSocket.ConnectAsync("wss://" + data.Endpoint.Split(':')[0]);

                        await _voiceWebSocket.Login(_currentVoiceServerId, _myId, _myId, data.Token);
                    }
#endif
                }
                break;

                //Settings
                case "USER_UPDATE":
                {
                    var data = e.Event.ToObject <TextWebSocketEvents.UserUpdate>(_serializer);
                    var user = _users.Update(data.Id, data);
                    try { RaiseUserUpdated(user); } catch { }
                }
                break;

                case "USER_SETTINGS_UPDATE":
                {
                    //TODO: Process this
                }
                break;

                //Others
                default:
                    RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownEvent, "Unknown WebSocket message type: " + e.Type);
                    break;
                }
            };
        }