From 92f757e98103d02b8f3ded683ccfaa58a3022e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Sat, 30 Aug 2025 22:26:35 +0200 Subject: [PATCH] [comick] add 'covers' extractor --- docs/supportedsites.md | 4 +-- gallery_dl/extractor/comick.py | 40 ++++++++++++++++++++++++++++-- test/results/comick.py | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/docs/supportedsites.md b/docs/supportedsites.md index 86b4732e..9775d9cc 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -196,7 +196,7 @@ Consider all listed sites to potentially be NSFW. Comick https://comick.io/ - Chapters, Manga + Chapters, Covers, Manga @@ -994,7 +994,7 @@ Consider all listed sites to potentially be NSFW. Tungsten https://tungsten.run/ - Models, Posts + Models, Posts, User Profiles diff --git a/gallery_dl/extractor/comick.py b/gallery_dl/extractor/comick.py index 6c541560..19fc7a99 100644 --- a/gallery_dl/extractor/comick.py +++ b/gallery_dl/extractor/comick.py @@ -8,7 +8,7 @@ """Extractors for https://comick.io/""" -from .common import ChapterExtractor, MangaExtractor, Message +from .common import GalleryExtractor, ChapterExtractor, MangaExtractor, Message from .. import text from ..cache import memcache @@ -21,6 +21,42 @@ class ComickBase(): root = "https://comick.io" +class ComickCoversExtractor(ComickBase, GalleryExtractor): + """Extractor for comick.io manga covers""" + subcategory = "covers" + directory_fmt = ("{category}", "{manga}", "Covers") + filename_fmt = "{volume:>02}_{lang}.{extension}" + archive_fmt = "c_{id}" + pattern = BASE_PATTERN + r"/comic/([\w-]+)/cover" + example = "https://comick.io/comic/MANGA/cover" + + def metadata(self, page): + manga = _manga_info(self, self.groups[0]) + self.slug = manga['manga_slug'] + return manga + + def images(self, page): + url = f"{self.root}/comic/{self.slug}/cover" + page = self.request(url).text + data = self._extract_nextdata(page) + + covers = data["props"]["pageProps"]["comic"]["md_covers"] + covers.reverse() + + return [ + (f"https://meo.comick.pictures/{cover['b2key']}", { + "id" : cover["id"], + "width" : cover["w"], + "height": cover["h"], + "size" : cover["s"], + "lang" : cover["locale"], + "volume": text.parse_int(cover["vol"]), + "cover" : cover, + }) + for cover in covers + ] + + class ComickChapterExtractor(ComickBase, ChapterExtractor): """Extractor for comick.io manga chapters""" archive_fmt = "{chapter_hid}_{page}" @@ -61,7 +97,7 @@ class ComickChapterExtractor(ComickBase, ChapterExtractor): def images(self, page): return [ - ("https://meo.comick.pictures/" + img["b2key"], { + (f"https://meo.comick.pictures/{img['b2key']}", { "width" : img["w"], "height" : img["h"], "size" : img["s"], diff --git a/test/results/comick.py b/test/results/comick.py index 124f6075..8b8c68f5 100644 --- a/test/results/comick.py +++ b/test/results/comick.py @@ -304,4 +304,49 @@ __tests__ = ( "lang" : "iso:639", }, +{ + "#url" : "https://comick.io/comic/neko-no-oshigoto/cover", + "#class" : comick.ComickCoversExtractor, + "#results" : ( + "https://meo.comick.pictures/l6wvkz.jpg", + "https://meo.comick.pictures/X8xRNp.jpg", + ), + + "id" : {45687770, 45687771}, + "width" : {1053, 1055}, + "height" : 1500, + "size" : int, + "lang" : "ja", + "extension" : "jpg", + "manga" : "Neko no Oshigoto", + "volume" : range(1, 2), + "cover" : { + "b2key" : str, + "gpurl" : str, + "h" : int, + "id" : int, + "is_primary" : bool, + "locale" : "ja", + "md_comic_id": int, + "mdid" : "iso:uuid", + "s" : int, + "url" : "iso:uuid", + "vol" : str, + "w" : int, + }, +}, + +{ + "#url" : "https://comick.io/comic/01-sakamoto-days/cover", + "#class" : comick.ComickCoversExtractor, + "#pattern" : r"https://meo\.comick\.pictures/\w+\.jpg", + "#count" : range(50, 80), + + "id" : int, + "width" : int, + "height": int, + "volume": range(1, 30), + "lang" : {"ja", "en", "fr", "pt-br"}, +}, + )