Beispiel #1
0
        public async Task <IEnumerable <User> > GetBans()
        {
            var response = await Client.ClientAPI.Send(new GetBansRequest(Id)).ConfigureAwait(false);

            return(response.Select(x =>
            {
                var user = new User(Client, x.Id, this);
                user.Update(x);
                return user;
            }));
        }
Beispiel #2
0
 internal void Update(InviteReference model)
 {
     if (model.Guild != null && _generatedServer != null)
     {
         _generatedServer.Update(model.Guild);
     }
     if (model.Inviter != null && _generatedInviter != null)
     {
         _generatedInviter.Update(model.Inviter);
     }
     if (model.Channel != null && _generatedChannel != null)
     {
         _generatedChannel.Update(model.Channel);
     }
 }
 public async Task<IEnumerable<User>> GetBans()
 {
     var response = await Client.ClientAPI.Send(new GetBansRequest(Id)).ConfigureAwait(false);
     return response.Select(x =>
     {
         var user = new User(Client, x.Id, this);
         user.Update(x);
         return user;
     });
 }
Beispiel #4
0
		internal override async Task OnReceivedEvent(WebSocketEventEventArgs e)
		{
			try
			{
				await base.OnReceivedEvent(e);

				switch (e.Type)
				{
					//Global
					case "READY": //Resync
						{
							var data = e.Payload.ToObject<ReadyEvent>(_serializer);
							_currentUser = _users.GetOrAdd(data.User.Id);
							_currentUser.Update(data.User);
							foreach (var model in data.Guilds)
							{
								if (!model.Unavailable)
								{
									var server = _servers.GetOrAdd(model.Id);
									server.Update(model);
								}
							}
							foreach (var model in data.PrivateChannels)
							{
								var user = _users.GetOrAdd(model.Recipient.Id);
								user.Update(model.Recipient);
								var channel = _channels.GetOrAdd(model.Id, null, user.Id);
								channel.Update(model);
							}
						}
						break;

					//Servers
					case "GUILD_CREATE":
						{
							var data = e.Payload.ToObject<GuildCreateEvent>(_serializer);
							if (!data.Unavailable)
							{
								var server = _servers.GetOrAdd(data.Id);
								server.Update(data);
								if (data.Unavailable == false)
									RaiseServerAvailable(server);
								else
									RaiseServerCreated(server);
							}
						}
						break;
					case "GUILD_UPDATE":
						{
							var data = e.Payload.ToObject<GuildUpdateEvent>(_serializer);
							var server = _servers[data.Id];
							if (server != null)
							{
								server.Update(data);
								RaiseServerUpdated(server);
							}
						}
						break;
					case "GUILD_DELETE":
						{
							var data = e.Payload.ToObject<GuildDeleteEvent>(_serializer);
							var server = _servers.TryRemove(data.Id);
							if (server != null)
							{
								if (data.Unavailable == true)
									RaiseServerAvailable(server);
								else
									RaiseServerDestroyed(server);
							}
						}
						break;

					//Channels
					case "CHANNEL_CREATE":
						{
							var data = e.Payload.ToObject<ChannelCreateEvent>(_serializer);
							Channel channel;
							if (data.IsPrivate)
							{
								var user = _users.GetOrAdd(data.Recipient.Id);
								user.Update(data.Recipient);
								channel = _channels.GetOrAdd(data.Id, null, user.Id);
							}
							else
								channel = _channels.GetOrAdd(data.Id, data.GuildId, null);
							channel.Update(data);
							RaiseChannelCreated(channel);
						}
						break;
					case "CHANNEL_UPDATE":
						{
							var data = e.Payload.ToObject<ChannelUpdateEvent>(_serializer);
							var channel = _channels[data.Id];
							if (channel != null)
							{
								channel.Update(data);
								RaiseChannelUpdated(channel);
							}
						}
						break;
					case "CHANNEL_DELETE":
						{
							var data = e.Payload.ToObject<ChannelDeleteEvent>(_serializer);
							var channel = _channels.TryRemove(data.Id);
							if (channel != null)
								RaiseChannelDestroyed(channel);
						}
						break;

					//Members
					case "GUILD_MEMBER_ADD":
						{
							var data = e.Payload.ToObject<GuildMemberAddEvent>(_serializer);
							var user = _users.GetOrAdd(data.User.Id);
							user.Update(data.User);
							var member = _members.GetOrAdd(data.User.Id, data.GuildId);
							member.Update(data);
							if (Config.TrackActivity)
								member.UpdateActivity();
							RaiseUserAdded(member);
						}
						break;
					case "GUILD_MEMBER_UPDATE":
						{
							var data = e.Payload.ToObject<GuildMemberUpdateEvent>(_serializer);
							var member = _members[data.User.Id, data.GuildId];
							if (member != null)
							{
								member.Update(data);
								RaiseMemberUpdated(member);
							}
						}
						break;
					case "GUILD_MEMBER_REMOVE":
						{
							var data = e.Payload.ToObject<GuildMemberRemoveEvent>(_serializer);
							var member = _members.TryRemove(data.UserId, data.GuildId);
							if (member != null)
								RaiseUserRemoved(member);
						}
						break;

					//Roles
					case "GUILD_ROLE_CREATE":
						{
							var data = e.Payload.ToObject<GuildRoleCreateEvent>(_serializer);
							var role = _roles.GetOrAdd(data.Data.Id, data.GuildId, false);
							role.Update(data.Data);
							var server = _servers[data.GuildId];
							if (server != null)
								server.AddRole(data.Data.Id);
							RaiseRoleUpdated(role);
						}
						break;
					case "GUILD_ROLE_UPDATE":
						{
							var data = e.Payload.ToObject<GuildRoleUpdateEvent>(_serializer);
							var role = _roles[data.Data.Id];
							if (role != null)
								role.Update(data.Data);
							RaiseRoleUpdated(role);
						}
						break;
					case "GUILD_ROLE_DELETE":
						{
							var data = e.Payload.ToObject<GuildRoleDeleteEvent>(_serializer);
							var server = _servers[data.GuildId];
							if (server != null)
								server.RemoveRole(data.RoleId);
							var role = _roles.TryRemove(data.RoleId);
							if (role != null)
								RaiseRoleDeleted(role);
						}
						break;

					//Bans
					case "GUILD_BAN_ADD":
						{
							var data = e.Payload.ToObject<GuildBanAddEvent>(_serializer);
							var server = _servers[data.GuildId];
							if (server != null)
							{
								server.AddBan(data.User?.Id);
								RaiseBanAdded(data.User?.Id, server);
							}
						}
						break;
					case "GUILD_BAN_REMOVE":
						{
							var data = e.Payload.ToObject<GuildBanRemoveEvent>(_serializer);
							var server = _servers[data.GuildId];
							if (server != null && server.RemoveBan(data.User?.Id))
								RaiseBanRemoved(data.User?.Id, server);
						}
						break;

					//Messages
					case "MESSAGE_CREATE":
						{
							var data = e.Payload.ToObject<MessageCreateEvent>(_serializer);
							Message msg = null;

							bool isAuthor = data.Author.Id == CurrentUserId;
                            bool hasFinishedSending = false;
							if (Config.UseMessageQueue && isAuthor && data.Nonce != null)
							{
								msg = _messages.Remap("nonce" + data.Nonce, data.Id);
								if (msg != null)
								{
									msg.IsQueued = false;
									msg.Id = data.Id;
									hasFinishedSending = true;
                                }
							}

							if (msg == null)
								msg = _messages.GetOrAdd(data.Id, data.ChannelId, data.Author.Id);
							msg.Update(data);
							if (Config.TrackActivity)
							{
								var channel = msg.Channel;
								if (channel == null || channel.IsPrivate)
								{
									var user = msg.User;
									if (user != null)
										user.UpdateActivity(data.Timestamp);
								}
								else
								{
									var member = msg.Member;
									if (member != null)
										member.UpdateActivity(data.Timestamp);
								}
							}

							if (Config.AckMessages && isAuthor)
								await _api.AckMessage(data.Id, data.ChannelId);

							if (hasFinishedSending)
								RaiseMessageSent(msg);
							RaiseMessageCreated(msg);
						}
						break;
					case "MESSAGE_UPDATE":
						{
							var data = e.Payload.ToObject<MessageUpdateEvent>(_serializer);
							var msg = _messages[data.Id];
							if (msg != null)
							{
								msg.Update(data);
								RaiseMessageUpdated(msg);
							}
						}
						break;
					case "MESSAGE_DELETE":
						{
							var data = e.Payload.ToObject<MessageDeleteEvent>(_serializer);
							var msg = _messages.TryRemove(data.Id);
							if (msg != null)
								RaiseMessageDeleted(msg);
						}
						break;
					case "MESSAGE_ACK":
						{
							var data = e.Payload.ToObject<MessageAckEvent>(_serializer);
							var msg = GetMessage(data.MessageId);
							if (msg != null)
								RaiseMessageReadRemotely(msg);
						}
						break;

					//Statuses
					case "PRESENCE_UPDATE":
						{
							var data = e.Payload.ToObject<PresenceUpdateEvent>(_serializer);
							var member = _members[data.User.Id, data.GuildId];
							/*if (_config.TrackActivity)
							{
								var user = _users[data.User.Id];
								if (user != null)
									user.UpdateActivity(DateTime.UtcNow);
							}*/
							if (member != null)
							{
								member.Update(data);
								RaiseUserPresenceUpdated(member);
							}
						}
						break;
					case "TYPING_START":
						{
							var data = e.Payload.ToObject<TypingStartEvent>(_serializer);
							var channel = _channels[data.ChannelId];
							var user = _users[data.UserId];

							if (user != null)
							{
								if (channel != null)
									RaiseUserIsTyping(user, channel);
							}
							if (Config.TrackActivity)
							{
								if (channel.IsPrivate)
								{
									if (user != null)
										user.UpdateActivity();
								}
								else
								{
									var member = _members[data.UserId, channel.ServerId];
									if (member != null)
										member.UpdateActivity();
								}
							}
						}
						break;

					//Voice
					case "VOICE_STATE_UPDATE":
						{
							var data = e.Payload.ToObject<VoiceStateUpdateEvent>(_serializer);
							var member = _members[data.UserId, data.GuildId];
							if (member != null)
							{
								if (data.ChannelId != member.VoiceChannelId && member.IsSpeaking)
								{
									member.IsSpeaking = false;
									RaiseUserIsSpeaking(member, false);
								}
								member.Update(data);
								RaiseUserVoiceStateUpdated(member);
							}
						}
						break;

					//Settings
					case "USER_UPDATE":
						{
							var data = e.Payload.ToObject<UserUpdateEvent>(_serializer);
							var user = _users[data.Id];
							if (user != null)
							{
								user.Update(data);
								RaiseUserUpdated(user);
							}
						}
						break;
					case "USER_SETTINGS_UPDATE":
						{
							//TODO: Process this
						}
						break;

					//Internal (handled in DataWebSocket)
					case "RESUMED":
						break;

					//Internal (handled in DiscordSimpleClient)
					case "VOICE_SERVER_UPDATE":
						break;

					//Others
					default:
						RaiseOnLog(LogMessageSeverity.Warning, LogMessageSource.DataWebSocket, $"Unknown message type: {e.Type}");
						break;
				}
			}
			catch (Exception ex)
			{
				RaiseOnLog(LogMessageSeverity.Error, LogMessageSource.Client, $"Error handling {e.Type} event: {ex.GetBaseException().Message}");
			}
		}
        private void OnReceivedEvent(WebSocketEventEventArgs e)
        {
            try
            {
                switch (e.Type)
                {
                    //Global
                    case "READY":
                        {
                            Stopwatch stopwatch = null;
                            if (Config.LogLevel >= LogSeverity.Verbose)
                                stopwatch = Stopwatch.StartNew();
                            var data = e.Payload.ToObject<ReadyEvent>(_serializer);
                            GatewaySocket.StartHeartbeat(data.HeartbeatInterval);
                            GatewaySocket.SessionId = data.SessionId;
                            SessionId = data.SessionId;
                            PrivateUser = new User(this, data.User.Id, null);
                            PrivateUser.Update(data.User);
                            CurrentUser = new Profile(this, data.User.Id);
                            CurrentUser.Update(data.User);
                            foreach (var model in data.Guilds)
                            {
                                if (model.Unavailable != true)
                                {
                                    var server = AddServer(model.Id);
                                    server.Update(model);
                                }
                            }
                            foreach (var model in data.PrivateChannels)
                            {
                                var channel = AddPrivateChannel(model.Id, model.Recipient.Id);
                                channel.Update(model);
                            }
                            if (Config.LogLevel >= LogSeverity.Verbose)
                            {
                                stopwatch.Stop();
                                double seconds = Math.Round(stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerSecond, 2);
                                Logger.Verbose($"READY took {seconds} sec");
                            }
                        }
                        break;
                    case "RESUMED":
                        {
                            var data = e.Payload.ToObject<ResumedEvent>(_serializer);
                            GatewaySocket.StartHeartbeat(data.HeartbeatInterval);
                        }
                        break;

                    //Servers
                    case "GUILD_CREATE":
                        {
                            var data = e.Payload.ToObject<GuildCreateEvent>(_serializer);
                            if (data.Unavailable != true)
                            {
                                var server = AddServer(data.Id);
                                server.Update(data);

                                if (Config.LogEvents)
                                {
                                    if (data.Unavailable != false)
                                        Logger.Info($"Server Created: {server.Name}");
                                    else
                                        Logger.Info($"Server Available: {server.Name}");
                                }

                                if (data.Unavailable != false)
                                    OnJoinedServer(server);
                                OnServerAvailable(server);
                            }
                        }
                        break;
                    case "GUILD_UPDATE":
                        {
                            var data = e.Payload.ToObject<GuildUpdateEvent>(_serializer);
                            var server = GetServer(data.Id);
                            if (server != null)
                            {
                                server.Update(data);
                                if (Config.LogEvents)
                                    Logger.Info($"Server Updated: {server.Name}");
                                OnServerUpdated(server);
                            }
                            else
                                Logger.Warning("GUILD_UPDATE referenced an unknown guild.");
                        }
                        break;
                    case "GUILD_DELETE":
                        {
                            var data = e.Payload.ToObject<GuildDeleteEvent>(_serializer);
                            Server server = RemoveServer(data.Id);
                            if (server != null)
                            {
                                if (Config.LogEvents)
                                {
                                    if (data.Unavailable != true)
                                        Logger.Info($"Server Destroyed: {server.Name}");
                                    else
                                        Logger.Info($"Server Unavailable: {server.Name}");
                                }

                                OnServerUnavailable(server);
                                if (data.Unavailable != true)
                                    OnLeftServer(server);
                            }
                            else
                                Logger.Warning("GUILD_DELETE referenced an unknown guild.");
                        }
                        break;

                    //Channels
                    case "CHANNEL_CREATE":
                        {
                            var data = e.Payload.ToObject<ChannelCreateEvent>(_serializer);

                            Channel channel = null;
                            if (data.GuildId != null)
                            {
                                var server = GetServer(data.GuildId.Value);
                                if (server != null)
                                    channel = server.AddChannel(data.Id);
                                else
                                    Logger.Warning("CHANNEL_CREATE referenced an unknown guild.");
                            }
                            else
                                channel = AddPrivateChannel(data.Id, data.Recipient.Id);
                            if (channel != null)
                            {
                                channel.Update(data);
                                if (Config.LogEvents)
                                    Logger.Info($"Channel Created: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
                                OnChannelCreated(channel);
                            }
                        }
                        break;
                    case "CHANNEL_UPDATE":
                        {
                            var data = e.Payload.ToObject<ChannelUpdateEvent>(_serializer);
                            var channel = GetChannel(data.Id);
                            if (channel != null)
                            {
                                channel.Update(data);
                                if (Config.LogEvents)
                                    Logger.Info($"Channel Updated: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
                                OnChannelUpdated(channel);
                            }
                            else
                                Logger.Warning("CHANNEL_UPDATE referenced an unknown channel.");
                        }
                        break;
                    case "CHANNEL_DELETE":
                        {
                            var data = e.Payload.ToObject<ChannelDeleteEvent>(_serializer);
                            var channel = RemoveChannel(data.Id);
                            if (channel != null)
                            {
                                if (Config.LogEvents)
                                    Logger.Info($"Channel Destroyed: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
                                OnChannelDestroyed(channel);
                            }
                            else
                                Logger.Warning("CHANNEL_DELETE referenced an unknown channel.");
                        }
                        break;

                    //Members
                    case "GUILD_MEMBER_ADD":
                        {
                            var data = e.Payload.ToObject<GuildMemberAddEvent>(_serializer);
                            var server = GetServer(data.GuildId.Value);
                            if (server != null)
                            {
                                var user = server.AddUser(data.User.Id);
                                user.Update(data);
                                user.UpdateActivity();
                                if (Config.LogEvents)
                                    Logger.Info($"User Joined: {server.Name}/{user.Name}");
                                OnUserJoined(user);
                            }
                            else
                                Logger.Warning("GUILD_MEMBER_ADD referenced an unknown guild.");
                        }
                        break;
                    case "GUILD_MEMBER_UPDATE":
                        {
                            var data = e.Payload.ToObject<GuildMemberUpdateEvent>(_serializer);
                            var server = GetServer(data.GuildId.Value);
                            if (server != null)
                            {
                                var user = server.GetUser(data.User.Id);
                                if (user != null)
                                {
                                    user.Update(data);
                                    if (Config.LogEvents)
                                        Logger.Info($"User Updated: {server.Name}/{user.Name}");
                                    OnUserUpdated(user);
                                }
                                else
                                    Logger.Warning("GUILD_MEMBER_UPDATE referenced an unknown user.");
                            }
                            else
                                Logger.Warning("GUILD_MEMBER_UPDATE referenced an unknown guild.");
                        }
                        break;
                    case "GUILD_MEMBER_REMOVE":
                        {
                            var data = e.Payload.ToObject<GuildMemberRemoveEvent>(_serializer);
                            var server = GetServer(data.GuildId.Value);
                            if (server != null)
                            {
                                var user = server.RemoveUser(data.User.Id);
                                if (user != null)
                                {
                                    if (Config.LogEvents)
                                        Logger.Info($"User Left: {server.Name}/{user.Name}");
                                    OnUserLeft(user);
                                }
                                else
                                    Logger.Warning("GUILD_MEMBER_REMOVE referenced an unknown user.");
                            }
                            else
                                Logger.Warning("GUILD_MEMBER_REMOVE referenced an unknown guild.");
                        }
                        break;
                    case "GUILD_MEMBERS_CHUNK":
                        {
                            var data = e.Payload.ToObject<GuildMembersChunkEvent>(_serializer);
                            var server = GetServer(data.GuildId);
                            if (server != null)
                            {
                                foreach (var memberData in data.Members)
                                {
                                    var user = server.AddUser(memberData.User.Id);
                                    user.Update(memberData);
                                    //OnUserAdded(user);
                                }
                            }
                            else
                                Logger.Warning("GUILD_MEMBERS_CHUNK referenced an unknown guild.");
                        }
                        break;

                    //Roles
                    case "GUILD_ROLE_CREATE":
                        {
                            var data = e.Payload.ToObject<GuildRoleCreateEvent>(_serializer);
                            var server = GetServer(data.GuildId);
                            if (server != null)
                            {
                                var role = server.AddRole(data.Data.Id);
                                role.Update(data.Data);
                                if (Config.LogEvents)
                                    Logger.Info($"Role Created: {server.Name}/{role.Name}");
                                OnRoleUpdated(role);
                            }
                            else
                                Logger.Warning("GUILD_ROLE_CREATE referenced an unknown guild.");
                        }
                        break;
                    case "GUILD_ROLE_UPDATE":
                        {
                            var data = e.Payload.ToObject<GuildRoleUpdateEvent>(_serializer);
                            var server = GetServer(data.GuildId);
                            if (server != null)
                            {
                                var role = server.GetRole(data.Data.Id);
                                if (role != null)
                                {
                                    role.Update(data.Data);
                                    if (Config.LogEvents)
                                        Logger.Info($"Role Updated: {server.Name}/{role.Name}");
                                    OnRoleUpdated(role);
                                }
                                else
                                    Logger.Warning("GUILD_ROLE_UPDATE referenced an unknown role.");
                            }
                            else
                                Logger.Warning("GUILD_ROLE_UPDATE referenced an unknown guild.");
                        }
                        break;
                    case "GUILD_ROLE_DELETE":
                        {
                            var data = e.Payload.ToObject<GuildRoleDeleteEvent>(_serializer);
                            var server = GetServer(data.GuildId);
                            if (server != null)
                            {
                                var role = server.RemoveRole(data.RoleId);
                                if (role != null)
                                {
                                    if (Config.LogEvents)
                                        Logger.Info($"Role Deleted: {server.Name}/{role.Name}");
                                    OnRoleDeleted(role);
                                }
                                else
                                    Logger.Warning("GUILD_ROLE_DELETE referenced an unknown role.");
                            }
                            else
                                Logger.Warning("GUILD_ROLE_DELETE referenced an unknown guild.");
                        }
                        break;

                    //Bans
                    case "GUILD_BAN_ADD":
                        {
                            var data = e.Payload.ToObject<GuildBanAddEvent>(_serializer);
                            var server = GetServer(data.GuildId.Value);
                            if (server != null)
                            {
                                var user = server.GetUser(data.User.Id);
                                if (user != null)
                                {
                                    if (Config.LogEvents)
                                        Logger.Info($"User Banned: {server.Name}/{user.Name}");
                                    OnUserBanned(user);
                                }
                                else
                                    Logger.Warning("GUILD_BAN_ADD referenced an unknown user.");
                            }
                            else
                                Logger.Warning("GUILD_BAN_ADD referenced an unknown guild.");
                        }
                        break;
                    case "GUILD_BAN_REMOVE":
                        {
                            var data = e.Payload.ToObject<GuildBanRemoveEvent>(_serializer);
                            var server = GetServer(data.GuildId.Value);
                            if (server != null)
                            {
                                var user = new User(this, data.User.Id, server);
                                user.Update(data.User);
                                if (Config.LogEvents)
                                    Logger.Info($"User Unbanned: {server.Name}/{user.Name}");
                                OnUserUnbanned(user);
                            }
                            else
                                Logger.Warning("GUILD_BAN_REMOVE referenced an unknown guild.");
                        }
                        break;

                    //Messages
                    case "MESSAGE_CREATE":
                        {
                            var data = e.Payload.ToObject<MessageCreateEvent>(_serializer);

                            Channel channel = GetChannel(data.ChannelId);
                            if (channel != null)
                            {
                                var user = channel.GetUser(data.Author.Id);
                                if (user != null)
                                {
                                    Message msg = null;
                                    bool isAuthor = data.Author.Id == CurrentUser.Id;
                                    //ulong nonce = 0;

                                    /*if (data.Author.Id == _privateUser.Id && Config.UseMessageQueue)
                                    {
                                        if (data.Nonce != null && ulong.TryParse(data.Nonce, out nonce))
                                            msg = _messages[nonce];
                                    }*/
                                    if (msg == null)
                                    {
                                        msg = channel.AddMessage(data.Id, user, data.Timestamp.Value);
                                        //nonce = 0;
                                    }

                                    //Remapped queued message
                                    /*if (nonce != 0)
                                    {
                                        msg = _messages.Remap(nonce, data.Id);
                                        msg.Id = data.Id;
                                        RaiseMessageSent(msg);
                                    }*/

                                    msg.Update(data);
                                    user.UpdateActivity();

                                    msg.State = MessageState.Normal;
                                    if (Config.LogEvents)
                                        Logger.Verbose($"Message Received: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
                                    OnMessageReceived(msg);
                                }
                            }
                            else
                                Logger.Warning("MESSAGE_CREATE referenced an unknown channel.");
                        }
                        break;
                    case "MESSAGE_UPDATE":
                        {
                            if (Config.MessageCacheSize > 0)
                            {
                                var data = e.Payload.ToObject<MessageUpdateEvent>(_serializer);
                                var channel = GetChannel(data.ChannelId);
                                if (channel != null)
                                {
                                    var msg = channel.GetMessage(data.Id);
                                    if (msg != null)
                                    {
                                        msg.Update(data);
                                        msg.State = MessageState.Normal;
                                        if (Config.LogEvents)
                                            Logger.Info($"Message Update: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
                                        OnMessageUpdated(msg);
                                    }
                                }
                                else
                                    Logger.Warning("MESSAGE_UPDATE referenced an unknown channel.");
                            }
                        }
                        break;
                    case "MESSAGE_DELETE":
                        {
                            if (Config.MessageCacheSize > 0)
                            {
                                var data = e.Payload.ToObject<MessageDeleteEvent>(_serializer);
                                var channel = GetChannel(data.ChannelId);
                                if (channel != null)
                                {
                                    var msg = channel.RemoveMessage(data.Id);
                                    if (msg != null)
                                    {
                                        if (Config.LogEvents)
                                            Logger.Info($"Message Deleted: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
                                        OnMessageDeleted(msg);
                                    }
                                }
                                else
                                    Logger.Warning("MESSAGE_DELETE referenced an unknown channel.");
                            }
                        }
                        break;
                    case "MESSAGE_ACK":
                        {
                            if (Config.MessageCacheSize > 0)
                            {
                                var data = e.Payload.ToObject<MessageAckEvent>(_serializer);
                                var channel = GetChannel(data.ChannelId);
                                if (channel != null)
                                {
                                    var msg = channel.GetMessage(data.MessageId);
                                    if (msg != null)
                                    {
                                        if (Config.LogEvents)
                                            Logger.Verbose($"Message Ack: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
                                        OnMessageAcknowledged(msg);
                                    }
                                }
                                else
                                    Logger.Warning("MESSAGE_ACK referenced an unknown channel.");
                            }
                        }
                        break;

                    //Statuses
                    case "PRESENCE_UPDATE":
                        {
                            var data = e.Payload.ToObject<PresenceUpdateEvent>(_serializer);
                            User user;
                            Server server;
                            if (data.GuildId == null)
                            {
                                server = null;
                                user = GetPrivateChannel(data.User.Id)?.Recipient;
                            }
                            else
                            {
                                server = GetServer(data.GuildId.Value);
                                if (server == null)
                                {
                                    Logger.Warning("PRESENCE_UPDATE referenced an unknown server.");
                                    break;
                                }
                                else
                                {
                                    if (Config.UseLargeThreshold)
                                        user = server.AddUser(data.User.Id);
                                    else
                                        user = server.GetUser(data.User.Id);
                                }
                            }

                            if (user != null)
                            {
                                user.Update(data);
                                //Logger.Verbose($"Presence Updated: {server.Name}/{user.Name}");
                                OnUserPresenceUpdated(user);
                            }
                            /*else //Occurs when a user leaves a server
                                Logger.Warning("PRESENCE_UPDATE referenced an unknown user.");*/
                        }
                        break;
                    case "TYPING_START":
                        {
                            var data = e.Payload.ToObject<TypingStartEvent>(_serializer);
                            var channel = GetChannel(data.ChannelId);
                            if (channel != null)
                            {
                                User user;
                                if (channel.IsPrivate)
                                {
                                    if (channel.Recipient.Id == data.UserId)
                                        user = channel.Recipient;
                                    else
                                        return; ;
                                }
                                else
                                    user = channel.Server.GetUser(data.UserId);
                                if (user != null)
                                {
                                    //Logger.Verbose($"Is Typing: {channel.Server?.Name ?? "[Private]"}/{channel.Name}/{user.Name}");
                                    OnUserIsTypingUpdated(channel, user);
                                    user.UpdateActivity();
                                }
                            }
                            else
                                Logger.Warning("TYPING_START referenced an unknown channel.");
                        }
                        break;

                    //Voice
                    case "VOICE_STATE_UPDATE":
                        {
                            var data = e.Payload.ToObject<VoiceStateUpdateEvent>(_serializer);
                            var server = GetServer(data.GuildId);
                            if (server != null)
                            {
                                var user = server.GetUser(data.UserId);
                                if (user != null)
                                {
                                    user.Update(data);
                                    //Logger.Verbose($"Voice Updated: {server.Name}/{user.Name}");
                                    OnUserVoiceStateUpdated(user);
                                }
                                /*else //Occurs when a user leaves a server
                                    Logger.Warning("VOICE_STATE_UPDATE referenced an unknown user.");*/
                            }
                            else
                                Logger.Warning("VOICE_STATE_UPDATE referenced an unknown server.");
                        }
                        break;

                    //Settings
                    case "USER_UPDATE":
                        {
                            var data = e.Payload.ToObject<UserUpdateEvent>(_serializer);
                            if (data.Id == CurrentUser.Id)
                            {
                                CurrentUser.Update(data);
                                PrivateUser.Update(data);
                                foreach (var server in _servers)
                                    server.Value.CurrentUser.Update(data);
                                if (Config.LogEvents)
                                    Logger.Info("Profile Updated");
                                OnProfileUpdated(CurrentUser);
                            }
                        }
                        break;

                    //Ignored
                    case "USER_SETTINGS_UPDATE":
                    case "GUILD_INTEGRATIONS_UPDATE":
                    case "VOICE_SERVER_UPDATE":
                    case "GUILD_EMOJIS_UPDATE":
                        break;

                    //Others
                    default:
                        Logger.Warning($"Unknown message type: {e.Type}");
                        break;
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"Error handling {e.Type} event", ex);
            }
        }
Beispiel #6
0
        private void OnReceivedEvent(WebSocketEventEventArgs e)
        {
            try
            {
                switch (e.Type)
                {
                //Global
                case "READY":
                {
                    //TODO: None of this is really threadsafe - should only replace the cache collections when they have been fully populated

                    var data = e.Payload.ToObject <ReadyEvent>(Serializer);

                    int channelCount = 0;
                    for (int i = 0; i < data.Guilds.Length; i++)
                    {
                        channelCount += data.Guilds[i].Channels.Length;
                    }

                    //ConcurrencyLevel = 2 (only REST and WebSocket can add/remove)
                    _servers         = new ConcurrentDictionary <ulong, Server>(2, (int)(data.Guilds.Length * 1.05));
                    _channels        = new ConcurrentDictionary <ulong, IChannel>(2, (int)(channelCount * 1.05));
                    _privateChannels = new ConcurrentDictionary <ulong, PrivateChannel>(2, (int)(data.PrivateChannels.Length * 1.05));
                    List <ulong> largeServers = new List <ulong>();

                    SessionId   = data.SessionId;
                    PrivateUser = new User(data.User, this, null);
                    PrivateUser.Update(data.User);
                    CurrentUser = new Profile(data.User, this);
                    CurrentUser.Update(data.User);

                    for (int i = 0; i < data.Guilds.Length; i++)
                    {
                        var model = data.Guilds[i];
                        if (model.Unavailable != true)
                        {
                            var server = AddServer(model.Id);
                            server.Update(model);
                            if (model.IsLarge)
                            {
                                largeServers.Add(server.Id);
                            }
                        }
                    }
                    for (int i = 0; i < data.PrivateChannels.Length; i++)
                    {
                        AddPrivateChannel(data.PrivateChannels[i]);
                    }
                    if (largeServers.Count > 0)
                    {
                        GatewaySocket.SendRequestMembers(largeServers, "", 0);
                    }
                    else
                    {
                        EndConnect();
                    }
                }
                break;

                //Servers
                case "GUILD_CREATE":
                {
                    var data = e.Payload.ToObject <GuildCreateEvent>(Serializer);
                    if (data.Unavailable != true)
                    {
                        var server = AddServer(data.Id);
                        server.Update(data);

                        if (data.Unavailable != false)
                        {
                            Logger.Info($"GUILD_CREATE: {server}");
                        }
                        else
                        {
                            Logger.Info($"GUILD_AVAILABLE: {server}");
                        }

                        if (data.Unavailable != false)
                        {
                            OnJoinedServer(server);
                        }
                        OnServerAvailable(server);
                    }
                }
                break;

                case "GUILD_UPDATE":
                {
                    var data   = e.Payload.ToObject <GuildUpdateEvent>(Serializer);
                    var server = GetServer(data.Id);
                    if (server != null)
                    {
                        var before = Config.EnablePreUpdateEvents ? server.Clone() : null;
                        server.Update(data);
                        Logger.Info($"GUILD_UPDATE: {server}");
                        OnServerUpdated(before, server);
                    }
                    else
                    {
                        Logger.Warning("GUILD_UPDATE referenced an unknown guild.");
                    }
                }
                break;

                case "GUILD_DELETE":
                {
                    var    data   = e.Payload.ToObject <GuildDeleteEvent>(Serializer);
                    Server server = RemoveServer(data.Id);
                    if (server != null)
                    {
                        if (data.Unavailable != true)
                        {
                            Logger.Info($"GUILD_DELETE: {server}");
                        }
                        else
                        {
                            Logger.Info($"GUILD_UNAVAILABLE: {server}");
                        }

                        OnServerUnavailable(server);
                        if (data.Unavailable != true)
                        {
                            OnLeftServer(server);
                        }
                    }
                    else
                    {
                        Logger.Warning("GUILD_DELETE referenced an unknown guild.");
                    }
                }
                break;

                //Channels
                case "CHANNEL_CREATE":
                {
                    var data = e.Payload.ToObject <ChannelCreateEvent>(Serializer);

                    IChannel channel = null;
                    if (data.GuildId != null)
                    {
                        var server = GetServer(data.GuildId.Value);
                        if (server != null)
                        {
                            channel = server.AddChannel(data, true);
                        }
                        else
                        {
                            Logger.Warning("CHANNEL_CREATE referenced an unknown guild.");
                            break;
                        }
                    }
                    else
                    {
                        channel = AddPrivateChannel(data);
                    }
                    Logger.Info($"CHANNEL_CREATE: {channel}");
                    OnChannelCreated(channel);
                }
                break;

                case "CHANNEL_UPDATE":
                {
                    var data    = e.Payload.ToObject <ChannelUpdateEvent>(Serializer);
                    var channel = GetChannel(data.Id);
                    if (channel != null)
                    {
                        var before = Config.EnablePreUpdateEvents ? (channel as Channel).Clone() : null;
                        (channel as Channel).Update(data);
                        Logger.Info($"CHANNEL_UPDATE: {channel}");
                        OnChannelUpdated(before, channel);
                    }
                    else
                    {
                        Logger.Warning("CHANNEL_UPDATE referenced an unknown channel.");
                    }
                }
                break;

                case "CHANNEL_DELETE":
                {
                    var data    = e.Payload.ToObject <ChannelDeleteEvent>(Serializer);
                    var channel = RemoveChannel(data.Id);
                    if (channel != null)
                    {
                        Logger.Info($"CHANNEL_DELETE: {channel}");
                        OnChannelDestroyed(channel);
                    }
                    else
                    {
                        Logger.Warning("CHANNEL_DELETE referenced an unknown channel.");
                    }
                }
                break;

                //Members
                case "GUILD_MEMBER_ADD":
                {
                    var data   = e.Payload.ToObject <GuildMemberAddEvent>(Serializer);
                    var server = GetServer(data.GuildId.Value);
                    if (server != null)
                    {
                        var user = server.AddUser(data, true, true);
                        user.Update(data);
                        user.UpdateActivity();
                        Logger.Info($"GUILD_MEMBER_ADD: {user}");
                        OnUserJoined(user);
                    }
                    else
                    {
                        Logger.Warning("GUILD_MEMBER_ADD referenced an unknown guild.");
                    }
                }
                break;

                case "GUILD_MEMBER_UPDATE":
                {
                    var data   = e.Payload.ToObject <GuildMemberUpdateEvent>(Serializer);
                    var server = GetServer(data.GuildId.Value);
                    if (server != null)
                    {
                        var user = server.GetUser(data.User.Id);
                        if (user != null)
                        {
                            var before = Config.EnablePreUpdateEvents ? user.Clone() : null;
                            user.Update(data);
                            Logger.Info($"GUILD_MEMBER_UPDATE: {user}");
                            OnUserUpdated(before, user);
                        }
                        else
                        {
                            Logger.Warning("GUILD_MEMBER_UPDATE referenced an unknown user.");
                        }
                    }
                    else
                    {
                        Logger.Warning("GUILD_MEMBER_UPDATE referenced an unknown guild.");
                    }
                }
                break;

                case "GUILD_MEMBER_REMOVE":
                {
                    var data   = e.Payload.ToObject <GuildMemberRemoveEvent>(Serializer);
                    var server = GetServer(data.GuildId.Value);
                    if (server != null)
                    {
                        var user = server.RemoveUser(data.User.Id);
                        if (user != null)
                        {
                            Logger.Info($"GUILD_MEMBER_REMOVE: {user}");
                            OnUserLeft(user);
                        }
                        else
                        {
                            Logger.Warning("GUILD_MEMBER_REMOVE referenced an unknown user.");
                        }
                    }
                    else
                    {
                        Logger.Warning("GUILD_MEMBER_REMOVE referenced an unknown guild.");
                    }
                }
                break;

                case "GUILD_MEMBERS_CHUNK":
                {
                    var data   = e.Payload.ToObject <GuildMembersChunkEvent>(Serializer);
                    var server = GetServer(data.GuildId);
                    if (server != null)
                    {
                        foreach (var memberData in data.Members)
                        {
                            var user = server.AddUser(memberData, true, false);
                            user.Update(memberData);
                        }
                        Logger.Verbose($"GUILD_MEMBERS_CHUNK: {data.Members.Length} users");

                        if (server.CurrentUserCount >= server.UserCount)         //Finished downloading for there
                        {
                            bool isConnectComplete = true;
                            foreach (var server2 in _servers.Select(x => x.Value))
                            {
                                if (server2.CurrentUserCount < server2.UserCount)
                                {
                                    isConnectComplete = false;
                                }
                            }
                            if (isConnectComplete)
                            {
                                EndConnect();
                            }
                        }
                    }
                    else
                    {
                        Logger.Warning("GUILD_MEMBERS_CHUNK referenced an unknown guild.");
                    }
                }
                break;

                //Roles
                case "GUILD_ROLE_CREATE":
                {
                    var data   = e.Payload.ToObject <GuildRoleCreateEvent>(Serializer);
                    var server = GetServer(data.GuildId);
                    if (server != null)
                    {
                        var role = server.AddRole(data.Data.Id);
                        role.Update(data.Data, false);
                        Logger.Info($"GUILD_ROLE_CREATE: {role}");
                        OnRoleCreated(role);
                    }
                    else
                    {
                        Logger.Warning("GUILD_ROLE_CREATE referenced an unknown guild.");
                    }
                }
                break;

                case "GUILD_ROLE_UPDATE":
                {
                    var data   = e.Payload.ToObject <GuildRoleUpdateEvent>(Serializer);
                    var server = GetServer(data.GuildId);
                    if (server != null)
                    {
                        var role = server.GetRole(data.Data.Id);
                        if (role != null)
                        {
                            var before = Config.EnablePreUpdateEvents ? role.Clone() : null;
                            role.Update(data.Data, true);
                            Logger.Info($"GUILD_ROLE_UPDATE: {role}");
                            OnRoleUpdated(before, role);
                        }
                        else
                        {
                            Logger.Warning("GUILD_ROLE_UPDATE referenced an unknown role.");
                        }
                    }
                    else
                    {
                        Logger.Warning("GUILD_ROLE_UPDATE referenced an unknown guild.");
                    }
                }
                break;

                case "GUILD_ROLE_DELETE":
                {
                    var data   = e.Payload.ToObject <GuildRoleDeleteEvent>(Serializer);
                    var server = GetServer(data.GuildId);
                    if (server != null)
                    {
                        var role = server.RemoveRole(data.RoleId);
                        if (role != null)
                        {
                            Logger.Info($"GUILD_ROLE_DELETE: {role}");
                            OnRoleDeleted(role);
                        }
                        else
                        {
                            Logger.Warning("GUILD_ROLE_DELETE referenced an unknown role.");
                        }
                    }
                    else
                    {
                        Logger.Warning("GUILD_ROLE_DELETE referenced an unknown guild.");
                    }
                }
                break;

                //Bans
                case "GUILD_BAN_ADD":
                {
                    var data   = e.Payload.ToObject <GuildBanAddEvent>(Serializer);
                    var server = GetServer(data.GuildId.Value);
                    if (server != null)
                    {
                        var user = server.GetUser(data.User.Id);
                        if (user != null)
                        {
                            Logger.Info($"GUILD_BAN_ADD: {user}");
                            OnUserBanned(user);
                        }
                        else
                        {
                            Logger.Warning("GUILD_BAN_ADD referenced an unknown user.");
                        }
                    }
                    else
                    {
                        Logger.Warning("GUILD_BAN_ADD referenced an unknown guild.");
                    }
                }
                break;

                case "GUILD_BAN_REMOVE":
                {
                    var data   = e.Payload.ToObject <GuildBanRemoveEvent>(Serializer);
                    var server = GetServer(data.GuildId.Value);
                    if (server != null)
                    {
                        var user = new User(data.User, this, server);
                        user.Update(data.User);
                        Logger.Info($"GUILD_BAN_REMOVE: {user}");
                        OnUserUnbanned(user);
                    }
                    else
                    {
                        Logger.Warning("GUILD_BAN_REMOVE referenced an unknown guild.");
                    }
                }
                break;

                //Messages
                case "MESSAGE_CREATE":
                {
                    var data = e.Payload.ToObject <MessageCreateEvent>(Serializer);

                    var channel = GetChannel(data.ChannelId) as ITextChannel;
                    if (channel != null)
                    {
                        var user = (channel as Channel).GetUser(data.Author.Id);

                        if (user != null)
                        {
                            Message msg = null;
                            msg = (channel as Channel).MessageManager.Add(data, user);
                            user.UpdateActivity();

                            Logger.Verbose($"MESSAGE_CREATE: {channel} ({user})");
                            OnMessageReceived(msg);
                        }
                        else
                        {
                            Logger.Warning("MESSAGE_CREATE referenced an unknown user.");
                        }
                    }
                    else
                    {
                        Logger.Warning("MESSAGE_CREATE referenced an unknown channel.");
                    }
                }
                break;

                case "MESSAGE_UPDATE":
                {
                    var data    = e.Payload.ToObject <MessageUpdateEvent>(Serializer);
                    var channel = GetChannel(data.ChannelId) as ITextChannel;
                    if (channel != null)
                    {
                        var msg    = (channel as Channel).MessageManager.Get(data.Id, data.Author?.Id);
                        var before = Config.EnablePreUpdateEvents ? msg.Clone() : null;
                        msg.Update(data);
                        Logger.Verbose($"MESSAGE_UPDATE: {channel} ({data.Author?.Username ?? "Unknown"})");
                        OnMessageUpdated(before, msg);
                    }
                    else
                    {
                        Logger.Warning("MESSAGE_UPDATE referenced an unknown channel.");
                    }
                }
                break;

                case "MESSAGE_DELETE":
                {
                    var data    = e.Payload.ToObject <MessageDeleteEvent>(Serializer);
                    var channel = GetChannel(data.ChannelId) as ITextChannel;
                    if (channel != null)
                    {
                        var msg = (channel as Channel).MessageManager.Remove(data.Id);
                        Logger.Verbose($"MESSAGE_DELETE: {channel} ({msg.User?.Name ?? "Unknown"})");
                        OnMessageDeleted(msg);
                    }
                    else
                    {
                        Logger.Warning("MESSAGE_DELETE referenced an unknown channel.");
                    }
                }
                break;

                //Statuses
                case "PRESENCE_UPDATE":
                {
                    var    data = e.Payload.ToObject <PresenceUpdateEvent>(Serializer);
                    User   user;
                    Server server;
                    if (data.GuildId == null)
                    {
                        server = null;
                        user   = GetPrivateChannel(data.User.Id)?.Recipient;
                    }
                    else
                    {
                        server = GetServer(data.GuildId.Value);
                        if (server == null)
                        {
                            Logger.Warning("PRESENCE_UPDATE referenced an unknown server.");
                            break;
                        }
                        else
                        {
                            user = server.GetUser(data.User.Id);
                        }
                    }

                    if (user != null)
                    {
                        if (Config.LogLevel == LogSeverity.Debug)
                        {
                            Logger.Debug($"PRESENCE_UPDATE: {user}");
                        }
                        var before = Config.EnablePreUpdateEvents ? user.Clone() : null;
                        user.Update(data);
                        OnUserUpdated(before, user);
                    }

                    /*else //Occurs when a user leaves a server
                     *  Logger.Warning("PRESENCE_UPDATE referenced an unknown user.");*/
                }
                break;

                case "TYPING_START":
                {
                    var data    = e.Payload.ToObject <TypingStartEvent>(Serializer);
                    var channel = GetChannel(data.ChannelId) as ITextChannel;
                    if (channel != null)
                    {
                        User user = (channel as Channel).GetUser(data.UserId);
                        if (user != null)
                        {
                            if (Config.LogLevel == LogSeverity.Debug)
                            {
                                Logger.Debug($"TYPING_START: {user.ToString(channel)}");
                            }
                            OnUserIsTypingUpdated(channel, user);
                            user.UpdateActivity();
                        }
                    }
                }
                break;

                //Voice
                case "VOICE_STATE_UPDATE":
                {
                    var data   = e.Payload.ToObject <VoiceStateUpdateEvent>(Serializer);
                    var server = GetServer(data.GuildId);
                    if (server != null)
                    {
                        var user = server.GetUser(data.UserId);
                        if (user != null)
                        {
                            if (Config.LogLevel == LogSeverity.Debug)
                            {
                                Logger.Debug($"VOICE_STATE_UPDATE: {user}");
                            }
                            var before = Config.EnablePreUpdateEvents ? user.Clone() : null;
                            user.Update(data);
                            //Logger.Verbose($"Voice Updated: {server.Name}/{user.Name}");
                            OnUserUpdated(before, user);
                        }

                        /*else //Occurs when a user leaves a server
                         *  Logger.Warning("VOICE_STATE_UPDATE referenced an unknown user.");*/
                    }
                    else
                    {
                        Logger.Warning("VOICE_STATE_UPDATE referenced an unknown server.");
                    }
                }
                break;

                //Settings
                case "USER_UPDATE":
                {
                    var data = e.Payload.ToObject <UserUpdateEvent>(Serializer);
                    if (data.Id == CurrentUser.Id)
                    {
                        var before = Config.EnablePreUpdateEvents ? CurrentUser.Clone() : null;
                        CurrentUser.Update(data);
                        PrivateUser.Update(data);
                        foreach (var server in _servers)
                        {
                            server.Value.CurrentUser.Update(data);
                        }
                        Logger.Info($"USER_UPDATE");
                        OnProfileUpdated(before, CurrentUser);
                    }
                }
                break;

                //Handled in GatewaySocket
                case "RESUMED":
                    break;

                //Ignored
                case "USER_SETTINGS_UPDATE":
                case "GUILD_INTEGRATIONS_UPDATE":
                case "VOICE_SERVER_UPDATE":
                case "GUILD_EMOJIS_UPDATE":
                case "MESSAGE_ACK":
                    Logger.Debug($"{e.Type} [Ignored]");
                    break;

                //Others
                default:
                    Logger.Warning($"Unknown message type: {e.Type}");
                    break;
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"Error handling {e.Type} event", ex);
            }
        }
		private async Task<Channel> CreatePMChannel(User user, string userId)
		{
			CheckReady();
			if (userId == null) throw new ArgumentNullException(nameof(userId));

			Channel channel = null;
			if (user != null)
				channel = user.PrivateChannel;
			if (channel == null)
			{
				var response = await _api.CreatePMChannel(CurrentUserId, userId).ConfigureAwait(false);
				user = _users.GetOrAdd(response.Recipient?.Id);
				user.Update(response.Recipient);
				channel = _channels.GetOrAdd(response.Id, response.GuildId, response.Recipient?.Id);
				channel.Update(response);
			}
			return channel;
		}