Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save udovichenko/295357dc6b504e4ce3dd540ad6c368a4 to your computer and use it in GitHub Desktop.
Save udovichenko/295357dc6b504e4ce3dd540ad6c368a4 to your computer and use it in GitHub Desktop.
Clean YouTube Watch Later Videos with Limit and Random Delay
(async function() {
const REMOVE_BUTTON_TEXT = 'Remove from Watch later'
// de-DE: const REMOVE_BUTTON_TEXT = 'Aus "Später ansehen" entfernen'
// pt-BR: const REMOVE_BUTTON_TEXT = 'Remover de Assistir mais tarde'
// swe-SE: const REMOVE_BUTTON_TEXT = 'Ta bort från Titta senare'
// zh-Hans-CN: const REMOVE_BUTTON_TEXT = '从稍后观看中移除'
// ru-RU: const REMOVE_BUTTON_TEXT = 'Удалить из плейлиста "Смотреть позже"'
const playlistName = document.querySelector('#title a').text
const limit = +prompt(`How many videos do you want to remove from ${playlistName}?`)
if (!limit) return
console.info('start...')
let count = 0
while (true) {
const videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
if (videos.length == 0) break
for (const videoElement of videos) {
const videoTitle = videoElement.querySelector('a#video-title')
console.info(`Remove Video\n` + ` Title: ${videoTitle.innerText}\n` + ` URL: ${videoTitle.href}`)
const actionMenuButton = videoElement.querySelector('#menu #button')
console.debug('click actionMenuButton', actionMenuButton)
actionMenuButton.click()
const removeButton = await untilDefined(() => {
for (const actionMenu of [...document.querySelectorAll('ytd-popup-container > tp-yt-iron-dropdown')]) {
if ((actionMenu) => actionMenu.style.display !== 'none') {
for (const actionButton of [...actionMenu.querySelectorAll('tp-yt-paper-item')]) {
if (actionButton.innerText.trim().toLowerCase() === REMOVE_BUTTON_TEXT.toLowerCase()) {
return actionButton
}
}
}
}
console.debug('wait for removeButton')
})
console.debug('click removeButton', removeButton)
removeButton.click()
count++
if (count >= limit) break
const randDelay = 1000 + Math.random() * 400
await sleep(randDelay)
}
if (count >= limit) break
}
console.info('done!')
// === util functions ========================================================
async function sleep(timeout) {
return new Promise((res) => setTimeout(res, timeout))
}
async function untilDefined(factory, checkInterval = 100) {
while (true) {
const value = factory()
if (value != null) return value
await sleep(checkInterval)
}
}
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment