diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | plugins/Youtube.hpp | 2 | ||||
-rw-r--r-- | src/plugins/Youtube.cpp | 180 |
3 files changed, 4 insertions, 181 deletions
@@ -212,4 +212,5 @@ Improve pinephone video load performance by not restarting mpv on next video. In Very large resolutions, such as 7680x2160 (id 272) for video https://www.youtube.com/watch?v=GxaH40zpvYc are not supported by the youtube android video loader. Find a way to fix that. Use std::move(string) for all places where text.set_string is called. Use reference for text.get_string() in all places. -Cleanup font sizes that are not visible (or not used for a while). Also do the same for character ranges font texture.
\ No newline at end of file +Cleanup font sizes that are not visible (or not used for a while). Also do the same for character ranges font texture. +Show video upload date in video description on youtube.
\ No newline at end of file diff --git a/plugins/Youtube.hpp b/plugins/Youtube.hpp index 2a3b36e..53fb3b7 100644 --- a/plugins/Youtube.hpp +++ b/plugins/Youtube.hpp @@ -27,7 +27,6 @@ namespace QuickMedia { struct YoutubeVideoDetails { std::string title; std::string author; - std::string rating; std::string views; std::string description; }; @@ -174,7 +173,6 @@ namespace QuickMedia { private: std::string timestamp; std::string comments_continuation_token; - int64_t num_likes = -1; std::string livestream_url; std::vector<YoutubeVideoFormat> video_formats; std::vector<YoutubeAudioFormat> audio_formats; diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index 8ffaebf..9a9ed81 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -75,49 +75,6 @@ namespace QuickMedia { static std::string ysc; static std::string visitor_info1_live; - static bool is_whitespace(char c) { - return (c >= 8 && c <= 13) || c == ' '; - } - - // 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; - size_t api_key_length; - std::string website_result; - std::string::iterator api_key_start; - - if(download_to_string("https://www.youtube.com/?gl=US&hl=en", website_result, {}, true) != DownloadResult::OK) - goto fallback; - - api_key_index = website_result.find("INNERTUBE_API_KEY"); - if(api_key_index == std::string::npos) - goto fallback; - - api_key_index += 17; - api_key_start = std::find_if(website_result.begin() + api_key_index, website_result.end(), [](char c) { - return c != '"' && c != ':' && !is_whitespace(c); - }); - - if(api_key_start == website_result.end()) - goto fallback; - - api_key_index = api_key_start - website_result.begin(); - api_key_index_end = website_result.find('"', api_key_index); - if(api_key_index_end == std::string::npos) - goto fallback; - - api_key_length = api_key_index_end - api_key_index; - if(api_key_length > 512) // sanity check - goto fallback; - - return website_result.substr(api_key_index, api_key_length); - - fallback: - fprintf(stderr, "Failed to fetch youtube api key, fallback to %s\n", api_key.c_str()); - return "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"; - } - static std::string cpn; static bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size) { @@ -2036,109 +1993,6 @@ namespace QuickMedia { return ""; } - // Returns -1 if not found - static int64_t toggle_button_renderer_get_likes(const Json::Value &toggle_button_renderer_json) { - if(!toggle_button_renderer_json.isObject()) - return -1; - - const Json::Value &default_text_json = toggle_button_renderer_json["defaultText"]; - if(!default_text_json.isObject()) - return -1; - - const Json::Value &simple_text_json = default_text_json["simpleText"]; - if(!simple_text_json.isString()) - return -1; - - // The accessibility text for videos with 0 likes is "No Likes". We instead check for 0 in the simple text. - if(strcmp(simple_text_json.asCString(), "0") == 0) - return 0; - - const Json::Value &accessibility_json = default_text_json["accessibility"]; - if(!accessibility_json.isObject()) - return -1; - - const Json::Value &accessibility_data_json = accessibility_json["accessibilityData"]; - if(!accessibility_data_json.isObject()) - return -1; - - const Json::Value &label_json = accessibility_data_json["label"]; - if(!label_json.isString()) - return -1; - - std::string label = label_json.asString(); - size_t space_index = label.find(' '); - if(space_index != std::string::npos) - label.erase(space_index); - - string_replace_all(label, ",", ""); - - errno = 0; - char *endptr; - const int64_t num_likes = strtoll(label.c_str(), &endptr, 10); - if(endptr != label.c_str() && errno == 0) - return num_likes; - return -1; - } - - // Returns -1 if not found - static int64_t two_column_watch_next_results_get_video_likes(const Json::Value &tcwnr_json) { - if(!tcwnr_json.isObject()) - return -1; - - const Json::Value &results_json = tcwnr_json["results"]; - if(!results_json.isObject()) - return -1; - - const Json::Value &results2_json = results_json["results"]; - if(!results2_json.isObject()) - return -1; - - const Json::Value &contents_json = results2_json["contents"]; - if(!contents_json.isArray()) - return -1; - - for(const Json::Value &content_item_json : contents_json) { - if(!content_item_json.isObject()) - continue; - - const Json::Value &video_primary_info_renderer_json = content_item_json["videoPrimaryInfoRenderer"]; - if(!video_primary_info_renderer_json.isObject()) - continue; - - const Json::Value &video_actions_json = video_primary_info_renderer_json["videoActions"]; - if(!video_actions_json.isObject()) - continue; - - const Json::Value &menu_renderer_json = video_actions_json["menuRenderer"]; - if(!menu_renderer_json.isObject()) - continue; - - const Json::Value &top_level_buttons_json = menu_renderer_json["topLevelButtons"]; - if(!top_level_buttons_json.isArray()) - continue; - - for(const Json::Value &top_level_button_json : top_level_buttons_json) { - if(!top_level_button_json.isObject()) - continue; - - const Json::Value &toggle_button_renderer_json = top_level_button_json["toggleButtonRenderer"]; - if(!toggle_button_renderer_json.isObject()) - continue; - - const Json::Value &target_id_json = toggle_button_renderer_json["targetId"]; - if(!target_id_json.isString()) - continue; - - if(strcmp(target_id_json.asCString(), "watch-like") != 0) - continue; - - return toggle_button_renderer_get_likes(toggle_button_renderer_json); - } - } - - return -1; - } - static int youtube_url_timestamp_to_seconds(const std::string ×tamp) { int hours = 0; int minutes = 0; @@ -2183,7 +2037,6 @@ namespace QuickMedia { BodyItems YoutubeVideoPage::get_related_media(const std::string &url) { comments_continuation_token.clear(); - num_likes = -1; BodyItems result_items; std::string video_id; @@ -2229,9 +2082,6 @@ namespace QuickMedia { if(comments_continuation_token.empty()) comments_continuation_token = two_column_watch_next_results_get_comments_continuation_token(tcwnr_json); - if(num_likes == -1) - num_likes = two_column_watch_next_results_get_video_likes(tcwnr_json); - const Json::Value &secondary_results_json = tcwnr_json["secondaryResults"]; if(!secondary_results_json.isObject()) return result_items; @@ -2274,11 +2124,7 @@ namespace QuickMedia { return result_items; } - static int64_t round_double(double value) { - return value + 0.5; - } - - static std::shared_ptr<BodyItem> video_details_to_body_item(const YoutubeVideoDetails &video_details, int64_t num_likes) { + static std::shared_ptr<BodyItem> video_details_to_body_item(const YoutubeVideoDetails &video_details) { auto body_item = BodyItem::create(video_details.title); std::string description; @@ -2286,25 +2132,6 @@ namespace QuickMedia { description = number_separate_thousand_commas(video_details.views) + " view" + (video_details.views == "1" ? "" : "s"); } - if(!video_details.rating.empty()) { - if(!description.empty()) - description += " • "; - - double average_rating = atof(video_details.rating.c_str()); - // Minimum rating for a video is 1.0, even if a video only has dislikes - average_rating -= 1.0; - if(average_rating < 0.00000001) - average_rating = 0.00000001; - - if(num_likes == -1) { - description += "rated " + std::to_string(average_rating / 4.0 * 5.0).substr(0, 4) + "/5.0"; - } else { - const int64_t num_ratings = num_likes * (4.0 / average_rating); - const int64_t num_dislikes = (num_ratings - num_likes); - description += "👍 " + number_separate_thousand_commas(std::to_string(num_likes)) + " 👎 " + number_separate_thousand_commas(std::to_string(num_dislikes)); - } - } - if(!video_details.author.empty()) { if(!description.empty()) description += '\n'; @@ -2325,7 +2152,7 @@ namespace QuickMedia { PluginResult YoutubeVideoPage::get_related_pages(const BodyItems &related_videos, const std::string &channel_url, std::vector<Tab> &result_tabs) { auto description_page_body = create_body(); - description_page_body->append_item(video_details_to_body_item(video_details, num_likes)); + description_page_body->append_item(video_details_to_body_item(video_details)); auto related_page_body = create_body(false, true); related_page_body->set_items(related_videos); @@ -2506,7 +2333,6 @@ namespace QuickMedia { static void video_details_clear(YoutubeVideoDetails &video_details) { video_details.title.clear(); video_details.author.clear(); - video_details.rating.clear(); video_details.views.clear(); video_details.description.clear(); } @@ -2568,13 +2394,11 @@ namespace QuickMedia { const Json::Value &title_json = video_details_json["title"]; const Json::Value &author_json = video_details_json["author"]; - const Json::Value &average_rating_json = video_details_json["averageRating"]; const Json::Value &view_count_json = video_details_json["viewCount"]; const Json::Value &short_description_json = video_details_json["shortDescription"]; if(title_json.isString()) video_details.title = title_json.asString(); if(author_json.isString()) video_details.author = author_json.asString(); - if(average_rating_json.isDouble()) video_details.rating = std::to_string(average_rating_json.asDouble()); if(view_count_json.isString()) video_details.views = view_count_json.asString(); if(short_description_json.isString()) video_details.description = short_description_json.asString(); |