Ejemplo n.º 1
0
        internal override async Task OnReceivedEvent(WebSocketEventEventArgs e)
        {
            try
            {
                switch (e.Type)
                {
                //Global
                case "READY":                         //Resync
                {
                    base.OnReceivedEvent(e).Wait();   //This cannot be an await, or we'll get later messages before we're ready
                    var data = e.Payload.ToObject <ReadyEvent>(_serializer);
                    _currentUser = _users.GetOrAdd(data.User.Id, null);
                    _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, null);
                        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, null);
                        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 <MemberAddEvent>(_serializer);
                    var user = _users.GetOrAdd(data.User.Id, data.GuildId);
                    user.Update(data);
                    if (Config.TrackActivity)
                    {
                        user.UpdateActivity();
                    }
                    RaiseUserAdded(user);
                }
                break;

                case "GUILD_MEMBER_UPDATE":
                {
                    var data = e.Payload.ToObject <MemberUpdateEvent>(_serializer);
                    var user = _users[data.User.Id, data.GuildId];
                    if (user != null)
                    {
                        user.Update(data);
                        RaiseUserUpdated(user);
                    }
                }
                break;

                case "GUILD_MEMBER_REMOVE":
                {
                    var data = e.Payload.ToObject <MemberRemoveEvent>(_serializer);
                    var user = _users.TryRemove(data.UserId, data.GuildId);
                    if (user != null)
                    {
                        RaiseUserRemoved(user);
                    }
                }
                break;

                case "GUILD_MEMBERS_CHUNK":
                {
                    var data = e.Payload.ToObject <MembersChunkEvent>(_serializer);
                    foreach (var memberData in data.Members)
                    {
                        var user = _users.GetOrAdd(memberData.User.Id, memberData.GuildId);
                        user.Update(memberData);
                        //RaiseUserAdded(user);
                    }
                }
                break;

                //Roles
                case "GUILD_ROLE_CREATE":
                {
                    var data = e.Payload.ToObject <RoleCreateEvent>(_serializer);
                    var role = _roles.GetOrAdd(data.Data.Id, data.GuildId);
                    role.Update(data.Data);
                    var server = _servers[data.GuildId];
                    if (server != null)
                    {
                        server.AddRole(role);
                    }
                    RaiseRoleUpdated(role);
                }
                break;

                case "GUILD_ROLE_UPDATE":
                {
                    var data = e.Payload.ToObject <RoleUpdateEvent>(_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 <RoleDeleteEvent>(_serializer);
                    var role = _roles.TryRemove(data.RoleId);
                    if (role != null)
                    {
                        RaiseRoleDeleted(role);
                        var server = _servers[data.GuildId];
                        if (server != null)
                        {
                            server.RemoveRole(role);
                        }
                    }
                }
                break;

                //Bans
                case "GUILD_BAN_ADD":
                {
                    var data   = e.Payload.ToObject <BanAddEvent>(_serializer);
                    var server = _servers[data.GuildId];
                    if (server != null)
                    {
                        server.AddBan(data.User?.Id);
                        RaiseUserBanned(data.User?.Id, server);
                    }
                }
                break;

                case "GUILD_BAN_REMOVE":
                {
                    var data   = e.Payload.ToObject <BanRemoveEvent>(_serializer);
                    var server = _servers[data.GuildId];
                    if (server != null && server.RemoveBan(data.User?.Id))
                    {
                        RaiseUserUnbanned(data.User?.Id, server);
                    }
                }
                break;

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

                    bool isAuthor = data.Author.Id == _userId;

                    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?.IsPrivate == false)
                        {
                            var user = msg.User;
                            if (user != null)
                            {
                                user.UpdateActivity(data.Timestamp);
                            }
                        }
                    }

                    RaiseMessageReceived(msg);

                    if (Config.AckMessages && !isAuthor)
                    {
                        await _api.AckMessage(data.Id, data.ChannelId).ConfigureAwait(false);
                    }
                }
                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 user = _users.GetOrAdd(data.User.Id, data.GuildId);
                    if (user != null)
                    {
                        user.Update(data);
                        RaiseUserPresenceUpdated(user);
                    }
                }
                break;

                case "TYPING_START":
                {
                    var data    = e.Payload.ToObject <TypingStartEvent>(_serializer);
                    var channel = _channels[data.ChannelId];
                    if (channel != null)
                    {
                        var user = _users[data.UserId, channel.Server?.Id];
                        if (user != null)
                        {
                            if (channel != null)
                            {
                                RaiseUserIsTyping(user, channel);
                            }
                        }

                        if (Config.TrackActivity)
                        {
                            if (!channel.IsPrivate)
                            {
                                if (user != null)
                                {
                                    user.UpdateActivity();
                                }
                            }
                        }
                    }
                }
                break;

                //Voice
                case "VOICE_STATE_UPDATE":
                {
                    var data = e.Payload.ToObject <MemberVoiceStateUpdateEvent>(_serializer);
                    var user = _users[data.UserId, data.GuildId];
                    if (user != null)
                    {
                        var voiceChannel = user.VoiceChannel;
                        if (voiceChannel != null && data.ChannelId != voiceChannel.Id && user.IsSpeaking)
                        {
                            user.IsSpeaking = false;
                            RaiseUserIsSpeaking(user, _channels[voiceChannel.Id], false);
                        }
                        user.Update(data);
                        RaiseUserVoiceStateUpdated(user);
                    }
                }
                break;

                //Settings
                case "USER_UPDATE":
                {
                    var data = e.Payload.ToObject <UserUpdateEvent>(_serializer);
                    var user = _globalUsers[data.Id];
                    if (user != null)
                    {
                        user.Update(data);
                        RaiseProfileUpdated();
                    }
                }
                break;

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

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

                //Pass to DiscordWSClient
                case "VOICE_SERVER_UPDATE":
                    await base.OnReceivedEvent(e).ConfigureAwait(false);

                    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}");
            }
        }