您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hide any recommended videos whose IDs already exist in your Supabase table, and log those IDs
// ==UserScript== // @name YouTube → Supabase Deduplicator & Blocker (with ID logging) // @description Hide any recommended videos whose IDs already exist in your Supabase table, and log those IDs // @match https://www.youtube.com/* // @run-at document-end // @version 0.0.1.20250510181837 // @namespace https://gf.qytechs.cn/users/1435046 // ==/UserScript== (function () { 'use strict'; // 1. Supabase configuration const SUPABASE_URL = 'https://haughsijawbsqwumuryg.supabase.co'; const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhhdWdoc2lqYXdic3F3dW11cnlnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzM0ODE3MjYsImV4cCI6MjA0OTA1NzcyNn0.stESUMuJEs4CNBWGtxZr1XNp2XpnQeXmKkq3fNaVE-c'; const TABLE = 'youtube_recommended_videos_table'; const ID_COLUMN = 'video_id_column'; // 2. Skip search/results or channel pages if (location.pathname.startsWith('/results') || location.pathname.startsWith('/@')) { return; } // 3. Data structures & selectors const existingIds = new Set(); const ITEM_SELECTOR = 'ytd-rich-item-renderer'; /*, ytd-rich-grid-media, ytd-video-renderer*/ const TITLE_LINK_SEL = 'a#video-title-link'; // 4. Utility to extract ?v= from a link function getVideoId(href) { try { const url = new URL(href); return url.searchParams.get('v'); } catch { return null; } } // 5. Hide one item if its ID is in existingIds function filterItem(item) { const linkEl = item.querySelector(TITLE_LINK_SEL); if (!linkEl) return; const id = getVideoId(linkEl.href); if (id && existingIds.has(id)) { item.style.display = 'none'; //item.textContent = 'This video was blocked because it was found in the Supabase database.'; //item.style.color = 'gray'; } } // 6. Scan all current items function scanPage() { document.querySelectorAll(ITEM_SELECTOR).forEach(filterItem); } // 7. Fetch existing IDs from Supabase and log them async function fetchExistingIds() { const url = `${SUPABASE_URL}/rest/v1/${TABLE}?select=${ID_COLUMN}`; const res = await fetch(url, { headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${SUPABASE_KEY}` } }); if (!res.ok) { console.error('Failed to fetch existing IDs:', res.status, res.statusText); return; } const rows = await res.json(); for (const row of rows) { if (row[ID_COLUMN]) { existingIds.add(row[ID_COLUMN]); } } // Log the imported IDs console.log('Imported video IDs from Supabase:', Array.from(existingIds)); } // 8. Initialization (async () => { await fetchExistingIds(); scanPage(); // 9. Watch for newly added nodes (infinite scroll, dynamic loading) new MutationObserver(mutations => { const path = location.pathname; if (path.startsWith('/results') || path.startsWith('/@')) return; for (const { addedNodes } of mutations) { for (const node of addedNodes) { if (!(node instanceof HTMLElement)) continue; if (node.matches(ITEM_SELECTOR)) { filterItem(node); } else if (node.querySelectorAll) { node.querySelectorAll(ITEM_SELECTOR).forEach(filterItem); } } } }).observe(document.body, { childList: true, subtree: true }); // 10. Also re-scan after YouTube navigation window.addEventListener('yt-navigate-finish', () => { const path = location.pathname; if (path.startsWith('/results') || path.startsWith('/@')) return; scanPage(); }); })(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址