aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/Youtube.cpp229
1 files changed, 140 insertions, 89 deletions
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index c32e22e..3177f4d 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -676,29 +676,26 @@ namespace QuickMedia {
return "";
}
- static BodyItems parse_channel_videos(const Json::Value &json_root, std::string &continuation_token, std::unordered_set<std::string> &added_videos) {
- BodyItems body_items;
-
+ static void parse_channel_videos(const Json::Value &json_root, std::string &continuation_token, std::unordered_set<std::string> &added_videos, BodyItems &body_items) {
if(!json_root.isObject())
- return body_items;
+ return;
const Json::Value &response_json = json_root["response"];
if(!response_json.isObject())
- return body_items;
+ return;
const Json::Value &contents_json = response_json["contents"];
if(!contents_json.isObject())
- return body_items;
+ return;
const Json::Value &tcbrr_json = contents_json["twoColumnBrowseResultsRenderer"];
if(!tcbrr_json.isObject())
- return body_items;
+ return;
const Json::Value &tabs_json = tcbrr_json["tabs"];
if(!tabs_json.isArray())
- return body_items;
+ return;
- std::string new_continuation_token;
for(const Json::Value &tab_json : tabs_json) {
if(!tab_json.isObject())
continue;
@@ -747,8 +744,8 @@ namespace QuickMedia {
if(!item_json.isObject())
continue;
- if(new_continuation_token.empty())
- new_continuation_token = item_section_renderer_get_continuation_token(item_json);
+ if(continuation_token.empty())
+ continuation_token = item_section_renderer_get_continuation_token(item_json);
const Json::Value &grid_video_renderer = item_json["gridVideoRenderer"];
if(!grid_video_renderer.isObject())
@@ -761,9 +758,6 @@ namespace QuickMedia {
}
}
}
-
- continuation_token = std::move(new_continuation_token);
- return body_items;
}
static void parse_section_list_renderer(const Json::Value &section_list_renderer_json, std::string &continuation_token, BodyItems &result_items, std::unordered_set<std::string> &added_videos) {
@@ -875,6 +869,29 @@ namespace QuickMedia {
return PluginResult::OK;
}
+ static void search_page_submit_suggestion_handler(const Json::Value &json_item, std::string &continuation_token, BodyItems &result_items, std::unordered_set<std::string> &added_videos) {
+ if(!json_item.isObject())
+ return;
+
+ const Json::Value &response_json = json_item["response"];
+ if(!response_json.isObject())
+ return;
+
+ const Json::Value &contents_json = response_json["contents"];
+ if(!contents_json.isObject())
+ return;
+
+ const Json::Value &tcsrr_json = contents_json["twoColumnSearchResultsRenderer"];
+ if(!tcsrr_json.isObject())
+ return;
+
+ const Json::Value &primary_contents_json = tcsrr_json["primaryContents"];
+ if(!primary_contents_json.isObject())
+ return;
+
+ parse_section_list_renderer(primary_contents_json["sectionListRenderer"], continuation_token, result_items, added_videos);
+ }
+
PluginResult YoutubeSearchPage::submit_suggestion(const SubmitArgs &args, BodyItems &result_items) {
continuation_token.clear();
current_page = 0;
@@ -897,26 +914,17 @@ namespace QuickMedia {
DownloadResult result = download_json(json_root, search_url + "&pbj=1&gl=US&hl=en", std::move(additional_args), true);
if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
- if(!json_root.isObject())
- return PluginResult::ERR;
-
- const Json::Value &response_json = json_root["response"];
- if(!response_json.isObject())
- return PluginResult::OK;
-
- const Json::Value &contents_json = response_json["contents"];
- if(!contents_json.isObject())
- return PluginResult::OK;
-
- const Json::Value &tcsrr_json = contents_json["twoColumnSearchResultsRenderer"];
- if(!tcsrr_json.isObject())
+ if(json_root.isObject()) {
+ search_page_submit_suggestion_handler(json_root, continuation_token, result_items, added_videos);
return PluginResult::OK;
+ }
- const Json::Value &primary_contents_json = tcsrr_json["primaryContents"];
- if(!primary_contents_json.isObject())
- return PluginResult::OK;
+ if(!json_root.isArray())
+ return PluginResult::ERR;
- parse_section_list_renderer(primary_contents_json["sectionListRenderer"], continuation_token, result_items, added_videos);
+ for(const Json::Value &json_item : json_root) {
+ search_page_submit_suggestion_handler(json_item, continuation_token, result_items, added_videos);
+ }
return PluginResult::OK;
}
@@ -926,39 +934,18 @@ namespace QuickMedia {
return PluginResult::OK;
}
- PluginResult YoutubeSearchPage::search_get_continuation(const std::string &url, const std::string &current_continuation_token, BodyItems &result_items) {
- if(current_continuation_token.empty())
- return PluginResult::OK;
-
- std::string next_url = url + "&pbj=1&gl=US&hl=en&ctoken=" + current_continuation_token;
-
- std::vector<CommandArg> additional_args = {
- { "-H", "x-spf-referer: " + url },
- { "-H", "x-youtube-client-name: 1" },
- { "-H", "x-spf-previous: " + url },
- { "-H", youtube_client_version },
- { "-H", "referer: " + url }
- };
-
- std::vector<CommandArg> cookies = get_cookies();
- additional_args.insert(additional_args.end(), cookies.begin(), cookies.end());
-
- Json::Value json_root;
- DownloadResult result = download_json(json_root, next_url, std::move(additional_args), true);
- if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
-
- if(!json_root.isObject())
- return PluginResult::ERR;
+ static void search_page_search_get_continuation(const Json::Value &json_item, std::string &new_continuation_token, std::unordered_set<std::string> &added_videos, BodyItems &result_items) {
+ if(!json_item.isObject())
+ return;
- const Json::Value &response_json = json_root["response"];
+ const Json::Value &response_json = json_item["response"];
if(!response_json.isObject())
- return PluginResult::OK;
+ return;
const Json::Value &on_response_received_commands_json = response_json["onResponseReceivedCommands"];
if(!on_response_received_commands_json.isArray())
- return PluginResult::OK;
+ return;
- std::string new_continuation_token;
for(const Json::Value &response_received_command : on_response_received_commands_json) {
if(!response_received_command.isObject())
continue;
@@ -987,6 +974,42 @@ namespace QuickMedia {
parse_item_section_renderer(item_section_renderer_json, added_videos, result_items);
}
}
+ }
+
+ PluginResult YoutubeSearchPage::search_get_continuation(const std::string &url, const std::string &current_continuation_token, BodyItems &result_items) {
+ if(current_continuation_token.empty())
+ return PluginResult::OK;
+
+ std::string next_url = url + "&pbj=1&gl=US&hl=en&ctoken=" + current_continuation_token;
+ std::string new_continuation_token;
+
+ std::vector<CommandArg> additional_args = {
+ { "-H", "x-spf-referer: " + url },
+ { "-H", "x-youtube-client-name: 1" },
+ { "-H", "x-spf-previous: " + url },
+ { "-H", youtube_client_version },
+ { "-H", "referer: " + url }
+ };
+
+ std::vector<CommandArg> cookies = get_cookies();
+ additional_args.insert(additional_args.end(), cookies.begin(), cookies.end());
+
+ Json::Value json_root;
+ DownloadResult result = download_json(json_root, next_url, std::move(additional_args), true);
+ if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
+
+ if(json_root.isObject()) {
+ search_page_search_get_continuation(json_root, new_continuation_token, added_videos, result_items);
+ continuation_token = std::move(new_continuation_token);
+ return PluginResult::OK;
+ }
+
+ if(!json_root.isArray())
+ return PluginResult::ERR;
+
+ for(const Json::Value &json_item : json_root) {
+ search_page_search_get_continuation(json_item, new_continuation_token, added_videos, result_items);
+ }
continuation_token = std::move(new_continuation_token);
return PluginResult::OK;
@@ -1538,6 +1561,8 @@ namespace QuickMedia {
PluginResult YoutubeChannelPage::lazy_fetch(BodyItems &result_items) {
added_videos.clear();
+ continuation_token.clear();
+
std::vector<CommandArg> additional_args = {
{ "-H", "x-spf-referer: " + url },
{ "-H", "x-youtube-client-name: 1" },
@@ -1552,7 +1577,19 @@ namespace QuickMedia {
Json::Value json_root;
DownloadResult result = download_json(json_root, url + "/videos?pbj=1&gl=US&hl=en", std::move(additional_args), true);
if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
- result_items = parse_channel_videos(json_root, continuation_token, added_videos);
+
+ if(json_root.isObject()) {
+ parse_channel_videos(json_root, continuation_token, added_videos, result_items);
+ return PluginResult::OK;
+ }
+
+ if(!json_root.isArray())
+ return PluginResult::ERR;
+
+ for(const Json::Value &json_item : json_root) {
+ parse_channel_videos(json_item, continuation_token, added_videos, result_items);
+ }
+
return PluginResult::OK;
}
@@ -1874,58 +1911,36 @@ namespace QuickMedia {
return std::to_string(it->second.time_pos_sec);
}
- BodyItems YoutubeVideoPage::get_related_media(const std::string &url) {
- comments_continuation_token.clear();
- BodyItems result_items;
-
- std::string video_id;
- if(!youtube_url_extract_id(url, video_id)) {
- fprintf(stderr, "Failed to extract youtube id from %s\n", url.c_str());
- return result_items;
- }
-
- std::vector<CommandArg> additional_args = {
- { "-H", "x-youtube-client-name: 1" },
- { "-H", youtube_client_version },
- };
-
- std::vector<CommandArg> cookies = get_cookies();
- additional_args.insert(additional_args.end(), cookies.begin(), cookies.end());
-
- // TODO: Remove this code completely and replace with existing player? api
- Json::Value json_root;
- DownloadResult download_result = download_json(json_root, "https://www.youtube.com/watch?v=" + video_id + "&pbj=1&gl=US&hl=en", additional_args, true);
- if(download_result != DownloadResult::OK) return result_items;
-
+ static void video_page_related_media_handler(const Json::Value &json_root, std::string &comments_continuation_token, BodyItems &result_items) {
if(!json_root.isObject())
- return result_items;
+ return;
const Json::Value &response_json = json_root["response"];
if(!response_json.isObject())
- return result_items;
+ return;
const Json::Value &contents_json = response_json["contents"];
if(!contents_json.isObject())
- return result_items;
+ return;
const Json::Value &tcwnr_json = contents_json["twoColumnWatchNextResults"];
if(!tcwnr_json.isObject())
- return result_items;
+ return;
if(comments_continuation_token.empty())
comments_continuation_token = two_column_watch_next_results_get_comments_continuation_token(tcwnr_json);
const Json::Value &secondary_results_json = tcwnr_json["secondaryResults"];
if(!secondary_results_json.isObject())
- return result_items;
+ return;
const Json::Value &secondary_results2_json = secondary_results_json["secondaryResults"];
if(!secondary_results2_json.isObject())
- return result_items;
+ return;
const Json::Value &results_json = secondary_results2_json["results"];
if(!results_json.isArray())
- return result_items;
+ return;
std::unordered_set<std::string> added_videos;
for(const Json::Value &item_json : results_json) {
@@ -1953,6 +1968,42 @@ namespace QuickMedia {
result_items.push_back(std::move(body_item));
}
}
+ }
+
+ BodyItems YoutubeVideoPage::get_related_media(const std::string &url) {
+ comments_continuation_token.clear();
+ BodyItems result_items;
+
+ std::string video_id;
+ if(!youtube_url_extract_id(url, video_id)) {
+ fprintf(stderr, "Failed to extract youtube id from %s\n", url.c_str());
+ return result_items;
+ }
+
+ std::vector<CommandArg> additional_args = {
+ { "-H", "x-youtube-client-name: 1" },
+ { "-H", youtube_client_version },
+ };
+
+ std::vector<CommandArg> cookies = get_cookies();
+ additional_args.insert(additional_args.end(), cookies.begin(), cookies.end());
+
+ // TODO: Remove this code completely and replace with existing player? api
+ Json::Value json_root;
+ DownloadResult download_result = download_json(json_root, "https://www.youtube.com/watch?v=" + video_id + "&pbj=1&gl=US&hl=en", additional_args, true);
+ if(download_result != DownloadResult::OK) return result_items;
+
+ if(json_root.isObject()) {
+ video_page_related_media_handler(json_root, comments_continuation_token, result_items);
+ return result_items;
+ }
+
+ if(!json_root.isArray())
+ return result_items;
+
+ for(const Json::Value &json_item : json_root) {
+ video_page_related_media_handler(json_item, comments_continuation_token, result_items);
+ }
return result_items;
}