use super::*;
impl CaptchaSolverChain {
pub(crate) fn ordered_solvers(
&self,
domain: &str,
captcha_type: &CaptchaType,
kind: &crate::captcha_detect::DetectedCaptcha,
) -> Vec<&dyn CaptchaSolver> {
if let Some(reg) = &self.providers {
if let Some(provider) = reg.find_by_kind(kind) {
let names = provider.recommended_solver_names();
if !names.is_empty() {
return self.solvers_by_name(names, kind);
}
if matches!(kind, DetectedCaptcha::Custom(_)) {
let methods = provider.recommended_solver_methods();
return self.solvers_by_method(methods, kind);
}
} else if matches!(kind, DetectedCaptcha::Custom(_)) {
return Vec::new();
}
} else if matches!(kind, DetectedCaptcha::Custom(_)) {
return Vec::new();
}
let preferred = self.patterns.best_method(domain, captcha_type);
let mut ordered: Vec<&dyn CaptchaSolver> = self
.solvers
.iter()
.filter(|s| s.supports(kind))
.map(|s| s.as_ref())
.collect();
if let Some(pref) = preferred {
if let Some(pos) = ordered.iter().position(|s| s.method() == pref) {
if pos > 0 {
let item = ordered.remove(pos);
ordered.insert(0, item);
}
}
}
ordered
}
fn solvers_by_name(
&self,
names: &[&'static str],
kind: &crate::captcha_detect::DetectedCaptcha,
) -> Vec<&dyn CaptchaSolver> {
let mut ordered: Vec<&dyn CaptchaSolver> = Vec::with_capacity(names.len());
for name in names {
if let Some(s) = self
.solvers
.iter()
.find(|s| s.name() == *name && s.supports(kind))
{
let s_ref: &dyn CaptchaSolver = s.as_ref();
if !ordered
.iter()
.any(|existing| std::ptr::eq(*existing, s_ref))
{
ordered.push(s_ref);
}
}
}
ordered
}
fn solvers_by_method(
&self,
methods: &[SolveMethod],
kind: &crate::captcha_detect::DetectedCaptcha,
) -> Vec<&dyn CaptchaSolver> {
let mut ordered: Vec<&dyn CaptchaSolver> = Vec::with_capacity(methods.len());
for method in methods {
if let Some(s) = self
.solvers
.iter()
.find(|s| s.method() == *method && s.supports(kind))
{
let s_ref: &dyn CaptchaSolver = s.as_ref();
if !ordered
.iter()
.any(|existing| std::ptr::eq(*existing, s_ref))
{
ordered.push(s_ref);
}
}
}
ordered
}
}