Adding Torrents and Existing Data FR - Kheopsian/Hydranos GitHub Wiki
S'applique à Hydranos 4.4.
Cette page s'adresse à quiconque met des torrents dans Hydranos : à la main, depuis un script, depuis Sonarr/Radarr/autobrr, depuis une règle RSS, depuis un client IA ou via un dossier surveillé. Elle couvre toutes les façons d'ajouter, les options que chacune respecte, comment ajouter un torrent par-dessus des données déjà présentes sur disque sans les retélécharger, ce qui se passe quand un autre torrent nomme déjà les mêmes fichiers, l'ordre dans lequel un torrent se télécharge, et pourquoi un ajout peut être refusé. Les termes employés ici sont définis sur Concepts & glossaire.
Tous les chemins d'ajout aboutissent à la même fonction : les mêmes règles s'appliquent donc partout. Les magnets font un détour : ils sont vérifiés, enregistrés et résolus en arrière-plan, puis entrent dans le pipeline une fois leurs métadonnées arrivées.
flowchart LR
UI["Onglet d'ajout : envoi ou chemin serveur"] --> SF
REST["REST : POST /api/torrents/upload, POST /api/torrents (chemin ou URL)"] --> SF
QB["Shim qBit : POST /api/v2/torrents/add"] --> SF
RSS["Règle RSS ou Téléchargement de l'onglet RSS"] --> SF
SF["Option sous-dossier : un torrent mono-fichier<br/>reçoit un dossier à son nom"] --> P
MCP["Outil MCP add_torrent"] --> P
WF["Dossier surveillé : fichier .torrent"] --> P
NF["Rapatriement depuis un nœud : bring it here"] --> P
IMP["Assistant d'import"] --> P
MIN["Magnet depuis l'onglet d'ajout, REST, shim, RSS, MCP ou un fichier .magnet"] --> MQ{"Lien valide, chemin de sauvegarde connu,<br/>absent du moteur cible ?"}
MQ -- non --> MR["Refusé immédiatement"]
MQ -- oui --> MS["Enregistré, résolu en arrière-plan (BEP 9)"]
MS -- "métadonnées arrivées, option sous-dossier du shim appliquée" --> P
P["Analyse du .torrent"] --> PL["Placement : moteur explicite, sinon mode,<br/>sinon mode de la catégorie, sinon race"]
PL --> SP{"Chemin de sauvegarde : explicite, sinon celui de la catégorie"}
SP -- aucun --> R1["Refusé : no save path"]
SP -- trouvé --> EN{"Le moteur existe ?"}
EN -- non --> R0["Refusé : no engine"]
EN -- oui --> RA{"Moteur de rôle race, add_block_enabled<br/>et espace projeté insuffisant ?"}
RA -- oui --> R2["Refusé : race disk full"]
RA -- non --> PC{"Revendication de chemin : un autre torrent<br/>nomme ces fichiers avec d'autres octets ?"}
PC -- "oui, refuse" --> R3["Refusé : écraserait"]
PC -- "oui, isolate" --> ISO["Dossier propre NAME [hash8], retenu en pause,<br/>mode seed abandonné"]
PC -- "non, legacy, ou mode seed<br/>avec toutes les tailles identiques" --> ST["Ligne du store et clé de contenu écrites"]
ISO --> ST
ST --> DD{"[dedup] enabled ?"}
DD -- oui --> DL["Tenter un hardlink du contenu identique déjà détenu"]
DD -- non --> EA
DL --> EA{"Hash déjà dans ce moteur ?"}
EA -- oui --> AA["Refusé : already added"]
EA -- non --> HOLD{"Retenu par la revendication de chemin ?"}
HOLD -- oui --> PR["Preuve de revendication en arrière-plan,<br/>voir Fichiers qu'un autre torrent détient déjà"]
HOLD -- non --> SM{"Mode seed ?"}
SM -- oui --> SEED["Seed, sans vérification des hashs"]
SM -- non --> DOD{"Un fichier présent au chemin de sauvegarde ?"}
DOD -- oui --> RC["Revérification : seed, ou téléchargement des pièces manquantes"]
DOD -- non --> DLD["Téléchargement"]
PR --> WK
SEED --> WK["Les workflows 'quand un torrent est ajouté' se déclenchent<br/>(pas pour l'assistant d'import)"]
RC --> WK
DLD --> WK
Ce que le diagramme signifie en pratique :
- Le placement (quel moteur, quel dossier) est décidé par la catégorie ; la règle complète est sur Catégories & routage. Un
engineexplicite (oumode,raceouhoard, sur les routes natives et l'onglet d'ajout) l'emporte sur la catégorie. Une catégorie inconnue ou vide part vers le moteurracesans chemin de sauvegarde : elle est donc refusée, sauf si vous fournissez explicitement un chemin de sauvegarde. -
Il n'y a pas de chemin de sauvegarde par défaut, à une exception près sur le shim qBit : un dossier qu'un client a réglé avec
save_pathdesetPreferencesest utilisé quand un ajout ne nomme ni chemin de sauvegarde ni catégorie qui en a un (vide tant qu'aucun client ne l'a réglé). - La revendication de chemin (path claim) empêche un nouveau torrent d'écrire dans des fichiers qu'un autre torrent nomme avec d'autres octets ; voir Fichiers qu'un autre torrent détient déjà.
- Le contrôle « déjà ajouté » se fait par moteur. Ajouter un hash qu'un autre moteur détient déjà crée une seconde copie dans le moteur cible. Seuls l'assistant d'import et bring it here (rapatriement depuis un nœud, qui répond 409 this node already has that torrent) vérifient tous les moteurs.
- Les workflows « quand un torrent est ajouté » (when a torrent is added) se déclenchent pour tous les chemins sauf l'assistant d'import (voir Workflows) ; ajouts RSS compris.
| Chemin | Fichiers | Magnets | URL .torrent
|
Catégorie | Chemin de sauvegarde | Tags | Démarrer arrêté | Mode seed | Moteur |
|---|---|---|---|---|---|---|---|---|---|
| Onglet + Ajouter un torrent, envoi | oui, plusieurs (une requête chacun) | — | — | oui | oui | — | oui | oui | Mode (Race / Hoard) |
| Onglet + Ajouter un torrent, Chemin du fichier torrent | un fichier sur le disque du démon | — | — | oui | oui | — | oui | oui | Mode |
| Onglet + Ajouter un torrent, Lien magnet | — | oui | — | oui | oui | — | oui | oui | Mode |
POST /api/torrents/upload (multipart) |
un par requête | — | — | category |
savepath ou save_path
|
tags |
paused ou stopped
|
skip_checking, seed_mode ou skip_recheck
|
engine ou mode (inconnu → 400) |
POST /api/torrents (JSON) |
torrent_path (disque du démon) |
magnet_uri |
torrent_url |
category |
save_path |
tags |
stopped ou paused (bool) |
seed_mode ou skip_recheck (bool) |
engine ou mode (inconnu → 400) |
Shim qBit POST /api/v2/torrents/add
|
torrents, file ou fileselect, plusieurs |
urls |
urls |
category |
savepath |
tags |
paused ou stopped
|
skip_checking |
— |
Outil MCP add_torrent
|
torrent_path |
magnet |
torrent_url |
obligatoire, doit exister | save_path |
tags (tableau) |
paused |
jamais | engine |
| Dossier surveillé | .torrent |
.magnet |
— | celle du dossier (obligatoire) | celui de la catégorie | — | Ajouter arrêté (Add stopped) | jamais | API seulement |
Les champs booléens de formulaire acceptent true ou 1 ; la route JSON veut de vrais booléens JSON. La route d'envoi prend le fichier sous le nom de champ multipart torrent, torrents ou file : les trois fonctionnent (avec plusieurs parties fichier, seule la dernière est ajoutée). mode (race ou hoard, casse indifférente) choisit le moteur de ce rôle, en priorité celui qui porte le nom du rôle ; engine l'emporte quand les deux sont envoyés. Les règles RSS et le bouton Téléchargement (Download) de l'onglet RSS ajoutent par le même pipeline, jamais en mode seed : voir RSS et téléchargements automatiques. Toutes les routes REST et du shim exigent la clé API (en-tête X-Api-Key ou paramètre de requête apikey) ou un cookie de session connectée (ce qu'utilisent Sonarr/Radarr via la connexion du shim) ; voir Sécurité & accès. Chaque route et chaque champ sont listés sur API REST ; l'activation et la connexion du point d'accès MCP sont décrites sur Serveur MCP.
Deux autres chemins réutilisent le pipeline : bring it here sur le torrent d'un nœud déclaré (Nœuds & plusieurs machines) et l'assistant d'import (Migrer depuis qBittorrent).
Exemples, avec une instance sur le port 8199 :
# Envoyer un .torrent dans la catégorie "tv", en faisant confiance aux données déjà sur disque
curl -H "X-Api-Key: YOUR_API_KEY" \
-F "[email protected]" -F "category=tv" -F "seed_mode=true" \
http://localhost:8199/api/torrents/upload
# Envoyer vers un moteur supplémentaire, avec un chemin de sauvegarde explicite, arrêté
curl -H "X-Api-Key: YOUR_API_KEY" \
-F "[email protected]" -F "engine=vpn1" \
-F "save_path=/data/vpn1" -F "stopped=true" \
http://localhost:8199/api/torrents/upload
# Ajouter un magnet (répond 202 {"info_hash":...,"status":"resolving"})
curl -H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"magnet_uri":"magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567&tr=https%3A%2F%2Ftracker.example.org%2Fannounce","category":"tv"}' \
http://localhost:8199/api/torrents
# Ajouter depuis l'URL .torrent d'un tracker dans le moteur hoard, arrêté
curl -H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"torrent_url":"https://tracker.example.org/download/123.torrent","mode":"hoard","category":"movies","stopped":true}' \
http://localhost:8199/api/torrentsSous Windows, dans PowerShell, appelez curl.exe (curl tout court est un alias de Invoke-WebRequest dans Windows PowerShell 5.1) et gardez la commande sur une seule ligne ; les chemins Windows fonctionnent après @ :
curl.exe -H "X-Api-Key: YOUR_API_KEY" -F "torrent=@D:\Torrents\Film (2020).torrent" -F "category=movies" -F "seed_mode=true" http://localhost:8199/api/torrents/uploadRéponses :
-
Route d'envoi : 200
{"info_hash","name","engine","mode"}(engineest le moteur où le torrent est allé,modeson rôle) ; 409{"error"}quand ce moteur le détient déjà ; 400{"error"}pour tout autre refus. -
Route JSON : 200
{"info_hash","name","engine","mode"}pour un fichier ou une URL, 202{"info_hash","status":"resolving"}pour un magnet. Un refus porte{"error","targets":[{"agent":"local","error"}]}: 409 quand le moteur le détient déjà et pour les autres refus (disque race plein,path_collision = "refuse"), 404 quandtorrent_pathn'existe pas, 400 pour les mauvaises requêtes listées dans Quand un ajout est refusé (y compris un hash de magnet mal formé, absent ou uniquement v2), 500 seulement pour une panne du store. -
Shim :
Ok.ouFails.comme qBittorrent ; voir Shim qBittorrent & automatisation.
Les URL .torrent (torrent_url natif, shim urls, MCP torrent_url) sont récupérées par un simple GET, par la propre sortie du démon (voir VPN & sortie réseau) : http ou https uniquement (sinon torrent_url must be an http(s) URL), délai de 30 s, 15 MiB au maximum, sans cookies ni en-têtes supplémentaires. L'URL est remplacée par <url> dans le journal et dans l'erreur de la route native, car une URL de tracker contient généralement une passkey.
Quand un torrent est ajouté, Hydranos décide quoi faire du chemin de sauvegarde :
| Situation | Ce qui se passe |
|---|---|
| Mode seed non demandé, aucun fichier du torrent présent | Téléchargement normal. |
| Mode seed non demandé, au moins un fichier présent | Revérification (recheck) en arrière-plan : chaque pièce est hachée ; le torrent finit en seed si toutes les pièces sont valides, ou ne télécharge que ce qui manque. |
Mode seed demandé (skip_checking / seed_mode / skip_recheck, la case Skip the hash check… de l'onglet d'ajout) |
Commence à seeder immédiatement. Rien n'est vérifié : ni l'existence des fichiers, ni leur taille. |
| Un autre torrent nomme certains de ces fichiers avec d'autres octets, ou des fichiers sur disque ont un hardlink ailleurs | Avec path_collision = "isolate" (par défaut) : déplacé dans son propre dossier, retenu en pause le temps de prouver les fichiers de même taille, puis revérifié. refuse : refusé. legacy : revérifié par-dessus. Mode seed sur des fichiers de même taille uniquement : fait confiance, ajouté tout de suite. Fichiers sur disque ayant un hardlink ailleurs et nommés par aucun torrent : retenu sur place jusqu'à preuve (pas en mode seed). Voir Fichiers qu'un autre torrent détient déjà. |
Le comportement par défaut — la revérification — est le plus sûr : ajouter un torrent par-dessus une copie complète des données coûte une lecture des données et aucun téléchargement. Il s'applique aussi à un torrent ajouté arrêté : il est revérifié et reste arrêté, ce qui vous permet de voir ce qui se trouve sur disque avant qu'il ne touche au réseau.
N'utilisez le mode seed que si vous savez que les données sont complètes et exactement au bon chemin, typiquement pour le cross-seed (cross-seed envoie skip_checking=true via le shim) ou pour l'import scripté d'une bibliothèque vérifiée. Si vous vous trompez, le torrent annonce des pièces qu'il ne peut pas servir. En cas de doute, ajoutez sans mode seed, ou lancez plus tard Vérifier à nouveau (Recheck) (menu contextuel, affiché quand la sélection contient un torrent hoard ; ou POST /api/hoard/torrents/<hash>/verify, qui trouve le torrent dans n'importe quel moteur malgré le préfixe /hoard/ et répond {"status":"ok","checking":true,"paused":…}). Chaque revérification est gardée par la revendication de chemin (voir Fichiers qu'un autre torrent détient déjà).
La disposition sur disque, qui doit correspondre exactement pour qu'une revérification ou le mode seed trouve les données :
- torrent multi-fichiers :
<save path>/<torrent name>/<files> - torrent mono-fichier :
<save path>/<file> - torrent mono-fichier avec l'option sous-dossier :
<save path>/<file name without its extension>/<file>
Le nom du torrent et les noms des fichiers sont utilisés exactement comme le .torrent les écrit ; rien n'est renommé ni rapproché approximativement. L'option sous-dossier est Put the payload in its own subfolder sur l'onglet d'ajout, create_subfolder sur les deux routes natives, contentLayout / root_folder sur le shim, avec [daemon] create_torrent_folder (par défaut false) comme valeur par défaut pour tous et pour les ajouts RSS. Elle ne change que les torrents mono-fichier (un torrent multi-fichiers a déjà son dossier). Il n'existe aucun moyen de supprimer le dossier de premier niveau d'un torrent multi-fichiers (le shim refuse contentLayout=NoSubfolder sur un tel torrent). Si votre dossier porte un autre nom (un renommage façon Plex, un autre format d'année), les données ne sont pas trouvées : sans mode seed, le torrent retélécharge tout dans un nouveau dossier au bon nom ; avec le mode seed, il annonce des données qu'il n'a pas. Renommez le dossier au nom du torrent avant l'ajout, ou gardez une copie disposée comme le torrent l'attend.
Exemple sous Windows : vous avez déjà D:\Media\Movies\Film (2020)\Film.2020.mkv et un torrent multi-fichiers nommé Film (2020) contenant Film.2020.mkv. Donnez à la catégorie le Chemin d'enregistrement (Save Path) D:\Media\Movies (le parent, pas le dossier du film) et ajoutez le .torrent avec la ligne PowerShell de Façons d'ajouter ci-dessus. Avec seed_mode=true, il seed immédiatement ; sans, Hydranos lit le fichier en entier une fois pour le vérifier (durée ≈ taille des données ÷ vitesse de lecture du disque), puis seed. Dans les champs de l'interface (chemin de sauvegarde, dossier surveillé, Chemin du fichier torrent (Torrent File Path)), tapez les chemins Windows avec des barres obliques inverses comme d'habitude ; le conseil sur les barres obliques de Windows concerne les chaînes à l'intérieur de default.toml.
Accepté mais ignoré en 4.4 : l'option sous-dossier (
create_subfolder,[daemon] create_torrent_folder) sur un magnet ajouté parPOST /api/torrentsou l'onglet d'ajout, et sur les dossiers surveillés, les ajouts MCP, les magnets RSS, les rapatriements depuis un nœud et l'assistant d'import — ceux-là gardent la disposition simple — envoyez plutôt le.torrent, ou ajoutez le magnet par le shim aveccontentLayout=Subfolder.
Le mode seed sur un magnet est conservé avec la requête et appliqué à l'arrivée des métadonnées (seed_mode / skip_recheck natifs, la case de l'onglet d'ajout, skip_checking du shim). Un .magnet dans un dossier surveillé, un magnet MCP et un magnet RSS ne sont jamais ajoutés en mode seed.
Un torrent télécharge toujours tous ses fichiers. Ce que vous pouvez changer, c'est l'ordre dans lequel les pièces sont récupérées ; Hydranos n'a pas de « ne pas télécharger » (la priorité 0 de qBittorrent), volontairement : un torrent laissé incomplet est un torrent qu'il ne pourra jamais seeder.
- Priorités de fichiers : Normale (Normal), Haute (High), Maximale (Maximum) (1, 6, 7 chez qBittorrent). Une pièce est classée selon la plus haute priorité des fichiers qu'elle couvre ; le rang le plus haut est récupéré en premier.
- Première/dernière pièce d'abord (First/last piece first) : la première et la dernière pièce de chaque fichier passent avant tout le reste, au-dessus de toute priorité (comme dans qBittorrent).
- Téléchargement séquentiel (Sequential download) : au sein d'un même rang, les pièces sont récupérées dans l'ordre de leur index plutôt que les plus rares d'abord. Plusieurs pièces restent en cours à la fois, et la fin de partie (endgame : les 16 dernières pièces, demandées à plus d'un pair) fonctionne comme d'habitude.
- Par défaut : rien de réglé signifie simplement les plus rares d'abord ; rien n'est enregistré pour cela.
-
Conservé : un changement s'applique tout de suite et est écrit dans la base de reprise du moteur (
state.db), il survit donc à un redémarrage et suit le torrent quand il passe dans un autre moteur. Un torrent complet garde et affiche ses réglages ; ils agissent de nouveau si une revérification trouve des pièces manquantes.
Où le régler :
| Où | Quoi |
|---|---|
| Panneau de détail › onglet Contenu (Content) | Colonne Priorité (Priority), un sélecteur par fichier (Normale / Haute / Maximale). La ligne de résumé ajoute séquentiel et première/dernière pièce d'abord quand ils sont réglés. Une ligne venant d'un autre nœud affiche les priorités en lecture seule. Un échec affiche Priorité inchangée : … (Priority not changed: …). |
| Menu contextuel, groupe Torrent | Téléchargement séquentiel et Première/dernière pièce d'abord, cochés quand tous les torrents sélectionnés l'ont activé (lu pour 50 torrents sélectionnés au plus ; une sélection plus grande, par filtre ou distante s'affiche décochée) ; un clic règle l'inverse sur toute la sélection. Il n'y a pas de priorité de fichier groupée. |
GET / POST /api/torrents/<hash>/download-order
|
GET répond {"info_hash","copies":[{"engine","sequential","first_last_piece","file_priorities","complete"}]}. POST prend n'importe lesquels de sequential, first_last_piece, et file_ids (indices venant de GET /api/torrents/<hash>/files, champ index) accompagné de priority. S'applique à toutes les copies locales sauf si ?engine= en nomme une. Priorité 0 → 409 (Hydranos always downloads the whole torrent…) ; tout autre corps invalide → 400 qui dit pourquoi ; hash inconnu → 404. |
Action de sélection download_order
|
{"sequential","first_last_piece"} (au moins un) ; voir API REST. |
| Shim qBit |
torrents/filePrio (1, 6, 7 ; 0 → 409), torrents/toggleSequentialDownload, torrents/toggleFirstLastPiecePrio ; à l'ajout, sequentialDownload et firstLastPiecePrio, conservés avec un magnet jusqu'à l'arrivée de ses métadonnées. Voir Shim qBittorrent & automatisation. |
# Lire le fichier 2 en premier, et récupérer tôt les extrémités de chaque fichier
curl -H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"file_ids":[2],"priority":7,"first_last_piece":true}' \
http://localhost:8199/api/torrents/<hash>/download-orderNon implémenté en 4.4 : un réglage d'ordre de téléchargement au moment de l'ajout sur l'onglet d'ajout,
POST /api/torrents, la route d'envoi, MCP ou un dossier surveillé — seul le shim en lit un — réglez-le juste après l'ajout (menu contextuel oudownload-order), ou ajoutez par le shim.
L'onglet intitulé + Ajouter un torrent (+ Add Torrent) (titre Ajouter un torrent (Add Torrent)) comporte ces champs :
| Champ | Ce qu'il fait réellement |
|---|---|
| Catégorie (Category) (avec + Nouveau (+ New)) | Envoyée avec l'ajout. En choisir une remplace Chemin d'enregistrement par le chemin de la catégorie (vide si elle n'en a pas) et bascule Mode sur le mode de la catégorie. La première entrée est - none -. |
| Chemin du fichier torrent (Torrent File Path) | Chemin d'un .torrent sur la machine qui exécute Hydranos (sous Docker : dans le conteneur), pas sur votre ordinateur. Sur une installation Windows, un chemin normal comme D:\Torrents\release.torrent fonctionne. |
| Ou envoyer un .torrent (Or Upload .torrent) | Un ou plusieurs fichiers depuis votre ordinateur, envoyés une requête chacun. Prioritaire sur les champs chemin et magnet. |
| Prévisualiser le contenu avant d'ajouter (Preview contents before adding) | Lit les fichiers sélectionnés dans votre navigateur et les affiche dans la colonne Contenu (Contents). Rien n'est envoyé. |
| Lien magnet (Magnet link) | Utilisé seulement si aucun fichier n'est sélectionné et que Chemin du fichier torrent est vide. |
| Avancé : forcer le mode et le chemin (Advanced, override mode & save path) › Chemin d'enregistrement (Save Path) | Envoyé comme chemin de sauvegarde ; remplace celui de la catégorie. Ce qu'affiche le champ est ce qui est envoyé. |
| Mode (Race / Hoard) | Envoyé avec chaque ajout (mode) ; choisit le moteur de ce rôle, en priorité celui nommé race ou hoard. Commence sur Race ; il suit la catégorie choisie, et l'emporte sur elle si vous le changez ensuite. |
| Put the payload in its own subfolder |
create_subfolder : un torrent mono-fichier va dans <save path>/<file name without extension>/. Pré-cochée d'après [daemon] create_torrent_folder (lu par GET /api/torrents/add-defaults ; si cette lecture échoue, rien n'est envoyé et le réglage du démon s'applique). Non appliquée à un Lien magnet. |
| Skip the hash check, the data is already on disk | Mode seed, pour un envoi, un chemin ou un magnet. Décochée au départ. |
| Add without starting | Ajouté arrêté, pour un envoi, un chemin ou un magnet. Un ajout arrêté par-dessus des données existantes est quand même revérifié. |
La ligne de succès affiche Added <name> → <mode>[ · <category>], avec le rôle du moteur où le torrent est allé. Une erreur est affichée telle que le serveur l'a envoyée.
L'onglet n'a ni champ tags ni champ d'URL .torrent (une URL tapée dans Chemin du fichier torrent est lue comme un chemin et refusée avec no such file ; utilisez torrent_url sur POST /api/torrents, le shim ou MCP), et le moteur ne se choisit que par rôle. Avec - none - et un Chemin d'enregistrement vide, l'ajout est refusé (no save path).
Bug connu en 4.4 : revenir à
- none -dans Catégorie semble réinitialiser le formulaire — Chemin d'enregistrement et Mode gardent les valeurs de la catégorie précédente et sont envoyés — videz Chemin d'enregistrement et choisissez le mode à la main.
Bug connu en 4.4 : deux textes d'aide sous les cases ne décrivent pas le code — Put the payload in its own subfolder dit qu'elle s'applique « on the hoard agent » (elle s'applique à tout moteur), et Skip the hash check… dit que l'ajout est refusé quand un fichier manque ou n'a pas la bonne taille (rien n'est vérifié, le torrent annonce ce qu'il n'a pas) — fiez-vous à cette page.
Un magnet est accepté en quelques secondes et résolu en arrière-plan :
-
Vérifié immédiatement. Refusé tout de suite si le lien ne s'analyse pas, si aucun chemin de sauvegarde n'est trouvé, ou si le moteur cible a déjà le hash. Un
engine(oumode) qui n'existe pas est refusé (400) parPOST /api/torrents; depuis un magnet MCP, il est ignoré et le magnet va au moteur de la catégorie. Un dossier surveillé ne peut pas être enregistré avec unengineinconnu (PUT /api/watchrépond 400no engine "x") ; seul un moteur supprimé après l'enregistrement du dossier se rabat sur la catégorie. Les liens doivent avoir un info hash v1 (xt=urn:btih:, 40 hex ou 32 base32). Un magnet uniquement v2 (urn:btmh:seulement) est refusé avec add the .torrent file instead ; un magnet hybride convient.tr(y compris les numérotéstr.1…),dnetx.pesont utilisés. - Enregistré. La requête (catégorie, chemin de sauvegarde, tags, indicateur arrêté, mode seed, moteur, et les options d'ajout du shim : limites de débit, ordre de téléchargement, disposition du contenu) est écrite dans le store et survit à un redémarrage.
-
Résolu. Les pairs viennent des trackers du magnet, de
x.peet de la DHT ; les métadonnées sont récupérées via BEP 9 et leur hash doit être égal à l'info hash. Le moteur doit être sur le réseau ; s'il ne l'est pas et que la requête a plus de 600 s (comptées depuis sa création, pas depuis le dernier redémarrage ni le dernier Réessayer (Retry)), la requête échoue. -
Réessayé. Jusqu'à 4 tentatives, avec des attentes de 0, 1, 5 puis 15 minutes ; après le quatrième échec, la requête est marquée
failedavec le motif. -
Ajouté. Le
.torrentest reconstruit (dictionnaire info octet pour octet, un palier (tier) de tracker partr) et passe par le pipeline ci-dessus, en mode seed si la requête l'a demandé, avec les options du shim appliquées. UncontentLayout=NoSubfolderdu shim sur ce qui s'avère être un torrent multi-fichiers fait échouer la requête (contentLayout NoSubfolder on a multi-file torrent is not supported). Si le pipeline le refuse, la requête est aussitôt marquéefailed(sans nouvelle tentative) ; si le moteur le détient déjà, la requête est abandonnée sans bruit.
stateDiagram-v2
state "Refusé immédiatement" as Refused
state "resolving : récupération des métadonnées" as Fetching
state "en attente de nouvelle tentative" as Waiting
state "failed" as Failed
state "Ajouté via le pipeline d'ajout" as Added
state "Requête abandonnée, déjà dans le moteur" as Dropped
[*] --> Refused: lien invalide, pas de chemin, déjà présent
[*] --> Fetching: écrit dans le store, résolution lancée
Fetching --> Added: métadonnées conformes à l'info hash, ajout accepté
Fetching --> Dropped: l'ajout répond déjà ajouté
Fetching --> Waiting: pas de métadonnées, ou non conformes
Waiting --> Fetching: après 1, 5 puis 15 min
Fetching --> Failed: 4e tentative échouée, NoSubfolder sur un torrent multi-fichiers, ou ajout refusé
Fetching --> Failed: moteur hors réseau, requête de plus de 600 s
Failed --> Fetching: Réessayer, tentatives remises à 0
Failed --> [*]: Supprimer
Waiting --> [*]: Supprimer
Fetching --> [*]: Supprimer
Added --> [*]
Dropped --> [*]
Refused --> [*]
Sur l'onglet d'ajout, la carte Magnets (masquée quand elle est vide) liste les requêtes en attente avec Nom (Name), Engine et État (State) (fetching metadata..., waiting to retry (N min), failed: …), un bouton Réessayer (Retry) sur celles en échec et Supprimer (Remove). La même chose via l'API :
curl -H "X-Api-Key: YOUR_API_KEY" http://localhost:8199/api/magnets
curl -X POST -H "X-Api-Key: YOUR_API_KEY" http://localhost:8199/api/magnets/<hash>/retry
curl -X DELETE -H "X-Api-Key: YOUR_API_KEY" http://localhost:8199/api/magnets/<hash>Réessayer repart de la première tentative (la limite de 600 s hors réseau n'est pas réinitialisée).
Onglet Config › Dossiers surveillés (Watched folders) : chaque ligne contient Dossier (Folder), Catégorie (Category), Ajouter arrêté (Add stopped), Actif (On) et Statut (Status) ; + Dossier (+ Folder) ajoute une ligne et Enregistrer (Save) remplace toute la liste (PUT /api/watch).
-
La catégorie est obligatoire et doit exister au moment de l'enregistrement ; elle décide du moteur et du chemin de sauvegarde. Le dossier doit être un chemin absolu vers un répertoire visible par le démon (Linux/macOS : commence par
/; Windows :X:\…,C:/…ou un partage UNC\\server\share\watch). -
Analysé toutes les 10 secondes, premier niveau seulement (pas de sous-dossiers), fichiers se terminant par
.torrentou.magnet(casse indifférente). Un fichier est pris en compte dès que sa taille et sa date de modification n'ont pas changé entre deux analyses : comptez 10 à 20 s de latence. Les fichiers de plus de 64 MiB sont refusés. - Chaque dossier est analysé à part, si bien qu'un partage réseau qui ne répond plus ne bloque que sa propre ligne : au bout de 60 s sans réponse, cette ligne affiche une erreur (
no answer from this folder for 60 s …), et les autres dossiers continuent. - Un fichier
.magnetcontient le lien sur sa première ligne non vide. -
Résultat : un fichier ajouté, ou déjà présent dans le moteur, est déplacé dans
<folder>/added/(les conflits de nom reçoivent(2),(3)…). Un fichier refusé est renommé<name>.invalid, avec à côté<name>.invalid.txtqui donne le motif. Rien n'est supprimé. Pour un.magnet, « ajouté » signifie que la requête a été acceptée ; la résolution suit comme dans Magnets. - Jamais en mode seed : les données existantes sont toujours revérifiées. Pas de tags, pas d'option sous-dossier.
-
Statut affiche
vus N · ajoutés N · refusés N(seen, added, refused) et le dernier refus : vus est le nombre de fichiers.torrentet.magnetque la dernière analyse a trouvés dans le dossier. Un dossier pas encore analysé depuis le démarrage affichepas encore scanné(not scanned yet). Ces compteurs sont gardés en mémoire et remis à zéro au redémarrage. - L'API accepte aussi un
enginepar dossier. L'interface ne l'affiche pas, mais le conserve quand vous enregistrez la liste depuis l'onglet Config.
Sous Docker, le dossier est un chemin à l'intérieur du conteneur : montez-le. Sous Windows, tapez-le sous la forme D:\Watch\movies (ou \\server\share\watch) dans le champ Dossier.
Un dossier sur un partage réseau, sous Docker. Si le partage est monté sur l'hôte après le démarrage du conteneur, le conteneur voit toujours le point de montage vide qui est dessous : le dossier se lit sans erreur et rien n'est jamais pris. Le statut le montre : vus 0 alors que des fichiers y sont déposés. Montez le parent du point de montage avec la propagation rslave (- /mnt/remotes:/remotes:rslave, dossier /remotes/share/watch) pour qu'un montage ultérieur sur l'hôte atteigne le conteneur, ou redémarrez le conteneur une fois le partage monté.
flowchart TD
S["Toutes les 10 s : chaque dossier actif, premier niveau seulement"] --> F{"Nom se terminant par .torrent ou .magnet ?"}
F -- non --> IGN["Ignoré"]
F -- oui --> ST{"Même taille et même mtime<br/>qu'à l'analyse précédente ?"}
ST -- non --> WAIT["Mémorisé, examiné à l'analyse suivante"]
ST -- oui --> BIG{"Plus de 64 MiB ?"}
BIG -- oui --> INV["Renommé NAME.invalid,<br/>motif dans NAME.invalid.txt"]
BIG -- non --> K{"Un fichier .magnet ?"}
K -- oui --> MAG["Requête magnet, première ligne non vide,<br/>catégorie du dossier"]
K -- non --> ADD["Pipeline d'ajout, catégorie du dossier,<br/>jamais en mode seed"]
MAG --> R{"Accepté, ou déjà ajouté ?"}
ADD --> R
R -- oui --> OK["Déplacé dans FOLDER/added/"]
R -- non --> INV
Si vous ajoutez un torrent dont vous détenez déjà le contenu sous un autre torrent (même contenu, info hash différent : un ré-upload sur un autre tracker, une release renommée), Hydranos crée des hardlinks des fichiers existants sous les noms du nouveau torrent avant que le moteur n'examine le chemin de sauvegarde. Rien n'est retéléchargé.
-
Activé par défaut :
[dedup] enabled = trues'applique même quand la section est absente (ledefault.tomllivré n'en a pas). - Correspondance = les hashs de pièces des torrents sont identiques octet pour octet et les tailles de fichiers correspondent une à une. Pas de correspondance partielle. Les torrents uniquement v2 ne correspondent jamais.
- Chaque fichier source doit exister avec la bonne taille ; aucun fichier de destination ne doit déjà exister (la dédup n'écrase donc jamais rien, et un ajout par-dessus des données déjà présentes au chemin de sauvegarde suit simplement la voie de la revérification) ; source et destination doivent être sur le même système de fichiers tel que le démon le voit (même identifiant de périphérique sous Linux/macOS, même numéro de série de volume sous Windows : deux dossiers sur un même disque NTFS conviennent).
- Tout échec est silencieux et sans conséquence : les liens créés sont supprimés et le torrent se télécharge normalement.
Docker, Sonarr et Radarr. Hydranos vérifie l'identifiant de périphérique, puis appelle link() du noyau. Linux refuse un hardlink entre deux points de montage différents (erreur EXDEV) même s'il s'agit du même disque : deux bind mounts distincts (/mnt/user/downloads:/data/downloads et /mnt/user/media:/data/media) font donc échouer tous les liens de dédup, et le torrent est téléchargé à la place. Montez le parent commun une seule fois (par exemple /mnt/user/data:/data) et placez dessous le chemin de sauvegarde de chaque catégorie. Les imports par hardlink de Sonarr et Radarr suivent la même règle du noyau dans leur propre conteneur : donnez-leur le même montage parent unique, au même chemin dans le conteneur que dans Hydranos, pour que le chemin de sauvegarde que Hydranos indique via le shim soit un chemin qu'ils peuvent ouvrir. Hydranos lui-même ne crée jamais de lien dans votre bibliothèque ; cet import est une étape propre à Sonarr ou Radarr (voir Shim qBittorrent & automatisation et Docker).
- Le torrent lié est quand même revérifié (le mode seed n'est pas implicite), il lit donc les données une fois avant de seeder. Le texte de la carte disant qu'il « seed immédiatement » est optimiste.
Onglet Config › Duplicate data › On adding a torrent we already hold : case Link it instead of downloading, bouton Enregistrer et redémarrer (Save and restart). Le réglage est écrit dans default.toml et appliqué immédiatement ; le bouton redémarre quand même Hydranos (voir Exploiter Hydranos pour ce que fait un redémarrage depuis l'interface). La carte affiche aussi le nombre de groupes de contenu identique. API : POST /api/dedup/config {"enabled": false}, GET /api/dedup/stats. La clé est listée sur Config : démon, auth & global.
Deux torrents différents peuvent nommer le même fichier : un ré-upload qui a gardé le nom de la release, un REPACK qui n'a pas été renommé, le même titre encodé deux fois. Avant la 4.4, le second trouvait des fichiers à ses chemins, les revérifiait, téléchargeait les pièces différentes et les écrivait par-dessus le fichier du premier torrent, qui continuait à seeder un mélange. Depuis la 4.4, la revendication de chemin (path claim) contrôle chaque ajout, après l'admission race et avant que quoi que ce soit ne soit écrit, contre les torrents de tous les moteurs qui nomment les mêmes chemins (ses propres copies dans d'autres moteurs exclues). Par fichier :
- personne d'autre ne nomme le chemin : rien à faire ;
- un autre torrent le nomme avec les mêmes pièces et la même liste de fichiers (cross-seed des mêmes octets) : partagé, comme toujours ;
- un autre torrent le nomme avec une autre taille : un conflit, le fichier ne peut pas être les deux ;
- un autre torrent le nomme avec la même taille : non prouvé, car même taille ne veut pas dire mêmes octets ; il est haché avant tout partage.
flowchart TD
A["Ajout après l'admission race :<br/>les fichiers de ce torrent à son chemin de sauvegarde"] --> C{"Un autre torrent, dans un moteur quelconque, nomme un de ces chemins,<br/>pas avec les mêmes pièces et la même liste de fichiers ?"}
C -- non --> F{"Fichiers présents sur disque, nommés par aucun torrent,<br/>avec un nombre de hardlinks supérieur à 1 ?"}
F -- "non, ou mode seed" --> GO["Ajouté là où il l'a demandé"]
F -- oui --> HP["Ajouté en pause là où il l'a demandé"]
HP --> PV{"Chacun de ces fichiers est valide<br/>contre les pièces de ce torrent ?"}
PV -- oui --> RS["Revérification ; démarré sauf si l'ajout le voulait arrêté ;<br/>ce qui manque se télécharge"]
PV -- non --> ER["Reste en pause en erreur, rien d'écrit"]
C -- oui --> SZ{"Mode seed, et chaque chemin partagé<br/>à la taille attendue par ce torrent ?"}
SZ -- oui --> GO
SZ -- non --> M{"[dedup] path_collision"}
M -- legacy --> LG["Ajouté là où il l'a demandé : la revérification peut écraser,<br/>signalé comme partagé"]
M -- refuse --> RF["Refusé : les écraserait"]
M -- isolate --> IS["Ajouté en pause dans SAVE/TOP [hash8],<br/>mode seed abandonné"]
IS --> PI["Fichiers de même taille hachés contre ses pièces,<br/>ceux qui sont valides liés en hardlink"]
PI --> RS
[dedup] path_collision tranche le cas de conflit :
| Valeur | Ce qui se passe |
|---|---|
isolate (par défaut) |
Le torrent reçoit son propre dossier à côté de celui qu'il demandait : <save path>/<first component of its name> [<first 8 hex digits of its info hash>], par exemple /data/tv/Show.S01 [1a2b3c4d]. Les fichiers de même taille dont le hash correspond à ses pièces y sont liés en hardlink, de sorte que seuls les fichiers réellement différents sont téléchargés. Le mode seed est abandonné (le nouveau dossier commence vide). Le torrent indique ce dossier comme son chemin de sauvegarde, aux clients du shim aussi. |
refuse |
L'ajout est refusé : N file(s) of this torrent are already another torrent's with other bytes (path, path, path, ...); adding it there would overwrite them. |
legacy |
Le comportement d'avant la 4.4 : chemin partagé, la revérification écrase ce qui diffère. Journalisé et signalé à chaque fois. |
La clé n'est pas dans le default.toml livré et la carte Duplicate data n'écrit que enabled : ajoutez path_collision = "refuse" (ou "legacy") sous [dedup] à la main et redémarrez.
- Le mode seed (
skip_checking, tel que cross-seed l'envoie) par-dessus des fichiers de même taille d'un autre torrent est pris pour argent comptant : l'ajout se fait là où il le demandait, avec une ligne de journal info (path claim: skip_checking over files another torrent holds at the same size), pas une anomalie. Un conflit de taille est isolé, refusé ou laissé passer selon le réglage, même en mode seed. -
Hardlinks de bibliothèque. Les fichiers déjà au chemin qu'aucun torrent ne nomme mais qui ont un autre hardlink (typiquement un import Sonarr/Radarr) sont prouvés avant que quoi que ce soit puisse y écrire : le torrent est ajouté en pause, ces fichiers sont hachés, et il n'est libéré que s'ils sont tous valides. Sinon il reste en pause en erreur avec
N file(s) on disk differ from this torrent and are hardlinked elsewhere; held paused rather than overwrite them. Pas fait en mode seed. - La preuve tourne en arrière-plan (thread
pathclaim-proof) ; l'ajout répond tout de suite. Un redémarrage au milieu d'une isolation laisse au pire un torrent en pause avec un dossier vide (ou ne contenant que des fichiers déjà prouvés identiques), qui se télécharge quand on le démarre ; lancez d'abord Vérifier à nouveau (Recheck) pour que les fichiers déjà liés soient comptés. Un torrent retenu sur place (hardlinks de bibliothèque), ou arrêté par une revérification gardée, reste en pause et n'est pas prouvé de nouveau après un redémarrage : Démarrer (Start) le prouve d'abord, comme un ajout (le torrent reste en pause pendant que ces fichiers sont hachés et ne démarre que s'ils sont tous valides ; un torrent complet démarre tout de suite), et Vérifier à nouveau aussi. - Deux ajouts nommant le même dossier au même moment (la même release prise sur deux trackers) sont contrôlés l'un après l'autre ; un ajout attend au plus 30 s, puis passe avec un WARN
path claim: waited too long on another add, going ahead. - Sous Windows, les chemins sont comparés sans tenir compte de la casse.
-
Les revérifications sont gardées, quoi que dise
path_collision: Vérifier à nouveau dans l'interface,POST /api/hoard/torrents/<hash>/verify, les revérifications groupées et MCP, ettorrents/recheckdu shim arrêtent un torrent dont un autre torrent nomme les fichiers avec d'autres octets, hachent ces fichiers, et ne le revérifient (en le redémarrant s'il tournait) que s'ils sont tous valides. Sinon il reste en pause en erreur avec le message hardlinked elsewhere ci-dessus, même si l'autre nom est le fichier d'un torrent. -
Où le voir : chaque événement
isolated,refused,shared(legacy),heldetprovenest une ligne de journal WARNpath collision: …et est gardé en mémoire (les 500 derniers, perdus au redémarrage) pour le typepath_collisiondeGET /api/health/anomalies(voir Supervision & journaux). Il n'y a pas d'analyse périodique des torrents existants : seuls les ajouts, les revérifications et Démarrer sont contrôlés.
| Message (abrégé) | Cause | Solution |
|---|---|---|
no save path: category "x" is unknown and no savepath was given |
Pas de chemin de sauvegarde explicite, et la catégorie est inconnue, vide, ou a un chemin de sauvegarde vide (par exemple une catégorie créée via createCategory du shim sans savePath). |
Créez la catégorie avec un chemin de sauvegarde (Catégories & routage) ou envoyez un chemin de sauvegarde. |
no save path: give one, or a category that has one |
L'option sous-dossier sur un torrent mono-fichier, sans chemin de sauvegarde où placer le dossier. | Comme ci-dessus. |
no engine … / no engine named … on this node
|
Le moteur cible n'existe pas. Les deux routes natives refusent un engine inconnu (400), magnets compris ; les magnets MCP se rabattent sur la catégorie ; un dossier surveillé refuse un engine inconnu à l'enregistrement (400), et ne se rabat que si ce moteur a été supprimé ensuite. |
Vérifiez l'identifiant de moteur dans l'onglet Nodes. |
mode must be race or hoard, not "x" / no engine has the hoard role
|
mode n'est ni race ni hoard, ou aucun moteur ne porte ce rôle. |
Envoyez race ou hoard, ou nommez l'engine. |
give exactly one of torrent_path, torrent_url or magnet_uri |
POST /api/torrents n'en a reçu aucun ou plusieurs. |
Envoyez-en un seul. |
<path>: no such file (404) |
torrent_path n'existe pas sur le disque du démon (une URL tapée comme chemin finit ici aussi). |
Donnez un chemin que le démon voit, ou utilisez torrent_url. |
torrent_url must be an http(s) URL / <url> answered 404 …
|
L'URL .torrent n'est pas en http(s), ou la récupération a échoué. |
Vérifiez le lien et sa passkey. |
race disk full: … GB free of disk, … GB already promised … |
Admission race : uniquement pour un moteur de rôle race, uniquement quand [race_drain] add_block_enabled = true (par défaut false). L'espace libre (du quota race quand il y en a un : of N.N TB quota), moins ce que les téléchargements acceptés doivent encore écrire, moins reserve_free_gb (par défaut 0), est inférieur à la taille du torrent. Un volume illisible laisse passer l'ajout. |
Libérez de l'espace, ou voir Drain race & graduation. |
N file(s) of this torrent are already another torrent's with other bytes (…); adding it there would overwrite them |
[dedup] path_collision = "refuse" et un autre torrent nomme ces fichiers avec d'autres octets. |
Choisissez la release, donnez un autre chemin de sauvegarde, ou utilisez isolate. |
torrent already added / already added
|
Ce moteur détient déjà le hash. | Rien à faire. Le shim répond Ok., un dossier surveillé déplace le fichier dans added/, un magnet résolu est abandonné sans bruit ; les routes natives (409) et MCP le signalent comme une erreur. |
torrent file did not parse |
Pas un .torrent valide. |
— |
this magnet has only a v2 info hash (btmh) |
Magnet uniquement v2. | Ajoutez le fichier .torrent. |
contentLayout NoSubfolder on a multi-file torrent is not supported |
Ajout par le shim (ou son magnet, une fois résolu) demandant de supprimer le dossier d'un torrent multi-fichiers. | Utilisez Original ou Subfolder. |
Pour importer d'un coup une bibliothèque qBittorrent ou Transmission existante (catégories, états arrêtés, mode seed pour les torrents complets dont les données sont trouvées), utilisez l'assistant d'import : Config › Paramètres avancés (default.toml) (Advanced settings (default.toml)) › onglet Import › Importer… (Import…) (sous le titre Importer depuis un autre client (Import from another client)). Il est décrit pas à pas sur Migrer depuis qBittorrent.