From 18467b4cd333ab0b7aa10b1c1acd83942c583e60 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 3 Jul 2020 16:55:19 +0200 Subject: Add tab autocomplete for youtube --- src/plugins/Youtube.cpp | 70 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 16 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index c0180d8..3ab405c 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -3,6 +3,60 @@ #include namespace QuickMedia { + static void iterate_suggestion_result(const Json::Value &value, std::vector &result_items, int &iterate_count) { + ++iterate_count; + if(value.isArray()) { + for(const Json::Value &child : value) { + iterate_suggestion_result(child, result_items, iterate_count); + } + } else if(value.isString() && iterate_count > 2) { + result_items.push_back(value.asString()); + } + } + + std::string Youtube::autocomplete_search(const std::string &query) { + // Return the last result if the query is a substring of the autocomplete result + if(last_autocomplete_result.size() >= query.size() && memcmp(query.data(), last_autocomplete_result.data(), query.size()) == 0) + return last_autocomplete_result; + + std::string url = "https://clients1.google.com/complete/search?client=youtube&hl=en&gs_rn=64&gs_ri=youtube&ds=yt&cp=7&gs_id=x&q="; + url += url_param_encode(query); + + std::string server_response; + if(download_to_string(url, server_response, {}, use_tor, true) != DownloadResult::OK) + return query; + + size_t json_start = server_response.find_first_of('('); + if(json_start == std::string::npos) + return query; + ++json_start; + + size_t json_end = server_response.find_last_of(')'); + if(json_end == std::string::npos) + return query; + + if(json_end == 0 || json_start >= json_end) + return query; + + Json::Value json_root; + Json::CharReaderBuilder json_builder; + std::unique_ptr json_reader(json_builder.newCharReader()); + std::string json_errors; + if(!json_reader->parse(&server_response[json_start], &server_response[json_end], &json_root, &json_errors)) { + fprintf(stderr, "Youtube autocomplete search json error: %s\n", json_errors.c_str()); + return query; + } + + int iterate_count = 0; + std::vector result_items; + iterate_suggestion_result(json_root, result_items, iterate_count); + if(result_items.empty()) + return query; + + last_autocomplete_result = result_items[0]; + return result_items[0]; + } + static size_t find_end_of_json(const std::string &website_data, size_t data_start) { int brace_count = 0; char string_char = '\0'; @@ -228,14 +282,6 @@ namespace QuickMedia { } } - static std::string get_playlist_id_from_url(const std::string &url) { - std::string playlist_id = url; - size_t list_index = playlist_id.find("&list="); - if(list_index == std::string::npos) - return playlist_id; - return playlist_id.substr(list_index); - } - static std::string remove_index_from_playlist_url(const std::string &url) { std::string result = url; size_t index = result.rfind("&index="); @@ -280,14 +326,6 @@ namespace QuickMedia { BodyItems result_items; std::string modified_url = remove_index_from_playlist_url(url); - std::string playlist_id = get_playlist_id_from_url(modified_url); - if(playlist_id == last_related_media_playlist_id) { - result_items.reserve(last_playlist_data.size()); - for(auto &data : last_playlist_data) { - result_items.push_back(std::make_unique(*data)); - } - return result_items; - } std::string website_data; if(download_to_string(modified_url, website_data, {}, use_tor, true) != DownloadResult::OK) -- cgit v1.2.3