#pragma once #include "Manga.hpp" #include namespace QuickMedia { struct MangaFormData { const char *key; const char *value; }; struct MangaFormDataStr { const char *key; std::string value; }; using SearchQueryJsonHandler = std::function; struct SearchQuery { const char *search_template = nullptr; int page_start = 0; std::vector form_data; bool is_post = false; SearchQueryJsonHandler json_handler = nullptr; }; struct TextQuery { const char *html_query = nullptr; const char *title_field = nullptr; const char *url_field = nullptr; const char *url_contains = nullptr; }; struct DescriptionQuery { const char *html_query = nullptr; const char *field_name = nullptr; }; struct ThumbnailQuery { const char *html_query = nullptr; const char *field_name = nullptr; const char *field_contains = nullptr; }; struct AuthorsQuery { const char *html_query = nullptr; const char *title_field = nullptr; const char *url_field = nullptr; const char *url_contains = nullptr; }; struct ListChaptersQuery { const char *html_query = nullptr; const char *title_field = nullptr; const char *url_field = nullptr; const char *url_contains = nullptr; const char *uploaded_time_html_query = nullptr; const char *uploaded_time_field_name = nullptr; const char *uploaded_time_field_contains = nullptr; }; using ListPageImagesQueryPost = std::function &image_urls)>; struct ListPageImagesQuery { const char *html_query = nullptr; const char *field_name = nullptr; const char *field_contains = nullptr; ListPageImagesQueryPost post_handler = nullptr; }; struct ListPagePaginationQuery { const char *pages_html_query = nullptr; const char *pages_field_name = nullptr; const char *image_html_query = nullptr; const char *image_field_name = nullptr; const char *image_field_contains = nullptr; const char *next_page_html_query = nullptr; const char *next_page_field_name = nullptr; const char *next_page_field_contains = nullptr; }; // Return the image sources using ListPageCustomHandler = std::function(const std::string &html_source)>; struct ListPageCustomQuery { ListPageCustomHandler handler; }; enum class ListPageQueryType { IMAGES, PAGINATION, CUSTOM }; struct ListPageQuery { ListPageQueryType type = ListPageQueryType::IMAGES; ListPageImagesQuery images_query; ListPagePaginationQuery pagination_query; ListPageCustomQuery custom_query; }; struct MangaIdExtractor { const char *prefix = nullptr; const char *end = nullptr; }; class MangaGenericSearchPage : public Page { public: MangaGenericSearchPage(Program *program, const char *service_name, const char *website_url, bool fail_on_http_error = true); const char* get_title() const override { return "Search"; } bool search_is_filter() override { return false; } SearchResult search(const std::string &str, BodyItems &result_items) override; PluginResult get_page(const std::string &url, bool is_post, const std::vector &form_data, BodyItems &result_items); PluginResult get_page(const std::string &str, int page, BodyItems &result_items) override; PluginResult submit(const SubmitArgs &args, std::vector &result_tabs) override; const char* get_bookmark_name() const override { return service_name; } MangaGenericSearchPage& search_handler(const char *search_template, int page_start); MangaGenericSearchPage& search_post_handler(const char *url, std::vector form_data, SearchQueryJsonHandler result_handler); MangaGenericSearchPage& text_handler(std::vector queries); MangaGenericSearchPage& description_handler(std::vector queries); MangaGenericSearchPage& thumbnail_handler(std::vector queries); MangaGenericSearchPage& authors_handler(std::vector queries); MangaGenericSearchPage& list_chapters_handler(const char *html_query, const char *title_field, const char *url_field, const char *url_contains); MangaGenericSearchPage& list_chapters_uploaded_time_handler(const char *html_query, const char *field_name, const char *field_contains); MangaGenericSearchPage& list_page_images_handler(const char *html_query, const char *field_name, const char *field_contains, ListPageImagesQueryPost post_handler = nullptr); MangaGenericSearchPage& list_page_images_pagination_handler( const char *pages_html_query, const char *pages_field_name, const char *image_html_query, const char *image_field_name, const char *image_field_contains, const char *next_page_html_query, const char *next_page_field_name, const char *next_page_field_contains); MangaGenericSearchPage& list_page_images_custom_handler(ListPageCustomHandler handler); // For example: mangasite.com/manga/204353&f=23 // /manga/ here would be the |prefix| and & would be |end|. |end| is optional. // The goal is to extract 204353 from the manga chapter page url. MangaGenericSearchPage& manga_id_handler(const char *prefix, const char *end); private: const char *service_name; std::string website_url; bool fail_on_http_error; SearchQuery search_query; std::vector text_queries; std::vector description_queries; std::vector thumbnail_queries; std::vector authors_queries; ListChaptersQuery list_chapters_query; ListPageQuery list_page_query; MangaIdExtractor manga_id_extractor; }; class MangaGenericChaptersPage : public MangaChaptersPage { public: MangaGenericChaptersPage(Program *program, std::string manga_name, std::string manga_url, const std::string &thumbnail_url, const MangaIdExtractor &manga_id_extractor, const char *service_name, const std::string &website_url, const ListPageQuery *list_page_query, bool fail_on_http_error) : MangaChaptersPage(program, std::move(manga_name), std::move(manga_url), thumbnail_url), manga_id_extractor(manga_id_extractor), service_name(service_name), website_url(website_url), list_page_query(list_page_query), fail_on_http_error(fail_on_http_error) {} PluginResult submit(const SubmitArgs &args, std::vector &result_tabs) override; const char* get_bookmark_name() const override { return service_name; } protected: bool extract_id_from_url(const std::string &url, std::string &manga_id) const override; const char* get_service_name() const override { return service_name; } private: MangaIdExtractor manga_id_extractor; const char *service_name; std::string website_url; const ListPageQuery *list_page_query; bool fail_on_http_error; }; class MangaGenericCreatorPage : public LazyFetchPage { public: MangaGenericCreatorPage(Program *program, MangaGenericSearchPage *search_page, Creator creator) : LazyFetchPage(program), search_page(search_page), creator(std::move(creator)) {} const char* get_title() const override { return creator.name.c_str(); } PluginResult submit(const SubmitArgs &args, std::vector &result_tabs) override; PluginResult lazy_fetch(BodyItems &result_items) override; const char* get_bookmark_name() const override { return search_page->get_bookmark_name(); } private: MangaGenericSearchPage *search_page; Creator creator; }; class MangaGenericImagesPage : public MangaImagesPage { public: MangaGenericImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url, const char *service_name, const std::string &website_url, const ListPageQuery *list_page_query, bool fail_on_http_error, std::string thumbnail_url) : MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(url), std::move(thumbnail_url)), service_name(service_name), website_url(website_url), list_page_query(list_page_query), fail_on_http_error(fail_on_http_error) {} virtual ImageResult update_image_urls(int &num_images) override; ImageResult for_each_page_in_chapter(PageCallback callback) override; const char* get_service_name() const override { return service_name; } const char* get_website_url() const override { return website_url.c_str(); } private: ImageResult get_page_image_urls(); private: const char *service_name; std::string website_url; const ListPageQuery *list_page_query; bool fail_on_http_error; std::string current_image_url; std::string next_page_url; }; }