pub fn scan_screens_for_otpauth() -> Result<String, String> {
let screens =
screenshots::Screen::all().map_err(|e| format!("could not enumerate screens: {e}"))?;
if screens.is_empty() {
return Err("no screens available to scan".into());
}
let mut found_any_qr = false;
let mut saw_hotp = false;
for screen in screens {
let image = match screen.capture() {
Ok(img) => img,
Err(_) => continue, };
let png = image.buffer();
let texts = match keyroost_qr::texts_from_image(png) {
Ok(t) => t,
Err(_) => continue,
};
for text in texts.iter() {
let trimmed = text.trim();
let lower = trimmed.to_ascii_lowercase();
if lower.starts_with("otpauth://totp/") {
return Ok(trimmed.to_string());
}
if lower.starts_with("otpauth://") {
found_any_qr = true;
if lower.starts_with("otpauth://hotp/") {
saw_hotp = true;
}
} else if !trimmed.is_empty() {
found_any_qr = true;
}
}
}
if saw_hotp {
Err("this is an HOTP code; only TOTP is supported".into())
} else if found_any_qr {
Err("a QR code was found, but it isn't a TOTP (otpauth://totp) code".into())
} else {
Err("no QR code found on screen — make sure the TOTP QR is visible".into())
}
}