From 5bd767b862bec2e1a26304be6fa8f6dd8c25ec7f Mon Sep 17 00:00:00 2001 From: Apollo Nargang Date: Thu, 8 May 2025 23:10:04 -0400 Subject: [PATCH] [TikTokBridge] Use oEmbed for video metadata (#4514) * [TikTokBridge] Use oEmbed for video metadata Fetches oEmbed-formatted metadata for videos through the TikTok API to provide post titles, thumbnails, and authors. This hasn't yet been tested, so it's possible it doesn't work. * [TikTokBridge] Add back view count parsing oops * [TikTokBridge] Prepend www to the oEmbed API endpoint URL The non-www URL resulted in a 301 redirect to the www URL, so this just skips that redirect, improving performance a bit and hopefully helping with the 400 errors. * [TikTokBridge] Retry failed OEmbed requests If an OEmbed request fails, retry a few times, waiting a bit in between each retry. This should fix the problem for the most part, since I think the problem was related to some sort of rate limit (it isn't mentioned in the docs, but it seems to only happen when sending large quantities of sequential requests). --- bridges/TikTokBridge.php | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/bridges/TikTokBridge.php b/bridges/TikTokBridge.php index 43a9cb31..ff3bfbc2 100644 --- a/bridges/TikTokBridge.php +++ b/bridges/TikTokBridge.php @@ -21,6 +21,8 @@ class TikTokBridge extends BridgeAbstract 'context' => 'By user', 'username' => '@tiktok' ] ]; + const OEMBED_RETRY_COUNT = 20; + const OEMBED_RETRY_DELAY = 0.1; const CACHE_TIMEOUT = 900; // 15 minutes @@ -42,16 +44,33 @@ class TikTokBridge extends BridgeAbstract $parsedUrl = parse_url($href); $url = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/' . ltrim($parsedUrl['path'], '/'); - $image = $video->find('video', 0)->poster; + // Sometimes the API fails to return data for a second, so try a few times + $attempts = 0; + do { + try { + // Fetch the video embed data from the OEmbed API + $videoEmbedResponse = getContents('https://www.tiktok.com/oembed?url=' . $url); + } catch (Exception $e) { + $attempts++; + sleep($OEMBED_RETRY_DELAY); + continue; + } + break; + } while($attempts < $OEMBED_RETRY_COUNT); + $videoEmbedData = json_decode($videoEmbedResponse); + + $title = $videoEmbedData->title; + $image = $videoEmbedData->thumbnail_url; $views = $video->find('div[data-e2e=common-Video-Count]', 0)->plaintext; $enclosures = [$image, $authorProfilePicture]; $item['uri'] = $url; - $item['title'] = 'Video'; - $item['author'] = '@' . $author; + $item['title'] = $title; + $item['author'] = '@' . $videoEmbedData->author_unique_id; $item['enclosures'] = $enclosures; $item['content'] = <<$title

{$views} views


EOD;