From f503f7c6f4fe23be51657d3dc76bd4b3d1887387 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 12 Aug 2024 18:06:10 +0000 Subject: [PATCH] Prevent Twitch websocket client to subscribe again if Twitch moved/reconnected us --- .../Handlers/SessionReconnectHandler.cs | 1 + .../Socket/Handlers/SessionWelcomeHandler.cs | 106 +++++++----------- Twitch/Socket/TwitchWebsocketClient.cs | 1 + 3 files changed, 44 insertions(+), 64 deletions(-) diff --git a/Twitch/Socket/Handlers/SessionReconnectHandler.cs b/Twitch/Socket/Handlers/SessionReconnectHandler.cs index 7b27b9c..754faf6 100644 --- a/Twitch/Socket/Handlers/SessionReconnectHandler.cs +++ b/Twitch/Socket/Handlers/SessionReconnectHandler.cs @@ -43,6 +43,7 @@ namespace TwitchChatTTS.Twitch.Socket.Handlers _logger.Debug($"Reconnection received [receiver: {sender.UID}][main: {identified.UID}][backup: {backup.UID}]"); backup.URL = message.Session.ReconnectUrl; + backup.TwitchReconnected = true; await backup.Connect(); } } diff --git a/Twitch/Socket/Handlers/SessionWelcomeHandler.cs b/Twitch/Socket/Handlers/SessionWelcomeHandler.cs index 8809137..9afbe70 100644 --- a/Twitch/Socket/Handlers/SessionWelcomeHandler.cs +++ b/Twitch/Socket/Handlers/SessionWelcomeHandler.cs @@ -46,87 +46,65 @@ namespace TwitchChatTTS.Twitch.Socket.Handlers _logger.Information($"Twitch connection has {timeLeft} before it is revoked."); else if (span.Minutes >= 0) _logger.Warning($"Twitch connection has {timeLeft} before it is revoked. Refreshing the token is soon required."); - else { + else + { _logger.Error("Twitch connection has its permissions revoked. Refresh the token. Twith client will not be connecting."); return; } - string broadcasterId = _user.TwitchUserId.ToString(); - string[] subscriptionsv1 = [ - "channel.chat.message", - "channel.chat.message_delete", - "channel.chat.clear", - "channel.chat.clear_user_messages", - "channel.subscribe", - "channel.subscription.gift", - "channel.subscription.message", - "channel.ad_break.begin", - "channel.ban", - "channel.channel_points_custom_reward_redemption.add" - ]; - string[] subscriptionsv2 = [ - "channel.follow", - ]; - - string? pagination = null; - int size = 0; - do + if (!sender.TwitchReconnected) { - var subscriptionsData = await _api.GetSubscriptions(status: "enabled", broadcasterId: broadcasterId, after: pagination); - var subscriptionNames = subscriptionsData?.Data == null ? [] : subscriptionsData.Data.Select(s => s.Type).ToArray(); + string broadcasterId = _user.TwitchUserId.ToString(); + string[] subscriptionsv1 = [ + "channel.chat.message", + "channel.chat.message_delete", + "channel.chat.clear", + "channel.chat.clear_user_messages", + "channel.subscribe", + "channel.subscription.gift", + "channel.subscription.message", + "channel.ad_break.begin", + "channel.ban", + "channel.channel_points_custom_reward_redemption.add" + ]; + string[] subscriptionsv2 = [ + "channel.follow", + ]; - if (subscriptionNames.Length == 0) - break; + string? pagination = null; + int size = 0; + do + { + var subscriptionsData = await _api.GetSubscriptions(status: "enabled", broadcasterId: broadcasterId, after: pagination); + var subscriptionNames = subscriptionsData?.Data == null ? [] : subscriptionsData.Data.Select(s => s.Type).ToArray(); - foreach (var d in subscriptionsData!.Data!) - sender.AddSubscription(broadcasterId, d.Type, d.Id); + if (subscriptionNames.Length == 0) + break; - subscriptionsv1 = subscriptionsv1.Except(subscriptionNames).ToArray(); - subscriptionsv2 = subscriptionsv2.Except(subscriptionNames).ToArray(); + foreach (var d in subscriptionsData!.Data!) + sender.AddSubscription(broadcasterId, d.Type, d.Id); - pagination = subscriptionsData?.Pagination?.Cursor; - size = subscriptionNames.Length; - } while (size >= 100 && pagination != null && subscriptionsv1.Length + subscriptionsv2.Length > 0); + subscriptionsv1 = subscriptionsv1.Except(subscriptionNames).ToArray(); + subscriptionsv2 = subscriptionsv2.Except(subscriptionNames).ToArray(); - foreach (var subscription in subscriptionsv1) - await Subscribe(sender, subscription, message.Session.Id, broadcasterId, "1"); - foreach (var subscription in subscriptionsv2) - await Subscribe(sender, subscription, message.Session.Id, broadcasterId, "2"); + pagination = subscriptionsData?.Pagination?.Cursor; + size = subscriptionNames.Length; + } while (size >= 100 && pagination != null && subscriptionsv1.Length + subscriptionsv2.Length > 0); - await Subscribe(sender, "channel.raid", broadcasterId, async () => await _api.CreateChannelRaidEventSubscription("1", message.Session.Id, to: broadcasterId)); + foreach (var subscription in subscriptionsv1) + await Subscribe(sender, subscription, message.Session.Id, broadcasterId, "1"); + foreach (var subscription in subscriptionsv2) + await Subscribe(sender, subscription, message.Session.Id, broadcasterId, "2"); + + await Subscribe(sender, "channel.raid", broadcasterId, async () => await _api.CreateChannelRaidEventSubscription("1", message.Session.Id, to: broadcasterId)); + } sender.Identify(message.Session.Id); } private async Task Subscribe(TwitchWebsocketClient sender, string subscriptionName, string sessionId, string broadcasterId, string version) { - try - { - var response = await _api.CreateEventSubscription(subscriptionName, version, sessionId, broadcasterId); - if (response == null) - { - return; - } - if (response.Data == null) - { - _logger.Error($"Failed to create an event subscription [subscription type: {subscriptionName}][reason: data is null]"); - return; - } - if (!response.Data.Any()) - { - _logger.Error($"Failed to create an event subscription [subscription type: {subscriptionName}][reason: data is empty]"); - return; - } - - foreach (var d in response.Data) - sender.AddSubscription(broadcasterId, d.Type, d.Id); - - _logger.Information($"Sucessfully added subscription to Twitch websockets [subscription type: {subscriptionName}]"); - } - catch (Exception ex) - { - _logger.Error(ex, $"Failed to create an event subscription [subscription type: {subscriptionName}][reason: exception]"); - } + await Subscribe(sender, subscriptionName, broadcasterId, async () => await _api.CreateEventSubscription(subscriptionName, version, sessionId, broadcasterId)); } private async Task Subscribe(TwitchWebsocketClient sender, string subscriptionName, string broadcasterId, Func?>> subscribe) diff --git a/Twitch/Socket/TwitchWebsocketClient.cs b/Twitch/Socket/TwitchWebsocketClient.cs index 33b4ddf..30e0bcf 100644 --- a/Twitch/Socket/TwitchWebsocketClient.cs +++ b/Twitch/Socket/TwitchWebsocketClient.cs @@ -29,6 +29,7 @@ namespace TwitchChatTTS.Twitch.Socket public bool Identified { get; private set; } public string SessionId { get; private set; } public bool ReceivedReconnecting { get; set; } + public bool TwitchReconnected { get; set; } public TwitchWebsocketClient(