Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mikf
GitHub Repository: mikf/gallery-dl
Path: blob/master/gallery_dl/extractor/dankefuerslesen.py
5399 views
1
# -*- coding: utf-8 -*-
2
3
# Copyright 2025 Mike Fährmann
4
#
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License version 2 as
7
# published by the Free Software Foundation.
8
9
"""Extractors for https://danke.moe/"""
10
11
from .common import ChapterExtractor, MangaExtractor
12
from .. import text, util
13
from ..cache import memcache
14
15
BASE_PATTERN = r"(?:https?://)?(?:www\.)?danke\.moe"
16
17
18
class DankefuerslesenBase():
19
"""Base class for dankefuerslesen extractors"""
20
category = "dankefuerslesen"
21
root = "https://danke.moe"
22
23
@memcache(keyarg=1)
24
def _manga_info(self, slug):
25
url = f"{self.root}/api/series/{slug}/"
26
return self.request_json(url)
27
28
29
class DankefuerslesenChapterExtractor(DankefuerslesenBase, ChapterExtractor):
30
"""Extractor for Danke fürs Lesen manga chapters"""
31
pattern = BASE_PATTERN + r"/read/manga/([\w-]+)/([\w-]+)"
32
example = "https://danke.moe/read/manga/TITLE/123/1/"
33
34
def _init(self):
35
self.zip = self.config("zip", False)
36
if self.zip:
37
self.filename_fmt = f"{self.directory_fmt[-1]}.{{extension}}"
38
self.directory_fmt = self.directory_fmt[:-1]
39
40
def metadata(self, page):
41
slug, ch = self.groups
42
manga = self._manga_info(slug)
43
44
if "-" in ch:
45
chapter, sep, minor = ch.rpartition("-")
46
ch = ch.replace("-", ".")
47
minor = "." + minor
48
else:
49
chapter = ch
50
minor = ""
51
52
data = manga["chapters"][ch]
53
group_id, self._files = next(iter(data["groups"].items()))
54
55
if not self.zip:
56
self.base = (f"{self.root}/media/manga/{slug}/chapters"
57
f"/{data['folder']}/{group_id}/")
58
59
return {
60
"manga" : manga["title"],
61
"manga_slug": manga["slug"],
62
"author" : manga["author"],
63
"artist" : manga["artist"],
64
"description": manga["description"],
65
"title" : data["title"],
66
"volume" : text.parse_int(data["volume"]),
67
"chapter" : text.parse_int(chapter),
68
"chapter_minor": minor,
69
"group" : manga["groups"][group_id].split(" & "),
70
"group_id" : text.parse_int(group_id),
71
"date" : text.parse_timestamp(data["release_date"][group_id]),
72
"lang" : util.NONE,
73
"language" : util.NONE,
74
}
75
76
def images(self, page):
77
if self.zip:
78
return ()
79
80
base = self.base
81
return [(base + file, None) for file in self._files]
82
83
def assets(self, page):
84
if self.zip:
85
slug, ch = self.groups
86
url = f"{self.root}/api/download_chapter/{slug}/{ch}/"
87
return ({
88
"type" : "archive",
89
"extension": "zip",
90
"url" : url,
91
},)
92
93
94
class DankefuerslesenMangaExtractor(DankefuerslesenBase, MangaExtractor):
95
"""Extractor for Danke fürs Lesen manga"""
96
chapterclass = DankefuerslesenChapterExtractor
97
reverse = False
98
pattern = BASE_PATTERN + r"/read/manga/([^/?#]+)"
99
example = "https://danke.moe/read/manga/TITLE/"
100
101
def chapters(self, page):
102
results = []
103
104
manga = self._manga_info(self.groups[0]).copy()
105
manga["lang"] = util.NONE
106
manga["language"] = util.NONE
107
108
base = f"{self.root}/read/manga/{manga['slug']}/"
109
for ch, data in manga.pop("chapters").items():
110
111
if "." in ch:
112
chapter, sep, minor = ch.rpartition(".")
113
ch = ch.replace('.', '-')
114
data["chapter"] = text.parse_int(chapter)
115
data["chapter_minor"] = sep + minor
116
else:
117
data["chapter"] = text.parse_int(ch)
118
data["chapter_minor"] = ""
119
120
results.append((f"{base}{ch}/1/", {**manga, **data}))
121
122
return results
123
124