diff options
Diffstat (limited to 'src/plugins/Manganelo.cpp')
-rw-r--r-- | src/plugins/Manganelo.cpp | 277 |
1 files changed, 128 insertions, 149 deletions
diff --git a/src/plugins/Manganelo.cpp b/src/plugins/Manganelo.cpp index 52b9ebd..e96bc65 100644 --- a/src/plugins/Manganelo.cpp +++ b/src/plugins/Manganelo.cpp @@ -1,56 +1,10 @@ #include "../../plugins/Manganelo.hpp" #include "../../include/Notification.hpp" +#include "../../include/StringUtils.hpp" #include <quickmedia/HtmlSearch.h> namespace QuickMedia { - struct BodyItemImageContext { - BodyItems *body_items; - size_t index; - }; - - SearchResult Manganelo::search(const std::string &url, BodyItems &result_items) { - creators.clear(); - - 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='row-content-chapter']//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)); - } - }, &result_items); - - quickmedia_html_find_nodes_xpath(&html_search, "//a[class='a-h']", - [](QuickMediaHtmlNode *node, void *userdata) { - std::vector<Creator> *creators = (std::vector<Creator>*)userdata; - const char *href = quickmedia_html_node_get_attribute_value(node, "href"); - const char *text = quickmedia_html_node_get_text(node); - if(href && text && strstr(href, "/author/story/")) { - Creator creator; - creator.name = strip(text); - creator.url = href; - creators->push_back(std::move(creator)); - } - }, &creators); - - cleanup: - quickmedia_html_search_deinit(&html_search); - return result == 0 ? SearchResult::OK : SearchResult::ERR; - } - - // Returns true if changed + // Returns true if modified static bool remove_html_span(std::string &str) { size_t open_tag_start = str.find("<span"); if(open_tag_start == std::string::npos) @@ -70,103 +24,103 @@ namespace QuickMedia { return true; } - SuggestionResult Manganelo::update_search_suggestions(const std::string &text, BodyItems &result_items) { + SearchResult ManganeloSearchPage::search(const std::string &str, BodyItems &result_items) { std::string url = "https://manganelo.com/getstorysearchjson"; std::string search_term = "searchword="; - search_term += url_param_encode(text); + search_term += url_param_encode(str); CommandArg data_arg = { "--data", std::move(search_term) }; Json::Value json_root; DownloadResult result = download_json(json_root, url, {data_arg}, true); - if(result != DownloadResult::OK) return download_result_to_suggestion_result(result); - - if(json_root.isArray()) { - for(const Json::Value &child : json_root) { - if(child.isObject()) { - Json::Value name = child.get("name", ""); - Json::Value nameunsigned = child.get("nameunsigned", ""); - if(name.isString() && name.asCString()[0] != '\0' && nameunsigned.isString() && nameunsigned.asCString()[0] != '\0') { - std::string name_str = name.asString(); - while(remove_html_span(name_str)) {} - auto item = BodyItem::create(strip(name_str)); - item->url = "https://manganelo.com/manga/" + url_param_encode(nameunsigned.asString()); - Json::Value image = child.get("image", ""); - if(image.isString() && image.asCString()[0] != '\0') - item->thumbnail_url = image.asString(); - result_items.push_back(std::move(item)); - } - } + if(result != DownloadResult::OK) return download_result_to_search_result(result); + + if(json_root.isNull()) + return SearchResult::OK; + + if(!json_root.isArray()) + return SearchResult::ERR; + + for(const Json::Value &child : json_root) { + if(!child.isObject()) + continue; + + Json::Value name = child.get("name", ""); + Json::Value nameunsigned = child.get("nameunsigned", ""); + if(name.isString() && name.asCString()[0] != '\0' && nameunsigned.isString() && nameunsigned.asCString()[0] != '\0') { + std::string name_str = name.asString(); + while(remove_html_span(name_str)) {} + auto item = BodyItem::create(strip(name_str)); + item->url = "https://manganelo.com/manga/" + url_param_encode(nameunsigned.asString()); + Json::Value image = child.get("image", ""); + if(image.isString() && image.asCString()[0] != '\0') + item->thumbnail_url = image.asString(); + result_items.push_back(std::move(item)); } } - return SuggestionResult::OK; - } - ImageResult Manganelo::get_number_of_images(const std::string &url, int &num_images) { - std::lock_guard<std::mutex> lock(image_urls_mutex); - 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(); - return ImageResult::OK; + return SearchResult::OK; } - ImageResult Manganelo::get_image_urls_for_chapter(const std::string &url) { - if(url == last_chapter_url) - return ImageResult::OK; - - last_chapter_image_urls.clear(); + PluginResult ManganeloSearchPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) { + BodyItems chapters_items; + std::vector<Creator> creators; 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='container-chapter-reader']/img", + result = quickmedia_html_find_nodes_xpath(&html_search, "//ul[class='row-content-chapter']//a", [](QuickMediaHtmlNode *node, void *userdata) { - auto *urls = (std::vector<std::string>*)userdata; - const char *src = quickmedia_html_node_get_attribute_value(node, "src"); - if(src) { - std::string image_url = src; - urls->emplace_back(std::move(image_url)); + 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); + + quickmedia_html_find_nodes_xpath(&html_search, "//a[class='a-h']", + [](QuickMediaHtmlNode *node, void *userdata) { + std::vector<Creator> *creators = (std::vector<Creator>*)userdata; + const char *href = quickmedia_html_node_get_attribute_value(node, "href"); + const char *text = quickmedia_html_node_get_text(node); + if(href && text && strstr(href, "/author/story/")) { + Creator creator; + creator.name = strip(text); + creator.url = href; + creators->push_back(std::move(creator)); } - }, &last_chapter_image_urls); + }, &creators); cleanup: quickmedia_html_search_deinit(&html_search); - if(result == 0) - last_chapter_url = url; - if(last_chapter_image_urls.empty()) { - last_chapter_url.clear(); - return ImageResult::ERR; - } - return result == 0 ? ImageResult::OK : ImageResult::ERR; - } + if(result != 0) + return PluginResult::ERR; - ImageResult Manganelo::for_each_page_in_chapter(const std::string &chapter_url, PageCallback callback) { - std::vector<std::string> image_urls; - { - std::lock_guard<std::mutex> lock(image_urls_mutex); - ImageResult image_result = get_image_urls_for_chapter(chapter_url); - if(image_result != ImageResult::OK) - return image_result; + auto chapters_body = create_body(); + chapters_body->items = std::move(chapters_items); + result_tabs.push_back(Tab{std::move(chapters_body), std::make_unique<ManganeloChaptersPage>(program, title, url), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); - image_urls = last_chapter_image_urls; + for(Creator &creator : creators) { + result_tabs.push_back(Tab{create_body(), std::make_unique<ManganeloCreatorPage>(program, std::move(creator)), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); } - for(const std::string &url : image_urls) { - if(!callback(url)) - break; + std::string manga_id; + if(extract_id_from_url(url, manga_id)) { + if(load_manga_content_storage("manganelo", title, manga_id)) + return PluginResult::OK; } - return ImageResult::OK; + return PluginResult::ERR; } - - bool Manganelo::extract_id_from_url(const std::string &url, std::string &manga_id) { + + bool ManganeloSearchPage::extract_id_from_url(const std::string &url, std::string &manga_id) const { bool manganelo_website = false; if(url.find("mangakakalot") != std::string::npos || url.find("manganelo") != std::string::npos) manganelo_website = true; @@ -177,7 +131,7 @@ namespace QuickMedia { std::string err_msg = "Url "; err_msg += url; err_msg += " doesn't contain manga id"; - show_notification("Manga", err_msg, Urgency::CRITICAL); + show_notification("QuickMedia", err_msg, Urgency::CRITICAL); return false; } @@ -186,7 +140,7 @@ namespace QuickMedia { std::string err_msg = "Url "; err_msg += url; err_msg += " doesn't contain manga id"; - show_notification("Manga", err_msg, Urgency::CRITICAL); + show_notification("QuickMedia", err_msg, Urgency::CRITICAL); return false; } return true; @@ -194,56 +148,81 @@ namespace QuickMedia { std::string err_msg = "Unexpected url "; err_msg += url; err_msg += " is not manganelo or mangakakalot"; - show_notification("Manga", err_msg, Urgency::CRITICAL); + show_notification("QuickMedia", err_msg, Urgency::CRITICAL); return false; } } - PluginResult Manganelo::get_creators_manga_list(const std::string &url, BodyItems &result_items) { + PluginResult ManganeloChaptersPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) { + result_tabs.push_back(Tab{create_body(), std::make_unique<ManganeloImagesPage>(program, content_title, title, url), nullptr}); + return PluginResult::OK; + } + + PluginResult ManganeloCreatorPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) { + (void)title; + (void)url; + (void)result_tabs; + // TODO: Implement + return PluginResult::ERR; + } + + ImageResult ManganeloImagesPage::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 ManganeloImagesPage::for_each_page_in_chapter(PageCallback callback) { + std::vector<std::string> 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 ManganeloImagesPage::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, {}, use_tor, true) != DownloadResult::OK) - return PluginResult::NET_ERR; + 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='search-story-item']//a[class='item-img']", - [](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 body_item = BodyItem::create(title); - body_item->url = href; - item_data->push_back(std::move(body_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, "//div[class='search-story-item']//a[class='item-img']//img", + result = quickmedia_html_find_nodes_xpath(&html_search, "//div[class='container-chapter-reader']/img", [](QuickMediaHtmlNode *node, void *userdata) { - auto *item_data = (BodyItemImageContext*)userdata; + auto *urls = (std::vector<std::string>*)userdata; const char *src = quickmedia_html_node_get_attribute_value(node, "src"); - if(src && item_data->index < item_data->body_items->size()) { - (*item_data->body_items)[item_data->index]->thumbnail_url = src; - item_data->index++; + if(src) { + std::string image_url = src; + urls->push_back(std::move(image_url)); } - }, &body_item_image_context); + }, &chapter_image_urls); cleanup: quickmedia_html_search_deinit(&html_search); if(result != 0) { - result_items.clear(); - return PluginResult::ERR; + chapter_image_urls.clear(); + return ImageResult::ERR; } - return PluginResult::OK; + if(chapter_image_urls.empty()) + return ImageResult::ERR; + return ImageResult::OK; } }
\ No newline at end of file |