@@ -58,90 +58,85 @@ def enable_client_cache_on_condition(cls,
58
58
59
59
60
60
class DirRule :
61
- rule_sample = [
62
- # 根目录 / Album-id / Photo-序号 /
63
- 'Bd_Aid_Pindex' , # 禁漫网站的默认下载方式
64
- # 根目录 / Album-作者 / Album-标题 / Photo-序号 /
65
- 'Bd_Aauthor_Atitle_Pindex' ,
66
- # 根目录 / Photo-序号&标题 /
67
- 'Bd_Pindextitle' ,
68
- # 根目录 / Photo-自定义类属性 /
69
- 'Bd_Aauthor_Atitle_Pcustomfield' ,
70
- # 需要替换JmModuleConfig.CLASS_ALBUM / CLASS_PHOTO才能让自定义属性生效
71
- ]
72
-
73
- Detail = Union [JmAlbumDetail , JmPhotoDetail , None ]
74
- RuleFunc = Callable
75
- RuleSolver = Tuple [str , RuleFunc , str ]
76
- RuleSolverList = List [RuleSolver ]
61
+ RULE_BASE_DIR = 'Bd'
77
62
78
63
def __init__ (self , rule : str , base_dir = None ):
79
64
base_dir = JmcomicText .parse_to_abspath (base_dir )
80
65
self .base_dir = base_dir
81
66
self .rule_dsl = rule
82
- self .solver_list = self .get_role_solver_list (rule , base_dir )
67
+ self .parser_list : List [ Tuple [ str , Callable ]] = self .get_rule_parser_list (rule )
83
68
84
69
def decide_image_save_dir (self ,
85
70
album : JmAlbumDetail ,
86
71
photo : JmPhotoDetail ,
87
72
) -> str :
88
- path_ls = []
89
- for solver in self .solver_list :
90
- try :
91
- ret = self .apply_rule_solver (album , photo , solver )
92
- except BaseException as e :
93
- # noinspection PyUnboundLocalVariable
94
- jm_log ('dir_rule' , f'路径规则"{ solver [2 ]} "的解析出错: { e } , album={ album } , photo={ photo } ' )
95
- raise e
96
-
97
- path_ls .append (str (ret ))
98
-
99
- return fix_filepath ('/' .join (path_ls ), is_dir = True )
73
+ return self ._build_path_from_rules (album , photo )
100
74
101
75
def decide_album_root_dir (self , album : JmAlbumDetail ) -> str :
102
- path_ls = []
103
- for solver in self .solver_list :
104
- key , _ , rule = solver
76
+ return self ._build_path_from_rules (album , None , True )
105
77
106
- if key != 'Bd' and key != 'A' :
78
+ def _build_path_from_rules (self , album , photo , only_album_rules = False ) -> str :
79
+ path_ls = []
80
+ for rule , parser in self .parser_list :
81
+ if only_album_rules and not (rule == self .RULE_BASE_DIR or rule .startswith ('A' )):
107
82
continue
108
83
109
84
try :
110
- ret = self . apply_rule_solver (album , None , solver )
85
+ path = parser (album , photo , rule )
111
86
except BaseException as e :
112
87
# noinspection PyUnboundLocalVariable
113
- jm_log ('dir_rule' , f'路径规则"{ rule } "的解析出错: { e } , album={ album } ' )
88
+ jm_log ('dir_rule' , f'路径规则"{ rule } "的解析出错: { e } , album={ album } , photo= { photo } ' )
114
89
raise e
90
+ if parser != self .parse_bd_rule :
91
+ path = fix_windir_name (str (path )).strip ()
115
92
116
- path_ls .append (str ( ret ) )
93
+ path_ls .append (path )
117
94
118
95
return fix_filepath ('/' .join (path_ls ), is_dir = True )
119
96
120
- def get_role_solver_list (self , rule_dsl : str , base_dir : str ) -> RuleSolverList :
97
+ def get_rule_parser_list (self , rule_dsl : str ) :
121
98
"""
122
99
解析下载路径dsl,得到一个路径规则解析列表
123
100
"""
124
101
125
102
rule_list = self .split_rule_dsl (rule_dsl )
126
- solver_ls : List [ DirRule . RuleSolver ] = []
103
+ parser_list : list = []
127
104
128
105
for rule in rule_list :
129
106
rule = rule .strip ()
130
- if rule == 'Bd' :
131
- solver_ls .append (('Bd' , lambda _ : base_dir , 'Bd' ))
107
+ if rule == self . RULE_BASE_DIR :
108
+ parser_list .append ((rule , self . parse_bd_rule ))
132
109
continue
133
110
134
- rule_solver = self .get_rule_solver (rule )
135
- if rule_solver is None :
111
+ parser = self .get_rule_parser (rule )
112
+ if parser is None :
136
113
ExceptionTool .raises (f'不支持的dsl: "{ rule } " in "{ rule_dsl } "' )
137
114
138
- solver_ls .append (rule_solver )
115
+ parser_list .append ((rule , parser ))
116
+
117
+ return parser_list
118
+
119
+ # noinspection PyUnusedLocal
120
+ def parse_bd_rule (self , album , photo , rule ):
121
+ return self .base_dir
122
+
123
+ @classmethod
124
+ def parse_f_string_rule (cls , album , photo , rule : str ):
125
+ properties = {}
126
+ if album :
127
+ properties .update (album .get_properties_dict ())
128
+ if photo :
129
+ properties .update (photo .get_properties_dict ())
130
+ return rule .format (** properties )
139
131
140
- return solver_ls
132
+ @classmethod
133
+ def parse_detail_rule (cls , album , photo , rule : str ):
134
+ detail = album if rule .startswith ('A' ) else photo
135
+ return str (DetailEntity .get_dirname (detail , rule [1 :]))
141
136
142
137
# noinspection PyMethodMayBeStatic
143
- def split_rule_dsl (self , rule_dsl : str ) -> List [ str ] :
144
- if rule_dsl == 'Bd' :
138
+ def split_rule_dsl (self , rule_dsl : str ):
139
+ if rule_dsl == self . RULE_BASE_DIR :
145
140
return [rule_dsl ]
146
141
147
142
if '/' in rule_dsl :
@@ -153,50 +148,21 @@ def split_rule_dsl(self, rule_dsl: str) -> List[str]:
153
148
ExceptionTool .raises (f'不支持的rule配置: "{ rule_dsl } "' )
154
149
155
150
@classmethod
156
- def get_rule_solver (cls , rule : str ) -> Optional [ RuleSolver ] :
151
+ def get_rule_parser (cls , rule : str ):
157
152
if '{' in rule :
158
- def format_path (album , photo ):
159
- return fix_windir_name (rule .format (** album .get_properties_dict (), ** photo .get_properties_dict ())).strip ()
160
-
161
- return 'F' , format_path , rule
153
+ return cls .parse_f_string_rule
162
154
163
- # 检查dsl
164
- if not rule .startswith (('A' , 'P' )):
165
- return None
155
+ if rule .startswith (('A' , 'P' )):
156
+ return cls .parse_detail_rule
166
157
167
- def solve_func (detail ):
168
- return fix_windir_name (str (DetailEntity .get_dirname (detail , rule [1 :]))).strip ()
169
-
170
- return rule [0 ], solve_func , rule
171
-
172
- @classmethod
173
- def apply_rule_solver (cls , album , photo , rule_solver : RuleSolver ) -> str :
174
- """
175
- 应用规则解析器(RuleSolver)
176
-
177
- :param album: JmAlbumDetail
178
- :param photo: JmPhotoDetail
179
- :param rule_solver: Ptitle
180
- :returns: photo.title
181
- """
182
-
183
- def choose_detail (key ):
184
- if key == 'Bd' :
185
- return None ,
186
- if key == 'A' :
187
- return album ,
188
- if key == 'P' :
189
- return photo ,
190
- if key == 'F' :
191
- return album , photo
192
-
193
- key , func , _ = rule_solver
194
- detail = choose_detail (key )
195
- return func (* detail )
158
+ ExceptionTool .raises (f'不支持的rule配置: "{ rule } "' )
196
159
197
160
@classmethod
198
161
def apply_rule_directly (cls , album , photo , rule : str ) -> str :
199
- return cls .apply_rule_solver (album , photo , cls .get_rule_solver (rule ))
162
+ if album is None :
163
+ album = photo .from_album
164
+ # noinspection PyArgumentList
165
+ return fix_windir_name (cls .get_rule_parser (rule )(album , photo , rule )).strip ()
200
166
201
167
202
168
class JmOption :
@@ -471,7 +437,7 @@ def update_cookies(self, cookies: dict):
471
437
orig_cookies .update (cookies )
472
438
metadata ['cookies' ] = orig_cookies
473
439
474
- # noinspection PyMethodMayBeStatic
440
+ # noinspection PyMethodMayBeStatic,PyTypeChecker
475
441
def decide_client_domain (self , client_key : str ) -> List [str ]:
476
442
def is_client_type (ctype ) -> bool :
477
443
return self .client_key_is_given_type (client_key , ctype )
0 commit comments