#!/usr/bin/env python3 """ Inject the ARRFLIX runtime branding shim into web-overrides/index.html. Idempotent: if the shim is already present, exits 0 with a notice. """ import sys, pathlib, re ROOT = pathlib.Path(__file__).resolve().parent.parent TARGET = ROOT / "web-overrides" / "index.html" MARKER_BEGIN = "/* ARRFLIX-SHIM-BEGIN */" MARKER_END = "/* ARRFLIX-SHIM-END */" SHIM = MARKER_BEGIN + r""" (function(){ var TITLE = 'ARRFLIX'; var BARE_RE = /^Jellyfin$/i; /* === English-lockdown (synchronous, runs before Jellyfin bundle) === Pins UI locale to en-US so the SPA never reads navigator.language or the user's stored preference. Belt-and-braces against: - localStorage keys the SPA reads on boot - navigator.language / navigator.languages getters - fetch / XHR Accept-Language header (best-effort; most browsers block JS from setting it, but Jellyfin sometimes does) - user-config save round-trip (rewrite UICulture → en-US before send) */ try { var LS_KEYS = ['appLanguage','selectedlanguage','selectedlocale','language','locale','culture']; for (var i=0;i" def main(): html = TARGET.read_text(encoding="utf-8") if MARKER_BEGIN in html: # Replace the existing shim block in place pattern = re.compile(r"", re.DOTALL) # Use a callable replacement to bypass backreference parsing in WRAPPED new_html, n = pattern.subn(lambda _m: WRAPPED, html, count=1) if n != 1: print("ERROR: shim markers present but could not match for replacement", file=sys.stderr) sys.exit(2) TARGET.write_text(new_html, encoding="utf-8") print(f"Replaced existing shim ({len(WRAPPED)} chars).") return # Insert immediately after needle = "" idx = html.find(needle) if idx < 0: print("ERROR: not found in target", file=sys.stderr) sys.exit(1) insert_at = idx + len(needle) new_html = html[:insert_at] + WRAPPED + html[insert_at:] TARGET.write_text(new_html, encoding="utf-8") print(f"Inserted shim ({len(WRAPPED)} chars) after at offset {insert_at}.") if __name__ == "__main__": main()