(() => { const BASE_PATH = window.location.pathname.split("/web/")[0] || ""; const MENU_ID = "mlUserRulesMenuItem"; const USER_RULES_ROUTE = "multilang/user-rules"; let lastMenuItemId = ""; let userRulesRenderRun = 0; function getClientToken() { try { return window.ApiClient?.accessToken?.() || ""; } catch (_) { return ""; } } function hashParts() { const raw = (location.hash || "").replace(/^#\/?/, ""); const queryIndex = raw.indexOf("?"); const path = (queryIndex >= 0 ? raw.slice(0, queryIndex) : raw).toLowerCase(); const query = queryIndex >= 0 ? raw.slice(queryIndex + 1) : ""; return { path, params: new URLSearchParams(query) }; } function getCurrentUserId() { const fromHash = hashParts().params.get("userId"); if (fromHash) return fromHash; try { return window.ApiClient?.getCurrentUserId?.() || ""; } catch (_) { return ""; } } function userRulesHref() { const params = new URLSearchParams(); const userId = getCurrentUserId(); if (userId) params.set("userId", userId); params.set("multilang", "1"); return `${BASE_PATH}/web/#/${USER_RULES_ROUTE}?${params.toString()}`; } function isUserRulesRoute() { const parts = hashParts(); return parts.path === USER_RULES_ROUTE && parts.params.get("multilang") === "1"; } function pathSegments(pathname) { return String(pathname || "") .toLowerCase() .split("/") .filter(Boolean); } function looksLikeItemId(value) { return /^[0-9a-f]{32}$/.test(value) || /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(value); } function isUserItemsEndpoint(segments) { const usersIndex = segments.lastIndexOf("users"); if (usersIndex < 0 || segments[usersIndex + 2] !== "items") return false; const tail = segments.slice(usersIndex + 3); if (tail.length === 0) return true; if (tail.length !== 1) return false; return looksLikeItemId(tail[0]) || tail[0] === "latest" || tail[0] === "resume" || tail[0] === "nextup"; } function isRootItemsEndpoint(segments) { const itemsIndex = segments.lastIndexOf("items"); if (itemsIndex < 0) return false; const tail = segments.slice(itemsIndex + 1); if (tail.length === 0) return true; if (tail.length !== 1) return false; return looksLikeItemId(tail[0]) || tail[0] === "latest" || tail[0] === "resume" || tail[0] === "nextup"; } function isShowsListEndpoint(segments) { const showsIndex = segments.lastIndexOf("shows"); if (showsIndex < 0) return false; const tail = segments.slice(showsIndex + 1); if (tail.length === 1) return tail[0] === "nextup"; if (tail.length === 2 && looksLikeItemId(tail[0])) return tail[1] === "episodes" || tail[1] === "seasons"; return false; } function isGenresEndpoint(segments) { const genresIndex = segments.lastIndexOf("genres"); if (genresIndex < 0) return false; const tail = segments.slice(genresIndex + 1); return tail.length === 0 || (tail.length === 1 && looksLikeItemId(tail[0])); } function shouldProxyEndpoint(pathname) { const segments = pathSegments(pathname); return isUserItemsEndpoint(segments) || isRootItemsEndpoint(segments) || isShowsListEndpoint(segments) || isGenresEndpoint(segments); } function getItemsProxyUrl(urlInput) { const url = urlInput instanceof Request ? urlInput.url : String(urlInput || ""); if (!url) return null; const u = new URL(url, window.location.origin); if (u.origin !== window.location.origin) return null; const lower = u.pathname.toLowerCase(); if (lower.includes("/multilang/")) return null; if (lower.includes("/images/") || lower.endsWith("/images")) return null; if (!shouldProxyEndpoint(u.pathname)) return null; const locale = document.documentElement?.lang?.trim() || navigator.language || ""; const token = getClientToken(); const tokenParam = token ? `&token=${encodeURIComponent(token)}` : ""; const localeParam = locale ? `&mlLocale=${encodeURIComponent(locale)}` : ""; return `${BASE_PATH}/Multilang/ItemsProxy?url=${encodeURIComponent(`${u.pathname}${u.search}`)}${localeParam}${tokenParam}`; } function ensureUserRulesLink() { let menuItem = document.getElementById(MENU_ID); if (!(location.hash || "").toLowerCase().includes("mypreferences")) { menuItem?.remove(); return; } const href = userRulesHref(); if (menuItem) { menuItem.href = href; wireUserRulesLink(menuItem); return; } const links = [...document.querySelectorAll('a[href^="#/mypreferences"]')]; const insertAfter = links[links.length - 1]; if (!insertAfter) return; const cloned = insertAfter.cloneNode(true); cloned.id = MENU_ID; cloned.dataset.mlUserRulesLink = "1"; cloned.href = href; cloned.removeAttribute("title"); cloned.removeAttribute("aria-label"); [...cloned.classList] .filter((c) => c.startsWith("lnk")) .forEach((c) => cloned.classList.remove(c)); const textEl = cloned.querySelector(".listItemBodyText"); if (textEl) textEl.textContent = "Metadata language rules"; cloned.querySelectorAll(".material-icons").forEach((el) => el.remove()); const iconEl = document.createElement("span"); iconEl.className = "material-icons listItemIcon listItemIcon-transparent translate"; iconEl.setAttribute("aria-hidden", "true"); (cloned.querySelector(".listItemBody") || cloned).before(iconEl); wireUserRulesLink(cloned); insertAfter.parentElement.insertBefore(cloned, insertAfter.nextSibling); } function wireUserRulesLink(link) { if (link.dataset.mlUserRulesClick === "1") return; link.dataset.mlUserRulesClick = "1"; link.addEventListener("click", (event) => { openUserRulesPage(event); }, true); } function visiblePage() { const pages = [...document.querySelectorAll(".mainAnimatedPage, .page")]; return pages.reverse().find((page) => { if (page.closest("#ml-user") || page.classList.contains("hide")) return false; const style = window.getComputedStyle(page); return style.display !== "none" && style.visibility !== "hidden"; }); } function userRulesHost() { return ensureUserRulesShell().querySelector("#ml-user-host"); } function ensureUserRulesShell() { let shell = document.getElementById("ml-user-shell"); if (shell) { positionUserRulesShell(shell); shell.hidden = false; return shell; } shell = document.createElement("div"); shell.id = "ml-user-shell"; shell.className = "mainAnimatedPage type-interior page"; shell.style.position = "fixed"; shell.style.left = "0"; shell.style.right = "0"; shell.style.bottom = "0"; shell.style.zIndex = "100"; shell.style.overflow = "auto"; shell.style.background = "var(--theme-body-bg, var(--background-color, #101010))"; shell.style.color = "inherit"; const host = document.createElement("div"); host.id = "ml-user-host"; host.className = "content-primary"; shell.appendChild(host); document.body.appendChild(shell); positionUserRulesShell(shell); return shell; } function positionUserRulesShell(shell) { const header = document.querySelector(".skinHeader, .headerTop, header"); const top = header ? Math.max(0, Math.round(header.getBoundingClientRect().bottom)) : 0; shell.style.top = `${top}px`; } function closeUserRulesShellIfInactive() { if (isUserRulesRoute()) return; document.getElementById("ml-user-shell")?.remove(); } function openUserRulesPage(event) { event?.preventDefault?.(); event?.stopPropagation?.(); event?.stopImmediatePropagation?.(); history.pushState({}, "", userRulesHref()); scheduleUserRulesPageRender(); } function handleUserRulesClick(event) { const link = event.target?.closest?.(`#${MENU_ID}, [data-ml-user-rules-link='1'], a[href*="multilang=1"]`); if (!link) return; openUserRulesPage(event); } function executeScript(script) { return new Promise((resolve, reject) => { const next = document.createElement("script"); [...script.attributes].forEach((attr) => next.setAttribute(attr.name, attr.value)); if (script.src) { next.onload = () => resolve(); next.onerror = () => reject(new Error(`Failed to load ${script.src}`)); next.src = script.src; } else { next.text = script.textContent || ""; } document.body.appendChild(next); if (!script.src) resolve(); }); } async function renderUserRulesPage(run) { if (!isUserRulesRoute() || run !== userRulesRenderRun) return; const host = userRulesHost(); if (!host) return; if (host.dataset.mlUserRulesRendered === "1" && document.getElementById("ml-user")) return; host.dataset.mlUserRulesRendered = "1"; host.innerHTML = "