kmoe-manga-downloader 1.2.4__tar.gz → 1.2.5__tar.gz

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.
Files changed (64) hide show
  1. kmoe_manga_downloader-1.2.5/.github/ISSUE_TEMPLATE/bug_report.yml +81 -0
  2. kmoe_manga_downloader-1.2.5/.github/ISSUE_TEMPLATE/feature_request.yml +55 -0
  3. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/.github/workflows/unit-test.yml +3 -0
  4. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/PKG-INFO +1 -1
  5. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/_version.py +3 -3
  6. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/defaults.py +1 -0
  7. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/downloader/DirectDownloader.py +3 -2
  8. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/downloader/ReferViaDownloader.py +5 -3
  9. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/downloader/download_utils.py +28 -20
  10. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/downloader/misc.py +0 -1
  11. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmoe_manga_downloader.egg-info/PKG-INFO +1 -1
  12. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmoe_manga_downloader.egg-info/SOURCES.txt +2 -0
  13. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/tests/test_kmdr_download.py +49 -0
  14. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/.github/workflows/release-package.yml +0 -0
  15. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/.gitignore +0 -0
  16. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/LICENSE +0 -0
  17. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/README.md +0 -0
  18. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/assets/kmdr-demo.gif +0 -0
  19. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/assets/kmdr-log-demo.gif +0 -0
  20. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/mirror/mirrors.json +0 -0
  21. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/pyproject.toml +0 -0
  22. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/setup.cfg +0 -0
  23. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/__init__.py +0 -0
  24. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/__init__.py +0 -0
  25. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/bases.py +0 -0
  26. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/console.py +0 -0
  27. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/constants.py +0 -0
  28. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/context.py +0 -0
  29. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/error.py +0 -0
  30. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/protocol.py +0 -0
  31. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/registry.py +0 -0
  32. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/session.py +0 -0
  33. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/structure.py +0 -0
  34. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/core/utils.py +0 -0
  35. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/main.py +0 -0
  36. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/__init__.py +0 -0
  37. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/authenticator/CookieAuthenticator.py +0 -0
  38. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/authenticator/LoginAuthenticator.py +0 -0
  39. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/authenticator/__init__.py +0 -0
  40. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/authenticator/utils.py +0 -0
  41. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/configurer/BaseUrlUpdator.py +0 -0
  42. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/configurer/ConfigClearer.py +0 -0
  43. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/configurer/ConfigUnsetter.py +0 -0
  44. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/configurer/OptionLister.py +0 -0
  45. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/configurer/OptionSetter.py +0 -0
  46. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/configurer/__init__.py +0 -0
  47. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/configurer/option_validate.py +0 -0
  48. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/downloader/__init__.py +0 -0
  49. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/lister/BookUrlLister.py +0 -0
  50. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/lister/FollowedBookLister.py +0 -0
  51. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/lister/__init__.py +0 -0
  52. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/lister/utils.py +0 -0
  53. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/picker/ArgsFilterPicker.py +0 -0
  54. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/picker/DefaultVolPicker.py +0 -0
  55. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/picker/__init__.py +0 -0
  56. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmdr/module/picker/utils.py +0 -0
  57. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmoe_manga_downloader.egg-info/dependency_links.txt +0 -0
  58. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmoe_manga_downloader.egg-info/entry_points.txt +0 -0
  59. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmoe_manga_downloader.egg-info/requires.txt +0 -0
  60. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/src/kmoe_manga_downloader.egg-info/top_level.txt +0 -0
  61. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/tests/__init__.py +0 -0
  62. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/tests/test_async_retry_decorator.py +0 -0
  63. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/tests/test_kmdr_config_option.py +0 -0
  64. {kmoe_manga_downloader-1.2.4 → kmoe_manga_downloader-1.2.5}/tests/test_utils_resolve_volme.py +0 -0
@@ -0,0 +1,81 @@
1
+ name: Bug 报告
2
+ description: 提交一个 Bug 帮助我们改进
3
+ labels: ['bug']
4
+
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ 感谢您提交 Bug!
10
+ 请确保已阅读相关文档,并按照模版提供信息,否则 issue 可能会被关闭。
11
+
12
+ - type: input
13
+ id: app-version
14
+ attributes:
15
+ label: 应用版本
16
+ description: 请提供您使用的应用版本号,可以通过 `kmdr --version` 获取。
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: actual-command
22
+ attributes:
23
+ label: 实际执行的命令
24
+ description: 请提供您实际执行的命令。
25
+ placeholder: kmdr download -l <book_url> -v <volume_selected>
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: what-expected
31
+ attributes:
32
+ label: 预期是什么?
33
+ description: 您期望发生什么?
34
+ validations:
35
+ required: true
36
+
37
+ - type: textarea
38
+ id: actual-happened
39
+ attributes:
40
+ label: 实际发生了什么?
41
+ description: 实际发生了什么,可以附带截图等说明问题。
42
+ validations:
43
+ required: true
44
+
45
+ - type: textarea
46
+ id: logs
47
+ attributes:
48
+ label: 应用输出信息
49
+ description: 请在此处粘贴任何相关的日志、报错信息或堆栈跟踪。
50
+ render: shell
51
+ validations:
52
+ required: true
53
+
54
+ - type: textarea
55
+ id: debug-logs
56
+ attributes:
57
+ label: 调试输出信息
58
+ description: |
59
+ 如果问题可以复现,请启用调试模式(添加 `--verbose` 参数)并粘贴调试日志。
60
+ 如 `kmdr --verbose status`。
61
+ render: shell
62
+ validations:
63
+ required: false
64
+
65
+ - type: textarea
66
+ id: additional-context
67
+ attributes:
68
+ label: 其他上下文信息
69
+ description: |
70
+ 请提供任何其他有助于理解问题的上下文信息,例如操作系统、使用的 shell 等。
71
+ placeholder: "OS: ..., Shell: ..."
72
+ validations:
73
+ required: false
74
+
75
+ - type: checkboxes
76
+ id: terms
77
+ attributes:
78
+ label: 这不是重复的 issue
79
+ options:
80
+ - label: 我已经搜索了现有 issue,以确保该错误尚未被报告。
81
+ required: true
@@ -0,0 +1,55 @@
1
+ name: 功能请求
2
+ description: 建议一个新功能或改进
3
+ labels: ['enhancement']
4
+
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ 感谢您抽出宝贵时间提出功能请求!
10
+ 请详细描述您的想法,以便我们更好地理解它。
11
+
12
+ - type: textarea
13
+ id: problem-description
14
+ attributes:
15
+ label: 您的功能请求是否与某个问题/痛点相关?
16
+ description: 请详细描述您遇到的问题或痛点。
17
+ placeholder: "当我...时,我希望能..."
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: solution-description
23
+ attributes:
24
+ label: 您希望的解决方案是什么?
25
+ description: |
26
+ 请清晰简洁地描述您希望发生什么。
27
+ 如果是 CLI 相关的,可以提供理想中的命令用法。
28
+ placeholder: |
29
+ 我希望 `kmdr download` 增加一个 `--format epub` 标志...
30
+ validations:
31
+ required: true
32
+
33
+ - type: textarea
34
+ id: alternatives-considered
35
+ attributes:
36
+ label: 您是否考虑过其他替代方案?
37
+ description: 请描述您可能考虑过的任何替代解决方案或功能,以及为什么提议的方案更好。
38
+ validations:
39
+ required: false
40
+
41
+ - type: textarea
42
+ id: additional-context
43
+ attributes:
44
+ label: 额外信息
45
+ description: 在这里添加任何其他关于功能请求的信息,例如伪代码、流程图、截图或外部链接。
46
+ validations:
47
+ required: false
48
+
49
+ - type: checkboxes
50
+ id: terms
51
+ attributes:
52
+ label: 确认
53
+ options:
54
+ - label: 我已经搜索了现有 issue,以确保这个功能尚未被提议。
55
+ required: true
@@ -3,6 +3,9 @@ name: Unit Tests
3
3
  on:
4
4
  push:
5
5
  branches: [ main ]
6
+ paths:
7
+ - 'src/**'
8
+ - 'tests/**'
6
9
 
7
10
  jobs:
8
11
  test:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kmoe-manga-downloader
3
- Version: 1.2.4
3
+ Version: 1.2.5
4
4
  Summary: A CLI-downloader for site @kox.moe.
5
5
  Author-email: Chris Zheng <chrisis58@outlook.com>
6
6
  License: MIT License
@@ -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.4'
32
- __version_tuple__ = version_tuple = (1, 2, 4)
31
+ __version__ = version = '1.2.5'
32
+ __version_tuple__ = version_tuple = (1, 2, 5)
33
33
 
34
- __commit_id__ = commit_id = 'gb584a1f0c'
34
+ __commit_id__ = commit_id = 'gd3b720692'
@@ -70,6 +70,7 @@ def argument_parser():
70
70
  download_parser.add_argument('-r', '--retry', type=int, help='网络请求失败时的重试次数', required=False)
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
+ download_parser.add_argument('--vip', action='store_true', help='尝试使用 VIP 链接进行下载(下载速度可能不及 CDN 方式)')
73
74
 
74
75
  login_parser = subparsers.add_parser('login', help='登录到 Kmoe')
75
76
  login_parser.add_argument('-u', '--username', type=str, help='用户名', required=True)
@@ -11,8 +11,9 @@ 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, *args, **kwargs):
14
+ def __init__(self, dest='.', callback=None, retry=3, num_workers=8, proxy=None, vip=False, *args, **kwargs):
15
15
  super().__init__(dest, callback, retry, num_workers, proxy, *args, **kwargs)
16
+ self._use_vip = vip
16
17
 
17
18
  async def _download(self, book: BookInfo, volume: VolInfo):
18
19
  sub_dir = readable_safe_filename(book.name)
@@ -33,5 +34,5 @@ class DirectDownloader(Downloader):
33
34
  return API_ROUTE.DOWNLOAD.format(
34
35
  book_id=book.id,
35
36
  volume_id=volume.id,
36
- is_vip=self._profile.is_vip
37
+ is_vip=self._profile.is_vip if not self._use_vip else 0
37
38
  )
@@ -6,6 +6,7 @@ from async_lru import alru_cache
6
6
  from kmdr.core import Downloader, VolInfo, DOWNLOADER, BookInfo
7
7
  from kmdr.core.constants import API_ROUTE
8
8
  from kmdr.core.error import ResponseError
9
+ from kmdr.core.utils import async_retry
9
10
  from kmdr.core.console import debug
10
11
 
11
12
  from .download_utils import download_file_multipart, readable_safe_filename
@@ -13,9 +14,9 @@ from .download_utils import download_file_multipart, readable_safe_filename
13
14
 
14
15
  @DOWNLOADER.register(order=10)
15
16
  class ReferViaDownloader(Downloader):
16
- def __init__(self, dest='.', callback=None, retry=3, num_workers=8, proxy=None, *args, **kwargs):
17
+ def __init__(self, dest='.', callback=None, retry=3, num_workers=8, proxy=None, vip=False, *args, **kwargs):
17
18
  super().__init__(dest, callback, retry, num_workers, proxy, *args, **kwargs)
18
-
19
+ self._use_vip = vip
19
20
 
20
21
  async def _download(self, book: BookInfo, volume: VolInfo):
21
22
  sub_dir = readable_safe_filename(book.name)
@@ -36,13 +37,14 @@ class ReferViaDownloader(Downloader):
36
37
  )
37
38
 
38
39
  @alru_cache(maxsize=128)
40
+ @async_retry()
39
41
  async def fetch_download_url(self, book_id: str, volume_id: str) -> str:
40
42
 
41
43
  async with self._session.get(
42
44
  API_ROUTE.GETDOWNURL.format(
43
45
  book_id=book_id,
44
46
  volume_id=volume_id,
45
- is_vip=self._profile.is_vip
47
+ is_vip=self._profile.is_vip if not self._use_vip else 0
46
48
  )
47
49
  ) as response:
48
50
  response.raise_for_status()
@@ -267,11 +267,16 @@ async def _fetch_content_length(
267
267
  """
268
268
  if headers is None:
269
269
  headers = {}
270
-
270
+
271
271
  async with session.head(url, headers=headers, allow_redirects=True) as response:
272
- # 注意:这个请求完成后,服务器就会记录这次下载,并消耗对应的流量配额,详细的规则请参考网站说明:
273
- # 注 1 : 訂閱連載中的漫畫,有更新時自動推送的卷(冊),暫不計算在使用額度中,不扣減使用額度。
274
- # 注 2 : 對同一卷()書在 12 小時內重複*下載*,不會重複扣減額度。但重復推送是會扣減的。
272
+ response.raise_for_status()
273
+ if 'Content-Length' in response.headers:
274
+ return int(response.headers['Content-Length'])
275
+
276
+ async with session.get(url, headers=headers, allow_redirects=True) as response:
277
+ # 普通下载链接可能不支持 HEAD 请求,尝试使用 GET 请求获取文件大小
278
+ # see: https://github.com/chrisis58/kmoe-manga-downloader/issues/25
279
+ debug("HEAD 请求未返回 Content-Length,尝试使用 GET 请求获取文件大小")
275
280
  response.raise_for_status()
276
281
  if 'Content-Length' not in response.headers:
277
282
  raise ResponseError("无法从服务器获取文件大小,请检查网络连接或稍后重试。", status_code=response.status)
@@ -392,19 +397,22 @@ def safe_filename(name: str) -> str:
392
397
  """
393
398
  return re.sub(r'[\\/:*?"<>|]', '_', name)
394
399
 
395
- async def fetch_url(url: Union[str, Callable[[], str], Callable[[], Awaitable[str]]], retry_times: int = 3) -> str:
396
- while retry_times >= 0:
397
- try:
398
- if callable(url):
399
- result = url()
400
- if asyncio.iscoroutine(result) or isinstance(result, Awaitable):
401
- return await result
402
- return result
403
- elif isinstance(url, str):
404
- return url
405
- except Exception as e:
406
- retry_times -= 1
407
- if retry_times < 0:
408
- raise e
409
- await asyncio.sleep(2)
410
- raise RuntimeError("Max retries exceeded")
400
+ async def fetch_url(url: Union[str, Callable[[], str], Callable[[], Awaitable[str]]]) -> str:
401
+ """
402
+ 获取下载链接的包装函数,支持直接传入字符串或异步/同步的 Supplier 函数。
403
+
404
+ :note: 不包含重试机制,调用方需自行处理。
405
+ :param url: 下载链接或其 Supplier
406
+ :return: 下载链接
407
+ """
408
+
409
+ if callable(url):
410
+ result = url()
411
+ if asyncio.iscoroutine(result) or isinstance(result, Awaitable):
412
+ # 如果 url() 是一个异步函数,等待它
413
+ return await result
414
+ # 如果 url() 是一个同步函数,直接返回
415
+ return result
416
+ elif isinstance(url, str):
417
+ # 如果 url 只是个字符串,直接返回
418
+ return url
@@ -55,7 +55,6 @@ class StateManager:
55
55
  if not self._part_states:
56
56
  return
57
57
 
58
- debug("当前状态:", self._part_states)
59
58
  highest_status = max(self._part_states.values())
60
59
  if highest_status != self._current_status:
61
60
  self._current_status = highest_status
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kmoe-manga-downloader
3
- Version: 1.2.4
3
+ Version: 1.2.5
4
4
  Summary: A CLI-downloader for site @kox.moe.
5
5
  Author-email: Chris Zheng <chrisis58@outlook.com>
6
6
  License: MIT License
@@ -2,6 +2,8 @@
2
2
  LICENSE
3
3
  README.md
4
4
  pyproject.toml
5
+ .github/ISSUE_TEMPLATE/bug_report.yml
6
+ .github/ISSUE_TEMPLATE/feature_request.yml
5
7
  .github/workflows/release-package.yml
6
8
  .github/workflows/unit-test.yml
7
9
  assets/kmdr-demo.gif
@@ -129,6 +129,55 @@ class TestKmdrDownload(unittest.TestCase):
129
129
  os.path.getsize(os.path.join(dest, book_dir, f)) for f in os.listdir(os.path.join(dest, book_dir)) if os.path.isfile(os.path.join(dest, book_dir, f))
130
130
  )
131
131
  assert total_size < 1 * 0.6 * 1024 * 1024, "Total size of downloaded files exceeds 0.6 MB"
132
+
133
+ def test_download_single_volume_use_vip(self):
134
+ dest = f'{BASE_DIR}/{self.test_download_single_volume_use_vip.__name__}'
135
+
136
+ kmdr_main(
137
+ Namespace(
138
+ command='download',
139
+ dest=dest,
140
+ book_url=f'{DEFAULT_BASE_URL}/c/51044.htm',
141
+ vol_type='extra',
142
+ volume='all',
143
+ max_size=0.6,
144
+ limit=1,
145
+ retry=3,
146
+ vip=True
147
+ )
148
+ )
149
+
150
+ assert len(sub_dir := os.listdir(dest)) == 1, "Expected one subdirectory in the destination"
151
+ assert os.path.isdir(os.path.join(dest, book_dir := sub_dir[0])), "Expected the subdirectory to be a directory"
152
+ assert len(os.listdir(os.path.join(dest, book_dir))) == 1, "Expected 1 volume to be downloaded"
153
+
154
+ total_size = sum(
155
+ os.path.getsize(os.path.join(dest, book_dir, f)) for f in os.listdir(os.path.join(dest, book_dir)) if os.path.isfile(os.path.join(dest, book_dir, f))
156
+ )
157
+ assert total_size < 1 * 0.6 * 1024 * 1024, "Total size of downloaded files exceeds 0.6 MB"
158
+
159
+ def test_download_volume_with_direct_downloader_and_use_vip(self):
160
+ dest = f'{BASE_DIR}/{self.test_download_volume_with_direct_downloader_and_use_vip.__name__}'
161
+
162
+ kmdr_main(
163
+ Namespace(
164
+ command='download',
165
+ dest=dest,
166
+ book_url=f'{DEFAULT_BASE_URL}/c/51043.htm',
167
+ vol_type='extra',
168
+ volume='all',
169
+ max_size=0.4,
170
+ method=2, # use direct download method
171
+ limit=1,
172
+ retry=3,
173
+ num_workers=1,
174
+ vip=True
175
+ )
176
+ )
177
+
178
+ assert len(sub_dir := os.listdir(dest)) == 1, "Expected one subdirectory in the destination"
179
+ assert os.path.isdir(os.path.join(dest, book_dir := sub_dir[0])), "Expected the subdirectory to be a directory"
180
+ assert len(os.listdir(os.path.join(dest, book_dir))) == 1, "Expected 1 volume to be downloaded"
132
181
 
133
182
  def test_download_multiple_volumes_with_multiple_workers(self):
134
183
  dest = f'{BASE_DIR}/{self.test_download_multiple_volumes_with_multiple_workers.__name__}'