"""The source registry: what a source is, and which ones may feed the library.
Sources were hardcoded -- extract_streams named fmovies and vsembed inline, and
vidcore was bolted on beside them as a special case. There was no shape into
which a fourth could be added, and no place to record what a source can and
cannot do.
Three properties matter, and the third is the one that cost a day to learn:
container hls-fmp4 needs a remux to become seekable; progressive-mp4 is
seekable as-is, so ingesting it is a plain fetch with no ffmpeg.
browser resolving needs a real browser (~11s, xvfb+patchright) rather than
plain HTTP, which decides whether it can sit on a hot path.
ingestable whether a plain HTTP client can fetch the BYTES.
`ingestable` is not a detail. vidlink hands over a signed progressive-MP4 URL in
3s with exact sizes -- strictly better than vidcore on every axis that shows up
in an API response -- and is still useless to us, because its proxy rejects curl
AND ffmpeg even with byte-exact browser headers (measured 2026-08-11: 428/403/429
across six combinations). The local-first design rests on ffmpeg pulling bytes
independently of any player, so a browser-only source cannot feed the library at
any quality.
Encoding that here means the next candidate cannot be silently wired into ingest
on the strength of a good-looking API.
Run: .venv/bin/python3 -m pytest test_source_registry.py -q
"""
import pytest
import addon
@pytest.fixture(autouse=True)
def clean_registry(monkeypatch):
monkeypatch.setattr(addon, "SOURCES", {})
yield
def _src(sid, **kw):
defaults = dict(name=sid, container="hls-fmp4", ingestable=True,
browser=False, heights=(1080,), resolve=None, enabled=True)
defaults.update(kw)
return addon.Source(id=sid, **defaults)
# --- registration -----------------------------------------------------------
def test_a_source_can_be_registered_and_looked_up():
addon.register_source(_src("alpha"))
assert addon.get_source("alpha").name == "alpha"
def test_an_unknown_source_is_none_rather_than_a_crash():
assert addon.get_source("nope") is None
def test_a_duplicate_id_is_refused():
"""Two sources sharing an id would make row ordering and breaker state
silently ambiguous."""
addon.register_source(_src("alpha"))
with pytest.raises(ValueError):
addon.register_source(_src("alpha"))
# --- ordering ---------------------------------------------------------------
def test_progressive_sources_are_offered_before_hls():
"""A progressive MP4 seeks natively. HLS on this stack does not -- that is
the whole subject of #4 -- so it goes second."""
addon.register_source(_src("hls-one", container="hls-fmp4"))
addon.register_source(_src("prog-one", container="progressive-mp4"))
assert [s.id for s in addon.ordered_sources()] == ["prog-one", "hls-one"]
def test_a_disabled_source_is_not_offered():
addon.register_source(_src("off", enabled=False))
assert addon.ordered_sources() == []
def test_ordering_is_stable_within_a_container_class():
for sid in ("a", "b", "c"):
addon.register_source(_src(sid))
assert [s.id for s in addon.ordered_sources()] == ["a", "b", "c"]
# --- the ingest guarantee ---------------------------------------------------
def test_a_browser_only_source_is_never_chosen_for_ingest():
"""THE point of this registry. vidlink sorts first on every visible merit --
progressive MP4, 3s resolve, exact sizes -- and ffmpeg cannot fetch a byte
of it. Ranking must not be able to override that."""
addon.register_source(_src("vidlink-like", container="progressive-mp4",
ingestable=False))
addon.register_source(_src("vidcore-like", container="hls-fmp4",
ingestable=True))
assert addon.ingest_source().id == "vidcore-like"
def test_no_ingestable_source_yields_none_rather_than_a_bad_choice():
addon.register_source(_src("browser-only", ingestable=False))
assert addon.ingest_source() is None
def test_a_non_ingestable_source_is_still_offered_for_playback():
"""It cannot feed the library, but it can still be watched -- withholding it
would remove a working way to play something."""
addon.register_source(_src("browser-only", ingestable=False))
assert [s.id for s in addon.ordered_sources()] == ["browser-only"]
def test_a_disabled_source_is_never_chosen_for_ingest():
addon.register_source(_src("off", ingestable=True, enabled=False))
assert addon.ingest_source() is None
# --- the real registry ------------------------------------------------------
# Not fixture-isolated: these assert what the addon actually ships with.
def test_vidcore_is_registered_as_the_live_source():
src = addon.SOURCES_DEFAULT["vidcore"]
assert src.enabled and src.ingestable
assert src.container == "hls-fmp4" # why every copy needs a remux
assert src.browser # ~11s, xvfb+patchright
def test_vidlink_is_recorded_as_measured_and_disabled():
"""Recorded rather than omitted: the next person to notice vidlink serves
progressive MP4 should find the measurement, not repeat it."""
src = addon.SOURCES_DEFAULT["vidlink"]
assert src.container == "progressive-mp4"
assert src.ingestable is False
assert not src.enabled
assert "428" in src.note or "proxy" in src.note.lower()
def test_the_dead_scrapers_are_recorded_as_disabled():
for sid in ("fmovies", "vsembed"):
assert addon.SOURCES_DEFAULT[sid].enabled is False
def test_the_shipped_registry_chooses_vidcore_for_ingest(monkeypatch):
monkeypatch.setattr(addon, "SOURCES", dict(addon.SOURCES_DEFAULT))
assert addon.ingest_source().id == "vidcore"
# --- the registry gates ingest ----------------------------------------------
def test_ingest_refuses_when_no_source_may_feed_the_library(monkeypatch, tmp_path):
"""If every ingestable source were disabled, ingest must decline outright
rather than resolve, download and then discover it cannot."""
monkeypatch.setattr(addon, "SOURCES", {})
called = []
monkeypatch.setattr(addon, "_library_meta",
lambda *a, **k: called.append(a) or None)
state = addon._run_ingest("series", "tmdb:1", 1, 1, 720)
assert state == "failed: no ingestable source"
assert called == [], "it must not even look the title up"