-
Notifications
You must be signed in to change notification settings - Fork 2
CineInfo Sources
CineInfo Sources are the extension point that lets a third-party module add its own CineInfo data (ratings, providers, custom fields, ...) on top of the built-in TMDB lookup — without any change to the core. Where a provider pill only shows a small availability badge, a source feeds real fields into the CineInfo lookups themselves.
The core stays authoritative: sources are layered on top of the TMDB result, and with no source registered the whole mechanism is a zero-cost pass-through.
Every source declares a single capability flag, and the orchestrator picks the fetch form automatically — there is no user setting for this:
supports_bulk |
The orchestrator calls | Meaning | Use for |
|---|---|---|---|
False |
fetch_one(item, ctx) per item |
"einzeln nach und nach" — one request per item, looped with bounded concurrency | Upstreams that answer one lookup per request (e.g. TMDB) |
True |
fetch_many(items, ctx) per chunk |
"alles in einer Anfrage" — one request for up to max_bulk items |
Upstreams with a real batch endpoint |
Both forms run through the same cache + rate-limit + de-duplication layer, so a source never implements batching, caching or throttling itself.
from ...cineinfo.source import CineInfoSource, QueryContext
from ...db import get_setting
class MySource(CineInfoSource):
id = "myprovider" # stable; also cache namespace + rate-limiter bucket
label = "My Provider"
supports_bulk = False # ← the entire batch-form decision
rate = 5.0 # max upstream requests/second
cache_ttl = 86400.0 # provider-cache TTL in seconds (0 = no cache)
def is_enabled(self) -> bool:
# Follow your own toggle: a disabled module stops contributing at
# once. (Uninstall is handled by the item_id you pass below.)
return get_setting("myprovider_enabled", "0") == "1"
def fetch_one(self, item: dict, ctx: QueryContext) -> dict:
# item carries a stable "key" plus lookup fields
# (title / imdb_id / tmdb_id). ctx.country and ctx.ui_lang are resolved.
# Return only the fields you actually know.
...
return {"vote_average": 8.1, "myprovider_url": "https://..."}A bulk source instead implements fetch_many(items, ctx) and returns
{item["key"]: payload} for the whole chunk in one request.
From your module's register(app):
from ...cineinfo.registry import register_cineinfo_source
register_cineinfo_source(MySource(), item_id=MODULE_ID)Register one instance per source. You can register several (e.g. one per batch form).
item_id is the id you already passed to register_thirdparty(). It is
optional only so modules written against the first version of this API keep
working — always pass it. Without it the source still works, but:
- the Modulmanager cannot attribute it, so the module's capability line under- reports what it does (this is exactly why a CineInfo module used to show nothing but "1 × settings card"), and
-
unregister_module()cannot drop it, so an uninstalled module's source stays registered for the rest of the process' life — kept harmless only by its ownis_enabled(), which is reading a setting that no longer exists.
With item_id passed, the module manager shows 1 × CineInfo source (or 2 ×
for a module registering both batch forms) and uninstalling really removes it.
A registered source is not invisible plumbing:
-
Module manager lists it as
1 × CineInfo sourceamong the module's capabilities (that is whatitem_idis for, see above). -
Integrations → CineInfo → "Source order" lists it as a draggable row with
a "Module" badge, next to the provider pills. That list is one setting
(
cineinfo_provider_order) holding two kinds of entry —ci:<source id>for a CineInfo source,ext:<name>/bare ids for provider pills — and each consumer reads only its own prefix. The position you drag a source to is the orderenrich()applies it in: the first source that knows a field fills it, and the built-in TMDB base still beats every source. With nothing configured the old alphabetical-by-idorder applies, unchanged. - Module Settings (under the Module Manager) and Integrations → Third Party both list the module's settings card even though its home is the CineInfo tab — same card, same API, same edit.
The core CineInfo endpoints (/api/tmdb/info, /api/tmdb/batch) call
cineinfo.enrich(...), which runs every enabled source and field-merges
its payload onto the TMDB base:
- The built-in TMDB data wins. A source only fills fields TMDB is missing or left empty, plus any custom fields of its own.
- Sources are applied in stable
idorder for deterministic results. -
0/Falseare valid values and are preserved (not treated as "empty").
Cache-first (only cache-misses hit the network, via the shared provider_cache
table), a per-source token-bucket rate limiter, in-flight de-duplication of
concurrent identical lookups, bounded concurrency, per-query timeouts, and error
isolation — a failing item or source never takes CineInfo down.
See .examples/thirdparties/example_cineinfo_source/ for a complete,
offline-safe module that registers one source of each batch form under the
CineInfo settings tab. The plug-in system itself is documented in
.examples/thirdparties/README.md.
🇬🇧 English
Users
- Installation
- Getting Started
- Migration from AniWorld
- Configuration
- Web UI
- Download System
- Download History
- AutoSync
- Calendar
- Library
- Authentication
- Notifications
- Integrations
- SyncPlay
- Anime4K Upscaling
- Encoding
- Modules
- Theme Packs
- Backup
- Docker
- Supported Sites
Developers
🇩🇪 Deutsch
Benutzer
- Installation
- Erste Schritte
- Umzug von AniWorld
- Konfiguration
- Web-UI
- Download-System
- Download-Verlauf
- AutoSync
- Kalender
- Bibliothek
- Authentifizierung
- Benachrichtigungen
- Integrationen
- SyncPlay
- Anime4K-Upscaling
- Encoding
- Module
- Theme-Pakete
- Backup
- Docker
- Unterstützte Seiten
Entwickler