void HandleMessageDeleteEvent(DiscordApiData data) { Snowflake messageId = data.GetSnowflake("id").Value; Snowflake channelId = data.GetSnowflake("channel_id").Value; OnMessageDeleted?.Invoke(this, new MessageDeleteEventArgs(shard, messageId, channelId)); }
internal void FireOnMessageDeleted(ChatDeleted chatDelete) { if (chatDelete == null) { throw new ArgumentNullException(nameof(chatDelete)); } OnMessageDeleted?.Invoke(chatDelete); }
void HandleMessageDeleteBulkEvent(DiscordApiData data) { Snowflake channelId = data.GetSnowflake("channel_id").Value; IList <DiscordApiData> idArray = data.GetArray("ids"); for (int i = 0; i < idArray.Count; i++) { Snowflake messageId = idArray[i].ToSnowflake().Value; OnMessageDeleted?.Invoke(this, new MessageDeleteEventArgs(shard, messageId, channelId)); } }
private void PubSubService_OnMessageDeleted(object sender, OnMessageDeletedArgs e) { if (!UserIdChannelName.TryGetValue(e.ChannelId, out var channelName)) { return; } OnMessageDeleted?.Invoke(this, new MessageDeletedEvent { TwitchMessageId = e.MessageId, Channel = channelName, DeletedBy = e.DeletedBy, Message = e.Message, Username = e.TargetUser, }); }
private void SocketDataReceived(object sender, WebSocketSharp.MessageEventArgs result) { GatewayResponse payload = result.Data.Deserialize <GatewayResponse>(); Sequence = payload.Sequence; switch (payload.Opcode) { case GatewayOpcode.Event: switch (payload.Title) { case "READY": LoggedIn = true; Login login = payload.Deserialize <Login>().SetJson(payload.Deserialize <JObject>()).SetClient(this); this.User = login.User; this.SessionId = login.SessionId; OnLoggedIn?.Invoke(this, new LoginEventArgs(login)); break; case "USER_SETTINGS_UPDATE": OnSettingsUpdated?.Invoke(this, new SettingsUpdatedEventArgs(payload.Deserialize <Settings>())); break; case "USER_UPDATE": User user = payload.Deserialize <User>().SetClient(this); if (user.Id == User.Id) { User.Update(user); } OnUserUpdated?.Invoke(this, new UserEventArgs(user)); break; case "GUILD_CREATE": OnJoinedGuild?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_UPDATE": OnGuildUpdated?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_DELETE": OnLeftGuild?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_MEMBER_ADD": OnUserJoinedGuild?.Invoke(this, new GuildMemberEventArgs(payload.Deserialize <GuildMemberUpdate>().SetClient(this).Member)); break; case "GUILD_MEMBER_REMOVE": OnUserLeftGuild?.Invoke(this, new GuildMemberEventArgs(payload.Deserialize <GuildMemberUpdate>().SetClient(this).Member)); break; case "GUILD_MEMBER_UPDATE": OnGuildMemberUpdated?.Invoke(this, new GuildMemberEventArgs(payload.Deserialize <GuildMember>().SetClient(this))); break; case "GUILD_MEMBERS_CHUNK": OnGuildMembersReceived?.Invoke(this, new GuildMembersEventArgs(payload.Deserialize <GuildMemberList>().SetClient(this))); break; case "PRESENCE_UPDATE": OnUserPresenceUpdated?.Invoke(this, new PresenceUpdatedEventArgs(payload.Deserialize <PresenceUpdate>())); break; case "VOICE_STATE_UPDATE": VoiceState state = payload.Deserialize <VoiceState>().SetClient(this); if (state.ChannelId != null) { OnUserJoinedVoiceChannel?.Invoke(this, new VoiceStateEventArgs(state)); } else { OnUserLeftVoiceChannel?.Invoke(this, new VoiceStateEventArgs(state)); } break; case "GUILD_ROLE_CREATE": OnRoleCreated?.Invoke(this, new RoleEventArgs(payload.Deserialize <RoleContainer>().Role.SetClient(this))); break; case "GUILD_ROLE_UPDATE": OnRoleUpdated?.Invoke(this, new RoleEventArgs(payload.Deserialize <RoleContainer>().Role.SetClient(this))); break; case "GUILD_EMOJIS_UPDATE": OnEmojisUpdated?.Invoke(this, new EmojisUpdatedEventArgs(payload.Deserialize <EmojiContainer>().SetClient(this))); break; case "CHANNEL_CREATE": OnChannelCreated?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "CHANNEL_UPDATE": OnChannelUpdated?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "CHANNEL_DELETE": OnChannelDeleted?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "TYPING_START": OnUserTyping?.Invoke(this, new UserTypingEventArgs(payload.Deserialize <UserTyping>())); break; case "MESSAGE_CREATE": OnMessageReceived?.Invoke(this, new MessageEventArgs(payload.Deserialize <Message>().SetClient(this))); break; case "MESSAGE_UPDATE": OnMessageEdited?.Invoke(this, new MessageEventArgs(payload.Deserialize <Message>().SetClient(this))); break; case "MESSAGE_DELETE": OnMessageDeleted?.Invoke(this, new MessageDeletedEventArgs(payload.Deserialize <DeletedMessage>())); break; case "MESSAGE_REACTION_ADD": OnMessageReactionAdded?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this))); break; case "MESSAGE_REACTION_REMOVE": OnMessageReactionRemoved?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this))); break; case "GUILD_BAN_ADD": OnUserBanned?.Invoke(this, new BanUpdateEventArgs(payload.Deserialize <BanContainer>().SetClient(this))); break; case "GUILD_BAN_REMOVE": OnUserUnbanned?.Invoke(this, new BanUpdateEventArgs(payload.Deserialize <BanContainer>().SetClient(this))); break; case "RELATIONSHIP_ADD": OnRelationshipAdded?.Invoke(this, new RelationshipEventArgs(payload.Deserialize <Relationship>().SetClient(this))); break; case "RELATIONSHIP_REMOVE": OnRelationshipRemoved?.Invoke(this, new RelationshipEventArgs(payload.Deserialize <Relationship>().SetClient(this))); break; case "USER_CONNECTIONS_UPDATE": Task.Run(() => { DiscordProfile profile = this.User.GetProfile(); OnProfileUpdated?.Invoke(this, new ProfileUpdatedEventArgs(profile)); }); break; } break; case GatewayOpcode.InvalidSession: this.LoginToGateway(); break; case GatewayOpcode.Connected: if (!LoggedIn) { this.LoginToGateway(); } else { this.Resume(); } this.StartHeartbeatHandlersAsync(payload.Deserialize <JObject>().GetValue("heartbeat_interval").ToObject <uint>()); break; } }
private void NewConnection_OnMessageDeleted(object _, MessageDeletedEvent e) { logger.LogInformation("Received deleted message from channel {arg}, on user {arg2}, issued by {arg3} regarding message: {arg4}", e.Channel, e.Username, e.DeletedBy, e.Message); OnMessageDeleted?.Invoke(this, e); }
/// <summary> /// Parses the message. /// </summary> /// <param name="message">The message.</param> private void ParseMessage(string message) { var type = JObject.Parse(message).SelectToken("type")?.ToString(); switch (type?.ToLower()) { case "response": var resp = new Models.Responses.Response(message); if (_previousRequests.Count != 0) { bool handled = false; foreach (var request in _previousRequests) { if (string.Equals(request.Nonce, resp.Nonce, StringComparison.CurrentCulture)) { OnListenResponse?.Invoke(this, new OnListenResponseArgs { Response = resp, Topic = request.Topic, Successful = resp.Successful }); handled = true; } } if (handled) { return; } } break; case "message": var msg = new Models.Responses.Message(message); _topicToChannelId.TryGetValue(msg.Topic, out var channelId); channelId = channelId ?? ""; switch (msg.Topic.Split('.')[0]) { case "channel-subscribe-events-v1": var subscription = msg.MessageData as ChannelSubscription; OnChannelSubscription?.Invoke(this, new OnChannelSubscriptionArgs { Subscription = subscription, ChannelId = channelId }); return; case "whispers": var whisper = (Whisper)msg.MessageData; OnWhisper?.Invoke(this, new OnWhisperArgs { Whisper = whisper, ChannelId = channelId }); return; case "chat_moderator_actions": var cma = msg.MessageData as ChatModeratorActions; var reason = ""; var targetChannelId = msg.Topic.Split('.')[2]; switch (cma?.ModerationAction.ToLower()) { case "timeout": if (cma.Args.Count > 2) { reason = cma.Args[2]; } OnTimeout?.Invoke(this, new OnTimeoutArgs { TimedoutBy = cma.CreatedBy, TimedoutById = cma.CreatedByUserId, TimedoutUserId = cma.TargetUserId, TimeoutDuration = TimeSpan.FromSeconds(int.Parse(cma.Args[1])), TimeoutReason = reason, TimedoutUser = cma.Args[0], ChannelId = channelId }); return; case "ban": if (cma.Args.Count > 1) { reason = cma.Args[1]; } OnBan?.Invoke(this, new OnBanArgs { BannedBy = cma.CreatedBy, BannedByUserId = cma.CreatedByUserId, BannedUserId = cma.TargetUserId, BanReason = reason, BannedUser = cma.Args[0], ChannelId = channelId }); return; case "delete": OnMessageDeleted?.Invoke(this, new OnMessageDeletedArgs { DeletedBy = cma.CreatedBy, DeletedByUserId = cma.CreatedByUserId, TargetUserId = cma.TargetUserId, TargetUser = cma.Args[0], Message = cma.Args[1], MessageId = cma.Args[2], ChannelId = channelId }); return; case "unban": OnUnban?.Invoke(this, new OnUnbanArgs { UnbannedBy = cma.CreatedBy, UnbannedByUserId = cma.CreatedByUserId, UnbannedUserId = cma.TargetUserId, UnbannedUser = cma.Args[0], ChannelId = channelId }); return; case "untimeout": OnUntimeout?.Invoke(this, new OnUntimeoutArgs { UntimeoutedBy = cma.CreatedBy, UntimeoutedByUserId = cma.CreatedByUserId, UntimeoutedUserId = cma.TargetUserId, UntimeoutedUser = cma.Args[0], ChannelId = channelId }); return; case "host": OnHost?.Invoke(this, new OnHostArgs { HostedChannel = cma.Args[0], Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "subscribers": OnSubscribersOnly?.Invoke(this, new OnSubscribersOnlyArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "subscribersoff": OnSubscribersOnlyOff?.Invoke(this, new OnSubscribersOnlyOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "clear": OnClear?.Invoke(this, new OnClearArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "emoteonly": OnEmoteOnly?.Invoke(this, new OnEmoteOnlyArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "emoteonlyoff": OnEmoteOnlyOff?.Invoke(this, new OnEmoteOnlyOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "r9kbeta": OnR9kBeta?.Invoke(this, new OnR9kBetaArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "r9kbetaoff": OnR9kBetaOff?.Invoke(this, new OnR9kBetaOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; } break; case "channel-bits-events-v1": if (msg.MessageData is ChannelBitsEvents cbe) { OnBitsReceived?.Invoke(this, new OnBitsReceivedArgs { BitsUsed = cbe.BitsUsed, ChannelId = cbe.ChannelId, ChannelName = cbe.ChannelName, ChatMessage = cbe.ChatMessage, Context = cbe.Context, Time = cbe.Time, TotalBitsUsed = cbe.TotalBitsUsed, UserId = cbe.UserId, Username = cbe.Username }); return; } break; case "channel-commerce-events-v1": if (msg.MessageData is ChannelCommerceEvents cce) { OnChannelCommerceReceived?.Invoke(this, new OnChannelCommerceReceivedArgs { Username = cce.Username, DisplayName = cce.DisplayName, ChannelName = cce.ChannelName, UserId = cce.UserId, ChannelId = cce.ChannelId, Time = cce.Time, ItemImageURL = cce.ItemImageURL, ItemDescription = cce.ItemDescription, SupportsChannel = cce.SupportsChannel, PurchaseMessage = cce.PurchaseMessage }); return; } break; case "channel-ext-v1": var cEB = msg.MessageData as ChannelExtensionBroadcast; OnChannelExtensionBroadcast?.Invoke(this, new OnChannelExtensionBroadcastArgs { Messages = cEB.Messages, ChannelId = channelId }); return; case "video-playback": case "video-playback-by-id": var vP = msg.MessageData as VideoPlayback; switch (vP?.Type) { case VideoPlaybackType.StreamDown: OnStreamDown?.Invoke(this, new OnStreamDownArgs { ChannelId = channelId, ServerTime = vP.ServerTime }); return; case VideoPlaybackType.StreamUp: OnStreamUp?.Invoke(this, new OnStreamUpArgs { ChannelId = channelId, PlayDelay = vP.PlayDelay, ServerTime = vP.ServerTime }); return; case VideoPlaybackType.ViewCount: OnViewCount?.Invoke(this, new OnViewCountArgs { ChannelId = channelId, ServerTime = vP.ServerTime, Viewers = vP.Viewers }); return; case VideoPlaybackType.Commercial: OnCommercial?.Invoke(this, new OnCommercialArgs { ChannelId = channelId, ServerTime = vP.ServerTime, Length = vP.Length }); return; case VideoPlaybackType.WatchPartyVod: OnWatchPartyVod?.Invoke(this, new OnWatchPartyVodArgs { ChannelId = channelId, WpId = vP.WpId, WpType = vP.WpType, IncrementUrl = vP.IncrementUrl, VodId = vP.VodId, Title = vP.Title, BroadcastType = vP.BroadcastType, Viewable = vP.Viewable }); return; } break; case "broadcast-settings-update": var bsu = msg.MessageData as BroadcastSettingsUpdate; switch (bsu?.Type) { case BroadcastSettingsUpdateType.BroadcastSettingsUpdate: OnBroadcastSettingsUpdate?.Invoke(this, new OnBroadcastSettingsUpdateArgs { ChannelId = channelId, Channel = bsu.Channel, Game = bsu.Game, GameId = bsu.GameId, OldGame = bsu.OldGame, OldGameId = bsu.OldGameId, OldStatus = bsu.OldStatus, Status = bsu.Status }); return; } break; case "following": var f = (Following)msg.MessageData; f.FollowedChannelId = msg.Topic.Split('.')[1]; OnFollow?.Invoke(this, new OnFollowArgs { FollowedChannelId = f.FollowedChannelId, DisplayName = f.DisplayName, UserId = f.UserId, Username = f.Username }); return; case "community-points-channel-v1": var cpc = msg.MessageData as CommunityPointsChannel; switch (cpc?.Type) { case CommunityPointsChannelType.RewardRedeemed: OnRewardRedeemed?.Invoke(this, new OnRewardRedeemedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, Login = cpc.Login, DisplayName = cpc.DisplayName, Message = cpc.Message, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt, RewardCost = cpc.RewardCost, Status = cpc.Status }); return; case CommunityPointsChannelType.CustomRewardUpdated: OnCustomRewardUpdated?.Invoke(this, new OnCustomRewardUpdatedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt, RewardCost = cpc.RewardCost }); return; case CommunityPointsChannelType.CustomRewardCreated: OnCustomRewardCreated?.Invoke(this, new OnCustomRewardCreatedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt, RewardCost = cpc.RewardCost }); return; case CommunityPointsChannelType.CustomRewardDeleted: OnCustomRewardDeleted?.Invoke(this, new OnCustomRewardDeletedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt }); return; } return; case "leaderboard-events-v1": var lbe = msg.MessageData as LeaderboardEvents; switch (lbe?.Type) { case LeaderBoardType.BitsUsageByChannel: OnLeaderboardBits?.Invoke(this, new OnLeaderboardEventArgs { ChannelId = lbe.ChannelId, TopList = lbe.Top }); return; case LeaderBoardType.SubGiftSent: OnLeaderboardSubs?.Invoke(this, new OnLeaderboardEventArgs { ChannelId = lbe.ChannelId, TopList = lbe.Top }); return; } return; case "raid": var r = msg.MessageData as RaidEvents; switch (r?.Type) { case RaidType.RaidUpdate: OnRaidUpdate?.Invoke(this, new OnRaidUpdateArgs { Id = r.Id, ChannelId = r.ChannelId, TargetChannelId = r.TargetChannelId, AnnounceTime = r.AnnounceTime, RaidTime = r.RaidTime, RemainingDurationSeconds = r.RemainigDurationSeconds, ViewerCount = r.ViewerCount }); return; case RaidType.RaidUpdateV2: OnRaidUpdateV2?.Invoke(this, new OnRaidUpdateV2Args { Id = r.Id, ChannelId = r.ChannelId, TargetChannelId = r.TargetChannelId, TargetLogin = r.TargetLogin, TargetDisplayName = r.TargetDisplayName, TargetProfileImage = r.TargetProfileImage, ViewerCount = r.ViewerCount }); return; case RaidType.RaidGo: OnRaidGo?.Invoke(this, new OnRaidGoArgs { Id = r.Id, ChannelId = r.ChannelId, TargetChannelId = r.TargetChannelId, TargetLogin = r.TargetLogin, TargetDisplayName = r.TargetDisplayName, TargetProfileImage = r.TargetProfileImage, ViewerCount = r.ViewerCount }); return; } return; } break; } UnaccountedFor(message); }
private void SocketDataReceived(object sender, WebSocketSharp.MessageEventArgs result) { var payload = JsonConvert.DeserializeObject <GatewayResponse>(result.Data); Sequence = payload.Sequence; switch (payload.Opcode) { case GatewayOpcode.Event: switch (payload.Title) { case "READY": LoggedIn = true; GatewayLogin lgn = JsonConvert.DeserializeObject <GatewayLogin>(payload.Data.ToString()); this.User = lgn.User; OnLoggedIn?.Invoke(this, new UserEventArgs(this.User)); break; case "GUILD_CREATE": Guild cGuild = JsonConvert.DeserializeObject <Guild>(payload.Data.ToString()); cGuild.Client = this; OnJoinedGuild?.Invoke(this, new GuildEventArgs(cGuild)); break; case "GUILD_UPDATE": Guild uGuild = JsonConvert.DeserializeObject <Guild>(payload.Data.ToString()); uGuild.Client = this; OnGuildUpdated?.Invoke(this, new GuildEventArgs(uGuild)); break; case "GUILD_DELETE": Guild dGuild = JsonConvert.DeserializeObject <Guild>(payload.Data.ToString()); dGuild.Client = this; OnLeftGuild?.Invoke(this, new GuildEventArgs(dGuild)); break; case "CHANNEL_CREATE": Channel cChannel = JsonConvert.DeserializeObject <Channel>(payload.Data.ToString()); cChannel.Client = this; OnChannelCreated?.Invoke(this, new ChannelEventArgs(cChannel)); break; case "CHANNEL_UPDATE": Channel uChannel = JsonConvert.DeserializeObject <Channel>(payload.Data.ToString()); uChannel.Client = this; OnChannelUpdated?.Invoke(this, new ChannelEventArgs(uChannel)); break; case "CHANNEL_DELETE": Channel dChannel = JsonConvert.DeserializeObject <Channel>(payload.Data.ToString()); dChannel.Client = this; OnChannelDeleted?.Invoke(this, new ChannelEventArgs(dChannel)); break; case "GUILD_ROLE_CREATE": GatewayRole cRole = JsonConvert.DeserializeObject <GatewayRole>(payload.Data.ToString()); cRole.Role.Client = this; OnRoleCreated?.Invoke(this, new RoleEventArgs(cRole.Role)); break; case "GUILD_ROLE_UPDATE": GatewayRole uRole = JsonConvert.DeserializeObject <GatewayRole>(payload.Data.ToString()); uRole.Role.Client = this; OnRoleUpdated?.Invoke(this, new RoleEventArgs(uRole.Role)); break; case "MESSAGE_CREATE": Message cMsg = JsonConvert.DeserializeObject <Message>(payload.Data.ToString()); cMsg.Client = this; OnMessageReceived?.Invoke(this, new MessageEventArgs(cMsg)); break; case "MESSAGE_UPDATE": Message uMsg = JsonConvert.DeserializeObject <Message>(payload.Data.ToString()); uMsg.Client = this; OnMessageEdited?.Invoke(this, new MessageEventArgs(uMsg)); break; case "MESSAGE_DELETE": OnMessageDeleted?.Invoke(this, new MessageDeletedEventArgs(JsonConvert.DeserializeObject <MessageDelete>(payload.Data.ToString()))); break; } break; case GatewayOpcode.InvalidSession: Logout(); break; case GatewayOpcode.Connected: //keep sending heartbeats every x second so the client's socket don't get closed Task.Run(async() => await this.StartHeartbeatHandlersAsync(JsonConvert.DeserializeObject <GatewayHeartbeat>(payload.Data.ToString()).Interval)); this.LoginToGateway(); break; } }
private void SocketDataReceived(object sender, WebSocketSharp.MessageEventArgs result) { GatewayResponse payload = result.Data.Deserialize <GatewayResponse>(); Sequence = payload.Sequence; System.Console.WriteLine(payload.ToString()); switch (payload.Opcode) { case GatewayOpcode.Event: switch (payload.Title) { case "READY": LoggedIn = true; Login login = payload.Deserialize <Login>().SetClient(this); this.User = login.User; OnLoggedIn?.Invoke(this, new LoginEventArgs(payload.Deserialize <Login>().SetClient(this))); break; case "GUILD_CREATE": OnJoinedGuild?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_UPDATE": OnGuildUpdated?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_DELETE": OnLeftGuild?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_MEMBERS_CHUNK": GuildMemberList list = payload.Deserialize <GuildMemberList>().SetClient(this); foreach (var member in list.Members) { member.GuildId = list.GuildId; } OnGuildMembersReceived?.Invoke(this, new GuildMembersEventArgs(list.Members)); break; case "PRESENCE_UPDATE": OnUserPresenceUpdated?.Invoke(this, new PresenceUpdatedEventArgs(payload.Deserialize <PresenceUpdate>())); break; case "CHANNEL_CREATE": OnChannelCreated?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "CHANNEL_UPDATE": OnChannelUpdated?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "CHANNEL_DELETE": OnChannelDeleted?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "GUILD_ROLE_CREATE": OnRoleCreated?.Invoke(this, new RoleEventArgs(payload.Deserialize <GatewayRole>().Role.SetClient(this))); break; case "GUILD_ROLE_UPDATE": OnRoleUpdated?.Invoke(this, new RoleEventArgs(payload.Deserialize <GatewayRole>().Role.SetClient(this))); break; case "GUILD_EMOJIS_UPDATE": OnEmojisUpdated?.Invoke(this, new EmojisUpdatedEventArgs(payload.Deserialize <EmojiContainer>().SetClient(this))); break; case "MESSAGE_CREATE": OnMessageReceived?.Invoke(this, new MessageEventArgs(payload.Deserialize <Message>().SetClient(this))); break; case "MESSAGE_UPDATE": OnMessageEdited?.Invoke(this, new MessageEventArgs(payload.Deserialize <Message>().SetClient(this))); break; case "MESSAGE_DELETE": OnMessageDeleted?.Invoke(this, new MessageDeletedEventArgs(payload.Deserialize <DeletedMessage>())); break; case "MESSAGE_REACTION_ADD": OnMessageReactionAdded?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this))); break; case "MESSAGE_REACTION_REMOVE": OnMessageReactionRemoved?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this))); break; case "GUILD_BAN_ADD": OnUserBanned?.Invoke(this, new BanUpdateEventArgs(payload.Deserialize <BanContainer>().SetClient(this))); break; case "GUILD_BAN_REMOVE": OnUserUnbanned?.Invoke(this, new BanUpdateEventArgs(payload.Deserialize <BanContainer>().SetClient(this))); break; } break; case GatewayOpcode.InvalidSession: Logout(); break; case GatewayOpcode.Connected: this.StartHeartbeatHandlersAsync(payload.Deserialize <GatewayHeartbeat>().Interval); this.LoginToGateway(); break; } }
/// <summary> /// Passes <see cref="OnMessageDeleted"/> events down to subscribed plugins. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">An <see cref="OnMessageDeletedArgs"/> object.</param> private void TwitchPubSub_OnMessageDeleted(object sender, OnMessageDeletedArgs e) => OnMessageDeleted?.Invoke(this, e);
private void SocketDataReceived(object sender, WebSocketSharp.MessageEventArgs result) { GatewayResponse payload = result.Data.Deserialize <GatewayResponse>(); Sequence = payload.Sequence; Task.Run(() => { switch (payload.Opcode) { case GatewayOpcode.Event: switch (payload.Title) { case "READY": LoggedIn = true; Login login = payload.Deserialize <Login>().SetJson(payload.Deserialize <JObject>()).SetClient(this); this.User = login.User; this.SessionId = login.SessionId; OnLoggedIn?.Invoke(this, new LoginEventArgs(login)); break; case "USER_SETTINGS_UPDATE": OnSettingsUpdated?.Invoke(this, new SettingsUpdatedEventArgs(payload.Deserialize <Settings>())); break; case "USER_UPDATE": User user = payload.Deserialize <User>().SetClient(this); if (user.Id == User.Id) { User.Update(user); } OnUserUpdated?.Invoke(this, new UserEventArgs(user)); break; case "GUILD_MEMBER_LIST_UPDATE": /* * var args = new GuildMembersEventArgs(payload.Deserialize<GatewayUserMemberQueryResponse>()); * * foreach (var member in args.Members) * { * member.SetClient(this); * member.GuildId = args.GuildId; * } * * OnGuildMembersReceived?.Invoke(this, args);*/ break; case "GUILD_CREATE": OnJoinedGuild?.Invoke(this, new SocketGuildEventArgs(payload.Deserialize <SocketGuild>().SetClient(this))); break; case "GUILD_UPDATE": OnGuildUpdated?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_DELETE": OnLeftGuild?.Invoke(this, new GuildEventArgs(payload.Deserialize <Guild>().SetClient(this))); break; case "GUILD_MEMBER_ADD": OnUserJoinedGuild?.Invoke(this, new GuildMemberEventArgs(payload.Deserialize <GuildMemberUpdate>().SetClient(this).Member)); break; case "GUILD_MEMBER_REMOVE": OnUserLeftGuild?.Invoke(this, new GuildMemberEventArgs(payload.Deserialize <GuildMemberUpdate>().SetClient(this).Member)); break; case "GUILD_MEMBER_UPDATE": OnGuildMemberUpdated?.Invoke(this, new GuildMemberEventArgs(payload.Deserialize <GuildMember>().SetClient(this))); break; case "GUILD_MEMBERS_CHUNK": OnGuildMembersReceived?.Invoke(this, new GuildMembersEventArgs(payload.Deserialize <GuildMemberList>().SetClient(this))); break; case "PRESENCE_UPDATE": OnUserPresenceUpdated?.Invoke(this, new PresenceUpdatedEventArgs(payload.Deserialize <PresenceUpdate>())); break; case "VOICE_STATE_UPDATE": OnVoiceStateUpdated?.Invoke(this, new VoiceStateEventArgs(payload.Deserialize <DiscordVoiceState>().SetClient(this))); break; case "VOICE_SERVER_UPDATE": OnVoiceServer?.Invoke(this, payload.Deserialize <DiscordVoiceServer>()); break; case "GUILD_ROLE_CREATE": OnRoleCreated?.Invoke(this, new RoleEventArgs(payload.Deserialize <RoleContainer>().Role.SetClient(this))); break; case "GUILD_ROLE_UPDATE": OnRoleUpdated?.Invoke(this, new RoleEventArgs(payload.Deserialize <RoleContainer>().Role.SetClient(this))); break; case "GUILD_EMOJIS_UPDATE": OnEmojisUpdated?.Invoke(this, new EmojisUpdatedEventArgs(payload.Deserialize <EmojiContainer>().SetClient(this))); break; case "CHANNEL_CREATE": OnChannelCreated?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "CHANNEL_UPDATE": OnChannelUpdated?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "CHANNEL_DELETE": OnChannelDeleted?.Invoke(this, new ChannelEventArgs(payload.Deserialize <GuildChannel>().SetClient(this))); break; case "TYPING_START": OnUserTyping?.Invoke(this, new UserTypingEventArgs(payload.Deserialize <UserTyping>())); break; case "MESSAGE_CREATE": OnMessageReceived?.Invoke(this, new MessageEventArgs(payload.Deserialize <Message>().SetClient(this))); break; case "MESSAGE_UPDATE": OnMessageEdited?.Invoke(this, new MessageEventArgs(payload.Deserialize <Message>().SetClient(this))); break; case "MESSAGE_DELETE": OnMessageDeleted?.Invoke(this, new MessageDeletedEventArgs(payload.Deserialize <DeletedMessage>())); break; case "MESSAGE_REACTION_ADD": OnMessageReactionAdded?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this))); break; case "MESSAGE_REACTION_REMOVE": OnMessageReactionRemoved?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this))); break; case "GUILD_BAN_ADD": OnUserBanned?.Invoke(this, new BanUpdateEventArgs(payload.Deserialize <BanContainer>().SetClient(this))); break; case "GUILD_BAN_REMOVE": OnUserUnbanned?.Invoke(this, new BanUpdateEventArgs(payload.Deserialize <BanContainer>().SetClient(this))); break; case "RELATIONSHIP_ADD": OnRelationshipAdded?.Invoke(this, new RelationshipEventArgs(payload.Deserialize <Relationship>().SetClient(this))); break; case "RELATIONSHIP_REMOVE": OnRelationshipRemoved?.Invoke(this, new RelationshipEventArgs(payload.Deserialize <Relationship>().SetClient(this))); break; case "USER_CONNECTIONS_UPDATE": try { DiscordProfile profile = this.User.GetProfile(); OnProfileUpdated?.Invoke(this, new ProfileUpdatedEventArgs(profile)); } catch { } break; case "MESSAGE_ACK": // triggered whenever another person logged into the account acknowledges a message break; case "SESSIONS_REPLACE": OnSessionsUpdated?.Invoke(this, new DiscordSessionsEventArgs(payload.Deserialize <List <DiscordSession> >())); break; } break; case GatewayOpcode.InvalidSession: this.LoginToGateway(); break; case GatewayOpcode.Connected: if (!LoggedIn) { this.LoginToGateway(); } else { this.Resume(); } int interval = payload.Deserialize <JObject>().GetValue("heartbeat_interval").ToObject <int>(); try { while (true) { Socket.Send(GatewayOpcode.Heartbeat, this.Sequence); Thread.Sleep(interval); } } catch { } break; } }); }
/// <summary> /// Parses the message. /// </summary> /// <param name="message">The message.</param> private void ParseMessage(string message) { var type = JObject.Parse(message).SelectToken("type")?.ToString(); switch (type?.ToLower()) { case "response": var resp = new Models.Responses.Response(message); if (_previousRequests.Count != 0) { bool handled = false; foreach (var request in _previousRequests) { if (string.Equals(request.Nonce, resp.Nonce, StringComparison.CurrentCulture)) { OnListenResponse?.Invoke(this, new OnListenResponseArgs { Response = resp, Topic = request.Topic, Successful = resp.Successful }); handled = true; } } if (handled) { return; } } break; case "message": var msg = new Models.Responses.Message(message); _topicToChannelId.TryGetValue(msg.Topic, out var channelId); channelId = channelId ?? ""; switch (msg.Topic.Split('.')[0]) { case "channel-subscribe-events-v1": var subscription = msg.MessageData as ChannelSubscription; OnChannelSubscription?.Invoke(this, new OnChannelSubscriptionArgs { Subscription = subscription, ChannelId = channelId }); return; case "whispers": var whisper = (Whisper)msg.MessageData; OnWhisper?.Invoke(this, new OnWhisperArgs { Whisper = whisper, ChannelId = channelId }); return; case "chat_moderator_actions": var cma = msg.MessageData as ChatModeratorActions; var reason = ""; var targetChannelId = msg.Topic.Split('.')[2]; switch (cma?.ModerationAction.ToLower()) { case "timeout": if (cma.Args.Count > 2) { reason = cma.Args[2]; } OnTimeout?.Invoke(this, new OnTimeoutArgs { TimedoutBy = cma.CreatedBy, TimedoutById = cma.CreatedByUserId, TimedoutUserId = cma.TargetUserId, TimeoutDuration = TimeSpan.FromSeconds(int.Parse(cma.Args[1])), TimeoutReason = reason, TimedoutUser = cma.Args[0], ChannelId = channelId }); return; case "ban": if (cma.Args.Count > 1) { reason = cma.Args[1]; } OnBan?.Invoke(this, new OnBanArgs { BannedBy = cma.CreatedBy, BannedByUserId = cma.CreatedByUserId, BannedUserId = cma.TargetUserId, BanReason = reason, BannedUser = cma.Args[0], ChannelId = channelId }); return; case "delete": OnMessageDeleted?.Invoke(this, new OnMessageDeletedArgs { DeletedBy = cma.CreatedBy, DeletedByUserId = cma.CreatedByUserId, TargetUserId = cma.TargetUserId, TargetUser = cma.Args[0], Message = cma.Args[1], MessageId = cma.Args[2], ChannelId = channelId }); return; case "unban": OnUnban?.Invoke(this, new OnUnbanArgs { UnbannedBy = cma.CreatedBy, UnbannedByUserId = cma.CreatedByUserId, UnbannedUserId = cma.TargetUserId, UnbannedUser = cma.Args[0], ChannelId = channelId }); return; case "untimeout": OnUntimeout?.Invoke(this, new OnUntimeoutArgs { UntimeoutedBy = cma.CreatedBy, UntimeoutedByUserId = cma.CreatedByUserId, UntimeoutedUserId = cma.TargetUserId, UntimeoutedUser = cma.Args[0], ChannelId = channelId }); return; case "host": OnHost?.Invoke(this, new OnHostArgs { HostedChannel = cma.Args[0], Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "subscribers": OnSubscribersOnly?.Invoke(this, new OnSubscribersOnlyArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "subscribersoff": OnSubscribersOnlyOff?.Invoke(this, new OnSubscribersOnlyOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "clear": OnClear?.Invoke(this, new OnClearArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "emoteonly": OnEmoteOnly?.Invoke(this, new OnEmoteOnlyArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "emoteonlyoff": OnEmoteOnlyOff?.Invoke(this, new OnEmoteOnlyOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "r9kbeta": OnR9kBeta?.Invoke(this, new OnR9kBetaArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "r9kbetaoff": OnR9kBetaOff?.Invoke(this, new OnR9kBetaOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; } break; case "channel-bits-events-v1": if (msg.MessageData is ChannelBitsEvents cbe) { OnBitsReceived?.Invoke(this, new OnBitsReceivedArgs { BitsUsed = cbe.BitsUsed, ChannelId = cbe.ChannelId, ChannelName = cbe.ChannelName, ChatMessage = cbe.ChatMessage, Context = cbe.Context, Time = cbe.Time, TotalBitsUsed = cbe.TotalBitsUsed, UserId = cbe.UserId, Username = cbe.Username }); return; } break; case "channel-commerce-events-v1": if (msg.MessageData is ChannelCommerceEvents cce) { OnChannelCommerceReceived?.Invoke(this, new OnChannelCommerceReceivedArgs { Username = cce.Username, DisplayName = cce.DisplayName, ChannelName = cce.ChannelName, UserId = cce.UserId, ChannelId = cce.ChannelId, Time = cce.Time, ItemImageURL = cce.ItemImageURL, ItemDescription = cce.ItemDescription, SupportsChannel = cce.SupportsChannel, PurchaseMessage = cce.PurchaseMessage }); return; } break; case "channel-ext-v1": var cEB = msg.MessageData as ChannelExtensionBroadcast; OnChannelExtensionBroadcast?.Invoke(this, new OnChannelExtensionBroadcastArgs { Messages = cEB.Messages, ChannelId = channelId }); return; case "video-playback": var vP = msg.MessageData as VideoPlayback; switch (vP?.Type) { case VideoPlaybackType.StreamDown: OnStreamDown?.Invoke(this, new OnStreamDownArgs { ServerTime = vP.ServerTime }); return; case VideoPlaybackType.StreamUp: OnStreamUp?.Invoke(this, new OnStreamUpArgs { PlayDelay = vP.PlayDelay, ServerTime = vP.ServerTime }); return; case VideoPlaybackType.ViewCount: OnViewCount?.Invoke(this, new OnViewCountArgs { ServerTime = vP.ServerTime, Viewers = vP.Viewers }); return; case VideoPlaybackType.Commercial: OnCommercial?.Invoke(this, new OnCommercialArgs { ServerTime = vP.ServerTime, Length = vP.Length }); return; } break; case "following": var f = (Following)msg.MessageData; f.FollowedChannelId = msg.Topic.Split('.')[1]; OnFollow?.Invoke(this, new OnFollowArgs { FollowedChannelId = f.FollowedChannelId, DisplayName = f.DisplayName, UserId = f.UserId, Username = f.Username }); return; } break; } UnaccountedFor(message); }
private void SocketDataReceived(object sender, WebSocketSharp.MessageEventArgs result) { GatewayResponse payload = result.Data.Deserialize <GatewayResponse>(); Sequence = payload.Sequence; try { switch (payload.Opcode) { case GatewayOpcode.Event: /* * Console.WriteLine(payload.Title); * * File.AppendAllText("Debug.log", $"{payload.Title}: {payload.Data}\n"); */ switch (payload.Title) { case "READY": Login login = payload.DeserializeEx <Login>().SetClient(this); this.User = login.User; this.UserSettings = login.Settings; this.SessionId = login.SessionId; if (Config.Cache) { if (this.User.Type == DiscordUserType.User) { PrivateChannels = login.PrivateChannels; foreach (var guild in login.Guilds) { GuildCache[guild.Id] = guild.ToSocketGuild(); foreach (var state in GuildCache[guild.Id].VoiceStates) { VoiceStates[state.UserId] = state; } } foreach (var settings in login.ClientGuildSettings) { if (settings.GuildId.HasValue) { GuildSettings.Add(settings.Guild.Id, settings); } else { PrivateChannelSettings = settings.ChannelOverrides.ToList(); } } } } LoggedIn = true; Task.Run(() => OnLoggedIn?.Invoke(this, new LoginEventArgs(login))); break; case "USER_SETTINGS_UPDATE": if (UserSettings != null) // for some reason this is null sometimes :thinking: { var update = payload.Deserialize <JObject>(); foreach (var field in UserSettings.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) { foreach (var attr in field.CustomAttributes) { if (attr.AttributeType == typeof(JsonPropertyAttribute)) { string propertyName = attr.ConstructorArguments[0].Value.ToString(); if (update.ContainsKey(propertyName)) { field.SetValue(UserSettings, update.GetValue(propertyName).ToObject(field.FieldType)); } break; } } } foreach (var property in UserSettings.GetType().GetProperties()) { foreach (var attr in property.CustomAttributes) { if (attr.AttributeType == typeof(JsonPropertyAttribute)) { string propertyName = attr.ConstructorArguments[0].Value.ToString(); if (update.ContainsKey(propertyName)) { property.SetValue(UserSettings, update.GetValue(propertyName).ToObject(property.PropertyType)); } break; } } } Task.Run(() => OnSettingsUpdated?.Invoke(this, new DiscordSettingsEventArgs(UserSettings))); } break; case "USER_GUILD_SETTINGS_UPDATE": if (Config.Cache) { ClientGuildSettings settings = payload.Deserialize <ClientGuildSettings>(); if (settings.GuildId.HasValue) { GuildSettings[settings.Guild.Id] = settings; } else { PrivateChannelSettings = settings.ChannelOverrides.ToList(); } } break; case "USER_UPDATE": DiscordUser user = payload.Deserialize <DiscordUser>().SetClient(this); if (user.Id == User.Id) { User.Update(user); } if (Config.Cache) { foreach (var dm in PrivateChannels) { bool updated = false; foreach (var recipient in dm.Recipients) { if (recipient.Id == user.Id) { recipient.Update(user); updated = true; break; } } if (updated) // this is somewhat resource intensive, so let's reduce the uses as much as possible { dm.UpdateSelfJson(); } } } Task.Run(() => OnUserUpdated?.Invoke(this, new UserEventArgs(user))); break; case "GUILD_MEMBER_LIST_UPDATE": OnMemberListUpdate?.Invoke(this, payload.Deserialize <GuildMemberListEventArgs>()); break; case "GUILD_CREATE": { SocketGuild guild = payload.DeserializeEx <SocketGuild>().SetClient(this); if (Config.Cache) { GuildCache.Remove(guild.Id); GuildCache.Add(guild.Id, guild); } Task.Run(() => OnJoinedGuild?.Invoke(this, new SocketGuildEventArgs(guild, Lurking.HasValue && Lurking.Value == guild.Id))); } break; case "GUILD_UPDATE": { DiscordGuild guild = payload.Deserialize <DiscordGuild>().SetClient(this); if (Config.Cache) { GuildCache[guild].Update(guild); } Task.Run(() => OnGuildUpdated?.Invoke(this, new GuildEventArgs(guild))); } break; case "GUILD_DELETE": { UnavailableGuild guild = payload.Deserialize <UnavailableGuild>(); if (Lurking.HasValue && Lurking.Value == guild.Id) { Lurking = null; } if (Config.Cache) { if (guild.Unavailable) { GuildCache[guild.Id].Unavailable = true; } else { GuildCache.Remove(guild.Id); } GuildSettings.Remove(guild.Id); } Task.Run(() => OnLeftGuild?.Invoke(this, new GuildUnavailableEventArgs(guild))); } break; case "GUILD_MEMBER_ADD": Task.Run(() => OnUserJoinedGuild?.Invoke(this, new GuildMemberEventArgs(payload.Deserialize <GuildMember>().SetClient(this)))); break; case "GUILD_MEMBER_REMOVE": Task.Run(() => OnUserLeftGuild?.Invoke(this, new MemberRemovedEventArgs(payload.Deserialize <PartialGuildMember>().SetClient(this)))); break; case "GUILD_MEMBER_UPDATE": GuildMember member = payload.Deserialize <GuildMember>().SetClient(this); if (Config.Cache && member.User.Id == User.Id) { SocketGuild guild = this.GetCachedGuild(member.GuildId); // Discord doesn't send us the user's JoinedAt on updates member.JoinedAt = guild.Member.JoinedAt; guild.Member = member; break; } Task.Run(() => OnGuildMemberUpdated?.Invoke(this, new GuildMemberEventArgs(member))); break; case "GUILD_MEMBERS_CHUNK": Task.Run(() => OnGuildMembersReceived?.Invoke(this, new GuildMembersEventArgs(payload.Deserialize <GuildMemberList>().SetClient(this)))); break; case "GIFT_CODE_CREATE": Task.Run(() => OnGiftCodeCreated?.Invoke(this, payload.Deserialize <GiftCodeCreatedEventArgs>())); break; case "PRESENCE_UPDATE": Task.Run(() => OnUserPresenceUpdated?.Invoke(this, new PresenceUpdatedEventArgs(payload.DeserializeEx <DiscordPresence>().SetClient(this)))); break; case "VOICE_STATE_UPDATE": DiscordVoiceState newState = payload.Deserialize <DiscordVoiceState>().SetClient(this); if (Config.Cache) { // this doesn't work very well for bot accounts since those can be connected to a channel in multiple guilds at once. VoiceStates[newState.UserId] = newState; // we also store voice states within SocketGuilds, so make sure to update those. foreach (var guild in this.GetCachedGuilds()) { if (newState.Guild == null || guild.Id != newState.Guild.Id) { guild._voiceStates.RemoveAll(s => s.UserId == newState.UserId); } else { int i = guild._voiceStates.FindIndex(s => s.UserId == newState.UserId); if (i > -1) { guild._voiceStates[i] = newState; } else { guild._voiceStates.Add(newState); } } } } Task.Run(() => OnVoiceStateUpdated?.Invoke(this, new VoiceStateEventArgs(newState))); break; case "VOICE_SERVER_UPDATE": Task.Run(() => OnVoiceServer?.Invoke(this, payload.Deserialize <DiscordVoiceServer>().SetClient(this))); break; case "GUILD_ROLE_CREATE": { DiscordRole role = payload.Deserialize <RoleUpdate>().Role.SetClient(this); if (Config.Cache) { GuildCache[role.GuildId]._roles.Add(role); } Task.Run(() => OnRoleCreated?.Invoke(this, new RoleEventArgs(role))); } break; case "GUILD_ROLE_UPDATE": { DiscordRole role = payload.Deserialize <RoleUpdate>().Role.SetClient(this); if (Config.Cache) { var roles = GuildCache[role.GuildId]._roles; roles[roles.FindIndex(r => r.Id == role.Id)] = role; } Task.Run(() => OnRoleUpdated?.Invoke(this, new RoleEventArgs(role))); } break; case "GUILD_ROLE_DELETE": { DeletedRole role = payload.Deserialize <DeletedRole>().SetClient(this); if (Config.Cache) { GuildCache[role.Guild]._roles.RemoveAll(r => r.Id == role.Id); } Task.Run(() => OnRoleDeleted?.Invoke(this, new RoleDeletedEventArgs(role))); } break; case "GUILD_EMOJIS_UPDATE": var emojis = payload.Deserialize <EmojiContainer>().SetClient(this); if (Config.Cache) { GuildCache[emojis.GuildId]._emojis = emojis.Emojis.ToList(); } Task.Run(() => OnEmojisUpdated?.Invoke(this, new EmojisUpdatedEventArgs(emojis))); break; case "CHANNEL_CREATE": { var channel = payload.DeserializeEx <DiscordChannel>().SetClient(this); if (Config.Cache) { if (channel.Type == ChannelType.DM || channel.Type == ChannelType.Group) { PrivateChannels.Add(channel.ToDMChannel()); } else { GuildChannel guildChannel = channel.ToGuildChannel(); GuildCache[guildChannel.GuildId]._channels.Add(guildChannel); } } Task.Run(() => OnChannelCreated?.Invoke(this, new ChannelEventArgs(channel))); } break; case "CHANNEL_UPDATE": { var channel = payload.DeserializeEx <DiscordChannel>().SetClient(this); if (Config.Cache) { if (channel.Type == ChannelType.DM || channel.Type == ChannelType.Group) { PrivateChannels[PrivateChannels.FindIndex(c => c.Id == channel.Id)] = channel.ToDMChannel(); } else { GuildChannel guildChannel = channel.ToGuildChannel(); var channels = GuildCache[guildChannel.GuildId]._channels; channels[channels.FindIndex(c => c.Id == guildChannel.Id)] = guildChannel; } } Task.Run(() => OnChannelUpdated?.Invoke(this, new ChannelEventArgs(channel))); } break; case "CHANNEL_DELETE": { var channel = payload.DeserializeEx <DiscordChannel>().SetClient(this); if (Config.Cache) { if (channel.Type == ChannelType.DM || channel.Type == ChannelType.Group) { PrivateChannels.RemoveAll(c => c.Id == channel.Id); } else { GuildCache[channel.ToGuildChannel().GuildId]._channels.RemoveAll(c => c.Id == channel.Id); } } Task.Run(() => OnChannelDeleted?.Invoke(this, new ChannelEventArgs(channel))); } break; case "TYPING_START": Task.Run(() => OnUserTyping?.Invoke(this, new UserTypingEventArgs(payload.Deserialize <UserTyping>().SetClient(this)))); break; case "MESSAGE_CREATE": var message = payload.Deserialize <DiscordMessage>().SetClient(this); if (Config.Cache) { var channel = this.GetChannel(message.Channel.Id); channel.Json["last_message_id"] = JToken.FromObject(message.Id); } Task.Run(() => OnMessageReceived?.Invoke(this, new MessageEventArgs(message))); break; case "MESSAGE_UPDATE": Task.Run(() => OnMessageEdited?.Invoke(this, new MessageEventArgs(payload.Deserialize <DiscordMessage>().SetClient(this)))); break; case "MESSAGE_DELETE": Task.Run(() => OnMessageDeleted?.Invoke(this, new MessageDeletedEventArgs(payload.Deserialize <DeletedMessage>().SetClient(this)))); break; case "MESSAGE_REACTION_ADD": Task.Run(() => OnMessageReactionAdded?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this)))); break; case "MESSAGE_REACTION_REMOVE": Task.Run(() => OnMessageReactionRemoved?.Invoke(this, new ReactionEventArgs(payload.Deserialize <MessageReactionUpdate>().SetClient(this)))); break; case "GUILD_BAN_ADD": Task.Run(() => OnUserBanned?.Invoke(this, payload.Deserialize <BanUpdateEventArgs>().SetClient(this))); break; case "GUILD_BAN_REMOVE": Task.Run(() => OnUserUnbanned?.Invoke(this, payload.Deserialize <BanUpdateEventArgs>().SetClient(this))); break; case "INVITE_CREATE": Task.Run(() => OnInviteCreated?.Invoke(this, payload.Deserialize <InviteCreatedEventArgs>().SetClient(this))); break; case "INVITE_DELETE": Task.Run(() => OnInviteDeleted?.Invoke(this, payload.Deserialize <InviteDeletedEventArgs>().SetClient(this))); break; case "RELATIONSHIP_ADD": Task.Run(() => OnRelationshipAdded?.Invoke(this, new RelationshipEventArgs(payload.Deserialize <Relationship>().SetClient(this)))); break; case "RELATIONSHIP_REMOVE": Task.Run(() => OnRelationshipRemoved?.Invoke(this, new RelationshipEventArgs(payload.Deserialize <Relationship>().SetClient(this)))); break; case "CHANNEL_RECIPIENT_ADD": { var recipUpdate = payload.Deserialize <ChannelRecipientUpdate>().SetClient(this); if (Config.Cache) { foreach (var channel in PrivateChannels) { if (channel.Id == recipUpdate.Channel.Id) { channel._recipients.Add(recipUpdate.User); channel.UpdateSelfJson(); break; } } } } break; case "CHANNEL_RECIPIENT_REMOVE": { var recipUpdate = payload.Deserialize <ChannelRecipientUpdate>().SetClient(this); if (Config.Cache) { foreach (var channel in PrivateChannels) { if (channel.Id == recipUpdate.Channel.Id) { channel._recipients.RemoveAll(u => u.Id == recipUpdate.User.Id); channel.UpdateSelfJson(); break; } } } } break; case "MESSAGE_ACK": // triggered whenever another person logged into the account acknowledges a message break; case "SESSIONS_REPLACE": Task.Run(() => OnSessionsUpdated?.Invoke(this, new DiscordSessionsEventArgs(payload.Deserialize <List <DiscordSession> >()))); break; case "CALL_CREATE": { JObject obj = payload.Deserialize <JObject>(); var call = obj.ToObject <DiscordCall>().SetClient(this); var voiceStates = obj.Value <JToken>("voice_states").ToObject <IReadOnlyList <DiscordVoiceState> >().SetClientsInList(this); foreach (var state in voiceStates) { VoiceStates[state.UserId] = state; } Task.Run(() => OnRinging?.Invoke(this, new RingingEventArgs(call, voiceStates))); } break; case "CALL_UPDATE": Task.Run(() => OnCallUpdated?.Invoke(this, new CallUpdateEventArgs(payload.Deserialize <DiscordCall>().SetClient(this)))); break; case "CALL_DELETE": ulong channelId = payload.Deserialize <JObject>().Value <ulong>("channel_id"); foreach (var state in new Dictionary <ulong, DiscordVoiceState> .ValueCollection(VoiceStates)) { if (state.Channel != null && state.Channel.Id == channelId) { VoiceStates.Remove(state.UserId); } } Task.Run(() => OnCallEnded?.Invoke(this, channelId)); break; case "USER_PREMIUM_GUILD_SUBSCRIPTION_SLOT_UPDATE": Task.Run(() => OnBoostUpdated?.Invoke(this, new NitroBoostUpdatedEventArgs(payload.Deserialize <DiscordNitroBoost>().SetClient(this)))); break; } break; case GatewayOpcode.InvalidSession: LoggedIn = false; this.LoginToGateway(); break; case GatewayOpcode.Connected: this.LoginToGateway(); Task.Run(() => { int interval = payload.Deserialize <JObject>().GetValue("heartbeat_interval").ToObject <int>(); try { while (true) { this.Send(GatewayOpcode.Heartbeat, this.Sequence); Thread.Sleep(interval); } } catch { } }); break; } } catch { } }
private void OnMessage(object sender, byte[] messagePayload) { try { string payload = Encoding.UTF8.GetString(messagePayload); FizzTopicMessage message = new FizzTopicMessage(payload); FizzLogger.D("OnMessage with id: " + message.Id); switch (message.Type) { case "CMSGP": if (OnMessagePublished != null) { OnMessagePublished.Invoke(AdaptTo(message)); } break; case "CMSGU": if (OnMessageUpdated != null) { OnMessageUpdated.Invoke(AdaptTo(message)); } break; case "CMSGD": if (OnMessageDeleted != null) { OnMessageDeleted.Invoke(AdaptTo(message)); } break; case "GRPMA": if (OnGroupMemberAdded != null) { OnGroupMemberAdded.Invoke(ParseMemberEventData(message)); } break; case "GRPMU": if (OnGroupMemberUpdated != null) { OnGroupMemberUpdated.Invoke(ParseMemberEventData(message)); } break; case "GRPMR": if (OnGroupMemberRemoved != null) { OnGroupMemberRemoved.Invoke(ParseMemberEventData(message)); } break; case "GRPU": if (OnGroupUpdated != null) { OnGroupUpdated.Invoke(ParseGroupUpdateEventData(message)); } break; case "USRPU": if (OnUserUpdated != null) { OnUserUpdated.Invoke(ParsePresenceUpdateEventData(message)); } break; case "USRU": if (OnUserUpdated != null) { OnUserUpdated.Invoke(ParseUserUpdateEventData(message)); } break; default: FizzLogger.W("unrecognized packet received: " + payload); break; } } catch { FizzLogger.W("received invalid message: " + messagePayload); } }
public PubSub(EndPoint proxy = null) : base(null) { ThreadDispatcher.EnsureCreated(); base.OnPubSubServiceConnected += ((object sender, EventArgs e) => { ThreadDispatcher.Enqueue(() => OnPubSubServiceConnected?.Invoke(sender, e)); }); base.OnPubSubServiceError += ((object sender, OnPubSubServiceErrorArgs e) => { ThreadDispatcher.Enqueue(() => OnPubSubServiceError?.Invoke(sender, e)); }); base.OnPubSubServiceClosed += ((object sender, EventArgs e) => { ThreadDispatcher.Enqueue(() => OnPubSubServiceClosed?.Invoke(sender, e)); }); base.OnListenResponse += ((object sender, OnListenResponseArgs e) => { ThreadDispatcher.Enqueue(() => OnListenResponse?.Invoke(sender, e)); }); base.OnTimeout += ((object sender, OnTimeoutArgs e) => { ThreadDispatcher.Enqueue(() => OnTimeout?.Invoke(sender, e)); }); base.OnBan += ((object sender, OnBanArgs e) => { ThreadDispatcher.Enqueue(() => OnBan?.Invoke(sender, e)); }); base.OnUnban += ((object sender, OnUnbanArgs e) => { ThreadDispatcher.Enqueue(() => OnUnban?.Invoke(sender, e)); }); base.OnUntimeout += ((object sender, OnUntimeoutArgs e) => { ThreadDispatcher.Enqueue(() => OnUntimeout?.Invoke(sender, e)); }); base.OnHost += ((object sender, OnHostArgs e) => { ThreadDispatcher.Enqueue(() => OnHost?.Invoke(sender, e)); }); base.OnSubscribersOnly += ((object sender, OnSubscribersOnlyArgs e) => { ThreadDispatcher.Enqueue(() => OnSubscribersOnly?.Invoke(sender, e)); }); base.OnSubscribersOnlyOff += ((object sender, OnSubscribersOnlyOffArgs e) => { ThreadDispatcher.Enqueue(() => OnSubscribersOnlyOff?.Invoke(sender, e)); }); base.OnClear += ((object sender, OnClearArgs e) => { ThreadDispatcher.Enqueue(() => OnClear?.Invoke(sender, e)); }); base.OnEmoteOnly += ((object sender, OnEmoteOnlyArgs e) => { ThreadDispatcher.Enqueue(() => OnEmoteOnly?.Invoke(sender, e)); }); base.OnEmoteOnlyOff += ((object sender, OnEmoteOnlyOffArgs e) => { ThreadDispatcher.Enqueue(() => OnEmoteOnlyOff?.Invoke(sender, e)); }); base.OnR9kBeta += ((object sender, OnR9kBetaArgs e) => { ThreadDispatcher.Enqueue(() => OnR9kBeta?.Invoke(sender, e)); }); base.OnR9kBetaOff += ((object sender, OnR9kBetaOffArgs e) => { ThreadDispatcher.Enqueue(() => OnR9kBetaOff?.Invoke(sender, e)); }); base.OnBitsReceived += ((object sender, OnBitsReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnBitsReceived?.Invoke(sender, e)); }); base.OnStreamUp += ((object sender, OnStreamUpArgs arg) => { ThreadDispatcher.Enqueue(() => OnStreamUp(sender, arg)); }); base.OnStreamDown += ((object sender, OnStreamDownArgs e) => { ThreadDispatcher.Enqueue(() => OnStreamDown?.Invoke(sender, e)); }); base.OnViewCount += ((object sender, OnViewCountArgs e) => { ThreadDispatcher.Enqueue(() => OnViewCount?.Invoke(sender, e)); }); base.OnWhisper += ((object sender, OnWhisperArgs e) => { ThreadDispatcher.Enqueue(() => OnWhisper?.Invoke(sender, e)); }); base.OnChannelSubscription += ((object sender, OnChannelSubscriptionArgs e) => { ThreadDispatcher.Enqueue(() => OnChannelSubscription?.Invoke(sender, e)); }); base.OnChannelCommerceReceived += ((object sender, OnChannelCommerceReceivedArgs e) => { ThreadDispatcher.Enqueue(() => OnChannelCommerceReceived?.Invoke(sender, e)); }); base.OnChannelExtensionBroadcast += ((object sender, OnChannelExtensionBroadcastArgs e) => { ThreadDispatcher.Enqueue(() => OnChannelExtensionBroadcast?.Invoke(sender, e)); }); base.OnFollow += ((object sender, OnFollowArgs e) => { ThreadDispatcher.Enqueue(() => OnFollow?.Invoke(sender, e)); }); base.OnCustomRewardCreated += ((object sender, OnCustomRewardCreatedArgs e) => { ThreadDispatcher.Enqueue(() => OnCustomRewardCreated?.Invoke(sender, e)); }); base.OnCustomRewardUpdated += ((object sender, OnCustomRewardUpdatedArgs e) => { ThreadDispatcher.Enqueue(() => OnCustomRewardUpdated?.Invoke(sender, e)); }); base.OnCustomRewardDeleted += ((object sender, OnCustomRewardDeletedArgs e) => { ThreadDispatcher.Enqueue(() => OnCustomRewardDeleted?.Invoke(sender, e)); }); base.OnRewardRedeemed += ((object sender, OnRewardRedeemedArgs e) => { ThreadDispatcher.Enqueue(() => OnRewardRedeemed?.Invoke(sender, e)); }); base.OnBitsReceivedV2 += ((object sender, OnBitsReceivedV2Args e) => { ThreadDispatcher.Enqueue(() => OnBitsReceivedV2?.Invoke(sender, e)); }); base.OnLeaderboardSubs += ((object sender, OnLeaderboardEventArgs e) => { ThreadDispatcher.Enqueue(() => OnLeaderboardSubs?.Invoke(sender, e)); }); base.OnLeaderboardBits += ((object sender, OnLeaderboardEventArgs e) => { ThreadDispatcher.Enqueue(() => OnLeaderboardBits?.Invoke(sender, e)); }); base.OnRaidUpdate += ((object sender, OnRaidUpdateArgs e) => { ThreadDispatcher.Enqueue(() => OnRaidUpdate?.Invoke(sender, e)); }); base.OnRaidUpdateV2 += ((object sender, OnRaidUpdateV2Args e) => { ThreadDispatcher.Enqueue(() => OnRaidUpdateV2?.Invoke(sender, e)); }); base.OnRaidGo += ((object sender, OnRaidGoArgs e) => { ThreadDispatcher.Enqueue(() => OnRaidGo?.Invoke(sender, e)); }); base.OnMessageDeleted += ((object sender, OnMessageDeletedArgs e) => { ThreadDispatcher.Enqueue(() => OnMessageDeleted?.Invoke(sender, e)); }); base.OnLog += ((object sender, OnLogArgs e) => { ThreadDispatcher.Enqueue(() => OnLog?.Invoke(sender, e)); }); base.OnCommercial += ((object sender, OnCommercialArgs e) => { ThreadDispatcher.Enqueue(() => OnCommercial?.Invoke(sender, e)); }); base.OnPrediction += ((object sender, OnPredictionArgs e) => { ThreadDispatcher.Enqueue(() => OnPrediction?.Invoke(sender, e)); }); }
private void WebSocket_OnMessageReceived(object sender, DiscordWebSocketMessage <GatewayOpcode> message) { Sequence = message.Sequence; switch (message.Opcode) { case GatewayOpcode.Event: /* * Console.WriteLine(message.EventName); * * File.AppendAllText("Debug.log", $"{message.EventName}: {message.Data}\n"); */ switch (message.EventName) { case "READY": LoginEventArgs login = message.Data.ToObject <LoginEventArgs>().SetClient(this); if (login.Application != null) { _appId = login.Application.Value <ulong>("id"); } this.User = login.User; this.UserSettings = login.Settings; this.SessionId = login.SessionId; if (Config.Cache && this.User.Type == DiscordUserType.User) { PrivateChannels.AddRange(login.PrivateChannels); foreach (var presence in login.Presences) { Presences[presence.UserId] = presence; } foreach (var guild in login.Guilds) { ApplyGuild(GuildCache[guild.Id] = (SocketGuild)guild); VoiceClients[guild.Id] = new DiscordVoiceClient(this, guild.Id); } foreach (var settings in login.ClientGuildSettings) { if (settings.GuildId.HasValue) { GuildSettings.Add(settings.Guild.Id, settings); } else { PrivateChannelSettings = settings.ChannelOverrides.ToList(); } } } LoggedIn = true; State = GatewayConnectionState.Connected; if (OnLoggedIn != null) { Task.Run(() => OnLoggedIn.Invoke(this, login)); } break; case "USER_SETTINGS_UPDATE": if (UserSettings == null) { } UserSettings.Update((JObject)message.Data); if (OnSettingsUpdated != null) { Task.Run(() => OnSettingsUpdated.Invoke(this, new DiscordSettingsEventArgs(UserSettings))); } break; case "USER_GUILD_SETTINGS_UPDATE": if (Config.Cache) { ClientGuildSettings settings = message.Data.ToObject <ClientGuildSettings>(); if (settings.GuildId.HasValue) { GuildSettings[settings.Guild.Id] = settings; } else { PrivateChannelSettings = settings.ChannelOverrides.ToList(); } } break; case "USER_UPDATE": DiscordUser user = message.Data.ToObject <DiscordUser>().SetClient(this); if (user.Id == User.Id) { User.Update(user); } if (Config.Cache) { lock (PrivateChannels.Lock) { foreach (var dm in PrivateChannels) { foreach (var recipient in dm.Recipients) { if (recipient.Id == user.Id) { recipient.Update(user); break; } } } } } if (OnUserUpdated != null) { Task.Run(() => OnUserUpdated.Invoke(this, new UserEventArgs(user))); } break; case "GUILD_MEMBER_LIST_UPDATE": OnMemberListUpdate?.Invoke(this, message.Data.ToObject <GuildMemberListEventArgs>()); break; case "GUILD_CREATE": if (Config.Cache || OnJoinedGuild != null) { var guild = message.Data.ToObject <SocketGuild>().SetClient(this); VoiceClients[guild.Id] = new DiscordVoiceClient(this, guild.Id); if (Config.Cache) { ApplyGuild(GuildCache[guild.Id] = guild); } if (OnJoinedGuild != null) { Task.Run(() => OnJoinedGuild.Invoke(this, new SocketGuildEventArgs(guild, Lurking.HasValue && Lurking.Value == guild.Id))); } } break; case "GUILD_UPDATE": if (Config.Cache || OnGuildUpdated != null) { DiscordGuild guild = message.Data.ToObject <DiscordGuild>().SetClient(this); if (Config.Cache) { GuildCache[guild.Id].Update(guild); } Task.Run(() => OnGuildUpdated?.Invoke(this, new GuildEventArgs(guild))); } break; case "GUILD_DELETE": { UnavailableGuild guild = message.Data.ToObject <UnavailableGuild>(); VoiceClients.Remove(guild.Id); if (Lurking.HasValue && Lurking.Value == guild.Id) { Lurking = null; } if (Config.Cache) { if (guild.Unavailable) { GuildCache[guild.Id].Unavailable = true; } else { GuildCache.Remove(guild.Id); GuildSettings.Remove(guild.Id); } } if (OnLeftGuild != null) { Task.Run(() => OnLeftGuild.Invoke(this, new GuildUnavailableEventArgs(guild))); } } break; case "GUILD_MEMBER_ADD": if (Config.Cache || OnUserJoinedGuild != null) { var member = message.Data.ToObject <GuildMember>().SetClient(this); if (Config.Cache) { GuildCache[member.GuildId].MemberCount++; } Task.Run(() => OnUserJoinedGuild?.Invoke(this, new GuildMemberEventArgs(member))); } break; case "GUILD_MEMBER_REMOVE": if (Config.Cache || OnUserLeftGuild != null) { var member = message.Data.ToObject <PartialGuildMember>().SetClient(this); if (Config.Cache) { GuildCache[member.GuildId].MemberCount--; } Task.Run(() => OnUserLeftGuild?.Invoke(this, new MemberRemovedEventArgs(member))); } break; case "GUILD_MEMBER_UPDATE": if (Config.Cache || OnGuildMemberUpdated != null) { GuildMember member = message.Data.ToObject <GuildMember>().SetClient(this); if (Config.Cache && member.User.Id == User.Id) { SocketGuild guild = this.GetCachedGuild(member.GuildId); // Discord doesn't send us the user's JoinedAt on updates member.JoinedAt = guild.ClientMember.JoinedAt; ClientMembers[guild.Id] = member; break; } Task.Run(() => OnGuildMemberUpdated.Invoke(this, new GuildMemberEventArgs(member))); } break; case "GUILD_MEMBERS_CHUNK": Task.Run(() => OnGuildMembersReceived?.Invoke(this, new GuildMembersEventArgs(message.Data.ToObject <GuildMemberList>().SetClient(this)))); break; case "GIFT_CODE_CREATE": if (OnGiftCodeCreated != null) { Task.Run(() => OnGiftCodeCreated.Invoke(this, message.Data.ToObject <GiftCodeCreatedEventArgs>())); } break; case "GIFT_CODE_UPDATE": if (OnGiftUpdated != null) { var gift = message.Data.ToObject <GiftCodeUpdatedEventArgs>().SetClient(this); gift.Json = (JObject)message.Data; Task.Run(() => OnGiftUpdated.Invoke(this, gift)); } break; case "PRESENCE_UPDATE": if (Config.Cache || OnUserPresenceUpdated != null) { var presence = message.Data.ToObject <DiscordPresence>().SetClient(this); if (Config.Cache) { if (Presences.TryGetValue(presence.UserId, out DiscordPresence existingPresence)) { existingPresence.Update(presence); presence = existingPresence; } else { Presences[presence.UserId] = presence; } } if (OnUserPresenceUpdated != null) { Task.Run(() => OnUserPresenceUpdated.Invoke(this, new PresenceUpdatedEventArgs(presence))); } } break; case "VOICE_STATE_UPDATE": DiscordVoiceState newState = message.Data.ToObject <DiscordVoiceState>().SetClient(this); if (Config.Cache) { if (newState.Guild == null) { VoiceStates[newState.UserId].PrivateChannelVoiceState = newState; } else { VoiceStates[newState.UserId].GuildStates[newState.Guild.Id] = newState; } // we also store voice states within SocketGuilds, so make sure to update those. foreach (var guild in this.GetCachedGuilds()) { if (!guild.Unavailable) { if (newState.Guild == null || guild.Id != newState.Guild.Id) { guild._voiceStates.RemoveFirst(s => s.UserId == newState.UserId); } else { int i = guild._voiceStates.FindIndex(s => s.UserId == newState.UserId); if (i > -1) { guild._voiceStates[i] = newState; } else { guild._voiceStates.Add(newState); } } } } } if (newState.UserId == User.Id) { if (newState.Guild == null) { VoiceClients.Private.SetSessionId(newState.SessionId); } else { VoiceClients[newState.Guild.Id].SetSessionId(newState.SessionId); } } if (OnVoiceStateUpdated != null) { Task.Run(() => OnVoiceStateUpdated.Invoke(this, new VoiceStateEventArgs(newState))); } break; case "VOICE_SERVER_UPDATE": OnMediaServer?.Invoke(this, message.Data.ToObject <DiscordMediaServer>().SetClient(this)); break; case "GUILD_ROLE_CREATE": if (Config.Cache || OnRoleCreated != null) { DiscordRole role = message.Data.ToObject <RoleUpdate>().Role.SetClient(this); if (Config.Cache) { GuildCache[role.GuildId]._roles.Add(role); } if (OnRoleCreated != null) { Task.Run(() => OnRoleCreated.Invoke(this, new RoleEventArgs(role))); } } break; case "GUILD_ROLE_UPDATE": if (Config.Cache || OnRoleUpdated != null) { DiscordRole role = message.Data.ToObject <RoleUpdate>().Role.SetClient(this); if (Config.Cache) { GuildCache[role.GuildId]._roles.ReplaceFirst(r => r.Id == role.Id, role); } if (OnRoleUpdated != null) { Task.Run(() => OnRoleUpdated.Invoke(this, new RoleEventArgs(role))); } } break; case "GUILD_ROLE_DELETE": if (Config.Cache || OnRoleDeleted != null) { DeletedRole role = message.Data.ToObject <DeletedRole>().SetClient(this); if (Config.Cache) { GuildCache[role.Guild]._roles.RemoveFirst(r => r.Id == role.Id); } if (OnRoleDeleted != null) { Task.Run(() => OnRoleDeleted.Invoke(this, new RoleDeletedEventArgs(role))); } } break; case "GUILD_EMOJIS_UPDATE": if (Config.Cache || OnEmojisUpdated != null) { var emojis = message.Data.ToObject <EmojiContainer>().SetClient(this); if (Config.Cache) { GuildCache[emojis.GuildId]._emojis = emojis.Emojis.ToList(); } if (OnEmojisUpdated != null) { Task.Run(() => OnEmojisUpdated.Invoke(this, new EmojisUpdatedEventArgs(emojis))); } } break; case "CHANNEL_CREATE": if (Config.Cache || OnChannelCreated != null) { var channel = ((JObject)message.Data).ParseDeterministic <DiscordChannel>(); if (Config.Cache) { if (channel.Type == ChannelType.DM || channel.Type == ChannelType.Group) { PrivateChannels.Add((PrivateChannel)channel); } else { GuildChannel guildChannel = (GuildChannel)channel; GuildCache[guildChannel.GuildId].ChannelsConcurrent.Add(guildChannel); } } if (OnChannelCreated != null) { Task.Run(() => OnChannelCreated.Invoke(this, new ChannelEventArgs(channel))); } } break; case "CHANNEL_UPDATE": if (Config.Cache || OnChannelUpdated != null) { var channel = ((JObject)message.Data).ParseDeterministic <DiscordChannel>(); if (Config.Cache) { if (channel.Type == ChannelType.DM || channel.Type == ChannelType.Group) { PrivateChannels.ReplaceFirst(c => c.Id == channel.Id, (PrivateChannel)channel); } else { GuildChannel guildChannel = (GuildChannel)channel; GuildCache[guildChannel.GuildId].ChannelsConcurrent.ReplaceFirst(c => c.Id == guildChannel.Id, guildChannel); } } if (OnChannelUpdated != null) { Task.Run(() => OnChannelUpdated.Invoke(this, new ChannelEventArgs(channel))); } } break; case "CHANNEL_DELETE": if (Config.Cache || OnChannelDeleted != null) { var channel = ((JObject)message.Data).ParseDeterministic <DiscordChannel>(); if (Config.Cache) { if (channel.Type == ChannelType.DM || channel.Type == ChannelType.Group) { PrivateChannels.RemoveFirst(c => c.Id == channel.Id); } else { GuildCache[((GuildChannel)channel).GuildId].ChannelsConcurrent.RemoveFirst(c => c.Id == channel.Id); } } if (OnChannelDeleted != null) { Task.Run(() => OnChannelDeleted.Invoke(this, new ChannelEventArgs(channel))); } } break; case "TYPING_START": if (OnUserTyping != null) { Task.Run(() => OnUserTyping.Invoke(this, new UserTypingEventArgs(message.Data.ToObject <UserTyping>().SetClient(this)))); } break; case "MESSAGE_CREATE": if (Config.Cache || OnMessageReceived != null) { var newMessage = message.Data.ToObject <DiscordMessage>().SetClient(this); if (Config.Cache) { try { this.GetChannel(newMessage.Channel.Id).SetLastMessageId(newMessage.Id); } catch (DiscordHttpException) { } } if (OnMessageReceived != null) { Task.Run(() => OnMessageReceived.Invoke(this, new MessageEventArgs(newMessage))); } } break; case "MESSAGE_UPDATE": if (OnMessageEdited != null) { Task.Run(() => OnMessageEdited.Invoke(this, new MessageEventArgs(message.Data.ToObject <DiscordMessage>().SetClient(this)))); } break; case "MESSAGE_DELETE": if (OnMessageDeleted != null) { Task.Run(() => OnMessageDeleted.Invoke(this, new MessageDeletedEventArgs(message.Data.ToObject <DeletedMessage>().SetClient(this)))); } break; case "MESSAGE_REACTION_ADD": if (OnMessageReactionAdded != null) { Task.Run(() => OnMessageReactionAdded.Invoke(this, new ReactionEventArgs(message.Data.ToObject <MessageReactionUpdate>().SetClient(this)))); } break; case "MESSAGE_REACTION_REMOVE": if (OnMessageReactionRemoved != null) { Task.Run(() => OnMessageReactionRemoved.Invoke(this, new ReactionEventArgs(message.Data.ToObject <MessageReactionUpdate>().SetClient(this)))); } break; case "GUILD_BAN_ADD": if (OnUserBanned != null) { Task.Run(() => OnUserBanned.Invoke(this, message.Data.ToObject <BanUpdateEventArgs>().SetClient(this))); } break; case "GUILD_BAN_REMOVE": if (OnUserUnbanned != null) { Task.Run(() => OnUserUnbanned.Invoke(this, message.Data.ToObject <BanUpdateEventArgs>().SetClient(this))); } break; case "INVITE_CREATE": if (OnInviteCreated != null) { Task.Run(() => OnInviteCreated.Invoke(this, message.Data.ToObject <InviteCreatedEventArgs>().SetClient(this))); } break; case "INVITE_DELETE": if (OnInviteDeleted != null) { Task.Run(() => OnInviteDeleted.Invoke(this, message.Data.ToObject <InviteDeletedEventArgs>().SetClient(this))); } break; case "RELATIONSHIP_ADD": if (OnRelationshipAdded != null) { Task.Run(() => OnRelationshipAdded.Invoke(this, new RelationshipEventArgs(message.Data.ToObject <DiscordRelationship>().SetClient(this)))); } break; case "RELATIONSHIP_REMOVE": if (OnRelationshipRemoved != null) { Task.Run(() => OnRelationshipRemoved.Invoke(this, message.Data.ToObject <RemovedRelationshipEventArgs>())); } break; case "CHANNEL_RECIPIENT_ADD": if (Config.Cache || OnChannelRecipientAdded != null) { var recipUpdate = message.Data.ToObject <ChannelRecipientEventArgs>().SetClient(this); if (Config.Cache) { ((PrivateChannel)this.GetChannel(recipUpdate.Channel.Id))._recipients.Add(recipUpdate.User); } if (OnChannelRecipientAdded != null) { Task.Run(() => OnChannelRecipientAdded.Invoke(this, recipUpdate)); } } break; case "CHANNEL_RECIPIENT_REMOVE": if (Config.Cache || OnChannelRecipientAdded != null) { var recipUpdate = message.Data.ToObject <ChannelRecipientEventArgs>().SetClient(this); if (Config.Cache) { ((PrivateChannel)this.GetChannel(recipUpdate.Channel.Id))._recipients.RemoveFirst(u => u.Id == recipUpdate.User.Id); } if (OnChannelRecipientRemoved != null) { Task.Run(() => OnChannelRecipientRemoved.Invoke(this, recipUpdate)); } } break; case "MESSAGE_ACK": // triggered whenever another person logged into the account acknowledges a message break; case "SESSIONS_REPLACE": if (OnSessionsUpdated != null) { Task.Run(() => OnSessionsUpdated.Invoke(this, new DiscordSessionsEventArgs(message.Data.ToObject <List <DiscordSession> >()))); } break; case "CALL_CREATE": if (Config.Cache || OnRinging != null) { var call = message.Data.ToObject <DiscordCall>().SetClient(this); var voiceStates = message.Data.Value <JToken>("voice_states").ToObject <IReadOnlyList <DiscordVoiceState> >().SetClientsInList(this); if (Config.Cache) { foreach (var state in voiceStates) { VoiceStates[state.UserId].PrivateChannelVoiceState = state; } } if (OnRinging != null) { Task.Run(() => OnRinging.Invoke(this, new RingingEventArgs(call, voiceStates))); } } break; case "CALL_UPDATE": if (OnCallUpdated != null) { Task.Run(() => OnCallUpdated.Invoke(this, new CallUpdateEventArgs(message.Data.ToObject <DiscordCall>().SetClient(this)))); } break; case "CALL_DELETE": if (Config.Cache || OnCallEnded != null) { ulong channelId = message.Data.Value <ulong>("channel_id"); if (Config.Cache) { foreach (var state in VoiceStates.CreateCopy().Values) { var privState = state.PrivateChannelVoiceState; if (privState != null && privState.Channel != null && privState.Channel.Id == channelId) { state.PrivateChannelVoiceState = null; } } } if (OnCallEnded != null) { Task.Run(() => OnCallEnded.Invoke(this, new MinimalTextChannel(channelId).SetClient(this))); } } break; case "ENTITLEMENT_CREATE": if (OnEntitlementCreated != null) { Task.Run(() => OnEntitlementCreated.Invoke(this, new EntitlementEventArgs(message.Data.ToObject <DiscordEntitlement>()))); } break; case "ENTITLEMENT_UPDATE": if (OnEntitlementUpdated != null) { Task.Run(() => OnEntitlementUpdated.Invoke(this, new EntitlementEventArgs(message.Data.ToObject <DiscordEntitlement>()))); } break; case "USER_PREMIUM_GUILD_SUBSCRIPTION_SLOT_CREATE": if (OnBoostSlotCreated != null) { Task.Run(() => OnBoostSlotCreated.Invoke(this, new NitroBoostEventArgs(message.Data.ToObject <DiscordBoostSlot>().SetClient(this)))); } break; case "USER_PREMIUM_GUILD_SUBSCRIPTION_SLOT_UPDATE": if (OnBoostSlotUpdated != null) { Task.Run(() => OnBoostSlotUpdated.Invoke(this, new NitroBoostEventArgs(message.Data.ToObject <DiscordBoostSlot>().SetClient(this)))); } break; case "STREAM_SERVER_UPDATE": OnMediaServer?.Invoke(this, message.Data.ToObject <DiscordMediaServer>().SetClient(this)); break; case "STREAM_CREATE": var create = message.Data.ToObject <GoLiveCreate>(); GetVoiceClient(new StreamKey(create.StreamKey).GuildId).Livestream.CreateSession(create); break; case "STREAM_UPDATE": var update = message.Data.ToObject <GoLiveUpdate>(); GetVoiceClient(new StreamKey(update.StreamKey).GuildId).Livestream.UpdateSession(update); break; case "STREAM_DELETE": var delete = message.Data.ToObject <GoLiveDelete>(); GetVoiceClient(new StreamKey(delete.StreamKey).GuildId).Livestream.KillSession(delete); break; case "CHANNEL_UNREAD_UPDATE": if (Config.Cache || OnGuildUnreadMessagesUpdated != null) { var unread = message.Data.ToObject <GuildUnreadMessages>().SetClient(this); if (Config.Cache) { foreach (var unreadChannel in unread.Channels) { this.GetChannel(unreadChannel.Channel.Id).SetLastMessageId(unreadChannel.LastMessageId); } } if (OnGuildUnreadMessagesUpdated != null) { Task.Run(() => OnGuildUnreadMessagesUpdated.Invoke(this, new UnreadMessagesEventArgs(unread))); } } break; case "INTERACTION_CREATE": if (OnInteraction != null) { Task.Run(() => OnInteraction.Invoke(this, new DiscordInteractionEventArgs(message.Data.ToObject <DiscordInteraction>().SetClient(this)))); } break; case "USER_REQUIRED_ACTION_UPDATE": if (OnRequiredUserAction != null) { Task.Run(() => OnRequiredUserAction.Invoke(this, message.Data.ToObject <RequiredActionEventArgs>())); } break; default: break; } break; case GatewayOpcode.InvalidSession: LoggedIn = false; this.LoginToGateway(); break; case GatewayOpcode.Connected: this.LoginToGateway(); Task.Run(() => { int interval = message.Data.ToObject <JObject>().GetValue("heartbeat_interval").ToObject <int>() - 1000; try { while (true) { this.Send(GatewayOpcode.Heartbeat, this.Sequence); Thread.Sleep(interval); } } catch { } }); break; } }
/// <summary> /// Parses the message. /// </summary> /// <param name="message">The message.</param> private void ParseMessage(string message) { var type = JObject.Parse(message).SelectToken("type")?.ToString(); switch (type?.ToLower()) { case "response": var resp = new Models.Responses.Response(message); if (_previousRequests.Count != 0) { bool handled = false; _previousRequestsSemaphore.WaitOne(); try { for (int i = 0; i < _previousRequests.Count;) { var request = _previousRequests[i]; if (string.Equals(request.Nonce, resp.Nonce, StringComparison.CurrentCulture)) { //Remove the request. _previousRequests.RemoveAt(i); _topicToChannelId.TryGetValue(request.Topic, out var requestChannelId); OnListenResponse?.Invoke(this, new OnListenResponseArgs { Response = resp, Topic = request.Topic, Successful = resp.Successful, ChannelId = requestChannelId }); handled = true; } else { i++; } } } finally { _previousRequestsSemaphore.Release(); } if (handled) { return; } } break; case "message": var msg = new Models.Responses.Message(message); _topicToChannelId.TryGetValue(msg.Topic, out var channelId); channelId = channelId ?? ""; switch (msg.Topic.Split('.')[0]) { case "user-moderation-notifications": var userModerationNotifications = msg.MessageData as UserModerationNotifications; switch (userModerationNotifications.Type) { case UserModerationNotificationsType.AutomodCaughtMessage: var automodCaughtMessage = userModerationNotifications.Data as Models.Responses.Messages.UserModerationNotificationsTypes.AutomodCaughtMessage; OnAutomodCaughtUserMessage?.Invoke(this, new OnAutomodCaughtUserMessage { ChannelId = channelId, UserId = msg.Topic.Split('.')[2], AutomodCaughtMessage = automodCaughtMessage }); break; case UserModerationNotificationsType.Unknown: break; } return; case "automod-queue": var automodQueue = msg.MessageData as AutomodQueue; switch (automodQueue.Type) { case AutomodQueueType.CaughtMessage: var caughtMessage = automodQueue.Data as AutomodCaughtMessage; OnAutomodCaughtMessage?.Invoke(this, new OnAutomodCaughtMessageArgs { ChannelId = channelId, AutomodCaughtMessage = caughtMessage }); break; case AutomodQueueType.Unknown: UnaccountedFor($"Unknown automod queue type. Msg: {automodQueue.RawData}"); break; } return; case "channel-subscribe-events-v1": var subscription = msg.MessageData as ChannelSubscription; OnChannelSubscription?.Invoke(this, new OnChannelSubscriptionArgs { Subscription = subscription, ChannelId = channelId }); return; case "whispers": var whisper = (Whisper)msg.MessageData; OnWhisper?.Invoke(this, new OnWhisperArgs { Whisper = whisper, ChannelId = channelId }); return; case "chat_moderator_actions": var cma = msg.MessageData as ChatModeratorActions; var reason = ""; switch (cma?.ModerationAction.ToLower()) { case "timeout": if (cma.Args.Count > 2) { reason = cma.Args[2]; } OnTimeout?.Invoke(this, new OnTimeoutArgs { TimedoutBy = cma.CreatedBy, TimedoutById = cma.CreatedByUserId, TimedoutUserId = cma.TargetUserId, TimeoutDuration = TimeSpan.FromSeconds(int.Parse(cma.Args[1])), TimeoutReason = reason, TimedoutUser = cma.Args[0], ChannelId = channelId }); return; case "ban": if (cma.Args.Count > 1) { reason = cma.Args[1]; } OnBan?.Invoke(this, new OnBanArgs { BannedBy = cma.CreatedBy, BannedByUserId = cma.CreatedByUserId, BannedUserId = cma.TargetUserId, BanReason = reason, BannedUser = cma.Args[0], ChannelId = channelId }); return; case "delete": OnMessageDeleted?.Invoke(this, new OnMessageDeletedArgs { DeletedBy = cma.CreatedBy, DeletedByUserId = cma.CreatedByUserId, TargetUserId = cma.TargetUserId, TargetUser = cma.Args[0], Message = cma.Args[1], MessageId = cma.Args[2], ChannelId = channelId }); return; case "unban": OnUnban?.Invoke(this, new OnUnbanArgs { UnbannedBy = cma.CreatedBy, UnbannedByUserId = cma.CreatedByUserId, UnbannedUserId = cma.TargetUserId, UnbannedUser = cma.Args[0], ChannelId = channelId }); return; case "untimeout": OnUntimeout?.Invoke(this, new OnUntimeoutArgs { UntimeoutedBy = cma.CreatedBy, UntimeoutedByUserId = cma.CreatedByUserId, UntimeoutedUserId = cma.TargetUserId, UntimeoutedUser = cma.Args[0], ChannelId = channelId }); return; case "host": OnHost?.Invoke(this, new OnHostArgs { HostedChannel = cma.Args[0], Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "subscribers": OnSubscribersOnly?.Invoke(this, new OnSubscribersOnlyArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "subscribersoff": OnSubscribersOnlyOff?.Invoke(this, new OnSubscribersOnlyOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "clear": OnClear?.Invoke(this, new OnClearArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "emoteonly": OnEmoteOnly?.Invoke(this, new OnEmoteOnlyArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "emoteonlyoff": OnEmoteOnlyOff?.Invoke(this, new OnEmoteOnlyOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "r9kbeta": OnR9kBeta?.Invoke(this, new OnR9kBetaArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; case "r9kbetaoff": OnR9kBetaOff?.Invoke(this, new OnR9kBetaOffArgs { Moderator = cma.CreatedBy, ChannelId = channelId }); return; } break; case "channel-bits-events-v1": if (msg.MessageData is ChannelBitsEvents cbe) { OnBitsReceived?.Invoke(this, new OnBitsReceivedArgs { BitsUsed = cbe.BitsUsed, ChannelId = cbe.ChannelId, ChannelName = cbe.ChannelName, ChatMessage = cbe.ChatMessage, Context = cbe.Context, Time = cbe.Time, TotalBitsUsed = cbe.TotalBitsUsed, UserId = cbe.UserId, Username = cbe.Username }); return; } break; case "channel-bits-events-v2": if (msg.MessageData is ChannelBitsEventsV2 cbev2) { OnBitsReceivedV2?.Invoke(this, new OnBitsReceivedV2Args { IsAnonymous = cbev2.IsAnonymous, BitsUsed = cbev2.BitsUsed, ChannelId = cbev2.ChannelId, ChannelName = cbev2.ChannelName, ChatMessage = cbev2.ChatMessage, Context = cbev2.Context, Time = cbev2.Time, TotalBitsUsed = cbev2.TotalBitsUsed, UserId = cbev2.UserId, UserName = cbev2.UserName }); return; } break; case "channel-commerce-events-v1": if (msg.MessageData is ChannelCommerceEvents cce) { OnChannelCommerceReceived?.Invoke(this, new OnChannelCommerceReceivedArgs { Username = cce.Username, DisplayName = cce.DisplayName, ChannelName = cce.ChannelName, UserId = cce.UserId, ChannelId = cce.ChannelId, Time = cce.Time, ItemImageURL = cce.ItemImageURL, ItemDescription = cce.ItemDescription, SupportsChannel = cce.SupportsChannel, PurchaseMessage = cce.PurchaseMessage }); return; } break; case "channel-ext-v1": var cEB = msg.MessageData as ChannelExtensionBroadcast; OnChannelExtensionBroadcast?.Invoke(this, new OnChannelExtensionBroadcastArgs { Messages = cEB.Messages, ChannelId = channelId }); return; case "video-playback-by-id": var vP = msg.MessageData as VideoPlayback; switch (vP?.Type) { case VideoPlaybackType.StreamDown: OnStreamDown?.Invoke(this, new OnStreamDownArgs { ServerTime = vP.ServerTime, ChannelId = channelId }); return; case VideoPlaybackType.StreamUp: OnStreamUp?.Invoke(this, new OnStreamUpArgs { PlayDelay = vP.PlayDelay, ServerTime = vP.ServerTime, ChannelId = channelId }); return; case VideoPlaybackType.ViewCount: OnViewCount?.Invoke(this, new OnViewCountArgs { ServerTime = vP.ServerTime, Viewers = vP.Viewers, ChannelId = channelId }); return; case VideoPlaybackType.Commercial: OnCommercial?.Invoke(this, new OnCommercialArgs { ServerTime = vP.ServerTime, Length = vP.Length, ChannelId = channelId }); return; } break; case "following": var f = (Following)msg.MessageData; f.FollowedChannelId = msg.Topic.Split('.')[1]; OnFollow?.Invoke(this, new OnFollowArgs { FollowedChannelId = f.FollowedChannelId, DisplayName = f.DisplayName, UserId = f.UserId, Username = f.Username }); return; case "community-points-channel-v1": var cpc = msg.MessageData as CommunityPointsChannel; switch (cpc?.Type) { case CommunityPointsChannelType.RewardRedeemed: OnRewardRedeemed?.Invoke(this, new OnRewardRedeemedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, Login = cpc.Login, DisplayName = cpc.DisplayName, Message = cpc.Message, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt, RewardCost = cpc.RewardCost, Status = cpc.Status, RedemptionId = cpc.RedemptionId }); return; case CommunityPointsChannelType.CustomRewardUpdated: OnCustomRewardUpdated?.Invoke(this, new OnCustomRewardUpdatedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt, RewardCost = cpc.RewardCost }); return; case CommunityPointsChannelType.CustomRewardCreated: OnCustomRewardCreated?.Invoke(this, new OnCustomRewardCreatedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt, RewardCost = cpc.RewardCost }); return; case CommunityPointsChannelType.CustomRewardDeleted: OnCustomRewardDeleted?.Invoke(this, new OnCustomRewardDeletedArgs { TimeStamp = cpc.TimeStamp, ChannelId = cpc.ChannelId, RewardId = cpc.RewardId, RewardTitle = cpc.RewardTitle, RewardPrompt = cpc.RewardPrompt }); return; } return; case "channel-points-channel-v1": var channelPointsChannel = msg.MessageData as ChannelPointsChannel; switch (channelPointsChannel.Type) { case ChannelPointsChannelType.RewardRedeemed: var rewardRedeemed = channelPointsChannel.Data as RewardRedeemed; OnChannelPointsRewardRedeemed?.Invoke(this, new OnChannelPointsRewardRedeemedArgs { ChannelId = rewardRedeemed.Redemption.ChannelId, RewardRedeemed = rewardRedeemed }); break; case ChannelPointsChannelType.Unknown: UnaccountedFor($"Unknown channel points type. Msg: {channelPointsChannel.RawData}"); break; } return; case "leaderboard-events-v1": var lbe = msg.MessageData as LeaderboardEvents; switch (lbe?.Type) { case LeaderBoardType.BitsUsageByChannel: OnLeaderboardBits?.Invoke(this, new OnLeaderboardEventArgs { ChannelId = lbe.ChannelId, TopList = lbe.Top }); return; case LeaderBoardType.SubGiftSent: OnLeaderboardSubs?.Invoke(this, new OnLeaderboardEventArgs { ChannelId = lbe.ChannelId, TopList = lbe.Top }); return; } return; case "raid": var r = msg.MessageData as RaidEvents; switch (r?.Type) { case RaidType.RaidUpdate: OnRaidUpdate?.Invoke(this, new OnRaidUpdateArgs { Id = r.Id, ChannelId = r.ChannelId, TargetChannelId = r.TargetChannelId, AnnounceTime = r.AnnounceTime, RaidTime = r.RaidTime, RemainingDurationSeconds = r.RemainigDurationSeconds, ViewerCount = r.ViewerCount }); return; case RaidType.RaidUpdateV2: OnRaidUpdateV2?.Invoke(this, new OnRaidUpdateV2Args { Id = r.Id, ChannelId = r.ChannelId, TargetChannelId = r.TargetChannelId, TargetLogin = r.TargetLogin, TargetDisplayName = r.TargetDisplayName, TargetProfileImage = r.TargetProfileImage, ViewerCount = r.ViewerCount }); return; case RaidType.RaidGo: OnRaidGo?.Invoke(this, new OnRaidGoArgs { Id = r.Id, ChannelId = r.ChannelId, TargetChannelId = r.TargetChannelId, TargetLogin = r.TargetLogin, TargetDisplayName = r.TargetDisplayName, TargetProfileImage = r.TargetProfileImage, ViewerCount = r.ViewerCount }); return; } return; case "predictions-channel-v1": var pred = msg.MessageData as PredictionEvents; switch (pred?.Type) { case PredictionType.EventCreated: OnPrediction?.Invoke(this, new OnPredictionArgs { CreatedAt = pred.CreatedAt, Title = pred.Title, ChannelId = pred.ChannelId, EndedAt = pred.EndedAt, Id = pred.Id, Outcomes = pred.Outcomes, LockedAt = pred.LockedAt, PredictionTime = pred.PredictionTime, Status = pred.Status, WinningOutcomeId = pred.WinningOutcomeId, Type = pred.Type }); return; case PredictionType.EventUpdated: OnPrediction?.Invoke(this, new OnPredictionArgs { CreatedAt = pred.CreatedAt, Title = pred.Title, ChannelId = pred.ChannelId, EndedAt = pred.EndedAt, Id = pred.Id, Outcomes = pred.Outcomes, LockedAt = pred.LockedAt, PredictionTime = pred.PredictionTime, Status = pred.Status, WinningOutcomeId = pred.WinningOutcomeId, Type = pred.Type }); return; case null: UnaccountedFor("Prediction Type: null"); break; default: UnaccountedFor($"Prediction Type: {pred.Type}"); break; } return; } break; case "pong": _pongReceived = true; return; case "reconnect": _socket.Close(); break; } UnaccountedFor(message); }
public static void RemoveMessage(TextMessage message) { Messages.Remove(message); OnMessageDeleted?.Invoke(); }