mirror of https://github.com/zedeus/nitter
Support more cards, even the undocumented ones
This commit is contained in:
parent
b4fe3d1f6a
commit
4d650fd33e
|
@ -1,6 +1,6 @@
|
|||
import strutils, options, tables, times, math
|
||||
import packedjson
|
||||
import types, parserutils
|
||||
import types, parserutils, utils
|
||||
|
||||
proc parseProfile(js: JsonNode; id=""): Profile =
|
||||
if js.isNull: return
|
||||
|
@ -124,25 +124,28 @@ proc parseVideo(js: JsonNode): Video =
|
|||
|
||||
proc parsePromoVideo(js: JsonNode): Video =
|
||||
result = Video(
|
||||
videoId: js{"player_content_id"}.getStrVal(js{"card_id"}.getStrVal),
|
||||
thumb: js{"player_image_large", "image_value", "url"}.getStr,
|
||||
thumb: js{"player_image_large"}.getImageVal,
|
||||
available: true,
|
||||
durationMs: js{"content_duration_seconds"}.getStrVal("0").parseInt * 1000,
|
||||
playbackType: vmap,
|
||||
videoId: js{"player_content_id"}.getStrVal(js{"card_id"}.getStrVal(
|
||||
js{"amplify_content_id"}.getStrVal())),
|
||||
)
|
||||
|
||||
var variant = VideoVariant(
|
||||
videoType: m3u8,
|
||||
url: js{"player_hls_url"}.getStrVal(js{"player_stream_url"}.getStrVal)
|
||||
videoType: vmap,
|
||||
url: js{"player_hls_url"}.getStrVal(js{"player_stream_url"}.getStrVal(
|
||||
js{"amplify_url_vmap"}.getStrVal()))
|
||||
)
|
||||
|
||||
if "vmap" in variant.url:
|
||||
variant.videoType = vmap
|
||||
if "m3u8" in variant.url:
|
||||
variant.videoType = m3u8
|
||||
result.playbackType = m3u8
|
||||
|
||||
result.playbackType = vmap
|
||||
result.variants.add variant
|
||||
|
||||
proc parseBroadcast(js: JsonNode): Card =
|
||||
let image = js{"broadcast_thumbnail_large", "image_value", "url"}.getStr
|
||||
let image = js{"broadcast_thumbnail_large"}.getImageVal
|
||||
result = Card(
|
||||
kind: broadcast,
|
||||
url: js{"broadcast_url"}.getStrVal,
|
||||
|
@ -153,8 +156,9 @@ proc parseBroadcast(js: JsonNode): Card =
|
|||
)
|
||||
|
||||
proc parseCard(js: JsonNode; urls: JsonNode): Card =
|
||||
const imageTypes = ["photo_image_full_size", "summary_photo_image",
|
||||
"thumbnail_image", "promo_image", "player_image"]
|
||||
const imageTypes = ["summary_photo_image", "player_image", "promo_image",
|
||||
"photo_image_full_size", "thumbnail_image", "thumbnail",
|
||||
"event_thumbnail"]
|
||||
let
|
||||
vals = ? js{"binding_values"}
|
||||
name = js{"name"}.getStr
|
||||
|
@ -172,19 +176,25 @@ proc parseCard(js: JsonNode; urls: JsonNode): Card =
|
|||
result.url = js{"url"}.getStr
|
||||
|
||||
case kind
|
||||
of promoVideo, promoVideoConvo:
|
||||
of promoVideoConvo, appPlayer:
|
||||
result.video = some parsePromoVideo(vals)
|
||||
if kind == appPlayer:
|
||||
result.text = vals{"app_category"}.getStrVal(result.text)
|
||||
of broadcast:
|
||||
result = parseBroadcast(vals)
|
||||
of liveEvent:
|
||||
result.text = vals{"event_title"}.getStrVal
|
||||
of player:
|
||||
result.url = vals{"player_url"}.getStrVal
|
||||
if "youtube.com" in result.url:
|
||||
result.url = result.url.replace("/embed/", "/watch?v=")
|
||||
of unified:
|
||||
result.title = "This card type is not supported."
|
||||
else: discard
|
||||
|
||||
for typ in imageTypes:
|
||||
with img, vals{typ & "_large"}:
|
||||
result.image = img{"image_value", "url"}.getStr
|
||||
result.image = img.getImageVal
|
||||
break
|
||||
|
||||
for u in ? urls:
|
||||
|
@ -192,6 +202,10 @@ proc parseCard(js: JsonNode; urls: JsonNode): Card =
|
|||
result.url = u{"expanded_url"}.getStr
|
||||
break
|
||||
|
||||
if kind in {promoImageConvo, promoImageApp} and result.url.len == 0 or
|
||||
result.url.startsWith("card://"):
|
||||
result.url = getPicUrl(result.image)
|
||||
|
||||
proc parseTweet(js: JsonNode): Tweet =
|
||||
if js.isNull: return
|
||||
result = Tweet(
|
||||
|
@ -223,9 +237,11 @@ proc parseTweet(js: JsonNode): Tweet =
|
|||
let name = jsCard{"name"}.getStr
|
||||
if "poll" in name:
|
||||
if "image" in name:
|
||||
result.photos.add jsCard{"binding_values", "image_large", "image_value", "url"}.getStr
|
||||
result.photos.add jsCard{"binding_values", "image_large"}.getImageVal
|
||||
|
||||
result.poll = some parsePoll(jsCard)
|
||||
elif name == "amplify":
|
||||
result.video = some(parsePromoVideo(jsCard{"binding_values"}))
|
||||
else:
|
||||
result.card = some parseCard(jsCard, js{"entities", "urls"})
|
||||
|
||||
|
|
|
@ -58,10 +58,15 @@ proc getId*(js: JsonNode): int64 {.inline.} =
|
|||
template getStrVal*(js: JsonNode; default=""): string =
|
||||
js{"string_value"}.getStr(default)
|
||||
|
||||
template getImageVal*(js: JsonNode; default=""): string =
|
||||
js{"image_value", "url"}.getStr(default)
|
||||
|
||||
proc getCardUrl*(js: JsonNode; kind: CardKind): string =
|
||||
result = js{"website_url"}.getStrVal
|
||||
if kind == promoVideoConvo:
|
||||
result = js{"thank_you_url"}.getStrVal(result)
|
||||
if result.startsWith("card://"):
|
||||
result = ""
|
||||
|
||||
proc getCardDomain*(js: JsonNode; kind: CardKind): string =
|
||||
result = js{"vanity_url"}.getStrVal(js{"domain"}.getStr)
|
||||
|
@ -72,6 +77,8 @@ proc getCardTitle*(js: JsonNode; kind: CardKind): string =
|
|||
result = js{"title"}.getStrVal
|
||||
if kind == promoVideoConvo:
|
||||
result = js{"thank_you_text"}.getStrVal(result)
|
||||
if kind == liveEvent:
|
||||
result = js{"event_category"}.getStrVal
|
||||
|
||||
proc getBanner*(js: JsonNode): string =
|
||||
let url = js{"profile_banner_url"}.getStr
|
||||
|
|
|
@ -101,24 +101,21 @@ type
|
|||
status*: string
|
||||
|
||||
CardKind* = enum
|
||||
amplify = "amplify"
|
||||
app = "app"
|
||||
appplayer = "appplayer"
|
||||
appPlayer = "appplayer"
|
||||
player = "player"
|
||||
audio = "audio"
|
||||
summary = "summary"
|
||||
summaryLarge = "summary_large_image"
|
||||
promoWebsite = "promo_website"
|
||||
promoVideo = "promo_video_website"
|
||||
promoVideoConvo = "promo_video_convo"
|
||||
promoImageConvo = "promo_image_convo"
|
||||
promoVideoApp = "promo_video_app"
|
||||
promoImageApp = "promo_image_app"
|
||||
amplify = "amplify"
|
||||
unified = "unified_card"
|
||||
storeLink = "direct_store_link_app"
|
||||
liveEvent = "live_event"
|
||||
broadcast = "broadcast"
|
||||
periscope = "periscope_broadcast"
|
||||
storeLink = "direct_store_link_app"
|
||||
unified = "unified_card"
|
||||
moment = "moment"
|
||||
messageMe = "message_me"
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ proc renderCardContent(card: Card): VNode =
|
|||
span(class="card-destination"): text card.dest
|
||||
|
||||
proc renderCard(card: Card; prefs: Prefs; path: string): VNode =
|
||||
const smallCards = {player, summary}
|
||||
const smallCards = {app, player, summary, storeLink}
|
||||
let large = if card.kind notin smallCards: " large" else: ""
|
||||
let url = replaceUrl(card.url, prefs)
|
||||
|
||||
|
|
Loading…
Reference in New Issue