您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Inserts each YouTube video ID, title, and channel name into your Supabase table exactly once
当前为
// ==UserScript== // @name YouTube → Supabase Logger // @description Inserts each YouTube video ID, title, and channel name into your Supabase table exactly once // @match https://www.youtube.com/ // @run-at document-end // @version 0.0.1.20250508195644 // @namespace https://greasyfork.org/users/1435046 // ==/UserScript== (function() { 'use strict'; // Supabase configuration const SUPABASE_URL = 'https://haughsijawbsqwumuryg.supabase.co'; const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhhdWdoc2lqYXdic3F3dW11cnlnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzM0ODE3MjYsImV4cCI6MjA0OTA1NzcyNn0.stESUMuJEs4CNBWGtxZr1XNp2XpnQeXmKkq3fNaVE-c'; const TABLE = 'youtube_recommended_videos_table'; // Keep track of which IDs have already been sent const seen = new Set(); // Extracts the “v” parameter from a YouTube URL function getVideoId(href) { try { const u = new URL(href); return u.searchParams.get('v'); } catch { return null; } } // Posts a row with id, title, and channel name function insertVideoData(id, title, channel) { fetch(`${SUPABASE_URL}/rest/v1/${TABLE}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${SUPABASE_KEY}` }, body: JSON.stringify([{ video_id_column: id, video_title_column: title, video_channel_name_column: channel }]) }); } // Scan all video items on the page function logAndSend() { const ITEM_SELECTOR = 'ytd-video-renderer, ytd-grid-video-renderer, ytd-compact-video-renderer'; const TITLE_LINK_SEL = 'a#video-title-link'; const CHANNEL_SEL = 'ytd-channel-name a'; document.querySelectorAll(ITEM_SELECTOR).forEach(item => { const linkEl = item.querySelector(TITLE_LINK_SEL); if (!linkEl) return; const href = linkEl.href; const id = getVideoId(href); if (!id || seen.has(id)) return; seen.add(id); // Pull title from aria-label exactly as in your blocker script const title = linkEl.getAttribute('aria-label').trim() || '‹no title›'; // Pull channel name const chanEl = item.querySelector(CHANNEL_SEL); const channel = chanEl ? chanEl.textContent.trim() : '‹no channel›'; insertVideoData(id, title, channel); }); } // Initial scan logAndSend(); // Watch for new videos being loaded into the DOM new MutationObserver(logAndSend) .observe(document.body, { childList: true, subtree: true }); // Also re-scan after YouTube navigation events window.addEventListener('yt-navigate-finish', logAndSend); })();