@@ -14,7 +14,12 @@ pub struct VerificationCode {
1414/// 提取策略 trait
1515trait ExtractionStrategy : Send + Sync {
1616 fn name ( & self ) -> & str ;
17- fn extract ( & self , text : & str , sender : Option < & str > , config : & AppConfig ) -> Option < VerificationCode > ;
17+ fn extract (
18+ & self ,
19+ text : & str ,
20+ sender : Option < & str > ,
21+ config : & AppConfig ,
22+ ) -> Option < VerificationCode > ;
1823 fn confidence ( & self ) -> f32 ;
1924}
2025
@@ -26,7 +31,12 @@ impl ExtractionStrategy for TemplateStrategy {
2631 "模板匹配"
2732 }
2833
29- fn extract ( & self , text : & str , _sender : Option < & str > , config : & AppConfig ) -> Option < VerificationCode > {
34+ fn extract (
35+ & self ,
36+ text : & str ,
37+ _sender : Option < & str > ,
38+ config : & AppConfig ,
39+ ) -> Option < VerificationCode > {
3040 for pattern_str in & config. verification_patterns {
3141 match Regex :: new ( pattern_str) {
3242 Ok ( re) => {
@@ -66,7 +76,12 @@ impl ExtractionStrategy for SenderWhitelistStrategy {
6676 "发件人白名单"
6777 }
6878
69- fn extract ( & self , text : & str , sender : Option < & str > , config : & AppConfig ) -> Option < VerificationCode > {
79+ fn extract (
80+ & self ,
81+ text : & str ,
82+ sender : Option < & str > ,
83+ config : & AppConfig ,
84+ ) -> Option < VerificationCode > {
7085 let sender = sender?;
7186 let sender_lower = sender. to_lowercase ( ) ;
7287
@@ -82,10 +97,7 @@ impl ExtractionStrategy for SenderWhitelistStrategy {
8297 // 对已知发件人使用更宽松的数字提取
8398 let re = Regex :: new ( r"\b(\d{4,8})\b" ) . ok ( ) ?;
8499 // 找到所有数字候选
85- let candidates: Vec < & str > = re
86- . find_iter ( text)
87- . map ( |m| m. as_str ( ) )
88- . collect ( ) ;
100+ let candidates: Vec < & str > = re. find_iter ( text) . map ( |m| m. as_str ( ) ) . collect ( ) ;
89101
90102 if candidates. is_empty ( ) {
91103 return None ;
@@ -119,19 +131,26 @@ impl ExtractionStrategy for KeywordProximityStrategy {
119131 "关键词近邻"
120132 }
121133
122- fn extract ( & self , text : & str , _sender : Option < & str > , config : & AppConfig ) -> Option < VerificationCode > {
134+ fn extract (
135+ & self ,
136+ text : & str ,
137+ _sender : Option < & str > ,
138+ config : & AppConfig ,
139+ ) -> Option < VerificationCode > {
123140 let text_lower = text. to_lowercase ( ) ;
124141
125142 for keyword in & config. verification_keywords {
126143 let keyword_lower = keyword. to_lowercase ( ) ;
127144 if let Some ( pos) = text_lower. find ( & keyword_lower) {
128145 // 在关键词前后 80 字符范围内搜索
129- let byte_start = text. char_indices ( )
146+ let byte_start = text
147+ . char_indices ( )
130148 . rev ( )
131149 . find ( |( i, _) | * i <= pos. saturating_sub ( 80 ) )
132150 . map ( |( i, _) | i)
133151 . unwrap_or ( 0 ) ;
134- let byte_end = text. char_indices ( )
152+ let byte_end = text
153+ . char_indices ( )
135154 . find ( |( i, _) | * i >= ( pos + keyword. len ( ) + 80 ) . min ( text. len ( ) ) )
136155 . map ( |( i, _) | i)
137156 . unwrap_or ( text. len ( ) ) ;
@@ -142,14 +161,16 @@ impl ExtractionStrategy for KeywordProximityStrategy {
142161 let re = Regex :: new ( r"\b(\d{4,8})\b" ) . ok ( ) ?;
143162 let candidates: Vec < regex:: Match > = re. find_iter ( window) . collect ( ) ;
144163
145- if let Some ( best) = candidates. iter ( )
146- . min_by_key ( |m| {
147- // 距离关键词最近的
148- let m_center = m. start ( ) + m. len ( ) / 2 ;
149- let kw_pos_in_window = if pos >= byte_start { pos - byte_start } else { 0 } ;
150- ( m_center as i64 - kw_pos_in_window as i64 ) . unsigned_abs ( )
151- } )
152- {
164+ if let Some ( best) = candidates. iter ( ) . min_by_key ( |m| {
165+ // 距离关键词最近的
166+ let m_center = m. start ( ) + m. len ( ) / 2 ;
167+ let kw_pos_in_window = if pos >= byte_start {
168+ pos - byte_start
169+ } else {
170+ 0
171+ } ;
172+ ( m_center as i64 - kw_pos_in_window as i64 ) . unsigned_abs ( )
173+ } ) {
153174 let code = best. as_str ( ) . to_string ( ) ;
154175 log:: debug!( "关键词 '{}' 近邻提取到验证码: {}" , keyword, code) ;
155176 return Some ( VerificationCode {
@@ -176,7 +197,12 @@ impl ExtractionStrategy for HtmlStructureStrategy {
176197 "HTML结构"
177198 }
178199
179- fn extract ( & self , text : & str , _sender : Option < & str > , _config : & AppConfig ) -> Option < VerificationCode > {
200+ fn extract (
201+ & self ,
202+ text : & str ,
203+ _sender : Option < & str > ,
204+ _config : & AppConfig ,
205+ ) -> Option < VerificationCode > {
180206 // 检测是否是 HTML 内容
181207 if !text. contains ( '<' ) || !text. contains ( '>' ) {
182208 return None ;
0 commit comments