kmoe-manga-downloader 1.2.7__py3-none-any.whl → 1.2.8a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kmdr/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.2.7'
32
- __version_tuple__ = version_tuple = (1, 2, 7)
31
+ __version__ = version = '1.2.8a1'
32
+ __version_tuple__ = version_tuple = (1, 2, 8, 'a1')
33
33
 
34
34
  __commit_id__ = commit_id = None
kmdr/core/defaults.py CHANGED
@@ -71,6 +71,7 @@ def argument_parser():
71
71
  download_parser.add_argument('-c', '--callback', type=str, help='每个卷下载完成后执行的回调脚本,例如: `echo {v.name} downloaded!`', required=False)
72
72
  download_parser.add_argument('-m', '--method', type=int, help='下载方法,对应网站上的不同下载方式', required=False, choices=[1, 2], default=1)
73
73
  download_parser.add_argument('--vip', action='store_true', help='尝试使用 VIP 链接进行下载(下载速度可能不及 CDN 方式)')
74
+ download_parser.add_argument('--disable-multi-part', action='store_true', help='禁用分片下载')
74
75
 
75
76
  login_parser = subparsers.add_parser('login', help='登录到 Kmoe')
76
77
  login_parser.add_argument('-u', '--username', type=str, help='用户名', required=True)
kmdr/core/utils.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import functools
2
- from typing import Optional, Callable, TypeVar, Hashable, Generic
2
+ from typing import Optional, Callable, TypeVar, Hashable, Generic, Mapping, Any
3
3
  import asyncio
4
4
  from asyncio.proactor_events import _ProactorBasePipeTransport
5
5
 
@@ -146,4 +146,18 @@ def _silence_event_loop_closed(func):
146
146
 
147
147
  return wrapper
148
148
 
149
- _ProactorBasePipeTransport.__del__ = _silence_event_loop_closed(_ProactorBasePipeTransport.__del__)
149
+ _ProactorBasePipeTransport.__del__ = _silence_event_loop_closed(_ProactorBasePipeTransport.__del__)
150
+
151
+
152
+
153
+ SENSITIVE_KEYS = {'cookie', 'authorization', 'proxy-authorization', 'set-cookie'}
154
+ """定义需要脱敏的字段(全部小写以便不区分大小写匹配)"""
155
+
156
+ def sanitize_headers(headers: Mapping[str, Any]) -> dict:
157
+ """
158
+ 清洗 HTTP 头信息,隐藏敏感字段(如 Cookie, Authorization)。
159
+ """
160
+ return {
161
+ k: '******' if k.lower() in SENSITIVE_KEYS else v
162
+ for k, v in headers.items()
163
+ }
@@ -3,7 +3,7 @@ from functools import partial
3
3
  from kmdr.core import Downloader, BookInfo, VolInfo, DOWNLOADER
4
4
  from kmdr.core.constants import API_ROUTE
5
5
 
6
- from .download_utils import download_file_multipart, readable_safe_filename
6
+ from .download_utils import download_file_multipart, readable_safe_filename, download_file
7
7
 
8
8
  @DOWNLOADER.register(
9
9
  hasvalues={
@@ -11,14 +11,28 @@ from .download_utils import download_file_multipart, readable_safe_filename
11
11
  }
12
12
  )
13
13
  class DirectDownloader(Downloader):
14
- def __init__(self, dest='.', callback=None, retry=3, num_workers=8, proxy=None, vip=False, *args, **kwargs):
14
+ def __init__(self, dest='.', callback=None, retry=3, num_workers=8, proxy=None, vip=False, disable_multi_part=False, *args, **kwargs):
15
15
  super().__init__(dest, callback, retry, num_workers, proxy, *args, **kwargs)
16
16
  self._use_vip = vip
17
+ self._disable_multi_part = disable_multi_part
17
18
 
18
19
  async def _download(self, book: BookInfo, volume: VolInfo):
19
20
  sub_dir = readable_safe_filename(book.name)
20
21
  download_path = f'{self._dest}/{sub_dir}'
21
22
 
23
+ if self._disable_multi_part:
24
+ await download_file(
25
+ self._session,
26
+ self._semaphore,
27
+ self._progress,
28
+ partial(self.construct_download_url, book, volume),
29
+ download_path,
30
+ readable_safe_filename(f'[Kmoe][{book.name}][{volume.name}].epub'),
31
+ self._retry,
32
+ callback=lambda: self._callback(book, volume) if self._callback else None
33
+ )
34
+ return
35
+
22
36
  await download_file_multipart(
23
37
  self._session,
24
38
  self._semaphore,
@@ -10,19 +10,33 @@ from kmdr.core.error import ResponseError
10
10
  from kmdr.core.utils import async_retry
11
11
  from kmdr.core.console import debug
12
12
 
13
- from .download_utils import download_file_multipart, readable_safe_filename
13
+ from .download_utils import download_file, download_file_multipart, readable_safe_filename
14
14
 
15
15
 
16
16
  @DOWNLOADER.register(order=10)
17
17
  class ReferViaDownloader(Downloader):
18
- def __init__(self, dest='.', callback=None, retry=3, num_workers=8, proxy=None, vip=False, *args, **kwargs):
18
+ def __init__(self, dest='.', callback=None, retry=3, num_workers=8, proxy=None, vip=False, disable_multi_part=False, *args, **kwargs):
19
19
  super().__init__(dest, callback, retry, num_workers, proxy, *args, **kwargs)
20
20
  self._use_vip = vip
21
+ self._disable_multi_part = disable_multi_part
21
22
 
22
23
  async def _download(self, book: BookInfo, volume: VolInfo):
23
24
  sub_dir = readable_safe_filename(book.name)
24
25
  download_path = f'{self._dest}/{sub_dir}'
25
26
 
27
+ if self._disable_multi_part:
28
+ await download_file(
29
+ self._session,
30
+ self._semaphore,
31
+ self._progress,
32
+ partial(self.fetch_download_url, book.id, volume.id),
33
+ download_path,
34
+ readable_safe_filename(f'[Kmoe][{book.name}][{volume.name}].epub'),
35
+ self._retry,
36
+ callback=lambda: self._callback(book, volume) if self._callback else None
37
+ )
38
+ return
39
+
26
40
  await download_file_multipart(
27
41
  self._session,
28
42
  self._semaphore,
@@ -15,7 +15,7 @@ from aiohttp.client_exceptions import ClientPayloadError
15
15
 
16
16
  from kmdr.core.console import info, log, debug
17
17
  from kmdr.core.error import ResponseError
18
- from kmdr.core.utils import async_retry
18
+ from kmdr.core.utils import async_retry, sanitize_headers
19
19
 
20
20
  from .misc import STATUS, StateManager
21
21
 
@@ -319,6 +319,9 @@ async def _download_part(
319
319
  debug("开始下载分片:", os.path.basename(part_path), "范围:", current_start, "-", end)
320
320
  async with session.get(url, headers=local_headers) as response:
321
321
  response.raise_for_status()
322
+ debug("分片", os.path.basename(part_path), "状态码:", response.status)
323
+ debug("分片", os.path.basename(part_path), "请求头:", sanitize_headers(response.request_info.headers))
324
+ debug("分片", os.path.basename(part_path), "响应头:", sanitize_headers(response.headers))
322
325
 
323
326
  await state_manager.request_status_update(part_id=start, status=STATUS.DOWNLOADING)
324
327
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kmoe-manga-downloader
3
- Version: 1.2.7
3
+ Version: 1.2.8a1
4
4
  Summary: A CLI-downloader for site @kox.moe.
5
5
  Author-email: Chris Zheng <chrisis58@outlook.com>
6
6
  License: MIT License
@@ -1,18 +1,18 @@
1
1
  kmdr/__init__.py,sha256=iLmy2rOkHS_4KZWMD8BgT7R3tLMKeaTCDVf3B4FyYxM,91
2
- kmdr/_version.py,sha256=R7K92G6qT3thh3TqV7dEawNJTwh11SHGYMpvuwpJv0Y,704
2
+ kmdr/_version.py,sha256=JyF-msezavGoYODPGaV_ID0jze_-I8yYyI16y_3GMJ0,712
3
3
  kmdr/main.py,sha256=B9CK53GlWO91-135AJDFOfqglSmYJe5-nZrha4A0LLs,2166
4
4
  kmdr/core/__init__.py,sha256=aR3mhP1A81oTmTnBOonVQm_mFvFeNCOo7kalZVfszAc,416
5
5
  kmdr/core/bases.py,sha256=47M6VyrIMnmTEvwZtt8WsPAjGz5vagkRyTpci16aH2k,3973
6
6
  kmdr/core/console.py,sha256=gD_PKjuAjePUJx-49ef9IBunetCiKt1LMI0EIU5kcZw,2016
7
7
  kmdr/core/constants.py,sha256=JFj8FHO9ab6AeIzHz3LaC8l3ziLLFi75vil8wMPfZoA,1869
8
8
  kmdr/core/context.py,sha256=ZhUfuCmZN0s1AQnxxkMFqYkCpjkRvJd53RUZWMhH8Gw,1390
9
- kmdr/core/defaults.py,sha256=o9Py-Y51xNMFxyZ_okpvUjh4Z92QX7y8RaWKJ98Q-JY,9100
9
+ kmdr/core/defaults.py,sha256=1Hh--iLw8nb8GJSpi9jcSfdOqVuj3S7eU6aymMDWZ68,9205
10
10
  kmdr/core/error.py,sha256=gH4tcFpLRJXKQCwEnvfVM0lkhlakCwS-IYtNEkpO9a4,1984
11
11
  kmdr/core/protocol.py,sha256=_4Ba6BU4oEFK2O61UH_-X2-bmZtUd61O20WGarvXVOM,399
12
12
  kmdr/core/registry.py,sha256=m5jKma2SLbYN6hG2WqkxoyOYUENE4a-e0CzRALkGD7k,5654
13
13
  kmdr/core/session.py,sha256=f6tUKXuFnJ0ok-sh8JwMtgjQI_qBdfqqzhb3-pe2RnU,5795
14
14
  kmdr/core/structure.py,sha256=EQG1-8kHQ22Not2S7Q_jGxE0nb9XUbLh3JcNTb_nkvk,1199
15
- kmdr/core/utils.py,sha256=e1AS4MGz22mr16zRnAaeEZGSivjCtw4066LQ7C5YX_g,4887
15
+ kmdr/core/utils.py,sha256=JsUH5Mpq40DeN4J5mSzZdA7_d3gPGmTAjvEp2KKFPwk,5337
16
16
  kmdr/module/__init__.py,sha256=hY6lMBpxSn93t7OKnEbXUwTok2XqQoQbuyq1HLeC4Kc,125
17
17
  kmdr/module/authenticator/CookieAuthenticator.py,sha256=lv_monQ7QUMfgPPgxoV1xr_KyUtwCKZhqJ8umv3W6xo,1108
18
18
  kmdr/module/authenticator/LoginAuthenticator.py,sha256=5nyrzxYEGiRQ9ulnhjpuUWYeog-ALZlCCSAYkbwlKMw,1890
@@ -25,10 +25,10 @@ kmdr/module/configurer/OptionLister.py,sha256=bGlrxouPiBGpGv8UiGPcT3KL6SWMJckQKd
25
25
  kmdr/module/configurer/OptionSetter.py,sha256=BQXIgyLoMDSNua2x96FtX-9JmJhVpPJ5o0tWHj_-7B0,898
26
26
  kmdr/module/configurer/__init__.py,sha256=nSWGwUCcwOkvg28zxRd0S3b4jeag_W0IhzP74xq0ewE,204
27
27
  kmdr/module/configurer/option_validate.py,sha256=9QzVO9wwGwhXMPXx2zLJSIsyVle7-GTgxCoPn7Tp6kw,3535
28
- kmdr/module/downloader/DirectDownloader.py,sha256=mMdxAudYEdzCjNtLEDIr6eoxZJJ61zEQey_PcOABxX0,1383
29
- kmdr/module/downloader/ReferViaDownloader.py,sha256=IFra1gVOfTl8hVK2KyINP53u0r6NFycYupoLx5TeMdY,2531
28
+ kmdr/module/downloader/DirectDownloader.py,sha256=ewSOV1BQ80LOq0mA6Lpr9gaYYYl33REQK4CgYlfD83c,1980
29
+ kmdr/module/downloader/ReferViaDownloader.py,sha256=j61KQ6Gb6Unz3Ww6m-8s1zwNLUcgrU6o-8YfODdLr88,3130
30
30
  kmdr/module/downloader/__init__.py,sha256=PajPBQ4ZJwz_6Ok6k-HV7-YSibxAW5m5voYyP-U-_f4,97
31
- kmdr/module/downloader/download_utils.py,sha256=K0zhOWy4iQH1qyrKr2bgGre8sgBiLHXb6O3Fxq0w--0,18515
31
+ kmdr/module/downloader/download_utils.py,sha256=bFlrH4AUIyTJnGvIBk2geGrP5FzplHQdo1K2dxpIjRs,18872
32
32
  kmdr/module/downloader/misc.py,sha256=P8hqtYIiD1AR6wzfJ0JBghpSJ_zx2_vTg8jDHcEU8hM,2328
33
33
  kmdr/module/lister/BookUrlLister.py,sha256=R1sak_GQG8HKfdSzHF-Dy1iby6TgFlxKJLf2dwBr0Bw,550
34
34
  kmdr/module/lister/FollowedBookLister.py,sha256=d2IxWAf1VSL1Kv8SQkzbxDUunFb7UkxkreUbWQvs6tc,2906
@@ -38,9 +38,9 @@ kmdr/module/picker/ArgsFilterPicker.py,sha256=wBCDa6KsSSOLLQk8D4ftZ9ZnwPLiHIirxf
38
38
  kmdr/module/picker/DefaultVolPicker.py,sha256=qScmRtwpe1u3fY7HMIo15YXtwB4LYAIJaTu_EkrAJbs,1780
39
39
  kmdr/module/picker/__init__.py,sha256=qYELEkv0nFT8DadItB6fdUTED2CHrC43wuPKO7QrCCQ,93
40
40
  kmdr/module/picker/utils.py,sha256=baJzpQSSSBdTPZ2scrEeNOssGYOL0nNwxN1gTsOAqnc,1604
41
- kmoe_manga_downloader-1.2.7.dist-info/licenses/LICENSE,sha256=bKQlsXu8mAYKRZyoZKOEqMcCc8YjT5Q3Hgr21e0yU4E,1068
42
- kmoe_manga_downloader-1.2.7.dist-info/METADATA,sha256=NtWHjh6DmIz3mwCXRFz_e1Foekl9vIf7qIz8BKVFhnI,10114
43
- kmoe_manga_downloader-1.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
- kmoe_manga_downloader-1.2.7.dist-info/entry_points.txt,sha256=DGMytQAhx4uNuKQL7BPkiWESHLXkH-2KSEqwHdygNPA,47
45
- kmoe_manga_downloader-1.2.7.dist-info/top_level.txt,sha256=e0qxOgWp0tl3GLpmXGjZv3--q_TLoJ7GztM48Ov27wM,5
46
- kmoe_manga_downloader-1.2.7.dist-info/RECORD,,
41
+ kmoe_manga_downloader-1.2.8a1.dist-info/licenses/LICENSE,sha256=bKQlsXu8mAYKRZyoZKOEqMcCc8YjT5Q3Hgr21e0yU4E,1068
42
+ kmoe_manga_downloader-1.2.8a1.dist-info/METADATA,sha256=Lj7KQHbci4AWXASNBCL-VLh9BE9OLbOUpub7JU_6BG0,10116
43
+ kmoe_manga_downloader-1.2.8a1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
+ kmoe_manga_downloader-1.2.8a1.dist-info/entry_points.txt,sha256=DGMytQAhx4uNuKQL7BPkiWESHLXkH-2KSEqwHdygNPA,47
45
+ kmoe_manga_downloader-1.2.8a1.dist-info/top_level.txt,sha256=e0qxOgWp0tl3GLpmXGjZv3--q_TLoJ7GztM48Ov27wM,5
46
+ kmoe_manga_downloader-1.2.8a1.dist-info/RECORD,,