Skip to main content

eduboardapi/utils/
captcha.rs

1use scraper::{Html, Selector};
2use std::sync::OnceLock;
3
4use crate::exceptions::{AppError, AppResult};
5
6fn td_selector() -> &'static Selector {
7    static TD_SELECTOR: OnceLock<Selector> = OnceLock::new();
8    TD_SELECTOR.get_or_init(|| Selector::parse("td").expect("valid td selector"))
9}
10
11pub fn solve_captcha(html: &str) -> AppResult<String> {
12    let document = Html::parse_document(html);
13
14    for td in document.select(td_selector()) {
15        let text = td.text().map(str::trim).collect::<String>();
16        if text.contains('+') {
17            let mut parts = text.split_whitespace();
18            if let (Some(left), Some("+"), Some(right), None) =
19                (parts.next(), parts.next(), parts.next(), parts.next())
20            {
21                let left: i32 = left
22                    .parse()
23                    .map_err(|e: std::num::ParseIntError| AppError::Captcha(e.to_string()))?;
24                let right: i32 = right
25                    .parse()
26                    .map_err(|e: std::num::ParseIntError| AppError::Captcha(e.to_string()))?;
27                return Ok((left + right).to_string());
28            }
29        }
30    }
31
32    Err(AppError::Captcha("Captcha not found".to_string()))
33}