feat: bouton télécharger et remplacer + fix extraction volumes UTF-8

- Ajout d'un bouton "télécharger et remplacer" avec popup de
  confirmation, qui passe tous les volumes du pack (pas seulement
  les manquants) et replace_existing=true à l'API.
- Nouvelle colonne replace_existing dans torrent_downloads.
- Fix critique du parseur de volumes : le pass 2 mélangeait les
  indices d'octets (String::find) avec les indices de caractères
  (Vec<char>), causant un décalage quand le titre contenait des
  caractères multi-octets (é, à...). "Tome #097" extrayait 9
  au lieu de 97. Réécrit en indexation char pure.
- Le préfixe "tome" skip désormais "#" (tome #097 → 97).
- Protection intra-batch : si une destination est déjà utilisée,
  le fichier garde son nom original au lieu d'écraser.
- Alerte WARN si N fichiers source donnent N/3 volumes uniques.
- Nettoyage du répertoire sl-{id} et de la catégorie qBittorrent
  après import.
- Badges volumes en flex-wrap dans la page downloads.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-27 16:01:08 +01:00
parent 9c18802864
commit eabb88eb9d
11 changed files with 205 additions and 66 deletions

View File

@@ -49,6 +49,8 @@ pub struct AvailableReleaseDto {
pub indexer: Option<String>,
pub seeders: Option<i32>,
pub matched_missing_volumes: Vec<i32>,
#[serde(default)]
pub all_volumes: Vec<i32>,
}
// ---------------------------------------------------------------------------
@@ -714,7 +716,8 @@ async fn search_prowlarr_for_series(
.filter_map(|r| {
let title_volumes = prowlarr::extract_volumes_from_title_pub(&r.title);
let matched_vols: Vec<i32> = title_volumes
.into_iter()
.iter()
.copied()
.filter(|v| missing_volumes.contains(v))
.collect();
if matched_vols.is_empty() {
@@ -727,6 +730,7 @@ async fn search_prowlarr_for_series(
indexer: r.indexer,
seeders: r.seeders,
matched_missing_volumes: matched_vols,
all_volumes: title_volumes,
})
}
})