Skip to content

Commit 7b3026f

Browse files
Merge pull request #46 from nullinside-development-group/feature/Poc2Prod
Abstracting TwitchClientProxy -> ITwitchClientProxy
2 parents b53da06 + cfe2781 commit 7b3026f

File tree

2 files changed

+131
-121
lines changed

2 files changed

+131
-121
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using TwitchLib.Client.Events;
2+
3+
namespace Nullinside.Api.Common.Twitch;
4+
5+
/// <summary>
6+
/// Represents a twitch chat messaging client.
7+
/// </summary>
8+
public interface ITwitchClientProxy : IDisposable, IAsyncDisposable {
9+
/// <summary>
10+
/// Gets or sets the twitch username to connect with.
11+
/// </summary>
12+
string? TwitchUsername { get; set; }
13+
14+
/// <summary>
15+
/// Gets or sets the twitch OAuth token to use to connect.
16+
/// </summary>
17+
string? TwitchOAuthToken { get; set; }
18+
19+
/// <summary>
20+
/// Send a message in twitch chat.
21+
/// </summary>
22+
/// <param name="channel">The channel to send the message in.</param>
23+
/// <param name="message">The message to send.</param>
24+
/// <param name="retryConnection">
25+
/// The number of times to retry connecting to twitch chat before
26+
/// giving up.
27+
/// </param>
28+
/// <returns>True if connected and sent, false otherwise.</returns>
29+
Task<bool> SendMessage(string channel, string message, uint retryConnection = 5);
30+
31+
/// <summary>
32+
/// Adds a callback for when the channel receives a new chat message.
33+
/// </summary>
34+
/// <param name="channel">The name of the channel to add the callback for.</param>
35+
/// <param name="callback">The callback to invoke.</param>
36+
/// <returns>An asynchronous task.</returns>
37+
Task AddMessageCallback(string channel, Action<OnMessageReceivedArgs> callback);
38+
39+
/// <summary>
40+
/// Removes a callback for when the channel receives a new chat message.
41+
/// </summary>
42+
/// <param name="callback">The callback to remove.</param>
43+
/// <returns>An asynchronous task.</returns>
44+
void RemoveMessageCallback(Action<OnMessageReceivedArgs> callback);
45+
46+
/// <summary>
47+
/// Adds a callback for when users are banned from the chat.
48+
/// </summary>
49+
/// <param name="channel">The channel to subscribe to notifications for.</param>
50+
/// <param name="callback">The callback to invoke when a user is banned.</param>
51+
Task AddBannedCallback(string channel, Action<OnUserBannedArgs> callback);
52+
53+
/// <summary>
54+
/// Removes a callback for when users are banned from the chat.
55+
/// </summary>
56+
/// <param name="callback">The callback to remove from when a user is banned.</param>
57+
void RemoveBannedCallback(Action<OnUserBannedArgs> callback);
58+
59+
/// <summary>
60+
/// Adds a callback for when the channel receives a raid.
61+
/// </summary>
62+
/// <param name="channel">The channel to subscribe to callbacks for.</param>
63+
/// <param name="callback">The callback to invoke.</param>
64+
/// <returns>An asynchronous task.</returns>
65+
Task AddRaidCallback(string channel, Action<OnRaidNotificationArgs> callback);
66+
67+
/// <summary>
68+
/// Removes a callback for when the channel receives a raid.
69+
/// </summary>
70+
/// <param name="callback">The callback to remove.</param>
71+
/// <returns>An asynchronous task.</returns>
72+
void RemoveRaidCallback(Action<OnRaidNotificationArgs> callback);
73+
}

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

Lines changed: 58 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ namespace Nullinside.Api.Common.Twitch;
1616
using Timer = Timer;
1717

1818
/// <summary>
19-
/// The singleton of the Cathy bot that existing in chat for reading and sending twitch chat messages.
19+
/// The singleton of a twitch chat messaging client.
2020
/// </summary>
21-
public class TwitchClientProxy : IDisposable {
21+
public class TwitchClientProxy : ITwitchClientProxy {
2222
/// <summary>
2323
/// The logger.
2424
/// </summary>
@@ -29,12 +29,6 @@ public class TwitchClientProxy : IDisposable {
2929
/// </summary>
3030
private static TwitchClientProxy? instance;
3131

32-
/// <summary>
33-
/// The lock to prevent mutual exclusion on <see cref="onMessageReceived" />
34-
/// and <see cref="onRaid" /> callbacks.
35-
/// </summary>
36-
private readonly object callbackLock = new();
37-
3832
/// <summary>
3933
/// The list of chats we attempted to join with the bot.
4034
/// </summary>
@@ -105,34 +99,19 @@ public static TwitchClientProxy Instance {
10599
}
106100
}
107101

108-
/// <summary>
109-
/// Gets or sets the twitch username to connect with.
110-
/// </summary>
102+
/// <inheritdoc />
111103
public string? TwitchUsername { get; set; }
112104

113-
/// <summary>
114-
/// Gets or sets the twitch OAuth token to use to connect.
115-
/// </summary>
105+
/// <inheritdoc />
116106
public string? TwitchOAuthToken { get; set; }
117107

118-
/// <summary>
119-
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
120-
/// </summary>
108+
/// <inheritdoc />
121109
public void Dispose() {
122110
Dispose(true);
123111
GC.SuppressFinalize(this);
124112
}
125113

126-
/// <summary>
127-
/// Send a message in twitch chat.
128-
/// </summary>
129-
/// <param name="channel">The channel to send the message in.</param>
130-
/// <param name="message">The message to send.</param>
131-
/// <param name="retryConnection">
132-
/// The number of times to retry connecting to twitch chat before
133-
/// giving up.
134-
/// </param>
135-
/// <returns>True if connected and sent, false otherwise.</returns>
114+
/// <inheritdoc />
136115
public async Task<bool> SendMessage(string channel, string message, uint retryConnection = 5) {
137116
// Sanity check.
138117
if (string.IsNullOrWhiteSpace(channel)) {
@@ -174,6 +153,50 @@ public async Task<bool> SendMessage(string channel, string message, uint retryCo
174153
return true;
175154
}
176155

156+
/// <inheritdoc />
157+
public async Task AddMessageCallback(string channel, Action<OnMessageReceivedArgs> callback) {
158+
await JoinChannel(channel);
159+
onMessageReceived -= callback;
160+
onMessageReceived += callback;
161+
}
162+
163+
/// <inheritdoc />
164+
public void RemoveMessageCallback(Action<OnMessageReceivedArgs> callback) {
165+
onMessageReceived -= callback;
166+
}
167+
168+
/// <inheritdoc />
169+
public async Task AddBannedCallback(string channel, Action<OnUserBannedArgs> callback) {
170+
await JoinChannel(channel);
171+
172+
onUserBanReceived -= callback;
173+
onUserBanReceived += callback;
174+
}
175+
176+
/// <inheritdoc />
177+
public void RemoveBannedCallback(Action<OnUserBannedArgs> callback) {
178+
onUserBanReceived -= callback;
179+
}
180+
181+
/// <inheritdoc />
182+
public async Task AddRaidCallback(string channel, Action<OnRaidNotificationArgs> callback) {
183+
await JoinChannel(channel);
184+
185+
onRaid -= callback;
186+
onRaid += callback;
187+
}
188+
189+
/// <inheritdoc />
190+
public void RemoveRaidCallback(Action<OnRaidNotificationArgs> callback) {
191+
onRaid -= callback;
192+
}
193+
194+
/// <inheritdoc />
195+
public ValueTask DisposeAsync() {
196+
Dispose();
197+
return ValueTask.CompletedTask;
198+
}
199+
177200
/// <summary>
178201
/// Joins a twitch channel.
179202
/// </summary>
@@ -316,94 +339,13 @@ private async Task<bool> Connect() {
316339
});
317340
}
318341

319-
/// <summary>
320-
/// Adds a callback for when the channel receives a new chat message.
321-
/// </summary>
322-
/// <param name="channel">The name of the channel to add the callback for.</param>
323-
/// <param name="callback">The callback to invoke.</param>
324-
/// <returns>An asynchronous task.</returns>
325-
public async Task AddMessageCallback(string channel, Action<OnMessageReceivedArgs> callback) {
326-
await JoinChannel(channel);
327-
328-
lock (callbackLock) {
329-
onMessageReceived -= callback;
330-
onMessageReceived += callback;
331-
}
332-
}
333-
334-
/// <summary>
335-
/// Removes a callback for when the channel receives a new chat message.
336-
/// </summary>
337-
/// <param name="callback">The callback to remove.</param>
338-
/// <returns>An asynchronous task.</returns>
339-
public void RemoveMessageCallback(Action<OnMessageReceivedArgs> callback) {
340-
lock (callbackLock) {
341-
onMessageReceived -= callback;
342-
}
343-
}
344-
345-
/// <summary>
346-
/// Adds a callback for when users are banned from the chat.
347-
/// </summary>
348-
/// <param name="channel">The channel to subscribe to notifications for.</param>
349-
/// <param name="callback">The callback to invoke when a user is banned.</param>
350-
public async Task AddBannedCallback(string channel, Action<OnUserBannedArgs> callback) {
351-
await JoinChannel(channel);
352-
353-
lock (callbackLock) {
354-
onUserBanReceived -= callback;
355-
onUserBanReceived += callback;
356-
}
357-
}
358-
359-
/// <summary>
360-
/// Removes a callback for when users are banned from the chat.
361-
/// </summary>
362-
/// <param name="callback">The callback to remove from when a user is banned.</param>
363-
public void RemoveBannedCallback(Action<OnUserBannedArgs> callback) {
364-
lock (callbackLock) {
365-
onUserBanReceived -= callback;
366-
}
367-
}
368-
369-
/// <summary>
370-
/// Adds a callback for when the channel receives a raid.
371-
/// </summary>
372-
/// <param name="channel">The channel to subscribe to callbacks for.</param>
373-
/// <param name="callback">The callback to invoke.</param>
374-
/// <returns>An asynchronous task.</returns>
375-
public async Task AddRaidCallback(string channel, Action<OnRaidNotificationArgs> callback) {
376-
await JoinChannel(channel);
377-
378-
lock (callbackLock) {
379-
onRaid -= callback;
380-
onRaid += callback;
381-
}
382-
}
383-
384-
/// <summary>
385-
/// Removes a callback for when the channel receives a raid.
386-
/// </summary>
387-
/// <param name="callback">The callback to remove.</param>
388-
/// <returns>An asynchronous task.</returns>
389-
public void RemoveRaidCallback(Action<OnRaidNotificationArgs> callback) {
390-
lock (callbackLock) {
391-
onRaid -= callback;
392-
}
393-
}
394-
395342
/// <summary>
396343
/// Handles when the channel receives a raid.
397344
/// </summary>
398345
/// <param name="sender">The twitch client.</param>
399346
/// <param name="e">The event arguments.</param>
400347
private void TwitchChatClient_OnRaidNotification(object? sender, OnRaidNotificationArgs e) {
401-
Delegate[]? invokeList = null;
402-
403-
lock (callbackLock) {
404-
invokeList = onRaid?.GetInvocationList();
405-
}
406-
348+
Delegate[]? invokeList = onRaid?.GetInvocationList();
407349
if (null == invokeList) {
408350
return;
409351
}
@@ -419,12 +361,7 @@ private void TwitchChatClient_OnRaidNotification(object? sender, OnRaidNotificat
419361
/// <param name="sender">The twitch client.</param>
420362
/// <param name="e">The event arguments.</param>
421363
private void TwitchChatClient_OnMessageReceived(object? sender, OnMessageReceivedArgs e) {
422-
Delegate[]? invokeList = null;
423-
424-
lock (callbackLock) {
425-
invokeList = onMessageReceived?.GetInvocationList();
426-
}
427-
364+
Delegate[]? invokeList = onMessageReceived?.GetInvocationList();
428365
if (null == invokeList) {
429366
return;
430367
}
@@ -434,13 +371,13 @@ private void TwitchChatClient_OnMessageReceived(object? sender, OnMessageReceive
434371
}
435372
}
436373

374+
/// <summary>
375+
/// Handles when a channel receives a new ban.
376+
/// </summary>
377+
/// <param name="sender">The twitch client.</param>
378+
/// <param name="e">The event arguments.</param>
437379
private void TwitchChatClient_OnUserBanned(object? sender, OnUserBannedArgs e) {
438-
Delegate[]? invokeList = null;
439-
440-
lock (callbackLock) {
441-
invokeList = onUserBanReceived?.GetInvocationList();
442-
}
443-
380+
Delegate[]? invokeList = onUserBanReceived?.GetInvocationList();
444381
if (null == invokeList) {
445382
return;
446383
}

0 commit comments

Comments
 (0)