resources/lib/__init__.py — shared helpers
Role
The companion module that makes from resources.lib import
work. Holds the cross-module constants (INPUTSTREAM_PROP,
INPUTSTREAM_ADDON), the cached provider-map loader, the DASH
listitem configurator, and a couple of small utility functions used
everywhere.
Constants
The Kodi listitem property name and the addon ID of the
inputstream.adaptive addon. Used by
setup_dash_item() on every playable
item; never re-string these in provider code.
Cached xbmcaddon.Addon("plugin.video.easyplaytv"), its writable
profile directory, and the path to provider_map.json inside
that profile. Used by load/save_provider_map().
Provider-map persistence
Reads provider_map.json from the addon profile dir. Caches
the result in module globals keyed on the file's mtime — re-reads only if
the file has been touched. Returns {} on any error, never raises.
The map's shape is {safe_title: {provider, f_name|pid|slug, ...}}
and is used by library_sync.prefix_existing_tvshows()
to retrofit the [PROVIDER] prefix onto rows that lack it.
Writes the map atomically (json.dump) and refreshes the in-memory cache. Silently swallows errors — losing the map is recoverable on the next sync.
Utilities
Replaces / \\ : * ? " < > | with spaces and strips.
Used everywhere a Kodi-show title is going to become a folder name or a
file table row's strFilename.
The shared HTTP GET used by every scraper module. Sends
Accept-Encoding: gzip, deflate, decompresses gzip transparently
if the server used it. Returns a UTF-8 string (with errors="ignore"
so encoding sniffing never breaks a fetch). Used by BBC, ITVX, C4, STV,
Blaze scrapers.
Each call opens a fresh urllib.request.urlopen with no cookie
jar. Provider modules that need cookies (ITVX auth, My5 corona) manage their
own requests.Session or http.cookiejar — see
itvx.py for the only example.
Returns System.HasAddon(inputstream.adaptive) via Kodi's
condition visibility. Used by default.py:resolve_live
as a sanity check before attempting DASH playback (the resolver still
short-circuits with a notification dialog if the addon's missing).
Reads the max_resolution addon setting (0/480/720/1080) and
returns a Kodi inputstream.adaptive.chooser_resolution_max value
or None for "no cap". Used by
setup_dash_item() so the user's cap is enforced on every DASH
manifest without each provider having to read the setting itself.
setup_dash_item — the DASH configurator
The workhorse. Sets every inputstream.adaptive listitem
property in the right shape for Kodi to hand off to the adaptive addon:
IsPlayable=true·inputstream=inputstream.adaptive- Resolution cap via
get_max_resolution()unless caller overrides withmax_resolution= - If
license_urlis set:license_type=com.widevine.alpha+ a pipe-delimitedlicense_keytuple assembled aslicense_url | license_headers | (license_payload or "R{SSM}") | (license_payload and "JBlicense" or "R"). The two terminal tokens tell IA whether to POST the payload as-is (JBlicense) or to use a raw challenge response (R). - Pass-through headers for manifest / stream fetches (e.g. STV's
stv-drm: trueheader, ITVX'sAuthorization: Bearer …). play_timeshift_buffer=truewhen caller requeststimeshift=True(used by live channels that expose a rewind buffer).listitem.setPath(manifest_url)as the final step.
The resolution cap is set before the license fields — IA reads the
chooser_resolution_max property at directory-list-build time,
before it opens the manifest, so setting it after the license key has no
effect. Don't reorder.
When license_payload is provided (My5 Cassie case — see
my5.py) the trailing token is
JBlicense, meaning the payload is sent verbatim as the body.
Without it, the trailing token is R and IA uses the
{SSM} placeholder to substitute the Widevine service
certificate into the request body. C4 and ITVX use the placeholder paths;
My5 is the only one that pre-builds a payload.
Server/client role detection
Legacy: returned _ADDON.getSettingInt("db_source") == 0 to
decide whether to schedule syncs (master) or skip them (follower). The
master/follower role lived in the Service addon's db_source
setting and is gone today — the Service addon is always a server, and
client boxes configure pvr.iptvsimple via the video addon's
PVR server URL setting instead. The Video addon's
pvr_enabled flag now only hides its own Live TV menu item when
a PVR server is configured.
get_ua — the shared User-Agent
One Chrome 131 on Win64 UA string used by every scraper via
fetch_url(url). Hard-coded rather than read from a setting
because some providers (notably C4) UA-sniff and reject Roku/Android
strings — keeping it desktop-Chrome-shaped avoids the sniff without
exposing a knob.