您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Kiss the annoying "Video paused. Continue watching?" confirmation goodbye!
// ==UserScript== // @name Yes Continue // @namespace http://tampermonkey.net/ // @version 1.0.0 // @description Kiss the annoying "Video paused. Continue watching?" confirmation goodbye! // @author elliottophellia // @license GPL-3.0 // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com // @homepageURL https://github.com/elliottophellia/yescontinue // @supportURL https://github.com/elliottophellia/yescontinue/issues // @match https://www.youtube.com/* // @match https://music.youtube.com/* // @run-at document-idle // @compatible chrome // @compatible firefox // @compatible opera // @compatible edge // ==/UserScript== (async () => { 'use strict'; const tag = '[Yes Continue]'; const isYoutubeMusic = window.location.hostname === 'music.youtube.com'; const popupEventNodename = isYoutubeMusic ? 'YTMUSIC-YOU-THERE-RENDERER' : 'YT-CONFIRM-DIALOG-RENDERER'; const MutationObserver = window.MutationObserver || window.WebKitMutationObserver; const appName = isYoutubeMusic ? 'ytmusic-app' : 'ytd-app'; const popupContainer = isYoutubeMusic ? 'ytmusic-popup-container' : 'ytd-popup-container'; const pauseRequestedTimeoutMillis = 5000; const idleTimeoutMillis = 5000; let appObserver = null; let pauseRequested = false; let pauseRequestedTimeout; let lastInteractionTime = Date.now(); let videoElement = null; const log = message => console.log(`${tag}[${getTimestamp()}] ${message}`); const debug = message => console.debug(`${tag}[${getTimestamp()}] ${message}`); const asDoubleDigit = value => value < 10 ? `0${value}` : value; const getTimestamp = () => { const dt = new Date(); return `${asDoubleDigit(dt.getHours())}:${asDoubleDigit(dt.getMinutes())}:${asDoubleDigit(dt.getSeconds())}`; }; const isIdle = () => Date.now() - lastInteractionTime >= idleTimeoutMillis; const listenForMediaKeys = () => { if (!navigator.mediaSession) { log("Your browser doesn't seem to support navigator.mediaSession yet :/"); return; } navigator.mediaSession.setActionHandler('pause', pauseVideo); navigator.mediaSession.yns_setActionHandler = navigator.mediaSession.setActionHandler; navigator.mediaSession.setActionHandler = (action, fn) => { if (action !== 'pause') { navigator.mediaSession.yns_setActionHandler(action, fn); } }; }; const listenForMouse = () => { const eventName = window.PointerEvent ? 'pointer' : 'mouse'; ['down', 'up'].forEach(type => document.addEventListener(`${eventName}${type}`, () => processInteraction(`${eventName}${type}`)) ); }; const listenForKeyboard = () => { ['keydown', 'keyup'].forEach(type => document.addEventListener(type, () => processInteraction(type)) ); }; const processInteraction = action => { if (pauseRequested) { pauseVideo(); return; } lastInteractionTime = Date.now(); }; const observeApp = () => { appObserver = new MutationObserver(overrideVideoPause); appObserver.observe(document.querySelector(appName), { childList: true, subtree: true }); }; const listenForPopupEvent = () => { document.addEventListener('yt-popup-opened', (e) => { if (isIdle() && e.detail.nodeName === popupEventNodename) { document.querySelector(popupContainer).click(); pauseVideo(); videoElement?.play(); } }); }; const overrideVideoPause = () => { if (videoElement?.yns_pause !== undefined) return; videoElement = document.querySelector('video'); if (!videoElement) return; listenForMediaKeys(); videoElement.yns_pause = videoElement.pause; videoElement.pause = () => { if (!isIdle()) { pauseVideo(); return; } pauseRequested = true; setPauseRequestedTimeout(); }; }; const setPauseRequestedTimeout = (justClear = false) => { clearTimeout(pauseRequestedTimeout); if (!justClear) { pauseRequestedTimeout = setTimeout(() => { pauseRequested = false; }, pauseRequestedTimeoutMillis); } }; const pauseVideo = () => { videoElement?.yns_pause(); pauseRequested = false; setPauseRequestedTimeout(true); }; const waitForApp = () => { return new Promise(resolve => { const checkApp = () => { if (document.querySelector(appName)) { resolve(); } else { setTimeout(checkApp, 100); } }; checkApp(); }); }; await waitForApp(); listenForMouse(); listenForKeyboard(); listenForPopupEvent(); observeApp(); log(`Monitoring YouTube ${isYoutubeMusic ? 'Music ' : ''}for 'Video paused. Continue watching?' action...`); })();