Merge pull request 'update to work again' (#4) from dev into master
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #4
This commit is contained in:
commit
e62de962a7
8 changed files with 638 additions and 473 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -9,3 +9,5 @@ downloads/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
chaps.txt
|
chaps.txt
|
||||||
|
venv/
|
||||||
|
|
||||||
|
|
12
CHANGELOG.md
Normal file
12
CHANGELOG.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres
|
||||||
|
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
- Add support for new mangadex api
|
||||||
|
- Rewrite api section
|
||||||
|
- Add support for more sites
|
||||||
|
|
177
manga-dlp.py
177
manga-dlp.py
|
@ -1,86 +1,105 @@
|
||||||
import mangadlp.main as MangaDLP
|
import mangadlp.main as mangadlp
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
MangaDLP.main(args.url,
|
mangadlp.main(
|
||||||
args.lang,
|
args.url_uuid,
|
||||||
args.chapters,
|
args.lang,
|
||||||
args.read,
|
args.chapters,
|
||||||
args.list,
|
args.read,
|
||||||
args.nocbz,
|
args.list,
|
||||||
args.forcevol,
|
args.nocbz,
|
||||||
args.path,
|
args.forcevol,
|
||||||
args.wait,
|
args.path,
|
||||||
args.verbose)
|
args.wait,
|
||||||
|
args.verbose,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description='Script to download mangas from various sites')
|
parser = argparse.ArgumentParser(
|
||||||
parser.add_argument('-u', '--url',
|
description="Script to download mangas from various sites"
|
||||||
dest='url',
|
)
|
||||||
required=False,
|
parser.add_argument(
|
||||||
help='URL of the manga',
|
"-u",
|
||||||
action='store',
|
"--url",
|
||||||
)
|
"--uuid",
|
||||||
parser.add_argument('-c', '--chapters',
|
dest="url_uuid",
|
||||||
dest='chapters',
|
required=False,
|
||||||
required=False,
|
help="URL or UUID of the manga",
|
||||||
help='Chapters to download',
|
action="store",
|
||||||
action='store',
|
)
|
||||||
)
|
parser.add_argument(
|
||||||
parser.add_argument('-p', '--path',
|
"-c",
|
||||||
dest='path',
|
"--chapters",
|
||||||
required=False,
|
dest="chapters",
|
||||||
help='Download path. Defaults to "<script_dir>/downloads"',
|
required=False,
|
||||||
action='store',
|
help="Chapters to download",
|
||||||
default='downloads',
|
action="store",
|
||||||
)
|
)
|
||||||
parser.add_argument('-l', '--language',
|
parser.add_argument(
|
||||||
dest='lang',
|
"-p",
|
||||||
required=False,
|
"--path",
|
||||||
help='Manga language. Defaults to "en" --> english',
|
dest="path",
|
||||||
action='store',
|
required=False,
|
||||||
default='en',
|
help='Download path. Defaults to "<script_dir>/downloads"',
|
||||||
)
|
action="store",
|
||||||
parser.add_argument('--read',
|
default="downloads",
|
||||||
dest='read',
|
)
|
||||||
required=False,
|
parser.add_argument(
|
||||||
help='Path of file with manga links to download. One per line',
|
"-l",
|
||||||
action='store',
|
"--language",
|
||||||
)
|
dest="lang",
|
||||||
parser.add_argument('--list',
|
required=False,
|
||||||
dest='list',
|
help='Manga language. Defaults to "en" --> english',
|
||||||
required=False,
|
action="store",
|
||||||
help='List all available chapters. Defaults to false',
|
default="en",
|
||||||
action='store_true',
|
)
|
||||||
)
|
parser.add_argument(
|
||||||
parser.add_argument('--nocbz',
|
"--read",
|
||||||
dest='nocbz',
|
dest="read",
|
||||||
required=False,
|
required=False,
|
||||||
help='Dont pack it to a cbz archive. Defaults to false',
|
help="Path of file with manga links to download. One per line",
|
||||||
action='store_true',
|
action="store",
|
||||||
)
|
)
|
||||||
parser.add_argument('--forcevol',
|
parser.add_argument(
|
||||||
dest='forcevol',
|
"--list",
|
||||||
required=False,
|
dest="list",
|
||||||
help='Force naming of volumes. For mangas where chapters reset each volume',
|
required=False,
|
||||||
action='store_true',
|
help="List all available chapters. Defaults to false",
|
||||||
)
|
action="store_true",
|
||||||
parser.add_argument('--wait',
|
)
|
||||||
dest='wait',
|
parser.add_argument(
|
||||||
required=False,
|
"--nocbz",
|
||||||
type=float,
|
dest="nocbz",
|
||||||
help='Time to wait for each picture to download in seconds(float). Defaults 0.5',
|
required=False,
|
||||||
)
|
help="Dont pack it to a cbz archive. Defaults to false",
|
||||||
parser.add_argument('--verbose',
|
action="store_true",
|
||||||
dest='verbose',
|
)
|
||||||
required=False,
|
parser.add_argument(
|
||||||
help='Verbose logging. Defaults to false',
|
"--forcevol",
|
||||||
action='store_true',
|
dest="forcevol",
|
||||||
)
|
required=False,
|
||||||
|
help="Force naming of volumes. For mangas where chapters reset each volume",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--wait",
|
||||||
|
dest="wait",
|
||||||
|
required=False,
|
||||||
|
type=float,
|
||||||
|
help="Time to wait for each picture to download in seconds(float). Defaults 0.5",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--verbose",
|
||||||
|
dest="verbose",
|
||||||
|
required=False,
|
||||||
|
help="Verbose logging. Defaults to false",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
|
||||||
#parser.print_help()
|
# parser.print_help()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
main(args)
|
|
||||||
|
|
||||||
|
main(args)
|
||||||
|
|
|
@ -1,146 +1,242 @@
|
||||||
import requests
|
|
||||||
import re
|
import re
|
||||||
import mangadlp.utils as MUtils
|
from time import sleep
|
||||||
|
import requests
|
||||||
|
import mangadlp.utils as utils
|
||||||
|
|
||||||
|
|
||||||
class Mangadex():
|
class Mangadex:
|
||||||
|
|
||||||
# api information
|
# api information
|
||||||
api_base_url = 'https://api.mangadex.org'
|
api_base_url = "https://api.mangadex.org"
|
||||||
img_base_url = 'https://uploads.mangadex.org'
|
img_base_url = "https://uploads.mangadex.org"
|
||||||
|
# get infos to initiate class
|
||||||
|
|
||||||
|
def __init__(self, manga_url_uuid, manga_lang, forcevol, verbose):
|
||||||
|
# static info
|
||||||
|
self.manga_url_uuid = manga_url_uuid
|
||||||
|
self.manga_lang = manga_lang
|
||||||
|
self.forcevol = forcevol
|
||||||
|
self.verbose = verbose
|
||||||
|
|
||||||
# get infos to initiate class
|
# api stuff
|
||||||
def __init__(self, manga_url, manga_lang):
|
self.api_content_ratings = "contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic"
|
||||||
self.manga_url = manga_url
|
self.api_language = f"translatedLanguage[]={self.manga_lang}"
|
||||||
self.manga_lang = manga_lang
|
self.api_additions = f"{self.api_language}&{self.api_content_ratings}"
|
||||||
self.manga_uuid = self.get_manga_uuid()
|
|
||||||
self.manga_title = self.get_manga_title(self.manga_uuid)
|
|
||||||
self.manga_chapter_data = self.get_manga_chapters(self.manga_uuid)
|
|
||||||
|
|
||||||
|
# infos from functions
|
||||||
|
self.manga_uuid = self.get_manga_uuid()
|
||||||
|
self.manga_data = self.get_manga_data()
|
||||||
|
self.manga_title = self.get_manga_title()
|
||||||
|
self.manga_chapter_data = self.get_chapter_data()
|
||||||
|
|
||||||
# get the uuid for the manga
|
# make initial request
|
||||||
def get_manga_uuid(self):
|
def get_manga_data(self):
|
||||||
# isolate id from url
|
if self.verbose:
|
||||||
uuid_regex = re.compile('[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}')
|
print(f"INFO: Getting manga data for: {self.manga_uuid}")
|
||||||
# check for new mangadex id
|
counter = 1
|
||||||
if uuid_regex.search(self.manga_url):
|
while counter < 3:
|
||||||
manga_uuid = uuid_regex.search(self.manga_url)[0]
|
try:
|
||||||
else:
|
manga_data = requests.get(
|
||||||
print('No valid uuid found')
|
f"{self.api_base_url}/manga/{self.manga_uuid}"
|
||||||
exit(1)
|
)
|
||||||
# check if the manga exists
|
except:
|
||||||
try:
|
if counter >= 3:
|
||||||
req = requests.get(f'{self.api_base_url}/manga/{manga_uuid}')
|
print("ERR: Maybe the MangaDex API is down?")
|
||||||
except:
|
exit(1)
|
||||||
print('Error. Maybe the MangaDex API is down?')
|
else:
|
||||||
exit(1)
|
print("ERR: Mangadex API not reachable. Retrying")
|
||||||
else:
|
sleep(2)
|
||||||
# check mangadex status
|
counter += 1
|
||||||
response = req.json()['result']
|
else:
|
||||||
if not response == 'ok':
|
break
|
||||||
print('Manga not found')
|
# check if manga exists
|
||||||
exit(1)
|
if manga_data.json()["result"] != "ok":
|
||||||
|
print("ERR: Manga not found")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
return manga_uuid
|
return manga_data
|
||||||
|
|
||||||
|
# get the uuid for the manga
|
||||||
|
def get_manga_uuid(self):
|
||||||
|
# isolate id from url
|
||||||
|
uuid_regex = re.compile(
|
||||||
|
"[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}"
|
||||||
|
)
|
||||||
|
# check for new mangadex id
|
||||||
|
if not uuid_regex.search(self.manga_url_uuid):
|
||||||
|
print("ERR: No valid UUID found")
|
||||||
|
exit(1)
|
||||||
|
manga_uuid = uuid_regex.search(self.manga_url_uuid)[0]
|
||||||
|
return manga_uuid
|
||||||
|
|
||||||
# get the title of the manga (and fix the filename)
|
# get the title of the manga (and fix the filename)
|
||||||
def get_manga_title(self, manga_uuid):
|
def get_manga_title(self):
|
||||||
req = requests.get(f'{self.api_base_url}/manga/{manga_uuid}')
|
if self.verbose:
|
||||||
api_resp = req.json()
|
print(f"INFO: Getting manga title for: {self.manga_uuid}")
|
||||||
try:
|
manga_data = self.manga_data.json()
|
||||||
title = api_resp['data']['attributes']['title'][self.manga_lang]
|
try:
|
||||||
except:
|
title = manga_data["data"]["attributes"]["title"][self.manga_lang]
|
||||||
# search in alt titles
|
except:
|
||||||
try:
|
# search in alt titles
|
||||||
alt_titles = {}
|
try:
|
||||||
for title in api_resp['data']['attributes']['altTitles']:
|
alt_titles = {}
|
||||||
alt_titles.update(title)
|
for title in manga_data["data"]["attributes"]["altTitles"]:
|
||||||
title = alt_titles[self.manga_lang]
|
alt_titles.update(title)
|
||||||
except: # no title on requested language found
|
title = alt_titles[self.manga_lang]
|
||||||
print('Chapter in requested language not found.')
|
except: # no title on requested language found
|
||||||
exit(1)
|
print("ERR: Chapter in requested language not found.")
|
||||||
|
exit(1)
|
||||||
|
return utils.fix_name(title)
|
||||||
|
|
||||||
return MUtils.fix_name(title)
|
# check if chapters are available in requested language
|
||||||
|
def check_chapter_lang(self):
|
||||||
|
if self.verbose:
|
||||||
|
print(
|
||||||
|
f"INFO: Checking for chapters in specified language for: {self.manga_uuid}"
|
||||||
|
)
|
||||||
|
r = requests.get(
|
||||||
|
f"{self.api_base_url}/manga/{self.manga_uuid}/feed?limit=0&{self.api_additions}"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
total_chapters = r.json()["total"]
|
||||||
|
except:
|
||||||
|
print(
|
||||||
|
"ERR: Error retrieving the chapters list. Did you specify a valid language code?"
|
||||||
|
)
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
if total_chapters == 0:
|
||||||
|
print("ERR: No chapters available to download!")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return total_chapters
|
||||||
|
|
||||||
# get all chapter data for further parsing
|
# get chapter data like name, uuid etc
|
||||||
def get_manga_chapters(self, manga_uuid):
|
def get_chapter_data(self):
|
||||||
content_ratings = 'contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic'
|
if self.verbose:
|
||||||
chap_data_list = []
|
print(f"INFO: Getting chapter data for: {self.manga_uuid}")
|
||||||
req = requests.get(f'{self.api_base_url}/manga/{manga_uuid}/feed?limit=0&translatedLanguage[]={self.manga_lang}&{content_ratings}')
|
api_sorting = "order[chapter]=asc&order[volume]=asc"
|
||||||
try:
|
# check for chapters in specified lang
|
||||||
total = req.json()['total']
|
total_chapters = self.check_chapter_lang()
|
||||||
except:
|
if total_chapters == 0:
|
||||||
print('Error retrieving the chapters list. Did you specify a valid language code?')
|
exit(1)
|
||||||
exit(1)
|
|
||||||
if total == 0:
|
|
||||||
print('No chapters available to download!')
|
|
||||||
exit(0)
|
|
||||||
last_chap = ['', '']
|
|
||||||
offset = 0
|
|
||||||
while offset < total: # if more than 500 chapters
|
|
||||||
req = requests.get(f'{self.api_base_url}/manga/{manga_uuid}/feed?order[chapter]=asc&order[volume]=asc&limit=500&translatedLanguage[]={self.manga_lang}&offset={offset}&{content_ratings}')
|
|
||||||
for chapter in req.json()['data']:
|
|
||||||
chap_num = chapter['attributes']['chapter']
|
|
||||||
chap_vol = chapter['attributes']['volume']
|
|
||||||
chap_uuid = chapter['id']
|
|
||||||
chap_hash = chapter['attributes']['hash']
|
|
||||||
chap_data = chapter['attributes']['data']
|
|
||||||
chap_name = chapter['attributes']['title']
|
|
||||||
if not chap_name == None:
|
|
||||||
chap_name = MUtils.fix_name(chap_name)
|
|
||||||
# check if the chapter is external (cant download them)
|
|
||||||
chap_external = chapter['attributes']['externalUrl']
|
|
||||||
# name chapter "oneshot" if there is no chapter number
|
|
||||||
if chap_external == None and chap_num == None:
|
|
||||||
# check for duplicates
|
|
||||||
if last_chap[0] == chap_vol and last_chap[1] == chap_num:
|
|
||||||
continue
|
|
||||||
chap_data_list.append([chap_vol, 'Oneshot', chap_uuid, chap_hash, chap_name, chap_data])
|
|
||||||
# else add chapter number
|
|
||||||
elif chap_external == None:
|
|
||||||
# check for duplicates
|
|
||||||
if last_chap[0] == chap_vol and last_chap[1] == chap_num:
|
|
||||||
continue
|
|
||||||
chap_data_list.append([chap_vol, chap_num, chap_uuid, chap_hash, chap_name, chap_data])
|
|
||||||
last_chap = [chap_vol, chap_num]
|
|
||||||
offset += 500
|
|
||||||
|
|
||||||
return chap_data_list
|
chapter_data = {}
|
||||||
|
last_chapter = ["", ""]
|
||||||
|
offset = 0
|
||||||
|
while offset < total_chapters: # if more than 500 chapters
|
||||||
|
r = requests.get(
|
||||||
|
f"{self.api_base_url}/manga/{self.manga_uuid}/feed?{api_sorting}&limit=500&offset={offset}&{self.api_additions}"
|
||||||
|
)
|
||||||
|
for chapter in r.json()["data"]:
|
||||||
|
# chapter infos from feed
|
||||||
|
chapter_num = chapter["attributes"]["chapter"]
|
||||||
|
chapter_vol = chapter["attributes"]["volume"]
|
||||||
|
chapter_uuid = chapter["id"]
|
||||||
|
chapter_name = chapter["attributes"]["title"]
|
||||||
|
chapter_external = chapter["attributes"]["externalUrl"]
|
||||||
|
|
||||||
|
# check for chapter title and fix it
|
||||||
|
if chapter_name is None:
|
||||||
|
chapter_name = "No Title"
|
||||||
|
else:
|
||||||
|
chapter_name = utils.fix_name(chapter_name)
|
||||||
|
# check if the chapter is external (can't download them)
|
||||||
|
if chapter_external is not None:
|
||||||
|
continue
|
||||||
|
# name chapter "oneshot" if there is no chapter number
|
||||||
|
if chapter_num is None:
|
||||||
|
chapter_num = "Oneshot"
|
||||||
|
|
||||||
def get_chapter_index(self, chapter, forcevol):
|
# check if its duplicate from the last entry
|
||||||
# get index of chapter
|
if last_chapter[0] == chapter_vol and last_chapter[1] == chapter_num:
|
||||||
if forcevol:
|
continue
|
||||||
chapter_index = next(c for c in self.manga_chapter_data if f'{c[0]}:{c[1]}' == chapter)
|
|
||||||
else:
|
|
||||||
chapter_index = next(c for c in self.manga_chapter_data if c[1] == chapter)
|
|
||||||
|
|
||||||
return chapter_index
|
# export chapter data as a dict
|
||||||
|
chapter_index = (
|
||||||
|
chapter_num if not self.forcevol else f"{chapter_vol}:{chapter_num}"
|
||||||
|
)
|
||||||
|
chapter_data[chapter_index] = [
|
||||||
|
chapter_uuid,
|
||||||
|
chapter_vol,
|
||||||
|
chapter_num,
|
||||||
|
chapter_name,
|
||||||
|
]
|
||||||
|
# add last chapter to duplicate check
|
||||||
|
last_chapter = [chapter_vol, chapter_num]
|
||||||
|
|
||||||
|
# increase offset for mangas with more than 500 chapters
|
||||||
|
offset += 500
|
||||||
|
|
||||||
# create list of chapters
|
return chapter_data
|
||||||
def create_chapter_list(self, chapter_data, forcevol):
|
|
||||||
chapter_list = []
|
|
||||||
for chap in chapter_data:
|
|
||||||
volume_number = chap[0]
|
|
||||||
chapter_number = chap[1]
|
|
||||||
if forcevol:
|
|
||||||
chapter_list.append(f'{volume_number}:{chapter_number}')
|
|
||||||
else:
|
|
||||||
chapter_list.append(chapter_number)
|
|
||||||
|
|
||||||
return chapter_list
|
# get images for the chapter (mangadex@home)
|
||||||
|
def get_chapter_images(self, chapter):
|
||||||
|
if self.verbose:
|
||||||
|
print(f"INFO: Getting chapter images for: {self.manga_uuid}")
|
||||||
|
athome_url = f"{self.api_base_url}/at-home/server"
|
||||||
|
chapter_uuid = self.manga_chapter_data[chapter][0]
|
||||||
|
|
||||||
|
r = requests.get(f"{athome_url}/{chapter_uuid}")
|
||||||
|
api_data = r.json()
|
||||||
|
if api_data["result"] != "ok":
|
||||||
|
print(f"ERR: No chapter with the id {chapter_uuid} found")
|
||||||
|
elif api_data["chapter"]["data"] is None:
|
||||||
|
print(f"ERR: No chapter data found for chapter {chapter_uuid}")
|
||||||
|
|
||||||
# get list of image urls
|
chapter_hash = api_data["chapter"]["hash"]
|
||||||
def get_img_urls(self, images, chapter_hash):
|
chapter_img_data = api_data["chapter"]["data"]
|
||||||
img_urls = []
|
|
||||||
for img in images:
|
|
||||||
img_urls.append(f'{self.img_base_url}/data/{chapter_hash}/{img}')
|
|
||||||
|
|
||||||
return img_urls
|
# get list of image urls
|
||||||
|
image_urls = []
|
||||||
|
for image in chapter_img_data:
|
||||||
|
image_urls.append(f"{self.img_base_url}/data/{chapter_hash}/{image}")
|
||||||
|
|
||||||
|
return image_urls
|
||||||
|
|
||||||
|
# create list of chapters
|
||||||
|
def create_chapter_list(self):
|
||||||
|
if self.verbose:
|
||||||
|
print(f"INFO: Creating chapter list for: {self.manga_uuid}")
|
||||||
|
chapter_list = []
|
||||||
|
for chapter in self.manga_chapter_data.items():
|
||||||
|
chapter_info = self.get_chapter_infos(chapter[0])
|
||||||
|
chapter_number = chapter_info["chapter"]
|
||||||
|
volume_number = chapter_info["volume"]
|
||||||
|
if self.forcevol:
|
||||||
|
chapter_list.append(f"{volume_number}:{chapter_number}")
|
||||||
|
else:
|
||||||
|
chapter_list.append(chapter_number)
|
||||||
|
|
||||||
|
return chapter_list
|
||||||
|
|
||||||
|
# create filename for chapter
|
||||||
|
def get_filename(self, chapter):
|
||||||
|
if self.verbose:
|
||||||
|
print(f"INFO: Creating filename for: {self.manga_uuid}")
|
||||||
|
chapter_info = self.get_chapter_infos(chapter)
|
||||||
|
chapter_name = chapter_info["name"]
|
||||||
|
chapter_num = chapter_info["chapter"]
|
||||||
|
volume_number = chapter_info["volume"]
|
||||||
|
|
||||||
|
return utils.get_filename(
|
||||||
|
chapter_name, volume_number, chapter_num, self.forcevol
|
||||||
|
)
|
||||||
|
|
||||||
|
# create easy to access chapter infos
|
||||||
|
def get_chapter_infos(self, chapter):
|
||||||
|
if self.verbose:
|
||||||
|
print(
|
||||||
|
f"INFO: Getting chapter infos for: {self.manga_chapter_data[chapter][0]}"
|
||||||
|
)
|
||||||
|
chapter_uuid = self.manga_chapter_data[chapter][0]
|
||||||
|
chapter_vol = self.manga_chapter_data[chapter][1]
|
||||||
|
chapter_num = self.manga_chapter_data[chapter][2]
|
||||||
|
chapter_name = self.manga_chapter_data[chapter][3]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"uuid": chapter_uuid,
|
||||||
|
"volume": chapter_vol,
|
||||||
|
"chapter": chapter_num,
|
||||||
|
"name": chapter_name,
|
||||||
|
}
|
||||||
|
|
|
@ -1,34 +1,33 @@
|
||||||
import shutil
|
import shutil
|
||||||
import requests
|
|
||||||
from time import sleep
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from time import sleep
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# download images
|
||||||
def download_chapter(image_urls, chapter_path, md_wait=0.5, md_verbose=False):
|
def download_chapter(image_urls, chapter_path, md_wait=0.5, md_verbose=False):
|
||||||
# download images
|
img_num = 1
|
||||||
img_num = 1
|
for img in image_urls:
|
||||||
for img in image_urls:
|
# set image path
|
||||||
# set image path
|
image_path = Path(f"{chapter_path}/{img_num:03d}")
|
||||||
image_path = Path(f'{chapter_path}/{img_num:03d}')
|
try:
|
||||||
try:
|
# print('Try getting ' + img)
|
||||||
#print('Try getting ' + img)
|
req = requests.get(img, stream=True)
|
||||||
req = requests.get(img, stream = True)
|
except:
|
||||||
except:
|
print(f"ERR: Request for image {img} failed, retrying")
|
||||||
print(f'Request for image {img} failed, retrying')
|
sleep(md_wait)
|
||||||
sleep(md_wait)
|
req = requests.get(img, stream=True)
|
||||||
req = requests.get(img, stream = True)
|
|
||||||
|
|
||||||
if req.status_code == 200:
|
if req.status_code == 200:
|
||||||
req.raw.decode_content = True
|
req.raw.decode_content = True
|
||||||
with image_path.open('wb') as file:
|
with image_path.open("wb") as file:
|
||||||
shutil.copyfileobj(req.raw, file)
|
shutil.copyfileobj(req.raw, file)
|
||||||
|
|
||||||
# verbose logging
|
# verbose logging
|
||||||
if md_verbose:
|
if md_verbose:
|
||||||
print(f' Downloaded image {img_num}')
|
print(f"INFO: Downloaded image {img_num}")
|
||||||
|
|
||||||
img_num += 1
|
img_num += 1
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
else:
|
else:
|
||||||
print('Image {img} could not be downloaded. Exiting')
|
print(f"ERR: Image {img} could not be downloaded. Exiting")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
411
mangadlp/main.py
411
mangadlp/main.py
|
@ -1,219 +1,248 @@
|
||||||
from pathlib import Path
|
|
||||||
import re
|
import re
|
||||||
from mangadlp import api
|
from pathlib import Path
|
||||||
import mangadlp.utils as MUtils
|
|
||||||
import mangadlp.downloader as MDownloader
|
import mangadlp.downloader as downloader
|
||||||
|
import mangadlp.utils as utils
|
||||||
|
|
||||||
# supported api's
|
# supported api's
|
||||||
from mangadlp.api.mangadex import Mangadex
|
from mangadlp.api.mangadex import Mangadex
|
||||||
|
|
||||||
|
|
||||||
def main(manga_url='',
|
def main(
|
||||||
manga_language='en',
|
manga_url_uuid="",
|
||||||
manga_chapters=None,
|
manga_language="en",
|
||||||
manga_readlist='',
|
manga_chapters=None,
|
||||||
manga_list_chapters=False,
|
manga_readlist="",
|
||||||
manga_nocbz=False,
|
manga_list_chapters=False,
|
||||||
manga_forcevol=False,
|
manga_nocbz=False,
|
||||||
download_path='downloads',
|
manga_forcevol=False,
|
||||||
download_wait=0.5,
|
download_path="downloads",
|
||||||
log_verbose=False):
|
download_wait=0.5,
|
||||||
'''Download Mangas from supported sites\n
|
log_verbose=False,
|
||||||
|
):
|
||||||
|
"""Download Mangas from supported sites\n
|
||||||
|
|
||||||
Args:\n
|
Args:\n
|
||||||
url (str) -- Manga URL to Download. No defaults\n
|
url (str) -- Manga URL or UUID to Download. No defaults\n
|
||||||
lang (str) -- Language to download chapters in. Defaults to "en" -> english\n
|
lang (str) -- Language to download chapters in. Defaults to "en" -> english\n
|
||||||
chapter (str) -- Chapters to download "all" for every chapter available. Defaults to none\n
|
chapter (str) -- Chapters to download "all" for every chapter available. Defaults to none\n
|
||||||
readlist (str) -- List of chapters to read in. One link per line. No defaults\n
|
readlist (str) -- List of chapters to read in. One link per line. No defaults\n
|
||||||
list_chapters (bool) -- If it should only list all available chapters. Defaults to False\n
|
list_chapters (bool) -- If it should only list all available chapters. Defaults to False\n
|
||||||
nocbz (bool) -- If the downloaded images should not be packed into a .cbz archive. Defaults to false\n
|
nocbz (bool) -- If the downloaded images should not be packed into a .cbz archive. Defaults to false\n
|
||||||
forcevol (bool) -- Force naming of volumes. For mangas where chapters reset each volume. Defaults to false.\n
|
forcevol (bool) -- Force naming of volumes. For mangas where chapters reset each volume. Defaults to false.\n
|
||||||
download_path (str) -- Folder to save mangas to. Defaults to "<script_dir>/downloads"\n
|
download_path (str) -- Folder to save mangas to. Defaults to "<script_dir>/downloads"\n
|
||||||
download_wait (float) -- Time to wait for each picture to download in seconds(float). Defaults 0.5.\n
|
download_wait (float) -- Time to wait for each picture to download in seconds(float). Defaults 0.5.\n
|
||||||
log_verbose (bool) -- If verbose logging is enabled. Defaults to false\n
|
log_verbose (bool) -- If verbose logging is enabled. Defaults to false\n
|
||||||
|
|
||||||
Returns:\n
|
Returns:\n
|
||||||
nothing\n
|
nothing\n
|
||||||
'''
|
"""
|
||||||
# prechecks userinput/options
|
# prechecks userinput/options
|
||||||
if not manga_list_chapters and manga_chapters == None:
|
if not manga_list_chapters and manga_chapters is None:
|
||||||
# no chapters to download were given
|
# no chapters to download were given
|
||||||
print(f'You need to specify one or more chapters to download. To see all chapters use "--list"')
|
print(
|
||||||
exit(1)
|
f'ERR: You need to specify one or more chapters to download. To see all chapters use "--list"'
|
||||||
# no url and no readin list given
|
)
|
||||||
elif not manga_url and not manga_readlist:
|
exit(1)
|
||||||
print(f'You need to specify a manga url with "-u" or a list with "--read"')
|
# no url and no readin list given
|
||||||
exit(1)
|
elif not manga_url_uuid and not manga_readlist:
|
||||||
# url and readin list given
|
print(
|
||||||
elif manga_url and manga_readlist:
|
f'ERR: You need to specify a manga url/uuid with "-u" or a list with "--read"'
|
||||||
print(f'You can only use "-u" or "--read". Dont specify both')
|
)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
# url and readin list given
|
||||||
|
elif manga_url_uuid and manga_readlist:
|
||||||
|
print(f'ERR: You can only use "-u" or "--read". Dont specify both')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
# check if readin file was specified
|
# check if readin file was specified
|
||||||
if manga_readlist:
|
if manga_readlist:
|
||||||
# loop trough every chapter in readin file
|
# loop trough every chapter in readin file
|
||||||
for url in readin_list(manga_readlist):
|
for url in readin_list(manga_readlist):
|
||||||
ApiUsed = check_api(url)
|
api_used = check_api(url)
|
||||||
if not ApiUsed:
|
if not api_used:
|
||||||
continue
|
continue
|
||||||
if log_verbose:
|
# get manga
|
||||||
print(f'Api used: {ApiUsed}')
|
get_manga(
|
||||||
# get manga
|
api_used,
|
||||||
get_manga(ApiUsed, url, manga_language, manga_chapters, manga_list_chapters, manga_nocbz, manga_forcevol, download_path, download_wait, log_verbose)
|
url,
|
||||||
else:
|
manga_language,
|
||||||
# single manga
|
manga_chapters,
|
||||||
ApiUsed = check_api(manga_url)
|
manga_list_chapters,
|
||||||
if not ApiUsed:
|
manga_nocbz,
|
||||||
exit(1)
|
manga_forcevol,
|
||||||
if log_verbose:
|
download_path,
|
||||||
print(f'Api used: {ApiUsed}')
|
download_wait,
|
||||||
# get manga
|
log_verbose,
|
||||||
get_manga(ApiUsed, manga_url, manga_language, manga_chapters, manga_list_chapters, manga_nocbz, manga_forcevol, download_path, download_wait, log_verbose)
|
)
|
||||||
|
else:
|
||||||
|
# single manga
|
||||||
|
api_used = check_api(manga_url_uuid)
|
||||||
|
if not api_used:
|
||||||
|
exit(1)
|
||||||
|
# get manga
|
||||||
|
get_manga(
|
||||||
|
api_used,
|
||||||
|
manga_url_uuid,
|
||||||
|
manga_language,
|
||||||
|
manga_chapters,
|
||||||
|
manga_list_chapters,
|
||||||
|
manga_nocbz,
|
||||||
|
manga_forcevol,
|
||||||
|
download_path,
|
||||||
|
download_wait,
|
||||||
|
log_verbose,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# read in the list of links from a file
|
# read in the list of links from a file
|
||||||
def readin_list(manga_readlist):
|
def readin_list(manga_readlist):
|
||||||
url_file = Path(manga_readlist)
|
url_file = Path(manga_readlist)
|
||||||
url_list = []
|
url_list = []
|
||||||
with url_file.open('r') as file:
|
with url_file.open("r") as file:
|
||||||
for line in file:
|
for line in file:
|
||||||
url_list.append(line.rstrip())
|
url_list.append(line.rstrip())
|
||||||
|
|
||||||
return url_list
|
return url_list
|
||||||
|
|
||||||
|
|
||||||
# check the api which needs to be used
|
# check the api which needs to be used
|
||||||
def check_api(manga_url):
|
def check_api(manga_url):
|
||||||
# apis to check
|
# apis to check
|
||||||
api_mangadex = re.compile('mangadex.org')
|
api_mangadex = re.compile("mangadex.org")
|
||||||
api_test = re.compile('test.test')
|
api_mangadex2 = re.compile(
|
||||||
# check url for match
|
"[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}"
|
||||||
if api_mangadex.search(manga_url):
|
)
|
||||||
return Mangadex
|
api_test = re.compile("test.test")
|
||||||
# this is only for testing multiple apis
|
# check url for match
|
||||||
elif api_test.search(manga_url):
|
if api_mangadex.search(manga_url) or api_mangadex2.search(manga_url):
|
||||||
pass
|
return Mangadex
|
||||||
# no supported api found
|
# this is only for testing multiple apis
|
||||||
else:
|
elif api_test.search(manga_url):
|
||||||
print(f'No supported api in link found\n{manga_url}')
|
pass
|
||||||
return False
|
# no supported api found
|
||||||
|
else:
|
||||||
|
print(f"ERR: No supported api in link/uuid found\n{manga_url}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
# main function to get the chapters
|
# main function to get the chapters
|
||||||
def get_manga(ApiUsed, manga_url, manga_language, manga_chapters, manga_list_chapters, manga_nocbz, manga_forcevol, download_path, download_wait, log_verbose):
|
def get_manga(
|
||||||
# init api
|
api_used,
|
||||||
Api = ApiUsed(manga_url, manga_language)
|
manga_url,
|
||||||
# get manga title and uuid
|
manga_language,
|
||||||
manga_uuid = Api.manga_uuid
|
manga_chapters,
|
||||||
manga_title = Api.manga_title
|
manga_list_chapters,
|
||||||
# get chapter data
|
manga_nocbz,
|
||||||
manga_chapter_data = Api.manga_chapter_data
|
manga_forcevol,
|
||||||
# crate chapter list
|
download_path,
|
||||||
manga_chapter_list = Api.create_chapter_list(manga_chapter_data, manga_forcevol)
|
download_wait,
|
||||||
|
log_verbose,
|
||||||
# print infos
|
):
|
||||||
print('\n=========================================')
|
# show api used
|
||||||
print(f'Manga Name: {manga_title}')
|
|
||||||
print(f'UUID: {manga_uuid}')
|
|
||||||
print(f'Total chapters: {len(manga_chapter_list)}')
|
|
||||||
|
|
||||||
# list chapters if manga_list_chapters is true
|
|
||||||
if manga_list_chapters:
|
|
||||||
print(f'Available Chapters:\n{", ".join(manga_chapter_list)}')
|
|
||||||
print('=========================================\n')
|
|
||||||
return
|
|
||||||
|
|
||||||
# check chapters to download if it not all
|
|
||||||
chapters_to_download = []
|
|
||||||
if manga_chapters.lower() == 'all':
|
|
||||||
chapters_to_download = manga_chapter_list
|
|
||||||
else:
|
|
||||||
chapters_to_download = MUtils.get_chapter_list(manga_chapters)
|
|
||||||
|
|
||||||
# show chapters to download
|
|
||||||
print(f'Chapters selected:\n{", ".join(chapters_to_download)}')
|
|
||||||
print('=========================================\n')
|
|
||||||
|
|
||||||
# create manga folder
|
|
||||||
manga_path = Path(f'{download_path}/{manga_title}')
|
|
||||||
manga_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
# main download loop
|
|
||||||
for chapter in chapters_to_download:
|
|
||||||
# get index of chapter
|
|
||||||
chapter_index = Api.get_chapter_index(chapter, manga_forcevol)
|
|
||||||
|
|
||||||
# default mapping of chapter data
|
|
||||||
chapter_vol = chapter_index[0]
|
|
||||||
chapter_num = chapter_index[1]
|
|
||||||
chapter_uuid = chapter_index[2]
|
|
||||||
chapter_hash = chapter_index[3]
|
|
||||||
chapter_name = chapter_index[4]
|
|
||||||
chapter_img_data = chapter_index[5]
|
|
||||||
# create image urls from img data
|
|
||||||
image_urls = Api.get_img_urls(chapter_img_data, chapter_hash)
|
|
||||||
|
|
||||||
# get filename for chapter
|
|
||||||
chapter_filename = MUtils.get_filename(chapter_name, chapter_vol, chapter_num, manga_forcevol)
|
|
||||||
|
|
||||||
# set download path for chapter
|
|
||||||
chapter_path = manga_path / chapter_filename
|
|
||||||
|
|
||||||
# check if chapter already exists.
|
|
||||||
# check for folder if option nocbz is given. if nocbz is not given, the folder will be overwritten
|
|
||||||
if MUtils.check_existence(chapter_path, manga_nocbz) and manga_forcevol:
|
|
||||||
print(f'- Vol {chapter_vol} Chapter {chapter_num} already exists. Skipping\n')
|
|
||||||
continue
|
|
||||||
elif MUtils.check_existence(chapter_path, manga_nocbz):
|
|
||||||
print(f'- Chapter {chapter_num} already exists. Skipping\n')
|
|
||||||
continue
|
|
||||||
|
|
||||||
# create chapter folder (skips it if it already exists)
|
|
||||||
chapter_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
# verbose log
|
|
||||||
if log_verbose:
|
if log_verbose:
|
||||||
print(f'Chapter UUID: {chapter_uuid}')
|
print(f"INFO: API used: {api_used}")
|
||||||
print(f'Filename: {chapter_path}\n' if manga_nocbz else f'Filename: {chapter_path}.cbz\n')
|
# init api
|
||||||
print(f'Image URLS: {image_urls}')
|
Api = api_used(manga_url, manga_language, manga_forcevol, log_verbose)
|
||||||
print(f'DEBUG: Downloading Volume {chapter_vol}')
|
# get manga title and uuid
|
||||||
|
manga_uuid = Api.manga_uuid
|
||||||
|
manga_title = Api.manga_title
|
||||||
|
# crate chapter list
|
||||||
|
manga_chapter_list = Api.create_chapter_list()
|
||||||
|
|
||||||
# log
|
# show infos
|
||||||
if manga_forcevol:
|
print_divider = "========================================="
|
||||||
print(f'+ Downloading Volume {chapter_vol} Chapter {chapter_num}')
|
print(f"\n{print_divider}")
|
||||||
|
print(f"INFO: Manga Name: {manga_title}")
|
||||||
|
print(f"INFO: Manga UUID: {manga_uuid}")
|
||||||
|
print(f"INFO: Total chapters: {len(manga_chapter_list)}")
|
||||||
|
|
||||||
|
# list chapters if manga_list_chapters is true
|
||||||
|
if manga_list_chapters:
|
||||||
|
print(f'INFO: Available Chapters:\n{", ".join(manga_chapter_list)}')
|
||||||
|
print(f"{print_divider}\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
# check chapters to download if not all
|
||||||
|
if manga_chapters.lower() == "all":
|
||||||
|
chapters_to_download = manga_chapter_list
|
||||||
else:
|
else:
|
||||||
print(f'+ Downloading Chapter {chapter_num}')
|
chapters_to_download = utils.get_chapter_list(manga_chapters)
|
||||||
|
|
||||||
# download images
|
# show chapters to download
|
||||||
try:
|
print(f'INFO: Chapters selected:\n{", ".join(chapters_to_download)}')
|
||||||
MDownloader.download_chapter(image_urls, chapter_path, download_wait, log_verbose)
|
print(f"{print_divider}\n")
|
||||||
except:
|
|
||||||
if manga_forcevol:
|
|
||||||
print(f'Cant download volume {chapter_vol} chapter {chapter_num}. Exiting')
|
|
||||||
else:
|
|
||||||
print(f'Cant download chapter {chapter_num}. Exiting')
|
|
||||||
exit(1)
|
|
||||||
else:
|
|
||||||
# Done with chapter
|
|
||||||
if manga_forcevol:
|
|
||||||
print(f'Successfully downloaded volume {chapter_vol} chapter {chapter_num}')
|
|
||||||
else:
|
|
||||||
print(f'Successfully downloaded chapter {chapter_num}')
|
|
||||||
|
|
||||||
# make cbz of folder
|
# create manga folder
|
||||||
if not manga_nocbz:
|
manga_path = Path(f"{download_path}/{manga_title}")
|
||||||
print('\n+ Creating .cbz archive')
|
manga_path.mkdir(parents=True, exist_ok=True)
|
||||||
try:
|
|
||||||
MUtils.make_archive(chapter_path)
|
|
||||||
except:
|
|
||||||
print('Could not make cbz archive')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
# done with chapter
|
# main download loop
|
||||||
print('Done with chapter')
|
for chapter in chapters_to_download:
|
||||||
print('------------------------------\n')
|
# get chapter infos
|
||||||
|
chapter_infos = Api.get_chapter_infos(chapter)
|
||||||
|
|
||||||
# done with manga
|
# get image urls for chapter
|
||||||
print('=============================')
|
chapter_image_urls = Api.get_chapter_images(chapter)
|
||||||
print(f'Done with manga: {manga_title}')
|
|
||||||
print('=============================\n')
|
|
||||||
|
|
||||||
|
# get filename for chapter
|
||||||
|
chapter_filename = Api.get_filename(chapter)
|
||||||
|
|
||||||
|
# set download path for chapter
|
||||||
|
chapter_path = manga_path / chapter_filename
|
||||||
|
|
||||||
|
# check if chapter already exists.
|
||||||
|
# check for folder if option nocbz is given. if nocbz is not given, the folder will be overwritten
|
||||||
|
|
||||||
|
if utils.check_existence(chapter_path, manga_nocbz):
|
||||||
|
print(f"INFO: '{chapter_filename}' already exists. Skipping\n")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# create chapter folder (skips it if it already exists)
|
||||||
|
chapter_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# verbose log
|
||||||
|
if log_verbose:
|
||||||
|
print(f"INFO: Chapter UUID: {chapter_infos['uuid']}")
|
||||||
|
print(
|
||||||
|
f"INFO: Filename: '{chapter_filename}'\n"
|
||||||
|
if manga_nocbz
|
||||||
|
else f"INFO: Filename: '{chapter_filename}.cbz'\n"
|
||||||
|
)
|
||||||
|
print(f"INFO: Image URLS: {chapter_image_urls}")
|
||||||
|
|
||||||
|
# log
|
||||||
|
print(f"INFO: Downloading: '{chapter_filename}'")
|
||||||
|
|
||||||
|
# download images
|
||||||
|
try:
|
||||||
|
downloader.download_chapter(
|
||||||
|
chapter_image_urls, chapter_path, download_wait, log_verbose
|
||||||
|
)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("ERR: Stopping")
|
||||||
|
exit(1)
|
||||||
|
except:
|
||||||
|
print(f"ERR: Cant download: '{chapter_filename}'. Exiting")
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Done with chapter
|
||||||
|
print(f"INFO: Successfully downloaded: '{chapter_filename}'")
|
||||||
|
|
||||||
|
# make cbz of folder
|
||||||
|
if not manga_nocbz:
|
||||||
|
print("INFO: Creating .cbz archive")
|
||||||
|
try:
|
||||||
|
utils.make_archive(chapter_path)
|
||||||
|
except:
|
||||||
|
print("ERR: Could not make cbz archive")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# done with chapter
|
||||||
|
print("INFO: Done with chapter")
|
||||||
|
print("-----------------------------------------\n")
|
||||||
|
|
||||||
|
# done with manga
|
||||||
|
print(f"{print_divider}")
|
||||||
|
print(f"INFO: Done with manga: {manga_title}")
|
||||||
|
print(f"{print_divider}\n")
|
||||||
|
|
|
@ -3,71 +3,78 @@ import shutil
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
# create a cbz archive
|
||||||
def make_archive(chapter_path):
|
def make_archive(chapter_path):
|
||||||
image_folder = Path(chapter_path)
|
image_folder = Path(chapter_path)
|
||||||
zip_path = Path(f'{chapter_path}.zip')
|
zip_path = Path(f"{chapter_path}.zip")
|
||||||
with ZipFile(f'{image_folder}.zip', 'w') as zip_archive:
|
with ZipFile(f"{image_folder}.zip", "w") as zip_archive:
|
||||||
for file in image_folder.iterdir():
|
for file in image_folder.iterdir():
|
||||||
zip_archive.write(file, file.name)
|
zip_archive.write(file, file.name)
|
||||||
|
|
||||||
zip_path.rename(zip_path.with_suffix('.cbz'))
|
zip_path.rename(zip_path.with_suffix(".cbz"))
|
||||||
shutil.rmtree(image_folder)
|
shutil.rmtree(image_folder)
|
||||||
|
|
||||||
|
|
||||||
|
# check if the file already exists
|
||||||
def check_existence(chapter_path, manga_nocbz):
|
def check_existence(chapter_path, manga_nocbz):
|
||||||
# check for folder if option nocbz is given. if nocbz is not given, the folder will be overwritten
|
# check for folder if option nocbz is given. if nocbz is not given, the folder will be overwritten
|
||||||
chapter_path = Path(chapter_path)
|
chapter_path = Path(chapter_path)
|
||||||
cbz_path = chapter_path.parent / f'{chapter_path.name}.cbz'
|
cbz_path = chapter_path.parent / f"{chapter_path.name}.cbz"
|
||||||
if manga_nocbz and chapter_path.exists():
|
if manga_nocbz and chapter_path.exists():
|
||||||
return True
|
return True
|
||||||
# check for cbz archive
|
# check for cbz archive
|
||||||
elif not manga_nocbz and cbz_path.exists():
|
elif not manga_nocbz and cbz_path.exists():
|
||||||
return True
|
return True
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_chapter_list(chapters):
|
|
||||||
chapter_list = []
|
|
||||||
for chapter in chapters.split(','):
|
|
||||||
if '-' in chapter and ':' in chapter:
|
|
||||||
lower = chapter.split('-')[0].split(':')
|
|
||||||
upper = chapter.split('-')[1].split(':')
|
|
||||||
for n in range(int(lower[1]), int(upper[1])+1):
|
|
||||||
chapter_list.append(str(f'{lower[0]}:{n}'))
|
|
||||||
elif '-' in chapter:
|
|
||||||
lower = chapter.split('-')[0]
|
|
||||||
upper = chapter.split('-')[1]
|
|
||||||
for n in range(int(lower), int(upper)+1):
|
|
||||||
chapter_list.append(str(n))
|
|
||||||
else:
|
else:
|
||||||
chapter_list.append(chapter)
|
return False
|
||||||
|
|
||||||
return chapter_list
|
|
||||||
|
|
||||||
|
|
||||||
def fix_name(name):
|
# create a list of chapters
|
||||||
# remove illegal characters
|
def get_chapter_list(chapters):
|
||||||
name = re.sub('[/<>:"\\|?*!.]', '', name)
|
chapter_list = []
|
||||||
# remove trailing space
|
for chapter in chapters.split(","):
|
||||||
name = re.sub('[ \t]+$', '', name)
|
if "-" in chapter and ":" in chapter:
|
||||||
|
lower = chapter.split("-")[0].split(":")
|
||||||
|
upper = chapter.split("-")[1].split(":")
|
||||||
|
for n in range(int(lower[1]), int(upper[1]) + 1):
|
||||||
|
chapter_list.append(str(f"{lower[0]}:{n}"))
|
||||||
|
elif "-" in chapter:
|
||||||
|
lower = chapter.split("-")[0]
|
||||||
|
upper = chapter.split("-")[1]
|
||||||
|
for n in range(int(lower), int(upper) + 1):
|
||||||
|
chapter_list.append(str(n))
|
||||||
|
else:
|
||||||
|
chapter_list.append(chapter)
|
||||||
|
|
||||||
return name
|
return chapter_list
|
||||||
|
|
||||||
|
|
||||||
|
# remove illegal characters etc
|
||||||
|
def fix_name(filename):
|
||||||
|
# remove illegal characters
|
||||||
|
filename = re.sub("[\\\/\<\>\:\;'\"\|\?\*\!\@]", ".", filename)
|
||||||
|
# remove multiple dots
|
||||||
|
filename = re.sub("([\.]{2,})", ".", filename)
|
||||||
|
# remove dot(s) at the beginning and end of the filename
|
||||||
|
filename = re.sub("(^[\.]{1,})|([\.]{1,}$)", "", filename)
|
||||||
|
# remove trailing and beginning spaces
|
||||||
|
filename = re.sub("([ \t]+$)|(^[ \t]+)", "", filename)
|
||||||
|
|
||||||
|
return filename
|
||||||
|
|
||||||
|
|
||||||
|
# create name for chapter
|
||||||
def get_filename(chapter_name, chapter_vol, chapter_num, manga_forcevol):
|
def get_filename(chapter_name, chapter_vol, chapter_num, manga_forcevol):
|
||||||
# filename for chapter
|
# filename for chapter
|
||||||
if chapter_name == 'Oneshot' or chapter_num == 'Oneshot':
|
if chapter_name == "Oneshot" or chapter_num == "Oneshot":
|
||||||
chapter_filename = 'Oneshot'
|
chapter_filename = "Oneshot"
|
||||||
elif not chapter_name and manga_forcevol:
|
elif not chapter_name and manga_forcevol:
|
||||||
chapter_filename = f'Vol. {chapter_vol} Ch. {chapter_num}'
|
chapter_filename = f"Vol. {chapter_vol} Ch. {chapter_num}"
|
||||||
elif not chapter_name:
|
elif not chapter_name:
|
||||||
chapter_filename = f'Ch. {chapter_num}'
|
chapter_filename = f"Ch. {chapter_num}"
|
||||||
elif manga_forcevol:
|
elif manga_forcevol:
|
||||||
chapter_filename = f'Vol. {chapter_vol} Ch. {chapter_num} - {chapter_name}'
|
chapter_filename = f"Vol. {chapter_vol} Ch. {chapter_num} - {chapter_name}"
|
||||||
else:
|
else:
|
||||||
chapter_filename = f'Ch. {chapter_num} - {chapter_name}'
|
chapter_filename = f"Ch. {chapter_num} - {chapter_name}"
|
||||||
|
|
||||||
return chapter_filename
|
|
||||||
|
|
||||||
|
return chapter_filename
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
https://mangadex.org/title/a96676e5-8ae2-425e-b549-7f15dd34a6d8/komi-san-wa-komyushou-desu
|
https://mangadex.org/title/a96676e5-8ae2-425e-b549-7f15dd34a6d8/komi-san-wa-komyushou-desu
|
||||||
https://mangadex.org/title/bd6d0982-0091-4945-ad70-c028ed3c0917/mushoku-tensei-isekai-ittara-honki-dasu
|
https://mangadex.org/title/bd6d0982-0091-4945-ad70-c028ed3c0917/mushoku-tensei-isekai-ittara-honki-dasu
|
||||||
|
37f5cce0-8070-4ada-96e5-fa24b1bd4ff9
|
||||||
|
|
Loading…
Reference in a new issue