/// <summary> Initializes a new instance of the DiscordClient class. </summary>
		public DiscordSimpleClient(DiscordClientConfig config = null)
		{
			_config = config ?? new DiscordClientConfig();
			_config.Lock();

			_enableVoice = config.VoiceMode != DiscordVoiceMode.Disabled && !config.EnableVoiceMultiserver;

			_state = (int)DiscordClientState.Disconnected;
			_cancelToken = new CancellationToken(true);
			_disconnectedEvent = new ManualResetEvent(true);
			_connectedEvent = new ManualResetEventSlim(false);
			
			_dataSocket = CreateDataSocket();
			if (_enableVoice)
				_voiceSocket = CreateVoiceSocket();
		}
		internal DiscordSimpleClient(DiscordClientConfig config = null, string serverId = null)
			: this(config)
		{
			_voiceServerId = serverId;
		}
        /// <summary> Initializes a new instance of the DiscordClient class. </summary>
        public DiscordClient(DiscordClientConfig config = null)
            : base(config ?? new DiscordClientConfig())
        {
            _rand = new Random();
            _api  = new DiscordAPIClient(_config);
            if (Config.UseMessageQueue)
            {
                _pendingMessages = new ConcurrentQueue <Message>();
            }
            if (Config.EnableVoiceMultiserver)
            {
                _voiceClients = new ConcurrentDictionary <string, DiscordWSClient>();
            }

            object cacheLock = new object();

            _channels    = new Channels(this, cacheLock);
            _users       = new Users(this, cacheLock);
            _messages    = new Messages(this, cacheLock, Config.MessageCacheLength > 0);
            _roles       = new Roles(this, cacheLock);
            _servers     = new Servers(this, cacheLock);
            _globalUsers = new GlobalUsers(this, cacheLock);

            _status = UserStatus.Online;

            this.Connected += async(s, e) =>
            {
                _api.CancelToken = _cancelToken;
                await SendStatus().ConfigureAwait(false);
            };

            VoiceDisconnected += (s, e) =>
            {
                var server = _servers[e.ServerId];
                if (server != null)
                {
                    foreach (var member in server.Members)
                    {
                        if (member.IsSpeaking)
                        {
                            member.IsSpeaking = false;
                            RaiseUserIsSpeaking(member, _channels[_voiceSocket.CurrentChannelId], false);
                        }
                    }
                }
            };

            if (_config.LogLevel >= LogMessageSeverity.Info)
            {
                ServerCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                      $"Server Created: {e.Server?.Name ?? "[Private]"}");
                ServerDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                        $"Server Destroyed: {e.Server?.Name ?? "[Private]"}");
                ServerUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                      $"Server Updated: {e.Server?.Name ?? "[Private]"}");
                ServerAvailable += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                        $"Server Available: {e.Server?.Name ?? "[Private]"}");
                ServerUnavailable += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                          $"Server Unavailable: {e.Server?.Name ?? "[Private]"}");
                ChannelCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                       $"Channel Created: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}");
                ChannelDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                         $"Channel Destroyed: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}");
                ChannelUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                       $"Channel Updated: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}");
                MessageReceived += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                        $"Message Received: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
                MessageDeleted += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                       $"Message Deleted: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
                MessageUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                       $"Message Update: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
                RoleCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                    $"Role Created: {e.Server?.Name ?? "[Private]"}/{e.Role?.Name}");
                RoleUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                    $"Role Updated: {e.Server?.Name ?? "[Private]"}/{e.Role?.Name}");
                RoleDeleted += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                    $"Role Deleted: {e.Server?.Name ?? "[Private]"}/{e.Role?.Name}");
                UserBanned += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                   $"Banned User: {e.Server?.Name ?? "[Private]" }/{e.UserId}");
                UserUnbanned += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                     $"Unbanned User: {e.Server?.Name ?? "[Private]"}/{e.UserId}");
                UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                  $"User Joined: {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
                UserRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                    $"User Left: {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
                UserUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                    $"User Updated: {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
                UserVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                              $"User Updated (Voice State): {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
                ProfileUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
                                                       "Profile Updated");
            }
            if (_config.LogLevel >= LogMessageSeverity.Verbose)
            {
                UserIsTypingUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client,
                                                            $"User Updated (Is Typing): {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.User?.Name}");
                MessageReadRemotely += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client,
                                                            $"Read Message (Remotely): {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
                MessageSent += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client,
                                                    $"Sent Message: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
                UserPresenceUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client,
                                                            $"User Updated (Presence): {e.Server?.Name ?? "[Private]"}/{e.User?.Name}");

                _api.RestClient.OnRequest += (s, e) =>
                {
                    if (e.Payload != null)
                    {
                        RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Rest, $"{e.Method.Method} {e.Path}: {Math.Round(e.ElapsedMilliseconds, 2)} ms ({e.Payload})");
                    }
                    else
                    {
                        RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Rest, $"{e.Method.Method} {e.Path}: {Math.Round(e.ElapsedMilliseconds, 2)} ms");
                    }
                };
            }
            if (_config.LogLevel >= LogMessageSeverity.Debug)
            {
                _channels.ItemCreated      += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
                _channels.ItemDestroyed    += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
                _channels.Cleared          += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Channels");
                _users.ItemCreated         += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
                _users.ItemDestroyed       += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
                _users.Cleared             += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users");
                _messages.ItemCreated      += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
                _messages.ItemDestroyed    += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
                _messages.ItemRemapped     += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Remapped Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/[{e.OldId} -> {e.NewId}]");
                _messages.Cleared          += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Messages");
                _roles.ItemCreated         += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Role {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
                _roles.ItemDestroyed       += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Role {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
                _roles.Cleared             += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Roles");
                _servers.ItemCreated       += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Server {e.Item.Id}");
                _servers.ItemDestroyed     += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Server {e.Item.Id}");
                _servers.Cleared           += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Servers");
                _globalUsers.ItemCreated   += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {e.Item.Id}");
                _globalUsers.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {e.Item.Id}");
                _globalUsers.Cleared       += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users");
            }

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

            _serializer = new JsonSerializer();
            _serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
#if TEST_RESPONSES
            _serializer.CheckAdditionalContent = true;
            _serializer.MissingMemberHandling  = MissingMemberHandling.Error;
#endif
        }
示例#4
0
		/// <summary> Initializes a new instance of the DiscordClient class. </summary>
		public DiscordClient(DiscordClientConfig config = null)
			: base(config ?? new DiscordClientConfig())
		{
			_rand = new Random();
			_api = new DiscordAPIClient(_config.LogLevel, _config.UserAgent, _config.APITimeout);
			if (Config.UseMessageQueue)
				_pendingMessages = new ConcurrentQueue<Message>();
			if (Config.EnableVoiceMultiserver)
				_voiceClients = new ConcurrentDictionary<string, DiscordSimpleClient>();

			object cacheLock = new object();
			_channels = new Channels(this, cacheLock);
			_members = new Members(this, cacheLock);
			_messages = new Messages(this, cacheLock);
			_roles = new Roles(this, cacheLock);
			_servers = new Servers(this, cacheLock);
			_users = new Users(this, cacheLock);
			_status = UserStatus.Online;

			this.Connected += async (s, e) =>
			{
				_api.CancelToken = CancelToken;
				await SendStatus();
			};

			VoiceDisconnected += (s, e) =>
			{
				foreach (var member in _members)
				{
					if (member.ServerId == e.ServerId && member.IsSpeaking)
					{
						member.IsSpeaking = false;
						RaiseUserIsSpeaking(member, false);
					}
				}
			};

			bool showIDs = _config.LogLevel > LogMessageSeverity.Debug; //Hide this for now
			if (_config.LogLevel >= LogMessageSeverity.Info)
			{
				ServerCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Created Server: {e.Server?.Name}" +
					(showIDs ? $" ({e.ServerId})" : ""));
				ServerDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Destroyed Server: {e.Server?.Name}" +
					(showIDs ? $" ({e.ServerId})" : ""));
				ServerUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Updated Server: {e.Server?.Name}" +
					(showIDs ? $" ({e.ServerId})" : ""));
				ServerAvailable += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Server Unavailable: {e.Server?.Name}" +
					(showIDs ? $" ({e.ServerId})" : ""));
				ServerUnavailable += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Server Unavailable: {e.Server?.Name}" +
					(showIDs ? $" ({e.ServerId})" : ""));
				ChannelCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Created Channel: {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId})" : ""));
				ChannelDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Destroyed Channel: {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId})" : ""));
				ChannelUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Updated Channel: {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId})" : ""));
				MessageCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Created Message: {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}/{e.MessageId}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId}/{e.MessageId})" : ""));
				MessageDeleted += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Deleted Message: {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}/{e.MessageId}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId}/{e.MessageId})" : ""));
				MessageUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Updated Message: {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}/{e.MessageId}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId}/{e.MessageId})" : ""));
				RoleCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Created Role: {e.Server?.Name ?? "[Private]"}/{e.Role.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.RoleId})." : ""));
				RoleUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Updated Role: {e.Server?.Name ?? "[Private]"}/{e.Role.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.RoleId})." : ""));
				RoleDeleted += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Deleted Role: {e.Server?.Name ?? "[Private]"}/{e.Role.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.RoleId})." : ""));
				BanAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Added Ban: {e.Server?.Name ?? "[Private]"}/{e.User?.Name ?? "Unknown"}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : ""));
				BanRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Removed Ban: {e.Server?.Name ?? "[Private]"}/{e.User?.Name ?? "Unknown"}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : ""));
				UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Added Member: {e.Server?.Name ?? "[Private]"}/{e.User.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : ""));
				UserRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Removed Member: {e.Server?.Name ?? "[Private]"}/{e.User.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : ""));
				MemberUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Updated Member: {e.Server?.Name ?? "[Private]"}/{e.User.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : ""));
				UserVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Updated Member (Voice State): {e.Server?.Name ?? "[Private]"}/{e.User.Name}" +
					(showIDs ? $" ({e.ServerId ?? "0"}/{e.UserId})" : ""));
				UserUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Updated User: {e.User.Name}" +
					(showIDs ? $" ({e.UserId})." : ""));
			}
			if (_config.LogLevel >= LogMessageSeverity.Verbose)
			{
				UserIsTyping += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client,
					$"Updated User (Is Typing): {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}/{e.User.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId}/{e.UserId})" : ""));
				MessageReadRemotely += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, 
					$"Read Message (Remotely): {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}/{e.MessageId}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId}/{e.MessageId})" : ""));
				MessageSent += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, 
					$"Sent Message: {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}/{e.MessageId}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId}/{e.MessageId})" : ""));
				UserPresenceUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, 
					$"Updated Member (Presence): {e.Server?.Name ?? "[Private]"}/{e.User.Name}" +
					(showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})" : ""));
				
				_api.RestClient.OnRequest += (s, e) =>
				{
					if (e.Payload != null)
						RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Rest, $"{e.Method.Method} {e.Path}: {Math.Round(e.ElapsedMilliseconds, 2)} ms ({e.Payload})");
					else
						RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Rest, $"{e.Method.Method} {e.Path}: {Math.Round(e.ElapsedMilliseconds, 2)} ms");
				};
			}
			if (_config.LogLevel >= LogMessageSeverity.Debug)
			{
				_channels.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Channel {e.Item?.ServerId ?? "[Private]"}/{e.Item.Id}");
				_channels.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Channel {e.Item.ServerId ?? "[Private]"}/{e.Item.Id}");
				_channels.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Channels");
				_members.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Member {e.Item.ServerId ?? "[Private]"}/{e.Item.UserId}");
				_members.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Member {e.Item.ServerId ?? "[Private]"}/{e.Item.UserId}");
				_members.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Members");
				_messages.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Message {e.Item.ServerId ?? "[Private]"}/{e.Item.ChannelId}/{e.Item.Id}");
				_messages.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Message {e.Item.ServerId ?? "[Private]"}/{e.Item.ChannelId}/{e.Item.Id}");
				_messages.ItemRemapped += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Remapped Message {e.Item.ServerId ?? "[Private]"}/{e.Item.ChannelId}/[{e.OldId} -> {e.NewId}]");
				_messages.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Messages");
				_roles.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Role {e.Item.ServerId}/{e.Item.Id}");
				_roles.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Role {e.Item.ServerId}/{e.Item.Id}");
				_roles.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Roles");
				_servers.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Server {e.Item.Id}");
				_servers.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Server {e.Item.Id}");
				_servers.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Servers");
				_users.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {e.Item.Id}");
				_users.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {e.Item.Id}");
				_users.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users");
			}

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

			_serializer = new JsonSerializer();
#if TEST_RESPONSES
			_serializer.CheckAdditionalContent = true;
			_serializer.MissingMemberHandling = MissingMemberHandling.Error;
#endif
		}
示例#5
0
        static void Main(string[] args)
        {
            if (!restart)
            {
                rpg = new KokoroBotRPG();
                loadFiles();
            }
            else
            {
                restart = false;
            }
            {
                DiscordClientConfig config = new DiscordClientConfig();
                config.VoiceMode = DiscordVoiceMode.Outgoing;
                config.VoiceBufferLength = 40;
                var client = new DiscordClient(config);
                
                //Display all log messages in the console
                client.LogMessage += (s, e) => Console.WriteLine($"[{e.Severity}] {e.Source}: {e.Message}");
                
                client.MessageReceived += async (s, e) =>
                {
                    Console.WriteLine(e.Message.User.Name + ": " + e.Message.Text);
                    if (!e.Message.IsAuthor)
                    {
                        var currentChannel = e.Channel;
                        if (e.User.Id == 95543627391959040)
                        {
                            if (e.Message.Text == "-mute")
                            {
                                mute = !mute;
                                await client.SendMessage(currentChannel, "KokoroBot is now mute: " + mute.ToString());
                            }
                            else if (e.Message.Text == "-clear")
                            {
                                if (voiceclient != null)
                                    voiceclient.ClearVoicePCM();
                            }
                            else if (e.Message.Text == "-save")
                            {
                                saveFiles();
                                await client.SendMessage(currentChannel, "I have saved everything :3");
                            }
                            else if (e.Message.Text == "-dc")
                            {
                                quit = true;
                                running = false;
                            }
                            else if (e.Message.Text == "-restart")
                            {
                                await client.SendMessage(currentChannel, "Cya on the other side :3");
                                restart = true;
                                running = false;
                                await client.Disconnect();
                            }
                            else if (e.Message.Text.StartsWith("-join"))
                            {
                                var channels = e.Server.Channels.Where((Channel chan) => {
                                    return e.Message.Text.Substring(5).TrimStart(' ') == chan.Name && chan.Type == ChannelType.Voice;  });
                                if (channels.Any())
                                {
                                    var channel = channels.First();
                                    Console.WriteLine("KokoroBot tries to join Channel: " + channel.Name);
                                    voiceclient = await client.JoinVoiceServer(channel);
                                    voiceserver = e.Message.Server;
                                }
                            }
                            else if (e.Message.Text == "-leave")
                            {
                                if (voiceclient != null)
                                {
                                    voiceclient.ClearVoicePCM();
                                    await client.LeaveVoiceServer(voiceserver);
                                    voiceclient = null;
                                    voiceserver = null;
                                }
                            }
                        }
                        else if (e.User.Name == "part")
                        {
                            await client.SendMessage(currentChannel, "I don't like you. B-b-baka. >.<");
                            return;
                        }
                        if (!mute) {
                            if (e.Message.Text.Length > 0)
                            {
                                string[] splitmessage = e.Message.Text.Split(' ');
                                if (splitmessage[0] == "-kardfacts")
                                {
                                    if (splitmessage.Length > 2)
                                    {
                                        if (splitmessage[1] == "add")
                                        {
                                            try
                                            {
                                                string finalstr = "";
                                                for (int i = 2; i < splitmessage.Length; i++)
                                                {
                                                    if (i != 2)
                                                        finalstr += ' ' + splitmessage[i];
                                                    else
                                                        finalstr = splitmessage[i];
                                                }
                                                if (finalstr.Length > 5)
                                                {
                                                    kardFactsStrings.Add(finalstr);
                                                    await client.SendMessage(currentChannel, "A new fact about Kard has been added. (Yay ^-^):");
                                                    currentChannel = e.Channel;
                                                    await client.SendMessage(currentChannel, finalstr);
                                                }
                                                else
                                                {
                                                    throw new IOException("Hue.");
                                                }
                                            }
                                            catch (Exception)
                                            {
                                                await client.SendMessage(currentChannel, "That hurt <.< Don't do this again, ok? :3");
                                            }
                                        }
                                    }
                                    else
                                    {
                                        await client.SendMessage(currentChannel, kardFacts());
                                    }
                                }
                                else if (e.Message.Text.StartsWith("-play"))
                                {
                                    Task.Run(() => { PlaySoundWav(e); });
                                }
                                else if(e.Message.Text.StartsWith("-getclientid"))
                                {
                                    if (e.Message.Text.Length > "-getclientid ".Length)
                                    {
                                        try {
                                            await client.SendMessage(currentChannel, e.Server.Members.Where((User u) =>
                                           {
                                               return u.Name.StartsWith(e.Message.Text.Substring("-getclientid ".Length));
                                           }).First().Id.ToString());
                                        }
                                        catch(Exception)
                                        {
                                            await client.SendMessage(currentChannel, "User does not exist. B-baka.");
                                        }
                                    }
                                    else
                                    {
                                        await client.SendMessage(currentChannel, e.Message.User.Id.ToString());
                                    }
                                }
                                else if(e.Message.Text.StartsWith(":"))
                                {
                                    await rpg.HandleCommands(e, client, currentChannel);
                                }
                                else if (await handleSimpleCommands(e, client, currentChannel) == false)
                                {
                                    await handleTiroCommands(e, client, currentChannel);
                                }
                            }

                            
                        }
                    }
                };

                //Convert our sync method to an async one and block the Main function until the bot disconnects
                client.Run(async () =>
                {
                    //Connect to the Discord server using our email and password
                    await client.Connect(Sensitive.email, Sensitive.passwd);

                    while (running)
                    {
                        var inputTask = Task.Run<string>((Func<string>)Console.ReadLine);
                        await inputTask;
                        string dbgCommand = inputTask.Result;
                        if( dbgCommand == "exit" || restart || quit)
                        {
                            running = false;
                            await client.Disconnect();
                        } else if ( dbgCommand == "listservers")
                        {
                            foreach(Server s in client.AllServers)
                            {
                                Console.WriteLine("#######################################");
                                Console.WriteLine("Servername: " + s.Name);
                                Console.WriteLine("Voicechannels: ");
                                foreach(Channel c in s.VoiceChannels)
                                {
                                    Console.WriteLine("    "+c.Name);
                                }
                                Console.WriteLine("Channels: ");
                                foreach (Channel c in s.Channels)
                                {
                                    Console.WriteLine("    "+c.Name);
                                }
                            }
                        }
                    }
                    //If we are not a member of any server, use our invite code (made beforehand in the official Discord Client)
                });
            }
            if (!restart)
            { 
                saveFiles();
            }
            else
            {
                Main(new string[] { });
            }
        }
		/// <summary> Initializes a new instance of the DiscordClient class. </summary>
		public DiscordClient(DiscordClientConfig config = null)
			: base(config ?? new DiscordClientConfig())
		{
			_rand = new Random();
			_api = new DiscordAPIClient(_config);
			if (Config.UseMessageQueue)
				_pendingMessages = new ConcurrentQueue<Message>();
			if (Config.EnableVoiceMultiserver)
				_voiceClients = new ConcurrentDictionary<string, DiscordWSClient>();

			object cacheLock = new object();
			_channels = new Channels(this, cacheLock);
			_users = new Users(this, cacheLock);
			_messages = new Messages(this, cacheLock, Config.MessageCacheLength > 0);
			_roles = new Roles(this, cacheLock);
			_servers = new Servers(this, cacheLock);
			_globalUsers = new GlobalUsers(this, cacheLock);

			_status = UserStatus.Online;

			this.Connected += async (s, e) =>
			{
				_api.CancelToken = _cancelToken;
				await SendStatus().ConfigureAwait(false);
			};

			VoiceDisconnected += (s, e) =>
			{
				var server = _servers[e.ServerId];
				if (server != null)
				{
					foreach (var member in server.Members)
					{
						if (member.IsSpeaking)
						{
							member.IsSpeaking = false;
							RaiseUserIsSpeaking(member, _channels[_voiceSocket.CurrentChannelId], false);
						}
					}
				}
			};
			
			if (_config.LogLevel >= LogMessageSeverity.Info)
			{
				ServerCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Server Created: {e.Server?.Name ?? "[Private]"}");
				ServerDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Server Destroyed: {e.Server?.Name ?? "[Private]"}");
				ServerUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Server Updated: {e.Server?.Name ?? "[Private]"}");
				ServerAvailable += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Server Available: {e.Server?.Name ?? "[Private]"}");
				ServerUnavailable += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Server Unavailable: {e.Server?.Name ?? "[Private]"}");
				ChannelCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Channel Created: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}");
				ChannelDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Channel Destroyed: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}");
				ChannelUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Channel Updated: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}");
				MessageReceived += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Message Received: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
				MessageDeleted += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Message Deleted: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
				MessageUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Message Update: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
				RoleCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Role Created: {e.Server?.Name ?? "[Private]"}/{e.Role?.Name}");
				RoleUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Role Updated: {e.Server?.Name ?? "[Private]"}/{e.Role?.Name}");
				RoleDeleted += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Role Deleted: {e.Server?.Name ?? "[Private]"}/{e.Role?.Name}");
				UserBanned += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Banned User: {e.Server?.Name ?? "[Private]" }/{e.UserId}");
				UserUnbanned += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"Unbanned User: {e.Server?.Name ?? "[Private]"}/{e.UserId}");
				UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"User Joined: {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
				UserRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"User Left: {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
				UserUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"User Updated: {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
				UserVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					$"User Updated (Voice State): {e.Server?.Name ?? "[Private]"}/{e.User.Name}");
				ProfileUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
					"Profile Updated");
			}
			if (_config.LogLevel >= LogMessageSeverity.Verbose)
			{
				UserIsTypingUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client,
					$"User Updated (Is Typing): {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.User?.Name}");
				MessageReadRemotely += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, 
					$"Read Message (Remotely): {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
				MessageSent += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, 
					$"Sent Message: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}");
				UserPresenceUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, 
					$"User Updated (Presence): {e.Server?.Name ?? "[Private]"}/{e.User?.Name}");
				
				_api.RestClient.OnRequest += (s, e) =>
				{
                    if (e.Payload != null)
						RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Rest, $"{e.Method.Method} {e.Path}: {Math.Round(e.ElapsedMilliseconds, 2)} ms ({e.Payload})");
					else
						RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Rest, $"{e.Method.Method} {e.Path}: {Math.Round(e.ElapsedMilliseconds, 2)} ms");
				};
			}
			if (_config.LogLevel >= LogMessageSeverity.Debug)
			{
				_channels.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
				_channels.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
				_channels.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Channels");
				_users.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
				_users.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
				_users.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users");
				_messages.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
				_messages.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}");
				_messages.ItemRemapped += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Remapped Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/[{e.OldId} -> {e.NewId}]");
				_messages.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Messages");
				_roles.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Role {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
				_roles.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Role {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}");
				_roles.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Roles");
				_servers.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Server {e.Item.Id}");
				_servers.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Server {e.Item.Id}");
				_servers.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Servers");
				_globalUsers.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {e.Item.Id}");
				_globalUsers.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {e.Item.Id}");
				_globalUsers.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users");
			}

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

			_serializer = new JsonSerializer();
			_serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
#if TEST_RESPONSES
			_serializer.CheckAdditionalContent = true;
			_serializer.MissingMemberHandling = MissingMemberHandling.Error;
#endif
		}
示例#7
0
		public DiscordBotClient(DiscordClientConfig config = null, Func<User, Server, int> getPermissions = null)
			: base(config)
		{
			_commands = new List<Command>();

			CommandChar = '~';
			UseCommandChar = true;
			RequireCommandCharInPublic = true;
			RequireCommandCharInPrivate = true;

			MessageCreated += async (s, e) =>
			{
				//If commands aren't being used, don't bother processing them
				if (_commands.Count == 0)
					return;

				//Ignore messages from ourselves
				if (e.Message.UserId == CurrentUserId)
					return;

				//Check for the command character
				string msg = e.Message.Text;
				if (UseCommandChar)
				{
					if (msg.Length == 0)
						return;
					bool isPrivate = e.Message.Channel.IsPrivate;
					bool hasCommandChar = msg[0] == CommandChar;
					if (hasCommandChar)
						msg = msg.Substring(1);
					if (!isPrivate && RequireCommandCharInPublic && !hasCommandChar)
						return;
					if (isPrivate && RequireCommandCharInPrivate && !hasCommandChar)
						return;
				}

				string[] args;
				if (!CommandParser.ParseArgs(msg, out args))
					return;

				for (int i = 0; i < _commands.Count; i++)
				{
					Command cmd = _commands[i];

					//Check Command Parts
					if (args.Length < cmd.Parts.Length)
						continue;

                    bool isValid = true;
					for (int j = 0; j < cmd.Parts.Length; j++)
					{
						if (!string.Equals(args[j], cmd.Parts[j], StringComparison.OrdinalIgnoreCase))
						{
							isValid = false;
							break;
						}
					}
					if (!isValid)
						continue;

					//Check Arg Count
					int argCount = args.Length - cmd.Parts.Length;
					if (argCount < cmd.MinArgs || argCount > cmd.MaxArgs)
						continue;

					//Clean Args
					string[] newArgs = new string[argCount];
					for (int j = 0; j < newArgs.Length; j++)
						newArgs[j] = args[j + cmd.Parts.Length];
					
					//Check Permissions
                    int permissions = getPermissions != null ? getPermissions(e.Message.User, e.Message.Channel?.Server) : 0;
					var eventArgs = new CommandEventArgs(e.Message, cmd, msg, permissions, newArgs);
					if (permissions < cmd.MinPerms)
					{
						RaiseCommandError(eventArgs, new PermissionException());
						return;
					}

					//Run Command					
                    RaiseRanCommand(eventArgs);
					try
					{
						var task = cmd.Handler(eventArgs);
						if (task != null)
							await task;
					}
					catch (Exception ex)
					{
						RaiseCommandError(eventArgs, ex);
					}
					break;
				}
			};
		}
示例#8
0
        public DiscordBotClient(DiscordClientConfig config = null, Func <User, Server, int> getPermissions = null)
            : base(config)
        {
            _commands = new List <Command>();

            CommandChar = '~';
            RequireCommandCharInPublic  = true;
            RequireCommandCharInPrivate = true;

            MessageCreated += async(s, e) =>
            {
                //Ignore messages from ourselves
                if (e.Message.UserId == _myId)
                {
                    return;
                }

                //Check for the command character
                string msg = e.Message.Text;
                if (UseCommandChar)
                {
                    if (msg.Length == 0)
                    {
                        return;
                    }
                    bool isPrivate      = e.Message.Channel.IsPrivate;
                    bool hasCommandChar = msg[0] == CommandChar;
                    if (hasCommandChar)
                    {
                        msg = msg.Substring(1);
                    }
                    if (!isPrivate && RequireCommandCharInPublic && !hasCommandChar)
                    {
                        return;
                    }
                    if (isPrivate && RequireCommandCharInPrivate && !hasCommandChar)
                    {
                        return;
                    }
                }

                string[] args;
                if (!CommandParser.ParseArgs(msg, out args))
                {
                    return;
                }

                for (int i = 0; i < _commands.Count; i++)
                {
                    Command cmd = _commands[i];

                    //Check Command Parts
                    if (args.Length < cmd.Parts.Length)
                    {
                        continue;
                    }

                    bool isValid = true;
                    for (int j = 0; j < cmd.Parts.Length; j++)
                    {
                        if (!string.Equals(args[j], cmd.Parts[j], StringComparison.OrdinalIgnoreCase))
                        {
                            isValid = false;
                            break;
                        }
                    }
                    if (!isValid)
                    {
                        continue;
                    }

                    //Check Arg Count
                    int argCount = args.Length - cmd.Parts.Length;
                    if (argCount < cmd.MinArgs || argCount > cmd.MaxArgs)
                    {
                        continue;
                    }

                    //Clean Args
                    string[] newArgs = new string[argCount];
                    for (int j = 0; j < newArgs.Length; j++)
                    {
                        newArgs[j] = args[j + cmd.Parts.Length];
                    }

                    //Check Permissions
                    int permissions = getPermissions != null?getPermissions(e.Message.User, e.Message.Channel?.Server) : 0;

                    var eventArgs = new CommandEventArgs(e.Message, cmd, msg, permissions, newArgs);
                    if (permissions < cmd.MinPerms)
                    {
                        RaiseCommandError(eventArgs, new PermissionException());
                        return;
                    }

                    //Run Command
                    RaiseRanCommand(eventArgs);
                    try
                    {
                        var task = cmd.Handler(eventArgs);
                        if (task != null)
                        {
                            await task;
                        }
                    }
                    catch (Exception ex)
                    {
                        RaiseCommandError(eventArgs, ex);
                    }
                    break;
                }
            };
        }
示例#9
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;
				}
			};
		}
示例#10
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;
                }
            };
        }