Skip to content

Commit 7c34d16

Browse files
Merge pull request #81 from nullinside-development-group/fix/disconnect-chats
fix: Disconnect twitch client proxy
2 parents c4cd288 + 3d8416a commit 7c34d16

File tree

2 files changed

+73
-38
lines changed

2 files changed

+73
-38
lines changed

src/Nullinside.Api.Common/Twitch/ITwitchClientProxy.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ public interface ITwitchClientProxy : IDisposable, IAsyncDisposable {
3939
/// <summary>
4040
/// Removes a callback for when the channel receives a new chat message.
4141
/// </summary>
42+
/// <param name="channel">The name of the channel to add the callback for.</param>
4243
/// <param name="callback">The callback to remove.</param>
4344
/// <returns>An asynchronous task.</returns>
44-
void RemoveMessageCallback(Action<OnMessageReceivedArgs> callback);
45+
void RemoveMessageCallback(string channel, Action<OnMessageReceivedArgs> callback);
4546

4647
/// <summary>
4748
/// Adds a callback for when users are banned from the chat.
@@ -53,8 +54,9 @@ public interface ITwitchClientProxy : IDisposable, IAsyncDisposable {
5354
/// <summary>
5455
/// Removes a callback for when users are banned from the chat.
5556
/// </summary>
57+
/// <param name="channel">The name of the channel to add the callback for.</param>
5658
/// <param name="callback">The callback to remove from when a user is banned.</param>
57-
void RemoveBannedCallback(Action<OnUserBannedArgs> callback);
59+
void RemoveBannedCallback(string channel, Action<OnUserBannedArgs> callback);
5860

5961
/// <summary>
6062
/// Adds a callback for when the channel receives a raid.
@@ -67,7 +69,8 @@ public interface ITwitchClientProxy : IDisposable, IAsyncDisposable {
6769
/// <summary>
6870
/// Removes a callback for when the channel receives a raid.
6971
/// </summary>
72+
/// <param name="channel">The name of the channel to add the callback for.</param>
7073
/// <param name="callback">The callback to remove.</param>
7174
/// <returns>An asynchronous task.</returns>
72-
void RemoveRaidCallback(Action<OnRaidNotificationArgs> callback);
75+
void RemoveRaidCallback(string channel, Action<OnRaidNotificationArgs> callback);
7376
}

src/Nullinside.Api.Common/Twitch/TwitchClientProxy.cs

Lines changed: 67 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ public class TwitchClientProxy : ITwitchClientProxy {
2929
/// </summary>
3030
private static TwitchClientProxy? instance;
3131

32-
/// <summary>
33-
/// The callback(s) to invoke when a new instance is created.
34-
/// </summary>
35-
private static Action<TwitchClientProxy>? onInstanceCreated;
36-
3732
/// <summary>
3833
/// The list of chats we attempted to join with the bot.
3934
/// </summary>
@@ -61,17 +56,17 @@ public class TwitchClientProxy : ITwitchClientProxy {
6156
/// <summary>
6257
/// The callback(s) to invoke when a channel receives a chat message.
6358
/// </summary>
64-
private Action<OnMessageReceivedArgs>? onMessageReceived;
59+
private Dictionary<string, Action<OnMessageReceivedArgs>?> _onMessageReceived = new();
6560

6661
/// <summary>
6762
/// The callback(s) to invoke when a channel is raided.
6863
/// </summary>
69-
private Action<OnRaidNotificationArgs>? onRaid;
64+
private Dictionary<string, Action<OnRaidNotificationArgs>?> onRaid = new();
7065

7166
/// <summary>
7267
/// The callback(s) to invoke when a channel receives a ban message.
7368
/// </summary>
74-
private Action<OnUserBannedArgs>? onUserBanReceived;
69+
private Dictionary<string, Action<OnUserBannedArgs>?> onUserBanReceived = new();
7570

7671
/// <summary>
7772
/// The web socket to connect to twitch chat with.
@@ -98,7 +93,6 @@ public static TwitchClientProxy Instance {
9893
get {
9994
if (null == instance) {
10095
instance = new TwitchClientProxy();
101-
onInstanceCreated?.Invoke(instance);
10296
}
10397

10498
return instance;
@@ -162,39 +156,60 @@ public async Task<bool> SendMessage(string channel, string message, uint retryCo
162156
/// <inheritdoc />
163157
public async Task AddMessageCallback(string channel, Action<OnMessageReceivedArgs> callback) {
164158
await JoinChannel(channel);
165-
onMessageReceived -= callback;
166-
onMessageReceived += callback;
159+
var channelSan = channel.ToLowerInvariant();
160+
lock (_onMessageReceived) {
161+
_onMessageReceived[channelSan] = callback;
162+
}
167163
}
168164

169165
/// <inheritdoc />
170-
public void RemoveMessageCallback(Action<OnMessageReceivedArgs> callback) {
171-
onMessageReceived -= callback;
166+
public void RemoveMessageCallback(string channel, Action<OnMessageReceivedArgs> callback) {
167+
bool shouldRemove = false;
168+
var channelSan = channel.ToLowerInvariant();
169+
lock (_onMessageReceived) {
170+
_onMessageReceived.Remove(channel);
171+
}
172+
173+
if (shouldRemove) {
174+
client?.LeaveChannel(channelSan);
175+
176+
// First add the channel to the master list.
177+
lock (joinedChannels) {
178+
joinedChannels.Add(channelSan);
179+
}
180+
}
172181
}
173182

174183
/// <inheritdoc />
175184
public async Task AddBannedCallback(string channel, Action<OnUserBannedArgs> callback) {
176185
await JoinChannel(channel);
177186

178-
onUserBanReceived -= callback;
179-
onUserBanReceived += callback;
187+
lock (onUserBanReceived) {
188+
onUserBanReceived[channel] = callback;
189+
}
180190
}
181191

182192
/// <inheritdoc />
183-
public void RemoveBannedCallback(Action<OnUserBannedArgs> callback) {
184-
onUserBanReceived -= callback;
193+
public void RemoveBannedCallback(string channel, Action<OnUserBannedArgs> callback) {
194+
lock (onUserBanReceived) {
195+
onUserBanReceived.Remove(channel);
196+
}
185197
}
186198

187199
/// <inheritdoc />
188200
public async Task AddRaidCallback(string channel, Action<OnRaidNotificationArgs> callback) {
189201
await JoinChannel(channel);
190202

191-
onRaid -= callback;
192-
onRaid += callback;
203+
lock (onRaid) {
204+
onRaid[channel] = callback;
205+
}
193206
}
194207

195208
/// <inheritdoc />
196-
public void RemoveRaidCallback(Action<OnRaidNotificationArgs> callback) {
197-
onRaid -= callback;
209+
public void RemoveRaidCallback(string channel, Action<OnRaidNotificationArgs> callback) {
210+
lock (onRaid) {
211+
onRaid.Remove(channel);
212+
}
198213
}
199214

200215
/// <inheritdoc />
@@ -203,17 +218,6 @@ public ValueTask DisposeAsync() {
203218
return ValueTask.CompletedTask;
204219
}
205220

206-
/// <inheritdoc />
207-
public void AddInstanceCallback(Action<TwitchClientProxy> callback) {
208-
onInstanceCreated -= callback;
209-
onInstanceCreated += callback;
210-
}
211-
212-
/// <inheritdoc />
213-
public void RemoveInstanceCallback(Action<TwitchClientProxy> callback) {
214-
onInstanceCreated -= callback;
215-
}
216-
217221
/// <summary>
218222
/// Joins a twitch channel.
219223
/// </summary>
@@ -303,6 +307,10 @@ private async Task<bool> Connect() {
303307
try {
304308
bool isConnected = false;
305309
lock (twitchClientLock) {
310+
if (client?.IsConnected ?? false) {
311+
return true;
312+
}
313+
306314
// If this is a first time initialization, create a brand-new client.
307315
bool haveNoClient = null == client;
308316
if (haveNoClient) {
@@ -377,7 +385,13 @@ private async Task<bool> Connect() {
377385
/// <param name="sender">The twitch client.</param>
378386
/// <param name="e">The event arguments.</param>
379387
private void TwitchChatClient_OnRaidNotification(object? sender, OnRaidNotificationArgs e) {
380-
Delegate[]? invokeList = onRaid?.GetInvocationList();
388+
Action<OnRaidNotificationArgs>? callback;
389+
var channel = e.Channel.ToLowerInvariant();
390+
lock (onRaid) {
391+
onRaid.TryGetValue(channel, out callback);
392+
}
393+
394+
Delegate[]? invokeList = callback?.GetInvocationList();
381395
if (null == invokeList) {
382396
return;
383397
}
@@ -393,7 +407,19 @@ private void TwitchChatClient_OnRaidNotification(object? sender, OnRaidNotificat
393407
/// <param name="sender">The twitch client.</param>
394408
/// <param name="e">The event arguments.</param>
395409
private void TwitchChatClient_OnMessageReceived(object? sender, OnMessageReceivedArgs e) {
396-
Delegate[]? invokeList = onMessageReceived?.GetInvocationList();
410+
Action<OnMessageReceivedArgs>? callbacks = null;
411+
var channelSan = e.ChatMessage.Channel.ToLowerInvariant();
412+
lock (_onMessageReceived) {
413+
if (_onMessageReceived.TryGetValue(channelSan, out Action<OnMessageReceivedArgs>? messageReceivedCallback)) {
414+
callbacks = messageReceivedCallback;
415+
}
416+
}
417+
418+
if (null == callbacks) {
419+
return;
420+
}
421+
422+
Delegate[]? invokeList = callbacks?.GetInvocationList();
397423
if (null == invokeList) {
398424
return;
399425
}
@@ -409,7 +435,13 @@ private void TwitchChatClient_OnMessageReceived(object? sender, OnMessageReceive
409435
/// <param name="sender">The twitch client.</param>
410436
/// <param name="e">The event arguments.</param>
411437
private void TwitchChatClient_OnUserBanned(object? sender, OnUserBannedArgs e) {
412-
Delegate[]? invokeList = onUserBanReceived?.GetInvocationList();
438+
Action<OnUserBannedArgs>? callback;
439+
var channel = e.UserBan.Channel.ToLowerInvariant();
440+
lock (onUserBanReceived) {
441+
onUserBanReceived.TryGetValue(channel, out callback);
442+
}
443+
444+
Delegate[]? invokeList = callback?.GetInvocationList();
413445
if (null == invokeList) {
414446
return;
415447
}

0 commit comments

Comments
 (0)