您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Auto scroll YouTube Shorts with an ON/OFF switch and Config option
// ==UserScript== // @name Auto Scroll YouTube Shorts // @namespace https://gf.qytechs.cn/users/1308345-hellfiveosborn // @homepageURL https://gf.qytechs.cn/scripts/498319 // @supportURL https://gf.qytechs.cn/scripts/498319/feedback // @version 1.0 // @description Auto scroll YouTube Shorts with an ON/OFF switch and Config option // @date 2024-06-19 // @author HellFive Osborn // @match *://*.youtube.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_xmlhttpRequest // @compatible chrome // @compatible firefox // @compatible edge // @compatible brave // @compatible kiwi // @license MIT // ==/UserScript== (function () { 'use strict'; // Init CONFIG const config = { appName: 'Auto Scroll YouTube Shorts', appSymbol: '📺', keyPrefix: 'autoscrollytshorts', greasyForkURL: 'https://gf.qytechs.cn/scripts/498319-auto-scroll-youtube-shorts', updateUrl: 'https://update.gf.qytechs.cn/scripts/498319/Auto%20Scroll%20YouTube%20Shorts.meta.js' }; // Load TailwindCSS const tailwindCSS = ` @import url('https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css'); `; GM_addStyle(tailwindCSS); // Register the Config menu command const idMenu = GM_registerMenuCommand('Config', showConfigInterface); let autoScrollInterval; function showConfigInterface() { // Check if the interface already exists if (document.getElementById('autoScrollInterface')) { return; } // Create the interface const interfaceHTML = ` <div id="autoScrollInterface" class="fixed bottom-4 right-4 bg-gray-800 p-4 rounded-lg shadow-lg z-50 text-center"> <div class="flex justify-between items-center mb-2 relative"> <h1 class="text-gray-300 font-medium">YouTube Shorts Auto Scroll</h1> <button id="closeButton" class="text-gray-100 hover:bg-red-300 p-0 lh-0 bg-red-400 mt-0 absolute -right-5 -top-6 rounded-full w-5 h-5 leading-none">×</button> </div> <label class="flex items-center cursor-pointer justify-center"> <div class="relative"> <input id="autoScrollToggle" type="checkbox" class="sr-only" /> <div class="block bg-gray-600 w-14 h-8 rounded-full"></div> <div id="toggleDot" class="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div> </div> <div class="ml-3 text-gray-300 font-medium">Auto Scroll</div> </label> <div id="updateMessage" class="mt-2 text-gray-300"></div> <button id="updateButton" class="hidden mt-2 bg-blue-500 text-white p-2 rounded-full w-full">Update now 🚀</button> </div> `; document.body.insertAdjacentHTML('beforeend', interfaceHTML); // Toggle functionality const autoScrollToggle = document.getElementById('autoScrollToggle'); const toggleDot = document.getElementById('toggleDot'); const closeButton = document.getElementById('closeButton'); closeButton.addEventListener('click', () => { document.getElementById('autoScrollInterface').remove(); }); autoScrollToggle.addEventListener('change', function () { if (this.checked) { toggleDot.style.transform = 'translateX(100%)'; startAutoScroll(); GM_setValue('autoScroll', 'on'); closeButton.style.display = 'none'; } else { toggleDot.style.transform = 'translateX(0)'; stopAutoScroll(); GM_setValue('autoScroll', 'off'); closeButton.style.display = 'block'; } }); // Initialize based on GM_getValue const autoScrollStatus = GM_getValue('autoScroll', 'off'); if (autoScrollStatus === 'on') { autoScrollToggle.checked = true; toggleDot.style.transform = 'translateX(100%)'; startAutoScroll(); closeButton.style.display = 'none'; } else { autoScrollToggle.checked = false; toggleDot.style.transform = 'translateX(0)'; stopAutoScroll(); closeButton.style.display = 'block'; } // Handle visibility change document.addEventListener('visibilitychange', function () { if (autoScrollToggle.checked) { if (document.visibilityState === 'visible' || document.pictureInPictureElement) { startAutoScroll(); } else { stopAutoScroll(); } } }); // Check for updates updateCheck(); } function startAutoScroll() { console.log('Auto scroll started'); autoScrollInterval = setInterval(() => { const video = document.querySelector('video'); if (video) { video.loop = false; // Ensure loop is disabled if (video.duration > 0 && video.currentTime >= video.duration - 0.5) { console.log('Video finished, scrolling to next'); goToNextShort(); } } }, 1000); // Check every second } function stopAutoScroll() { console.log('Auto scroll stopped'); clearInterval(autoScrollInterval); } function goToNextShort() { const nextButtonContainer = document.querySelector('.navigation-container #navigation-button-down'); if (nextButtonContainer) { const nextButton = nextButtonContainer.querySelector('button'); if (nextButton) { nextButton.click(); console.log('Clicked next button'); } else { console.log('Next button not found inside container'); } } else { console.log('Next button container not found'); } } // Function to handle keydown events function handleKeyDown(event) { if (event.key === 'ArrowDown') { const video = document.querySelector('video'); if (video) { video.currentTime = video.duration; // Skip to the end of the video } } } // Update check function updateCheck() { const currentVer = GM_info.script.version; GM_xmlhttpRequest({ method: 'GET', url: config.updateUrl + '?t=' + Date.now(), headers: { 'Cache-Control': 'no-cache' }, onload: response => { const latestVer = /@version +(.*)/.exec(response.responseText)[1]; console.log('[Auto Scroll Youtube Shorts]', 'Current version:', currentVer, 'Latest:', latestVer) if (isOutdatedVersion(currentVer, latestVer)) { const updateMessage = document.getElementById('updateMessage'); const updateButton = document.getElementById('updateButton'); updateMessage.innerHTML = `There is an update available: v${latestVer}`; updateButton.classList.remove('hidden'); updateButton.addEventListener('click', () => { window.open(config.greasyForkURL, '_blank'); }); } } }); } function isOutdatedVersion(currentVer, latestVer) { const current = currentVer.split('.').map(Number); const latest = latestVer.split('.').map(Number); for (let i = 0; i < current.length; i++) { if (latest[i] > current[i]) return true; if (latest[i] < current[i]) return false; } return false; } // Add event listener for keydown events document.addEventListener('keydown', handleKeyDown); // Cleanup on script disable function cleanup() { stopAutoScroll(); const interfaceElement = document.getElementById('autoScrollInterface'); if (interfaceElement) { interfaceElement.remove(); } //GM_unregisterMenuCommand(idMenu); } // Observe script disable const observer = new MutationObserver(mutations => { for (const mutation of mutations) { if (mutation.removedNodes) { for (const node of mutation.removedNodes) { if (node.nodeType === 1 && node.id === 'autoScrollInterface') { cleanup(); } } } } }); observer.observe(document.body, { childList: true }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址