@@ -58,90 +58,85 @@ def enable_client_cache_on_condition(cls,
5858
5959
6060class 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'
7762
7863 def __init__ (self , rule : str , base_dir = None ):
7964 base_dir = JmcomicText .parse_to_abspath (base_dir )
8065 self .base_dir = base_dir
8166 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 )
8368
8469 def decide_image_save_dir (self ,
8570 album : JmAlbumDetail ,
8671 photo : JmPhotoDetail ,
8772 ) -> 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 )
10074
10175 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 )
10577
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' )):
10782 continue
10883
10984 try :
110- ret = self . apply_rule_solver (album , None , solver )
85+ path = parser (album , photo , rule )
11186 except BaseException as e :
11287 # noinspection PyUnboundLocalVariable
113- jm_log ('dir_rule' , f'路径规则"{ rule } "的解析出错: { e } , album={ album } ' )
88+ jm_log ('dir_rule' , f'路径规则"{ rule } "的解析出错: { e } , album={ album } , photo= { photo } ' )
11489 raise e
90+ if parser != self .parse_bd_rule :
91+ path = fix_windir_name (str (path )).strip ()
11592
116- path_ls .append (str ( ret ) )
93+ path_ls .append (path )
11794
11895 return fix_filepath ('/' .join (path_ls ), is_dir = True )
11996
120- def get_role_solver_list (self , rule_dsl : str , base_dir : str ) -> RuleSolverList :
97+ def get_rule_parser_list (self , rule_dsl : str ) :
12198 """
12299 解析下载路径dsl,得到一个路径规则解析列表
123100 """
124101
125102 rule_list = self .split_rule_dsl (rule_dsl )
126- solver_ls : List [ DirRule . RuleSolver ] = []
103+ parser_list : list = []
127104
128105 for rule in rule_list :
129106 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 ))
132109 continue
133110
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 :
136113 ExceptionTool .raises (f'不支持的dsl: "{ rule } " in "{ rule_dsl } "' )
137114
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 )
139131
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 :]))
141136
142137 # 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 :
145140 return [rule_dsl ]
146141
147142 if '/' in rule_dsl :
@@ -153,50 +148,21 @@ def split_rule_dsl(self, rule_dsl: str) -> List[str]:
153148 ExceptionTool .raises (f'不支持的rule配置: "{ rule_dsl } "' )
154149
155150 @classmethod
156- def get_rule_solver (cls , rule : str ) -> Optional [ RuleSolver ] :
151+ def get_rule_parser (cls , rule : str ):
157152 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
162154
163- # 检查dsl
164- if not rule .startswith (('A' , 'P' )):
165- return None
155+ if rule .startswith (('A' , 'P' )):
156+ return cls .parse_detail_rule
166157
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 } "' )
196159
197160 @classmethod
198161 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 ()
200166
201167
202168class JmOption :
@@ -471,7 +437,7 @@ def update_cookies(self, cookies: dict):
471437 orig_cookies .update (cookies )
472438 metadata ['cookies' ] = orig_cookies
473439
474- # noinspection PyMethodMayBeStatic
440+ # noinspection PyMethodMayBeStatic,PyTypeChecker
475441 def decide_client_domain (self , client_key : str ) -> List [str ]:
476442 def is_client_type (ctype ) -> bool :
477443 return self .client_key_is_given_type (client_key , ctype )
0 commit comments