Skip to content

Commit 49c4891

Browse files
authored
v2.6.6: 更新禁漫APP端域名服务器的地址 (#473)
1 parent 5645e97 commit 49c4891

File tree

5 files changed

+101
-63
lines changed

5 files changed

+101
-63
lines changed

assets/docs/sources/tutorial/0_common_usage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ page: JmCategoryPage = cl.categories_filter(
216216
page=1,
217217
time=JmMagicConstants.TIME_ALL, # 时间选择全部,具体可以写什么请见JmMagicConstants
218218
category=JmMagicConstants.CATEGORY_ALL, # 分类选择全部,具体可以写什么请见JmMagicConstants
219-
order_by=JmMagicConstants.ORDER_BY_LATEST, # 按照观看数排序,具体可以写什么请见JmMagicConstants
219+
order_by=JmMagicConstants.ORDER_BY_VIEW, # 按照观看数排序,具体可以写什么请见JmMagicConstants
220220
)
221221

222222
# 月排行,底层实现也是调的categories_filter

src/jmcomic/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# 被依赖方 <--- 使用方
33
# config <--- entity <--- toolkit <--- client <--- option <--- downloader
44

5-
__version__ = '2.6.5'
5+
__version__ = '2.6.6'
66

77
from .api import *
88
from .jm_plugin import *

src/jmcomic/jm_client_impl.py

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def __init__(self,
2626
super().__init__(postman)
2727
self.retry_times = retry_times
2828
self.domain_list = domain_list
29+
self.domain_retry_strategy = None
2930
self.CLIENT_CACHE = None
3031
self._username = None # help for favorite_folder method
3132
self.enable_cache()
@@ -44,23 +45,14 @@ def of_api_url(self, api_path, domain):
4445
return JmcomicText.format_url(api_path, domain)
4546

4647
def get_jm_image(self, img_url) -> JmImageResp:
47-
48-
def callback(resp):
49-
"""
50-
使用此方法包装 self.get,使得图片数据为空时,判定为请求失败时,走重试逻辑
51-
"""
52-
resp = JmImageResp(resp)
53-
resp.require_success()
54-
return resp
55-
56-
return self.get(img_url, callback=callback, headers=JmModuleConfig.new_html_headers())
48+
return self.get(img_url, is_image=True, headers=JmModuleConfig.new_html_headers())
5749

5850
def request_with_retry(self,
5951
request,
6052
url,
6153
domain_index=0,
6254
retry_count=0,
63-
callback=None,
55+
is_image=False,
6456
**kwargs,
6557
):
6658
"""
@@ -74,11 +66,19 @@ def request_with_retry(self,
7466
:param url: 图片url / path (/album/xxx)
7567
:param domain_index: 域名下标
7668
:param retry_count: 重试次数
77-
:param callback: 回调,可以接收resp返回新的resp,也可以抛出异常强制重试
69+
:param is_image: 是否是图片请求
7870
:param kwargs: 请求方法的kwargs
7971
"""
72+
if self.domain_retry_strategy:
73+
return self.domain_retry_strategy(self,
74+
request,
75+
url,
76+
is_image,
77+
**kwargs,
78+
)
79+
8080
if domain_index >= len(self.domain_list):
81-
return self.fallback(request, url, domain_index, retry_count, **kwargs)
81+
return self.fallback(request, url, domain_index, retry_count, is_image, **kwargs)
8282

8383
url_backup = url
8484

@@ -87,12 +87,12 @@ def request_with_retry(self,
8787
domain = self.domain_list[domain_index]
8888
url = self.of_api_url(url, domain)
8989

90-
self.update_request_with_specify_domain(kwargs, domain)
90+
self.update_request_with_specify_domain(kwargs, domain, is_image)
9191

9292
jm_log(self.log_topic(), self.decode(url))
93-
else:
93+
elif is_image:
9494
# 图片url
95-
self.update_request_with_specify_domain(kwargs, None, True)
95+
self.update_request_with_specify_domain(kwargs, None, is_image)
9696

9797
if domain_index != 0 or retry_count != 0:
9898
jm_log(f'req.retry',
@@ -106,14 +106,8 @@ def request_with_retry(self,
106106

107107
try:
108108
resp = request(url, **kwargs)
109-
110-
# 回调,可以接收resp返回新的resp,也可以抛出异常强制重试
111-
if callback is not None:
112-
resp = callback(resp)
113-
114-
# 依然是回调,在最后返回之前,还可以判断resp是否重试
115-
resp = self.raise_if_resp_should_retry(resp)
116-
109+
# 在最后返回之前,还可以判断resp是否重试
110+
resp = self.raise_if_resp_should_retry(resp, is_image)
117111
return resp
118112
except Exception as e:
119113
if self.retry_times == 0:
@@ -122,15 +116,19 @@ def request_with_retry(self,
122116
self.before_retry(e, kwargs, retry_count, url)
123117

124118
if retry_count < self.retry_times:
125-
return self.request_with_retry(request, url_backup, domain_index, retry_count + 1, callback, **kwargs)
119+
return self.request_with_retry(request, url_backup, domain_index, retry_count + 1, is_image, **kwargs)
126120
else:
127-
return self.request_with_retry(request, url_backup, domain_index + 1, 0, callback, **kwargs)
121+
return self.request_with_retry(request, url_backup, domain_index + 1, 0, is_image, **kwargs)
128122

129123
# noinspection PyMethodMayBeStatic
130-
def raise_if_resp_should_retry(self, resp):
124+
def raise_if_resp_should_retry(self, resp, is_image):
131125
"""
132126
依然是回调,在最后返回之前,还可以判断resp是否重试
133127
"""
128+
if is_image is True:
129+
resp = JmImageResp(resp)
130+
resp.require_success()
131+
134132
return resp
135133

136134
def update_request_with_specify_domain(self, kwargs: dict, domain: Optional[str], is_image: bool = False):
@@ -208,7 +206,7 @@ def set_domain_list(self, domain_list: List[str]):
208206
self.domain_list = domain_list
209207

210208
# noinspection PyUnusedLocal
211-
def fallback(self, request, url, domain_index, retry_count, **kwargs):
209+
def fallback(self, request, url, domain_index, retry_count, is_image, **kwargs):
212210
msg = f"请求重试全部失败: [{url}], {self.domain_list}"
213211
jm_log('req.fallback', msg)
214212
ExceptionTool.raises(msg, {}, RequestRetryAllFailException)
@@ -965,17 +963,16 @@ def require_resp_success(cls, resp: JmApiResp, url: Optional[str] = None):
965963
# 2. 是否是特殊的内容
966964
# 暂无
967965

968-
def raise_if_resp_should_retry(self, resp):
966+
def raise_if_resp_should_retry(self, resp, is_image):
969967
"""
970968
该方法会判断resp返回值是否是json格式,
971969
如果不是,大概率是禁漫内部异常,需要进行重试
972970
973971
由于完整的json格式校验会有性能开销,所以只做简单的检查,
974972
只校验第一个有效字符是不是 '{',如果不是,就认为异常数据,需要重试
975-
976-
:param resp: 响应对象
977-
:return: resp
978973
"""
974+
resp = super().raise_if_resp_should_retry(resp, is_image)
975+
979976
if isinstance(resp, JmResp):
980977
# 不对包装过的resp对象做校验,包装者自行校验
981978
# 例如图片请求
@@ -1015,40 +1012,53 @@ def after_init(self):
10151012

10161013
client_update_domain_lock = Lock()
10171014

1015+
def req_api_domain_server(self, url):
1016+
resp = self.postman.get(url)
1017+
text: str = resp.text
1018+
# 去掉开头非ascii字符
1019+
while text and not text[0].isascii():
1020+
text = text[1:]
1021+
res_json = JmCryptoTool.decode_resp_data(text, '', JmMagicConstants.API_DOMAIN_SERVER_SECRET)
1022+
res_data = json_loads(res_json)
1023+
1024+
# 检查返回值
1025+
if not res_data.get('Server', None):
1026+
jm_log('api.update_domain.empty',
1027+
f'获取禁漫最新API域名失败, 返回值: {res_json}')
1028+
return None
1029+
else:
1030+
return res_data['Server']
1031+
10181032
def update_api_domain(self):
10191033
if True is JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE:
10201034
return
10211035

10221036
with self.client_update_domain_lock:
10231037
if True is JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE:
10241038
return
1025-
try:
1026-
# 获取域名列表
1027-
resp = self.postman.get(JmModuleConfig.API_URL_DOMAIN_SERVER)
1028-
res_json = JmCryptoTool.decode_resp_data(resp.text, '', JmMagicConstants.API_DOMAIN_SERVER_SECRET)
1029-
res_data = json_loads(res_json)
1030-
1031-
# 检查返回值
1032-
if not res_data.get('Server', None):
1033-
jm_log('api.update_domain.empty',
1034-
f'获取禁漫最新API域名失败, 返回值: {res_json}')
1035-
return
1036-
new_server_list: List[str] = res_data['Server']
1037-
old_server_list = JmModuleConfig.DOMAIN_API_LIST
1038-
jm_log('api.update_domain.success',
1039-
f'获取到最新的API域名,替换jmcomic内置域名:(new){new_server_list} ---→ (old){old_server_list}'
1040-
)
1041-
# 更新域名
1042-
if self.domain_list is old_server_list:
1043-
self.domain_list = new_server_list
1044-
JmModuleConfig.DOMAIN_API_LIST = new_server_list
1045-
except Exception as e:
1046-
jm_log('api.update_domain.error',
1047-
f'自动更新API域名失败,仍使用jmcomic内置域名。'
1048-
f'可通过代码[JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN=False]关闭自动更新API域名. 异常: {e}'
1049-
)
1050-
finally:
1051-
JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE = True
1039+
# 遍历多个域名服务器
1040+
for url in JmModuleConfig.API_URL_DOMAIN_SERVER_LIST:
1041+
try:
1042+
# 获取域名列表
1043+
new_server_list = self.req_api_domain_server(url)
1044+
if new_server_list is None:
1045+
continue
1046+
old_server_list = JmModuleConfig.DOMAIN_API_LIST
1047+
jm_log('api.update_domain.success',
1048+
f'获取到最新的API域名,替换jmcomic内置域名:(new){new_server_list} ---→ (old){old_server_list}'
1049+
)
1050+
# 更新域名
1051+
if sorted(self.domain_list) == sorted(old_server_list):
1052+
self.domain_list = new_server_list
1053+
JmModuleConfig.DOMAIN_API_LIST = new_server_list
1054+
break
1055+
except Exception as e:
1056+
jm_log('api.update_domain.error',
1057+
f'通过[{url}]自动更新API域名失败,仍使用jmcomic内置域名。'
1058+
f'可通过代码[JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN=False]关闭自动更新API域名. 异常: {e}'
1059+
)
1060+
# set done finally
1061+
JmModuleConfig.FLAG_API_CLIENT_AUTO_UPDATE_DOMAIN_DONE = True
10521062

10531063
client_init_cookies_lock = Lock()
10541064

src/jmcomic/jm_config.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class JmMagicConstants:
7777
APP_TOKEN_SECRET_2 = '18comicAPPContent'
7878
APP_DATA_SECRET = '185Hcomic3PAPP7R'
7979
API_DOMAIN_SERVER_SECRET = 'diosfjckwpqpdfjkvnqQjsik'
80-
APP_VERSION = '1.8.0'
80+
APP_VERSION = '2.0.6'
8181

8282

8383
# 模块级别共用配置
@@ -135,7 +135,10 @@ class JmModuleConfig:
135135
''')
136136

137137
# 获取最新移动端API域名的地址
138-
API_URL_DOMAIN_SERVER = f'{PROT}jmapp03-1308024008.cos.ap-jakarta.myqcloud.com/server-2024.txt'
138+
API_URL_DOMAIN_SERVER_LIST = shuffled('''
139+
https://rup4a04-c01.tos-ap-southeast-1.bytepluses.com/newsvr-2025.txt
140+
https://rup4a04-c02.tos-cn-hongkong.bytepluses.com/newsvr-2025.txt
141+
''')
139142

140143
APP_HEADERS_TEMPLATE = {
141144
'Accept-Encoding': 'gzip, deflate',

src/jmcomic/jm_plugin.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,3 +1216,28 @@ def new_decide_dir(photo, ensure_exists=True) -> str:
12161216
return original_path
12171217

12181218
self.option.decide_image_save_dir = new_decide_dir
1219+
1220+
1221+
class AdvancedRetryPlugin(JmOptionPlugin):
1222+
plugin_key = 'advanced-retry'
1223+
1224+
def invoke(self,
1225+
retry_config,
1226+
**kwargs):
1227+
new_jm_client: Callable = self.option.new_jm_client
1228+
1229+
def hook_new_jm_client(*args, **kwargs):
1230+
client: AbstractJmClient = new_jm_client(*args, **kwargs)
1231+
client.domain_retry_strategy = self.request_with_retry
1232+
return client
1233+
1234+
self.option.new_jm_client = hook_new_jm_client
1235+
1236+
def request_with_retry(self,
1237+
client,
1238+
request,
1239+
url,
1240+
is_image,
1241+
**kwargs,
1242+
):
1243+
pass

0 commit comments

Comments
 (0)