feat: suppression individuelle de releases dans les available downloads
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 39s

Ajoute DELETE /available-downloads/:id?release=N pour supprimer une
release spécifique du JSON array (supprime l'entrée série si c'est
la dernière). Bouton trash sur chaque release dans la page downloads.

Corrige aussi le parsing des ranges de volumes sans préfixe sur le
second nombre (T17-23 détecte maintenant T17 à T23).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 17:51:09 +01:00
parent 5e6217cc30
commit 9b04a79330
5 changed files with 146 additions and 8 deletions

View File

@@ -161,7 +161,10 @@ fn extract_volumes_from_title(title: &str) -> Vec<i32> {
while k < chars.len() && chars[k] == ' ' {
k += 1;
}
if let Some((n2, _)) = read_vol_prefix_number(&chars, k) {
// Try prefixed number first (T17-T23), then bare number (T17-23)
let n2_result = read_vol_prefix_number(&chars, k)
.or_else(|| read_bare_number(&chars, k));
if let Some((n2, _)) = n2_result {
if n1 < n2 && n2 - n1 <= 500 {
for v in n1..=n2 {
if !volumes.contains(&v) {
@@ -239,6 +242,19 @@ fn extract_volumes_from_title(title: &str) -> Vec<i32> {
volumes
}
/// Read a bare number (no prefix) at `pos`. Returns `(number, position_after_last_digit)`.
fn read_bare_number(chars: &[char], pos: usize) -> Option<(i32, usize)> {
let mut i = pos;
while i < chars.len() && chars[i].is_ascii_digit() {
i += 1;
}
if i == pos {
return None;
}
let n: i32 = chars[pos..i].iter().collect::<String>().parse().ok()?;
Some((n, i))
}
/// Try to read a vol-prefixed number starting at `pos` in the `chars` slice.
/// Returns `(number, position_after_last_digit)` or `None`.
/// Prefixes recognised (longest first to avoid "t" matching "tome"):
@@ -557,6 +573,15 @@ mod tests {
assert_eq!(v, (1..=15).collect::<Vec<_>>());
}
#[test]
fn range_dash_bare_end() {
// T17-23 (no prefix on second number) → 17..=23
let v = sorted(extract_volumes_from_title(
"Compressé.Demon.Slayer.en.couleurs.T17-23.CBZ.Team.Chromatique",
));
assert_eq!(v, (17..=23).collect::<Vec<_>>());
}
#[test]
fn no_false_positive_version_string() {
// v2.0 should NOT be treated as a range