From bb7ad686d202bfe513104546cb2d77e6720d62a3 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 12 Apr 2021 14:21:21 +0200 Subject: Add manganelos --- src/plugins/Manganelos.cpp | 180 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 src/plugins/Manganelos.cpp (limited to 'src/plugins') diff --git a/src/plugins/Manganelos.cpp b/src/plugins/Manganelos.cpp new file mode 100644 index 0000000..f67c313 --- /dev/null +++ b/src/plugins/Manganelos.cpp @@ -0,0 +1,180 @@ +#include "../../plugins/Manganelos.hpp" +#include "../../include/Notification.hpp" +#include "../../include/StringUtils.hpp" +#include "../../include/NetUtils.hpp" +#include + +namespace QuickMedia { + static SearchResult search_page(const std::string &str, int page, BodyItems &result_items) { + std::string url = "http://manganelos.com/search?q="; + url += url_param_encode(str); + url += "&page=" + std::to_string(page); + + std::string website_data; + if(download_to_string(url, website_data, {}, true) != DownloadResult::OK) + return SearchResult::NET_ERR; + + if(website_data.empty()) + return SearchResult::OK; + + 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='media-left cover-manga']//a", + [](QuickMediaHtmlNode *node, void *userdata) { + auto *item_data = (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 && strstr(href, "/manga/")) { + auto item = BodyItem::create(strip(title)); + item->url = href; + item_data->push_back(std::move(item)); + } + }, &result_items); + + BodyItemContext body_item_image_context; + body_item_image_context.body_items = &result_items; + body_item_image_context.index = 0; + + result = quickmedia_html_find_nodes_xpath(&html_search, "//div[class='media-left cover-manga']//img[class='media-object']", + [](QuickMediaHtmlNode *node, void *userdata) { + auto *item_data = (BodyItemContext*)userdata; + const char *src = quickmedia_html_node_get_attribute_value(node, "src"); + if(src && strstr(src, "/mangaimage/") && item_data->index < item_data->body_items->size()) { + (*item_data->body_items)[item_data->index]->thumbnail_url = src; + item_data->index++; + } + }, &body_item_image_context); + + cleanup: + quickmedia_html_search_deinit(&html_search); + return SearchResult::OK; + } + + SearchResult ManganelosSearchPage::search(const std::string &str, BodyItems &result_items) { + return search_page(str, 1, result_items); + } + + PluginResult ManganelosSearchPage::get_page(const std::string &str, int page, BodyItems &result_items) { + return search_result_to_plugin_result(search_page(str, 1 + page, result_items)); + } + + PluginResult ManganelosSearchPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { + BodyItems chapters_items; + + std::string website_data; + if(download_to_string(url, website_data, {}, true) != DownloadResult::OK) + return PluginResult::NET_ERR; + + 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, "//section[id='examples']//div[class='chapter-list']//a", + [](QuickMediaHtmlNode *node, void *userdata) { + auto *item_data = (BodyItems*)userdata; + const char *href = quickmedia_html_node_get_attribute_value(node, "href"); + const char *text = quickmedia_html_node_get_text(node); + if(href && text) { + auto item = BodyItem::create(strip(text)); + item->url = href; + item_data->push_back(std::move(item)); + } + }, &chapters_items); + + cleanup: + quickmedia_html_search_deinit(&html_search); + if(result != 0) + return PluginResult::ERR; + + auto body = create_body(); + body->items = std::move(chapters_items); + result_tabs.push_back(Tab{std::move(body), std::make_unique(program, title, url), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); + return PluginResult::OK; + } + + PluginResult ManganelosChaptersPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { + result_tabs.push_back(Tab{nullptr, std::make_unique(program, content_title, title, url), nullptr}); + return PluginResult::OK; + } + + bool ManganelosChaptersPage::extract_id_from_url(const std::string &url, std::string &manga_id) const { + size_t start_index = url.find("/manga/"); + if(start_index == std::string::npos) + return false; + + start_index += 7; + size_t end_index = url.find("?", start_index); + if(end_index == std::string::npos) { + manga_id = url.substr(start_index); + return true; + } + + manga_id = url.substr(start_index, end_index - start_index); + return true; + } + + ImageResult ManganelosImagesPage::get_number_of_images(int &num_images) { + num_images = 0; + ImageResult image_result = get_image_urls_for_chapter(url); + if(image_result != ImageResult::OK) + return image_result; + + num_images = chapter_image_urls.size(); + return ImageResult::OK; + } + + ImageResult ManganelosImagesPage::for_each_page_in_chapter(PageCallback callback) { + std::vector image_urls; + ImageResult image_result = get_image_urls_for_chapter(url); + if(image_result != ImageResult::OK) + return image_result; + + image_urls = chapter_image_urls; + + for(const std::string &url : image_urls) { + if(!callback(url)) + break; + } + + return ImageResult::OK; + } + + ImageResult ManganelosImagesPage::get_image_urls_for_chapter(const std::string &url) { + if(!chapter_image_urls.empty()) + return ImageResult::OK; + + std::string website_data; + if(download_to_string(url, website_data, {}, true) != DownloadResult::OK) + return ImageResult::NET_ERR; + + 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, "//p[id='arraydata']", + [](QuickMediaHtmlNode *node, void *userdata) { + std::vector *chapter_image_urls = (std::vector*)userdata; + const char *text = quickmedia_html_node_get_text(node); + string_split(text, ',', [chapter_image_urls](const char *str, size_t size) { + std::string url(str, size); + chapter_image_urls->push_back(std::move(url)); + return true; + }); + }, &chapter_image_urls); + + cleanup: + quickmedia_html_search_deinit(&html_search); + if(result != 0) { + chapter_image_urls.clear(); + return ImageResult::ERR; + } + if(chapter_image_urls.empty()) + return ImageResult::ERR; + return ImageResult::OK; + } +} \ No newline at end of file -- cgit v1.2.3