Skip to content

Workflows FR

Kheopsian edited this page Oct 13, 2026 · 3 revisions

🇬🇧 English · 🇫🇷 Français

Workflows

S'applique à Hydranos 4.4.

Pour tous ceux qui veulent qu'Hydranos agisse sur les torrents sans script : arrêter le seed au bout d'un certain temps, poser des tags, appeler un webhook à la fin d'un téléchargement, ajouter des trackers. Vous verrez ce que fait chaque déclencheur, chaque condition et chaque action, comment tester une règle, et ce qui manque encore en 4.4. Vocabulaire : Concepts & glossaire.

Ce qu'est un workflow

Un workflow a trois parties :

  • un déclencheur (le champ Se lance (Runs)) : à intervalle régulier (on a timer), quand un téléchargement se termine (when a download completes) ou quand un torrent est ajouté (when a torrent is added) ;
  • un arbre de conditions (When) : des comparaisons de champs regroupées en ET / OU / NON ;
  • une liste d'actions (Then), exécutées dans l'ordre sur chaque torrent qui correspond.

Les workflows vivent dans le store (hydra.db), pas dans default.toml. Un workflow enregistré sans "enabled": true est désactivé. Ils agissent sur les torrents des moteurs de cette instance (race, hoard, supplémentaires), jamais sur les lignes fusionnées depuis un nœud déclaré.

flowchart LR
    T1["Minuterie (toutes les interval_secs, min 60)"] --> ALL["Chaque copie de torrent dans chaque moteur local"]
    T2["Un téléchargement se termine"] --> EV["File d'événements (table du store workflow_events)"]
    T3["Un torrent est ajouté"] --> EV
    EV --> ONE["Ce seul torrent"]
    ALL --> WHEN["When : arbre de conditions"]
    ONE --> WHEN
    WHEN -->|"pas de correspondance"| NOP["Rien, rien n'est journalisé"]
    WHEN -->|"correspondance"| DONE{"Chaque action hors webhook<br/>déjà comme demandé ?"}
    DONE -->|"oui, et aucun webhook à envoyer"| SKIP["Ignoré, rien n'est journalisé"]
    DONE -->|"oui, déclencheur d'événement avec webhook"| THEN
    DONE -->|"non"| CAP{"Minuterie : At most atteint<br/>sur ce passage ?"}
    CAP -->|"oui"| STOP["Reste du passage remis à la fois suivante"]
    CAP -->|"non"| THEN["Then : actions restant à faire, dans l'ordre,<br/>webhooks en dernier"]
    THEN --> ACT["Journal Activity : applied ou failed"]
    THEN -.->|"move files to a folder"| JOB["Onglet Jobs : job move_data"]
Loading

Onglet Workflows, bouton + New workflow : Nom (Name), Se lance (Runs), pour les minuteries Runs every (secondes, minimum 60, 900 par défaut) et At most (torrents par passage, 500 par défaut), puis When, Then, et Aperçu (Preview) / Enregistrer (Save) / Annuler (Cancel). Traduits dans toutes les langues : Name, Save, Cancel, l'en-tête Actions de la liste ; en français, également Runs, les choix de déclencheur, Preview, Every (on completion, when added), none of these (NOT), la case hardlink de move files to a folder, les notes d'action et le Remove d'un groupe. Les boutons de la liste, le Remove d'une ligne, all of these (AND) / any of these (OR), ainsi que les libellés de champs, d'opérateurs et d'actions restent en anglais.

Déclencheurs

Se lance (Runs) Valeur transmise Quand il se déclenche Ce qu'il évalue
à intervalle régulier (on a timer) schedule (par défaut) Quand now − last run ≥ interval_secs (plancher de 60 s). La minuterie fait son premier tic environ trois minutes après le démarrage, puis une fois par minute. Les workflows dus s'exécutent tour à tour. Chaque copie de torrent dans chaque moteur local. Au plus cap torrents ayant quelque chose à faire par passage.
quand un téléchargement se termine (when a download completes) completed Une fois par téléchargement, quand sa dernière pièce est vérifiée. Un torrent ajouté avec ses données déjà sur le disque, ou revérifié complet, ne le déclenche jamais. Ce seul torrent.
quand un torrent est ajouté (when a torrent is added) added Une fois par torrent, dès que le moteur le détient. Se déclenche pour les ajouts depuis l'onglet + Ajouter un torrent (+ Add Torrent), l'API REST, le shim qBittorrent (Sonarr, Radarr, autobrr), les magnets une fois résolus, les dossiers surveillés, le serveur MCP, les règles RSS (et le Téléchargement (Download) de l'onglet RSS) et un rapatriement depuis un nœud déclaré. L'assistant d'import et les déplacements de données ne le déclenchent pas. Ce seul torrent.

Les détails qui comptent :

  • Un workflow à minuterie converge : un torrent déjà « comme demandé » (arrêté, tagué…) est ignoré et non journalisé, jusqu'à ce qu'il s'en écarte de nouveau (démarrez à la main un torrent qu'un workflow arrête, et le passage suivant l'arrête de nouveau).
  • La dernière exécution est enregistrée avant le passage, si bien qu'un passage lent n'est jamais lancé deux fois. Un workflow à minuterie nouvellement activé et qui n'a jamais tourné est dû au prochain tic.
  • Les événements sont d'abord écrits dans le store, donc un redémarrage n'en perd aucun. Un événement dont le torrent n'est pas encore chargé attend jusqu'à une heure, puis est abandonné. Les workflows à événement n'ont ni intervalle ni plafond.
  • Sur un déclencheur d'événement, un When vide est autorisé et signifie « chaque téléchargement qui se termine » ou « chaque torrent ajouté ». Pour l'obtenir dans l'éditeur, cliquez sur Remove sur la ligne de condition avec laquelle démarre un nouveau workflow. Sur une minuterie, un When vide est refusé (il correspondrait à tout le catalogue).
  • Les champs de hardlinks (link_count, external_links, freeable_bytes, data_missing) sont refusés sur les déclencheurs d'événement : l'index n'a pas mesuré un torrent qui vient d'arriver.

Conditions

When commence par un groupe racine. Chaque groupe est all of these (AND), any of these (OR) ou aucune de ces conditions (NON) (none of these (NOT)). À l'intérieur, + Condition ajoute une ligne (champ, opérateur, valeur) et + Group ajoute un groupe imbriqué. Remove supprime une ligne ou un groupe (le groupe racine ne peut pas être supprimé). Les groupes vides sont éliminés à l'enregistrement.

aucune de ces conditions (NON) correspond quand aucune de ses lignes n'est vraie ; il est enregistré sous la forme {"kind":"not","of":{"kind":"any","of":[…]}}. Un NOT écrit via l'API s'ouvre comme un groupe aucune de ces conditions (NON) (ce qu'il enveloppe devient l'unique enfant de ce groupe quand ce n'est pas un OU), si bien que l'enregistrer depuis l'éditeur garde son sens.

L'éditeur construit ses listes à partir de GET /api/workflows/fields. Voici tous les champs :

Libellé dans l'interface Champ Type Ce qu'il lit
torrent name / info hash name / info_hash text Nom du métainfo / hash hexadécimal.
category category text La catégorie de cette copie.
tags tags tags Les tags du torrent.
state state text L'état affiché par la liste : seeding, downloading, stopped, queued, checking_files, error.
engine engine text Identifiant de moteur (race, hoard, vpn1…).
save path save_path text Chemin de sauvegarde enregistré pour cette copie.
tracker tracker_host text Hôte (sans schéma ni port) du premier tracker de la liste en cours uniquement.
has a tracker error tracker_error bool La dernière annonce a renvoyé une erreur.
tracker error message tracker_error_msg text Son texte.
has a torrent error torrent_error bool Le moteur marque le torrent en erreur.
stopped by hand user_paused bool Votre intention d'arrêt telle qu'enregistrée, pas l'état momentané du moteur.
has several files multi_file bool Plus d'un fichier.
private private bool Drapeau privé du métainfo. Affiché private, faute de libellé.
progress progress percent Part du contenu détenue : pièces vérifiées, (taille − octets restants) ÷ taille, 0-100. Un torrent vaut 100 pendant qu'il seede ; un torrent dont les pièces ne sont pas encore connues (encore en vérification) vaut 0 — tout comme un torrent arrêté sans carte des pièces (voir le bug connu plus bas). Utilisez completed_age pour dire « complet ».
ratio ratio number Le ratio de la liste : envoyé ÷ téléchargé, ou ÷ données détenues quand moins de 1 % a été téléchargé (un cross-seed). Conservé par tout déplacement (Déplacer vers un dossier… (Set location…), un déplacement de catégorie, move files to a folder, une graduation, un Move to engine ›) ; une copie faite par Duplicate to engine › part de 0 (Jobs).
size / uploaded / downloaded total_size / total_uploaded / total_downloaded size Compteurs du moteur.
upload rate / download rate upload_rate / download_rate size (bytes/s) Débits actuels.
connected peers num_peers number Pairs connectés en ce moment.
seeds the tracker reports num_seeds number Seeders rapportés par le tracker (identique à swarm_seeds), pas des pairs connectés.
seeds in swarm / leechers in swarm swarm_seeds / swarm_leechers number Seeders / leechers rapportés par le tracker.
time spent seeding seeding_time duration Le temps de seed cumulé par le moteur depuis la fin du téléchargement : n'augmente que pendant le seed et hors arrêt.
time since added added_age duration Maintenant − date d'ajout.
time since completed completed_age duration Maintenant − date de fin. Un torrent qui ne s'est jamais terminé n'en a pas.
free space where it is stored free_space size Espace libre sur le système de fichiers du chemin de sauvegarde. Sur une minuterie, mesuré seulement quand une condition l'utilise.
hardlinks to its files link_count number Tous les hardlinks, y compris ceux d'Hydranos. Deux cross-seeds l'un de l'autre valent tous deux 2.
hardlinks from outside Hydranos external_links number 0 signifie que seul Hydranos pointe vers ces fichiers.
space deleting would really free freeable_bytes size Uniquement les fichiers vers lesquels rien d'autre ne pointe.
its files are missing from disk data_missing bool Vrai quand l'index des hardlinks n'a trouvé aucun des fichiers du torrent. Un torrent dont seuls certains fichiers ont disparu vaut faux (la ligne Hardlink index les compte à part, en with some files missing). Pas encore mesuré = faux.

Opérateurs (l'éditeur affiche le libellé, l'API prend l'identifiant) :

Type Opérateurs (libellé → identifiant)
text is eq, is not ne, contains contains, does not contain not_contains, starts with starts_with, ends with ends_with, matches regex matches
number, percent, size is eq, is not ne, is more than gt, is at least ge, is less than lt, is at most le
duration is older than gt, is at least ge, is newer than lt, is at most le, is eq, is not ne
bool is eq, is not ne (valeur true / false)
tags has tag has_tag, does not have tag not_has_tag

Valeurs :

  • Durées : 2d, 36h, 90m, 45s ou des secondes brutes (l'éditeur a un sélecteur d'unité).
  • Tailles : KB/MB/GB/TB sont des puissances de 1000, KiB/MiB/GiB/TiB des puissances de 1024 : 500GB ≠ 500GiB.
  • Booléens : true, yes ou 1 signifient vrai ; tout le reste signifie faux.
  • Texte : les comparaisons ignorent la casse, sauf matches, qui est une expression régulière sensible à la casse (syntaxe Rust regex ; préfixez (?i) pour ignorer la casse). Les comparaisons de tags sont exactes, casse comprise.
  • Pour category, tags, tracker et engine, l'éditeur propose une liste déroulante des valeurs connues.
  • « Jamais arrivé » ne correspond à rien. Un torrent qui ne s'est jamais terminé échoue à toute comparaison sur completed_age, is not compris. Un torrent que l'index des hardlinks n'a pas encore mesuré échoue à toute condition sur link_count, external_links et freeable_bytes ; data_missing vaut faux pour lui, donc data_missing is false le prend. Dans un groupe aucune de ces conditions (NON), le résultat s'inverse : NON completed_age is newer than 1d ou NON external_links is more than 0 prend chaque torrent jamais terminé ou pas encore mesuré. Écrivez plutôt la forme positive (external_links is 0) qu'un NON.

Index des hardlinks. Les champs de hardlinks viennent d'un index en arrière-plan (démarre ~3 min après le boot, re-mesure les entrées de plus de 24 h ; HYDRANOS_LINK_SCAN_THREADS, 16 par défaut). La ligne Hardlink index: X of Y torrents measured sous la liste montre son avancement. Un passage re-mesure ses candidats avant d'agir, et un delete décidé sur des faits de hardlinks est refusé si un nouveau lien est apparu entre-temps.

Actions

Libellé dans Then type transmis et champs Ce qu'elle fait
stop the torrent {"type":"pause"} Enregistre l'intention d'arrêt pour cette copie et l'arrête dans son moteur, comme le bouton Arrêter (Stop). Aucun effet sur le disque.
start the torrent {"type":"resume"} L'inverse.
set category (files stay) {"type":"set_category","to":"tv"} Change uniquement l'étiquette de catégorie de cette copie : aucun déplacement de fichiers, aucun changement de moteur (pour déplacer les données : move files to a folder ou Changer de catégorie + déplacer les fichiers › (Change category + move files ›)).
move files to a folder {"type":"set_location","to":"/data/archive","allow_breaking_hardlinks":false} Met en file un job move_data (onglet Jobs), avec le même plan et les mêmes refus que Déplacer vers un dossier… (Set location…). « Déjà sur place »/« déjà en file » comptent comme un succès. Le chemin doit être absolu, avec des noms simples uniquement. Sous Windows, un chemin avec lettre de lecteur (D:\archive) ou UNC est accepté ; \archive n'y est pas absolu. Un fichier hardlinké qui exigerait une copie entre disques fait échouer le torrent, sauf si allow_breaking_hardlinks vaut true (case copier quand même les fichiers hardlinkés d'un disque à l'autre (casse le lien, double l'espace) (copy hardlinked files across disks anyway (breaks the link, uses the space twice))).
add trackers {"type":"add_trackers","urls":["udp://tracker.example.org:6969/announce"],"list_url":""} Ajoute chaque nouvelle URL dans son propre palier. list_url récupère une liste (une URL par ligne, commentaires # ignorés, ≤ 500 URL, mise en cache 24 h). Jamais appliquée à un torrent privé. Chaque tracker ajouté apprend l'IP de cette instance. Voir Trackers & annonces.
add tags / remove tags {"type":"add_tags","tags":["noHL"]} Réécrit les tags du torrent sur chaque copie. Dans l'éditeur, séparez les tags par des virgules.
delete the torrent {"type":"delete","with_files":false} Supprime la copie qui correspond comme une suppression manuelle. also delete the files on disk positionne with_files. Les fichiers qu'un autre torrent chargé lit au même chemin sont conservés (la copie de ce torrent dans un autre moteur comprise, quand elle pointe vers le même dossier) ; une copie dont le contenu est ailleurs ne protège rien (voir Jobs, actions groupées & déplacement). Doit être la seule action.
call a webhook {"type":"webhook","url":"https://hooks.example.org/hydranos"} Envoie du JSON en POST (voir ci-dessous) par la sortie propre du démon ([daemon] egress, voir VPN & sortie réseau). L'URL doit être en http:// ou https://.

Comment les actions s'exécutent :

  • Les actions d'un torrent s'exécutent dans l'ordre. Le premier échec arrête les suivantes pour ce torrent, qui compte comme failed.
  • Les webhooks s'exécutent toujours après les autres actions, quelle que soit leur position dans Then.
  • Sur une minuterie, un webhook n'est envoyé que lors d'un passage où une autre action du même workflow modifie le torrent. Un workflow à minuterie dont les seules actions sont des webhooks est refusé (il appellerait l'URL à chaque passage). Sur un déclencheur d'événement, le webhook est toujours envoyé, et un webhook seul est autorisé.
  • Si le webhook échoue après l'écriture d'un tag, le tag reste, et le passage suivant (torrent « comme demandé ») ne retente pas le webhook.
  • Chaque tentative a un délai d'expiration de 10 s ; un échec est retenté après 2 s puis 5 s, un 4xx ne l'est pas. L'URL n'apparaît jamais dans les erreurs. Un endpoint mort ralentit le passage.
  • Quand le kill switch ne laisse au démon aucune sortie, le webhook n'est pas envoyé du tout (pas de nouvelle tentative) : le torrent compte comme failed avec webhook: <reason>.
  • Il n'existe aucune action pour lancer une commande, revérifier, ré-annoncer, fixer des limites ou déplacer un torrent vers un autre moteur.

Corps du webhook :

{"event": "completed", "workflow": "Notify on completion", "at": 1790000000,
 "content": "Some.Torrent finished downloading (4.37 GiB)", "text": "…same…", "message": "…same…",
 "torrent": {"info_hash": "0123…", "name": "Some.Torrent", "category": "tv", "tags": [],
   "engine": "race", "save_path": "/data/race/tv", "state": "seeding", "tracker": "tracker.example.org",
   "size": 4692251443, "progress": 100, "ratio": 0.0, "uploaded": 0, "downloaded": 4692251443,
   "seeding_time": 0}}

event vaut matched (minuterie), completed ou added. Le résumé est répété sous content (Discord), text (Slack, Mattermost) et message (Gotify), si bien que ces services acceptent l'URL directement. Les nombres inconnus valent null.

Aperçu, dry-run, exécution immédiate

Contrôle Où Route Ce qu'il fait
Aperçu (Preview) éditeur POST /api/workflows/preview (corps = le workflow, enregistré ou non) Valide comme un enregistrement, exécute la même évaluation qu'un vrai passage, ne modifie aucun torrent. Minuterie : N matched, M would change, K already as asked, (capped), would free X GB pour une suppression, les 10 premiers noms. quand un téléchargement se termine (when a download completes) : sur chaque torrent dont progress est sous 100, arrêtés compris — ce qui prend aussi les torrents complets arrêtés sans carte des pièces (voir progress), si bien que le compte peut surestimer. quand un torrent est ajouté (when a torrent is added) : sur les torrents ajoutés dans les dernières 24 heures.
Dry-run ligne de la liste (minuterie uniquement) POST /api/workflows/:id/run?dry=1 Même évaluation, sur la version enregistrée. La réponse apparaît en JSON brut dans une alerte du navigateur : dry_run, matched, would_apply, skipped, capped, rechecked, no_longer_true. Un dry-run qui n'appliquerait rien (aucune correspondance, ou chaque correspondance déjà comme demandé) écrit une ligne Activity avec le résultat dry_run_no_match.
Run now ligne de la liste (minuterie uniquement) POST /api/workflows/:id/run Un vrai passage, activé ou non. Il enregistre la dernière exécution et renvoie matched, applied, skipped, failed, capped, rechecked, no_longer_true.

Dry-run et Run now sont masqués pour les workflows à événement (l'API répond 400) : utilisez Aperçu (Preview). « Would free » additionne la taille complète de chaque torrent correspondant : il surestime pour les fichiers hardlinkés ou partagés. Pour une règle sur les hardlinks, Aperçu et Dry-run re-mesurent aussi les candidats et écrivent les valeurs fraîches dans l'index des hardlinks. C'est, avec la ligne dry_run_no_match, tout ce qu'ils écrivent.

Activity

Le tableau Activity sous la liste affiche le journal des workflows : When, Workflow, Torrent, Action, Outcome, Detail. Il charge les 500 lignes les plus récentes. Les lignes de plus de 7 jours sont purgées chaque minute.

  • Une ligne par torrent traité. Action joint les actions effectuées par + (pause, resume, category, add_tags, remove_tags, delete, webhook, set_location, add_trackers), par ex. add_tags+webhook.
  • Le même tableau contient ce qu'ont fait les règles RSS : Workflow RSS: <rule name> (RSS: (manual) pour le Téléchargement de l'onglet RSS), Action rss_add, Torrent le titre de l'article, Outcome applied, skipped (Detail already in this client) ou failed avec la raison (un échec passager se termine par ; tried again at the next pass).
  • Pour un workflow, Outcome vaut applied ou failed. Pour failed, Detail donne l'erreur (par exemple webhook: HTTP 500 after 3 tries ; un 4xx donne webhook: HTTP 404). Un torrent privé n'est jamais un échec : add trackers le saute comme « comme demandé ».
  • Les torrents déjà « comme demandé » et les passages qui ne correspondent à rien ne sont pas journalisés (sauf un Dry-run qui n'a rien à appliquer : dry_run_no_match).
  • applied pour move files to a folder signifie « job mis en file » ; suivez le déplacement dans l'onglet Jobs.

Exemples

Chaque exemple donne les étapes dans l'éditeur et le même workflow en JSON pour l'API. L'API accepte "enabled": true ; l'éditeur enregistre un nouveau workflow désactivé, donc cochez Enabled dans la liste après le premier enregistrement (enregistrer une modification garde l'état du workflow).

1. Arrêter le seed après 14 jours sur un tracker

  1. + New workflow. Nom (Name) : Stop after 14 days on tracker.example.org. Se lance (Runs) : à intervalle régulier (on a timer). Runs every : 3600.
  2. When (all of these (AND)) : tracker · is · tracker.example.org. Cliquez sur + Condition : time spent seeding · is older than · 14 jours.
  3. Then : stop the torrent.
  4. Aperçu (Preview), puis Enregistrer (Save), puis cochez Enabled.
{
  "name": "Stop after 14 days on tracker.example.org",
  "enabled": true,
  "trigger": "schedule",
  "interval_secs": 3600,
  "cap": 500,
  "when": {"kind": "all", "of": [
    {"kind": "cond", "field": "tracker_host", "op": "eq", "value": "tracker.example.org"},
    {"kind": "cond", "field": "seeding_time", "op": "gt", "value": "14d"}
  ]},
  "then": [{"type": "pause"}]
}

tracker ne lit que le premier tracker. Hydranos a aussi des limites de partage intégrées, par moteur et par torrent (File d'attente, limites de partage et de débit) ; un workflow comme celui-ci sert aux règles qu'elles ne savent pas exprimer (par tracker, par catégorie, par tags…).

2. Taguer les torrents sans hardlink hors d'Hydranos

Repère les contenus que votre médiathèque n'utilise plus (par ex. après que Sonarr a supprimé son hardlink).

  1. + New workflow. Nom (Name) : Tag noHL. Se lance (Runs) : à intervalle régulier (on a timer). Runs every : 21600.
  2. When : hardlinks from outside Hydranos · is · 0. + Condition : state · is · seeding.
  3. Then : add tags · noHL.
  4. Aperçu (Preview). Vérifiez la ligne Hardlink index sous la liste : les torrents pas encore mesurés ne correspondent jamais. Puis Enregistrer (Save) et cochez Enabled.
{
  "name": "Tag noHL",
  "enabled": true,
  "trigger": "schedule",
  "interval_secs": 21600,
  "cap": 500,
  "when": {"kind": "all", "of": [
    {"kind": "cond", "field": "external_links", "op": "eq", "value": "0"},
    {"kind": "cond", "field": "state", "op": "eq", "value": "seeding"}
  ]},
  "then": [{"type": "add_tags", "tags": ["noHL"]}]
}

Le tag reste quand la condition cesse d'être vraie ; un second workflow (external_links is more than 0, has tag noHL → remove tags) l'efface. Vérifiez avant de supprimer quoi que ce soit.

3. Appeler un webhook à la fin d'un téléchargement

  1. + New workflow. Nom (Name) : Notify on completion. Se lance (Runs) : quand un téléchargement se termine (when a download completes).
  2. When : cliquez sur Remove sur la ligne de condition de départ pour agir sur chaque téléchargement, ou gardez une condition comme category · is · tv.
  3. Then : call a webhook · https://hooks.example.org/hydranos.
  4. Aperçu (Preview) (il s'exécute sur les torrents dont progress est sous 100, voir Aperçu), Enregistrer (Save), cochez Enabled.
{
  "name": "Notify on completion",
  "enabled": true,
  "trigger": "completed",
  "when": {"kind": "all", "of": []},
  "then": [{"type": "webhook", "url": "https://hooks.example.org/hydranos"}]
}

Le corps est le JSON montré sous Actions. Les torrents ajoutés avec leurs données déjà sur le disque ne le déclenchent jamais.

4. Ajouter des trackers publics aux nouveaux torrents publics

  1. + New workflow. Nom (Name) : Public trackers on add. Se lance (Runs) : quand un torrent est ajouté (when a torrent is added).
  2. When : private · is · false.
  3. Then : add trackers. Saisissez une URL d'annonce par ligne, par ex. udp://tracker.example.org:6969/announce, ou mettez l'URL d'une liste dans la seconde case.
  4. Aperçu (Preview) (il montre ce qui serait arrivé aux arrivées du dernier jour), Enregistrer (Save), cochez Enabled.
{
  "name": "Public trackers on add",
  "enabled": true,
  "trigger": "added",
  "when": {"kind": "all", "of": [
    {"kind": "cond", "field": "private", "op": "eq", "value": "false"}
  ]},
  "then": [{"type": "add_trackers",
            "urls": ["udp://tracker.example.org:6969/announce"],
            "list_url": ""}]
}

L'action saute les torrents privés même sans la condition. Donnez toujours un port pour les URL udp://. Une récupération de liste qui échoue se rabat sur la dernière copie valide ; s'il n'y en a aucune, l'action échoue.

Bugs connus et limites en 4.4

L'éditeur ne peut pas réordonner les workflows (position n'est jamais envoyé).

Bug connu en 4.4 : progress semble valoir 100 pour tout torrent complet — il vaut 0 pour un torrent arrêté sans carte des pièces : un ajout en mode seed ou un cross-seed ajouté arrêté, ou un torrent complet rechargé après un redémarrage et arrêté (seul un torrent qui seede est connu pour tout détenir sans carte). Une règle comme progress is 100 les rate et progress < 100 les prend — pour dire « complet », testez completed_age (renseigné pour un ajout en mode seed et conservé après un redémarrage) ; state is seeding laisse de côté les torrents arrêtés.

API

Toutes les routes exigent la clé API (en-tête X-Api-Key ou paramètre de requête apikey). Les conventions complètes sont sur API REST.

Méthode et route Corps / réponse
GET /api/workflows Liste : id, name, enabled, position, trigger, interval_secs, last_run, when, then, cap.
POST /api/workflows Création ou mise à jour (même id = mise à jour). Corps : name (obligatoire), enabled (false par défaut), trigger (schedule par défaut), interval_secs (900 par défaut, relevé à 60), cap (500 par défaut ; 0 devient 500), when, then, id et position facultatifs. Le workflow est d'abord compilé : un workflow invalide reçoit un 400 avec la raison.
DELETE /api/workflows/:id Suppression ; 404 si inconnu.
POST /api/workflows/preview Corps = un workflow. Réponse comme dans Aperçu ci-dessus, plus freed_bytes et sample (≤ 200 torrents) ; les déclencheurs d'événement ajoutent trigger et downloading / recent.
POST /api/workflows/:id/run[?dry=1] Exécution immédiate ou dry-run (workflows à minuterie uniquement ; les workflows à événement reçoivent 400).
GET /api/workflows/fields Le catalogue de champs qu'utilise l'éditeur (name, label, kind, operators, hint…).
GET /api/workflows/activity Les 500 dernières lignes Activity : at, workflow_name, info_hash, torrent_name, action, outcome, detail.
GET /api/workflows/links État de l'index des hardlinks (catalogue, measured, data_missing, sweep…).

Arbre de conditions : {"kind":"all","of":[…]}, {"kind":"any","of":[…]}, {"kind":"not","of":{…}}, {"kind":"cond","field":"…","op":"…","value":"…"}.

Enregistrer et Aperçu refusent aussi un champ inconnu, une valeur qui ne se lit pas et une regex invalide, en plus des formes listées sous Déclencheurs et Actions.

# Preview a draft
curl -s -H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d @stop-after-14d.json http://localhost:8199/api/workflows/preview

# Save it (enabled if the file says "enabled": true)
curl -s -H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d @stop-after-14d.json http://localhost:8199/api/workflows

Pour modifier un workflow existant, faites un GET de la liste, modifiez l'objet et renvoyez-le entier en POST, avec son id (last_run est ignoré).

Hydranos 4.4 · 🇬🇧

Start

Install

Use

Integrate

Network & machines

Operate

Reference


Hydranos 4.4 · 🇫🇷

Démarrer

Installer

Utiliser

Intégrer

Réseau & machines

Exploiter

Référence


Clone this wiki locally