Fix the caps kicker to trigger on ratio, not uppercase count
All checks were successful
CI / check (push) Successful in 5m16s

This commit is contained in:
Jean Chevronnet 2026-07-19 18:52:26 +00:00
parent e4a2e76903
commit d0a86359c2
No known key found for this signature in database
2 changed files with 15 additions and 1 deletions

View file

@ -635,7 +635,9 @@ impl KickerSettings {
if text.chars().count() >= min { if text.chars().count() >= min {
let upper = text.chars().filter(|c| c.is_ascii_uppercase()).count() as u32; let upper = text.chars().filter(|c| c.is_ascii_uppercase()).count() as u32;
let lower = text.chars().filter(|c| c.is_ascii_lowercase()).count() as u32; let lower = text.chars().filter(|c| c.is_ascii_lowercase()).count() as u32;
if upper as usize >= min && upper + lower > 0 && upper * 100 / (upper + lower) >= percent { // Length is already gated above; gate only on the caps ratio here
// (a prior `upper >= min` clause wrongly demanded min uppercase letters).
if upper + lower > 0 && upper * 100 / (upper + lower) >= percent {
return Some("Turn caps lock off!"); return Some("Turn caps lock off!");
} }
} }

View file

@ -941,3 +941,15 @@
assert_eq!(db.channel("#foo").unwrap().join_mode("alice"), None, "purge holds after replay"); assert_eq!(db.channel("#foo").unwrap().join_mode("alice"), None, "purge holds after replay");
assert_eq!(db.channel_successor("#bar"), None, "successor purge holds after replay"); assert_eq!(db.channel_successor("#bar"), None, "successor purge holds after replay");
} }
#[test]
fn caps_kicker_triggers_on_ratio_not_uppercase_count() {
let k = KickerSettings { caps: true, ..Default::default() };
// 9 uppercase in an 18-char line is ~50% caps and over the length floor —
// it must trip even though the uppercase count is below caps_min (a prior
// `upper >= min` bug let it slip through).
assert_eq!(k.violation("AAAAAAAAA hi there"), Some("Turn caps lock off!"));
// A short or low-ratio line still doesn't trip.
assert_eq!(k.violation("Hello there"), None);
assert_eq!(k.violation("YO"), None, "too short for the length floor");
}