aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-04-16 09:37:53 +0200
committerdec05eba <dec05eba@protonmail.com>2021-04-16 18:50:03 +0200
commitba4e62d55156f9b94b569b56b6382bbcf94b7d86 (patch)
tree1896a38bd43a39a4affcc0e2b4c8d3529fa58a53 /plugins
parentab36fbffef977b99cc03d0b77ac37bdc1b5705dc (diff)
Convert mangatown and manganelos into a generic manga plugin
Revert for_each_page.. processing of manga instead of getting all pages. Mangatown requires you to navigate page by page, cant predict what a specific pages image url will be.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Manga.hpp14
-rw-r--r--plugins/MangaGeneric.hpp166
-rw-r--r--plugins/Mangadex.hpp5
-rw-r--r--plugins/Manganelo.hpp5
-rw-r--r--plugins/Manganelos.hpp33
-rw-r--r--plugins/Mangatown.hpp33
6 files changed, 185 insertions, 71 deletions
diff --git a/plugins/Manga.hpp b/plugins/Manga.hpp
index 60e739b..5dfa800 100644
--- a/plugins/Manga.hpp
+++ b/plugins/Manga.hpp
@@ -14,27 +14,35 @@ namespace QuickMedia {
class MangaImagesPage : public Page {
public:
- MangaImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url) : Page(program), manga_name(std::move(manga_name)), chapter_name(std::move(chapter_name)), url(std::move(url)) {}
+ MangaImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url) : Page(program), manga_name(std::move(manga_name)), chapter_name(std::move(chapter_name)), url(std::move(url)), chapter_num_pages(-1) {}
virtual ~MangaImagesPage() = default;
const char* get_title() const override { return chapter_name.c_str(); }
PageTypez get_type() const override { return PageTypez::MANGA_IMAGES; }
- virtual ImageResult get_page_image_urls(std::vector<std::string> &urls) = 0;
+ virtual ImageResult get_number_of_images(int &num_images) = 0;
+ virtual ImageResult for_each_page_in_chapter(PageCallback callback) = 0;
virtual void change_chapter(std::string new_chapter_name, std::string new_url) {
chapter_name = std::move(new_chapter_name);
- url = std::move(new_url);
+ if(url != new_url) {
+ url = std::move(new_url);
+ chapter_image_urls.clear();
+ chapter_num_pages = -1;
+ }
}
const std::string& get_chapter_name() const { return chapter_name; }
const std::string& get_url() const { return url; }
+ // TODO: Remove and use plugin name instead
virtual const char* get_service_name() const = 0;
const std::string manga_name;
protected:
std::string chapter_name;
std::string url;
+ std::vector<std::string> chapter_image_urls;
+ int chapter_num_pages;
};
class MangaChaptersPage : public TrackablePage {
diff --git a/plugins/MangaGeneric.hpp b/plugins/MangaGeneric.hpp
new file mode 100644
index 0000000..7d63622
--- /dev/null
+++ b/plugins/MangaGeneric.hpp
@@ -0,0 +1,166 @@
+#pragma once
+
+#include "Manga.hpp"
+#include <functional>
+
+namespace QuickMedia {
+ struct SearchQuery {
+ const char *search_prefix = nullptr;
+ const char *page_prefix = nullptr;
+ int page_start = 0;
+ };
+
+ struct TextQuery {
+ const char *html_query = nullptr;
+ const char *title_field = nullptr;
+ const char *url_field = nullptr;
+ const char *url_contains = nullptr;
+ };
+
+ struct ThumbnailQuery {
+ const char *html_query = nullptr;
+ const char *field_name = nullptr;
+ const char *field_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<void(std::vector<std::string> &image_urls)>;
+ struct ListPageImagesQuery {
+ const char *html_query = nullptr;
+ const char *field_name = nullptr;
+ const char *field_contains = nullptr;
+ ListPageImagesQueryPost post_handler = nullptr;
+ };
+
+ // Return the actual number of pages
+ using ListPagePaginationPagesPost = std::function<int(int num_pages)>;
+ struct ListPagePaginationQuery {
+ const char *pages_html_query = nullptr;
+ const char *pages_field_name = nullptr;
+ const char *pages_field_contains = nullptr;
+ ListPagePaginationPagesPost pages_post_handler = 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;
+ };
+
+ enum class ListPageQueryType {
+ IMAGES,
+ PAGINATION
+ };
+
+ struct ListPageQuery {
+ ListPageQueryType type = ListPageQueryType::IMAGES;
+ ListPageImagesQuery images_query;
+ ListPagePaginationQuery pagination_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);
+ const char* get_title() const override { return "All"; }
+ bool search_is_filter() override { return false; }
+ SearchResult search(const std::string &str, BodyItems &result_items) override;
+ PluginResult get_page(const std::string &str, int page, BodyItems &result_items) override;
+ PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override;
+ sf::Vector2i get_thumbnail_max_size() override { return sf::Vector2i(101, 141); };
+
+ // Add a %s where the query or page number should be inserted into |search_prefix| and |page_prefix|, for example:
+ // search_prefix: example.com/search?q=%s
+ // page_prefix: &page=%s
+ // |page_start| is the first page, so the result page is |page_start| + |page| where page is the current page we are navigating on.
+ // This is required.
+ MangaGenericSearchPage& search_handler(const char *search_prefix, const char *page_prefix, int page_start);
+ // If |url_contains| is null, then any matching query is added. If |title_field| is "text", then the inner text is used.
+ // This is required.
+ MangaGenericSearchPage& text_handler(const char *html_query, const char *title_field, const char *url_field, const char *url_contains);
+ // If |field_contains| is null, then any matching query is added. If |field_name| is "text", then the inner text is used.
+ // This is optional.
+ MangaGenericSearchPage& thumbnail_handler(const char *html_query, const char *field_name, const char *field_contains);
+
+ // If |url_contains| is null, then any matching query is added. If |title_field| is "text", then the inner text is used.
+ // This is required.
+ MangaGenericSearchPage& list_chapters_handler(const char *html_query, const char *title_field, const char *url_field, const char *url_contains);
+ // If |field_contains| is null, then any matching query is added. If |field_name| is "text", then the inner text is used.
+ // This is optional.
+ MangaGenericSearchPage& list_chapters_uploaded_time_handler(const char *html_query, const char *field_name, const char *field_contains);
+
+ // If |field_contains| is null, then any matching query is added. If |field_name| is "text", then the inner text is used.
+ // This or |list_page_images_pagination_handler| is required.
+ MangaGenericSearchPage& list_page_images_handler(const char *html_query, const char *field_name, const char *field_contains, ListPageImagesQueryPost post_handler = nullptr);
+
+ // If |pages_field_contains| or |image_field_contains| is null, then any matching query is added. If |pages_field_name| or |image_field_name| is "text", then the inner text is used.
+ // This or |list_page_images_handler| is required.
+ MangaGenericSearchPage& list_page_images_pagination_handler(
+ const char *pages_html_query, const char *pages_field_name, const char *pages_field_contains, ListPagePaginationPagesPost pages_post_handler,
+ 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);
+
+ // 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;
+ SearchQuery search_query;
+ TextQuery text_query;
+ ThumbnailQuery thumbnail_query;
+ 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 MangaIdExtractor &manga_id_extractor, const char *service_name, const std::string &website_url, const ListPageQuery *list_page_query) :
+ MangaChaptersPage(program, std::move(manga_name), std::move(manga_url)), manga_id_extractor(manga_id_extractor), service_name(service_name), website_url(website_url), list_page_query(list_page_query) {}
+ PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override;
+ 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;
+ };
+
+ 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) :
+ MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(url)), service_name(service_name), website_url(website_url), list_page_query(list_page_query) {}
+ ImageResult get_number_of_images(int &num_images) override;
+ ImageResult for_each_page_in_chapter(PageCallback callback) override;
+ const char* get_service_name() const override { return service_name; }
+ private:
+ ImageResult get_page_image_urls();
+ private:
+ const char *service_name;
+ std::string website_url;
+ const ListPageQuery *list_page_query;
+ std::string prev_chapter_url;
+ std::string current_image_url;
+ std::string next_page_url;
+ };
+} \ No newline at end of file
diff --git a/plugins/Mangadex.hpp b/plugins/Mangadex.hpp
index e4a64d8..7fd6ca0 100644
--- a/plugins/Mangadex.hpp
+++ b/plugins/Mangadex.hpp
@@ -31,9 +31,12 @@ namespace QuickMedia {
class MangadexImagesPage : public MangaImagesPage {
public:
MangadexImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url) : MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(url)) {}
- ImageResult get_page_image_urls(std::vector<std::string> &urls) override;
+ ImageResult get_number_of_images(int &num_images) override;
+ ImageResult for_each_page_in_chapter(PageCallback callback) override;
const char* get_service_name() const override { return "mangadex"; }
private:
+ // Cached
+ ImageResult get_image_urls_for_chapter(const std::string &url);
bool save_mangadex_cookies(const std::string &url, const std::string &cookie_filepath);
};
} \ No newline at end of file
diff --git a/plugins/Manganelo.hpp b/plugins/Manganelo.hpp
index 4a7bfc3..530a1f2 100644
--- a/plugins/Manganelo.hpp
+++ b/plugins/Manganelo.hpp
@@ -37,7 +37,10 @@ namespace QuickMedia {
class ManganeloImagesPage : public MangaImagesPage {
public:
ManganeloImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url) : MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(url)) {}
- ImageResult get_page_image_urls(std::vector<std::string> &urls) override;
+ ImageResult get_number_of_images(int &num_images) override;
+ ImageResult for_each_page_in_chapter(PageCallback callback) override;
const char* get_service_name() const override { return "manganelo"; }
+ private:
+ ImageResult get_image_urls_for_chapter(const std::string &url);
};
} \ No newline at end of file
diff --git a/plugins/Manganelos.hpp b/plugins/Manganelos.hpp
deleted file mode 100644
index 4df0c3f..0000000
--- a/plugins/Manganelos.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include "Manga.hpp"
-#include <functional>
-
-namespace QuickMedia {
- class ManganelosSearchPage : public Page {
- public:
- ManganelosSearchPage(Program *program) : Page(program) {}
- const char* get_title() const override { return "All"; }
- bool search_is_filter() override { return false; }
- SearchResult search(const std::string &str, BodyItems &result_items) override;
- PluginResult get_page(const std::string &str, int page, BodyItems &result_items) override;
- PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override;
- sf::Vector2i get_thumbnail_max_size() override { return sf::Vector2i(101, 141); };
- };
-
- class ManganelosChaptersPage : public MangaChaptersPage {
- public:
- ManganelosChaptersPage(Program *program, std::string manga_name, std::string manga_url) : MangaChaptersPage(program, std::move(manga_name), std::move(manga_url)) {}
- PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override;
- protected:
- bool extract_id_from_url(const std::string &url, std::string &manga_id) const override;
- const char* get_service_name() const override { return "manganelos"; }
- };
-
- class ManganelosImagesPage : public MangaImagesPage {
- public:
- ManganelosImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url) : MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(url)) {}
- ImageResult get_page_image_urls(std::vector<std::string> &urls) override;
- const char* get_service_name() const override { return "manganelos"; }
- };
-} \ No newline at end of file
diff --git a/plugins/Mangatown.hpp b/plugins/Mangatown.hpp
deleted file mode 100644
index 0b6c1c4..0000000
--- a/plugins/Mangatown.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include "Manga.hpp"
-#include <functional>
-
-namespace QuickMedia {
- class MangatownSearchPage : public Page {
- public:
- MangatownSearchPage(Program *program) : Page(program) {}
- const char* get_title() const override { return "All"; }
- bool search_is_filter() override { return false; }
- SearchResult search(const std::string &str, BodyItems &result_items) override;
- PluginResult get_page(const std::string &str, int page, BodyItems &result_items) override;
- PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override;
- sf::Vector2i get_thumbnail_max_size() override { return sf::Vector2i(101, 141); };
- };
-
- class MangatownChaptersPage : public MangaChaptersPage {
- public:
- MangatownChaptersPage(Program *program, std::string manga_name, std::string manga_url) : MangaChaptersPage(program, std::move(manga_name), std::move(manga_url)) {}
- PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override;
- protected:
- bool extract_id_from_url(const std::string &url, std::string &manga_id) const override;
- const char* get_service_name() const override { return "mangatown"; }
- };
-
- class MangatownImagesPage : public MangaImagesPage {
- public:
- MangatownImagesPage(Program *program, std::string manga_name, std::string chapter_name, std::string url) : MangaImagesPage(program, std::move(manga_name), std::move(chapter_name), std::move(url)) {}
- ImageResult get_page_image_urls(std::vector<std::string> &urls) override;
- const char* get_service_name() const override { return "mangatown"; }
- };
-} \ No newline at end of file