diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml
index 257b3ad..c759a86 100644
--- a/.github/workflows/preview-release.yml
+++ b/.github/workflows/preview-release.yml
@@ -11,7 +11,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- - uses: benjlevesque/short-sha@v2.2
+ - uses: benjlevesque/short-sha@v3.0
id: short-sha
- name: Setup .NET
uses: actions/setup-dotnet@v3
@@ -22,6 +22,6 @@ jobs:
- name: Build TwitchLib.EventSub.Websockets
run: dotnet build -c Release --no-restore
- name: Pack TwitchLib.EventSub.Websockets
- run: dotnet pack ./TwitchLib.EventSub.Websockets/TwitchLib.EventSub.Websockets.csproj -v normal -c Release -o nugets --no-build --version-suffix "preview-${{ steps.short-sha.outputs.sha }}"
+ run: dotnet pack ./TwitchLib.EventSub.Websockets/TwitchLib.EventSub.Websockets.csproj -v normal -c Release -o nugets --no-build --version-suffix "preview.${{ github.run_number }}.${{ steps.short-sha.outputs.sha }}"
- name: Push to Nuget
run: dotnet nuget push "./nugets/*.nupkg" -k ${{ secrets.API_NUGET_TOKEN }} -s https://api.nuget.org/v3/index.json
diff --git a/README.md b/README.md
index 151f784..49a336a 100644
--- a/README.md
+++ b/README.md
@@ -17,10 +17,10 @@ You can also find a console app example for .NET 8 and for .NET Framework 4.8 in
| NuGet | | [![TwitchLib.EventSub.Websockets][1]][2] |
| :--------------- | ----: | :--------------------------------------------------------------------------- |
-| Package Manager | `PM>` | `Install-Package TwitchLib.EventSub.Websockets -Version 0.5.0` |
-| .NET CLI | `>` | `dotnet add package TwitchLib.EventSub.Websockets --version 0.5.0` |
-| PackageReference | | `` |
-| Paket CLI | `>` | `paket add TwitchLib.EventSub.Websockets --version 0.5.0` |
+| Package Manager | `PM>` | `Install-Package TwitchLib.EventSub.Websockets -Version 0.6.0` |
+| .NET CLI | `>` | `dotnet add package TwitchLib.EventSub.Websockets --version 0.6.0` |
+| PackageReference | | `` |
+| Paket CLI | `>` | `paket add TwitchLib.EventSub.Websockets --version 0.6.0` |
[1]: https://img.shields.io/nuget/v/TwitchLib.EventSub.Websockets.svg?label=TwitchLib.EventSub.Websockets
[2]: https://www.nuget.org/packages/TwitchLib.EventSub.Websockets
diff --git a/TwitchLib.EventSub.Websockets.Example.NetStandard/TwitchLib.EventSub.Websockets.Example.NetStandard.csproj b/TwitchLib.EventSub.Websockets.Example.NetStandard/TwitchLib.EventSub.Websockets.Example.NetStandard.csproj
index c7f6f82..09e0246 100644
--- a/TwitchLib.EventSub.Websockets.Example.NetStandard/TwitchLib.EventSub.Websockets.Example.NetStandard.csproj
+++ b/TwitchLib.EventSub.Websockets.Example.NetStandard/TwitchLib.EventSub.Websockets.Example.NetStandard.csproj
@@ -5,10 +5,12 @@
netframework4.8
disable
disable
+ latest
+
diff --git a/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedService.cs b/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedService.cs
index e590f75..958eca5 100644
--- a/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedService.cs
+++ b/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedService.cs
@@ -5,7 +5,6 @@
using System.Threading;
using System.Threading.Tasks;
using TwitchLib.Api;
-using TwitchLib.Api.Core.Enums;
using TwitchLib.EventSub.Websockets.Core.EventArgs;
using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
@@ -16,7 +15,7 @@ public class WebsocketHostedService : IHostedService
private readonly IConfiguration _configuration;
private readonly ILogger _logger;
private readonly EventSubWebsocketClient _eventSubWebsocketClient;
- private readonly TwitchApi _twitchApi = new();
+ private readonly TwitchAPI _twitchApi = new();
private string _userId;
public WebsocketHostedService(IConfiguration configuration ,ILogger logger, EventSubWebsocketClient eventSubWebsocketClient)
diff --git a/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedServiceWithoutDI.cs b/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedServiceWithoutDI.cs
index bcd5565..1b4b68d 100644
--- a/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedServiceWithoutDI.cs
+++ b/TwitchLib.EventSub.Websockets.Example.NetStandard/WebsocketHostedServiceWithoutDI.cs
@@ -3,6 +3,7 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
+using TwitchLib.Api;
using TwitchLib.EventSub.Websockets.Core.EventArgs;
using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
@@ -12,7 +13,7 @@ public class WebsocketHostedServiceWithoutDI : IHostedService
{
private readonly ILogger _logger;
private readonly EventSubWebsocketClient _eventSubWebsocketClient;
- private readonly TwitchApi _twitchApi = new();
+ private readonly TwitchAPI _twitchApi = new();
private string _userId;
public WebsocketHostedServiceWithoutDI(ILogger logger, ILoggerFactory loggerFactory)
diff --git a/TwitchLib.EventSub.Websockets.Example/TwitchLib.EventSub.Websockets.Example.csproj b/TwitchLib.EventSub.Websockets.Example/TwitchLib.EventSub.Websockets.Example.csproj
index ca8f5e6..28ce0c7 100644
--- a/TwitchLib.EventSub.Websockets.Example/TwitchLib.EventSub.Websockets.Example.csproj
+++ b/TwitchLib.EventSub.Websockets.Example/TwitchLib.EventSub.Websockets.Example.csproj
@@ -8,6 +8,7 @@
+
diff --git a/TwitchLib.EventSub.Websockets.Example/WebsocketHostedService.cs b/TwitchLib.EventSub.Websockets.Example/WebsocketHostedService.cs
index af8678a..7b3e3a4 100644
--- a/TwitchLib.EventSub.Websockets.Example/WebsocketHostedService.cs
+++ b/TwitchLib.EventSub.Websockets.Example/WebsocketHostedService.cs
@@ -15,7 +15,7 @@ public class WebsocketHostedService : IHostedService
{
private readonly ILogger _logger;
private readonly EventSubWebsocketClient _eventSubWebsocketClient;
- private readonly TwitchApi _twitchApi = new();
+ private readonly TwitchAPI _twitchApi = new();
private string _userId;
public WebsocketHostedService(ILogger logger, EventSubWebsocketClient eventSubWebsocketClient)
diff --git a/TwitchLib.EventSub.Websockets/Client/WebsocketClient.cs b/TwitchLib.EventSub.Websockets/Client/WebsocketClient.cs
index 4b285b9..11bc032 100644
--- a/TwitchLib.EventSub.Websockets/Client/WebsocketClient.cs
+++ b/TwitchLib.EventSub.Websockets/Client/WebsocketClient.cs
@@ -29,17 +29,17 @@ public class WebsocketClient : IDisposable
///
public bool IsFaulted => _webSocket.CloseStatus != WebSocketCloseStatus.Empty && _webSocket.CloseStatus != WebSocketCloseStatus.NormalClosure;
- internal event AsyncEventHandler OnDataReceived;
- internal event AsyncEventHandler OnErrorOccurred;
+ internal event AsyncEventHandler? OnDataReceived;
+ internal event AsyncEventHandler? OnErrorOccurred;
- private readonly ClientWebSocket _webSocket;
- private readonly ILogger _logger;
+ private ClientWebSocket _webSocket;
+ private readonly ILogger? _logger;
///
/// Constructor to create a new Websocket client with a logger
///
/// Logger used by the websocket client to print various state info
- public WebsocketClient(ILogger logger = null)
+ public WebsocketClient(ILogger? logger = null)
{
_webSocket = new ClientWebSocket();
_logger = logger;
@@ -56,6 +56,8 @@ public async Task ConnectAsync(Uri url)
{
if (_webSocket.State is WebSocketState.Open or WebSocketState.Connecting)
return true;
+ if (_webSocket.State is WebSocketState.Closed) //after a socken is closed it cannot be reopened
+ _webSocket = new();
await _webSocket.ConnectAsync(url, CancellationToken.None);
@@ -92,7 +94,6 @@ public async Task DisconnectAsync()
}
}
-#if NET6_0_OR_GREATER
///
/// Background operation to process incoming data via the websocket
///
@@ -100,38 +101,43 @@ public async Task DisconnectAsync()
///
private async Task ProcessDataAsync()
{
- const int minimumBufferSize = 256;
- var storeSize = 4096;
- var decoder = Encoding.UTF8.GetDecoder();
-
- var store = MemoryPool.Shared.Rent(storeSize).Memory;
- var buffer = MemoryPool.Shared.Rent(minimumBufferSize).Memory;
-
+ const int bufferLength = 4096;
+#if NETSTANDARD2_0
+ var buffer = new ArraySegment(new byte[bufferLength]);
+#else
+ var buffer = new Memory(new byte[bufferLength]);
+#endif
+ var store = new byte[4096];
var payloadSize = 0;
while (IsConnected)
{
try
{
+#if NETSTANDARD2_0
+ WebSocketReceiveResult receiveResult;
+#else
ValueWebSocketReceiveResult receiveResult;
+#endif
do
{
receiveResult = await _webSocket.ReceiveAsync(buffer, CancellationToken.None);
-
- if (payloadSize + receiveResult.Count >= storeSize)
+
+ if (payloadSize + receiveResult.Count >= store.Length)
{
- storeSize +=
-#if NET8_0_OR_GREATER
- int.Max(4096, receiveResult.Count);
-#else
- Math.Max(4096, receiveResult.Count);
-#endif
- var newStore = MemoryPool.Shared.Rent(storeSize).Memory;
- store.CopyTo(newStore);
+ var newStoreLength = store.Length + Math.Max(bufferLength, receiveResult.Count);
+ var newStore = new byte[newStoreLength];
+ store.AsSpan().CopyTo(newStore);
store = newStore;
}
- buffer.CopyTo(store[payloadSize..]);
+ buffer
+#if NETSTANDARD2_0
+ .Array.AsSpan(0, receiveResult.Count)
+#else
+ .Span.Slice(0, receiveResult.Count)
+#endif
+ .CopyTo(store.AsSpan(payloadSize));
payloadSize += receiveResult.Count;
} while (!receiveResult.EndOfMessage);
@@ -139,19 +145,12 @@ private async Task ProcessDataAsync()
switch (receiveResult.MessageType)
{
case WebSocketMessageType.Text:
- {
- var intermediate = MemoryPool.Shared.Rent(payloadSize).Memory;
-
if (payloadSize == 0)
continue;
- decoder.Convert(store.Span[..payloadSize], intermediate.Span, true, out _, out var charsCount, out _);
- var message = intermediate[..charsCount];
-
- OnDataReceived?.Invoke(this, new DataReceivedArgs { Message = message.Span.ToString() });
+ OnDataReceived?.Invoke(this, new DataReceivedArgs { Bytes = store.AsSpan(0, payloadSize).ToArray() });
payloadSize = 0;
break;
- }
case WebSocketMessageType.Binary:
break;
case WebSocketMessageType.Close:
@@ -168,75 +167,6 @@ private async Task ProcessDataAsync()
}
}
}
-#else
- ///
- /// Background operation to process incoming data via the websocket
- ///
- /// Task representing the background operation
- ///
- private async Task ProcessDataAsync()
- {
- const int minimumBufferSize = 8192;
-
- var buffer = new ArraySegment(new byte[minimumBufferSize]);
- var payloadSize = 0;
-
- while (IsConnected)
- {
- try
- {
- WebSocketReceiveResult receiveResult;
- var memory = new MemoryStream();
-
- do
- {
- receiveResult = await _webSocket.ReceiveAsync(buffer, CancellationToken.None);
-
- if (buffer.Array == null)
- continue;
-
-#pragma warning disable CA1849
- memory.Write(buffer.Array, buffer.Offset, receiveResult.Count);
-#pragma warning restore CA1849
- payloadSize += receiveResult.Count;
- } while (!receiveResult.EndOfMessage);
-
- switch (receiveResult.MessageType)
- {
- case WebSocketMessageType.Text:
- {
- if (payloadSize == 0)
- continue;
-
- memory.Seek(0, SeekOrigin.Begin);
-
- var reader = new StreamReader(memory, Encoding.UTF8);
-
- OnDataReceived?.Invoke(this, new DataReceivedArgs { Message = await reader.ReadToEndAsync() });
-
- memory.Dispose();
- reader.Dispose();
- break;
- }
- case WebSocketMessageType.Binary:
- break;
- case WebSocketMessageType.Close:
- if (_webSocket.CloseStatus != null)
- _logger?.LogWebsocketClosed((WebSocketCloseStatus)_webSocket.CloseStatus!, _webSocket.CloseStatusDescription!);
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
-
- catch (Exception ex)
- {
- OnErrorOccurred?.Invoke(this, new ErrorOccuredArgs { Exception = ex });
- break;
- }
- }
- }
-#endif
///
/// Cleanup of any unused resources as per IDisposable guidelines
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatClearArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatClearArgs.cs
new file mode 100644
index 0000000..a1b36ba
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatClearArgs.cs
@@ -0,0 +1,7 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+
+public class ChannelChatClearArgs : TwitchLibEventSubEventArgs>
+{ }
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatClearUserMessagesArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatClearUserMessagesArgs.cs
new file mode 100644
index 0000000..e4ff9ef
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatClearUserMessagesArgs.cs
@@ -0,0 +1,7 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+
+public class ChannelChatClearUserMessagesArgs : TwitchLibEventSubEventArgs>
+{ }
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatMessageDeleteArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatMessageDeleteArgs.cs
new file mode 100644
index 0000000..bf7c5c5
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatMessageDeleteArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelChatMessageDeleteArgs : TwitchLibEventSubEventArgs>
+ {
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatNotificationArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatNotificationArgs.cs
new file mode 100644
index 0000000..43bb582
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelChatNotificationArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelChatNotificationArgs : TwitchLibEventSubEventArgs>
+ {
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelPointsAutomaticRewardRedemptionArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelPointsAutomaticRewardRedemptionArgs.cs
new file mode 100644
index 0000000..d57b9f7
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelPointsAutomaticRewardRedemptionArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+
+public class ChannelPointsAutomaticRewardRedemptionArgs : TwitchLibEventSubEventArgs>
+{
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionBeginArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionBeginArgs.cs
new file mode 100644
index 0000000..76a0403
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionBeginArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelSharedChatSessionBeginArgs : TwitchLibEventSubEventArgs>
+ { }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionEndArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionEndArgs.cs
new file mode 100644
index 0000000..82c81fb
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionEndArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelSharedChatSessionEndArgs : TwitchLibEventSubEventArgs>
+ { }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionUpdateArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionUpdateArgs.cs
new file mode 100644
index 0000000..d996faa
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSharedChatSessionUpdateArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelSharedChatSessionUpdateArgs : TwitchLibEventSubEventArgs>
+ { }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSuspiciousUserMessageArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSuspiciousUserMessageArgs.cs
new file mode 100644
index 0000000..e0db5b7
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSuspiciousUserMessageArgs.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelSuspiciousUserMessageArgs : TwitchLibEventSubEventArgs>
+ {
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSuspiciousUserUpdateArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSuspiciousUserUpdateArgs.cs
new file mode 100644
index 0000000..5b8d851
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelSuspiciousUserUpdateArgs.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public sealed class ChannelSuspiciousUserUpdateArgs : TwitchLibEventSubEventArgs>
+ {
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelUnbanRequestCreateArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelUnbanRequestCreateArgs.cs
new file mode 100644
index 0000000..50226f1
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelUnbanRequestCreateArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelUnbanRequestCreateArgs : TwitchLibEventSubEventArgs>
+ { }
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelUnbanRequestResolveArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelUnbanRequestResolveArgs.cs
new file mode 100644
index 0000000..a86c678
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelUnbanRequestResolveArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelUnbanRequestResolveArgs : TwitchLibEventSubEventArgs>
+ { }
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelVipArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelVipArgs.cs
new file mode 100644
index 0000000..4e7d517
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelVipArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelVipArgs : TwitchLibEventSubEventArgs>
+ { }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelWarningAcknowledgeArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelWarningAcknowledgeArgs.cs
new file mode 100644
index 0000000..acfad2e
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelWarningAcknowledgeArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelWarningAcknowledgeArgs : TwitchLibEventSubEventArgs>
+ { }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelWarningSendArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelWarningSendArgs.cs
new file mode 100644
index 0000000..e05d67a
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/Channel/ChannelWarningSendArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
+{
+ public class ChannelWarningSendArgs : TwitchLibEventSubEventArgs>
+ { }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/DataReceivedArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/DataReceivedArgs.cs
index 292d6cf..4c2fdbf 100644
--- a/TwitchLib.EventSub.Websockets/Core/EventArgs/DataReceivedArgs.cs
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/DataReceivedArgs.cs
@@ -1,7 +1,6 @@
-namespace TwitchLib.EventSub.Websockets.Core.EventArgs
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs;
+
+internal class DataReceivedArgs : System.EventArgs
{
- internal class DataReceivedArgs : System.EventArgs
- {
- public string Message { get; internal set; }
- }
-}
\ No newline at end of file
+ public byte[] Bytes { get; internal set; }
+}
diff --git a/TwitchLib.EventSub.Websockets/Core/EventArgs/User/UserWhisperMessageArgs.cs b/TwitchLib.EventSub.Websockets/Core/EventArgs/User/UserWhisperMessageArgs.cs
new file mode 100644
index 0000000..297cdd5
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Core/EventArgs/User/UserWhisperMessageArgs.cs
@@ -0,0 +1,8 @@
+using TwitchLib.EventSub.Core.SubscriptionTypes.User;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Core.EventArgs.User
+{
+ public class UserWhisperMessageArgs : TwitchLibEventSubEventArgs>
+ { }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/Models/EventSubMetadata.cs b/TwitchLib.EventSub.Websockets/Core/Models/EventSubMetadata.cs
index 8cb527e..1c0c63b 100644
--- a/TwitchLib.EventSub.Websockets/Core/Models/EventSubMetadata.cs
+++ b/TwitchLib.EventSub.Websockets/Core/Models/EventSubMetadata.cs
@@ -1,13 +1,31 @@
using System;
-namespace TwitchLib.EventSub.Websockets.Core.Models
+namespace TwitchLib.EventSub.Websockets.Core.Models;
+
+public class EventSubMetadata
{
- public class EventSubMetadata
- {
- public string MessageId { get; set; }
- public string MessageType { get; set; }
- public DateTime MessageTimestamp { get; set; }
- public string SubscriptionType { get; set; }
- public string SubscriptionVersion { get; set; }
- }
+ ///
+ /// An ID that uniquely identifies message.
+ ///
+ public string MessageId { get; set; }
+
+ ///
+ /// The type of notification.
+ ///
+ public string MessageType { get; set; }
+
+ ///
+ /// The UTC date and time that Twitch sent the notification.
+ ///
+ public DateTime MessageTimestamp { get; set; }
+
+ ///
+ /// The subscription type.
+ ///
+ public string? SubscriptionType { get; set; }
+
+ ///
+ /// The subscription version.
+ ///
+ public string? SubscriptionVersion { get; set; }
}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/Models/EventSubNotificationPayload.cs b/TwitchLib.EventSub.Websockets/Core/Models/EventSubNotificationPayload.cs
index 2b1997a..fad563e 100644
--- a/TwitchLib.EventSub.Websockets/Core/Models/EventSubNotificationPayload.cs
+++ b/TwitchLib.EventSub.Websockets/Core/Models/EventSubNotificationPayload.cs
@@ -3,6 +3,10 @@
public class EventSubNotificationPayload
{
public EventSubTransport Transport { get; set; }
+
+ ///
+ /// The event’s data.
+ ///
public T Event { get; set; }
}
}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Core/Models/EventSubWebsocketSessionInfo.cs b/TwitchLib.EventSub.Websockets/Core/Models/EventSubWebsocketSessionInfo.cs
index 6994b91..903e831 100644
--- a/TwitchLib.EventSub.Websockets/Core/Models/EventSubWebsocketSessionInfo.cs
+++ b/TwitchLib.EventSub.Websockets/Core/Models/EventSubWebsocketSessionInfo.cs
@@ -1,16 +1,34 @@
using System;
-namespace TwitchLib.EventSub.Websockets.Core.Models
+namespace TwitchLib.EventSub.Websockets.Core.Models;
+
+public class EventSubWebsocketSessionInfo
{
- public class EventSubWebsocketSessionInfo
- {
- public string Id { get; set; }
- public string Status { get; set; }
- public string DisconnectReason { get; set; }
- public int? KeepaliveTimeoutSeconds { get; set; }
- public string ReconnectUrl { get; set; }
- public DateTime ConnectedAt { get; set; }
- public DateTime? DisconnectedAt { get; set; }
- public DateTime? ReconnectingAt { get; set; }
- }
+ ///
+ /// An ID that uniquely identifies this WebSocket connection.
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// The connection’s status.
+ ///
+ public string Status { get; set; }
+ public string DisconnectReason { get; set; }
+
+ ///
+ /// The maximum number of seconds that you should expect silence before receiving a keepalive message.
+ ///
+ public int? KeepaliveTimeoutSeconds { get; set; }
+
+ ///
+ /// The URL to reconnect to.
+ ///
+ public string? ReconnectUrl { get; set; }
+
+ ///
+ /// The UTC date and time when the connection was created.
+ ///
+ public DateTime ConnectedAt { get; set; }
+ public DateTime? DisconnectedAt { get; set; }
+ public DateTime? ReconnectingAt { get; set; }
}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/EventSubWebsocketClient.cs b/TwitchLib.EventSub.Websockets/EventSubWebsocketClient.cs
index 75cd279..7c54122 100644
--- a/TwitchLib.EventSub.Websockets/EventSubWebsocketClient.cs
+++ b/TwitchLib.EventSub.Websockets/EventSubWebsocketClient.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
@@ -32,239 +33,320 @@ public class EventSubWebsocketClient
///
/// Event that triggers when the websocket was successfully connected
///
- public event AsyncEventHandler WebsocketConnected;
+ public event AsyncEventHandler? WebsocketConnected;
///
/// Event that triggers when the websocket disconnected
///
- public event AsyncEventHandler WebsocketDisconnected;
+ public event AsyncEventHandler? WebsocketDisconnected;
///
/// Event that triggers when an error occurred on the websocket
///
- public event AsyncEventHandler ErrorOccurred;
+ public event AsyncEventHandler? ErrorOccurred;
///
/// Event that triggers when the websocket was successfully reconnected
///
- public event AsyncEventHandler WebsocketReconnected;
+ public event AsyncEventHandler? WebsocketReconnected;
///
/// Event that triggers on "channel.ad_break.begin" notifications
///
- public event AsyncEventHandler ChannelAdBreakBegin;
+ public event AsyncEventHandler? ChannelAdBreakBegin;
///
/// Event that triggers on "channel.ban" notifications
///
- public event AsyncEventHandler ChannelBan;
+ public event AsyncEventHandler? ChannelBan;
///
/// Event that triggers on "channel.charity_campaign.start" notifications
///
- public event AsyncEventHandler ChannelCharityCampaignStart;
+ public event AsyncEventHandler? ChannelCharityCampaignStart;
///
/// Event that triggers on "channel.charity_campaign.donate" notifications
///
- public event AsyncEventHandler ChannelCharityCampaignDonate;
+ public event AsyncEventHandler? ChannelCharityCampaignDonate;
///
/// Event that triggers on "channel.charity_campaign.progress" notifications
///
- public event AsyncEventHandler ChannelCharityCampaignProgress;
+ public event AsyncEventHandler? ChannelCharityCampaignProgress;
///
/// Event that triggers on "channel.charity_campaign.stop" notifications
///
- public event AsyncEventHandler ChannelCharityCampaignStop;
+ public event AsyncEventHandler? ChannelCharityCampaignStop;
+
+ ///
+ /// Event that triggers on channel.chat.clear notifications
+ ///
+ public event AsyncEventHandler? ChannelChatClear;
+ ///
+ /// Event that triggers on channel.chat.clear_user_messages notifications
+ ///
+ public event AsyncEventHandler? ChannelChatClearUserMessages;
///
/// Event that triggers on channel.chat.message notifications
///
- public event AsyncEventHandler ChannelChatMessage;
+ public event AsyncEventHandler? ChannelChatMessage;
+ ///
+ /// Event that triggers on "channel.chat.message_delete" notifications
+ ///
+ public event AsyncEventHandler? ChannelChatMessageDelete;
+ ///
+ /// Event that triggers on "channel.chat.notification" notifications
+ ///
+ public event AsyncEventHandler? ChannelChatNotification;
///
/// Event that triggers on "channel.cheer" notifications
///
- public event AsyncEventHandler ChannelCheer;
+ public event AsyncEventHandler? ChannelCheer;
///
/// Event that triggers on "channel.follow" notifications
///
- public event AsyncEventHandler ChannelFollow;
+ public event AsyncEventHandler? ChannelFollow;
///
/// Event that triggers on "channel.goal.begin" notifications
///
- public event AsyncEventHandler ChannelGoalBegin;
+ public event AsyncEventHandler? ChannelGoalBegin;
///
/// Event that triggers on "channel.goal.end" notifications
///
- public event AsyncEventHandler ChannelGoalEnd;
+ public event AsyncEventHandler? ChannelGoalEnd;
///
/// Event that triggers on "channel.goal.progress" notifications
///
- public event AsyncEventHandler ChannelGoalProgress;
+ public event AsyncEventHandler? ChannelGoalProgress;
///
/// Event that triggers on "channel.guest_star_guest.update" notifications
///
- public event AsyncEventHandler ChannelGuestStarGuestUpdate;
+ public event AsyncEventHandler? ChannelGuestStarGuestUpdate;
///
/// Event that triggers on "channel.guest_star_session.begin" notifications
///
- public event AsyncEventHandler ChannelGuestStarSessionBegin;
+ public event AsyncEventHandler? ChannelGuestStarSessionBegin;
///
/// Event that triggers on "channel.guest_star_guest.update" notifications
///
- public event AsyncEventHandler ChannelGuestStarSessionEnd;
+ public event AsyncEventHandler? ChannelGuestStarSessionEnd;
///
/// Event that triggers on "channel.guest_star_settings.update" notifications
///
- public event AsyncEventHandler ChannelGuestStarSettingsUpdate;
+ public event AsyncEventHandler? ChannelGuestStarSettingsUpdate;
///
/// Event that triggers on "channel.guest_star_slot.update" notifications
///
- public event AsyncEventHandler ChannelGuestStarSlotUpdate;
+ public event AsyncEventHandler? ChannelGuestStarSlotUpdate;
///
/// Event that triggers on "channel.hype_train.begin" notifications
///
- public event AsyncEventHandler ChannelHypeTrainBegin;
+ public event AsyncEventHandler? ChannelHypeTrainBegin;
///
/// Event that triggers on "channel.hype_train.end" notifications
///
- public event AsyncEventHandler ChannelHypeTrainEnd;
+ public event AsyncEventHandler? ChannelHypeTrainEnd;
///
/// Event that triggers on "channel.hype_train.progress" notifications
///
- public event AsyncEventHandler ChannelHypeTrainProgress;
+ public event AsyncEventHandler? ChannelHypeTrainProgress;
///
/// Event that triggers on "channel.moderator.add" notifications
///
- public event AsyncEventHandler ChannelModeratorAdd;
+ public event AsyncEventHandler? ChannelModeratorAdd;
///
/// Event that triggers on "channel.moderator.remove" notifications
///
- public event AsyncEventHandler ChannelModeratorRemove;
+ public event AsyncEventHandler? ChannelModeratorRemove;
+
+ ///
+ /// Event that triggers on "channel.vip.add" notifications
+ ///
+ public event AsyncEventHandler? ChannelVipAdd;
+ ///
+ /// Event that triggers on "channel.vip.remove" notifications
+ ///
+ public event AsyncEventHandler? ChannelVipRemove;
///
/// Event that triggers on "channel.channel_points_custom_reward.add" notifications
///
- public event AsyncEventHandler ChannelPointsCustomRewardAdd;
+ public event AsyncEventHandler? ChannelPointsCustomRewardAdd;
///
/// Event that triggers on "channel.channel_points_custom_reward.remove" notifications
///
- public event AsyncEventHandler ChannelPointsCustomRewardRemove;
+ public event AsyncEventHandler? ChannelPointsCustomRewardRemove;
///
/// Event that triggers on "channel.channel_points_custom_reward.update" notifications
///
- public event AsyncEventHandler ChannelPointsCustomRewardUpdate;
+ public event AsyncEventHandler? ChannelPointsCustomRewardUpdate;
+
+ ///
+ /// Event that triggers on "channel.channel_points_automatic_reward_redemption.add" notifications
+ ///
+ public event AsyncEventHandler? ChannelPointsAutomaticRewardRedemptionAdd;
///
/// Event that triggers on "channel.channel_points_custom_reward_redemption.add" notifications
///
- public event AsyncEventHandler ChannelPointsCustomRewardRedemptionAdd;
+ public event AsyncEventHandler? ChannelPointsCustomRewardRedemptionAdd;
///
/// Event that triggers on "channel.channel_points_custom_reward_redemption.update" notifications
///
- public event AsyncEventHandler ChannelPointsCustomRewardRedemptionUpdate;
+ public event AsyncEventHandler? ChannelPointsCustomRewardRedemptionUpdate;
///
/// Event that triggers on "channel.poll.begin" notifications
///
- public event AsyncEventHandler ChannelPollBegin;
+ public event AsyncEventHandler? ChannelPollBegin;
///
/// Event that triggers on "channel.poll.end" notifications
///
- public event AsyncEventHandler ChannelPollEnd;
+ public event AsyncEventHandler? ChannelPollEnd;
///
/// Event that triggers on "channel.poll.progress" notifications
///
- public event AsyncEventHandler ChannelPollProgress;
+ public event AsyncEventHandler? ChannelPollProgress;
///
/// Event that triggers on "channel.prediction.begin" notifications
///
- public event AsyncEventHandler ChannelPredictionBegin;
+ public event AsyncEventHandler? ChannelPredictionBegin;
///
/// Event that triggers on "channel.prediction.end" notifications
///
- public event AsyncEventHandler ChannelPredictionEnd;
+ public event AsyncEventHandler? ChannelPredictionEnd;
///
/// Event that triggers on "channel.prediction.lock" notifications
///
- public event AsyncEventHandler ChannelPredictionLock;
+ public event AsyncEventHandler? ChannelPredictionLock;
///
/// Event that triggers on "channel.prediction.progress" notifications
///
- public event AsyncEventHandler ChannelPredictionProgress;
+ public event AsyncEventHandler? ChannelPredictionProgress;
///
/// Event that triggers on "channel.raid" notifications
///
- public event AsyncEventHandler ChannelRaid;
+ public event AsyncEventHandler? ChannelRaid;
///
/// Event that triggers on "channel.shield_mode.begin" notifications
///
- public event AsyncEventHandler ChannelShieldModeBegin;
+ public event AsyncEventHandler? ChannelShieldModeBegin;
///
/// Event that triggers on "channel.shield_mode.end" notifications
///
- public event AsyncEventHandler ChannelShieldModeEnd;
+ public event AsyncEventHandler? ChannelShieldModeEnd;
///
/// Event that triggers on "channel.shoutout.create" notifications
///
- public event AsyncEventHandler ChannelShoutoutCreate;
+ public event AsyncEventHandler? ChannelShoutoutCreate;
///
/// Event that triggers on "channel.shoutout.receive" notifications
///
- public event AsyncEventHandler ChannelShoutoutReceive;
+ public event AsyncEventHandler? ChannelShoutoutReceive;
///
/// Event that triggers on "channel.subscribe" notifications
///
- public event AsyncEventHandler ChannelSubscribe;
+ public event AsyncEventHandler? ChannelSubscribe;
///
/// Event that triggers on "channel.subscription.end" notifications
///
- public event AsyncEventHandler ChannelSubscriptionEnd;
+ public event AsyncEventHandler? ChannelSubscriptionEnd;
///
/// Event that triggers on "channel.subscription.gift" notifications
///
- public event AsyncEventHandler ChannelSubscriptionGift;
+ public event AsyncEventHandler? ChannelSubscriptionGift;
///
/// Event that triggers on "channel.subscription.message" notifications
///
- public event AsyncEventHandler ChannelSubscriptionMessage;
+ public event AsyncEventHandler? ChannelSubscriptionMessage;
+
+ ///
+ /// Event that triggers on "channel.suspicious_user.message" notifications
+ ///
+ public event AsyncEventHandler? ChannelSuspiciousUserMessage;
+
+ ///
+ /// Event that triggers on "channel.suspicious_user.update" notifications
+ ///
+ public event AsyncEventHandler? ChannelSuspiciousUserUpdate;
+
+ ///
+ /// Event that triggers on "channel.warning.acknowledge" notifications
+ ///
+ public event AsyncEventHandler? ChannelWarningAcknowledge;
+
+ ///
+ /// Event that triggers on "channel.warning.send" notifications
+ ///
+ public event AsyncEventHandler? ChannelWarningSend;
///
/// Event that triggers on "channel.unban" notifications
///
- public event AsyncEventHandler ChannelUnban;
+ public event AsyncEventHandler? ChannelUnban;
///
/// Event that triggers on "channel.update" notifications
///
- public event AsyncEventHandler ChannelUpdate;
+ public event AsyncEventHandler? ChannelUpdate;
///
/// Event that triggers on "stream.offline" notifications
///
- public event AsyncEventHandler StreamOffline;
+ public event AsyncEventHandler? StreamOffline;
///
/// Event that triggers on "stream.online" notifications
///
- public event AsyncEventHandler StreamOnline;
+ public event AsyncEventHandler? StreamOnline;
///
/// Event that triggers on "user.update" notifications
///
- public event AsyncEventHandler UserUpdate;
+ public event AsyncEventHandler? UserUpdate;
+
+ ///
+ /// Event that triggers on "user.whisper.message" notifications
+ ///
+ public event AsyncEventHandler? UserWhisperMessage;
+
+ ///
+ /// Event that triggers on "channel.shared_chat.begin" notifications
+ ///
+ public event AsyncEventHandler? ChannelSharedChatSessionBegin;
+
+ ///
+ /// Event that triggers on "channel.shared_chat.update" notifications
+ ///
+ public event AsyncEventHandler? ChannelSharedChatSessionUpdate;
+
+ ///
+ /// Event that triggers on "channel.shared_chat.end" notifications
+ ///
+ public event AsyncEventHandler? ChannelSharedChatSessionEnd;
+
+ ///
+ /// Event that triggers on "channel.unban_request.create" notifications
+ ///
+ public event AsyncEventHandler? ChannelUnbanRequestCreate;
+
+ ///
+ /// Event that triggers on "channel.unban_request.resolve" notifications
+ ///
+ public event AsyncEventHandler? ChannelUnbanRequestResolve;
#endregion
///
/// Id associated with the Websocket Session. Needed for creating subscriptions for the socket.
///
- public string SessionId { get; private set; }
+ public string SessionId { get; private set; } = string.Empty;
- private CancellationTokenSource _cts;
+ private CancellationTokenSource? _cts;
private DateTimeOffset _lastReceived = DateTimeOffset.MinValue;
private TimeSpan _keepAliveTimeout = TimeSpan.Zero;
@@ -273,11 +355,11 @@ public class EventSubWebsocketClient
private bool _reconnectComplete;
private WebsocketClient _websocketClient;
- private Dictionary> _handlers;
+ private readonly Dictionary> _handlers = new();
private readonly ILogger _logger;
- private readonly ILoggerFactory _loggerFactory;
- private readonly IServiceProvider _serviceProvider;
+ private readonly ILoggerFactory? _loggerFactory;
+ private readonly IServiceProvider? _serviceProvider;
private readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions
{
@@ -315,7 +397,7 @@ public EventSubWebsocketClient(ILogger logger, IEnumera
/// Instantiates an EventSubWebsocketClient used to subscribe to EventSub notifications via Websockets.
///
/// LoggerFactory used to construct Loggers for the EventSubWebsocketClient and underlying classes
- public EventSubWebsocketClient(ILoggerFactory loggerFactory = null)
+ public EventSubWebsocketClient(ILoggerFactory? loggerFactory = null)
{
_loggerFactory = loggerFactory;
@@ -347,7 +429,7 @@ public EventSubWebsocketClient(ILoggerFactory loggerFactory = null)
///
/// Optional url param to be able to connect to reconnect urls provided by Twitch or test servers
/// true: Connection successful false: Connection failed
- public async Task ConnectAsync(Uri url = null)
+ public async Task ConnectAsync(Uri? url = null)
{
url = url ?? new Uri(WEBSOCKET_URL);
_lastReceived = DateTimeOffset.MinValue;
@@ -464,8 +546,6 @@ private async Task ReconnectAsync(Uri url)
/// Enumerable of handlers that are responsible for acting on a specified subscription type
private void PrepareHandlers(IEnumerable handlers)
{
- _handlers = _handlers ?? new Dictionary>();
-
foreach (var handler in handlers)
{
#if NET6_0_OR_GREATER
@@ -506,24 +586,25 @@ private async Task ConnectionCheckAsync()
/// EventArgs send with the event.
private async Task OnDataReceived(object sender, DataReceivedArgs e)
{
+ _logger?.LogMessage(e.Bytes);
_lastReceived = DateTimeOffset.Now;
- var json = JsonDocument.Parse(e.Message);
+ var json = JsonDocument.Parse(e.Bytes);
var metadata = json.RootElement.GetProperty("metadata"u8);
var messageType = metadata.GetProperty("message_type"u8).GetString();
switch (messageType)
{
case "session_welcome":
- await HandleWelcome(e.Message);
+ await HandleWelcome(e.Bytes);
break;
case "session_disconnect":
- await HandleDisconnect(e.Message);
+ await HandleDisconnect(e.Bytes);
break;
case "session_reconnect":
- HandleReconnect(e.Message);
+ HandleReconnect(e.Bytes);
break;
case "session_keepalive":
- HandleKeepAlive(e.Message);
+ HandleKeepAlive(e.Bytes);
break;
case "notification":
var subscriptionType = metadata.GetProperty("subscription_type"u8).GetString();
@@ -532,14 +613,15 @@ private async Task OnDataReceived(object sender, DataReceivedArgs e)
await ErrorOccurred.InvokeAsync(this, new ErrorOccuredArgs { Exception = new ArgumentNullException(nameof(subscriptionType)), Message = "Unable to determine subscription type!" });
break;
}
- HandleNotification(e.Message, subscriptionType);
+ var message1 = Encoding.UTF8.GetString(e.Bytes);
+ HandleNotification(message1, subscriptionType!);
break;
case "revocation":
- HandleRevocation(e.Message);
+ var message2 = Encoding.UTF8.GetString(e.Bytes);
+ HandleRevocation(message2);
break;
default:
_logger?.LogUnknownMessageType(messageType);
- _logger?.LogMessage(e.Message);
break;
}
}
@@ -558,22 +640,20 @@ private async Task OnErrorOccurred(object sender, ErrorOccuredArgs e)
/// Handles 'session_reconnect' notifications
///
/// notification message received from Twitch EventSub
- private void HandleReconnect(string message)
+ private void HandleReconnect(byte[] message)
{
_logger?.LogReconnectRequested(SessionId);
var data = JsonSerializer.Deserialize(message, _jsonSerializerOptions);
_reconnectRequested = true;
Task.Run(async () => await ReconnectAsync(new Uri(data?.Payload.Session.ReconnectUrl ?? WEBSOCKET_URL)));
-
- _logger?.LogMessage(message);
}
///
/// Handles 'session_welcome' notifications
///
/// notification message received from Twitch EventSub
- private async ValueTask HandleWelcome(string message)
+ private async ValueTask HandleWelcome(byte[] message)
{
var data = JsonSerializer.Deserialize(message, _jsonSerializerOptions);
@@ -589,21 +669,19 @@ private async ValueTask HandleWelcome(string message)
_keepAliveTimeout = TimeSpan.FromSeconds(keepAliveTimeout ?? 10);
await WebsocketConnected.InvokeAsync(this, new WebsocketConnectedArgs { IsRequestedReconnect = _reconnectRequested });
-
- _logger?.LogMessage(message);
}
///
/// Handles 'session_disconnect' notifications
///
/// notification message received from Twitch EventSub
- private async Task HandleDisconnect(string message)
+ private async Task HandleDisconnect(byte[] message)
{
var data = JsonSerializer.Deserialize(message);
if (data != null)
_logger?.LogForceDisconnected(data.Payload.Session.Id, data.Payload.Session.DisconnectedAt, data.Payload.Session.DisconnectReason);
-
+
await WebsocketDisconnected.InvokeAsync(this, EventArgs.Empty);
}
@@ -611,9 +689,9 @@ private async Task HandleDisconnect(string message)
/// Handles 'session_keepalive' notifications
///
/// notification message received from Twitch EventSub
- private void HandleKeepAlive(string message)
+ private void HandleKeepAlive(byte[] message)
{
- _logger?.LogMessage(message);
+ _ = message;
}
///
@@ -623,10 +701,8 @@ private void HandleKeepAlive(string message)
/// subscription type received from Twitch EventSub
private void HandleNotification(string message, string subscriptionType)
{
- if (_handlers != null && _handlers.TryGetValue(subscriptionType, out var handler))
+ if (_handlers.TryGetValue(subscriptionType, out var handler))
handler(this, message, _jsonSerializerOptions);
-
- _logger?.LogMessage(message);
}
///
@@ -635,10 +711,8 @@ private void HandleNotification(string message, string subscriptionType)
/// notification message received from Twitch EventSub
private void HandleRevocation(string message)
{
- if (_handlers != null && _handlers.TryGetValue("revocation", out var handler))
+ if (_handlers.TryGetValue("revocation", out var handler))
handler(this, message, _jsonSerializerOptions);
-
- _logger?.LogMessage(message);
}
///
@@ -646,16 +720,26 @@ private void HandleRevocation(string message)
///
/// name of the event to raise
/// args to pass with the event
- internal void RaiseEvent(string eventName, object args = null)
+ internal async void RaiseEvent(string eventName, object? args = null)
{
var fInfo = GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
if (fInfo?.GetValue(this) is not MulticastDelegate multi)
return;
+ var parameters = new object[] { this, args ?? EventArgs.Empty };
foreach (var del in multi.GetInvocationList())
{
- del.Method.Invoke(del.Target, args == null ? new object[] { this, EventArgs.Empty } : new[] { this, args });
+ try
+ {
+ var result = del.Method.Invoke(del.Target, parameters);
+ if (result is Task task)
+ await task;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogRaiseEventExeption(eventName, ex);
+ }
}
}
}
diff --git a/TwitchLib.EventSub.Websockets/Extensions/LogExtensions.cs b/TwitchLib.EventSub.Websockets/Extensions/LogExtensions.cs
index 31656e3..9203519 100644
--- a/TwitchLib.EventSub.Websockets/Extensions/LogExtensions.cs
+++ b/TwitchLib.EventSub.Websockets/Extensions/LogExtensions.cs
@@ -1,5 +1,6 @@
using System;
using System.Net.WebSockets;
+using System.Text;
using Microsoft.Extensions.Logging;
using TwitchLib.EventSub.Websockets.Client;
@@ -7,9 +8,14 @@ namespace TwitchLib.EventSub.Websockets.Extensions
{
internal static partial class LogExtensions
{
- [LoggerMessage(LogLevel.Debug, "{message}")]
+ const LogLevel LogMessageLogLevel = LogLevel.Debug;
+
+ [LoggerMessage(LogLevel.Error, "Exeption was throw when raising '{eventName}' event.")]
+ public static partial void LogRaiseEventExeption(this ILogger logger, string eventName, Exception ex);
+
+ [LoggerMessage(LogMessageLogLevel, "{message}")]
public static partial void LogMessage(this ILogger logger, string message);
-
+
[LoggerMessage(LogLevel.Critical, "Websocket {sessionId} disconnected at {disconnectedAt}. Reason: {disconnectReason}")]
public static partial void LogForceDisconnected(this ILogger logger, string sessionId, DateTime? disconnectedAt, string disconnectReason);
@@ -24,5 +30,13 @@ internal static partial class LogExtensions
[LoggerMessage(LogLevel.Critical, "{closeStatus} - {closeStatusDescription}")]
public static partial void LogWebsocketClosed(this ILogger logger, WebSocketCloseStatus closeStatus, string closeStatusDescription);
+
+ public static void LogMessage(this ILogger logger, byte[] message)
+ {
+ if (logger.IsEnabled(LogMessageLogLevel))
+ {
+ __LogMessageCallback(logger, Encoding.UTF8.GetString(message), null);
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/ChannelPoints/Redemptions/ChannelPointsAutomaticRewardRedemptionAddHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/ChannelPoints/Redemptions/ChannelPointsAutomaticRewardRedemptionAddHandler.cs
new file mode 100644
index 0000000..6ae04f6
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/ChannelPoints/Redemptions/ChannelPointsAutomaticRewardRedemptionAddHandler.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.ChannelPoints.Redemptions;
+///
+/// Handler for 'channel.channel_points_automatic_reward_redemption.add' notifications
+///
+public class ChannelPointsAutomaticRewardRedemptionAddHandler : INotificationHandler
+{
+ ///
+ public string SubscriptionType => "channel.channel_points_automatic_reward_redemption.add";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelPointsAutomaticRewardRedemptionAdd", new ChannelPointsAutomaticRewardRedemptionArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChannelChatClearHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChannelChatClearHandler.cs
new file mode 100644
index 0000000..5fd0d20
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChannelChatClearHandler.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Chat;
+
+///
+/// Handler for 'channel.chat.clear' notifications
+///
+public class ChannelChatClearHandler : INotificationHandler
+{
+ ///
+ public string SubscriptionType => "channel.chat.clear";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelChatClear", new ChannelChatClearArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChannelChatClearUserMessagesHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChannelChatClearUserMessagesHandler.cs
new file mode 100644
index 0000000..2931c65
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChannelChatClearUserMessagesHandler.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Chat;
+
+///
+/// Handler for 'channel.chat.clear_user_messages' notifications
+///
+public class ChannelChatClearUserMessagesHandler : INotificationHandler
+{
+ ///
+ public string SubscriptionType => "channel.chat.clear_user_messages";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelChatClearUserMessages", new ChannelChatClearUserMessagesArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChatMessageDeleteHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChatMessageDeleteHandler.cs
new file mode 100644
index 0000000..980cba1
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChatMessageDeleteHandler.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Chat
+{
+ ///
+ /// Handler for 'channel.chat.message_delete' notifications
+ ///
+ public class ChatMessageDeleteHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.chat.message_delete";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+ client.RaiseEvent("ChannelChatMessageDelete", new ChannelChatMessageDeleteArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChatNotificationHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChatNotificationHandler.cs
new file mode 100644
index 0000000..9e401ed
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Chat/ChatNotificationHandler.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Chat
+{
+ ///
+ /// Handler for 'channel.chat.notification' notifications
+ ///
+ public class ChatNotificationHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.chat.notification";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+ client.RaiseEvent("ChannelChatNotification", new ChannelChatNotificationArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/ChatMessageHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/ChatMessageHandler.cs
index 226fe03..07f5a6c 100644
--- a/TwitchLib.EventSub.Websockets/Handler/Channel/ChatMessageHandler.cs
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/ChatMessageHandler.cs
@@ -8,10 +8,15 @@
namespace TwitchLib.EventSub.Websockets.Handler.Channel
{
+ ///
+ /// Handler for 'channel.chat.nessage' notifications
+ ///
public class ChatMessageHandler : INotificationHandler
{
+ ///
public string SubscriptionType => "channel.chat.message";
+ ///
public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
{
try
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Moderation/ChannelUnbanRequestCreateHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Moderation/ChannelUnbanRequestCreateHandler.cs
new file mode 100644
index 0000000..2e0e8f7
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Moderation/ChannelUnbanRequestCreateHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Moderation
+{
+ ///
+ /// Handler for 'channel.unban_request.create' notifications
+ ///
+ public class ChannelUnbanRequestCreateHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.unban_request.create";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelUnbanRequestCreate", new ChannelUnbanRequestCreateArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Moderation/ChannelUnbanRequestResolveHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Moderation/ChannelUnbanRequestResolveHandler.cs
new file mode 100644
index 0000000..411da7e
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Moderation/ChannelUnbanRequestResolveHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Moderation
+{
+ ///
+ /// Handler for 'channel.unban_request.resolve' notifications
+ ///
+ public class ChannelUnbanRequestResolveHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.unban_request.resolve";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelUnbanRequestResolve", new ChannelUnbanRequestResolveArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionBeginHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionBeginHandler.cs
new file mode 100644
index 0000000..ea2f3e1
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionBeginHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.SharedChat
+{
+ ///
+ /// Handler for 'channel.shared_chat.begin' notifications
+ ///
+ public class ChannelSharedChatSessionBeginHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.shared_chat.begin";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelSharedChatSessionBegin", new ChannelSharedChatSessionBeginArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle channel.shared_chat.begin notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionEndHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionEndHandler.cs
new file mode 100644
index 0000000..ef0e972
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionEndHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.SharedChat
+{
+ ///
+ /// Handler for 'channel.shared_chat.end' notifications
+ ///
+ public class ChannelSharedChatSessionEndHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.shared_chat.end";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelSharedChatSessionEnd", new ChannelSharedChatSessionEndArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle channel.shared_chat.end notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionUpdateHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionUpdateHandler.cs
new file mode 100644
index 0000000..0047e0b
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/SharedChat/ChannelSharedChatSessionUpdateHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.SharedChat
+{
+ ///
+ /// Handler for 'channel.shared_chat.update' notifications
+ ///
+ public class ChannelSharedChatSessionUpdateHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.shared_chat.update";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelSharedChatSessionUpdate", new ChannelSharedChatSessionUpdateArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle channel.shared_chat.update notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/SuspiciousUser/ChannelSuspiciousUserMessageHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/SuspiciousUser/ChannelSuspiciousUserMessageHandler.cs
new file mode 100644
index 0000000..8616f65
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/SuspiciousUser/ChannelSuspiciousUserMessageHandler.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.SuspiciousUser
+{
+ ///
+ /// Handler for 'channel.suspicious_user.message' notifications
+ ///
+ public class ChannelSuspiciousUserMessageHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.suspicious_user.message";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelSuspiciousUserMessage", new ChannelSuspiciousUserMessageArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/SuspiciousUser/ChannelSuspiciousUserUpdateHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/SuspiciousUser/ChannelSuspiciousUserUpdateHandler.cs
new file mode 100644
index 0000000..af11ae8
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/SuspiciousUser/ChannelSuspiciousUserUpdateHandler.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.SuspiciousUser
+{
+ ///
+ /// Handler for 'channel.suspicious_user.update' notifications
+ ///
+ public class ChannelSuspiciousUserUpdateHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.suspicious_user.update";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelSuspiciousUserUpdate", new ChannelSuspiciousUserUpdateArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Vips/ChannelVipAddHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Vips/ChannelVipAddHandler.cs
new file mode 100644
index 0000000..1b11576
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Vips/ChannelVipAddHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Vips
+{
+ ///
+ /// Handler for 'channel.vip.add' notifications
+ ///
+ public class ChannelVipAddHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.vip.add";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelVipAdd", new ChannelVipArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Vips/ChannelVipRemoveHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Vips/ChannelVipRemoveHandler.cs
new file mode 100644
index 0000000..34bb979
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Vips/ChannelVipRemoveHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Vips
+{
+ ///
+ /// Handler for 'channel.vip.remove' notifications
+ ///
+ public class ChannelVipRemoveHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.vip.remove";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelVipRemove", new ChannelVipArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Warning/ChannelWarningAcknowledgeHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Warning/ChannelWarningAcknowledgeHandler.cs
new file mode 100644
index 0000000..b6787f5
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Warning/ChannelWarningAcknowledgeHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Warning
+{
+ ///
+ /// Handler for 'channel.warning.acknowledge' notifications
+ ///
+ public class ChannelWarningAcknowledgeHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.warning.acknowledge";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelWarningAcknowledge", new ChannelWarningAcknowledgeArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/Channel/Warning/ChannelWarningSendHandler.cs b/TwitchLib.EventSub.Websockets/Handler/Channel/Warning/ChannelWarningSendHandler.cs
new file mode 100644
index 0000000..236d9c9
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/Channel/Warning/ChannelWarningSendHandler.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.Channel.Warning
+{
+ ///
+ /// Handler for 'channel.warning.send' notifications
+ ///
+ public class ChannelWarningSendHandler : INotificationHandler
+ {
+ ///
+ public string SubscriptionType => "channel.warning.send";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("ChannelWarningSend", new ChannelWarningSendArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/User/UserUpdateHandler.cs b/TwitchLib.EventSub.Websockets/Handler/User/UserUpdateHandler.cs
index 4bc5093..47a436e 100644
--- a/TwitchLib.EventSub.Websockets/Handler/User/UserUpdateHandler.cs
+++ b/TwitchLib.EventSub.Websockets/Handler/User/UserUpdateHandler.cs
@@ -33,5 +33,5 @@ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerial
client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
}
}
- }
-}
\ No newline at end of file
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/Handler/User/UserWhisperMessageHandler.cs b/TwitchLib.EventSub.Websockets/Handler/User/UserWhisperMessageHandler.cs
new file mode 100644
index 0000000..24367f9
--- /dev/null
+++ b/TwitchLib.EventSub.Websockets/Handler/User/UserWhisperMessageHandler.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Text.Json;
+using TwitchLib.EventSub.Core.SubscriptionTypes.User;
+using TwitchLib.EventSub.Websockets.Core.EventArgs;
+using TwitchLib.EventSub.Websockets.Core.EventArgs.User;
+using TwitchLib.EventSub.Websockets.Core.Handler;
+using TwitchLib.EventSub.Websockets.Core.Models;
+
+namespace TwitchLib.EventSub.Websockets.Handler.User;
+
+///
+/// Handler for 'user.whisper.message' notifications
+///
+public class UserWhisperMessageHandler : INotificationHandler
+{
+ ///
+ public string SubscriptionType => "user.whisper.message";
+
+ ///
+ public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
+ {
+ try
+ {
+ var data = JsonSerializer.Deserialize>(jsonString.AsSpan(), serializerOptions);
+
+ if (data is null)
+ throw new InvalidOperationException("Parsed JSON cannot be null!");
+
+ client.RaiseEvent("UserWhisperMessage", new UserWhisperMessageArgs { Notification = data });
+ }
+ catch (Exception ex)
+ {
+ client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs { Exception = ex, Message = $"Error encountered while trying to handle {SubscriptionType} notification! Raw Json: {jsonString}" });
+ }
+ }
+}
diff --git a/TwitchLib.EventSub.Websockets/TwitchLib.EventSub.Websockets.csproj b/TwitchLib.EventSub.Websockets/TwitchLib.EventSub.Websockets.csproj
index 1ac360e..8daedb8 100644
--- a/TwitchLib.EventSub.Websockets/TwitchLib.EventSub.Websockets.csproj
+++ b/TwitchLib.EventSub.Websockets/TwitchLib.EventSub.Websockets.csproj
@@ -5,10 +5,10 @@
TwitchLib.EventSub.Websockets
TwitchLib.EventSub.Websockets
swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin
- 0.5.0
+ 0.6.0
$(VersionSuffix)
- 0.5.0
- 0.5.0
+ 0.6.0
+ 0.6.0
EventSub Websockets (also known as EventSockets) Client Library
https://cdn.syzuna-programs.de/images/twitchlib.png
https://github.com/TwitchLib/TwitchLib.EventSub.Websockets
@@ -17,21 +17,22 @@
MIT
Copyright 2023
twitch library events eventsub websockets eventsockets c# csharp netstandard2.0 netstandard2.1 net6.0 net7.0 net8.0
- Updated TwitchLib.EventSub.Core for the latest SubscriptionType changes
+ Updated dependencies, enabled nullable, added new events (ChannelChatClear, ChannelChatClearUserMessages, ChannelChatMessageDelete, ChannelChatNotification, ChannelVipAdd, ChannelVipRemove, ChannelPointsAutomaticRewardRedemptionAdd, ChannelSuspiciousUserMessage, ChannelSuspiciousUserUpdate, ChannelWarningAcknowledge, ChannelWarningSend, UserWhisperMessage, ChannelSharedChatSessionBegin, ChannelSharedChatSessionUpdate, ChannelSharedChatSessionEnd, ChannelUnbanRequestCreate, ChannelUnbanRequestResolve)
en-US
disable
- disable
+ enable
True
latest-all
True
README.md
latest
+ 1701;1702;CA1003
-
-
+
+