---
id: hdforever
name: HD-Forever
description: "HD-Forever (HD-F) is a FRENCH Private Torrent Tracker for HD MOVIES"
language: fr-FR
type: private
encoding: UTF-8
links:
  - https://hdf.world/

caps:
  categorymappings:
    - {id: 1, cat: Movies, desc: "Film"}
    - {id: 2, cat: Movies, desc: "Film d'animation"}
    - {id: 3, cat: Movies, desc: "Spectacle"}
    - {id: 4, cat: Movies, desc: "Concert"}
    - {id: 5, cat: TV, desc: "Série"}
    - {id: 6, cat: TV/Anime, desc: "Série d'animation"}
    - {id: 7, cat: Movies, desc: "Documentaire"}

  modes:
    search: [q]
    tv-search: [q, season, ep, imdbid, tvdbid]
    movie-search: [q, imdbid, tmdbid]
  allowtvsearchimdb: true

settings:
  - name: info_2fa
    type: info
    label: "About 2FA"
    default: "If you want to enable 2FA then use the HD-Forever2FA indexer instead."
  - name: username
    type: text
    label: Username
  - name: password
    type: password
    label: Password
  - name: freeleech
    type: checkbox
    label: Search freeleech only
    default: false
  - name: usetoken
    type: checkbox
    label: Always try to use the FreeLeech Token
    default: false
  - name: info_token
    type: info
    label: About the Freeleech token
    default: If you <b>do not</b> have any <i>Freeleech tokens</i> then do not tick this box.</br>Attempting a token download when you have no tokens will generate an <b>error</b>.
  - name: multilang
    type: checkbox
    label: Replace MULTi by another language in release name
    default: false
  - name: multilanguage
    type: select
    label: Replace MULTi by this language
    default: FRENCH
    options:
      FRENCH: FRENCH
      MULTi.FRENCH: MULTi.FRENCH
      ENGLISH: ENGLISH
      MULTi.ENGLISH: MULTi.ENGLISH
      VOSTFR: VOSTFR
      MULTi.VOSTFR: MULTi.VOSTFR
  - name: vostfr
    type: checkbox
    label: Replace VOSTFR and SUBFRENCH with ENGLISH
    default: false
  - name: sort
    type: select
    label: Sort requested from site
    default: time
    options:
      time: created
      seeders: seeders
      size: size
  - name: type
    type: select
    label: Order requested from site
    default: desc
    options:
      desc: desc
      asc: asc
  - name: info_radarr
    type: info
    label: About Radarr
    default: The HD-F web site cannot find movies if you use the release year in a title search. When you define your Radarr Indexer remember to tick the <i>Remove year from search string</i> checkbox.
  - name: info_release_name
    type: info
    label: About release names
    default: For more stable release names, enable <b>Afficher les noms de fichiers</b> in your HD-F profile settings.

login:
  path: login.php
  method: post
  inputs:
    username: "{{ .Config.username }}"
    password: "{{ .Config.password }}"
    keeplogged: 1
  error:
    - selector: form#loginform > span.warning
  test:
    path: torrents.php
    selector: a[href^="logout.php?auth="]

search:
  # https://hdf.world/torrents.php?searchstr=Un+Singe+en+hiver+1962&freetorrent=1&order_by=time&order_way=desc&action=advanced&searchsubmit=1
  paths:
    - path: torrents.php
  inputs:
    $raw: "{{ range .Categories }}filter_cat[{{.}}]=1&{{end}}"
    searchstr: "{{ .Keywords }}"
    order_by: "{{ .Config.sort }}"
    order_way: "{{ .Config.type }}"
    action: advanced
    searchsubmit: 1
    # 1 freeleech, 2 neutral, 3 both, 0 normal
    freetorrent: "{{ if .Config.freeleech }}1{{ else }}{{ end }}"
    tmdbid: "{{ .Query.TMDBID }}"
    imdbid: "{{ .Query.IMDBID }}"

  rows:
    selector: table#torrent_table > tbody > tr.torrent:has(a[href^="torrents.php?action=download&"])

  fields:
    category:
      selector: td.cats_col
      case:
        div.cats_film: 1
        div[class*="cats_filmd"]: 2
        div.cats_spectacle: 3
        div.cats_concert: 4
        div.cats_série: 5
        div[class*="cats_séried"]: 6
        div.cats_documentaire: 7
    details:
      selector: a[href^="torrents.php?id="]
      attribute: href
    download_regular:
      selector: a[href^="torrents.php?action=download&"]
      attribute: href
    download_usetoken:
      selector: a[href^="torrents.php?action=download&"]
      attribute: href
      filters:
        - name: append
          args: "&usetoken=1"
    download:
      text: "{{ if .Config.usetoken }}{{ .Result.download_usetoken }}{{ else }}{{ .Result.download_regular }}{{ end }}"
    _release_group:
      selector: span.team_name
      optional: true
      filters:
        - name: trim
    poster:
      selector: div.group_image img
      attribute: src
    imdbid:
      selector: a[href*="imdb.com/title/tt"]
      attribute: href
    tmdbid:
      selector: a[href*="themoviedb.org/movie/"], a[href*="themoviedb.org/tv/"]
      attribute: href
    date:
      selector: span.time
      filters:
        - name: replace
          args: ["Il y a ", ""]
        - name: replace
          args: ["heures", "hours"]
        - name: replace
          args: ["heure", "hour"]
        - name: replace
          args: ["jours", "days"]
        - name: replace
          args: ["jour", "day"]
        - name: replace
          args: ["semaines", "weeks"]
        - name: replace
          args: ["semaine", "week"]
        - name: replace
          args: ["mois", "months"]
        - name: replace
          args: ["ans", "years"]
        - name: replace
          args: ["an", "year"]
        - name: append
          args: " ago"
    size:
      selector: td:nth-child(5)
    grabs:
      selector: td:nth-child(6)
    seeders:
      selector: td:nth-child(7)
    leechers:
      selector: td:nth-child(8)
    downloadvolumefactor:
      case:
        "div.torrent_info .tl_free": 0
        "div.torrent_info .tl_notice[title*=\"Freeleech\"]": 0 # Global freeleech enabled
        "div.torrent_info .tl_notice[title=\"-75%\"]": 0.75
        "div.torrent_info .tl_notice[title=\"-50%\"]": 0.50
        "div.torrent_info .tl_notice[title=\"-25%\"]": 0.25 # for this site this is the count ratio, which is 25% of the total torrent size. (I.E. it's 75% free)
        "*": 1
    uploadvolumefactor:
      text: 1
    title_torrent_filename:
      selector: div.torrent_filename_row
      optional: true
      filters:
        - name: trim
    title_parsed:
      selector: div.group_info
      remove: span.team_name, span:has(a[href^="torrents.php?action=download"]), div.tags, div.vote_controls, div.stats-content, .add_bookmark, img, .tl_free, .tl_notice, .torrent_filename_row
      filters:
        - name: replace
          args: ["\n", " "]
        - name: re_replace
          args: ["\\[(?:Concert|Film|Film d'animation|Spectacle|Série|Série d'animation|Documentaire)\\]", ""]
        - name: replace
          args: ["Blu-ray Original", "Complete.BluRay"]
        - name: replace
          args: ["Blu-ray Remux", "Remux"]
        - name: replace
          args: ["Blu-ray Rip", "BluRay.Rip"]
        - name: replace
          args: ["mHD", "mHD.BluRay.Rip"]
        - name: re_replace
          args: ["(?:\\]|\\/\\s)DC", ".Directors.Cut"]
        - name: re_replace
          args: ["(?:\\]|\\/\\s)VL", ".Extended"]
        - name: re_replace
          args: ["(?:\\]|\\/\\s)RM", ".Remastered"]
        - name: re_replace
          args: ["(?:\\]|\\/\\s)UC", ".Uncut"]
        - name: re_replace
          args: ["(?:\\]|\\/\\s)UR", ".Unrated"]
        - name: re_replace
          args: ["(?:\\]|\\/\\s)ES", ".Special.Edition"]
        - name: re_replace
          args: ["(?:\\]|\\/\\s)Crit", ".Criterion"]
        - name: re_replace
          args: ["(?:\\/ )?(?:Remplaçable|Complété|Bonus|Note Modo|[2-9]+ème partie|\\b(?:Cust(?:_sub)?|WAC|BFI|MUET)\\b)(?: \\/)?", ""]
        - name: trim
        - name: re_replace
          args: ["[\\[\\]\\/\\s?.,:'!]+", "."]
        - name: trim
          args: "."
        - name: re_replace
          args: ["(?i)\\.VFF\\.VFQ\\.(?:MULTI|StFR(?:\\.MULTI)?|VO(?:\\.StFR)?)", ".MULTI.VF2"]
        - name: re_replace
          args: ["(?i)\\.VFF\\.(?:MULTI|StFR(?:\\.MULTI)?|VO(?:\\.StFR)?)", ".MULTI.VFF"]
        - name: re_replace
          args: ["(?i)\\.VFQ\\.(?:MULTI|StFR(?:\\.MULTI)?|VO(?:\\.StFR)?)", ".MULTI.VFQ"]
        - name: re_replace
          args: ["(?i)\\.VOQ\\.(?:MULTI|StFR(?:\\.MULTI)?|VO(?:\\.StFR)?)", ".MULTI.VOQ"]
        - name: re_replace
          args: ["(?i)\\.VFI\\.(?:MULTI|StFR(?:\\.MULTI)?|VO(?:\\.StFR)?)", ".MULTI.VFI"]
        - name: re_replace
          args: ["(?i)\\.VOF\\.(?:MULTI|StFR(?:\\.MULTI)?|VO(?:\\.StFR)?)", ".MULTI.VOF"]
        - name: re_replace
          args: ["(?i)\\.(?:VO\\.)?StFR", ".VOSTFR"]
        - name: append
          args: "{{ if .Result._release_group }}-{{ .Result._release_group }}{{ else }}{{ end }}"
    title_phase1:
      text: "{{ if .Result.title_torrent_filename }}{{ .Result.title_torrent_filename }}{{ else }}{{ .Result.title_parsed }}{{ end }}"
    title_vostfr:
      text: "{{ .Result.title_phase1 }}"
      filters:
        - name: re_replace
          args: ["(?i)\\b(vostfr|subfrench)\\b", "ENGLISH"]
    title_phase2:
      text: "{{ if .Config.vostfr }}{{ .Result.title_vostfr }}{{ else }}{{ .Result.title_phase1 }}{{ end }}"
    title_multilang:
      text: "{{ .Result.title_phase2 }}"
      filters:
        - name: re_replace
          args: ["(?i)\\b(MULTI(?!.*(?:FRENCH|ENGLISH|VOSTFR|VF2|VFF|VFQ|VOQ|VFI|VOF)))\\b", "{{ .Config.multilanguage }}"]
    title:
      text: "{{ if .Config.multilang }}{{ .Result.title_multilang }}{{ else }}{{ .Result.title_phase2 }}{{ end }}"
    description:
      selector: div.group_info
      filters:
        - name: replace
          args: ["\n", " "]
        - name: re_replace
          args: ["\\s+", " "]
# global MR is 0.6 but torrents must be seeded for 3 days regardless of ratio
#    minimumratio:
#      text: 0.6
    minimumseedtime:
      # 3 days (as seconds = 3 x 24 x 60 x 60)
      text: 259200
# Gazelle
