#!/usr/bin/env python3 """A tiny fake Newznab indexer for the dev instances (no real indexer needed). Answers every movie / TV search with a fixed set of releases for "The Matrix (1999)" and "Breaking Bad", and serves a dummy NZB for all of them. Radarr/Sonarr then do their real release parsing and decisions (approved / rejected, with reasons) on top. python3 dev/fake-indexer.py # listens on 0.0.0.0:19292 dev/add-indexer.sh # registers it in the dev Radarr and Sonarr """ import time from email.utils import formatdate from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import urlparse, parse_qs from xml.sax.saxutils import escape PORT = 19292 HOST = "host.containers.internal" # how the dev containers reach this machine GB = 1024 ** 3 MOVIES = [ # title, size, age in days ("The.Matrix.1999.1080p.BluRay.x264-DEV", 8 * GB, 1), ("The.Matrix.1999.2160p.UHD.BluRay.x265-DEV", 40 * GB, 3), ("The.Matrix.1999.720p.BluRay.x264-OTHER", 4 * GB, 400), ("The.Matrix.1999.480p.DVDRip.XviD-OLD", 700 * 1024 ** 2, 2000), ("The.Matrix.Reloaded.2003.1080p.BluRay.x264-DEV", 9 * GB, 5), ] TV = [ ("Breaking.Bad.S01E01.1080p.BluRay.x264-DEV", 2 * GB, 30), ("Breaking.Bad.S01E01.720p.HDTV.x264-OTHER", 900 * 1024 ** 2, 60), ("Breaking.Bad.S01.1080p.BluRay.x264-DEV", 14 * GB, 20), ("Breaking.Bad.S02E01.1080p.BluRay.x264-DEV", 2 * GB, 30), ] NZB = b""" alt.binaries.test abc123@example.com """ CAPS = """ """ def item(n, title, size, age_days, cat): link = f"http://{HOST}:{PORT}/nzb/{n}.nzb" date = formatdate(time.time() - age_days * 86400) return f"""{escape(title)}http://{HOST}:{PORT}/details/{n} {link}{date} """ class Handler(BaseHTTPRequestHandler): def log_message(self, *args): pass def reply(self, body, ctype="application/xml"): data = body if isinstance(body, bytes) else body.encode() self.send_response(200) self.send_header("Content-Type", ctype) self.send_header("Content-Length", str(len(data))) self.end_headers() self.wfile.write(data) def do_GET(self): url = urlparse(self.path) if url.path.startswith("/nzb/"): return self.reply(NZB, "application/x-nzb") q = {k: v[0] for k, v in parse_qs(url.query).items()} t = q.get("t", "") if t == "caps": return self.reply(CAPS) releases = TV if t == "tvsearch" else MOVIES cat = 5040 if t == "tvsearch" else 2040 items = "".join(item(i, *r, cat) for i, r in enumerate(releases)) self.reply(f""" fake{items}""") if __name__ == "__main__": print(f"fake indexer on :{PORT}") HTTPServer(("0.0.0.0", PORT), Handler).serve_forever()