From d99c5768d314dfa07f5c929fe938e1f15762c217 Mon Sep 17 00:00:00 2001 From: rgueldenpfennig Date: Sat, 18 Jan 2025 19:14:21 +0100 Subject: [PATCH] fix(tiktok): correctly handle Tiktok URLs shared from the app --- src/Squidlr.Web/Program.cs | 1 + src/Squidlr/Tiktok/TiktokContentProvider.cs | 5 ++--- src/Squidlr/Tiktok/TiktokIdentifier.cs | 2 +- .../Tiktok/TiktokServiceCollectionExtensions.cs | 2 +- src/Squidlr/Tiktok/Utilities/UrlUtilities.cs | 13 +++++++++++-- .../Tiktok/Utilities/UrlUtilitiesTests.cs | 6 ++++-- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Squidlr.Web/Program.cs b/src/Squidlr.Web/Program.cs index 12ee8c2..7cf2934 100644 --- a/src/Squidlr.Web/Program.cs +++ b/src/Squidlr.Web/Program.cs @@ -173,6 +173,7 @@ public static int Main(string[] args) builder.AddFrameAncestors().None(); builder.AddImgSrc().Self().From("https://*.tiktokcdn.com") .From("https://*.tiktokcdn-us.com") + .From("https://*.tiktokcdn-eu.com") .From("https://media.licdn.com") .From("https://*.fbcdn.net") .From("https://pbs.twimg.com"); diff --git a/src/Squidlr/Tiktok/TiktokContentProvider.cs b/src/Squidlr/Tiktok/TiktokContentProvider.cs index 6d11396..b53c53e 100644 --- a/src/Squidlr/Tiktok/TiktokContentProvider.cs +++ b/src/Squidlr/Tiktok/TiktokContentProvider.cs @@ -60,8 +60,8 @@ public async ValueTask> GetContentAsync(st var videoDetail = root.GetPropertyOrNull("__DEFAULT_SCOPE__")?.GetPropertyOrNull("webapp.video-detail"); if (videoDetail == null) { - _logger.LogError("Could not find 'webapp.video-detail' in JSON payload."); - return new(RequestContentResult.Error); + _logger.LogWarning("Could not find 'webapp.video-detail' in JSON payload."); + return new(RequestContentResult.NoVideo); } var statusCode = videoDetail.Value.GetPropertyOrNull("statusCode")?.GetInt32(); @@ -80,7 +80,6 @@ public async ValueTask> GetContentAsync(st if (id == null || !id.Equals(identifier.Id, StringComparison.OrdinalIgnoreCase)) { _logger.LogWarning("ID does not match requested Tiktok identifier."); - return new(RequestContentResult.NotFound); } if (itemStruct.GetPropertyOrNull("isContentClassified")?.GetBoolean() == true) diff --git a/src/Squidlr/Tiktok/TiktokIdentifier.cs b/src/Squidlr/Tiktok/TiktokIdentifier.cs index 7942a3b..fa12a0f 100644 --- a/src/Squidlr/Tiktok/TiktokIdentifier.cs +++ b/src/Squidlr/Tiktok/TiktokIdentifier.cs @@ -1,3 +1,3 @@ namespace Squidlr.Tiktok; -public record struct TiktokIdentifier(string Id, string Url); +public record struct TiktokIdentifier(string Id, string Url, bool IsShareUrl = false); diff --git a/src/Squidlr/Tiktok/TiktokServiceCollectionExtensions.cs b/src/Squidlr/Tiktok/TiktokServiceCollectionExtensions.cs index c1a1d30..5bca02d 100644 --- a/src/Squidlr/Tiktok/TiktokServiceCollectionExtensions.cs +++ b/src/Squidlr/Tiktok/TiktokServiceCollectionExtensions.cs @@ -28,7 +28,7 @@ public static IServiceCollection AddTiktok(this IServiceCollection services) { var handler = new SocketsHttpHandler { - AllowAutoRedirect = false, + AllowAutoRedirect = true, UseCookies = true }; diff --git a/src/Squidlr/Tiktok/Utilities/UrlUtilities.cs b/src/Squidlr/Tiktok/Utilities/UrlUtilities.cs index 39387c2..f801f77 100644 --- a/src/Squidlr/Tiktok/Utilities/UrlUtilities.cs +++ b/src/Squidlr/Tiktok/Utilities/UrlUtilities.cs @@ -8,16 +8,25 @@ public static partial class UrlUtilities [GeneratedRegex(@"https?:\/\/(www\.)?tiktok\.com\/(\S+)\/video\/(?\d+).*?", RegexOptions.IgnoreCase)] private static partial Regex TiktokUrlRegex(); + [GeneratedRegex(@"https?:\/\/vm.tiktok\.com\/(?[\s\S][^\/\?]+).*?", RegexOptions.IgnoreCase)] + private static partial Regex TiktokShareUrlRegex(); + public static bool TryGetTiktokIdentifier(string url, [NotNullWhen(true)] out TiktokIdentifier? identifier) { ArgumentException.ThrowIfNullOrEmpty(url); identifier = null; + var isShareUrl = false; var match = TiktokUrlRegex().Match(url); if (!match.Success) - return false; + { + match = TiktokShareUrlRegex().Match(url); + if (!match.Success) + return false; + isShareUrl = true; + } - identifier = new(match.Groups["id"].Value, match.Groups[0].Value); + identifier = new(match.Groups["id"].Value, match.Groups[0].Value, isShareUrl); return true; } diff --git a/test/Squidlr.Tests/Tiktok/Utilities/UrlUtilitiesTests.cs b/test/Squidlr.Tests/Tiktok/Utilities/UrlUtilitiesTests.cs index 4a3b1f7..fe3aba4 100644 --- a/test/Squidlr.Tests/Tiktok/Utilities/UrlUtilitiesTests.cs +++ b/test/Squidlr.Tests/Tiktok/Utilities/UrlUtilitiesTests.cs @@ -13,6 +13,7 @@ public class UrlUtilitiesTests [InlineData("https://www.tiktok.com/@_le_cannibale_/video/7139980461132074283", true)] [InlineData("https://www.tiktok.com/@moxypatch/video/7206382937372134662", true)] [InlineData("http://tiktok.com/@moxypatch/video/7206382937372134662", true)] + [InlineData("https://vm.tiktok.com/ZNeKLnGKw", true)] [InlineData("https://www.tiktok.com/@moxypatch/image/7206382937372134662", false)] [InlineData("https://example.com/foo/1152128691131318273/", false)] [InlineData("https://google.com", false)] @@ -30,13 +31,14 @@ public void IsValidTiktokUrl(string url, bool expectedResult) [InlineData("https://www.tiktok.com/@leenabhushan/video/6748451240264420610?foo=bar#abc", "6748451240264420610", "https://www.tiktok.com/@leenabhushan/video/6748451240264420610")] [InlineData("https://www.tiktok.com/@patroxofficial/video/6742501081818877190?langCountry=en", "6742501081818877190", "https://www.tiktok.com/@patroxofficial/video/6742501081818877190")] [InlineData("http://tiktok.com/@moxypatch/video/7206382937372134662", "7206382937372134662", "http://tiktok.com/@moxypatch/video/7206382937372134662")] + [InlineData("https://vm.tiktok.com/ZNeKLnGKw?foo=bar", "ZNeKLnGKw", "https://vm.tiktok.com/ZNeKLnGKw")] public void GetTiktokIdentifier(string url, string expectedId, string expectedUrl) { // Act Assert.True(UrlUtilities.TryGetTiktokIdentifier(url, out var identifier)); // Assert - Assert.Equal(expectedId, identifier?.Id); - Assert.Equal(expectedUrl, identifier?.Url); + Assert.Equal(expectedId, identifier.Value.Id); + Assert.Equal(expectedUrl, identifier.Value.Url); } }