From 869068ba5e43d613f1e83bec476e61ad4e52ce45 Mon Sep 17 00:00:00 2001 From: Scrub <72096833+ScrubN@users.noreply.github.com> Date: Tue, 28 Nov 2023 18:39:17 -0500 Subject: [PATCH] A few minor changes (#904) * Use the obsolete attribute instead of a summary * Use a switch expression instead of nested ternaries * Use quantifier instead of multiple conditionals * Add channel point icon svg string, just in case * Minor HighlightType parsing changes * Inline FormatTimestamp as switch expression --- TwitchDownloaderCore/Chat/ChatJson.cs | 2 + TwitchDownloaderCore/ChatRenderer.cs | 50 ++++++++----------- TwitchDownloaderCore/Tools/HighlightIcons.cs | 5 +- TwitchDownloaderCore/Tools/TwitchRegex.cs | 2 +- .../TwitchObjects/ChatRoot.cs | 6 +-- 5 files changed, 29 insertions(+), 36 deletions(-) diff --git a/TwitchDownloaderCore/Chat/ChatJson.cs b/TwitchDownloaderCore/Chat/ChatJson.cs index ec1143e8..3c198649 100644 --- a/TwitchDownloaderCore/Chat/ChatJson.cs +++ b/TwitchDownloaderCore/Chat/ChatJson.cs @@ -170,6 +170,7 @@ private static async Task GetJsonDocumentAsync(Stream stream, stri } } +#pragma warning disable CS0618 private static async Task UpgradeChatJson(ChatRoot chatRoot) { const int MAX_STREAM_LENGTH = 172_800; // 48 hours in seconds. https://help.twitch.tv/s/article/broadcast-guidelines @@ -213,6 +214,7 @@ private static async Task UpgradeChatJson(ChatRoot chatRoot) } } } +#pragma warning restore CS0618 /// /// Asynchronously serializes a chat json file. diff --git a/TwitchDownloaderCore/ChatRenderer.cs b/TwitchDownloaderCore/ChatRenderer.cs index e24c160a..a4dbcb6d 100644 --- a/TwitchDownloaderCore/ChatRenderer.cs +++ b/TwitchDownloaderCore/ChatRenderer.cs @@ -1470,7 +1470,17 @@ private void DrawTimestamp(Comment comment, List<(SKImageInfo info, SKBitmap bit var timestamp = new TimeSpan(0, 0, (int)comment.content_offset_seconds); const int MAX_TIMESTAMP_LENGTH = 8; // 48:00:00 - var formattedTimestamp = FormatTimestamp(stackalloc char[MAX_TIMESTAMP_LENGTH], timestamp); + Span timestampStackSpace = stackalloc char[MAX_TIMESTAMP_LENGTH]; + ReadOnlySpan formattedTimestamp = timestamp.Ticks switch + { + >= 24 * TimeSpan.TicksPerHour => TimeSpanHFormat.ReusableInstance.Format(@"HH\:mm\:ss", timestamp), + >= 1 * TimeSpan.TicksPerHour => timestamp.TryFormat(timestampStackSpace, out var charsWritten, @"h\:mm\:ss") + ? timestampStackSpace[..charsWritten] + : timestamp.ToString(@"h\:mm\:ss"), + _ => timestamp.TryFormat(timestampStackSpace, out var charsWritten, @"m\:ss") + ? timestampStackSpace[..charsWritten] + : timestamp.ToString(@"m\:ss") + }; if (renderOptions.Outline) { @@ -1479,37 +1489,17 @@ private void DrawTimestamp(Comment comment, List<(SKImageInfo info, SKBitmap bit } sectionImageCanvas.DrawText(formattedTimestamp, drawPos.X, drawPos.Y, messageFont); - var textWidth = - timestamp.TotalHours >= 1 - ? timestamp.TotalHours >= 10 - ? renderOptions.TimestampWidths[3] - : renderOptions.TimestampWidths[2] - : timestamp.Minutes >= 10 - ? renderOptions.TimestampWidths[1] - : renderOptions.TimestampWidths[0]; - drawPos.X += textWidth + renderOptions.WordSpacing * 2; - defaultPos.X = drawPos.X; - static ReadOnlySpan FormatTimestamp(Span stackSpace, TimeSpan timespan) + // We use pre-defined widths so all timestamps have the same defaultPos regardless of individual character width + var textWidth = timestamp.Ticks switch { - if (timespan.TotalHours >= 1) - { - if (timespan.TotalHours >= 24) - { - return TimeSpanHFormat.ReusableInstance.Format(@"HH\:mm\:ss", timespan); - } - - return timespan.TryFormat(stackSpace, out var charsWritten, @"h\:mm\:ss") - ? stackSpace[..charsWritten] - : timespan.ToString(@"h\:mm\:ss"); - } - else - { - return timespan.TryFormat(stackSpace, out var charsWritten, @"m\:ss") - ? stackSpace[..charsWritten] - : timespan.ToString(@"m\:ss"); - } - } + >= 10 * TimeSpan.TicksPerHour => renderOptions.TimestampWidths[3], + >= 1 * TimeSpan.TicksPerHour => renderOptions.TimestampWidths[2], + >= 10 * TimeSpan.TicksPerMinute => renderOptions.TimestampWidths[1], + _ => renderOptions.TimestampWidths[0] + }; + drawPos.X += textWidth + renderOptions.WordSpacing * 2; + defaultPos.X = drawPos.X; } private void AddImageSection(List<(SKImageInfo info, SKBitmap bitmap)> sectionImages, ref Point drawPos, Point defaultPos) diff --git a/TwitchDownloaderCore/Tools/HighlightIcons.cs b/TwitchDownloaderCore/Tools/HighlightIcons.cs index 649c079a..5aeb5aa8 100644 --- a/TwitchDownloaderCore/Tools/HighlightIcons.cs +++ b/TwitchDownloaderCore/Tools/HighlightIcons.cs @@ -34,6 +34,7 @@ public sealed class HighlightIcons : IDisposable private const string GIFTED_ANONYMOUS_ICON_SVG = "m 54.571425,64.514958 a 4.3531428,4.2396967 0 0 1 -1.273998,-0.86096 l -1.203426,-1.172067 a 7.0051428,6.822584 0 0 0 -9.90229,0 c -3.417139,3.328092 -8.962569,3.328092 -12.383427,0 l -0.159707,-0.155553 a 7.1871427,6.9998405 0 0 0 -9.854005,-0.28216 l -1.894286,1.635103 a 4.9362858,4.8076423 0 0 1 -3.276,1.215474 H 10 V 32.337399 a 26.000001,25.322423 0 0 1 52,0 v 32.557396 h -5.627146 c -0.627714,0 -1.240569,-0.133847 -1.801429,-0.379837 z M 35.999996,14.249955 A 18.571428,18.087444 0 0 0 17.428572,32.337399 v 22.515245 a 14.619428,14.238435 0 0 1 17.471998,2.358609 l 0.163448,0.155554 c 0.516285,0.50645 1.355715,0.50645 1.875712,0 a 14.437428,14.061179 0 0 1 17.631712,-2.11623 V 32.337399 A 18.571428,18.087444 0 0 0 35.999996,14.249955 Z M 24.857142,35.954887 a 3.7142855,3.6174889 0 1 1 7.42857,0 3.7142855,3.6174889 0 0 1 -7.42857,0 z m 18.571432,-3.617488 a 3.7142859,3.6174892 0 1 0 0,7.234978 3.7142859,3.6174892 0 0 0 0,-7.234978 z"; private const string BIT_BADGE_TIER_NOTIFICATION_ICON_SVG = "M 14.242705,42.37453 36,11.292679 57.757295,42.37453 36,61.023641 Z M 22.566425,41.323963 36,22.13092 49.433577,41.317747 46.79162,43.580506 36,39.266345 25.205273,43.586723 22.566425,41.320854 Z"; private const string WATCH_STREAK_ICON_SVG = "M 38.84325,21.169078 33.156748,14.060989 21.215093,27.992844 a 21.267516,21.267402 0 0 0 -5.11785,13.846557 c 0,9.752298 7.961102,17.713358 17.713453,17.713358 H 38.50206 A 17.400696,17.400602 0 0 0 55.902755,42.152157 c 0,-5.288419 -1.848114,-10.406242 -5.231581,-14.500501 L 41.686501,16.904225 Z m -13.306415,10.519973 7.619913,-9.098354 5.686502,7.108089 2.843251,-4.264854 4.606066,5.885497 a 16.945776,16.945684 0 0 1 3.923686,10.832728 c 0,5.91393 -4.407039,10.804296 -10.121973,11.600401 1.02357,-1.336321 1.592221,-2.985397 1.592221,-4.719771 0,-1.478483 -0.511786,-2.900101 -1.421626,-4.065827 l -4.264877,-5.316851 -4.264876,5.316851 c -0.90984,1.137294 -1.421625,2.587344 -1.421625,4.065827 0,1.705941 0.56865,3.355018 1.535355,4.662906 A 12.026952,12.026887 0 0 1 21.783744,41.839401 c 0,-3.72464 1.336328,-7.335548 3.753091,-10.15035 z"; + private const string CHANNEL_POINT_ICON_SVG = "m 34.074833,10.317667 a 25.759205,25.759174 0 0 0 -23.83413,25.686052 25.759298,25.759267 0 0 0 51.518594,0 25.759205,25.759174 0 0 0 -27.684464,-25.686052 z m 0.329458,6.432744 a 19.319404,19.319381 0 0 1 20.915597,19.253308 19.319888,19.319865 0 0 1 -38.639776,0 19.319404,19.319381 0 0 1 17.724179,-19.253308 z M 36,23.124918 v 6.439401 a 6.4398012,6.4397935 0 0 1 6.439407,6.4394 H 48.88048 A 12.879602,12.879587 0 0 0 36,23.124918 Z"; private static readonly Regex SubMessageRegex = new(@"^(subscribed (?:with Prime|at Tier \d)\. They've subscribed for \d{1,3} months(?:, currently on a \d{1,3} month streak)?! )(.+)$", RegexOptions.Compiled); private static readonly Regex GiftAnonymousRegex = new(@"^An anonymous user (?:gifted a|is gifting \d{1,4}) Tier \d", RegexOptions.Compiled); @@ -90,7 +91,7 @@ public static HighlightType GetHighlightType(Comment comment) if (bodyWithoutName.StartsWith(" is paying forward the Gift they got from")) return HighlightType.PayingForward; - if (bodyWithoutName.Contains(" consecutive streams this month and sparked a watch streak!", StringComparison.Ordinal)) + if (bodyWithoutName.EndsWith(" consecutive streams this month and sparked a watch streak! ")) return HighlightType.WatchStreak; if (bodyWithoutName.StartsWith(" converted from a")) @@ -115,7 +116,7 @@ public static HighlightType GetHighlightType(Comment comment) if (bodySpan.Equals("bits badge tier notification ", StringComparison.Ordinal)) return HighlightType.BitBadgeTierNotification; - if (char.IsDigit(bodySpan[0]) && bodySpan.Contains("have joined!", StringComparison.Ordinal)) + if (char.IsDigit(bodySpan[0]) && bodySpan.EndsWith(" have joined! ")) { // TODO: use bodySpan when .NET 7 if (Regex.IsMatch(comment.message.body, $@"^\d+ raiders from {comment.commenter.display_name} have joined!")) diff --git a/TwitchDownloaderCore/Tools/TwitchRegex.cs b/TwitchDownloaderCore/Tools/TwitchRegex.cs index 4005d5b5..20b5b2cb 100644 --- a/TwitchDownloaderCore/Tools/TwitchRegex.cs +++ b/TwitchDownloaderCore/Tools/TwitchRegex.cs @@ -12,7 +12,7 @@ public static class TwitchRegex public static readonly Regex UrlTimeCode = new(@"(?<=(?:\?|&)t=)\d+h\d+m\d+s(?=$|\?|\s)", RegexOptions.Compiled); public static readonly Regex BitsRegex = new( - @"(?<=(?:\s|^)(?:4Head|Anon|Bi(?:bleThumb|tBoss)|bday|C(?:h(?:eer|arity)|orgo)|cheerwal|D(?:ansGame|oodleCheer)|EleGiggle|F(?:rankerZ|ailFish)|Goal|H(?:eyGuys|olidayCheer)|K(?:appa|reygasm)|M(?:rDestructoid|uxy)|NotLikeThis|P(?:arty|ride|JSalt)|RIPCheer|S(?:coops|h(?:owLove|amrock)|eemsGood|wiftRage|treamlabs)|TriHard|uni|VoHiYo))[1-9]\d?\d?\d?\d?\d?\d?(?=\s|$)", + @"(?<=(?:\s|^)(?:4Head|Anon|Bi(?:bleThumb|tBoss)|bday|C(?:h(?:eer|arity)|orgo)|cheerwal|D(?:ansGame|oodleCheer)|EleGiggle|F(?:rankerZ|ailFish)|Goal|H(?:eyGuys|olidayCheer)|K(?:appa|reygasm)|M(?:rDestructoid|uxy)|NotLikeThis|P(?:arty|ride|JSalt)|RIPCheer|S(?:coops|h(?:owLove|amrock)|eemsGood|wiftRage|treamlabs)|TriHard|uni|VoHiYo))[1-9]\d{0,6}(?=\s|$)", RegexOptions.Compiled); /// A of the video's id or . diff --git a/TwitchDownloaderCore/TwitchObjects/ChatRoot.cs b/TwitchDownloaderCore/TwitchObjects/ChatRoot.cs index 36fa5b73..665b1abe 100644 --- a/TwitchDownloaderCore/TwitchObjects/ChatRoot.cs +++ b/TwitchDownloaderCore/TwitchObjects/ChatRoot.cs @@ -204,13 +204,13 @@ public class Video public List chapters { get; set; } = new(); #region DeprecatedProperties - /// Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21. + [Obsolete("Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string duration { get; set; } = null; - /// Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21. + [Obsolete("Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string user_id { get; set; } = null; - /// Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21. + [Obsolete("Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string user_name { get; set; } = null; #endregion