Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,11 @@ jmcomic 123
- `下载特定后缀图片插件`
- `发送QQ邮件插件`
- `自动使用浏览器cookies插件`
- `jpg图片合成为一个pdf插件`
- `导出收藏夹为csv文件插件`
- `合并所有图片为pdf文件插件`
- `合并所有图片为长图插件`
- `合并所有图片为长图png插件`
- `重复文件检测删除插件`
- `网页观看本地章节插件`

## 使用小说明

Expand Down
15 changes: 0 additions & 15 deletions assets/docs/sources/option_file_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,19 +264,4 @@ plugins:
img_dir: D:/pdf/ # 长图存放文件夹
filename_rule: Aname # 长图命名规则,同上

# 请注意⚠
# 下方的j2p插件的功能不如img2pdf插件,不建议使用。
# 如有图片转pdf的需求,直接使用img2pdf即可,下面的内容请忽略。

- plugin: j2p # 图片合并插件,可以将下载下来的jpg图片合成为一个pdf插件
# 请注意⚠ 该插件的使用前提是,下载下来的图片是jpg图片
# 因此,使用该插件前,需要有如下配置:(下载图片格式转为jpg,上文有解释过此配置)
# download:
# image:
# suffix: .jpg
kwargs:
pdf_dir: D:/pdf/ # pdf存放文件夹
filename_rule: Pid # pdf命名规则
quality: 100 # pdf质量,0 - 100

```
2 changes: 1 addition & 1 deletion src/jmcomic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# 被依赖方 <--- 使用方
# config <--- entity <--- toolkit <--- client <--- option <--- downloader

__version__ = '2.5.39'
__version__ = '2.6.0'

from .api import *
from .jm_plugin import *
Expand Down
41 changes: 41 additions & 0 deletions src/jmcomic/jm_client_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,10 +1005,51 @@ def raise_if_resp_should_retry(self, resp):
ExceptionTool.raises_resp(f'响应无数据!request_url=[{url}]', resp)

def after_init(self):
# 自动更新禁漫API域名
if JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN:
self.update_api_domain()

# 保证拥有cookies,因为移动端要求必须携带cookies,否则会直接跳转同一本子【禁漫娘】
if JmModuleConfig.FLAG_API_CLIENT_REQUIRE_COOKIES:
self.ensure_have_cookies()

client_update_domain_lock = Lock()

def update_api_domain(self):
if True is JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE:
return

with self.client_update_domain_lock:
if True is JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE:
return
try:
# 获取域名列表
resp = self.postman.get(JmModuleConfig.API_URL_DOMAIN_SERVER)
res_json = JmCryptoTool.decode_resp_data(resp.text, '', JmMagicConstants.API_DOMAIN_SERVER_SECRET)
res_data = json_loads(res_json)

# 检查返回值
if not res_data.get('Server', None):
jm_log('api.update_domain.empty',
f'获取禁漫最新API域名失败, 返回值: {res_json}')
return
new_server_list: list[str] = res_data['Server']
old_server_list = JmModuleConfig.DOMAIN_API_LIST
jm_log('api.update_domain.success',
f'获取到最新的API域名,替换jmcomic内置域名:(new){new_server_list} ---→ (old){old_server_list}'
)
# 更新域名
if self.domain_list is old_server_list:
self.domain_list = new_server_list
JmModuleConfig.DOMAIN_API_LIST = new_server_list
except Exception as e:
jm_log('api.update_domain.error',
f'自动更新API域名失败,仍使用jmcomic内置域名。'
f'可通过代码[JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN=False]关闭自动更新API域名. 异常: {e}'
)
finally:
JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE = True

client_init_cookies_lock = Lock()

def ensure_have_cookies(self):
Expand Down
18 changes: 13 additions & 5 deletions src/jmcomic/jm_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ class JmMagicConstants:
APP_TOKEN_SECRET = '18comicAPP'
APP_TOKEN_SECRET_2 = '18comicAPPContent'
APP_DATA_SECRET = '185Hcomic3PAPP7R'
APP_VERSION = '1.7.9'
API_DOMAIN_SERVER_SECRET = 'diosfjckwpqpdfjkvnqQjsik'
APP_VERSION = '1.8.0'


# 模块级别共用配置
Expand Down Expand Up @@ -128,11 +129,15 @@ class JmModuleConfig:
# 移动端API域名
DOMAIN_API_LIST = shuffled('''
www.cdnmhwscc.vip
www.cdnblackmyth.club
www.cdnmhws.cc
www.cdnplaystation6.club
www.cdnplaystation6.org
www.cdnuc.vip
www.cdn-mspjmapiproxy.xyz
''')

# 获取最新移动端API域名的地址
API_URL_DOMAIN_SERVER = f'{PROT}jmappc01-1308024008.cos.ap-guangzhou.myqcloud.com/server-2024.txt'

APP_HEADERS_TEMPLATE = {
'Accept-Encoding': 'gzip, deflate',
'user-agent': 'Mozilla/5.0 (Linux; Android 9; V1938CT Build/PQ3A.190705.11211812; wv) AppleWebKit/537.36 (KHTML, '
Expand Down Expand Up @@ -200,6 +205,9 @@ class JmModuleConfig:
FLAG_USE_FIX_TIMESTAMP = True
# 移动端Client初始化cookies
FLAG_API_CLIENT_REQUIRE_COOKIES = True
# 自动更新禁漫API域名
FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN = True
FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE = None
# log开关标记
FLAG_ENABLE_JM_LOG = True
# log时解码url
Expand Down Expand Up @@ -380,7 +388,7 @@ def disable_jm_log(cls):

@classmethod
def new_postman(cls, session=False, **kwargs):
kwargs.setdefault('impersonate', 'chrome110')
kwargs.setdefault('impersonate', 'chrome')
kwargs.setdefault('headers', JmModuleConfig.new_html_headers())
kwargs.setdefault('proxies', JmModuleConfig.DEFAULT_PROXIES)

Expand Down Expand Up @@ -416,7 +424,7 @@ def new_postman(cls, session=False, **kwargs):
'postman': {
'type': 'curl_cffi',
'meta_data': {
'impersonate': 'chrome110',
'impersonate': 'chrome',
'headers': None,
'proxies': None,
}
Expand Down
31 changes: 17 additions & 14 deletions src/jmcomic/jm_option.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ def decide_image_save_dir(self,
album: JmAlbumDetail,
photo: JmPhotoDetail,
) -> str:
return self._build_path_from_rules(album, photo)
return self.apply_rule_to_path(album, photo)

def decide_album_root_dir(self, album: JmAlbumDetail) -> str:
return self._build_path_from_rules(album, None, True)
return self.apply_rule_to_path(album, None, True)

def _build_path_from_rules(self, album, photo, only_album_rules=False) -> str:
def apply_rule_to_path(self, album, photo, only_album_rules=False) -> str:
path_ls = []
for rule, parser in self.parser_list:
if only_album_rules and not (rule == self.RULE_BASE_DIR or rule.startswith('A')):
Expand All @@ -92,7 +92,7 @@ def _build_path_from_rules(self, album, photo, only_album_rules=False) -> str:

path_ls.append(path)

return fix_filepath('/'.join(path_ls), is_dir=True)
return fix_filepath('/'.join(path_ls))

def get_rule_parser_list(self, rule_dsl: str):
"""
Expand All @@ -103,7 +103,6 @@ def get_rule_parser_list(self, rule_dsl: str):
parser_list: list = []

for rule in rule_list:
rule = rule.strip()
if rule == self.RULE_BASE_DIR:
parser_list.append((rule, self.parse_bd_rule))
continue
Expand Down Expand Up @@ -135,17 +134,21 @@ def parse_detail_rule(cls, album, photo, rule: str):
return str(DetailEntity.get_dirname(detail, rule[1:]))

# noinspection PyMethodMayBeStatic
def split_rule_dsl(self, rule_dsl: str):
if rule_dsl == self.RULE_BASE_DIR:
return [rule_dsl]

def split_rule_dsl(self, rule_dsl: str) -> list[str]:
if '/' in rule_dsl:
return rule_dsl.split('/')
rule_list = rule_dsl.split('/')
elif '_' in rule_dsl:
rule_list = rule_dsl.split('_')
else:
rule_list = [rule_dsl]

for i, e in enumerate(rule_list):
rule_list[i] = e.strip()

if '_' in rule_dsl:
return rule_dsl.split('_')
if rule_list[0] != self.RULE_BASE_DIR:
rule_list.insert(0, self.RULE_BASE_DIR)

ExceptionTool.raises(f'不支持的rule配置: "{rule_dsl}"')
return rule_list

@classmethod
def get_rule_parser(cls, rule: str):
Expand All @@ -158,7 +161,7 @@ def get_rule_parser(cls, rule: str):
ExceptionTool.raises(f'不支持的rule配置: "{rule}"')

@classmethod
def apply_rule_directly(cls, album, photo, rule: str) -> str:
def apply_rule_to_filename(cls, album, photo, rule: str) -> str:
if album is None:
album = photo.from_album
# noinspection PyArgumentList
Expand Down
Loading