diff --git a/TwitchIrcClient/IRC/Badge.cs b/TwitchIrcClient/IRC/Badge.cs index f5363b4..30c939c 100644 --- a/TwitchIrcClient/IRC/Badge.cs +++ b/TwitchIrcClient/IRC/Badge.cs @@ -9,6 +9,6 @@ namespace TwitchIrcClient.IRC { public record struct Badge(string Name, string Version) { - + } } diff --git a/TwitchIrcClient/IRC/Messages/UserNotice.cs b/TwitchIrcClient/IRC/Messages/UserNotice.cs index e3a16b0..59c3406 100644 --- a/TwitchIrcClient/IRC/Messages/UserNotice.cs +++ b/TwitchIrcClient/IRC/Messages/UserNotice.cs @@ -85,9 +85,6 @@ namespace TwitchIrcClient.IRC.Messages public string Id => TryGetTag("id"); public UserNoticeType? UserNoticeType => Enum.TryParse(TryGetTag("msg-id"), out UserNoticeType type) ? type : null; - /// - /// - /// public string Login => TryGetTag("login"); /// /// Whether the user is a moderator in this channel @@ -263,21 +260,15 @@ namespace TwitchIrcClient.IRC.Messages public UserType UserType { get { - if (!MessageTags.TryGetValue("user-type", out string? value)) - return UserType.None; - switch (value.ToUpper()) + var value = TryGetTag("user-type"); + return value.ToUpper() switch { - case "ADMIN": - return UserType.Admin; - case "GLOBAL_MOD": - return UserType.GlobalMod; - case "STAFF": - return UserType.Staff; - case "": - return UserType.Normal; - default: - throw new InvalidDataException(); - } + "ADMIN" => UserType.Admin, + "GLOBAL_MOD" => UserType.GlobalMod, + "STAFF" => UserType.Staff, + "" => UserType.Normal, + _ => UserType.Normal, + }; } } /// diff --git a/TwitchIrcClient/IRC/RateLimiter.cs b/TwitchIrcClient/IRC/RateLimiter.cs index 3a93de7..071a8f1 100644 --- a/TwitchIrcClient/IRC/RateLimiter.cs +++ b/TwitchIrcClient/IRC/RateLimiter.cs @@ -88,25 +88,27 @@ namespace TwitchIrcClient.IRC { lock (Semaphore) { - Semaphore.Release(MessageLimit - Semaphore.CurrentCount); + var count = MessageLimit - Semaphore.CurrentCount; + if (count > 0) + Semaphore.Release(count); } } - catch (SemaphoreFullException) { } + catch (SemaphoreFullException) { } catch (ObjectDisposedException) { } } #region RateLimiter Dispose - private bool disposedValue; + //https://stackoverflow.com/questions/8927878/what-is-the-correct-way-of-adding-thread-safety-to-an-idisposable-object + private int _disposedCount; protected virtual void Dispose(bool disposing) { - if (!disposedValue) + if (Interlocked.Increment(ref _disposedCount) == 1) { if (disposing) { Semaphore?.Dispose(); Timer?.Dispose(); } - disposedValue = true; } } diff --git a/TwitchIrcClient/Program.cs b/TwitchIrcClient/Program.cs index 885e0ed..e4ffc2f 100644 --- a/TwitchIrcClient/Program.cs +++ b/TwitchIrcClient/Program.cs @@ -52,7 +52,7 @@ async Task CreateConnection(string channel) Console.Write("Channel: "); var channelName = Console.ReadLine(); ArgumentNullException.ThrowIfNull(channelName, nameof(Channel)); -var connection = CreateConnection(channelName); +var connection = await CreateConnection(channelName); while (true) { //all the work happens in other threads