@@ -29,11 +29,6 @@ public class TwitchClientProxy : ITwitchClientProxy {
29
29
/// </summary>
30
30
private static TwitchClientProxy ? instance ;
31
31
32
- /// <summary>
33
- /// The callback(s) to invoke when a new instance is created.
34
- /// </summary>
35
- private static Action < TwitchClientProxy > ? onInstanceCreated ;
36
-
37
32
/// <summary>
38
33
/// The list of chats we attempted to join with the bot.
39
34
/// </summary>
@@ -61,17 +56,17 @@ public class TwitchClientProxy : ITwitchClientProxy {
61
56
/// <summary>
62
57
/// The callback(s) to invoke when a channel receives a chat message.
63
58
/// </summary>
64
- private Action < OnMessageReceivedArgs > ? onMessageReceived ;
59
+ private Dictionary < string , Action < OnMessageReceivedArgs > ? > _onMessageReceived = new ( ) ;
65
60
66
61
/// <summary>
67
62
/// The callback(s) to invoke when a channel is raided.
68
63
/// </summary>
69
- private Action < OnRaidNotificationArgs > ? onRaid ;
64
+ private Dictionary < string , Action < OnRaidNotificationArgs > ? > onRaid = new ( ) ;
70
65
71
66
/// <summary>
72
67
/// The callback(s) to invoke when a channel receives a ban message.
73
68
/// </summary>
74
- private Action < OnUserBannedArgs > ? onUserBanReceived ;
69
+ private Dictionary < string , Action < OnUserBannedArgs > ? > onUserBanReceived = new ( ) ;
75
70
76
71
/// <summary>
77
72
/// The web socket to connect to twitch chat with.
@@ -98,7 +93,6 @@ public static TwitchClientProxy Instance {
98
93
get {
99
94
if ( null == instance ) {
100
95
instance = new TwitchClientProxy ( ) ;
101
- onInstanceCreated ? . Invoke ( instance ) ;
102
96
}
103
97
104
98
return instance ;
@@ -162,39 +156,60 @@ public async Task<bool> SendMessage(string channel, string message, uint retryCo
162
156
/// <inheritdoc />
163
157
public async Task AddMessageCallback ( string channel , Action < OnMessageReceivedArgs > callback ) {
164
158
await JoinChannel ( channel ) ;
165
- onMessageReceived -= callback ;
166
- onMessageReceived += callback ;
159
+ var channelSan = channel . ToLowerInvariant ( ) ;
160
+ lock ( _onMessageReceived ) {
161
+ _onMessageReceived [ channelSan ] = callback ;
162
+ }
167
163
}
168
164
169
165
/// <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
+ }
172
181
}
173
182
174
183
/// <inheritdoc />
175
184
public async Task AddBannedCallback ( string channel , Action < OnUserBannedArgs > callback ) {
176
185
await JoinChannel ( channel ) ;
177
186
178
- onUserBanReceived -= callback ;
179
- onUserBanReceived += callback ;
187
+ lock ( onUserBanReceived ) {
188
+ onUserBanReceived [ channel ] = callback ;
189
+ }
180
190
}
181
191
182
192
/// <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
+ }
185
197
}
186
198
187
199
/// <inheritdoc />
188
200
public async Task AddRaidCallback ( string channel , Action < OnRaidNotificationArgs > callback ) {
189
201
await JoinChannel ( channel ) ;
190
202
191
- onRaid -= callback ;
192
- onRaid += callback ;
203
+ lock ( onRaid ) {
204
+ onRaid [ channel ] = callback ;
205
+ }
193
206
}
194
207
195
208
/// <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
+ }
198
213
}
199
214
200
215
/// <inheritdoc />
@@ -203,17 +218,6 @@ public ValueTask DisposeAsync() {
203
218
return ValueTask . CompletedTask ;
204
219
}
205
220
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
-
217
221
/// <summary>
218
222
/// Joins a twitch channel.
219
223
/// </summary>
@@ -303,6 +307,10 @@ private async Task<bool> Connect() {
303
307
try {
304
308
bool isConnected = false ;
305
309
lock ( twitchClientLock ) {
310
+ if ( client ? . IsConnected ?? false ) {
311
+ return true ;
312
+ }
313
+
306
314
// If this is a first time initialization, create a brand-new client.
307
315
bool haveNoClient = null == client ;
308
316
if ( haveNoClient ) {
@@ -377,7 +385,13 @@ private async Task<bool> Connect() {
377
385
/// <param name="sender">The twitch client.</param>
378
386
/// <param name="e">The event arguments.</param>
379
387
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 ( ) ;
381
395
if ( null == invokeList ) {
382
396
return ;
383
397
}
@@ -393,7 +407,19 @@ private void TwitchChatClient_OnRaidNotification(object? sender, OnRaidNotificat
393
407
/// <param name="sender">The twitch client.</param>
394
408
/// <param name="e">The event arguments.</param>
395
409
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 ( ) ;
397
423
if ( null == invokeList ) {
398
424
return ;
399
425
}
@@ -409,7 +435,13 @@ private void TwitchChatClient_OnMessageReceived(object? sender, OnMessageReceive
409
435
/// <param name="sender">The twitch client.</param>
410
436
/// <param name="e">The event arguments.</param>
411
437
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 ( ) ;
413
445
if ( null == invokeList ) {
414
446
return ;
415
447
}
0 commit comments