From b1020bd9c2f005c0de4976365f7047fe078938b7 Mon Sep 17 00:00:00 2001 From: AoshiW Date: Sun, 30 Jul 2023 09:22:08 +0200 Subject: [PATCH 1/8] replace all duplicate Notice events with one universal event --- .../TwitchClientEventTests.cs | 4 +- TwitchLib.Client/Events/NoticeEventArgs.cs | 24 ++++ TwitchLib.Client/Events/OnBannedArgs.cs | 22 ---- .../Events/OnBannedEmailAliasArgs.cs | 22 ---- TwitchLib.Client/Events/OnConnectedArgs.cs | 22 ---- .../Events/OnConnectedEventArgs.cs | 13 +++ TwitchLib.Client/Events/OnDuplicateArgs.cs | 22 ---- TwitchLib.Client/Events/OnEmoteOnlyArgs.cs | 22 ---- .../Events/OnFollowersOnlyArgs.cs | 22 ---- .../Events/OnModeratorJoinedArgs.cs | 22 ---- .../Events/OnModeratorLeftArgs.cs | 22 ---- TwitchLib.Client/Events/OnR9kModeArgs.cs | 22 ---- .../OnRaidedChannelIsMatureAudienceArgs.cs | 23 ---- TwitchLib.Client/Events/OnRateLimitArgs.cs | 22 ---- .../Events/OnRequiresVerifiedEmailArgs.cs | 22 ---- .../OnRequiresVerifiedPhoneNumberArgs.cs | 22 ---- TwitchLib.Client/Events/OnSlowModeArgs.cs | 22 ---- TwitchLib.Client/Events/OnSubsOnlyArgs.cs | 22 ---- TwitchLib.Client/Events/OnSuspendedArgs.cs | 22 ---- TwitchLib.Client/Interfaces/ITwitchClient.cs | 44 +++---- TwitchLib.Client/OnNoPermissionErrorArgs.cs | 23 ---- TwitchLib.Client/OnSelfRaidErrorArgs.cs | 23 ---- .../Throttling/ThrottlingService.cs | 6 +- TwitchLib.Client/TwitchClient.cs | 108 ++++++------------ 24 files changed, 94 insertions(+), 504 deletions(-) create mode 100644 TwitchLib.Client/Events/NoticeEventArgs.cs delete mode 100644 TwitchLib.Client/Events/OnBannedArgs.cs delete mode 100644 TwitchLib.Client/Events/OnBannedEmailAliasArgs.cs delete mode 100644 TwitchLib.Client/Events/OnConnectedArgs.cs create mode 100644 TwitchLib.Client/Events/OnConnectedEventArgs.cs delete mode 100644 TwitchLib.Client/Events/OnDuplicateArgs.cs delete mode 100644 TwitchLib.Client/Events/OnEmoteOnlyArgs.cs delete mode 100644 TwitchLib.Client/Events/OnFollowersOnlyArgs.cs delete mode 100644 TwitchLib.Client/Events/OnModeratorJoinedArgs.cs delete mode 100644 TwitchLib.Client/Events/OnModeratorLeftArgs.cs delete mode 100644 TwitchLib.Client/Events/OnR9kModeArgs.cs delete mode 100644 TwitchLib.Client/Events/OnRaidedChannelIsMatureAudienceArgs.cs delete mode 100644 TwitchLib.Client/Events/OnRateLimitArgs.cs delete mode 100644 TwitchLib.Client/Events/OnRequiresVerifiedEmailArgs.cs delete mode 100644 TwitchLib.Client/Events/OnRequiresVerifiedPhoneNumberArgs.cs delete mode 100644 TwitchLib.Client/Events/OnSlowModeArgs.cs delete mode 100644 TwitchLib.Client/Events/OnSubsOnlyArgs.cs delete mode 100644 TwitchLib.Client/Events/OnSuspendedArgs.cs delete mode 100644 TwitchLib.Client/OnNoPermissionErrorArgs.cs delete mode 100644 TwitchLib.Client/OnSelfRaidErrorArgs.cs diff --git a/TwitchLib.Client.Test/TwitchClientEventTests.cs b/TwitchLib.Client.Test/TwitchClientEventTests.cs index 4bedb485..ed52f878 100644 --- a/TwitchLib.Client.Test/TwitchClientEventTests.cs +++ b/TwitchLib.Client.Test/TwitchClientEventTests.cs @@ -82,7 +82,7 @@ public async void ClientRaisesOnConnected() { var client = new TwitchClient(_mockClient); - await Assert.RaisesAsync( + await Assert.RaisesAsync( h => client.OnConnected += h, h => client.OnConnected -= h, async () => @@ -165,7 +165,7 @@ public async Task ClientReconnectsOk() var pauseConnected = new ManualResetEvent(false); var pauseReconnected = new ManualResetEvent(false); - await Assert.RaisesAsync( + await Assert.RaisesAsync( h => client.OnReconnected += h, h => client.OnReconnected -= h, async () => diff --git a/TwitchLib.Client/Events/NoticeEventArgs.cs b/TwitchLib.Client/Events/NoticeEventArgs.cs new file mode 100644 index 00000000..94bfc974 --- /dev/null +++ b/TwitchLib.Client/Events/NoticeEventArgs.cs @@ -0,0 +1,24 @@ +namespace TwitchLib.Client.Events; + +/// +/// EventArgs representing a NOTICE. +/// +public class NoticeEventArgs +{ + /// + /// Property representing message send with the NOTICE + /// + public string Message { get; } + + /// + /// Property representing channel bot is connected to. + /// + public string Channel { get; } + + + public NoticeEventArgs(string channel, string message) + { + Message = message; + Channel = channel; + } +} diff --git a/TwitchLib.Client/Events/OnBannedArgs.cs b/TwitchLib.Client/Events/OnBannedArgs.cs deleted file mode 100644 index 510e4fcb..00000000 --- a/TwitchLib.Client/Events/OnBannedArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client a message was not sent because the bot user is banned. - /// Implements the - /// - /// - /// - public class OnBannedArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnBannedEmailAliasArgs.cs b/TwitchLib.Client/Events/OnBannedEmailAliasArgs.cs deleted file mode 100644 index f36d7a45..00000000 --- a/TwitchLib.Client/Events/OnBannedEmailAliasArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client that the user is banned to chat bcs of an already banned alias with the same Email. - /// Implements the - /// - /// - /// - public class OnBannedEmailAliasArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} \ No newline at end of file diff --git a/TwitchLib.Client/Events/OnConnectedArgs.cs b/TwitchLib.Client/Events/OnConnectedArgs.cs deleted file mode 100644 index 0ccf4685..00000000 --- a/TwitchLib.Client/Events/OnConnectedArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing on connected event. - /// Implements the - /// - /// - /// - public class OnConnectedArgs : EventArgs - { - /// - /// Property representing bot username. - /// - public string BotUsername; - /// - /// Property representing connected channel. - /// - public string AutoJoinChannel; - } -} diff --git a/TwitchLib.Client/Events/OnConnectedEventArgs.cs b/TwitchLib.Client/Events/OnConnectedEventArgs.cs new file mode 100644 index 00000000..b53431af --- /dev/null +++ b/TwitchLib.Client/Events/OnConnectedEventArgs.cs @@ -0,0 +1,13 @@ +namespace TwitchLib.Client.Events; + +/// +/// Args representing on connected event. +/// Implements the +/// +public class OnConnectedEventArgs : EventArgs +{ + /// + /// Property representing bot username. + /// + public string BotUsername; +} diff --git a/TwitchLib.Client/Events/OnDuplicateArgs.cs b/TwitchLib.Client/Events/OnDuplicateArgs.cs deleted file mode 100644 index 35602a24..00000000 --- a/TwitchLib.Client/Events/OnDuplicateArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client that duplicate messages are not allowed. - /// Implements the - /// - /// - /// - public class OnDuplicateArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnEmoteOnlyArgs.cs b/TwitchLib.Client/Events/OnEmoteOnlyArgs.cs deleted file mode 100644 index d57bcb63..00000000 --- a/TwitchLib.Client/Events/OnEmoteOnlyArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client a message was not sent because its emote only mode. - /// Implements the - /// - /// - /// - public class OnEmoteOnlyArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnFollowersOnlyArgs.cs b/TwitchLib.Client/Events/OnFollowersOnlyArgs.cs deleted file mode 100644 index 4565796c..00000000 --- a/TwitchLib.Client/Events/OnFollowersOnlyArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client a message was not sent because its followers only mode. - /// Implements the - /// - /// - /// - public class OnFollowersOnlyArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnModeratorJoinedArgs.cs b/TwitchLib.Client/Events/OnModeratorJoinedArgs.cs deleted file mode 100644 index b12d8ae7..00000000 --- a/TwitchLib.Client/Events/OnModeratorJoinedArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing moderator joined event. - /// Implements the - /// - /// - /// - public class OnModeratorJoinedArgs : EventArgs - { - /// - /// Property representing username of joined moderator. - /// - public string Username; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnModeratorLeftArgs.cs b/TwitchLib.Client/Events/OnModeratorLeftArgs.cs deleted file mode 100644 index ad69554c..00000000 --- a/TwitchLib.Client/Events/OnModeratorLeftArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing moderator leave event. - /// Implements the - /// - /// - /// - public class OnModeratorLeftArgs : EventArgs - { - /// - /// Property representing username of moderator that left.. - /// - public string Username; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnR9kModeArgs.cs b/TwitchLib.Client/Events/OnR9kModeArgs.cs deleted file mode 100644 index 846c4e5d..00000000 --- a/TwitchLib.Client/Events/OnR9kModeArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client a message was not sent because the channel is in r9k mode - /// Implements the - /// - /// - /// - public class OnR9kModeArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} \ No newline at end of file diff --git a/TwitchLib.Client/Events/OnRaidedChannelIsMatureAudienceArgs.cs b/TwitchLib.Client/Events/OnRaidedChannelIsMatureAudienceArgs.cs deleted file mode 100644 index 2935617f..00000000 --- a/TwitchLib.Client/Events/OnRaidedChannelIsMatureAudienceArgs.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client the newly raided channel is mature audience only. - /// Implements the - /// - /// - /// - public class OnRaidedChannelIsMatureAudienceArgs : EventArgs - { - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - - /// - /// Property representing message send with the NOTICE - /// - public string Message; - } -} diff --git a/TwitchLib.Client/Events/OnRateLimitArgs.cs b/TwitchLib.Client/Events/OnRateLimitArgs.cs deleted file mode 100644 index 3d182324..00000000 --- a/TwitchLib.Client/Events/OnRateLimitArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client that a rate limit has been hit. - /// Implements the - /// - /// - /// - public class OnRateLimitArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} \ No newline at end of file diff --git a/TwitchLib.Client/Events/OnRequiresVerifiedEmailArgs.cs b/TwitchLib.Client/Events/OnRequiresVerifiedEmailArgs.cs deleted file mode 100644 index bf85fa47..00000000 --- a/TwitchLib.Client/Events/OnRequiresVerifiedEmailArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client that a verified email is required to chat. - /// Implements the - /// - /// - /// - public class OnRequiresVerifiedEmailArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} \ No newline at end of file diff --git a/TwitchLib.Client/Events/OnRequiresVerifiedPhoneNumberArgs.cs b/TwitchLib.Client/Events/OnRequiresVerifiedPhoneNumberArgs.cs deleted file mode 100644 index 387b8f05..00000000 --- a/TwitchLib.Client/Events/OnRequiresVerifiedPhoneNumberArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client that a verified phone number is required to chat. - /// Implements the - /// - /// - /// - public class OnRequiresVerifiedPhoneNumberArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} \ No newline at end of file diff --git a/TwitchLib.Client/Events/OnSlowModeArgs.cs b/TwitchLib.Client/Events/OnSlowModeArgs.cs deleted file mode 100644 index d18e1cc0..00000000 --- a/TwitchLib.Client/Events/OnSlowModeArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client a message was not sent because its in slow mode. - /// Implements the - /// - /// - /// - public class OnSlowModeArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnSubsOnlyArgs.cs b/TwitchLib.Client/Events/OnSubsOnlyArgs.cs deleted file mode 100644 index 1163de36..00000000 --- a/TwitchLib.Client/Events/OnSubsOnlyArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client a message was not sent because its subs only mode. - /// Implements the - /// - /// - /// - public class OnSubsOnlyArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Events/OnSuspendedArgs.cs b/TwitchLib.Client/Events/OnSuspendedArgs.cs deleted file mode 100644 index 94075f31..00000000 --- a/TwitchLib.Client/Events/OnSuspendedArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE telling the client a message was not sent because the channel is suspended. - /// Implements the - /// - /// - /// - public class OnSuspendedArgs : EventArgs - { - /// - /// Property representing message send with the NOTICE - /// - public string Message; - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - } -} diff --git a/TwitchLib.Client/Interfaces/ITwitchClient.cs b/TwitchLib.Client/Interfaces/ITwitchClient.cs index 382c8a3d..060a68dd 100644 --- a/TwitchLib.Client/Interfaces/ITwitchClient.cs +++ b/TwitchLib.Client/Interfaces/ITwitchClient.cs @@ -78,7 +78,7 @@ public interface ITwitchClient /// /// Fires when client connects to Twitch. /// - event AsyncEventHandler OnConnected; + event AsyncEventHandler OnConnected; /// /// Fires when client joins a channel. @@ -130,16 +130,6 @@ public interface ITwitchClient /// event AsyncEventHandler OnUserJoined; - /// - /// Fires when a moderator joined the channel's chat room, returns username and channel. - /// - event AsyncEventHandler OnModeratorJoined; - - /// - /// Fires when a moderator joins the channel's chat room, returns username and channel. - /// - event AsyncEventHandler OnModeratorLeft; - /// /// Fires when a message gets deleted in chat. /// @@ -248,47 +238,47 @@ public interface ITwitchClient /// /// Occurs when a reconnection occurs. /// - event AsyncEventHandler OnReconnected; + event AsyncEventHandler OnReconnected; /// /// Occurs when chatting in a channel that requires a verified email without a verified email attached to the account. /// - event AsyncEventHandler OnRequiresVerifiedEmail; + event AsyncEventHandler OnRequiresVerifiedEmail; /// /// Occurs when chatting in a channel that requires a verified phone number without a verified phone number attached to the account. /// - event AsyncEventHandler OnRequiresVerifiedPhoneNumber; + event AsyncEventHandler OnRequiresVerifiedPhoneNumber; /// /// Occurs when send message rate limit has been applied to the client in a specific channel by Twitch /// - event AsyncEventHandler OnRateLimit; + event AsyncEventHandler OnRateLimit; /// /// Occurs when sending duplicate messages and user is not permitted to do so /// - event AsyncEventHandler OnDuplicate; + event AsyncEventHandler OnDuplicate; /// /// Occurs when chatting in a channel that the user is banned in bcs of an already banned alias with the same Email /// - event AsyncEventHandler OnBannedEmailAlias; + event AsyncEventHandler OnBannedEmailAlias; /// /// Fires when TwitchClient attempts to host a channel it is in. /// - event AsyncEventHandler OnSelfRaidError; + event AsyncEventHandler OnSelfRaidError; /// /// Fires when TwitchClient receives generic no permission error from Twitch. /// - event AsyncEventHandler OnNoPermissionError; + event AsyncEventHandler OnNoPermissionError; /// /// Fires when newly raided channel is mature audience only. /// - event AsyncEventHandler OnRaidedChannelIsMatureAudience; + event AsyncEventHandler OnRaidedChannelIsMatureAudience; /// /// Fires when the client was unable to join a channel. @@ -298,37 +288,37 @@ public interface ITwitchClient /// /// Fires when the client attempts to send a message to a channel in followers only mode, as a non-follower /// - event AsyncEventHandler OnFollowersOnly; + event AsyncEventHandler OnFollowersOnly; /// /// Fires when the client attempts to send a message to a channel in subs only mode, as a non-sub /// - event AsyncEventHandler OnSubsOnly; + event AsyncEventHandler OnSubsOnly; /// /// Fires when the client attempts to send a non-emote message to a channel in emotes only mode /// - event AsyncEventHandler OnEmoteOnly; + event AsyncEventHandler OnEmoteOnly; /// /// Fires when the client attempts to send a message to a channel that has been suspended /// - event AsyncEventHandler OnSuspended; + event AsyncEventHandler OnSuspended; /// /// Fires when the client attempts to send a message to a channel they're banned in /// - event AsyncEventHandler OnBanned; + event AsyncEventHandler OnBanned; /// /// Fires when the client attempts to send a message in a channel with slow mode enabled, without cooldown expiring /// - event AsyncEventHandler OnSlowMode; + event AsyncEventHandler OnSlowMode; /// /// Fires when the client attempts to send a message in a channel with r9k mode enabled, and message was not permitted /// - event AsyncEventHandler OnR9kMode; + event AsyncEventHandler OnR9kMode; /// /// Fires when the client receives a PRIVMSG tagged as an user-intro diff --git a/TwitchLib.Client/OnNoPermissionErrorArgs.cs b/TwitchLib.Client/OnNoPermissionErrorArgs.cs deleted file mode 100644 index 60fec08d..00000000 --- a/TwitchLib.Client/OnNoPermissionErrorArgs.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE when the client receives generic no permission error from Twitch. - /// Implements the - /// - /// - /// - public class OnNoPermissionErrorArgs : EventArgs - { - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - - /// - /// Property representing message send with the NOTICE - /// - public string Message; - } -} diff --git a/TwitchLib.Client/OnSelfRaidErrorArgs.cs b/TwitchLib.Client/OnSelfRaidErrorArgs.cs deleted file mode 100644 index 40219723..00000000 --- a/TwitchLib.Client/OnSelfRaidErrorArgs.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing a NOTICE when the client attempts to host a channel it is in. - /// Implements the - /// - /// - /// - public class OnSelfRaidErrorArgs : EventArgs - { - /// - /// Property representing channel bot is connected to. - /// - public string Channel; - - /// - /// Property representing message send with the NOTICE - /// - public string Message; - } -} diff --git a/TwitchLib.Client/Throttling/ThrottlingService.cs b/TwitchLib.Client/Throttling/ThrottlingService.cs index 9a1d3697..1dc91797 100644 --- a/TwitchLib.Client/Throttling/ThrottlingService.cs +++ b/TwitchLib.Client/Throttling/ThrottlingService.cs @@ -65,13 +65,13 @@ internal bool Enqueue(OutboundChatMessage message) _queue.Enqueue((DateTime.UtcNow, message)); return true; } - - private Task StartThrottlerAsync(object sender, OnConnectedEventArgs args) + + private Task StartThrottlerAsync(object sender, Communication.Events.OnConnectedEventArgs args) { // Cancel old token first _tokenSource.Cancel(); _tokenSource = new CancellationTokenSource(); - _sendTask= Task.Run(async() => await SendTaskActionAsync(), _tokenSource.Token); + _sendTask = Task.Run(async () => await SendTaskActionAsync(), _tokenSource.Token); return Task.CompletedTask; } diff --git a/TwitchLib.Client/TwitchClient.cs b/TwitchLib.Client/TwitchClient.cs index 4a7ff079..e1299b6d 100644 --- a/TwitchLib.Client/TwitchClient.cs +++ b/TwitchLib.Client/TwitchClient.cs @@ -183,7 +183,7 @@ public class TwitchClient : ITwitchClient /// /// Fires when client connects to Twitch. /// - public event AsyncEventHandler OnConnected; + public event AsyncEventHandler OnConnected; /// /// Fires when client joins a channel. @@ -235,16 +235,6 @@ public class TwitchClient : ITwitchClient /// public event AsyncEventHandler OnUserJoined; - /// - /// Fires when a moderator joined the channel's chat room, returns username and channel. - /// - public event AsyncEventHandler OnModeratorJoined; - - /// - /// Fires when a moderator joins the channel's chat room, returns username and channel. - /// - public event AsyncEventHandler OnModeratorLeft; - /// /// Fires when a message gets deleted in chat. /// @@ -353,47 +343,47 @@ public class TwitchClient : ITwitchClient /// /// Occurs when a reconnection occurs. /// - public event AsyncEventHandler OnReconnected; + public event AsyncEventHandler OnReconnected; /// /// Occurs when chatting in a channel that requires a verified email without a verified email attached to the account. /// - public event AsyncEventHandler OnRequiresVerifiedEmail; + public event AsyncEventHandler OnRequiresVerifiedEmail; /// /// Occurs when chatting in a channel that requires a verified phone number without a verified phone number attached to the account. /// - public event AsyncEventHandler OnRequiresVerifiedPhoneNumber; + public event AsyncEventHandler OnRequiresVerifiedPhoneNumber; /// /// Occurs when send message rate limit has been applied to the client in a specific channel by Twitch /// - public event AsyncEventHandler OnRateLimit; + public event AsyncEventHandler OnRateLimit; /// /// Occurs when sending duplicate messages and user is not permitted to do so /// - public event AsyncEventHandler OnDuplicate; + public event AsyncEventHandler OnDuplicate; /// /// Occurs when chatting in a channel that the user is banned in bcs of an already banned alias with the same Email /// - public event AsyncEventHandler OnBannedEmailAlias; + public event AsyncEventHandler OnBannedEmailAlias; /// /// Fires when TwitchClient attempts to host a channel it is in. /// - public event AsyncEventHandler OnSelfRaidError; + public event AsyncEventHandler OnSelfRaidError; /// /// Fires when TwitchClient receives generic no permission error from Twitch. /// - public event AsyncEventHandler OnNoPermissionError; + public event AsyncEventHandler OnNoPermissionError; /// /// Fires when newly raided channel is mature audience only. /// - public event AsyncEventHandler OnRaidedChannelIsMatureAudience; + public event AsyncEventHandler OnRaidedChannelIsMatureAudience; /// /// Fires when the client was unable to join a channel. @@ -403,37 +393,37 @@ public class TwitchClient : ITwitchClient /// /// Fires when the client attempts to send a message to a channel in followers only mode, as a non-follower /// - public event AsyncEventHandler OnFollowersOnly; + public event AsyncEventHandler OnFollowersOnly; /// /// Fires when the client attempts to send a message to a channel in subs only mode, as a non-sub /// - public event AsyncEventHandler OnSubsOnly; + public event AsyncEventHandler OnSubsOnly; /// /// Fires when the client attempts to send a non-emote message to a channel in emotes only mode /// - public event AsyncEventHandler OnEmoteOnly; + public event AsyncEventHandler OnEmoteOnly; /// /// Fires when the client attempts to send a message to a channel that has been suspended /// - public event AsyncEventHandler OnSuspended; + public event AsyncEventHandler OnSuspended; /// /// Fires when the client attempts to send a message to a channel they're banned in /// - public event AsyncEventHandler OnBanned; + public event AsyncEventHandler OnBanned; /// /// Fires when the client attempts to send a message in a channel with slow mode enabled, without cooldown expiring /// - public event AsyncEventHandler OnSlowMode; + public event AsyncEventHandler OnSlowMode; /// /// Fires when the client attempts to send a message in a channel with r9k mode enabled, and message was not permitted /// - public event AsyncEventHandler OnR9kMode; + public event AsyncEventHandler OnR9kMode; /// /// Fires when the client receives a PRIVMSG tagged as an user-intro @@ -932,8 +922,8 @@ private Task _client_OnDisconnected(object sender, OnDisconnectedEventArgs e) /// Handles the OnReconnected event of the _client control. /// /// The source of the event. - /// The instance containing the event data. - private async Task _client_OnReconnected(object sender, OnConnectedEventArgs e) + /// The instance containing the event data. + private async Task _client_OnReconnected(object sender, Communication.Events.OnConnectedEventArgs e) { await SendHandshake(); @@ -948,7 +938,7 @@ private async Task _client_OnReconnected(object sender, OnConnectedEventArgs e) } _joinedChannelManager.Clear(); - await OnReconnected.TryInvoke(sender, new OnConnectedArgs()); + await OnReconnected.TryInvoke(sender, new Events.OnConnectedEventArgs()); } static readonly string[] NewLineSeparator = new[] @@ -1115,7 +1105,6 @@ private Task HandleIrcMessageAsync(IrcMessage ircMessage) IrcCommand.UserNotice => HandleUserNotice(ircMessage), IrcCommand.RoomState => HandleRoomState(ircMessage), IrcCommand.Reconnect => ReconnectAsync(), - IrcCommand.Mode => HandleMode(ircMessage), IrcCommand.Cap => HandleCap(ircMessage), IrcCommand.RPL_004 => Handle004(), IrcCommand.RPL_353 => Handle353(ircMessage), @@ -1217,13 +1206,13 @@ private Task HandleNotice(IrcMessage ircMessage) Moderators = message.SplitFirst(':').Remainder.ToString().Replace(" ", "").Split(',') }), MsgIds.NoMods => OnModeratorsReceived?.Invoke(this, new() { Channel = channel, Moderators = Array.Empty() }), - MsgIds.NoPermission => OnNoPermissionError?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.RaidErrorSelf => OnSelfRaidError?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.RaidNoticeMature => OnRaidedChannelIsMatureAudience?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgBannedEmailAlias => OnBannedEmailAlias?.Invoke(this, new() { Channel = channel, Message = message }), + MsgIds.NoPermission => OnNoPermissionError?.Invoke(this, new(channel, message)), + MsgIds.RaidErrorSelf => OnSelfRaidError?.Invoke(this, new(channel, message)), + MsgIds.RaidNoticeMature => OnRaidedChannelIsMatureAudience?.Invoke(this, new(channel, message)), + MsgIds.MsgBannedEmailAlias => OnBannedEmailAlias?.Invoke(this, new(channel, message)), MsgIds.MsgChannelSuspended => HandleChannelSuspended(ircMessage), - MsgIds.MsgRequiresVerifiedPhoneNumber => OnRequiresVerifiedPhoneNumber?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgVerifiedEmail => OnRequiresVerifiedEmail?.Invoke(this, new() { Channel = channel, Message = message }), + MsgIds.MsgRequiresVerifiedPhoneNumber => OnRequiresVerifiedPhoneNumber?.Invoke(this, new(channel, message)), + MsgIds.MsgVerifiedEmail => OnRequiresVerifiedEmail?.Invoke(this, new(channel, message)), MsgIds.NoVIPs => OnVIPsReceived?.Invoke(this, new() { Channel = channel, VIPs = Array.Empty() }), MsgIds.VIPsSuccess => OnVIPsReceived?.Invoke(this, new() { @@ -1231,15 +1220,15 @@ private Task HandleNotice(IrcMessage ircMessage) // TODO: Make it less allocatey VIPs = message.SplitFirst(':').Remainder.ToString().Replace(" ", "").Replace(".", "").Split(',') }), - MsgIds.MsgRateLimit => OnRateLimit?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgDuplicate => OnDuplicate?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgFollowersOnly => OnFollowersOnly?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgSubsOnly => OnSubsOnly?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgEmoteOnly => OnEmoteOnly?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgSuspended => OnSuspended?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgBanned => OnBanned?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgSlowMode => OnSlowMode?.Invoke(this, new() { Channel = channel, Message = message }), - MsgIds.MsgR9k => OnR9kMode?.Invoke(this, new() { Channel = channel, Message = message }), + MsgIds.MsgRateLimit => OnRateLimit?.Invoke(this, new(channel, message)), + MsgIds.MsgDuplicate => OnDuplicate?.Invoke(this, new(channel, message)), + MsgIds.MsgFollowersOnly => OnFollowersOnly?.Invoke(this, new(channel, message)), + MsgIds.MsgSubsOnly => OnSubsOnly?.Invoke(this, new(channel, message)), + MsgIds.MsgEmoteOnly => OnEmoteOnly?.Invoke(this, new(channel, message)), + MsgIds.MsgSuspended => OnSuspended?.Invoke(this, new(channel, message)), + MsgIds.MsgBanned => OnBanned?.Invoke(this, new(channel, message)), + MsgIds.MsgSlowMode => OnSlowMode?.Invoke(this, new(channel, message)), + MsgIds.MsgR9k => OnR9kMode?.Invoke(this, new(channel, message)), _ => OnUnaccountedFor?.Invoke(this, new() { BotUsername = TwitchUsername, @@ -1517,33 +1506,6 @@ private Task HandleUserNotice(IrcMessage ircMessage) }; } - /// - /// Handles the mode. - /// - /// The irc message. - private Task HandleMode(IrcMessage ircMessage) - { - if (ircMessage.Message.StartsWith("+o")) - { - return OnModeratorJoined.TryInvoke(this, new() - { - Channel = ircMessage.Channel, - Username = ircMessage.Message.SplitFirst(' ').Remainder.ToString() - }); - } - - if (ircMessage.Message.StartsWith("-o")) - { - return OnModeratorLeft.TryInvoke(this, new() - { - Channel = ircMessage.Channel, - Username = ircMessage.Message.SplitFirst(' ').Remainder.ToString() - }); - } - - return Task.CompletedTask; - } - /// /// Handles the Cap /// From a95e67d3be6fba671c04be5c26675ac218cdd17d Mon Sep 17 00:00:00 2001 From: AoshiW Date: Sun, 30 Jul 2023 09:44:32 +0200 Subject: [PATCH 2/8] delete sync methods wrapper around async --- .../TwitchClientEventTests.cs | 32 ++++----- TwitchLib.Client/Interfaces/ITwitchClient.cs | 45 +----------- TwitchLib.Client/TwitchClient.cs | 70 +------------------ 3 files changed, 18 insertions(+), 129 deletions(-) diff --git a/TwitchLib.Client.Test/TwitchClientEventTests.cs b/TwitchLib.Client.Test/TwitchClientEventTests.cs index ed52f878..3e6e7aef 100644 --- a/TwitchLib.Client.Test/TwitchClientEventTests.cs +++ b/TwitchLib.Client.Test/TwitchClientEventTests.cs @@ -31,7 +31,7 @@ await Assert.RaisesAsync( async () => { client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await _mockClient.ReceiveMessage($":tmi.twitch.tv 001 {TWITCH_BOT_USERNAME} :Welcome, GLHF!"); }); } @@ -42,7 +42,7 @@ public async Task ClientCanJoinChannels() var client = new TwitchClient(_mockClient); client.OnConnected += async (sender, e) => { - client.JoinChannel(TWITCH_CHANNEL); + await client.JoinChannelAsync(TWITCH_CHANNEL); await ReceivedRoomState(); }; @@ -52,7 +52,7 @@ await Assert.RaisesAsync( async () => { client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTwitchConnected(); }); @@ -68,7 +68,7 @@ public async Task MessageEmoteCollectionFilled() client.OnMessageReceived += async (sender, e) => emoteCount = e.ChatMessage.EmoteSet.Emotes.Count; client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTwitchConnected(); while (emoteCount == 0 && DateTime.Now < finish) @@ -88,7 +88,7 @@ public async void ClientRaisesOnConnected() async () => { client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTwitchConnected(); }); } @@ -104,7 +104,7 @@ await Assert.RaisesAsync( async () => { client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTestMessage(); }); } @@ -120,9 +120,9 @@ await Assert.RaisesAsync( async () => { client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTwitchConnected(); - client.JoinChannel(TWITCH_CHANNEL); + await client.JoinChannelAsync(TWITCH_CHANNEL); await ReceivedRoomState(); }); } @@ -132,9 +132,9 @@ public async Task ClientChannelAddedToJoinedChannels() { var client = new TwitchClient(_mockClient); client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTwitchConnected(); - client.JoinChannel(TWITCH_CHANNEL); + await client.JoinChannelAsync(TWITCH_CHANNEL); Assert.Equal((double)1, client.JoinedChannels.Count,0); } @@ -150,11 +150,11 @@ await Assert.RaisesAsync( async () => { client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTwitchConnected(); - client.JoinChannel(TWITCH_CHANNEL); + await client.JoinChannelAsync(TWITCH_CHANNEL); await ReceivedRoomState(); - client.Disconnect(); + await client.DisconnectAsync(); }); } @@ -173,14 +173,14 @@ public async Task ClientReconnectsOk() client.OnConnected += async (s, e) => { pauseConnected.Set(); - client.Disconnect(); + await client.DisconnectAsync(); }; - client.OnDisconnected += async (s, e) => { client.Reconnect(); }; + client.OnDisconnected += async (s, e) => { await client.ReconnectAsync(); }; client.OnReconnected += async (s, e) => { pauseReconnected.Set(); }; client.Initialize(new Models.ConnectionCredentials(TWITCH_BOT_USERNAME, "OAuth")); - client.Connect(); + await client.ConnectAsync(); await ReceivedTwitchConnected(); Assert.True(pauseConnected.WaitOne(5000)); diff --git a/TwitchLib.Client/Interfaces/ITwitchClient.cs b/TwitchLib.Client/Interfaces/ITwitchClient.cs index 060a68dd..99ed8eef 100644 --- a/TwitchLib.Client/Interfaces/ITwitchClient.cs +++ b/TwitchLib.Client/Interfaces/ITwitchClient.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using TwitchLib.Client.Events; +using TwitchLib.Client.Events; using TwitchLib.Client.Models; using TwitchLib.Communication.Events; @@ -350,33 +348,17 @@ public interface ITwitchClient /// The credentials. void SetConnectionCredentials(ConnectionCredentials credentials); - /// - /// Connects this instance. - /// - /// bool representing Connect() result - bool Connect(); - /// /// Connects this instance. /// /// bool representing Connect() result Task ConnectAsync(); - /// - /// Disconnects this instance. - /// - void Disconnect(); - /// /// Disconnects this instance. /// Task DisconnectAsync(); - /// - /// Reconnects this instance. - /// - void Reconnect(); - /// /// Reconnects this instance. /// @@ -388,13 +370,6 @@ public interface ITwitchClient /// The channel. /// JoinedChannel. JoinedChannel GetJoinedChannel(string channel); - - /// - /// Joins the channel. - /// - /// The channel. - /// if set to true [override check]. - void JoinChannel(string channel, bool overrideCheck = false); /// /// Joins the channel. @@ -403,35 +378,17 @@ public interface ITwitchClient /// if set to true [override check]. Task JoinChannelAsync(string channel, bool overrideCheck = false); - /// - /// Leaves the channel. - /// - /// The channel. - void LeaveChannel(JoinedChannel channel); - /// /// Leaves the channel. /// /// The channel. Task LeaveChannelAsync(JoinedChannel channel); - /// - /// Leaves the channel. - /// - /// The channel. - void LeaveChannel(string channel); - /// /// Leaves the channel. /// /// The channel. Task LeaveChannelAsync(string channel); - - /// - /// Called when [read line test]. - /// - /// The raw irc. - void OnReadLineTest(string rawIrc); /// /// Called when [read line test]. diff --git a/TwitchLib.Client/TwitchClient.cs b/TwitchLib.Client/TwitchClient.cs index e1299b6d..dc80456c 100644 --- a/TwitchLib.Client/TwitchClient.cs +++ b/TwitchLib.Client/TwitchClient.cs @@ -1,10 +1,6 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Reflection; -using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using TwitchLib.Client.Enums; using TwitchLib.Client.Enums.Internal; using TwitchLib.Client.Events; @@ -670,15 +666,6 @@ public Task SendReplyAsync(string channel, string replyToId, string message, boo #region Connection Calls - /// - /// Start connecting to the Twitch IRC chat. - /// - /// bool representing Connect() result - public bool Connect() - { - return ConnectAsync().GetAwaiter().GetResult(); - } - /// public async Task ConnectAsync() { @@ -699,14 +686,6 @@ public async Task ConnectAsync() return false; } - /// - /// Start disconnecting from the Twitch IRC chat. - /// - public void Disconnect() - { - DisconnectAsync().GetAwaiter().GetResult(); - } - /// public async Task DisconnectAsync() { @@ -722,14 +701,6 @@ public async Task DisconnectAsync() PreviousWhisper = null; } - /// - /// Start reconnecting to the Twitch IRC chat. - /// - public void Reconnect() - { - ReconnectAsync().GetAwaiter().GetResult(); - } - /// public async Task ReconnectAsync() { @@ -762,16 +733,6 @@ public void SetConnectionCredentials(ConnectionCredentials credentials) #region Channel Calls - /// - /// Join the Twitch IRC chat of . - /// - /// The channel to join. - /// Override a join check. - public void JoinChannel(string channel, bool overrideCheck = false) - { - JoinChannelAsync(channel, overrideCheck).GetAwaiter().GetResult(); - } - /// public Task JoinChannelAsync(string channel, bool overrideCheck = false) { @@ -813,16 +774,6 @@ public JoinedChannel GetJoinedChannel(string channel) return _joinedChannelManager.GetJoinedChannel(channel); } - /// - /// Leaves (PART) the Twitch IRC chat of . - /// - /// The channel to leave. - /// True is returned if the passed channel was found, false if channel not found. - public void LeaveChannel(string channel) - { - LeaveChannelAsync(channel).GetAwaiter().GetResult(); - } - /// public async Task LeaveChannelAsync(string channel) { @@ -844,16 +795,6 @@ public async Task LeaveChannelAsync(string channel) } } - /// - /// Leaves (PART) the Twitch IRC chat of . - /// - /// The JoinedChannel object to leave. - /// True is returned if the passed channel was found, false if channel not found. - public void LeaveChannel(JoinedChannel channel) - { - LeaveChannelAsync(channel).GetAwaiter().GetResult(); - } - /// public Task LeaveChannelAsync(JoinedChannel channel) { @@ -865,15 +806,6 @@ public Task LeaveChannelAsync(JoinedChannel channel) #endregion - /// - /// This method allows firing the message parser with a custom irc string allowing for easy testing - /// - /// This should be a raw IRC message resembling one received from Twitch IRC. - public void OnReadLineTest(string rawIrc) - { - OnReadLineTestAsync(rawIrc).GetAwaiter().GetResult(); - } - /// public Task OnReadLineTestAsync(string rawIrc) { From 23253b08a85c36a74842615cc09c3e8e437a8e99 Mon Sep 17 00:00:00 2001 From: AoshiW Date: Sun, 30 Jul 2023 11:56:25 +0200 Subject: [PATCH 3/8] Typo --- TwitchLib.Client/Extensions/EventInvocationExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TwitchLib.Client/Extensions/EventInvocationExtensions.cs b/TwitchLib.Client/Extensions/EventInvocationExtensions.cs index ef12cddb..0f0d4e42 100644 --- a/TwitchLib.Client/Extensions/EventInvocationExtensions.cs +++ b/TwitchLib.Client/Extensions/EventInvocationExtensions.cs @@ -5,12 +5,12 @@ namespace TwitchLib.Client.Extensions; /// /// Extends logic for handling events. /// -public static class EventInvocationExtensions +internal static class EventInvocationExtensions { /// /// Invokes the event handler when it is not null. Returns a completed task otherwise. /// - internal static Task TryInvoke(this AsyncEventHandler eventHandler, object sender, TEventArgs eventArgs) + public static Task TryInvoke(this AsyncEventHandler eventHandler, object sender, TEventArgs eventArgs) { return eventHandler?.Invoke(sender, eventArgs) ?? Task.CompletedTask; } From 9ea8a651923c0a24d15504bee9fa1e359f14758c Mon Sep 17 00:00:00 2001 From: AoshiW Date: Sun, 30 Jul 2023 13:31:47 +0200 Subject: [PATCH 4/8] remove unused Enum --- TwitchLib.Client.Enums/ChatColorPresets.cs | 37 ---------------------- TwitchLib.Client.Enums/CommercialLength.cs | 19 ----------- TwitchLib.Client.Enums/StringEnum.cs | 19 ----------- 3 files changed, 75 deletions(-) delete mode 100644 TwitchLib.Client.Enums/ChatColorPresets.cs delete mode 100644 TwitchLib.Client.Enums/CommercialLength.cs delete mode 100644 TwitchLib.Client.Enums/StringEnum.cs diff --git a/TwitchLib.Client.Enums/ChatColorPresets.cs b/TwitchLib.Client.Enums/ChatColorPresets.cs deleted file mode 100644 index 47748db4..00000000 --- a/TwitchLib.Client.Enums/ChatColorPresets.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace TwitchLib.Client.Enums -{ - /// Enum representing the available chat name color presets. - public enum ChatColorPresets - { - /// Chat color name. - Blue, - /// Chat color name. - Coral, - /// Chat color name. - DodgerBlue, - /// Chat color name. - SpringGreen, - /// Chat color name. - YellowGreen, - /// Chat color name. - Green, - /// Chat color name. - OrangeRed, - /// Chat color name. - Red, - /// Chat color name. - GoldenRod, - /// Chat color name. - HotPink, - /// Chat color name. - CadetBlue, - /// Chat color name. - SeaGreen, - /// Chat color name. - Chocolate, - /// Chat color name. - BlueViolet, - /// Chat color name. - Firebrick - } -} diff --git a/TwitchLib.Client.Enums/CommercialLength.cs b/TwitchLib.Client.Enums/CommercialLength.cs deleted file mode 100644 index 41a4d378..00000000 --- a/TwitchLib.Client.Enums/CommercialLength.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace TwitchLib.Client.Enums -{ - /// A list of valid commercial lengths. - public enum CommercialLength - { - /// 30 second commercial - Seconds30 = 30, - /// 60 second commercial - Seconds60 = 60, - /// 90 second commercial - Seconds90 = 90, - /// 120 second commercial - Seconds120 = 120, - /// 150 second commercial - Seconds150 = 150, - /// 180 second commercial - Seconds180 = 180 - } -} diff --git a/TwitchLib.Client.Enums/StringEnum.cs b/TwitchLib.Client.Enums/StringEnum.cs deleted file mode 100644 index b7ed9ba3..00000000 --- a/TwitchLib.Client.Enums/StringEnum.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace TwitchLib.Client.Enums -{ - ///Really cool way of doing string enums, credits to RogueException (https://github.com/RogueException) - public abstract class StringEnum - { - /// Value of enum - public string Value { get; } - - /// StringEnum constructor. - protected StringEnum(string value) - { - Value = value; - } - - /// Returns string value for overriden ToString() - /// Enum value - public override string ToString() => Value; - } -} From 41db3987d3f7a7ec592d5d2dba26000d31b71bd2 Mon Sep 17 00:00:00 2001 From: AoshiW Date: Mon, 31 Jul 2023 11:43:32 +0200 Subject: [PATCH 5/8] --- TwitchLib.Client/Interfaces/ITwitchClient.cs | 6 - TwitchLib.Client/TwitchClient.cs | 339 +++++-------------- 2 files changed, 77 insertions(+), 268 deletions(-) diff --git a/TwitchLib.Client/Interfaces/ITwitchClient.cs b/TwitchLib.Client/Interfaces/ITwitchClient.cs index 99ed8eef..e1a350a7 100644 --- a/TwitchLib.Client/Interfaces/ITwitchClient.cs +++ b/TwitchLib.Client/Interfaces/ITwitchClient.cs @@ -461,12 +461,6 @@ public interface ITwitchClient /// The message. Task SendQueuedItemAsync(string message); - /// - /// Sends the raw. - /// - /// The message. - void SendRaw(string message); - /// /// Sends the raw. /// diff --git a/TwitchLib.Client/TwitchClient.cs b/TwitchLib.Client/TwitchClient.cs index dc80456c..2b243d6c 100644 --- a/TwitchLib.Client/TwitchClient.cs +++ b/TwitchLib.Client/TwitchClient.cs @@ -88,63 +88,37 @@ public class TwitchClient : ITwitchClient #region Public Variables /// public ICollection ChatCommandIdentifiers { get; } = new HashSet(); + /// public ICollection WhisperCommandIdentifiers { get; } = new HashSet(); - /// - /// Assembly version of TwitchLib.Client. - /// - /// The version. - public Version Version => Assembly.GetEntryAssembly()?.GetName().Version; - /// - /// Checks if underlying client has been initialized. - /// - /// true if this instance is initialized; otherwise, false. + /// public bool IsInitialized => _client != null; - /// - /// A list of all channels the client is currently in. - /// - /// The joined channels. + /// public IReadOnlyList JoinedChannels => _joinedChannelManager.GetJoinedChannels(); - /// - /// Username of the user connected via this library. - /// - /// The twitch username. + /// public string TwitchUsername { get; private set; } - /// - /// The most recent whisper received. - /// - /// The previous whisper. + /// public WhisperMessage PreviousWhisper { get; private set; } - /// - /// The current connection status of the client. - /// - /// true if this instance is connected; otherwise, false. + /// public bool IsConnected => IsInitialized && _client?.IsConnected == true; - /// - /// The emotes this channel replaces. - /// - /// The channel emotes. - /// Twitch-handled emotes are automatically added to this collection (which also accounts for + /// + /// + /// Twitch-handled emotes are automatically added to this collection (which also accounts for /// managing user emote permissions such as sub-only emotes). Third-party emotes will have to be manually - /// added according to the availability rules defined by the third-party. + /// added according to the availability rules defined by the third-party. + /// public MessageEmoteCollection ChannelEmotes { get; } = new MessageEmoteCollection(); - /// - /// Will disable the client from sending automatic PONG responses to PING - /// - /// true if [disable automatic pong]; otherwise, false. + /// public bool DisableAutoPong { get; set; } = false; - /// - /// Determines whether Emotes will be replaced in messages. - /// - /// true if [will replace emotes]; otherwise, false. + /// public bool WillReplaceEmotes { get; set; } = false; /// @@ -157,278 +131,168 @@ public class TwitchClient : ITwitchClient /// public string ReplacedEmotesSuffix { get; set; } = ""; - /// - /// Provides access to connection credentials object. - /// - /// The connection credentials. + /// public ConnectionCredentials ConnectionCredentials { get; private set; } - #endregion #region Events - /// - /// Fires when an Announcement is received - /// + /// public event AsyncEventHandler OnAnnouncement; - /// - /// Fires when VIPs are received from chat - /// + /// public event AsyncEventHandler OnVIPsReceived; - /// - /// Fires when client connects to Twitch. - /// + /// public event AsyncEventHandler OnConnected; - /// - /// Fires when client joins a channel. - /// + /// public event AsyncEventHandler OnJoinedChannel; - /// - /// Fires on logging in with incorrect details, returns ErrorLoggingInException. - /// + /// public event AsyncEventHandler OnIncorrectLogin; - /// - /// Fires when connecting and channel state is changed, returns ChannelState. - /// + /// public event AsyncEventHandler OnChannelStateChanged; - /// - /// Fires when a user state is received, returns UserState. - /// + /// public event AsyncEventHandler OnUserStateChanged; - /// - /// Fires when a new chat message arrives, returns ChatMessage. - /// + /// public event AsyncEventHandler OnMessageReceived; - /// - /// Fires when a new whisper arrives, returns WhisperMessage. - /// + /// public event AsyncEventHandler OnWhisperReceived; - /// - /// Fires when a chat message is sent, returns username, channel and message. - /// + /// public event AsyncEventHandler OnMessageSent; - /// - /// Fires when command (uses custom chat command identifier) is received, returns channel, command, ChatMessage, arguments as string, arguments as list. - /// + /// public event AsyncEventHandler OnChatCommandReceived; - /// - /// Fires when command (uses custom whisper command identifier) is received, returns command, Whispermessage. - /// + /// public event AsyncEventHandler OnWhisperCommandReceived; - /// - /// Fires when a new viewer/chatter joined the channel's chat room, returns username and channel. - /// + /// public event AsyncEventHandler OnUserJoined; - /// - /// Fires when a message gets deleted in chat. - /// + /// public event AsyncEventHandler OnMessageCleared; - /// - /// Fires when new subscriber is announced in chat, returns Subscriber. - /// + /// public event AsyncEventHandler OnNewSubscriber; - /// - /// Fires when current subscriber renews subscription, returns ReSubscriber. - /// + /// public event AsyncEventHandler OnReSubscriber; - /// - /// Fires when a current Prime gaming subscriber converts to a paid subscription. - /// + /// public event AsyncEventHandler OnPrimePaidSubscriber; - /// - /// Fires when Twitch notifies client of existing users in chat. - /// + /// public event AsyncEventHandler OnExistingUsersDetected; - /// - /// Fires when a PART message is received from Twitch regarding a particular viewer - /// + /// public event AsyncEventHandler OnUserLeft; - /// - /// Fires when bot has disconnected. - /// + /// public event AsyncEventHandler OnDisconnected; - /// - /// Forces when bot suffers connection error. - /// + /// public event AsyncEventHandler OnConnectionError; - /// - /// Fires when a channel's chat is cleared. - /// + /// public event AsyncEventHandler OnChatCleared; - /// - /// Fires when a viewer gets timedout by any moderator. - /// + /// public event AsyncEventHandler OnUserTimedout; - /// - /// Fires when client successfully leaves a channel. - /// + /// public event AsyncEventHandler OnLeftChannel; - /// - /// Fires when a viewer gets banned by any moderator. - /// + /// public event AsyncEventHandler OnUserBanned; - /// - /// Fires when a list of moderators is received. - /// + /// public event AsyncEventHandler OnModeratorsReceived; - /// - /// Fires when confirmation of a chat color change request was received. - /// + /// public event AsyncEventHandler OnChatColorChanged; - /// - /// Fires when data is either received or sent. - /// + /// public event AsyncEventHandler OnSendReceiveData; - /// - /// Fires when a raid notification is detected in chat - /// + /// public event AsyncEventHandler OnRaidNotification; - /// - /// Fires when a subscription is gifted and announced in chat - /// + /// public event AsyncEventHandler OnGiftedSubscription; - /// - /// Fires when a community subscription is announced in chat - /// + /// public event AsyncEventHandler OnCommunitySubscription; - /// - /// Fires when a gifted subscription is continued and announced in chat - /// + /// public event AsyncEventHandler OnContinuedGiftedSubscription; - /// - /// Fires when a Message has been throttled. - /// + /// public event AsyncEventHandler OnMessageThrottled; - /// - /// Occurs when an Error is thrown in the protocol client - /// + /// public event AsyncEventHandler OnError; - /// - /// Occurs when a reconnection occurs. - /// + /// public event AsyncEventHandler OnReconnected; - /// - /// Occurs when chatting in a channel that requires a verified email without a verified email attached to the account. - /// + /// public event AsyncEventHandler OnRequiresVerifiedEmail; - /// - /// Occurs when chatting in a channel that requires a verified phone number without a verified phone number attached to the account. - /// + /// public event AsyncEventHandler OnRequiresVerifiedPhoneNumber; - /// - /// Occurs when send message rate limit has been applied to the client in a specific channel by Twitch - /// + /// public event AsyncEventHandler OnRateLimit; - /// - /// Occurs when sending duplicate messages and user is not permitted to do so - /// + /// public event AsyncEventHandler OnDuplicate; - /// - /// Occurs when chatting in a channel that the user is banned in bcs of an already banned alias with the same Email - /// + /// public event AsyncEventHandler OnBannedEmailAlias; - /// - /// Fires when TwitchClient attempts to host a channel it is in. - /// + /// public event AsyncEventHandler OnSelfRaidError; - /// - /// Fires when TwitchClient receives generic no permission error from Twitch. - /// + /// public event AsyncEventHandler OnNoPermissionError; - /// - /// Fires when newly raided channel is mature audience only. - /// + /// public event AsyncEventHandler OnRaidedChannelIsMatureAudience; - /// - /// Fires when the client was unable to join a channel. - /// + /// public event AsyncEventHandler OnFailureToReceiveJoinConfirmation; - /// - /// Fires when the client attempts to send a message to a channel in followers only mode, as a non-follower - /// + /// public event AsyncEventHandler OnFollowersOnly; - /// - /// Fires when the client attempts to send a message to a channel in subs only mode, as a non-sub - /// + /// public event AsyncEventHandler OnSubsOnly; - /// - /// Fires when the client attempts to send a non-emote message to a channel in emotes only mode - /// + /// public event AsyncEventHandler OnEmoteOnly; - /// - /// Fires when the client attempts to send a message to a channel that has been suspended - /// + /// public event AsyncEventHandler OnSuspended; - /// - /// Fires when the client attempts to send a message to a channel they're banned in - /// + /// public event AsyncEventHandler OnBanned; - /// - /// Fires when the client attempts to send a message in a channel with slow mode enabled, without cooldown expiring - /// + /// public event AsyncEventHandler OnSlowMode; - /// - /// Fires when the client attempts to send a message in a channel with r9k mode enabled, and message was not permitted - /// + /// public event AsyncEventHandler OnR9kMode; - /// - /// Fires when the client receives a PRIVMSG tagged as an user-intro - /// + /// public event AsyncEventHandler OnUserIntro; - /// - /// Fires when data is received from Twitch that is not able to be parsed. - /// + /// public event AsyncEventHandler OnUnaccountedFor; #endregion @@ -454,28 +318,20 @@ public TwitchClient( _sendOptions = sendOptions ?? new SendOptions(); } - /// - /// Initializes the TwitchChatClient class. - /// + /// /// /// If or dont have any command identifier the '!' is added. /// - /// The credentials to use to log in. - /// The channel to connect to. public void Initialize(ConnectionCredentials credentials, string channel = null) { if (channel?[0] == '#') channel = channel.Substring(1); InitializationHelper(credentials, new List() { channel }); } - /// - /// Initializes the TwitchChatClient class (with multiple channels). - /// + /// /// /// If or dont have any command identifier the '!' is added. /// - /// The credentials to use to log in. - /// List of channels to join when connected public void Initialize(ConnectionCredentials credentials, List channels) { channels = channels.ConvertAll(x => x[0] == '#' ? x.Substring(1) : x); @@ -547,15 +403,6 @@ private void InitializeClient() } #endregion - /// - /// Sends a RAW IRC message. - /// - /// The RAW message to be sent. - public void SendRaw(string message) - { - SendRawAsync(message).GetAwaiter().GetResult(); - } - /// public async Task SendRawAsync(string message) { @@ -603,35 +450,19 @@ private void SendTwitchMessage(JoinedChannel channel, string message, string rep _throttling.Enqueue(twitchMessage); } - /// - /// Sends a formatted Twitch channel chat message. - /// - /// Channel to send message to. - /// The message to be sent. - /// If set to true, the message will not actually be sent for testing purposes. + /// public void SendMessage(JoinedChannel channel, string message, bool dryRun = false) { SendTwitchMessage(channel, message,null, dryRun); } - /// - /// SendMessage wrapper that accepts channel in string form. - /// - /// The channel. - /// The message. - /// if set to true [dry run]. + /// public void SendMessage(string channel, string message, bool dryRun = false) { SendMessage(GetJoinedChannel(channel), message, dryRun); } - /// - /// Sends a formatted Twitch chat message reply. - /// - /// Channel to send Twitch chat reply to - /// The message id that is being replied to - /// Reply contents - /// if set to true [dry run] + /// public void SendReply(JoinedChannel channel, string replyToId, string message, bool dryRun = false) { SendReplyAsync(channel, replyToId, message, dryRun).GetAwaiter().GetResult(); @@ -644,13 +475,7 @@ public Task SendReplyAsync(JoinedChannel channel, string replyToId, string messa return Task.CompletedTask; } - /// - /// SendReply wrapper that accepts channel in string form. - /// - /// Channel to send Twitch chat reply to - /// The message id that is being replied to - /// Reply contents - /// if set to true [dry run] + /// public void SendReply(string channel, string replyToId, string message, bool dryRun = false) { SendReplyAsync(channel, replyToId, message, dryRun).GetAwaiter().GetResult(); @@ -713,11 +538,7 @@ public async Task ReconnectAsync() #endregion #region ConnectionCredentials - - /// - /// Sets the connection credentials. - /// - /// The credentials. + /// /// While the client is connected, you are unable to change the connection credentials. Please disconnect first and then change them. public void SetConnectionCredentials(ConnectionCredentials credentials) { @@ -754,11 +575,7 @@ public Task JoinChannelAsync(string channel, bool overrideCheck = false) return !_currentlyJoiningChannels ? QueueingJoinCheckAsync() : Task.CompletedTask; } - /// - /// Returns a JoinedChannel object using a passed string/>. - /// - /// String channel to search for. - /// JoinedChannel. + /// /// Must be connected to at least one channel. public JoinedChannel GetJoinedChannel(string channel) { @@ -1457,10 +1274,7 @@ private Task UnaccountedFor(string ircString) return Task.CompletedTask; } - /// - /// Sends the queued item. - /// - /// The message. + /// public void SendQueuedItem(string message) { SendQueuedItemAsync(message).GetAwaiter().GetResult(); @@ -1494,3 +1308,4 @@ protected static void HandleNotConnected() } } } +//1487 \ No newline at end of file From fca8c15ea42bccace7caca7a71094b9a9f9df616 Mon Sep 17 00:00:00 2001 From: AoshiW Date: Tue, 1 Aug 2023 11:30:40 +0200 Subject: [PATCH 6/8] rewrite: command workflow --- .../Builders/ChatCommandBuilder.cs | 67 -------------- .../Builders/WhisperCommandBuilder.cs | 62 ------------- TwitchLib.Client.Models/ChatCommand.cs | 52 ----------- TwitchLib.Client.Models/CommandInfo.cs | 92 +++++++++++++++++++ TwitchLib.Client.Models/WhisperCommand.cs | 49 ---------- TwitchLib.Client.Test/CommandInfoTest.cs | 17 ++++ .../Events/OnChatCommandReceivedArgs.cs | 20 ---- .../Events/OnMessageReceivedArgs.cs | 15 ++- .../Events/OnWhisperCommandReceivedArgs.cs | 19 ---- .../Events/OnWhisperReceivedArgs.cs | 15 ++- TwitchLib.Client/Interfaces/ITwitchClient.cs | 10 -- TwitchLib.Client/TwitchClient.cs | 37 ++------ 12 files changed, 142 insertions(+), 313 deletions(-) delete mode 100644 TwitchLib.Client.Models/Builders/ChatCommandBuilder.cs delete mode 100644 TwitchLib.Client.Models/Builders/WhisperCommandBuilder.cs delete mode 100644 TwitchLib.Client.Models/ChatCommand.cs create mode 100644 TwitchLib.Client.Models/CommandInfo.cs delete mode 100644 TwitchLib.Client.Models/WhisperCommand.cs create mode 100644 TwitchLib.Client.Test/CommandInfoTest.cs delete mode 100644 TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs delete mode 100644 TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs diff --git a/TwitchLib.Client.Models/Builders/ChatCommandBuilder.cs b/TwitchLib.Client.Models/Builders/ChatCommandBuilder.cs deleted file mode 100644 index 74976f0c..00000000 --- a/TwitchLib.Client.Models/Builders/ChatCommandBuilder.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Collections.Generic; - -namespace TwitchLib.Client.Models.Builders -{ - public sealed class ChatCommandBuilder : IBuilder - { - private readonly List _argumentsAsList = new List(); - private string _argumentsAsString; - private ChatMessage _chatMessage; - private char _commandIdentifier; - private string _commandText; - - private ChatCommandBuilder() - { - } - - public ChatCommandBuilder WithArgumentsAsList(params string[] argumentsList) - { - _argumentsAsList.AddRange(argumentsList); - return this; - } - - public ChatCommandBuilder WithArgumentsAsString(string argumentsAsString) - { - _argumentsAsString = argumentsAsString; - return this; - } - - public ChatCommandBuilder WithChatMessage(ChatMessage chatMessage) - { - _chatMessage = chatMessage; - return this; - } - - public ChatCommandBuilder WithCommandIdentifier(char commandIdentifier) - { - _commandIdentifier = commandIdentifier; - return this; - } - - public ChatCommandBuilder WithCommandText(string commandText) - { - _commandText = commandText; - return this; - } - - public static ChatCommandBuilder Create() - { - return new ChatCommandBuilder(); - } - - public ChatCommand Build() - { - return new ChatCommand( - _chatMessage, - _commandText, - _argumentsAsString, - _argumentsAsList, - _commandIdentifier); - } - - public ChatCommand BuildFromChatMessage(ChatMessage chatMessage) - { - return new ChatCommand(chatMessage); - } - } -} diff --git a/TwitchLib.Client.Models/Builders/WhisperCommandBuilder.cs b/TwitchLib.Client.Models/Builders/WhisperCommandBuilder.cs deleted file mode 100644 index 1ec4b44b..00000000 --- a/TwitchLib.Client.Models/Builders/WhisperCommandBuilder.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Collections.Generic; - -namespace TwitchLib.Client.Models.Builders -{ - public sealed class WhisperCommandBuilder : IBuilder - { - private readonly List _argumentsAsList = new List(); - private string _argumentsAsString; - private char _commandIdentifier; - private string _commandText; - private WhisperMessage _whisperMessage; - - private WhisperCommandBuilder() - { - } - - public WhisperCommandBuilder WithWhisperMessage(WhisperMessage whisperMessage) - { - _whisperMessage = whisperMessage; - return this; - } - - public WhisperCommandBuilder WithCommandText(string commandText) - { - _commandText = commandText; - return this; - } - - public WhisperCommandBuilder WithCommandIdentifier(char commandIdentifier) - { - _commandIdentifier = commandIdentifier; - return this; - } - - public WhisperCommandBuilder WithArgumentAsString(string argumentAsString) - { - _argumentsAsString = argumentAsString; - return this; - } - - public WhisperCommandBuilder WithArguments(params string[] arguments) - { - _argumentsAsList.AddRange(arguments); - return this; - } - - public static WhisperCommandBuilder Create() - { - return new WhisperCommandBuilder(); - } - - public WhisperCommand BuildFromWhisperMessage(WhisperMessage whisperMessage) - { - return new WhisperCommand(whisperMessage); - } - - public WhisperCommand Build() - { - return new WhisperCommand(_whisperMessage, _commandText, _argumentsAsString, _argumentsAsList, _commandIdentifier); - } - } -} diff --git a/TwitchLib.Client.Models/ChatCommand.cs b/TwitchLib.Client.Models/ChatCommand.cs deleted file mode 100644 index b53b07c1..00000000 --- a/TwitchLib.Client.Models/ChatCommand.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace TwitchLib.Client.Models -{ - /// Object representing a command received via Twitch chat. - public class ChatCommand - { - /// Property representing all arguments received in a List form. - public List ArgumentsAsList { get; } - - /// Property representing all arguments received in a string form. - public string ArgumentsAsString { get; } - - /// Property representing the chat message that the command came in. - public ChatMessage ChatMessage { get; } - - /// Property representing the command identifier (ie command prefix). - public char CommandIdentifier { get; } - - /// Property representing the actual command (without the command prefix). - public string CommandText { get; } - - /// ChatCommand constructor. - /// - public ChatCommand(ChatMessage chatMessage) - { - ChatMessage = chatMessage; - CommandText = chatMessage.Message.Split(' ')?[0].Substring(1, chatMessage.Message.Split(' ')[0].Length - 1) ?? chatMessage.Message.Substring(1, chatMessage.Message.Length - 1); ; - ArgumentsAsString = chatMessage.Message.Contains(" ") ? chatMessage.Message.Replace(chatMessage.Message.Split(' ')?[0] + " ", "") : ""; - if (!chatMessage.Message.Contains("\"") || chatMessage.Message.Count(x => x == '"') % 2 == 1) - ArgumentsAsList = chatMessage.Message.Split(' ')?.Where(arg => arg != chatMessage.Message[0] + CommandText).ToList() ?? new List(); - else - ArgumentsAsList = Common.Helpers.ParseQuotesAndNonQuotes(ArgumentsAsString); - CommandIdentifier = chatMessage.Message[0]; - } - - public ChatCommand( - ChatMessage chatMessage, - string commandText, - string argumentsAsString, - List argumentsAsList, - char commandIdentifier) - { - ChatMessage = chatMessage; - CommandText = commandText; - ArgumentsAsString = argumentsAsString; - ArgumentsAsList = argumentsAsList; - CommandIdentifier = commandIdentifier; - } - } -} diff --git a/TwitchLib.Client.Models/CommandInfo.cs b/TwitchLib.Client.Models/CommandInfo.cs new file mode 100644 index 00000000..f757aaaa --- /dev/null +++ b/TwitchLib.Client.Models/CommandInfo.cs @@ -0,0 +1,92 @@ +namespace TwitchLib.Client.Models; + +/// Object representing a command received via Twitch chat. +public class CommandInfo +{ + /// Property representing the command identifier (ie command prefix). + public char Identifier { get; } + + /// Property representing the actual command (without the command prefix). + public string Name { get; } + + /// Property representing all arguments received in a string form. + public string ArgumentsAsString { get; } + + /// Property representing all arguments received in a List form. + public List ArgumentsAsList { get; } + + public CommandInfo(char identifier, string name, string argumentsAsString = null, List argumentsAsList = null) + { + Identifier = identifier; + Name = name; + ArgumentsAsString = argumentsAsString; + ArgumentsAsList = argumentsAsList; + } + + public static bool TryParse(ReadOnlySpan s, out CommandInfo result) + { + result = default; + s = s.Trim(); + if (s.IsEmpty) + return false; + var commandIdentifier = s[0]; + s = s.Slice(1); + if (s.IsEmpty || s[0] == ' ') // if string contains only the identifier or the first char after identifier is space, then it is invalid input + return false; + var indexOfSpace = s.IndexOf(' '); + if (indexOfSpace == -1) + { + var name = s.ToString(); + result = new(commandIdentifier, name, string.Empty, new()); + } + else + { + var name = s.Slice(0, indexOfSpace).ToString(); + s = s.Slice(indexOfSpace + 1).TrimStart(); + var argumentsAsString = s.ToString(); + result = new(commandIdentifier, name, argumentsAsString, ParseArgumentsToList(s)); + } + return true; + + static List ParseArgumentsToList(ReadOnlySpan s) + { + int index; + var arguments = new List(); + while (!s.IsEmpty) + { + bool isQuote = s[0] == '"'; + if (s[0] == '"') + { + s = s.Slice(1); + index = s.IndexOf('"'); + } + else + { + index = s.IndexOfAny('"', ' '); + } + if (index == -1) + { + arguments.Add(s.ToString()); + s = default; + } + else + { + arguments.Add(s.Slice(0, index).ToString()); + if (!isQuote && s[index] == '"') // s"txt" we dont want remove quote after s + index--; + s = s.Slice(index + 1); + } + s = s.TrimStart(); + } + return arguments; + } + } + + /// + public override string ToString() + { + return ArgumentsAsString.Length == 0 + ? $"{Identifier}{Name}" + : $"{Identifier}{Name} {ArgumentsAsString}"; + } +} diff --git a/TwitchLib.Client.Models/WhisperCommand.cs b/TwitchLib.Client.Models/WhisperCommand.cs deleted file mode 100644 index be5e434d..00000000 --- a/TwitchLib.Client.Models/WhisperCommand.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace TwitchLib.Client.Models -{ - /// Object representing a command received via Twitch chat. - public class WhisperCommand - { - /// Property representing all arguments received in a List form. - public List ArgumentsAsList { get; } - - /// Property representing all arguments received in a string form. - public string ArgumentsAsString { get; } - - /// Property representing the command identifier (ie command prefix). - public char CommandIdentifier { get; } - - /// Property representing the actual command (without the command prefix). - public string CommandText { get; } - - /// Property representing the chat message that the command came in. - public WhisperMessage WhisperMessage { get; } - - /// ChatCommand constructor. - /// - public WhisperCommand(WhisperMessage whisperMessage) - { - WhisperMessage = whisperMessage; - CommandText = whisperMessage.Message.Split(' ')?[0].Substring(1, whisperMessage.Message.Split(' ')[0].Length - 1) ?? whisperMessage.Message.Substring(1, whisperMessage.Message.Length - 1); - ArgumentsAsString = whisperMessage.Message.Replace(whisperMessage.Message.Split(' ')?[0] + " ", ""); - ArgumentsAsList = whisperMessage.Message.Split(' ')?.Where(arg => arg != whisperMessage.Message[0] + CommandText).ToList() ?? new List(); - CommandIdentifier = whisperMessage.Message[0]; - } - - public WhisperCommand( - WhisperMessage whisperMessage, - string commandText, - string argumentsAsString, - List argumentsAsList, - char commandIdentifier) - { - WhisperMessage = whisperMessage; - CommandText = commandText; - ArgumentsAsString = argumentsAsString; - ArgumentsAsList = argumentsAsList; - CommandIdentifier = commandIdentifier; - } - } -} diff --git a/TwitchLib.Client.Test/CommandInfoTest.cs b/TwitchLib.Client.Test/CommandInfoTest.cs new file mode 100644 index 00000000..1ac0e754 --- /dev/null +++ b/TwitchLib.Client.Test/CommandInfoTest.cs @@ -0,0 +1,17 @@ +using TwitchLib.Client.Models; +using Xunit; + +namespace TwitchLib.Client.Test; + +public class CommandInfoTest +{ + [Theory] + [InlineData("")] + [InlineData("!")] + [InlineData("! command")] + public void ParsingFailAndReturnNull(string s) + { + Assert.False(CommandInfo.TryParse(s, out CommandInfo commandInfo)); + Assert.Null(commandInfo); + } +} diff --git a/TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs b/TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs deleted file mode 100644 index ecc376dc..00000000 --- a/TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using TwitchLib.Client.Models; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing chat command received event. - /// Implements the - /// - /// - /// - public class OnChatCommandReceivedArgs : EventArgs - { - /// - /// The command - /// - /// Property representing received command. - public ChatCommand Command; - } -} diff --git a/TwitchLib.Client/Events/OnMessageReceivedArgs.cs b/TwitchLib.Client/Events/OnMessageReceivedArgs.cs index bbaa5ba0..255ab908 100644 --- a/TwitchLib.Client/Events/OnMessageReceivedArgs.cs +++ b/TwitchLib.Client/Events/OnMessageReceivedArgs.cs @@ -1,5 +1,4 @@ -using System; -using TwitchLib.Client.Models; +using TwitchLib.Client.Models; namespace TwitchLib.Client.Events { @@ -14,6 +13,16 @@ public class OnMessageReceivedArgs : EventArgs /// /// Property representing received chat message. /// - public ChatMessage ChatMessage; + public ChatMessage ChatMessage { get; } + + public bool IsCommand => CommandInfo is not null; + + public CommandInfo CommandInfo { get; } + + public OnMessageReceivedArgs(ChatMessage message, CommandInfo commandInfo = null) + { + ChatMessage = message; + CommandInfo = commandInfo; + } } } diff --git a/TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs b/TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs deleted file mode 100644 index e22cc18a..00000000 --- a/TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using TwitchLib.Client.Models; - -namespace TwitchLib.Client.Events -{ - /// - /// Args representing whisper command received event. - /// Implements the - /// - /// - /// - public class OnWhisperCommandReceivedArgs : EventArgs - { - /// - /// Property representing received command. - /// - public WhisperCommand Command; - } -} diff --git a/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs b/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs index 1638b5e6..29238ac6 100644 --- a/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs +++ b/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs @@ -1,5 +1,4 @@ -using System; -using TwitchLib.Client.Models; +using TwitchLib.Client.Models; namespace TwitchLib.Client.Events { @@ -14,6 +13,16 @@ public class OnWhisperReceivedArgs : EventArgs /// /// The whisper message /// - public WhisperMessage WhisperMessage; + public WhisperMessage WhisperMessage { get; } + + public bool IsCommand => CommandInfo is not null; + + public CommandInfo CommandInfo { get; } + + public OnWhisperReceivedArgs(WhisperMessage message, CommandInfo commandInfo = null) + { + WhisperMessage = message; + CommandInfo = commandInfo; + } } } diff --git a/TwitchLib.Client/Interfaces/ITwitchClient.cs b/TwitchLib.Client/Interfaces/ITwitchClient.cs index e1a350a7..86934937 100644 --- a/TwitchLib.Client/Interfaces/ITwitchClient.cs +++ b/TwitchLib.Client/Interfaces/ITwitchClient.cs @@ -113,16 +113,6 @@ public interface ITwitchClient /// event AsyncEventHandler OnMessageSent; - /// - /// Fires when command (uses custom chat command identifier) is received, returns channel, command, ChatMessage, arguments as string, arguments as list. - /// - event AsyncEventHandler OnChatCommandReceived; - - /// - /// Fires when command (uses custom whisper command identifier) is received, returns command, Whispermessage. - /// - event AsyncEventHandler OnWhisperCommandReceived; - /// /// Fires when a new viewer/chatter joined the channel's chat room, returns username and channel. /// diff --git a/TwitchLib.Client/TwitchClient.cs b/TwitchLib.Client/TwitchClient.cs index 2b243d6c..175c8a39 100644 --- a/TwitchLib.Client/TwitchClient.cs +++ b/TwitchLib.Client/TwitchClient.cs @@ -166,12 +166,6 @@ public class TwitchClient : ITwitchClient /// public event AsyncEventHandler OnMessageSent; - /// - public event AsyncEventHandler OnChatCommandReceived; - - /// - public event AsyncEventHandler OnWhisperCommandReceived; - /// public event AsyncEventHandler OnUserJoined; @@ -893,6 +887,7 @@ private async Task HandlePrivMsg(IrcMessage ircMessage) WillReplaceEmotes, ReplacedEmotesPrefix, ReplacedEmotesSuffix); + CommandInfo commandInfo = null; foreach (JoinedChannel joinedChannel in JoinedChannels .Where(x => x.Channel.Equals(ircMessage.Channel, StringComparison.InvariantCultureIgnoreCase))) @@ -900,7 +895,6 @@ private async Task HandlePrivMsg(IrcMessage ircMessage) joinedChannel.HandleMessage(chatMessage); } - await OnMessageReceived.TryInvoke(this, new() { ChatMessage = chatMessage }); if (ircMessage.Tags.TryGetValue(Tags.MsgId, out var msgId) && msgId == MsgIds.UserIntro @@ -909,13 +903,12 @@ private async Task HandlePrivMsg(IrcMessage ircMessage) await OnUserIntro.Invoke(this, new() { ChatMessage = chatMessage }); } - if (ChatCommandIdentifiers.Count != 0 - && !string.IsNullOrEmpty(chatMessage.Message) - && ChatCommandIdentifiers.Contains(chatMessage.Message[0]) - && OnChatCommandReceived != null) + if (ChatCommandIdentifiers.Contains(chatMessage.Message[0])) { - await OnChatCommandReceived.Invoke(this, new() { Command = new ChatCommand(chatMessage) }); + _ = CommandInfo.TryParse(chatMessage.Message.AsSpan(), out commandInfo); } + + await OnMessageReceived.TryInvoke(this, new(chatMessage, commandInfo)); } /// @@ -1135,26 +1128,14 @@ private async Task HandleWhisper(IrcMessage ircMessage) { var whisperMessage = new WhisperMessage(ircMessage, TwitchUsername); PreviousWhisper = whisperMessage; + CommandInfo commandInfo = null; - await OnWhisperReceived.TryInvoke(this, new() { WhisperMessage = whisperMessage }); - - if (WhisperCommandIdentifiers.Count != 0 - && !string.IsNullOrEmpty(whisperMessage.Message) - && WhisperCommandIdentifiers.Contains(whisperMessage.Message[0])) + if (WhisperCommandIdentifiers.Contains(whisperMessage.Message[0])) { - var whisperCommand = new WhisperCommand(whisperMessage); - await OnWhisperCommandReceived.TryInvoke(this, new() { Command = whisperCommand }); - return; + _ = CommandInfo.TryParse(whisperMessage.Message.AsSpan(), out commandInfo); } - var rawMessage = ircMessage.ToString(); - await (OnUnaccountedFor?.Invoke(this, new() - { - BotUsername = TwitchUsername, - Channel = ircMessage.Channel, - Location = "WhispergHandling", - RawIRC = rawMessage - }) ?? UnaccountedFor(rawMessage)); + await OnWhisperReceived.TryInvoke(this, new(whisperMessage, commandInfo)); } /// From 4e2c54929f2f3e4d31c0ba10f04c0716b27d0631 Mon Sep 17 00:00:00 2001 From: AoshiW Date: Sat, 5 Aug 2023 18:24:35 +0200 Subject: [PATCH 7/8] old/new command handlers --- TwitchLib.Client.Models/CommandInfo.cs | 13 ++++++-- .../Events/OnChatCommandReceivedArgs.cs | 26 ++++++++++++++++ .../Events/OnMessageReceivedArgs.cs | 10 +++---- .../Events/OnWhisperCommandReceivedArgs.cs | 26 ++++++++++++++++ .../Events/OnWhisperReceivedArgs.cs | 10 +++---- TwitchLib.Client/Interfaces/ITwitchClient.cs | 10 +++++++ TwitchLib.Client/TwitchClient.cs | 30 +++++++++++++------ 7 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs create mode 100644 TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs diff --git a/TwitchLib.Client.Models/CommandInfo.cs b/TwitchLib.Client.Models/CommandInfo.cs index f757aaaa..3fbb4e42 100644 --- a/TwitchLib.Client.Models/CommandInfo.cs +++ b/TwitchLib.Client.Models/CommandInfo.cs @@ -15,7 +15,16 @@ public class CommandInfo /// Property representing all arguments received in a List form. public List ArgumentsAsList { get; } - public CommandInfo(char identifier, string name, string argumentsAsString = null, List argumentsAsList = null) + /// + /// Initializes a new instance of the class. + /// + public CommandInfo(char identifier, string name) : this(identifier, name, string.Empty, new()) + { } + + /// + /// Initializes a new instance of the class. + /// + public CommandInfo(char identifier, string name, string argumentsAsString, List argumentsAsList) { Identifier = identifier; Name = name; @@ -37,7 +46,7 @@ public static bool TryParse(ReadOnlySpan s, out CommandInfo result) if (indexOfSpace == -1) { var name = s.ToString(); - result = new(commandIdentifier, name, string.Empty, new()); + result = new(commandIdentifier, name); } else { diff --git a/TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs b/TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs new file mode 100644 index 00000000..3793ce0a --- /dev/null +++ b/TwitchLib.Client/Events/OnChatCommandReceivedArgs.cs @@ -0,0 +1,26 @@ +using TwitchLib.Client.Models; + +namespace TwitchLib.Client.Events +{ + /// + /// Args representing chat command received event. + /// Implements the + /// + /// + /// + public class OnChatCommandReceivedArgs : OnMessageReceivedArgs + { + /// + /// Property representing received command. + /// + public CommandInfo Command { get; } + + /// + /// Initializes a new instance of the class. + /// + public OnChatCommandReceivedArgs(ChatMessage message, CommandInfo commandInfo) : base(message) + { + Command = commandInfo; + } + } +} \ No newline at end of file diff --git a/TwitchLib.Client/Events/OnMessageReceivedArgs.cs b/TwitchLib.Client/Events/OnMessageReceivedArgs.cs index 255ab908..244f3f58 100644 --- a/TwitchLib.Client/Events/OnMessageReceivedArgs.cs +++ b/TwitchLib.Client/Events/OnMessageReceivedArgs.cs @@ -15,14 +15,12 @@ public class OnMessageReceivedArgs : EventArgs /// public ChatMessage ChatMessage { get; } - public bool IsCommand => CommandInfo is not null; - - public CommandInfo CommandInfo { get; } - - public OnMessageReceivedArgs(ChatMessage message, CommandInfo commandInfo = null) + /// + /// Initializes a new instance of the class. + /// + public OnMessageReceivedArgs(ChatMessage message) { ChatMessage = message; - CommandInfo = commandInfo; } } } diff --git a/TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs b/TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs new file mode 100644 index 00000000..657227f2 --- /dev/null +++ b/TwitchLib.Client/Events/OnWhisperCommandReceivedArgs.cs @@ -0,0 +1,26 @@ +using TwitchLib.Client.Models; + +namespace TwitchLib.Client.Events +{ + /// + /// Args representing whisper command received event. + /// Implements the + /// + /// + /// + public class OnWhisperCommandReceivedArgs : OnWhisperReceivedArgs + { + /// + /// Property representing received command. + /// + public CommandInfo Command { get; } + + /// + /// Initializes a new instance of the class. + /// + public OnWhisperCommandReceivedArgs(WhisperMessage message, CommandInfo commandInfo) : base(message) + { + Command = commandInfo; + } + } +} diff --git a/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs b/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs index 29238ac6..3a374c02 100644 --- a/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs +++ b/TwitchLib.Client/Events/OnWhisperReceivedArgs.cs @@ -15,14 +15,12 @@ public class OnWhisperReceivedArgs : EventArgs /// public WhisperMessage WhisperMessage { get; } - public bool IsCommand => CommandInfo is not null; - - public CommandInfo CommandInfo { get; } - - public OnWhisperReceivedArgs(WhisperMessage message, CommandInfo commandInfo = null) + /// + /// Initializes a new instance of the class. + /// + public OnWhisperReceivedArgs(WhisperMessage message) { WhisperMessage = message; - CommandInfo = commandInfo; } } } diff --git a/TwitchLib.Client/Interfaces/ITwitchClient.cs b/TwitchLib.Client/Interfaces/ITwitchClient.cs index 86934937..e1a350a7 100644 --- a/TwitchLib.Client/Interfaces/ITwitchClient.cs +++ b/TwitchLib.Client/Interfaces/ITwitchClient.cs @@ -113,6 +113,16 @@ public interface ITwitchClient /// event AsyncEventHandler OnMessageSent; + /// + /// Fires when command (uses custom chat command identifier) is received, returns channel, command, ChatMessage, arguments as string, arguments as list. + /// + event AsyncEventHandler OnChatCommandReceived; + + /// + /// Fires when command (uses custom whisper command identifier) is received, returns command, Whispermessage. + /// + event AsyncEventHandler OnWhisperCommandReceived; + /// /// Fires when a new viewer/chatter joined the channel's chat room, returns username and channel. /// diff --git a/TwitchLib.Client/TwitchClient.cs b/TwitchLib.Client/TwitchClient.cs index 175c8a39..117961fb 100644 --- a/TwitchLib.Client/TwitchClient.cs +++ b/TwitchLib.Client/TwitchClient.cs @@ -166,6 +166,12 @@ public class TwitchClient : ITwitchClient /// public event AsyncEventHandler OnMessageSent; + /// + public event AsyncEventHandler OnChatCommandReceived; + + /// + public event AsyncEventHandler OnWhisperCommandReceived; + /// public event AsyncEventHandler OnUserJoined; @@ -887,7 +893,6 @@ private async Task HandlePrivMsg(IrcMessage ircMessage) WillReplaceEmotes, ReplacedEmotesPrefix, ReplacedEmotesSuffix); - CommandInfo commandInfo = null; foreach (JoinedChannel joinedChannel in JoinedChannels .Where(x => x.Channel.Equals(ircMessage.Channel, StringComparison.InvariantCultureIgnoreCase))) @@ -895,6 +900,7 @@ private async Task HandlePrivMsg(IrcMessage ircMessage) joinedChannel.HandleMessage(chatMessage); } + await OnMessageReceived.TryInvoke(this, new(chatMessage)); if (ircMessage.Tags.TryGetValue(Tags.MsgId, out var msgId) && msgId == MsgIds.UserIntro @@ -903,12 +909,15 @@ private async Task HandlePrivMsg(IrcMessage ircMessage) await OnUserIntro.Invoke(this, new() { ChatMessage = chatMessage }); } - if (ChatCommandIdentifiers.Contains(chatMessage.Message[0])) + if (OnChatCommandReceived is not null + && !string.IsNullOrEmpty(chatMessage.Message) + && ChatCommandIdentifiers.Contains(chatMessage.Message[0]) + && CommandInfo.TryParse(chatMessage.Message.AsSpan(), out var commandInfo) + ) { - _ = CommandInfo.TryParse(chatMessage.Message.AsSpan(), out commandInfo); + await OnChatCommandReceived.Invoke(this, new(chatMessage, commandInfo)); } - await OnMessageReceived.TryInvoke(this, new(chatMessage, commandInfo)); } /// @@ -1128,14 +1137,17 @@ private async Task HandleWhisper(IrcMessage ircMessage) { var whisperMessage = new WhisperMessage(ircMessage, TwitchUsername); PreviousWhisper = whisperMessage; - CommandInfo commandInfo = null; - if (WhisperCommandIdentifiers.Contains(whisperMessage.Message[0])) + await OnWhisperReceived.TryInvoke(this, new(whisperMessage)); + + if (OnWhisperCommandReceived is not null + && !string.IsNullOrEmpty(whisperMessage.Message) + && WhisperCommandIdentifiers.Contains(whisperMessage.Message[0]) + && CommandInfo.TryParse(whisperMessage.Message.AsSpan(), out var commandInfo) + ) { - _ = CommandInfo.TryParse(whisperMessage.Message.AsSpan(), out commandInfo); + await OnWhisperCommandReceived.Invoke(this, new(whisperMessage, commandInfo)); } - - await OnWhisperReceived.TryInvoke(this, new(whisperMessage, commandInfo)); } /// From f42412993749f0521b5cf0d5c8ed7e3171dce743 Mon Sep 17 00:00:00 2001 From: AoshiW Date: Sat, 5 Aug 2023 18:32:02 +0200 Subject: [PATCH 8/8] merge dev and fix error --- TwitchLib.Client.Test/Parsing.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TwitchLib.Client.Test/Parsing.cs b/TwitchLib.Client.Test/Parsing.cs index d1bff5be..af1a8e0c 100644 --- a/TwitchLib.Client.Test/Parsing.cs +++ b/TwitchLib.Client.Test/Parsing.cs @@ -38,6 +38,6 @@ public void Badges() [InlineData("@badge-info=;badges=;color=;display-name=SevenTest1;emotes=30259:0-6;id=37feed0f-b9c7-4c3a-b475-21c6c6d21c3d;login=seventest1;mod=0;msg-id=ritual;msg-param-ritual-name=new_chatter;room-id=87654321;subscriber=0;system-msg=Seventoes\\sis\\snew\\shere!;tmi-sent-ts=1508363903826;turbo=0;user-id=77776666;user-type= :tmi.twitch.tv USERNOTICE #seventoes :HeyGuys")] public void Events(string raw) { - _twitchClient.OnReadLineTest(raw); + _twitchClient.OnReadLineTestAsync(raw).Wait(); } }