您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Delete videos that you watch 90 or more percent (with mobile support)
当前为
// ==UserScript== // @name Watch later: Better remove watched // @namespace shiftgeist // @icon https://www.youtube.com/s/desktop/50798525/img/logos/favicon_144x144.png // @match *://*.youtube.com/* // @grant none // @version 20250227.2 // @author shiftgeist // @description Delete videos that you watch 90 or more percent (with mobile support) // @license GNU GPLv3 // ==/UserScript== (async function () { 'use strict' const debug = window.localStorage.getItem('better-remove-watched-debug') === 'true' const threshold = Number(window.localStorage.getItem('better-remove-watched-threshold') || 90) const mobile = window.location.href.includes('m.youtube.com') const doc = window.document const attachmentPoint = mobile ? '.playlist-immersive-header-content .amsterdam-playlist-header-metadata-wrapper' : '.metadata-buttons-wrapper.ytd-playlist-header-renderer' let timeout = null let button = null function log(...params) { if (debug) { console.debug('[Clean]', ...params) } } function createButton() { if (button) { log('remove button first') button.remove() } button = document.createElement('button') button.textContent = 'Remove fully watched' button.title = 'Visible videos watched 90% or more' button.classList = 'yt-spec-button-shape-next yt-spec-button-shape-next--tonal yt-spec-button-shape-next--overlay yt-spec-button-shape-next--size-m' document.querySelector(attachmentPoint).appendChild(button) if (mobile) { button.style.marginTop = '8px' } button.addEventListener('click', clickHandler) button.addEventListener('auxclick', clickHandler) log('Button created') } function handleDropdownClick() { const parent = document.querySelector( 'ytd-popup-container tp-yt-iron-dropdown tp-yt-paper-listbox' ) log('handle dropdown click', parent) if (parent) { parent.children[2].click() } else { setTimeout(handleDropdownClick, 100) } } function removeFromWatched(video) { log('Removing video', video) video.querySelector('#button').click() handleDropdownClick() } function clickHandler(event) { log('button clicked') const videos = Array.from(document.querySelectorAll('ytd-playlist-video-renderer')) log('Found', videos.length, 'videos') videos.forEach(v => { const watchBar = v.querySelector('#progress') if (watchBar) { const percent = Number(watchBar.style.width.replace('%', '')) const t = v.innerText.replaceAll('\n', '') log(t.slice(t.indexOf('Now playing') + 11), percent) if (percent >= threshold) { removeFromWatched(v) } } }) } let checkCount = 0 function waitForLoad(query, callback) { log('wait for load') const search = new URLSearchParams(window.location.href) if ( !( window.location.href.includes('youtube.com/playlist') && window.location.search.includes('list=WL') ) ) { log('Not on watch later playlist') return } if (checkCount > 99) { log('Check count > 99') return } if (document.querySelector(query)) { checkCount = 0 callback() } else { checkCount += 1 const waitTime = 100 * checkCount * checkCount log('time until check is', waitTime) timeout = setTimeout(waitForLoad.bind(null, query, callback), waitTime) } } function init() { console.debug( '[Clean] Config: debug', debug, 'threshold', threshold, 'mobile', mobile, 'attachmentPoint', attachmentPoint ) waitForLoad(attachmentPoint, createButton) } function handlePageChange(event) { log('page change event fired', event.type, window.location.href) init() if (timeout) { clearTimeout(timeout) } } window.addEventListener('yt-page-data-updated', handlePageChange) init() })()
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址