From 77ed51898157d99112be7550471ec06e32344c9e Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 11 Oct 2020 21:35:37 +0200 Subject: Refactor plugin into seperate pages TODO: Readd 4chan login page, manganelo creators page, autocomplete --- src/plugins/Mangatown.cpp | 212 +++++++++++++++++++++++++--------------------- 1 file changed, 115 insertions(+), 97 deletions(-) (limited to 'src/plugins/Mangatown.cpp') diff --git a/src/plugins/Mangatown.cpp b/src/plugins/Mangatown.cpp index 400d1ef..5d6f97f 100644 --- a/src/plugins/Mangatown.cpp +++ b/src/plugins/Mangatown.cpp @@ -1,59 +1,26 @@ #include "../../plugins/Mangatown.hpp" #include "../../include/Notification.hpp" +#include "../../include/StringUtils.hpp" #include static const std::string mangatown_url = "https://www.mangatown.com"; namespace QuickMedia { - SearchResult Mangatown::search(const std::string &url, BodyItems &result_items) { - std::string website_data; - if(download_to_string(url, website_data, {}, use_tor, true) != DownloadResult::OK) - return SearchResult::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, "//ul[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 && strncmp(href, "/manga/", 7) == 0) { - auto item = BodyItem::create(strip(text)); - item->url = mangatown_url + href; - item_data->push_back(std::move(item)); - } - }, &result_items); - - cleanup: - quickmedia_html_search_deinit(&html_search); - - int chapter_num = result_items.size(); - for(auto &body_item : result_items) { - body_item->set_title("Ch. " + std::to_string(chapter_num)); - chapter_num--; - } - - return result == 0 ? SearchResult::OK : SearchResult::ERR; + static bool is_number_with_zero_fill(const char *str) { + while(*str == '0') { ++str; } + return atoi(str) != 0; } - struct BodyItemImageContext { - BodyItems *body_items; - size_t index; - }; - - SuggestionResult Mangatown::update_search_suggestions(const std::string &text, BodyItems &result_items) { + SearchResult MangatownSearchPage::search(const std::string &str, BodyItems &result_items) { std::string url = "https://www.mangatown.com/search?name="; - url += url_param_encode(text); + url += url_param_encode(str); std::string website_data; - if(download_to_string(url, website_data, {}, use_tor, true) != DownloadResult::OK) - return SuggestionResult::NET_ERR; + if(download_to_string(url, website_data, {}, is_tor_enabled(), true) != DownloadResult::OK) + return SearchResult::NET_ERR; if(website_data.empty()) - return SuggestionResult::OK; + return SearchResult::OK; QuickMediaHtmlSearch html_search; int result = quickmedia_html_search_init(&html_search, website_data.c_str()); @@ -88,77 +55,101 @@ namespace QuickMedia { cleanup: quickmedia_html_search_deinit(&html_search); - return SuggestionResult::OK; + return SearchResult::OK; } - static bool is_number_with_zero_fill(const char *str) { - while(*str == '0') { ++str; } - return atoi(str) != 0; - } - - ImageResult Mangatown::get_number_of_images(const std::string &url, int &num_images) { - std::lock_guard lock(image_urls_mutex); - - num_images = last_num_pages; - if(url == last_chapter_url_num_images) - return ImageResult::OK; - - last_num_pages = 0; + PluginResult MangatownSearchPage::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, {}, use_tor, true) != DownloadResult::OK) - return ImageResult::NET_ERR; + if(download_to_string(url, website_data, {}, is_tor_enabled(), 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, "//div[class='page_select']//option", + result = quickmedia_html_find_nodes_xpath(&html_search, "//ul[class='chapter_list']//a", [](QuickMediaHtmlNode *node, void *userdata) { - int *last_num_pages = (int*)userdata; - const char *value = quickmedia_html_node_get_attribute_value(node, "value"); + 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(value && strncmp(value, "/manga/", 7) == 0) { - if(is_number_with_zero_fill(text)) { - (*last_num_pages)++; - } + if(href && text && strncmp(href, "/manga/", 7) == 0) { + auto item = BodyItem::create(strip(text)); + item->url = mangatown_url + href; + item_data->push_back(std::move(item)); } - }, &last_num_pages); - - last_num_pages /= 2; - num_images = last_num_pages; + }, &chapters_items); cleanup: quickmedia_html_search_deinit(&html_search); + if(result != 0) + return PluginResult::ERR; - if(result == 0) - last_chapter_url_num_images = url; - if(last_num_pages == 0) { - last_chapter_url_num_images.clear(); - return ImageResult::ERR; + int chapter_num = chapters_items.size(); + for(auto &body_item : chapters_items) { + body_item->set_title("Ch. " + std::to_string(chapter_num)); + chapter_num--; } - return result == 0 ? ImageResult::OK : ImageResult::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)}); + + std::string manga_id; + if(extract_id_from_url(url, manga_id)) { + if(load_manga_content_storage("mangatown", title, manga_id)) + return PluginResult::OK; + } + return PluginResult::ERR; + } + + bool MangatownSearchPage::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 Mangatown::for_each_page_in_chapter(const std::string &chapter_url, PageCallback callback) { - int num_pages; - ImageResult image_result = get_number_of_images(chapter_url, num_pages); + PluginResult MangatownChaptersPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { + result_tabs.push_back(Tab{create_body(), std::make_unique(program, content_title, title, url), nullptr}); + return PluginResult::OK; + } + + ImageResult MangatownImagesPage::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; - int result = 0; - int page_index = 1; + num_images = chapter_image_urls.size(); + return ImageResult::OK; + } + + ImageResult MangatownImagesPage::for_each_page_in_chapter(PageCallback callback) { + int num_pages; + ImageResult image_result = get_number_of_images(num_pages); + if(image_result != ImageResult::OK) + return image_result; - while(true) { + for(const std::string &full_url : chapter_image_urls) { std::string image_src; std::string website_data; - std::string full_url = chapter_url + std::to_string(page_index++) + ".html"; - if(download_to_string_cache(full_url, website_data, {}, use_tor, true) != DownloadResult::OK) + if(download_to_string_cache(full_url, website_data, {}, is_tor_enabled(), true) != DownloadResult::OK) break; QuickMediaHtmlSearch html_search; - result = quickmedia_html_search_init(&html_search, website_data.c_str()); + int result = quickmedia_html_search_init(&html_search, website_data.c_str()); if(result != 0) goto cleanup; @@ -190,19 +181,46 @@ namespace QuickMedia { return ImageResult::OK; } - bool Mangatown::extract_id_from_url(const std::string &url, std::string &manga_id) { - 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; + ImageResult MangatownImagesPage::get_image_urls_for_chapter(const std::string &url) { + if(!chapter_image_urls.empty()) + return ImageResult::OK; + + int num_pages = 0; + + std::string website_data; + if(download_to_string(url, website_data, {}, is_tor_enabled(), 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, "//div[class='page_select']//option", + [](QuickMediaHtmlNode *node, void *userdata) { + int *last_num_pages = (int*)userdata; + const char *value = quickmedia_html_node_get_attribute_value(node, "value"); + const char *text = quickmedia_html_node_get_text(node); + if(value && strncmp(value, "/manga/", 7) == 0) { + if(is_number_with_zero_fill(text)) { + (*last_num_pages)++; + } + } + }, &num_pages); + + num_pages /= 2; + + cleanup: + quickmedia_html_search_deinit(&html_search); + if(result != 0) { + chapter_image_urls.clear(); + return ImageResult::ERR; } - - manga_id = url.substr(start_index, end_index - start_index); - return true; + if(num_pages == 0) + return ImageResult::ERR; + for(int i = 0; i < num_pages; ++i) { + chapter_image_urls.push_back(url + std::to_string(1 + i) + ".html"); + } + return ImageResult::OK; } } \ No newline at end of file -- cgit v1.2.3