diff --git a/ythdd_inv_tl.py b/ythdd_inv_tl.py index 285e55d..6c10ccc 100644 --- a/ythdd_inv_tl.py +++ b/ythdd_inv_tl.py @@ -454,11 +454,15 @@ def videos(data): author = safeTraverse(video_details, ['author'], default="Unknown Author") ucid = safeTraverse(video_details, ['channelId'], default="UNKNOWNCHANNELID") subs = ydata['channel_follower_count'] - author_thumbnail = ythdd_extractor.generateChannelAvatarsFromUrl(safeTraverse(video_secondary_renderer, ['owner', 'videoOwnerRenderer', 'thumbnail', 'thumbnails', 0, 'url'], default=DEFAULT_AVATAR)) - - # so far it seems to be impossible to tell if a channel is verified or not, - # that is - without making another request + author_thumbnail = safeTraverse(video_secondary_renderer, ['owner', 'videoOwnerRenderer', 'thumbnail', 'thumbnails', 0, 'url']) author_verified = ythdd_extractor.isVerified(safeTraverse(video_secondary_renderer, ['owner', 'videoOwnerRenderer', 'badges', 0], default=[])) + if author_thumbnail is None: + # there might be multiple authors (on a collaborative video) + # if so, then try to extract first channel's (uploader's) avatar + livm = safeTraverse(video_secondary_renderer, ["owner", "videoOwnerRenderer", "attributedTitle", "commandRuns", 0, "onTap", "innertubeCommand", "showDialogCommand", "panelLoadingStrategy", "inlineContent", "dialogViewModel", "customContent", "listViewModel", "listItems"], default=[]) + author_thumbnail = safeTraverse(livm, [0, "listItemViewModel", "leadingAccessory", "avatarViewModel", "image", "sources", 0, "url"], default=DEFAULT_AVATAR) + author_verified = author_verified or safeTraverse(livm, [0, "listItemViewModel", "title", "attachmentRuns", 0, "element", "type", "imageType", "image", "sources", 0, "clientResource", "imageName"]) in ("AUDIO_BADGE", "CHECK_CIRCLE_FILLED") + author_thumbnail = ythdd_extractor.generateChannelAvatarsFromUrl(author_thumbnail) format_streams = [] # adaptive_formats, format_streams = rebuildFormats(adaptive_formats) diff --git a/ythdd_struct_parser.py b/ythdd_struct_parser.py index 692fc75..8a5f1e8 100644 --- a/ythdd_struct_parser.py +++ b/ythdd_struct_parser.py @@ -346,7 +346,7 @@ def parseRenderers(entry: dict, context: dict = {}) -> dict: 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_ucid = safeTraverse(entry, ["playlistVideoRenderer", "shortBylineText", "runs", 0, "navigationEndpoint", "browseEndpoint", "browseId"]) 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")) @@ -357,6 +357,20 @@ def parseRenderers(entry: dict, context: dict = {}) -> dict: if not published_date: published_date = "now" + if author_ucid is None: + # likely a collaborative video, let's try + # to fetch the uploader's ucid with that in mind + livm = safeTraverse(entry, ["playlistVideoRenderer", "shortBylineText", "runs", 0, "navigationEndpoint", "showDialogCommand", "panelLoadingStrategy", "inlineContent", "dialogViewModel", "customContent", "listViewModel", "listItems"], default=[]) + # name extraction logic the same as in videoRenderer + all_authors = [] + for collaborative_author in livm: + collaborative_author_name = safeTraverse(collaborative_author, ["listItemViewModel", "title", "content"]) + if collaborative_author_name is not None: + all_authors.append(collaborative_author_name) + if all_authors != []: + author_name = ", ".join(all_authors) + author_ucid = safeTraverse(livm, [0, "listItemViewModel", "title", "commandRuns", 0, "onTap", "innertubeCommand", "browseEndpoint", "browseId"], default="UNKNOWNCHANNELID") + return { "type": "video", "title": title,