From afc8c731bdf482e87304d2f5df6cfc55018806b6 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 9 Aug 2019 05:13:38 +0200 Subject: Add pornhub plugin --- src/QuickMedia.cpp | 5 +- src/plugins/Pornhub.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 src/plugins/Pornhub.cpp (limited to 'src') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 4b3698d..691b62b 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -1,6 +1,7 @@ #include "../include/QuickMedia.hpp" #include "../plugins/Manganelo.hpp" #include "../plugins/Youtube.hpp" +#include "../plugins/Pornhub.hpp" #include "../include/Scale.hpp" #include "../include/Program.h" #include "../include/VideoPlayer.hpp" @@ -72,7 +73,7 @@ namespace QuickMedia { static void usage() { fprintf(stderr, "usage: QuickMedia \n"); fprintf(stderr, "OPTIONS:\n"); - fprintf(stderr, "plugin The plugin to use. Should be either manganelo or youtube\n"); + fprintf(stderr, "plugin The plugin to use. Should be either manganelo, youtube or pornhub\n"); } int Program::run(int argc, char **argv) { @@ -85,6 +86,8 @@ namespace QuickMedia { current_plugin = new Manganelo(); else if(strcmp(argv[1], "youtube") == 0) current_plugin = new Youtube(); + else if(strcmp(argv[1], "pornhub") == 0) + current_plugin = new Pornhub(); else { usage(); return -1; diff --git a/src/plugins/Pornhub.cpp b/src/plugins/Pornhub.cpp new file mode 100644 index 0000000..4955efd --- /dev/null +++ b/src/plugins/Pornhub.cpp @@ -0,0 +1,139 @@ +#include "../../plugins/Pornhub.hpp" +#include +#include +#include + +namespace QuickMedia { + static bool begins_with(const char *str, const char *begin_with) { + return strncmp(str, begin_with, strlen(begin_with)) == 0; + } + + static bool contains(const char *str, const char *substr) { + return strstr(str, substr); + } + + static void iterate_suggestion_result(const Json::Value &value, BodyItems &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) { + std::string title = value.asString(); + auto item = std::make_unique(title); + result_items.push_back(std::move(item)); + } + } + + // TODO: Speed this up by using string.find instead of parsing html + SuggestionResult Pornhub::update_search_suggestions(const std::string &text, BodyItems &result_items) { + std::string url = "https://www.pornhub.com/video/search?search="; + url += url_param_encode(text); + + std::string website_data; + if(download_to_string(url, website_data) != DownloadResult::OK) + return SuggestionResult::NET_ERR; + + struct ItemData { + BodyItems *result_items; + size_t index; + }; + ItemData item_data = { &result_items, 0 }; + + QuickMediaHtmlSearch html_search; + int result = quickmedia_html_search_init(&html_search, website_data.c_str()); + if(result != 0) + goto cleanup; + + result = quickmedia_html_find_nodes_xpath(&html_search, "//div[class='phimage']//a", + [](QuickMediaHtmlNode *node, void *userdata) { + auto *result_items = (BodyItems*)userdata; + const char *href = quickmedia_html_node_get_attribute_value(node, "href"); + const char *title = quickmedia_html_node_get_attribute_value(node, "title"); + if(href && title && begins_with(href, "/view_video.php?viewkey")) { + auto item = std::make_unique(strip(title)); + item->url = std::string("https://www.pornhub.com") + href; + result_items->push_back(std::move(item)); + } + }, &result_items); + if(result != 0) + goto cleanup; + + result = quickmedia_html_find_nodes_xpath(&html_search, "//div[class='phimage']//img", + [](QuickMediaHtmlNode *node, void *userdata) { + ItemData *item_data = (ItemData*)userdata; + if(item_data->index >= item_data->result_items->size()) + return; + + const char *data_src = quickmedia_html_node_get_attribute_value(node, "data-src"); + if(data_src && contains(data_src, "phncdn.com/videos")) { + (*item_data->result_items)[item_data->index]->thumbnail_url = data_src; + ++item_data->index; + } + }, &item_data); + + // Attempt to skip promoted videos (that are not related to the search term) + if(result_items.size() >= 4) { + result_items.erase(result_items.begin(), result_items.begin() + 4); + } + + cleanup: + quickmedia_html_search_deinit(&html_search); + return result == 0 ? SuggestionResult::OK : SuggestionResult::ERR; + } + + BodyItems Pornhub::get_related_media(const std::string &url) { + BodyItems result_items; + + std::string website_data; + if(download_to_string(url, website_data) != DownloadResult::OK) + return result_items; + + struct ItemData { + BodyItems *result_items; + size_t index; + }; + ItemData item_data = { &result_items, 0 }; + + QuickMediaHtmlSearch html_search; + int result = quickmedia_html_search_init(&html_search, website_data.c_str()); + if(result != 0) + goto cleanup; + + result = quickmedia_html_find_nodes_xpath(&html_search, "//div[class='phimage']//a", + [](QuickMediaHtmlNode *node, void *userdata) { + auto *result_items = (BodyItems*)userdata; + const char *href = quickmedia_html_node_get_attribute_value(node, "href"); + const char *title = quickmedia_html_node_get_attribute_value(node, "title"); + if(href && title && begins_with(href, "/view_video.php?viewkey")) { + auto item = std::make_unique(strip(title)); + item->url = std::string("https://www.pornhub.com") + href; + result_items->push_back(std::move(item)); + } + }, &result_items); + if(result != 0) + goto cleanup; + + result = quickmedia_html_find_nodes_xpath(&html_search, "//div[class='phimage']//img", + [](QuickMediaHtmlNode *node, void *userdata) { + ItemData *item_data = (ItemData*)userdata; + if(item_data->index >= item_data->result_items->size()) + return; + + const char *src = quickmedia_html_node_get_attribute_value(node, "src"); + if(src && contains(src, "phncdn.com/videos")) { + (*item_data->result_items)[item_data->index]->thumbnail_url = src; + ++item_data->index; + } + }, &item_data); + + // Attempt to skip promoted videos (that are not related to the search term) + if(result_items.size() >= 4) { + result_items.erase(result_items.begin(), result_items.begin() + 4); + } + + cleanup: + quickmedia_html_search_deinit(&html_search); + return result_items; + } +} \ No newline at end of file -- cgit v1.2.3