Ajoute la possibilité de convertir un livre CBR en CBZ depuis le backoffice. La conversion est sécurisée : le CBR original n'est supprimé qu'après vérification du CBZ généré et mise à jour de la base de données. - parsers: nouvelle fn `convert_cbr_to_cbz` (unar extract → zip pack → vérification → rename atomique) - api: `POST /books/:id/convert` crée un job `cbr_to_cbz` (vérifie format CBR, détecte collision) - indexer: nouveau `converter.rs` dispatché depuis `job.rs` - backoffice: bouton "Convert to CBZ" sur la page détail (visible si CBR), label dans JobRow - migrations: colonne `book_id` sur `index_jobs` + type `cbr_to_cbz` dans le check constraint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.8 KiB
ADDED Requirements
Requirement: Demande de conversion d'un livre CBR
L'API SHALL exposer un endpoint POST /books/:id/convert qui crée un job de type cbr_to_cbz pour le livre spécifié. L'endpoint SHALL retourner une erreur 409 Conflict si le livre n'est pas au format CBR. L'endpoint SHALL retourner une erreur 409 Conflict si un fichier {stem}.cbz existe déjà au même emplacement que le CBR.
Scenario: Conversion demandée sur un livre CBR
- WHEN l'utilisateur envoie
POST /books/:id/convertsur un livre avecfile_format = 'cbr' - THEN un job
cbr_to_cbzest créé en statutpendingavecbook_id= id du livre - THEN la réponse HTTP 200 contient le job créé
Scenario: Conversion demandée sur un livre non-CBR
- WHEN l'utilisateur envoie
POST /books/:id/convertsur un livre avecfile_format != 'cbr' - THEN l'API retourne HTTP 409 avec un message d'erreur explicite
Scenario: CBZ déjà présent au même emplacement
- WHEN l'utilisateur envoie
POST /books/:id/convertet qu'un fichier{stem}.cbzexiste déjà sur le disque - THEN l'API retourne HTTP 409 avec un message indiquant le conflit de fichier
Requirement: Exécution sécurisée de la conversion
L'indexer SHALL exécuter la conversion CBR→CBZ de manière sécurisée : le CBR original SHALL être supprimé uniquement après que le CBZ a été créé, vérifié, et que la base de données a été mise à jour. En cas d'échec à n'importe quelle étape, le CBR SHALL rester intact et le job SHALL passer en statut failed.
Scenario: Conversion réussie
- WHEN l'indexer traite un job
cbr_to_cbz - THEN il extrait les images du CBR vers un dossier temporaire
- THEN il crée
{stem}.cbz.tmpdans le même dossier que le CBR - THEN il vérifie que le CBZ contient le même nombre d'images que le CBR original
- THEN il renomme
{stem}.cbz.tmp→{stem}.cbz - THEN il met à jour
books.file_pathetbooks.file_format = 'cbz'en DB - THEN il supprime le fichier CBR original
- THEN le job passe en statut
success
Scenario: Échec pendant la création du CBZ
- WHEN une erreur survient avant la mise à jour DB (extraction, pack, vérification)
- THEN le fichier
.cbz.tmpest supprimé si présent - THEN le CBR original reste intact
- THEN le job passe en statut
failedavec un message d'erreur
Scenario: Échec de la suppression du CBR après conversion réussie
- WHEN la suppression du CBR échoue après que le CBZ est valide et la DB mise à jour
- THEN le job passe quand même en statut
success - THEN l'erreur de suppression est loguée en avertissement
Requirement: Vérification du CBZ généré
Le système SHALL vérifier l'intégrité du CBZ créé avant de modifier la base de données. La vérification SHALL confirmer que le nombre d'images dans le CBZ est égal au nombre d'images dans le CBR source.
Scenario: CBZ valide avec le bon nombre d'images
- WHEN le CBZ est créé avec N images
- THEN l'ouverture du ZIP et le décompte des entrées image retourne N
- THEN la vérification passe et la conversion continue
Scenario: CBZ invalide (décompte incorrect)
- WHEN le CBZ créé contient un nombre d'images différent du CBR source
- THEN la vérification échoue
- THEN le fichier
.cbz.tmpest supprimé - THEN le job échoue avec une erreur de vérification
Requirement: Mise à jour de la base de données après conversion
L'indexer SHALL mettre à jour le livre en base de données après une conversion réussie : file_path SHALL être mis à jour (.cbr → .cbz), file_format SHALL être mis à jour à 'cbz'.
Scenario: Mise à jour DB réussie
- WHEN le CBZ est vérifié et renommé
- THEN
books.file_pathest mis à jour pour pointer vers le nouveau fichier.cbz - THEN
books.file_formatest mis à jour à'cbz' - THEN
books.updated_atest mis à jour
Requirement: Bouton de conversion dans le backoffice
Le backoffice SHALL afficher un bouton "Convert to CBZ" sur la page détail d'un livre, visible uniquement si book.file_format === 'cbr'. Le clic SHALL appeler POST /books/:id/convert et SHALL afficher un feedback (succès ou erreur).
Scenario: Affichage du bouton sur un livre CBR
- WHEN l'utilisateur consulte la page détail d'un livre avec
file_format = 'cbr' - THEN le bouton "Convert to CBZ" est visible
Scenario: Bouton absent sur un livre non-CBR
- WHEN l'utilisateur consulte la page détail d'un livre avec
file_format != 'cbr' - THEN aucun bouton de conversion n'est affiché
Scenario: Conversion lancée depuis le bouton
- WHEN l'utilisateur clique sur "Convert to CBZ"
- THEN l'API est appelée et un job est créé
- THEN un message de confirmation avec le lien vers le job est affiché