Fix incorrectly shown Twitter video cards

Fixes #1407
This commit is contained in:
Zed 2026-06-10 14:28:01 +02:00
commit ac5ba9469e
2 changed files with 29 additions and 10 deletions

View file

@ -1,5 +1,5 @@
# SPDX-License-Identifier: AGPL-3.0-only
import strutils, options, times, math, tables
import strutils, options, times, math, tables, uri
import packedjson, packedjson/deserialiser
import types, parserutils, utils
import experimental/parser/unifiedcard
@ -229,6 +229,10 @@ proc parseLegacyMediaEntities(js: JsonNode; result: var Tweet) =
result.attribution = some(parseUser(user))
else:
result.attribution = some(parseGraphUser(user))
# Set attribution link from expanded_url (strip /video/N suffix)
let expanded = m{"expanded_url"}.getStr
if expanded.len > 0:
result.attributionLink = expanded.parseUri.path.replace("/video/1", "")
of "animated_gif":
result.media.addMedia(Gif(
url: m{"video_info", "variants"}[0]{"url"}.getImageStr,
@ -266,11 +270,9 @@ proc parseMediaEntities(js: JsonNode; result: var Tweet) =
# Parse source user for video attribution
with sourceUser, mediaEntity{"source_user_results", "result"}:
if result.attribution.isNone:
let
expanded = mediaEntity{"expanded_url"}.getStr
pathStart = expanded.find('/', expanded.find("://") + 3)
if pathStart >= 0:
result.attributionLink = expanded[pathStart .. ^1].replace("/video/1", "")
let expanded = mediaEntity{"expanded_url"}.getStr
if expanded.len > 0:
result.attributionLink = expanded.parseUri.path.replace("/video/1", "")
result.attribution = some(User(
id: sourceUser{"rest_id"}.getStr,
fullname: sourceUser{"core", "name"}.getStr,
@ -467,8 +469,8 @@ proc parseTweet(js: JsonNode; jsCard: JsonNode = newJNull();
elif name.len > 0 and jsCard{"binding_values"}.notNull:
result.card = some parseCard(jsCard, js{"entities", "urls"})
result.expandTweetEntities(js)
parseLegacyMediaEntities(js, result)
result.expandTweetEntities(js)
with jsWithheld, js{"withheld_in_countries"}:
let withheldInCountries: seq[string] =
@ -555,6 +557,10 @@ proc parseGraphTweet*(js: JsonNode): Tweet =
elif name.len > 0 and jsCard{"binding_values"}.notNull:
result.card = some parseCard(jsCard, js{"url_entities"})
parseMediaEntities(js, result)
if result.attribution.isNone:
parseLegacyMediaEntities(js{"legacy"}, result)
result.expandTweetEntitiesV2(js)
# Strip video source URL from text (for videos from other tweets)
@ -585,6 +591,14 @@ proc parseGraphTweet*(js: JsonNode): Tweet =
parseMediaEntities(js, result)
# Hide card if it's redundant with attribution (same video shown via embed)
if result.attribution.isSome and result.card.isSome:
let cardUri = get(result.card).url.parseUri
if cardUri.isTwitterUrl:
let cardPath = cardUri.path.replace("/video/1", "")
if cardPath.len > 0 and cardPath == result.attributionLink:
get(result.card).kind = hidden
# Handle retweets - check both legacy and top-level paths
with reposts, js{"legacy", "repostedStatusResults"}:
with rt, reposts{"result"}: