bhcli

"Strange's fork of n0tr1v's bhcli (onion)"
git clone https://git.dasho.dev/Strange/bhcli.git
Log | Files | Refs | README

commit 6b6c01b8f28addd3df211bd714628529d3f701d2
parent 8fb69816832f5d1bbdc82078c0e9aad40d6e9763
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Thu, 30 Mar 2023 01:19:28 -0700

cleanup

Diffstat:
Msrc/lechatphp/mod.rs | 88++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 49 insertions(+), 39 deletions(-)

diff --git a/src/lechatphp/mod.rs b/src/lechatphp/mod.rs @@ -179,6 +179,12 @@ impl Letter { #[derive(Debug)] struct CaptchaErr(String); +impl From<&str> for CaptchaErr { + fn from(value: &str) -> Self { + CaptchaErr(value.to_owned()) + } +} + impl Display for CaptchaErr { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) @@ -194,13 +200,52 @@ impl std::error::Error for CaptchaErr {} // Red circle is 17x17 (initial point) fn solve_difficulty3(img: &DynamicImage) -> Result<String, CaptchaErr> { //img.save(format!("captcha.gif")).unwrap(); + + // Step1: Find all letters with red on the center + let letters_map = find_letters(&img); + + if letters_map.len() != 5 { + return Err(CaptchaErr(format!("did not find exactly 5 letters {}", letters_map.len()))); + } + + // Step2: Find the starting letter + let starting = get_starting_letter(&img, &letters_map).ok_or(CaptchaErr("could not find starting letter".to_owned()))?; + + let mut answer = String::new(); + let mut visited = HashSet::<Letter>::new(); + let mut letter = starting; + answer.push(letter.character); + visited.insert(letter.clone()); + for i in 0..4 { + let top_left = Point::new(letter.offset.x-5, letter.offset.y-3); + let mut rect = Rect{p1: top_left, width: 8+5+6, height: 14+3+2}; + let mut retry = 0; + 'retry_loop: loop { + retry += 1; + let square = img.crop_imm(rect.p1.x, rect.p1.y, rect.width, rect.height); + let red_px_pts = get_contour_red_pixels(&rect.p1, &square); + let nb_lines = if i == 0 { 1 } else { 2 }; + if red_px_pts.len() != nb_lines { + if retry < 10 { + rect.enlarge(); + continue 'retry_loop; + } + return Err(CaptchaErr(format!("letter #{} {:?} invalid nb lines detected", i+1, letter))); + } + letter = get_next_node(&red_px_pts, &letter, &letters_map, &visited, i, nb_lines)?; + break 'retry_loop; + } + answer.push(letter.character); + visited.insert(letter.clone()); + } + Ok(answer) +} + +fn find_letters(img: &DynamicImage) -> HashMap<char, Letter> { let image_width = 150; let image_height = 200; let min_px_for_letter = 21; - let mut letters_map: HashMap<char, Letter> = HashMap::new(); - - // Step1: Find all letters with red on the center for y in 0..image_height { for x in 0..image_width { let letter_img = img.crop_imm(x, y, 8, 14); @@ -243,42 +288,7 @@ fn solve_difficulty3(img: &DynamicImage) -> Result<String, CaptchaErr> { } } } - - if letters_map.len() != 5 { - return Err(CaptchaErr(format!("did not find exactly 5 letters {}", letters_map.len()))); - } - - // Step2: Find the starting letter - let starting = get_starting_letter(&img, &letters_map).ok_or(CaptchaErr("could not find starting letter".to_owned()))?; - - let mut answer = String::new(); - let mut visited = HashSet::<Letter>::new(); - let mut letter = starting; - answer.push(letter.character); - visited.insert(letter.clone()); - for i in 0..4 { - let top_left = Point::new(letter.offset.x-5, letter.offset.y-3); - let mut rect = Rect{p1: top_left, width: 8+5+6, height: 14+3+2}; - let mut retry = 0; - 'retry_loop: loop { - retry += 1; - let square = img.crop_imm(rect.p1.x, rect.p1.y, rect.width, rect.height); - let red_px_pts = get_contour_red_pixels(&rect.p1, &square); - let nb_lines = if i == 0 { 1 } else { 2 }; - if red_px_pts.len() != nb_lines { - if retry < 10 { - rect.enlarge(); - continue 'retry_loop; - } - return Err(CaptchaErr(format!("letter #{} {:?} invalid nb lines detected", i+1, letter))); - } - letter = get_next_node(&red_px_pts, &letter, &letters_map, &visited, i, nb_lines)?; - break 'retry_loop; - } - answer.push(letter.character); - visited.insert(letter.clone()); - } - Ok(answer) + letters_map } fn get_starting_letter(img: &DynamicImage, letters_map: &HashMap<char, Letter>) -> Option<Letter> {