From 561d446e6871b7aa80c71357d8b2ccf78e4a6a7b Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 24 Jul 2021 23:28:25 +0200 Subject: Fix youtube copyrighted videos (revert back to watch?v= url) --- TODO | 3 +- depends/html-search | 2 +- plugins/Youtube.hpp | 3 +- src/QuickMedia.cpp | 2 +- src/VideoPlayer.cpp | 6 ++-- src/plugins/Youtube.cpp | 58 ++++++++++++++++----------------------- src/plugins/youtube/Signature.cpp | 3 +- 7 files changed, 31 insertions(+), 46 deletions(-) diff --git a/TODO b/TODO index e2d755d..066f811 100644 --- a/TODO +++ b/TODO @@ -174,5 +174,4 @@ Add option to view dead link in 4chan with 4chan archive and navigate to crossbo Show latest message before sync is done for a room when the latest message is an edit. Right now it has to fetch previous messages until the first non-edit message. Allow resuming downloads. Support downloading live youtube videos. -Youtube broke age restricted video again. Need to find a fix. It kinda works in yt-dlp, but not always. -Youtube broke copyrighted videos again... \ No newline at end of file +Youtube broke age restricted video again. Need to find a fix. It kinda works in yt-dlp, but not always. \ No newline at end of file diff --git a/depends/html-search b/depends/html-search index b62b5aa..9cafc14 160000 --- a/depends/html-search +++ b/depends/html-search @@ -1 +1 @@ -Subproject commit b62b5aa8a262d3f4e2c53c5fd5b67410106bca82 +Subproject commit 9cafc14e2508224c901f5a03bb6fda73f0c51e57 diff --git a/plugins/Youtube.hpp b/plugins/Youtube.hpp index c89d68d..50412de 100644 --- a/plugins/Youtube.hpp +++ b/plugins/Youtube.hpp @@ -149,8 +149,7 @@ namespace QuickMedia { PluginResult load(std::string &title, std::string &channel_url, std::vector &chapters) override; void mark_watched() override; private: - PluginResult get_video_info(const std::string &video_id, Json::Value &json_root); - PluginResult parse_video_response(Json::Value &json_root, std::string &title, std::string &channel_url, std::vector &chapters); + PluginResult parse_video_response(const Json::Value &json_root, std::string &title, std::string &channel_url, std::vector &chapters); void parse_format(const Json::Value &format_json, bool is_adaptive); void parse_formats(const Json::Value &streaming_data_json); private: diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index dfb7770..07d6640 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -2309,7 +2309,7 @@ namespace QuickMedia { unsigned long num_items = 0; unsigned long bytes_after = 0; unsigned char *properties = nullptr; - if(XGetWindowProperty(display, window, wm_state_atom, 0, 1024, False, XA_ATOM, &type, &format, &num_items, &bytes_after, &properties) != Success || !properties) { + if(XGetWindowProperty(display, window, wm_state_atom, 0, 1024, False, XA_ATOM, &type, &format, &num_items, &bytes_after, &properties) < Success || !properties) { fprintf(stderr, "Failed to get window wm state property\n"); return false; } diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp index ba7fb81..98d215d 100644 --- a/src/VideoPlayer.cpp +++ b/src/VideoPlayer.cpp @@ -262,9 +262,9 @@ namespace QuickMedia { std::vector result; Window root_window; Window parent_window; - Window *child_window; - unsigned int num_children; - if(XQueryTree(display, window, &root_window, &parent_window, &child_window, &num_children)) { + Window *child_window = nullptr; + unsigned int num_children = 0; + if(XQueryTree(display, window, &root_window, &parent_window, &child_window, &num_children) && child_window) { for(unsigned int i = 0; i < num_children; i++) result.push_back(child_window[i]); XFree(child_window); diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index 4544a45..7e5bd7b 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -2274,29 +2274,7 @@ R"END( return result; } - // TODO: Extract innertube_api_key from response? - PluginResult YoutubeVideoPage::get_video_info(const std::string &video_id, Json::Value &json_root) { - std::vector additional_args = get_cookies(); - - std::string response; - DownloadResult download_result = download_to_string("https://www.youtube.com/get_video_info?html5=1&c=TVHTML5&cver=6.20180913&gl=US&hl=en&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::CharReaderBuilder json_builder; - std::unique_ptr 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; - } - - return PluginResult::OK; - } - - PluginResult YoutubeVideoPage::parse_video_response(Json::Value &json_root, std::string &title, std::string &channel_url, std::vector &chapters) { + PluginResult YoutubeVideoPage::parse_video_response(const Json::Value &json_root, std::string &title, std::string &channel_url, std::vector &chapters) { livestream_url.clear(); video_formats.clear(); audio_formats.clear(); @@ -2409,24 +2387,34 @@ R"END( return PluginResult::ERR; } - std::string request_data = key_api_request_data; - string_replace_all(request_data, "%VIDEO_ID%", video_id); - std::vector additional_args = { - { "-H", "Content-Type: application/json" }, { "-H", "x-youtube-client-name: 1" }, { "-H", youtube_client_version }, - { "--data-raw", std::move(request_data) } }; std::vector 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/youtubei/v1/player?key=" + api_key + "&gl=US&hl=en", additional_args, true); + 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 download_result_to_plugin_result(download_result); - return parse_video_response(json_root, title, channel_url, chapters); + if(!json_root.isArray()) + return PluginResult::ERR; + + for(const Json::Value &json_item : json_root) { + if(!json_item.isObject()) + continue; + + const Json::Value &player_response_json = json_item["playerResponse"]; + if(!player_response_json.isObject()) + continue; + + return parse_video_response(player_response_json, title, channel_url, chapters); + } + + return PluginResult::ERR; } void YoutubeVideoPage::mark_watched() { @@ -2462,7 +2450,7 @@ R"END( cipher_params = http_params_parse(signature_cipher_json.asString()); } - const std::string &url = cipher_params["url"]; + std::string &url = cipher_params["url"]; if(url.empty()) return false; @@ -2471,17 +2459,17 @@ R"END( return true; } - std::string url_decoded = url_param_decode(url); - url_decoded += "&alr=yes&cver=2.20210615.01.00&cpn=" + cpn; + //std::string url_decoded = url_param_decode(url); + //url_decoded += "&alr=yes&cver=2.20210615.01.00&cpn=" + cpn; const std::string &s = cipher_params["s"]; const std::string &sp = cipher_params["sp"]; std::string sig_key; std::string sig_value; if(YoutubeSignatureDecryptor::get_instance().decrypt(s, sp, sig_key, sig_value)) - url_decoded += "&" + std::move(sig_key) + "=" + std::move(sig_value); + url += "&" + std::move(sig_key) + "=" + std::move(sig_value); - youtube_format.url = std::move(url_decoded); + youtube_format.url = std::move(url); return true; } diff --git a/src/plugins/youtube/Signature.cpp b/src/plugins/youtube/Signature.cpp index 7631182..59385ad 100644 --- a/src/plugins/youtube/Signature.cpp +++ b/src/plugins/youtube/Signature.cpp @@ -4,7 +4,6 @@ #include "../../../include/DownloadUtils.hpp" #include "../../../include/StringUtils.hpp" #include "../../../include/Program.hpp" -#include "../../../include/NetUtils.hpp" #include #include #include @@ -254,7 +253,7 @@ namespace QuickMedia { } sig_key = sp; - sig_value = url_param_encode(sig); + sig_value = sig;//url_param_encode(sig); return true; } -- cgit v1.2.3