Watch later: Better remove watched

Delete videos that you watch 90 or more percent.

目前为 2025-02-27 提交的版本。查看 最新版本

// ==UserScript==
// @name        Watch later: Better remove watched
// @namespace   shiftgeist
// @icon        https://www.youtube.com/s/desktop/50798525/img/logos/favicon_144x144.png
// @match       https://www.youtube.com/*
// @grant       none
// @version     20250227
// @author      shiftgeist
// @description Delete videos that you watch 90 or more percent.
// @license     GNU GPLv3
// ==/UserScript==

(async function () {
  'use strict'

  const debug = true
  const doc = window.document
  const threshold = Number(window.localStorage.getItem('better-remove-watched') || 90)

  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('.metadata-buttons-wrapper.ytd-playlist-header-renderer').appendChild(button)

    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')

      if (!window.location.href.includes('youtube.com/playlist?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)
      }
  }

  const elementToWaitFor = '.metadata-buttons-wrapper.ytd-playlist-header-renderer'

  function init() {
    log('threshold is', threshold)

    waitForLoad(elementToWaitFor, 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或关注我们的公众号极客氢云获取最新地址