jmcomic 2.5.9__py3-none-any.whl → 2.5.11__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.
jmcomic/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # 被依赖方 <--- 使用方
3
3
  # config <--- entity <--- toolkit <--- client <--- option <--- downloader
4
4
 
5
- __version__ = '2.5.9'
5
+ __version__ = '2.5.11'
6
6
 
7
7
  from .api import *
8
8
  from .jm_plugin import *
@@ -572,3 +572,15 @@ class JmcomicClient(
572
572
  }
573
573
 
574
574
  yield from self.do_page_iter(params, page, self.categories_filter)
575
+
576
+ def is_given_type(self, ctype: Type['JmcomicClient']) -> bool:
577
+ """
578
+ Client代理的此方法会被路由到内部client的方法
579
+ 即:ClientProxy(AClient()).is_given_type(AClient) is True
580
+ 但是: ClientProxy(AClient()).client_key != AClient.client_key
581
+ """
582
+ if isinstance(self, ctype):
583
+ return True
584
+ if self.client_key == instance.client_key:
585
+ return True
586
+ return False
jmcomic/jm_config.py CHANGED
@@ -368,7 +368,7 @@ class JmModuleConfig:
368
368
  'postman': {
369
369
  'type': 'cffi',
370
370
  'meta_data': {
371
- 'impersonate': 'chrome',
371
+ 'impersonate': 'chrome110',
372
372
  'headers': None,
373
373
  'proxies': None,
374
374
  }
jmcomic/jm_option.py CHANGED
@@ -236,28 +236,6 @@ class JmOption:
236
236
  def decide_photo_batch_count(self, album: JmAlbumDetail):
237
237
  return self.download.threading.photo
238
238
 
239
- def decide_album_dir(self, album: JmAlbumDetail) -> str:
240
- """
241
- 该方法目前仅在 plugin-zip 中使用,不建议外部调用
242
- """
243
- dir_layer = []
244
- dir_rule = self.dir_rule
245
- for rule in dir_rule.rule_dsl.split('_'):
246
- if rule == 'Bd':
247
- dir_layer.append(dir_rule.base_dir)
248
- continue
249
-
250
- if rule[0] == 'A':
251
- name = dir_rule.apply_rule_directly(album, None, rule)
252
- dir_layer.append(name)
253
-
254
- if rule[0] == 'P':
255
- break
256
-
257
- from os.path import join
258
- # noinspection PyTypeChecker
259
- return join(*dir_layer)
260
-
261
239
  # noinspection PyMethodMayBeStatic
262
240
  def decide_image_filename(self, image: JmImageDetail) -> str:
263
241
  """
jmcomic/jm_plugin.py CHANGED
@@ -302,27 +302,19 @@ class ZipPlugin(JmOptionPlugin):
302
302
 
303
303
  if level == 'album':
304
304
  zip_path = self.get_zip_path(album, None, filename_rule, suffix, zip_dir)
305
- dir_path = self.zip_album(album, photo_dict, zip_path)
306
- if dir_path is not None:
307
- # 要删除这个album文件夹
308
- dir_zip_dict[dir_path] = zip_path
309
- # 也要删除album下的photo文件夹
310
- for d in files_of_dir(dir_path):
311
- dir_zip_dict[d] = None
305
+ self.zip_album(album, photo_dict, zip_path, dir_zip_dict)
312
306
 
313
307
  elif level == 'photo':
314
308
  for photo, image_list in photo_dict.items():
315
309
  zip_path = self.get_zip_path(None, photo, filename_rule, suffix, zip_dir)
316
- dir_path = self.zip_photo(photo, image_list, zip_path)
317
- if dir_path is not None:
318
- dir_zip_dict[dir_path] = zip_path
310
+ self.zip_photo(photo, image_list, zip_path, dir_zip_dict)
319
311
 
320
312
  else:
321
313
  ExceptionTool.raises(f'Not Implemented Zip Level: {level}')
322
314
 
323
315
  self.after_zip(dir_zip_dict)
324
316
 
325
- def zip_photo(self, photo, image_list: list, zip_path: str) -> Optional[str]:
317
+ def zip_photo(self, photo, image_list: list, zip_path: str, dir_zip_dict) -> Optional[str]:
326
318
  """
327
319
  压缩photo文件夹
328
320
  :returns: photo文件夹路径
@@ -333,50 +325,58 @@ class ZipPlugin(JmOptionPlugin):
333
325
 
334
326
  all_filepath = set(map(lambda t: self.unified_path(t[0]), image_list))
335
327
 
336
- return self.do_zip(photo_dir,
337
- zip_path,
338
- all_filepath,
339
- f'压缩章节[{photo.photo_id}]成功 → {zip_path}',
340
- )
328
+ if len(all_filepath) == 0:
329
+ self.log('无下载文件,无需压缩', 'skip')
330
+ return None
331
+
332
+ from common import backup_dir_to_zip
333
+ backup_dir_to_zip(
334
+ photo_dir,
335
+ zip_path,
336
+ acceptor=lambda f: os.path.isdir(f) or self.unified_path(f) in all_filepath
337
+ ).close()
338
+
339
+ self.log(f'压缩章节[{photo.photo_id}]成功 → {zip_path}', 'finish')
340
+ dir_zip_dict[self.unified_path(photo_dir)] = zip_path
341
341
 
342
342
  @staticmethod
343
343
  def unified_path(f):
344
344
  return fix_filepath(f, os.path.isdir(f))
345
345
 
346
- def zip_album(self, album, photo_dict: dict, zip_path) -> Optional[str]:
346
+ def zip_album(self, album, photo_dict: dict, zip_path, dir_zip_dict) -> Optional[str]:
347
347
  """
348
348
  压缩album文件夹
349
349
  :returns: album文件夹路径
350
350
  """
351
- all_filepath: Set[str] = set()
352
-
353
- def addpath(f):
354
- all_filepath.update(set(f))
355
351
 
356
- album_dir = self.option.decide_album_dir(album)
357
- # addpath(self.option.decide_image_save_dir(photo) for photo in photo_dict.keys())
358
- addpath(path for ls in photo_dict.values() for path, _ in ls)
352
+ # 所有下载了的图片文件的路径
353
+ all_filepath: Set[str] = set(path for ls in photo_dict.values() for path, _ in ls)
359
354
 
360
- return self.do_zip(album_dir,
361
- zip_path,
362
- all_filepath,
363
- msg=f'压缩本子[{album.album_id}]成功 → {zip_path}',
364
- )
365
-
366
- def do_zip(self, source_dir, zip_path, all_filepath, msg):
367
355
  if len(all_filepath) == 0:
368
356
  self.log('无下载文件,无需压缩', 'skip')
369
- return None
357
+ return
370
358
 
359
+ # 该本子的所有章节的图片所在文件夹
360
+ photo_dir_list = [self.option.decide_image_save_dir(photo) for photo in photo_dict.keys()]
361
+
362
+ # 压缩文件对象
371
363
  from common import backup_dir_to_zip
372
- backup_dir_to_zip(
373
- source_dir,
374
- zip_path,
375
- acceptor=lambda f: os.path.isdir(f) or self.unified_path(f) in all_filepath
376
- ).close()
364
+ import zipfile
365
+ zfile = zipfile.ZipFile(zip_path, 'w')
366
+
367
+ for photo_dir in photo_dir_list:
368
+ photo_dir = self.unified_path(photo_dir)
369
+ backup_dir_to_zip(
370
+ photo_dir,
371
+ zip_path,
372
+ zfile=zfile,
373
+ prefix=os.path.basename(photo_dir.rstrip('/')),
374
+ acceptor=lambda f: os.path.isdir(f) or self.unified_path(f) in all_filepath
375
+ )
376
+ dir_zip_dict[photo_dir] = zip_path
377
377
 
378
- self.log(msg, 'finish')
379
- return self.unified_path(source_dir)
378
+ zfile.close()
379
+ self.log(f'压缩本子[{album.album_id}]成功 → {zip_path}', 'finish')
380
380
 
381
381
  def after_zip(self, dir_zip_dict: Dict[str, Optional[str]]):
382
382
  # 删除所有原文件
@@ -757,6 +757,49 @@ class ConvertJpgToPdfPlugin(JmOptionPlugin):
757
757
  self.execute_deletion(paths)
758
758
 
759
759
 
760
+ class Img2pdfPlugin(JmOptionPlugin):
761
+ plugin_key = 'img2pdf'
762
+
763
+ def invoke(self,
764
+ photo: JmPhotoDetail,
765
+ downloader=None,
766
+ pdf_dir=None,
767
+ filename_rule='Pid',
768
+ delete_original_file=False,
769
+ **kwargs,
770
+ ):
771
+ try:
772
+ import img2pdf
773
+ except ImportError:
774
+ self.warning_lib_not_install('img2pdf')
775
+ return
776
+
777
+ self.delete_original_file = delete_original_file
778
+
779
+ # 处理文件夹配置
780
+ filename = DirRule.apply_rule_directly(None, photo, filename_rule)
781
+ photo_dir = self.option.decide_image_save_dir(photo)
782
+
783
+ # 处理生成的pdf文件的路径
784
+ if pdf_dir is None:
785
+ pdf_dir = photo_dir
786
+ else:
787
+ pdf_dir = fix_filepath(pdf_dir, True)
788
+ mkdir_if_not_exists(pdf_dir)
789
+
790
+ pdf_filepath = os.path.join(pdf_dir, f'{filename}.pdf')
791
+
792
+ # 调用 img2pdf 把 photo_dir 下的所有图片转为pdf
793
+ all_img = files_of_dir(photo_dir)
794
+ with open(pdf_filepath, 'wb') as f:
795
+ f.write(img2pdf.convert(all_img))
796
+
797
+ # 执行删除
798
+ self.log(f'Convert Successfully: JM{photo.id} → {pdf_filepath}')
799
+ all_img.append(self.option.decide_image_save_dir(photo, ensure_exists=False))
800
+ self.execute_deletion(all_img)
801
+
802
+
760
803
  class JmServerPlugin(JmOptionPlugin):
761
804
  plugin_key = 'jm_server'
762
805
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jmcomic
3
- Version: 2.5.9
3
+ Version: 2.5.11
4
4
  Summary: Python API For JMComic (禁漫天堂)
5
5
  Home-page: https://github.com/hect0x7/JMComic-Crawler-Python
6
6
  Author: hect0x7
@@ -0,0 +1,18 @@
1
+ jmcomic/__init__.py,sha256=Hjp1Q6tJ5zCFkSqh2ETXJuh_Rgpx5OKEjMhSbrU3dTs,903
2
+ jmcomic/api.py,sha256=uLHtSof7ZaiWZcNDDAz6grD1NYs4VxsoCOrsge3G7v8,3864
3
+ jmcomic/cl.py,sha256=PBSh0JndNFZw3B7WJPj5Y8SeFdKzHE00jIwYo9An-K0,3475
4
+ jmcomic/jm_client_impl.py,sha256=Oszkw7dKfg8DHzmjyBVD1DrHp9OlvLK33IQHB7uXo48,37811
5
+ jmcomic/jm_client_interface.py,sha256=vP36T2OI5MQdmfdYEnoFGRpHZRTE9LnBetDUFCOnMg4,17691
6
+ jmcomic/jm_config.py,sha256=I08aDW1WH9uVnbyiUvy4lfI8cAU8NNK96cEA5kGYcoM,15252
7
+ jmcomic/jm_downloader.py,sha256=0r4z7FRnow6xkRy_WTv7nLQOhYdtZmoouw0BNrhngco,10397
8
+ jmcomic/jm_entity.py,sha256=-WUKYGkNToQv5Hja3RkI5abHF1g46WpLyVjoyXMs-wI,18974
9
+ jmcomic/jm_exception.py,sha256=B9APE1jw23JBzCT12eV_imCZny3mNrSXju1p2IquaHA,4801
10
+ jmcomic/jm_option.py,sha256=s16w8uZYfCBUgsxCjegnLoAqHF69rJicVZKQTZlQTJA,21723
11
+ jmcomic/jm_plugin.py,sha256=21bd71tmsKyli73skMx0ozcqBM5saHzICEicjRQ98-Q,33606
12
+ jmcomic/jm_toolkit.py,sha256=WLHaigCN03Z4b5swGTRTTSWzZsa0uFxGAnw4xKhbh1U,28649
13
+ jmcomic-2.5.11.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
14
+ jmcomic-2.5.11.dist-info/METADATA,sha256=2vGTgKwdQwztHQ8eIQ9cMOdHb5FTKYCPRZ_uWP6qP0E,6123
15
+ jmcomic-2.5.11.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
16
+ jmcomic-2.5.11.dist-info/entry_points.txt,sha256=tRbQltaGSBjejI0c9jYt-4SXQMd5nSDHcMvHmuTy4ow,44
17
+ jmcomic-2.5.11.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
18
+ jmcomic-2.5.11.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- jmcomic/__init__.py,sha256=WAC5HDkp2E-1HtrXfYzNJf9HWoCXqZx5wyLRUdFsFKI,902
2
- jmcomic/api.py,sha256=uLHtSof7ZaiWZcNDDAz6grD1NYs4VxsoCOrsge3G7v8,3864
3
- jmcomic/cl.py,sha256=PBSh0JndNFZw3B7WJPj5Y8SeFdKzHE00jIwYo9An-K0,3475
4
- jmcomic/jm_client_impl.py,sha256=Oszkw7dKfg8DHzmjyBVD1DrHp9OlvLK33IQHB7uXo48,37811
5
- jmcomic/jm_client_interface.py,sha256=f-2pFwJUzEdH4GVG8ExbR0dSoIP4w5M6CjX_Mlbxglc,17234
6
- jmcomic/jm_config.py,sha256=zVyxJrB-KpSwrVCEooglIdC2fT6St08P2ycK3GrqDTE,15249
7
- jmcomic/jm_downloader.py,sha256=0r4z7FRnow6xkRy_WTv7nLQOhYdtZmoouw0BNrhngco,10397
8
- jmcomic/jm_entity.py,sha256=-WUKYGkNToQv5Hja3RkI5abHF1g46WpLyVjoyXMs-wI,18974
9
- jmcomic/jm_exception.py,sha256=B9APE1jw23JBzCT12eV_imCZny3mNrSXju1p2IquaHA,4801
10
- jmcomic/jm_option.py,sha256=Y_ckE9xa6y0oqjG6CbKR3QX4TWvLuHK2ue_RzQkMxHM,22395
11
- jmcomic/jm_plugin.py,sha256=YWt7MAWuy2zOsHEARDKf4ZFE3pDmHPqM1M0vwnoNgVg,32262
12
- jmcomic/jm_toolkit.py,sha256=WLHaigCN03Z4b5swGTRTTSWzZsa0uFxGAnw4xKhbh1U,28649
13
- jmcomic-2.5.9.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
14
- jmcomic-2.5.9.dist-info/METADATA,sha256=317JlniKqNOIcwLCBrxP5hUpMCBIoiCECPM9poW_OHs,6122
15
- jmcomic-2.5.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
16
- jmcomic-2.5.9.dist-info/entry_points.txt,sha256=tRbQltaGSBjejI0c9jYt-4SXQMd5nSDHcMvHmuTy4ow,44
17
- jmcomic-2.5.9.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
18
- jmcomic-2.5.9.dist-info/RECORD,,