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/Mangadex.cpp | 201 +++++++++++++++++++++++------------------------ 1 file changed, 98 insertions(+), 103 deletions(-) (limited to 'src/plugins/Mangadex.cpp') diff --git a/src/plugins/Mangadex.cpp b/src/plugins/Mangadex.cpp index 9808654..be2d342 100644 --- a/src/plugins/Mangadex.cpp +++ b/src/plugins/Mangadex.cpp @@ -1,6 +1,7 @@ #include "../../plugins/Mangadex.hpp" #include "../../include/Storage.hpp" #include "../../include/Notification.hpp" +#include "../../include/StringUtils.hpp" #include #include @@ -27,30 +28,96 @@ namespace QuickMedia { return url.substr(find_index + 9); } + static bool get_cookie_filepath(std::string &cookie_filepath) { + Path cookie_path = get_storage_dir().join("cookies"); + if(create_directory_recursive(cookie_path) != 0) { + show_notification("Storage", "Failed to create directory: " + cookie_path.data, Urgency::CRITICAL); + return false; + } + cookie_filepath = cookie_path.join("mangadex.txt").data; + return true; + } + struct BodyItemChapterContext { BodyItems *body_items; int prev_chapter_number; bool *is_last_page; }; - SearchResult Mangadex::search(const std::string &url, BodyItems &result_items) { + // TODO: Implement pagination (go to next page and get all results as well) + SearchResult MangadexSearchPage::search(const std::string &str, BodyItems &result_items) { + std::string rememberme_token; + if(!get_rememberme_token(rememberme_token)) + return SearchResult::ERR; + + std::string url = "https://mangadex.org/search?title="; + url += url_param_encode(str); + CommandArg cookie_arg = { "-H", "cookie: mangadex_rememberme_token=" + rememberme_token }; + + std::string website_data; + if(download_to_string(url, website_data, {std::move(cookie_arg)}, is_tor_enabled(), 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, "//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(title && href && strncmp(href, "/title/", 7) == 0) { + auto item = BodyItem::create(strip(title)); + item->url = mangadex_url + href; + item_data->push_back(std::move(item)); + } + }, &result_items); + + if(result != 0) + goto cleanup; + + BodyItemImageContext 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, "//img", + [](QuickMediaHtmlNode *node, void *userdata) { + auto *item_data = (BodyItemImageContext*)userdata; + const char *src = quickmedia_html_node_get_attribute_value(node, "src"); + if(src && strncmp(src, "/images/manga/", 14) == 0 && item_data->index < item_data->body_items->size()) { + (*item_data->body_items)[item_data->index]->thumbnail_url = mangadex_url + src; + item_data->index++; + } + }, &body_item_image_context); + + if(result != 0) + goto cleanup; + + cleanup: + quickmedia_html_search_deinit(&html_search); + return result == 0 ? SearchResult::OK : SearchResult::ERR; + } + + PluginResult MangadexSearchPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { std::string manga_id = title_url_extract_manga_id(url); std::string request_url = "https://mangadex.org/api/?id=" + manga_id + "&type=manga"; Json::Value json_root; DownloadResult result = download_json(json_root, request_url, {}, true); - if(result != DownloadResult::OK) return download_result_to_search_result(result); + if(result != DownloadResult::OK) return download_result_to_plugin_result(result); if(!json_root.isObject()) - return SearchResult::ERR; + return PluginResult::ERR; Json::Value &status_json = json_root["status"]; if(!status_json.isString() || status_json.asString() != "OK") - return SearchResult::ERR; + return PluginResult::ERR; Json::Value &chapter_json = json_root["chapter"]; if(!chapter_json.isObject()) - return SearchResult::ERR; + return PluginResult::ERR; std::vector> chapters(chapter_json.size()); /* TODO: Optimize member access */ @@ -74,6 +141,8 @@ namespace QuickMedia { time_t time_now = time(NULL); + auto body = create_body(); + /* TODO: Pointer */ std::string prev_chapter_number; for(auto it = chapters.begin(); it != chapters.end(); ++it) { @@ -106,22 +175,17 @@ namespace QuickMedia { auto item = BodyItem::create(std::move(chapter_name)); item->url = std::move(chapter_url); - result_items.push_back(std::move(item)); + body->items.push_back(std::move(item)); } - return SearchResult::OK; - } - static bool get_cookie_filepath(std::string &cookie_filepath) { - Path cookie_path = get_storage_dir().join("cookies"); - if(create_directory_recursive(cookie_path) != 0) { - show_notification("Storage", "Failed to create directory: " + cookie_path.data, Urgency::CRITICAL); - return false; - } - cookie_filepath = cookie_path.join("mangadex.txt").data; - return true; + result_tabs.push_back(Tab{std::move(body), std::make_unique(program, title, url), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); + + if(load_manga_content_storage("mangadex", title, manga_id)) + return PluginResult::OK; + return PluginResult::ERR; } - bool Mangadex::get_rememberme_token(std::string &rememberme_token_output) { + bool MangadexSearchPage::get_rememberme_token(std::string &rememberme_token_output) { if(rememberme_token) { rememberme_token_output = rememberme_token.value(); return true; @@ -153,93 +217,34 @@ namespace QuickMedia { return true; } - struct BodyItemImageContext { - BodyItems *body_items; - size_t index; - }; - - // TODO: Implement pagination (go to next page and get all results as well) - SuggestionResult Mangadex::update_search_suggestions(const std::string &text, BodyItems &result_items) { - std::string rememberme_token; - if(!get_rememberme_token(rememberme_token)) - return SuggestionResult::ERR; - - std::string url = "https://mangadex.org/search?title="; - url += url_param_encode(text); - CommandArg cookie_arg = { "-H", "cookie: mangadex_rememberme_token=" + rememberme_token }; - - std::string website_data; - if(download_to_string(url, website_data, {std::move(cookie_arg)}, use_tor, true) != DownloadResult::OK) - return SuggestionResult::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, "//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(title && href && strncmp(href, "/title/", 7) == 0) { - auto item = BodyItem::create(strip(title)); - item->url = mangadex_url + href; - item_data->push_back(std::move(item)); - } - }, &result_items); - - if(result != 0) - goto cleanup; - - BodyItemImageContext 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, "//img", - [](QuickMediaHtmlNode *node, void *userdata) { - auto *item_data = (BodyItemImageContext*)userdata; - const char *src = quickmedia_html_node_get_attribute_value(node, "src"); - if(src && strncmp(src, "/images/manga/", 14) == 0 && item_data->index < item_data->body_items->size()) { - (*item_data->body_items)[item_data->index]->thumbnail_url = mangadex_url + src; - item_data->index++; - } - }, &body_item_image_context); - - if(result != 0) - goto cleanup; - - cleanup: - quickmedia_html_search_deinit(&html_search); - return result == 0 ? SuggestionResult::OK : SuggestionResult::ERR; + PluginResult MangadexChaptersPage::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 Mangadex::get_number_of_images(const std::string &url, int &num_images) { - std::lock_guard lock(image_urls_mutex); + ImageResult MangadexImagesPage::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 = last_chapter_image_urls.size(); + num_images = chapter_image_urls.size(); return ImageResult::OK; } - bool Mangadex::save_mangadex_cookies(const std::string &url, const std::string &cookie_filepath) { + bool MangadexImagesPage::save_mangadex_cookies(const std::string &url, const std::string &cookie_filepath) { CommandArg cookie_arg = { "-c", cookie_filepath }; std::string server_response; - if(download_to_string(url, server_response, {std::move(cookie_arg)}, use_tor, true) != DownloadResult::OK) + if(download_to_string(url, server_response, {std::move(cookie_arg)}, is_tor_enabled(), true) != DownloadResult::OK) return false; return true; } - ImageResult Mangadex::get_image_urls_for_chapter(const std::string &url) { - if(url == last_chapter_url) + ImageResult MangadexImagesPage::get_image_urls_for_chapter(const std::string &url) { + if(!chapter_image_urls.empty()) return ImageResult::OK; - last_chapter_image_urls.clear(); - std::string cookie_filepath; if(!get_cookie_filepath(cookie_filepath)) return ImageResult::ERR; @@ -281,38 +286,28 @@ namespace QuickMedia { continue; std::string image_url = server + chapter_hash_str + "/" + image_name.asCString(); - last_chapter_image_urls.push_back(std::move(image_url)); + chapter_image_urls.push_back(std::move(image_url)); } } - last_chapter_url = url; - if(last_chapter_image_urls.empty()) { - last_chapter_url.clear(); + if(chapter_image_urls.empty()) return ImageResult::ERR; - } return ImageResult::OK; } - ImageResult Mangadex::for_each_page_in_chapter(const std::string &chapter_url, PageCallback callback) { + ImageResult MangadexImagesPage::for_each_page_in_chapter(PageCallback callback) { std::vector image_urls; - { - std::lock_guard lock(image_urls_mutex); - ImageResult image_result = get_image_urls_for_chapter(chapter_url); - if(image_result != ImageResult::OK) - return image_result; + ImageResult image_result = get_image_urls_for_chapter(url); + if(image_result != ImageResult::OK) + return image_result; - image_urls = last_chapter_image_urls; - } + image_urls = chapter_image_urls; for(const std::string &url : image_urls) { if(!callback(url)) break; } - return ImageResult::OK; - } - bool Mangadex::extract_id_from_url(const std::string &url, std::string &manga_id) { - manga_id = title_url_extract_manga_id(url); - return true; + return ImageResult::OK; } } -- cgit v1.2.3