feat: playlist browsing
pagination still needs refinement for some of the clients. on another note, this is an anniversary commit, as ythdd turns 1 year today.
This commit is contained in:
@@ -312,6 +312,34 @@ def parseRenderers(entry: dict, context: dict = {}) -> dict:
|
||||
"descriptionHtml": description_html
|
||||
}
|
||||
|
||||
case "playlistVideoRenderer":
|
||||
|
||||
video_id = safeTraverse(entry, ["playlistVideoRenderer", "videoId"], default="UnknownVideoId")
|
||||
title = safeTraverse(entry, ["playlistVideoRenderer", "title", "runs", 0, "text"], default="Unknown video title")
|
||||
author_ucid = safeTraverse(entry, ["playlistVideoRenderer", "shortBylineText", "runs", 0, "navigationEndpoint", "browseEndpoint", "browseId"], default="UNKNOWNCHANNELID")
|
||||
author_name = safeTraverse(entry, ["playlistVideoRenderer", "shortBylineText", "runs", 0, "text"], default="Unknown author")
|
||||
video_index = int(safeTraverse(entry, ["playlistVideoRenderer", "index", "simpleText"], default="1")) - 1
|
||||
length = parseLengthFromTimeBadge(safeTraverse(entry, ["playlistVideoRenderer", "lengthText", "simpleText"], default="0:0"))
|
||||
published_date = safeTraverse(entry, ["playlistVideoRenderer", "videoInfo", "runs", -1, "text"], default="2000-01-01")
|
||||
published_date = published_date.removeprefix("Streamed ")
|
||||
|
||||
return {
|
||||
"type": "video",
|
||||
"title": title,
|
||||
"videoId": video_id,
|
||||
"author": author_name,
|
||||
"authorId": author_ucid,
|
||||
"authorUrl": "/channel/" + author_ucid,
|
||||
"videoThumbnails": genThumbs(video_id),
|
||||
"index": video_index,
|
||||
"lengthSeconds": length,
|
||||
"liveNow": False, # todo: check this?
|
||||
# these do not need to be returned, but some clients try to read it
|
||||
# so we return an approximation here:
|
||||
"published": int(dateparser.parse(published_date).timestamp()),
|
||||
"publishedText": published_date
|
||||
}
|
||||
|
||||
case _:
|
||||
print("received an entry of unknown type:")
|
||||
print(entry)
|
||||
@@ -372,3 +400,27 @@ def parseDescriptionSnippet(snippet: list):
|
||||
text_html = escape(text_html).replace("\r\n", "<br>").replace("\n", "<br>")
|
||||
|
||||
return text, text_html
|
||||
|
||||
def runsToText(runs: list, default: str = "") -> str:
|
||||
# "default" will be returned when text extraction fails.
|
||||
extracted_text = ""
|
||||
|
||||
for field in runs:
|
||||
extracted_text += safeTraverse(field, ["text"], default="")
|
||||
|
||||
if extracted_text:
|
||||
return extracted_text
|
||||
|
||||
return default
|
||||
|
||||
def extractTextFromSimpleOrRuns(obj: dict, default: str = "") -> str:
|
||||
# Extracts the text both from "runs" and "simpleText"
|
||||
# with failsafe to default.
|
||||
text = default
|
||||
if "runs" in obj:
|
||||
text = runsToText(obj["runs"])
|
||||
elif "simpleText" in obj:
|
||||
text = obj["simpleText"]
|
||||
else:
|
||||
print(f"error(extractTextFromSimpleOrRuns): text extraction failed for {obj}")
|
||||
return text
|
||||
|
||||
Reference in New Issue
Block a user