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