La navigation client-side (via Link) servait des pages cachées,
empêchant les recherches de fonctionner sans Ctrl+R.
staleTimes.dynamic: 0 force Next.js à toujours re-fetcher les pages
dynamiques lors de la navigation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ajoute les événements TorrentImportCompleted et TorrentImportFailed
au système de notifications. Une notif Telegram est envoyée après
l'import des fichiers dans la bibliothèque (succès ou erreur),
avec le nom de la série, la bibliothèque et le nombre de fichiers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
qBittorrent ne suit pas les redirections 301 des URLs proxy Prowlarr.
L'API résout maintenant les redirections elle-même : si l'URL mène à un
magnet on le passe directement, si c'est un .torrent on l'uploade en
multipart. Ajoute aussi des logs sur tous les points d'échec du endpoint
/qbittorrent/add et un User-Agent "Stripstream-Librarian" sur les
appels Prowlarr.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
La recherche utilise désormais le endpoint paginé /books avec un filtre
ILIKE sur title/series/author, ce qui permet la pagination des résultats.
Les series_hits sont toujours récupérés en parallèle via searchBooks.
Corrige aussi le remount du LiveSearchForm lors de la navigation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Supprime les entrées available_downloads dont le series_name ne
correspond plus à aucune série existante dans books, au début de
chaque job de détection de téléchargements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Le tri par date d'ajout utilisait updated_at qui est écrasé à chaque
rescan de l'indexer, empêchant les livres/séries récemment ajoutés
de remonter en premier. Utilise maintenant created_at qui reflète
la vraie date d'ajout.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Modale Prowlarr (page série) : remplacé le bouton qBittorrent brut
par QbittorrentDownloadButton avec suivi managé (libraryId,
seriesName, expectedVolumes) et bouton "télécharger et remplacer".
- Ajout de alwaysShowReplace pour la modale Prowlarr (toujours montrer
le bouton remplacer) vs la page downloads (seulement si allVolumes >
expectedVolumes).
- Fix parseur : les tags de version entre crochets [V2], [V3] ne sont
plus extraits comme volumes (le préfixe "v" est ignoré après "[").
- Progression qBittorrent : utilise directement le champ progress
(completed et amount_left sont non-fiables sur qBittorrent 4.3.2).
- Référence import : ne plus exclure les volumes attendus de la
recherche de référence (corrige le mauvais dossier/nommage quand
tous les volumes sont dans expected_volumes).
- allVolumes ajouté à ProwlarrRelease (backend + frontend).
- flex-wrap sur les pastilles volumes dans la modale Prowlarr.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
Le bouton revient à son état initial après l'icône verte de
confirmation, permettant de relancer un téléchargement si besoin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
L'ancienne stratégie diff avant/après échouait quand plusieurs
torrents étaient ajoutés en parallèle (le diff voyait N nouveaux
torrents et ne pouvait pas les distinguer). Les tags et savepath
ne sont pas appliqués sur qBittorrent 4.x en url-encoded.
Nouvelle approche : chaque download managé crée une catégorie
`sl-{uuid}` dans qBittorrent, puis résout le hash en filtrant
par catégorie. Le poller retente aussi la résolution par catégorie
pour les torrents avec qb_hash NULL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
La section "available downloads" n'était jamais mise à jour après le
chargement initial car seuls les torrent downloads étaient rafraîchis.
Stocke latestFound en state React et le rafraîchit en parallèle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nouvelle table available_downloads (library_id, series_name) unique
comme source de vérité pour les téléchargements disponibles
- Les jobs de détection font UPSERT (ajout/mise à jour) et DELETE
(séries complètes ou sans résultat)
- Après import, mise à jour ciblée : retire les volumes importés des
releases, supprime l'entrée si plus de releases
- Migration avec import des données existantes depuis detection_results
- Endpoint latest-found simplifié : une seule query sur la table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Essaie INDEXER_BASE_URL, puis indexer:7081 (Docker), puis
localhost:7081 (dev local) avec timeout 2s par tentative.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Endpoint GET /version sur l'indexer (sans auth)
- Le backoffice fetch la version indexer directement (INDEXER_BASE_URL)
- Grille 3 colonnes avec les 3 versions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Endpoint GET /version (sans auth) retournant la version API
- Bloc About dans l'onglet General : nom du projet, description,
versions API et Backoffice, lien GitHub
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remplace les 5 CTEs + double query (données + count) par une seule
requête avec COUNT(*) OVER() pour le total
- Calcule book_count et series_count directement depuis UNNEST, sans
re-JOIN sur les tables
- Ajoute des index GIN sur books.authors et series_metadata.authors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Serveur : envoie toujours les données (plus de skip si identiques),
ajoute un heartbeat toutes les 15s pour garder la connexion vivante
- Client : détecte les connexions mortes (timeout 30s sans message)
et reconnecte automatiquement, reconnexion plus rapide (3s vs 5s)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Le QbittorrentProvider expose un callback onDownloadStarted qui est
appelé quand un téléchargement est lancé avec succès. Sur la page
downloads, ce callback déclenche un refresh de la liste.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Les metadata providers sont récupérés côté serveur et les providers
sans API key sont passés en prop initialHiddenProviders, supprimant
le fetch client useEffect qui causait un layout shift.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toutes les configurations (Prowlarr, qBittorrent, Telegram, Anilist,
Komga, metadata providers, status mappings) sont maintenant récupérées
côté serveur dans page.tsx et passées en props aux cards.
Supprime ~10 fetchs client useEffect au chargement, élimine les
layout shifts et réduit le temps de rendu initial.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Les configs Prowlarr et qBittorrent sont récupérées côté serveur et
passées en props au ProwlarrSearchModal, évitant les deux fetchs
client qui causaient l'apparition tardive du bouton.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>