let whitelist = []; let debugEnabled = false; /* ---------------- CSS injection ---------------- */ function injectStyleOnce() { if (document.getElementById("member-filter-style")) return; const style = document.createElement("style"); style.id = "member-filter-style"; style.textContent = ` [data-member-filter-hidden="true"] { display: none !important; } `; document.head.appendChild(style); } injectStyleOnce(); /* ---------------- load whitelist ---------------- */ function debugLog(...args) { if (!debugEnabled) return; console.log("[MemberFilter]", ...args); } function loadSettings() { chrome.storage.local.get({ whitelist: [], debug: false }, data => { whitelist = data.whitelist.map(n => n.toLowerCase()); debugEnabled = Boolean(data.debug); debugLog("settings loaded:", { whitelist, debugEnabled }); process(); }); } loadSettings(); // Reload settings if popup changes them chrome.storage.onChanged.addListener(loadSettings); /* ---------------- detection logic ---------------- */ function isMemberOnly(video) { const badges = video.querySelectorAll("badge-shape"); for (const badge of badges) { if (badge.textContent?.includes("Nur für Kanalmitglieder")) { return true; } } return false; } function process(root = document) { const selector = "ytd-rich-item-renderer, ytd-video-renderer, ytd-grid-video-renderer"; const videos = root.querySelectorAll(selector); const rootIsVideo = root instanceof HTMLElement && root.matches && root.matches(selector); const allVideos = rootIsVideo ? [root, ...videos] : Array.from(videos); allVideos.forEach(video => { const titleEl = video.querySelector("#video-title"); const channelEl = video.querySelector("ytd-channel-name a") || video.querySelector(".ytd-channel-name a"); const channel = channelEl?.textContent?.trim() ?? ""; const channelKey = channel.toLowerCase(); const whitelisted = whitelist.includes(channelKey); const memberOnly = isMemberOnly(video); if (debugEnabled) { const title = titleEl?.textContent?.trim() ?? "(no title)"; const url = titleEl?.href ?? "(no url)"; console.group("[MemberFilter]"); console.log("Title :", title); console.log("Channel:", channel || "(no channel)"); console.log("URL :", url); console.log("MemberOnly:", memberOnly); console.log("Whitelisted:", whitelisted); console.groupEnd(); } if (memberOnly && !whitelisted) { video.setAttribute("data-member-filter-hidden", "true"); } else { video.removeAttribute("data-member-filter-hidden"); } }); } /* ---------------- initial + observer ---------------- */ process(); const observer = new MutationObserver(mutations => { for (const m of mutations) { for (const node of m.addedNodes) { if (node instanceof HTMLElement) { process(node); } } } }); observer.observe(document.body, { childList: true, subtree: true });