11"""A manga downloader and PDF generator for MangaWorld.
22
33This module allows you to download manga chapters from a given manga URL, process each
4- chapter, and generate PDF files for the downloaded images. It utilizes `requests` for
5- HTTP requests, `BeautifulSoup` for HTML parsing, and `rich` for displaying a progress
6- bar during the download and conversion process.
4+ chapter, and generate PDF files for the downloaded images.
75"""
86
97from __future__ import annotations
108
119import asyncio
1210from pathlib import Path
1311from typing import TYPE_CHECKING
14- import aiohttp
1512
13+ import aiohttp
1614from rich .live import Live
1715
1816from src .config import DOWNLOAD_FOLDER , parse_arguments
2119 extract_download_links ,
2220 extract_manga_type ,
2321 extract_volume_info ,
22+ fetch_chapter_data ,
2423)
2524from src .download_utils import download_chapter , run_in_parallel
26- from src .crawler_utils import fetch_chapter_data
2725from src .format_utils import extract_manga_info
2826from src .general_utils import clear_terminal , fetch_page , validate_chapter_range
2927from src .pdf_generator import generate_pdf_files
30- from src .progress_utils import create_progress_bar , create_progress_table , create_select_items_list
28+ from src .progress_utils import (
29+ create_progress_bar ,
30+ create_progress_table ,
31+ create_select_items_list ,
32+ )
3133
3234if TYPE_CHECKING :
3335 from rich .progress import Progress
3436
3537
36- def process_pdf_generation (manga_name : str , job_progress : Progress , single_pdf = False ) -> None :
38+ def process_pdf_generation (
39+ manga_name : str , job_progress : Progress , * , single_pdf : bool = False ,
40+ ) -> None :
3741 """Process the generation of PDF files for a specific manga."""
3842 manga_parent_folder = Path (DOWNLOAD_FOLDER ) / manga_name
3943 generate_pdf_files (str (manga_parent_folder ), job_progress , single_pdf = single_pdf )
4044
4145
46+ def download_chapter_with_progress (
47+ manga_name : str ,
48+ download_links : list [str ],
49+ pages_per_chapter : list [int ],
50+ * ,
51+ generate_pdf : bool = False ,
52+ volume_name : str | None = None ,
53+ ) -> None :
54+ """Download the chapters of a manga and displays a progress bar.
55+
56+ Optionally generate a PDF of the manga chapters if requested.
57+ """
58+ task_description = (
59+ manga_name if volume_name is None else f"{ manga_name } - { volume_name } "
60+ )
61+ working_path = manga_name if volume_name is None else f"{ manga_name } /{ volume_name } "
62+
63+ job_progress = create_progress_bar ()
64+ progress_table = create_progress_table (task_description , job_progress )
65+
66+ with Live (progress_table , refresh_per_second = 10 ):
67+ run_in_parallel (
68+ download_chapter ,
69+ download_links ,
70+ job_progress ,
71+ pages_per_chapter ,
72+ working_path ,
73+ )
74+ if generate_pdf :
75+ single_pdf = volume_name is not None
76+ process_pdf_generation (working_path , job_progress , single_pdf = single_pdf )
77+
78+
4279async def process_manga_download (
4380 url : str ,
4481 start_chapter : int | None = None ,
@@ -54,37 +91,35 @@ async def process_manga_download(
5491
5592 if volume_mode :
5693 volumes = extract_volume_info (soup )
57- volume_names = [v ['name' ] for v in volumes ]
58- selected_indices = create_select_items_list (volume_names )
59- for idx in selected_indices :
60- volume = volumes [idx ]
61- chapter_urls = [c ['url' ] for c in volume ['chapters' ]]
94+ volume_names = [volume ["name" ] for volume in volumes ]
95+ selected_indexes = create_select_items_list (volume_names )
96+
97+ for indx in selected_indexes :
98+ volume = volumes [indx ]
99+ chapter_urls = [chapter ["url" ] for chapter in volume ["chapters" ]]
62100 pages_per_chapter = []
101+
63102 async with aiohttp .ClientSession () as session :
64103 tasks = [fetch_chapter_data (url , session ) for url in chapter_urls ]
65104 results = await asyncio .gather (* tasks )
66- for result in results :
67- pages_per_chapter .append (result [1 ] if result and result [1 ] else None )
105+ pages_per_chapter = [
106+ result [1 ] if result and result [1 ] else None for result in results
107+ ]
68108
69109 download_links = await extract_download_links (
70110 chapter_urls ,
71111 0 ,
72112 len (chapter_urls ),
73113 manga_type ,
74114 )
75- job_progress = create_progress_bar ()
76- progress_table = create_progress_table (f"{ manga_name } - { volume ['name' ]} " , job_progress )
77-
78- with Live (progress_table , refresh_per_second = 10 ):
79- run_in_parallel (
80- download_chapter ,
81- download_links ,
82- job_progress ,
83- pages_per_chapter ,
84- f"{ manga_name } /{ volume ['name' ]} "
85- )
86- if generate_pdf :
87- process_pdf_generation (f"{ manga_name } /{ volume ['name' ]} " , job_progress , single_pdf = True )
115+ download_chapter_with_progress (
116+ manga_name ,
117+ download_links ,
118+ pages_per_chapter ,
119+ generate_pdf = generate_pdf ,
120+ volume_name = volume ["name" ],
121+ )
122+
88123 else :
89124 chapter_urls , pages_per_chapter = await extract_chapters_info (soup )
90125 start_index , end_index = validate_chapter_range (
@@ -98,28 +133,24 @@ async def process_manga_download(
98133 end_index ,
99134 manga_type ,
100135 )
101-
102- job_progress = create_progress_bar ()
103- progress_table = create_progress_table (manga_name , job_progress )
104-
105- with Live (progress_table , refresh_per_second = 10 ):
106- run_in_parallel (
107- download_chapter ,
108- download_links ,
109- job_progress ,
110- pages_per_chapter [start_index :end_index ],
111- manga_name ,
112- )
113- if generate_pdf :
114- process_pdf_generation (manga_name , job_progress )
136+ download_chapter_with_progress (
137+ manga_name ,
138+ download_links ,
139+ pages_per_chapter [start_index :end_index ],
140+ generate_pdf = generate_pdf ,
141+ )
115142
116143
117144async def main () -> None :
118145 """Initiate the manga download process from a given URL."""
119146 clear_terminal ()
120147 args = parse_arguments ()
121148 await process_manga_download (
122- args .url , start_chapter = args .start , end_chapter = args .end , generate_pdf = args .pdf , volume_mode = args .volume
149+ args .url ,
150+ start_chapter = args .start ,
151+ end_chapter = args .end ,
152+ generate_pdf = args .pdf ,
153+ volume_mode = args .volume ,
123154 )
124155
125156
0 commit comments