Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few minor changes #904

Merged
merged 6 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions TwitchDownloaderCore/Chat/ChatJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ private static async Task<JsonDocument> 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
Expand Down Expand Up @@ -213,6 +214,7 @@ private static async Task UpgradeChatJson(ChatRoot chatRoot)
}
}
}
#pragma warning restore CS0618

/// <summary>
/// Asynchronously serializes a chat json file.
Expand Down
50 changes: 20 additions & 30 deletions TwitchDownloaderCore/ChatRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<char> timestampStackSpace = stackalloc char[MAX_TIMESTAMP_LENGTH];
ReadOnlySpan<char> 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)
{
Expand All @@ -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<char> FormatTimestamp(Span<char> 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)
Expand Down
5 changes: 3 additions & 2 deletions TwitchDownloaderCore/Tools/HighlightIcons.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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"))
Expand All @@ -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!"))
Expand Down
2 changes: 1 addition & 1 deletion TwitchDownloaderCore/Tools/TwitchRegex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/// <returns>A <see cref="Match"/> of the video's id or <see langword="null"/>.</returns>
Expand Down
6 changes: 3 additions & 3 deletions TwitchDownloaderCore/TwitchObjects/ChatRoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,13 @@ public class Video
public List<VideoChapter> chapters { get; set; } = new();

#region DeprecatedProperties
/// <summary>Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.</summary>
[Obsolete("Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string duration { get; set; } = null;
/// <summary>Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.</summary>
[Obsolete("Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string user_id { get; set; } = null;
/// <summary>Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.</summary>
[Obsolete("Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string user_name { get; set; } = null;
#endregion
Expand Down