aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Youtube.cpp79
1 files changed, 64 insertions, 15 deletions
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index f113e0c..7e71830 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -374,7 +374,7 @@ namespace QuickMedia {
return (c >= 8 && c <= 13) || c == ' ';
}
- // TODO: Cache this and redownload it when a network request fails with this api key?
+ // TODO: Cache this and redownload it when a network request fails with this api key? Do that in the same place as the signature, which means it would be done asynchronously
static std::string youtube_page_find_api_key() {
size_t api_key_index;
size_t api_key_index_end;
@@ -1911,21 +1911,70 @@ namespace QuickMedia {
std::vector<CommandArg> cookies = get_cookies();
additional_args.insert(additional_args.end(), cookies.begin(), cookies.end());
- std::string response;
- DownloadResult download_result = download_to_string("https://www.youtube.com/get_video_info?html5=1&video_id=" + video_id + "&eurl=https://www.youtube.googleapis.com/v/" + video_id, response, std::move(additional_args), true);
- if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
-
- std::string player_response_param = url_extract_param(response, "player_response");
- player_response_param = url_param_decode(player_response_param);
-
Json::Value json_root;
- Json::CharReaderBuilder json_builder;
- std::unique_ptr<Json::CharReader> json_reader(json_builder.newCharReader());
- std::string json_errors;
- if(!json_reader->parse(player_response_param.data(), player_response_param.data() + player_response_param.size(), &json_root, &json_errors)) {
- fprintf(stderr, "Failed to read param as json, error: %s\n", json_errors.c_str());
- return PluginResult::ERR;
- }
+ std::string request_data =
+R"END(
+{
+ "context": {
+ "client": {
+ "hl": "en",
+ "gl": "US",
+ "deviceMake": "",
+ "deviceModel": "",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0,gzip(gfe)",
+ "clientName": "WEB",
+ "clientVersion": "2.20210615.01.00",
+ "osName": "Windows",
+ "osVersion": "10.0",
+ "originalUrl": "https://www.youtube.com/watch?v=%VIDEO_ID%",
+ "platform": "DESKTOP",
+ "clientFormFactor": "UNKNOWN_FORM_FACTOR",
+ "timeZone": "UTC",
+ "browserName": "Firefox",
+ "browserVersion": "78.0",
+ "screenWidthPoints": 1054,
+ "screenHeightPoints": 289,
+ "screenPixelDensity": 1,
+ "screenDensityFloat": 1,
+ "utcOffsetMinutes": 0,
+ "userInterfaceTheme": "USER_INTERFACE_THEME_LIGHT",
+ "clientScreen": "WATCH",
+ "mainAppWebInfo": {
+ "graftUrl": "/watch?v=%VIDEO_ID%",
+ "webDisplayMode": "WEB_DISPLAY_MODE_BROWSER",
+ "isWebNativeShareAvailable": false
+ }
+ },
+ "user": {
+ "lockedSafetyMode": false
+ },
+ "request": {
+ "useSsl": true,
+ "internalExperimentFlags": [],
+ "consistencyTokenJars": []
+ }
+ },
+ "videoId": "%VIDEO_ID%",
+ "playbackContext": {
+ "contentPlaybackContext": {
+ "currentUrl": "/watch?v=%VIDEO_ID%",
+ "vis": 0,
+ "splay": false,
+ "autoCaptionsDefaultOn": false,
+ "autonavState": "STATE_NONE",
+ "html5Preference": "HTML5_PREF_WANTS"
+ }
+ },
+ "racyCheckOk": false,
+ "contentCheckOk": false
+}
+)END";
+ string_replace_all(request_data, "%VIDEO_ID%", video_id);
+ additional_args.push_back({ "-H", "Content-Type: application/json" });
+ additional_args.push_back({ "--data-raw", std::move(request_data) });
+
+ DownloadResult download_result = download_json(json_root, "https://www.youtube.com/youtubei/v1/player?key=" + api_key, additional_args, true);
+ if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
if(!json_root.isObject())
return PluginResult::ERR;