diff --git a/src/backend/chat/twitch-chat.ts b/src/backend/chat/twitch-chat.ts index e5c06fb04..04b6b824e 100644 --- a/src/backend/chat/twitch-chat.ts +++ b/src/backend/chat/twitch-chat.ts @@ -123,10 +123,7 @@ class TwitchChat extends EventEmitter { // While connected, we can just react to changes via chat messages/EventSub events await twitchRolesManager.loadVips(); await twitchRolesManager.loadModerators(); - - if (!twitchRolesManager.getSubscribers().length) { - await twitchRolesManager.loadSubscribers(); - } + await twitchRolesManager.loadSubscribers(); // Load the current Shared Chat session await SharedChatCache.loadSessionFromTwitch(); diff --git a/src/backend/roles/twitch-roles-manager.ts b/src/backend/roles/twitch-roles-manager.ts index 3bcb7245f..1a1b746e7 100644 --- a/src/backend/roles/twitch-roles-manager.ts +++ b/src/backend/roles/twitch-roles-manager.ts @@ -98,6 +98,33 @@ class TwitchRolesManager extends TypedEmitter { return this._subscribers; } + addSubscriberToSubscribersList(userId: string, username: string, displayName: string, tier: string): void { + const subTier = this.getRoleForSubTier(tier); + const existing = this._subscribers.find(s => s.id === userId); + + if (existing == null) { + this._subscribers.push({ id: userId, username, displayName, subTier }); + this.emit("viewer-role-updated", userId, "sub", "added"); + this.emit("viewer-role-updated", userId, subTier, "added"); + return; + } + + const previousTier = existing.subTier; + existing.subTier = subTier; + + if (previousTier === subTier) { + return; + } + + this.emit("viewer-role-updated", userId, previousTier, "removed"); + this.emit("viewer-role-updated", userId, subTier, "added"); + } + + removeSubscriberFromSubscribersList(userId: string): void { + this._subscribers = this._subscribers.filter(s => s.id !== userId); + this.emit("viewer-role-updated", userId, "sub", "removed"); + } + private getRoleForSubTier(tier: string): string { let role = ""; switch (tier) { diff --git a/src/backend/streaming-platforms/twitch/api/eventsub/eventsub-client.ts b/src/backend/streaming-platforms/twitch/api/eventsub/eventsub-client.ts index 657ee7c5b..6f58b8125 100644 --- a/src/backend/streaming-platforms/twitch/api/eventsub/eventsub-client.ts +++ b/src/backend/streaming-platforms/twitch/api/eventsub/eventsub-client.ts @@ -29,12 +29,13 @@ class TwitchEventSubClient { const streamer = AccountAccess.getAccounts().streamer; // Stream online - const onlineSubscription = this._eventSubListener.onStreamOnline(streamer.userId, (event) => { + const onlineSubscription = this._eventSubListener.onStreamOnline(streamer.userId, async (event) => { TwitchEventHandlers.stream.triggerStreamOnline( event.broadcasterName, event.broadcasterId, event.broadcasterDisplayName ); + await twitchRolesManager.loadSubscribers(); }); this._subscriptions.push(onlineSubscription); @@ -815,6 +816,12 @@ class TwitchEventSubClient { event.isPrime, event.type === "resub" ); + twitchRolesManager.addSubscriberToSubscribersList( + event.chatterId, + event.chatterName, + event.chatterDisplayName, + event.tier + ); break; case "community_sub_gift": @@ -837,6 +844,12 @@ class TwitchEventSubClient { event.cumulativeAmount, event.communityGiftId ); + twitchRolesManager.addSubscriberToSubscribersList( + event.recipientId, + event.recipientName, + event.recipientDisplayName, + event.tier + ); await viewerDatabase.calculateAutoRanks(event.recipientId); break; @@ -852,6 +865,13 @@ class TwitchEventSubClient { event.gifterDisplayName, upgradeTier ); + + twitchRolesManager.addSubscriberToSubscribersList( + event.chatterId, + event.chatterName, + event.chatterDisplayName, + upgradeTier + ); } await viewerDatabase.calculateAutoRanks(event.chatterId); break; @@ -863,6 +883,12 @@ class TwitchEventSubClient { event.chatterDisplayName, event.tier ); + twitchRolesManager.addSubscriberToSubscribersList( + event.chatterId, + event.chatterName, + event.chatterDisplayName, + event.tier + ); await viewerDatabase.calculateAutoRanks(event.chatterId); break; @@ -872,6 +898,12 @@ class TwitchEventSubClient { } }); this._subscriptions.push(chatNotificationSubscription); + + // Subscription ended + const subscriptionEndSubscription = this._eventSubListener.onChannelSubscriptionEnd(streamer.userId, (event) => { + twitchRolesManager.removeSubscriberFromSubscribersList(event.userId); + }); + this._subscriptions.push(subscriptionEndSubscription); } createClient(): void {