# -*- coding: utf-8 -*- # Copyright 2025 Mike Fährmann # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. """Extractors for https://manga.madokami.al/""" from .common import Extractor, Message from .. import text, util, exception BASE_PATTERN = r"(?:https?://)?manga\.madokami\.al" class MadokamiExtractor(Extractor): """Base class for madokami extractors""" category = "madokami" root = "https://manga.madokami.al" class MadokamiMangaExtractor(MadokamiExtractor): """Extractor for madokami manga""" subcategory = "manga" directory_fmt = ("{category}", "{manga}") archive_fmt = "{chapter_id}" pattern = rf"{BASE_PATTERN}/Manga/(\w/\w{{2}}/\w{{4}}/.+)" example = "https://manga.madokami.al/Manga/A/AB/ABCD/ABCDE_TITLE" def items(self): username, password = self._get_auth_info() if not username: raise exception.AuthRequired("'username' & 'password'") self.session.auth = util.HTTPBasicAuth(username, password) url = f"{self.root}/Manga/{self.groups[0]}" page = self.request(url).text extr = text.extract_from(page) chapters = [] while True: if not (cid := extr('", "<")), "size": text.parse_bytes(extr("", "")), "date": text.parse_datetime( extr("", "").strip(), "%Y-%m-%d %H:%M"), }) if self.config("chapter-reverse"): chapters.reverse() self.kwdict.update({ "manga" : text.unescape(extr('itemprop="name">', "<")), "year" : text.parse_int(extr( 'itemprop="datePublished" content="', "-")), "author": text.split_html(extr('

"))[1::2], "genre" : text.split_html(extr("

Genres

", "")), "tags" : text.split_html(extr("

Tags

", "")), "complete": extr('span class="scanstatus">', "<").lower() == "yes", }) search_chstr = text.re( r"(?i)((?:v(?:ol)?\.?\s*(\d+))" r"(?:\s+ch?\.?\s*(\d+)(?:-(\d+))?)?)").search search_chstr_min = text.re( r"(?i)(ch?\.?\s*(\d+)(?:-(\d+))?)").search for ch in chapters: chstr = ch["chapter_string"] if match := search_chstr(chstr): ch["chapter_string"], volume, chapter, end = match.groups() ch["volume"] = text.parse_int(volume) ch["chapter"] = text.parse_int(chapter) ch["chapter_end"] = text.parse_int(end) elif match := search_chstr_min(chstr): ch["chapter_string"], chapter, end = match.groups() ch["volume"] = 0 ch["chapter"] = text.parse_int(chapter) ch["chapter_end"] = text.parse_int(end) else: ch["volume"] = ch["chapter"] = ch["chapter_end"] = 0 url = f"{self.root}{ch['path']}" text.nameext_from_url(url, ch) yield Message.Directory, ch yield Message.Url, url, ch