From b5c6432fbf3b12d1a65fdfded14c49abb49bc93c Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 28 Oct 2022 13:35:52 +0200 Subject: Youtube: fix channel page not loading (jesus what a clusterfuck) --- src/plugins/Youtube.cpp | 133 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 31 deletions(-) (limited to 'src/plugins/Youtube.cpp') diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index caf3a25..4dbb6c4 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -691,11 +691,11 @@ namespace QuickMedia { if(!json_root.isObject()) return; - const Json::Value &response_json = json_root["response"]; - if(!response_json.isObject()) - return; + const Json::Value *response_json = &json_root["response"]; + if(!response_json->isObject()) + response_json = &json_root; - const Json::Value &contents_json = response_json["contents"]; + const Json::Value &contents_json = (*response_json)["contents"]; if(!contents_json.isObject()) return; @@ -720,8 +720,41 @@ namespace QuickMedia { continue; const Json::Value §ion_list_renderer = content_json["sectionListRenderer"]; - if(!section_list_renderer.isObject()) + if(!section_list_renderer.isObject()) { + const Json::Value &rich_grid_renderer_json = content_json["richGridRenderer"]; + if(!rich_grid_renderer_json.isObject()) + continue; + + const Json::Value &contents2_json = rich_grid_renderer_json["contents"]; + if(!contents2_json.isArray()) + continue; + + for(const Json::Value &content_item_json : contents2_json) { + if(!content_item_json.isObject()) + continue; + + if(continuation_token.empty()) + continuation_token = item_section_renderer_get_continuation_token(content_item_json); + + const Json::Value &rich_item_renderer_json = content_item_json["richItemRenderer"]; + if(!rich_item_renderer_json.isObject()) + continue; + + const Json::Value &item_content_json = rich_item_renderer_json["content"]; + if(!item_content_json.isObject()) + continue; + + const Json::Value &video_renderer_json = item_content_json["videoRenderer"]; + if(!video_renderer_json.isObject()) + continue; + + auto body_item = parse_common_video_item(video_renderer_json, added_videos); + if(body_item) + body_items.push_back(std::move(body_item)); + } + continue; + } const Json::Value &contents2_json = section_list_renderer["contents"]; if(!contents2_json.isArray()) @@ -1487,6 +1520,43 @@ namespace QuickMedia { return PluginResult::OK; } + static void channel_page_continuation_get_content(const Json::Value &continuation_items_json, std::string &new_continuation_token, std::unordered_set &added_videos, BodyItems &result_items) { + if(!continuation_items_json.isArray()) + return; + + for(const Json::Value &item_json : continuation_items_json) { + if(!item_json.isObject()) + continue; + + if(new_continuation_token.empty()) + new_continuation_token = item_section_renderer_get_continuation_token(item_json); + + const Json::Value &grid_video_renderer_json = item_json["gridVideoRenderer"]; + const Json::Value &item_section_renderer_json = item_json["itemSectionRenderer"]; + const Json::Value &rich_item_renderer_json = item_json["richItemRenderer"]; + + if(grid_video_renderer_json.isObject()) { + auto body_item = parse_common_video_item(grid_video_renderer_json, added_videos); + if(body_item) + result_items.push_back(std::move(body_item)); + } else if(item_section_renderer_json.isObject()) { + parse_item_section_renderer(item_section_renderer_json, added_videos, result_items); + } else if(rich_item_renderer_json.isObject()) { + const Json::Value &content_json = rich_item_renderer_json["content"]; + if(!content_json.isObject()) + continue; + + const Json::Value &video_renderer_json = content_json["videoRenderer"]; + if(!video_renderer_json.isObject()) + continue; + + auto body_item = parse_common_video_item(video_renderer_json, added_videos); + if(body_item) + result_items.push_back(std::move(body_item)); + } + } + } + PluginResult YoutubeChannelPage::search_get_continuation(const std::string &url, const std::string ¤t_continuation_token, BodyItems &result_items) { if(current_continuation_token.empty()) return PluginResult::OK; @@ -1534,38 +1604,37 @@ namespace QuickMedia { if(!json_root.isObject()) return PluginResult::ERR; - const Json::Value &on_response_received_actions_json = json_root["onResponseReceivedActions"]; - if(!on_response_received_actions_json.isArray()) - return PluginResult::ERR; - std::string new_continuation_token; - for(const Json::Value &json_item : on_response_received_actions_json) { - if(!json_item.isObject()) - continue; - - const Json::Value &append_continuation_items_action_json = json_item["appendContinuationItemsAction"]; - if(!append_continuation_items_action_json.isObject()) - continue; + result_items.clear(); - const Json::Value &continuation_items_json = append_continuation_items_action_json["continuationItems"]; - if(!continuation_items_json.isArray()) - continue; + const Json::Value &on_response_received_actions_json = json_root["onResponseReceivedActions"]; + if(on_response_received_actions_json.isArray()) { + for(const Json::Value &json_item : on_response_received_actions_json) { + if(!json_item.isObject()) + continue; - for(const Json::Value &item_json : continuation_items_json) { - if(!item_json.isObject()) + const Json::Value &append_continuation_items_action_json = json_item["appendContinuationItemsAction"]; + if(!append_continuation_items_action_json.isObject()) continue; - if(new_continuation_token.empty()) - new_continuation_token = item_section_renderer_get_continuation_token(item_json); + channel_page_continuation_get_content(append_continuation_items_action_json["continuationItems"], new_continuation_token, added_videos, result_items); + } + } else { + // What a cluster-fuck. Sometimes youtube returns the same front page twice, so we try to parse it + // and if we dont get any new items then request the page again (I hope we got a new continuation key???). - const Json::Value &grid_video_renderer = item_json["gridVideoRenderer"]; - if(grid_video_renderer.isObject()) { - auto body_item = parse_common_video_item(grid_video_renderer, added_videos); - if(body_item) - result_items.push_back(std::move(body_item)); - } else { - parse_item_section_renderer(item_json["itemSectionRenderer"], added_videos, result_items); - } + const Json::Value &continuation_contents_json = json_root["continuationContents"]; + if(!continuation_contents_json.isObject()) + return PluginResult::ERR; + + const Json::Value &rich_grid_continuation_json = continuation_contents_json["richGridContinuation"]; + if(!rich_grid_continuation_json.isObject()) + return PluginResult::ERR; + + channel_page_continuation_get_content(rich_grid_continuation_json["contents"], new_continuation_token, added_videos, result_items); + if(result_items.empty()) { // Hopefully we dont have an infinite loop... + continuation_token = std::move(new_continuation_token); + return search_get_continuation(url, current_continuation_token, result_items); } } @@ -1600,6 +1669,7 @@ namespace QuickMedia { if(result != DownloadResult::OK) return download_result_to_plugin_result(result); if(json_root.isObject()) { + search_page_submit_suggestion_handler(json_root, continuation_token, result_items, added_videos); parse_channel_videos(json_root, continuation_token, added_videos, result_items); return PluginResult::OK; } @@ -1608,6 +1678,7 @@ namespace QuickMedia { return PluginResult::ERR; for(const Json::Value &json_item : json_root) { + search_page_submit_suggestion_handler(json_root, continuation_token, result_items, added_videos); parse_channel_videos(json_item, continuation_token, added_videos, result_items); } -- cgit v1.2.3