test: add real-world release fixtures (EASY bucket)
Captures 5 canonical releases from /mnt/testipool/downloads as parametrized fixtures under tests/fixtures/releases/easy/. Each fixture declares the release name, expected ParsedRelease fields, original tree, and the future routing (library / torrents / seed_hardlinks) for the upcoming organize_media refactor. Today only the 'parsed' section is asserted; tree is materialized into a tmp_path to catch typos. Routing is captured ahead of the planner work — it becomes verifiable once organize_media lands. Cases: back_in_action (movie), slow_horses_single_ep (TV single), foundation_season_pack (S02 + .nfo noise), long_walk_with_noise (movie + KONTRAST.TOP.txt), sinners_yts (YTS bracket-heavy + Subs/ dir). Also tracks CHANGELOG.md under [Unreleased] / Added.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
"""Real-world release fixtures — anti-regression baseline for parse_release.
|
||||
|
||||
Each fixture under ``tests/fixtures/releases/<bucket>/<case>/expected.yaml``
|
||||
declares a release name and the ``ParsedRelease`` fields it should produce.
|
||||
Fields absent from the fixture's ``parsed`` block are not checked, so adding
|
||||
new attributes to ``ParsedRelease`` never breaks existing fixtures.
|
||||
|
||||
The fixture's ``tree`` is materialized into a temp dir to prove the layout is
|
||||
self-consistent, even though no filesystem assertions are made yet. The
|
||||
``routing`` block (library / torrents / seed_hardlinks) is captured ahead of
|
||||
the ``organize_media`` refactor — it will become verifiable once the planner
|
||||
exists.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict
|
||||
|
||||
import pytest
|
||||
|
||||
from alfred.domain.release.services import parse_release
|
||||
from tests.fixtures.releases.conftest import ReleaseFixture, discover_fixtures
|
||||
|
||||
FIXTURES = discover_fixtures()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fixture",
|
||||
FIXTURES,
|
||||
ids=[f.name for f in FIXTURES],
|
||||
)
|
||||
def test_parse_matches_fixture(fixture: ReleaseFixture, tmp_path) -> None:
|
||||
# Materialize the tree to assert it is at least well-formed YAML +
|
||||
# plausible filesystem paths. Catches typos / missing leading dirs early.
|
||||
fixture.materialize(tmp_path)
|
||||
|
||||
result = asdict(parse_release(fixture.release_name))
|
||||
# ``is_season_pack`` is a @property — asdict() does not include it.
|
||||
result["is_season_pack"] = parse_release(fixture.release_name).is_season_pack
|
||||
|
||||
for field, expected in fixture.expected_parsed.items():
|
||||
assert field in result, (
|
||||
f"{fixture.name}: unknown field '{field}' in expected.parsed"
|
||||
)
|
||||
assert result[field] == expected, (
|
||||
f"{fixture.name}: parsed.{field} — "
|
||||
f"expected {expected!r}, got {result[field]!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_at_least_one_fixture_per_bucket() -> None:
|
||||
"""Each bucket should hold at least one case once populated."""
|
||||
buckets = {f.name.split("/")[0] for f in FIXTURES}
|
||||
assert "easy" in buckets, "EASY bucket must have at least one fixture"
|
||||
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
"""Fixture discovery and materialization helpers for release fixtures.
|
||||
|
||||
Each fixture is a directory under ``tests/fixtures/releases/<bucket>/<case>/``
|
||||
containing one ``expected.yaml`` file. See ``releases/README.md`` for the
|
||||
schema.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
FIXTURES_ROOT = Path(__file__).parent
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ReleaseFixture:
|
||||
"""A loaded fixture, ready to be materialized into a temp dir."""
|
||||
|
||||
name: str # "<bucket>/<case>", e.g. "easy/back_in_action"
|
||||
path: Path # directory containing expected.yaml
|
||||
data: dict # parsed YAML contents
|
||||
|
||||
@property
|
||||
def release_name(self) -> str:
|
||||
return self.data["release_name"]
|
||||
|
||||
@property
|
||||
def expected_parsed(self) -> dict:
|
||||
return self.data.get("parsed", {})
|
||||
|
||||
@property
|
||||
def tree(self) -> list[str]:
|
||||
return self.data.get("tree", [])
|
||||
|
||||
@property
|
||||
def routing(self) -> dict:
|
||||
return self.data.get("routing", {})
|
||||
|
||||
def materialize(self, root: Path) -> None:
|
||||
"""Create the fixture's ``tree`` as empty files/dirs under ``root``."""
|
||||
for entry in self.tree:
|
||||
target = root / entry
|
||||
if entry.endswith("/"):
|
||||
target.mkdir(parents=True, exist_ok=True)
|
||||
else:
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.touch()
|
||||
|
||||
|
||||
def discover_fixtures() -> list[ReleaseFixture]:
|
||||
"""Find all ``expected.yaml`` files under FIXTURES_ROOT."""
|
||||
fixtures = []
|
||||
for yaml_path in sorted(FIXTURES_ROOT.glob("*/*/expected.yaml")):
|
||||
data = yaml.safe_load(yaml_path.read_text())
|
||||
name = f"{yaml_path.parent.parent.name}/{yaml_path.parent.name}"
|
||||
fixtures.append(ReleaseFixture(name=name, path=yaml_path.parent, data=data))
|
||||
return fixtures
|
||||
@@ -0,0 +1,30 @@
|
||||
release_name: "Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST"
|
||||
|
||||
parsed:
|
||||
title: "Back.in.Action"
|
||||
year: 2025
|
||||
season: null
|
||||
episode: null
|
||||
episode_end: null
|
||||
quality: "1080p"
|
||||
source: "WEBRip"
|
||||
codec: "x265"
|
||||
group: "KONTRAST"
|
||||
tech_string: "1080p.WEBRip.x265"
|
||||
media_type: "movie"
|
||||
site_tag: null
|
||||
parse_path: "direct"
|
||||
is_season_pack: false
|
||||
|
||||
tree:
|
||||
- "Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST/"
|
||||
- "Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST/Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
|
||||
routing:
|
||||
library:
|
||||
- "Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST/Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
torrents:
|
||||
- "Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST/"
|
||||
seed_hardlinks:
|
||||
- source: "library/Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST/Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
target: "torrents/Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST/Back.in.Action.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
@@ -0,0 +1,68 @@
|
||||
release_name: "Foundation.S02.1080p.x265-ELiTE"
|
||||
|
||||
parsed:
|
||||
title: "Foundation"
|
||||
year: null
|
||||
season: 2
|
||||
episode: null
|
||||
episode_end: null
|
||||
quality: "1080p"
|
||||
source: null
|
||||
codec: "x265"
|
||||
group: "ELiTE"
|
||||
tech_string: "1080p.x265"
|
||||
media_type: "tv_show"
|
||||
site_tag: null
|
||||
parse_path: "direct"
|
||||
is_season_pack: true
|
||||
|
||||
tree:
|
||||
- "Foundation.S02.1080p.x265-ELiTE/"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02.1080p.x265-ELiTE.nfo"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E01.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E02.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E03.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E04.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E05.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E06.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E07.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E08.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E09.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E10.1080p.x265-ELiTE.mkv"
|
||||
|
||||
routing:
|
||||
library:
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E01.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E02.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E03.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E04.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E05.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E06.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E07.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E08.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E09.1080p.x265-ELiTE.mkv"
|
||||
- "Foundation.S02.1080p.x265-ELiTE/Foundation.S02E10.1080p.x265-ELiTE.mkv"
|
||||
torrents:
|
||||
# Whole original folder moves to torrents/ (carries the .nfo with it)
|
||||
- "Foundation.S02.1080p.x265-ELiTE/"
|
||||
seed_hardlinks:
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E01.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E01.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E02.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E02.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E03.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E03.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E04.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E04.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E05.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E05.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E06.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E06.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E07.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E07.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E08.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E08.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E09.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E09.1080p.x265-ELiTE.mkv"
|
||||
- source: "library/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E10.1080p.x265-ELiTE.mkv"
|
||||
target: "torrents/Foundation.S02.1080p.x265-ELiTE/Foundation.S02E10.1080p.x265-ELiTE.mkv"
|
||||
@@ -0,0 +1,32 @@
|
||||
release_name: "The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST"
|
||||
|
||||
parsed:
|
||||
title: "The.Long.Walk"
|
||||
year: 2025
|
||||
season: null
|
||||
episode: null
|
||||
episode_end: null
|
||||
quality: "1080p"
|
||||
source: "WEBRip"
|
||||
codec: "x265"
|
||||
group: "KONTRAST"
|
||||
tech_string: "1080p.WEBRip.x265"
|
||||
media_type: "movie"
|
||||
site_tag: null
|
||||
parse_path: "direct"
|
||||
is_season_pack: false
|
||||
|
||||
tree:
|
||||
- "The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST/"
|
||||
- "The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST/KONTRAST.TOP.txt"
|
||||
- "The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST/The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
|
||||
routing:
|
||||
library:
|
||||
- "The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST/The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
torrents:
|
||||
# KONTRAST.TOP.txt travels with the folder — never lives in library/
|
||||
- "The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST/"
|
||||
seed_hardlinks:
|
||||
- source: "library/The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST/The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
target: "torrents/The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST/The.Long.Walk.2025.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
@@ -0,0 +1,68 @@
|
||||
release_name: "Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX]"
|
||||
|
||||
# Quirks worth noting (current parse_release behavior):
|
||||
# - Trailing [YTS.MX] is stripped as a site_tag, leaving a dangling "-" in
|
||||
# raw/normalised and a UNKNOWN group. We capture this as-is — change requires
|
||||
# intentional parser work, not silent drift.
|
||||
parsed:
|
||||
title: "Sinners"
|
||||
year: 2025
|
||||
season: null
|
||||
episode: null
|
||||
episode_end: null
|
||||
quality: "1080p"
|
||||
source: "WEBRip"
|
||||
codec: "x265"
|
||||
group: "UNKNOWN"
|
||||
tech_string: "1080p.WEBRip.x265"
|
||||
media_type: "movie"
|
||||
site_tag: "YTS.MX"
|
||||
parse_path: "sanitized"
|
||||
bit_depth: "10bit"
|
||||
is_season_pack: false
|
||||
|
||||
# YTS uses bracket-heavy folder naming and ships a hefty Subs/ dir.
|
||||
# Selected language defaults from ltm.subtitle_preferences: ["fre", "eng"].
|
||||
tree:
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].mp4"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/www.YTS.MX.jpg"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/YIFYStatus.com.txt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/ara.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/Brazilian.por.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/English.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/European.fre.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/European.por.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/European.spa.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/ger.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/ita.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/Latin American.spa.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/SDH.eng.HI.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/Traditional.chi.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/tur.srt"
|
||||
|
||||
routing:
|
||||
library:
|
||||
# Video + sidecar srt + selected eng/fre subs from Subs/
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].mp4"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/English.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/European.fre.srt"
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/SDH.eng.HI.srt"
|
||||
torrents:
|
||||
# Whole original folder goes to torrents/ — non-selected subs, jpg, txt all
|
||||
# travel with it. Anything in library/ gets hard-linked back below.
|
||||
- "Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/"
|
||||
seed_hardlinks:
|
||||
- source: "library/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].mp4"
|
||||
target: "torrents/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].mp4"
|
||||
- source: "library/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].srt"
|
||||
target: "torrents/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Sinners.2025.1080p.WEBRip.x265.10bit.AAC5.1-[YTS.MX].srt"
|
||||
- source: "library/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/English.srt"
|
||||
target: "torrents/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/English.srt"
|
||||
- source: "library/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/European.fre.srt"
|
||||
target: "torrents/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/European.fre.srt"
|
||||
- source: "library/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/SDH.eng.HI.srt"
|
||||
target: "torrents/Sinners (2025) [1080p] [WEBRip] [x265] [10bit] [5.1] [YTS.MX]/Subs/SDH.eng.HI.srt"
|
||||
@@ -0,0 +1,32 @@
|
||||
release_name: "Slow.Horses.S05E01.1080p.WEBRip.x265-KONTRAST"
|
||||
|
||||
parsed:
|
||||
title: "Slow.Horses"
|
||||
year: null
|
||||
season: 5
|
||||
episode: 1
|
||||
episode_end: null
|
||||
quality: "1080p"
|
||||
source: "WEBRip"
|
||||
codec: "x265"
|
||||
group: "KONTRAST"
|
||||
tech_string: "1080p.WEBRip.x265"
|
||||
media_type: "tv_show"
|
||||
site_tag: null
|
||||
parse_path: "direct"
|
||||
is_season_pack: false
|
||||
|
||||
# The download folder happens to be the season pack folder (S05) but only
|
||||
# one episode is present — typical "single episode trickled in" case.
|
||||
tree:
|
||||
- "Slow.Horses.S05.1080p.WEBRip.x265-KONTRAST/"
|
||||
- "Slow.Horses.S05.1080p.WEBRip.x265-KONTRAST/Slow.Horses.S05E01.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
|
||||
routing:
|
||||
library:
|
||||
- "Slow.Horses.S05.1080p.WEBRip.x265-KONTRAST/Slow.Horses.S05E01.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
torrents:
|
||||
- "Slow.Horses.S05.1080p.WEBRip.x265-KONTRAST/"
|
||||
seed_hardlinks:
|
||||
- source: "library/Slow.Horses.S05.1080p.WEBRip.x265-KONTRAST/Slow.Horses.S05E01.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
target: "torrents/Slow.Horses.S05.1080p.WEBRip.x265-KONTRAST/Slow.Horses.S05E01.1080p.WEBRip.x265-KONTRAST.mkv"
|
||||
Reference in New Issue
Block a user