Files
managarr-demo/mock-htpc/prowlarr/Definitions/abnormal-api.yml
T
Dark-Alex-17 f3ad44f7d7 Add a Readarr mock instance to the demo
Adds darkalex17/readarr-mock, built from ghcr.io/pennydreadful/bookshelf:softcover
(the maintained Readarr continuation; the LinuxServer image is discontinued and
its metadata endpoint no longer resolves). The captured config carries 6 authors,
327 books, 39 book files, 4 tags, 7 indexers, 193 history rows and one root
folder at /books, with minimal EPUBs under mock-htpc/books so the files show as
imported.

Prowlarr now registers Readarr as a synced application, so its config is
recaptured and the prowlarr-mock image must be rebuilt and pushed alongside.

The compose file, managarr config, justfile recipes and README gain the fourth
instance. The demo script needs no change; it fetches the compose file and
config from main at run time.

Requires a Managarr release with Readarr support, since the demo script runs
the published darkalex17/managarr image against these files.
2026-09-21 17:12:10 -06:00

176 lines
4.6 KiB
YAML

---
id: abnormal-api
name: Abnormal (API)
description: "ABNormal (ABN) is a FRENCH Private Torrent Tracker for MOVIES / TV / GENERAL"
language: fr-FR
type: private
encoding: UTF-8
requestDelay: 2.1
links:
- https://abn.lol/
legacylinks:
- https://abnormal.ws
caps:
categorymappings:
- {id: 1, cat: TV, desc: "Series"}
- {id: 2, cat: Movies, desc: "Movies"}
- {id: 3, cat: TV/Documentary, desc: "Documentaries"}
- {id: 4, cat: TV/Anime, desc: "Anime"}
- {id: 5, cat: PC/Games, desc: "Games"}
- {id: 6, cat: PC, desc: "Applications"}
- {id: 7, cat: Books/EBook, desc: "Ebooks"}
- {id: 9, cat: TV, desc: "Emissions"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
book-search: [q]
settings:
- name: apikey
type: text
label: APIKey
- name: info_key
type: info
label: About your API key
default: "Find your API key on your <a href=\"https://abn.lol/User/Parameters\" target=\"_blank\">Parameters</a> page. The API key is read-only and never expires."
- name: apiurl
label: API URL
type: text
default: api.abn.lol
- name: freeleech
type: checkbox
label: Search freeleech only
default: false
- 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: Created
options:
Created: created
Seeders: seeders
Size: size
ReleaseName: 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: "Accounts are automatically deactivated after 4 months of inactivity (no connection to the site)."
login:
path: "https://{{ .Config.apiurl }}/api/Release/Search?name=test&resultByPage=1"
method: get
error:
- selector: :root:contains("Unauthorized")
message:
text: "The API key was not accepted by {{ .Config.sitelink }}."
search:
paths:
- path: "https://{{ .Config.apiurl }}/api/Release/Search"
response:
type: json
headers:
Authorization: ["Bearer {{ .Config.apikey }}"]
inputs:
$raw: "{{ range .Categories }}categoryId={{.}}&{{end}}"
name: "{{ .Keywords }}"
resultByPage: 100
sort: "{{ .Config.sort }}"
sortDirection: "{{ .Config.type }}"
freeleech: "{{ if .Config.freeleech }}true{{ else }}{{ end }}"
keywordsfilters:
- name: re_replace
args: ["\\.", " "]
rows:
selector: $
fields:
category:
selector: categoryId
title_phase1:
selector: name
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)))\\b", "{{ .Config.multilanguage }}"]
title:
text: "{{ if .Config.multilang }}{{ .Result.title_multilang }}{{ else }}{{ .Result.title_phase2 }}{{ end }}"
_id:
selector: id
details:
# api returns https://api.abn.lol/api/Release/671444 which is not valid for browsing
text: "{{ .Config.sitelink }}Torrent/Details?ReleaseId={{ .Result._id }}"
download:
selector: downloadUrl
infohash:
selector: infoHash
date:
# created": "2026-03-07T06:59:22.137408" is returned by Newtonsoft.Json.Linq as 03/07/2026 06:59:22
selector: created
filters:
- name: append
args: " +00:01" # CET
- name: dateparse
args: "MM/dd/yyyy HH:mm:ss zzz"
size:
selector: size
seeders:
selector: seeders
leechers:
selector: leechers
grabs:
selector: completed
downloadvolumefactor:
selector: freeleech
case:
False: 1 # not free
True: 0 # freeleech
uploadvolumefactor:
text: 1
minimumratio:
text: 1.0
minimumseedtime:
# 4 days (as seconds = 4 x 24 x 60 x 60)
text: 345600
# JSON