Skip to content

Instantly share code, notes, and snippets.

@gmcouto
Last active November 20, 2025 15:58
Show Gist options
  • Select an option

  • Save gmcouto/15d03a7a56561bbba5dd3db5e3e230dd to your computer and use it in GitHub Desktop.

Select an option

Save gmcouto/15d03a7a56561bbba5dd3db5e3e230dd to your computer and use it in GitHub Desktop.
---
id: capybarabr_gaucho_mediainfo
name: CapybaraBR Gaucho Mediainfo (API)
description: "CapybaraBR is a BRAZILIAN Private Torrent Tracker for MOVIES / TV / GENERAL"
language: pt-BR
type: private
encoding: UTF-8
links:
- https://capybarabr.com/
caps:
categorymappings:
- {id: 1, cat: Movies, desc: "Filmes"}
- {id: 2, cat: TV, desc: "Series"}
- {id: 4, cat: TV/Anime, desc: "Animes"}
- {id: 8, cat: TV/Sport, desc: "Esportes"}
- {id: 6, cat: Movies, desc: "Desenhos Animados"}
- {id: 5, cat: Console, desc: "Jogos"}
- {id: 9, cat: PC, desc: "Programas"}
- {id: 10, cat: Books/Comics, desc: "HQs"}
- {id: 11, cat: Books/EBook, desc: "Livros"}
- {id: 12, cat: Other, desc: "Cursos"}
- {id: 13, cat: Books/Mags, desc: "Revistas"}
modes:
search: [q]
tv-search: [q, season, ep, imdbid, tvdbid, tmdbid]
movie-search: [q, imdbid, tmdbid]
music-search: [q]
book-search: [q]
settings:
- name: apikey
type: text
label: APIKey
- name: info_key
type: info
label: About your API key
default: "Find or Generate a new API Token by accessing your <a href=\"https://capybarabr.com/\" target=\"_blank\">CapybaraBR</a> account <i>My Settings</i> page and clicking on the <b>API Key</b> tab."
- name: freeleech
type: checkbox
label: Search freeleech only
default: false
- name: use_single_file_release_use_filename
type: checkbox
label: Use filename as the title for single file releases
default: false
- name: sort
type: select
label: Sort requested from site
default: created_at
options:
created_at: created
seeders: seeders
size: size
name: title
- name: type
type: select
label: Order requested from site
default: desc
options:
desc: desc
asc: asc
- name: info_activity
type: info
label: Account Inactivity
default: "The system automatically makes an account inactive when not logged in for a period of 90 days. So just log in within this time so that it is not inactivated."
login:
path: /api/torrents
method: get
inputs: {} # TODO: remove in v10
error:
- selector: a[href*="/login"]
message:
text: "The API key was not accepted by {{ .Config.sitelink }}."
- selector: :root:contains("Account is Banned")
search:
paths:
# https://hdinnovations.github.io/UNIT3D/torrent_api.html
# https://github.com/HDInnovations/UNIT3D/blob/master/app/Http/Controllers/API/TorrentController.php#L657
- path: api/torrents/filter
response:
type: json
headers:
Authorization: ["Bearer {{ .Config.apikey }}"]
inputs:
# if we have an id based search, add Season and Episode as query in name for UNIT3D < v6. Else pass S/E Params for UNIT3D >= v6
$raw: "{{ range .Categories }}&categories[]={{.}}{{end}}"
name: "{{ .Keywords }}"
seasonNumber: "{{ .Query.Season }}"
episodeNumber: "{{ .Query.Ep }}"
imdbId: "{{ .Query.IMDBIDShort }}"
tmdbId: "{{ .Query.TMDBID }}"
tvdbId: "{{ .Query.TVDBID }}"
"free[]": "{{ if .Config.freeleech }}100{{ else }}{{ end }}"
sortField: "{{ .Config.sort }}"
sortDirection: "{{ .Config.type }}"
perPage: 100
keywordsfilters:
- name: re_replace
args: ["\\.", " "]
rows:
selector: data
attribute: attributes
fields:
languages: # languages = "English (US), French (CA), Portuguese (Brazil)" -> "English, French, Portuguese (Brazil)"
selector: media_info
optional: true
filters:
- name: re_replace
args: ['(?s)^(?![\s\S]*Audio\s+(#\d+)?)[\s\S]*$', ''] # if media info does not contain audio information, give up
- name: re_replace
args: ['(?s)^(?![\s\S]*Language)[\s\S]*$', ''] # if media info does not contain language information, give up
- name: re_replace
args: ['\r', ''] # removes crappy \r char
- name: re_replace
args: ['(?s)(.*(?:Audio\s+(#\d+)?.*?(?:Language[^\n]+))).*', "$1\n"] # removes everything after the last audio language
- name: re_replace
args: ['(?s).*?(Audio\s+(#\d+)?.*?(?:Language[^\n]+))', "\n$1"] # removes everything before the first audio language
- name: re_replace
args: ['(?m)^(?!.*\bLanguage\b).*\n', ''] # removes every line that is not a Language line
- name: re_replace
args: ['(?s)^(?!.*Language\s*:).*|Language\s*:\s*', ''] # removes everything that is not the actual language
- name: re_replace
args: ['^\s+|\s+$', ''] # trim leading and trailing spaces
- name: re_replace
args: ['(?i)((:?Portuguese \(Brazil\)|Spanish \(Latino\)|Norwegian Bokmal|\w+)).*', '$1'] # Language Cleanup (only select languages are multiple words)
- name: re_replace
args: ['[\n]+', ', '] # creates a single line of languages separated by comma
- name: re_replace
args: ['\b([^,]+)(?:,\s*\1)+', '$1'] # removes duplicated languages
- name: re_replace
args: ['(?i)(Portugu.s|Brazilian)(?:[^,]+)?', "Portuguese (Brazil)"] # portuguese is Portuguese (Brazil) (for radarr and sonarr)
subs: # languages = "English (US), French (CA), Portuguese (Brazil)" -> "English, French, Portuguese (Brazil)"
selector: media_info
optional: true
filters:
- name: re_replace
args: ['(?s)^(?![\s\S]*Text\s+(#\d+)?)[\s\S]*$', ''] # if media info does not contain Text information, give up
- name: re_replace
args: ['(?s)^(?![\s\S]*Language)[\s\S]*$', ''] # if media info does not contain language information, give up
- name: re_replace
args: ['\r', ''] # removes crappy \r char
- name: re_replace
args: ['(?s)(.*(?:Text\s+(#\d+)?.*?(?:Language[^\n]+))).*', "$1\n"] # removes everything after the last Text language
- name: re_replace
args: ['(?s).*?(Text\s+(#\d+)?.*?(?:Language[^\n]+))', "\n$1"] # removes everything before the first Text language
- name: re_replace
args: ['(?m)^(?!.*\bLanguage\b).*\n', ''] # removes every line that is not a Language line
- name: re_replace
args: ['(?s)^(?!.*Language\s*:).*|Language\s*:\s*', ''] # removes everything that is not the actual language
- name: re_replace
args: ['^\s+|\s+$', ''] # trim leading and trailing spaces
- name: re_replace
args: ['(?i)((:?Portuguese \(Brazil\)|Spanish \(Latino\)|Norwegian Bokmal|\w+)).*', '$1'] # Language Cleanup (only select languages are multiple words)
- name: re_replace
args: ['[\n]+', ', '] # creates a single line of languages separated by comma
- name: re_replace
args: ['\b([^,]+)(?:,\s*\1)+', '$1'] # removes duplicated languages
- name: re_replace
args: ['(?i)(Portugu.s|Brazilian)(?:[^,]+)?', "Portuguese (Brazil)"] # portuguese is Portuguese (Brazil) (for radarr and sonarr)
languages_suffix:
text: '{{ .Result.languages }}'
filters:
- name: re_replace
args: ['(?i)Portugu.s(?:[^,]+)?', "Brazilian"] # portuguese must be brazilian during release title matching
- name: re_replace
args: ['^(\w)', ' / $1'] # add prefix for title concatenation if languages are not empty
category:
selector: category_id
title_optional:
selector: name
title_filename:
selector: "files[0].name"
optional: true
files:
selector: num_file
title:
text: "{{ if and (.Config.use_single_file_release_use_filename) (eq .Result.files \"1\") (.Result.title_filename) }}{{ .Result.title_filename }}{{ else }}{{ .Result.title_optional }}{{ end }}{{ .Result.languages_suffix }}"
details:
selector: details_link
download:
selector: download_link
infohash:
selector: info_hash
poster:
selector: meta.poster
filters:
- name: replace
args: ["https://via.placeholder.com/90x135", ""]
imdbid:
selector: imdb_id
tmdbid:
selector: tmdb_id
tvdbid:
selector: tvdb_id
genre:
selector: meta.genres
filters:
- name: re_replace
args: ["(?i)(Ficção científica)", "Ficção_científica"]
- name: re_replace
args: ["(?i)(Cinema TV)", "Cinema_TV"]
- name: replace
args: [" & ", "_&_"]
_internal:
selector: internal
case:
False: "{{ .False }}"
True: "{{ .True }}"
description:
text: "{{ if .Result._internal }}Internal{{ else }}{{ end }}{{ if and .Result._internal .Result.genre }} | {{ else }}{{ end }}{{ .Result.genre }}"
seeders:
selector: seeders
leechers:
selector: leechers
grabs:
selector: times_completed
date:
# "created_at": "2021-10-18T00:34:50.000000Z" is returned by Newtonsoft.Json.Linq as 18/10/2021 00:34:50
selector: created_at
filters:
- name: append
args: " -03:00" # BRT
- name: dateparse
args: "MM/dd/yyyy HH:mm:ss zzz"
size:
selector: size
_featured:
selector: featured
case:
False: "{{ .False }}"
True: "{{ .True }}"
downloadvolumefactor_freeleech:
# api returns 0%, 25%, 50%, 75%, 100%
selector: freeleech
case:
0%: 1 # not free
25%: 0.75
50%: 0.5
75%: 0.25
100%: 0 # freeleech
"*": 0 # catch errors
downloadvolumefactor:
text: "{{ if .Result._featured }}0{{ else }}{{ .Result.downloadvolumefactor_freeleech }}{{ end }}"
uploadvolumefactor_double_upload:
# api returns False, True
selector: double_upload
case:
False: 1 # normal
True: 2 # double
uploadvolumefactor:
text: "{{ if .Result._featured }}2{{ else }}{{ .Result.uploadvolumefactor_double_upload }}{{ end }}"
# global MR is 1.0 but torrents must be seeded for 7 days regardless of ratio
# minimumratio:
# text: 1.0
minimumseedtime:
# 7 days (as seconds = 7 x 24 x 60 x 60)
text: 604800
# json UNIT3D 8.3.3 (custom)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment