Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save udovichenko/295357dc6b504e4ce3dd540ad6c368a4 to your computer and use it in GitHub Desktop.

Select an option

Save udovichenko/295357dc6b504e4ce3dd540ad6c368a4 to your computer and use it in GitHub Desktop.

Revisions

  1. udovichenko revised this gist Feb 10, 2023. 1 changed file with 55 additions and 55 deletions.
    110 changes: 55 additions & 55 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -1,67 +1,67 @@
    (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 = 'Удалить из плейлиста "Смотреть позже"'
    (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 playlistName = document.querySelector('#title a').text

    const limit = +prompt(`How many videos do you want to remove from ${playlistName}?`)
    if (!limit) return
    const limit = +prompt(`How many videos do you want to remove from ${playlistName}?`)
    if (!limit) return

    console.info('start...')
    let count = 0
    console.info('start...')
    let count = 0

    while (true) {
    const videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    if (videos.length == 0) break
    while (true) {
    const videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    if (videos.length == 0) break

    for (let videoElement of videos) {
    const videoTitle = videoElement.querySelector('a#video-title')
    console.info(`Remove Video\n` + ` Title: ${videoTitle.innerText}\n` + ` URL: ${videoTitle.href}`)
    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 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()
    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
    count++
    if (count >= limit) break

    const randDelay = 1000 + Math.random() * 400
    await sleep(randDelay)
    }
    if (count >= limit) break
    }
    console.info('done!')
    const randDelay = 1000 + Math.random() * 400
    await sleep(randDelay)
    }
    if (count >= limit) break
    }
    console.info('done!')

    // === util functions ========================================================
    // === util functions ========================================================

    async function sleep(timeout) {
    return new Promise((res) => setTimeout(res, timeout))
    }
    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)
    }
    }
    })()
    async function untilDefined(factory, checkInterval = 100) {
    while (true) {
    const value = factory()
    if (value != null) return value
    await sleep(checkInterval)
    }
    }
    })()
  2. udovichenko revised this gist Feb 10, 2023. 1 changed file with 60 additions and 64 deletions.
    124 changes: 60 additions & 64 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -1,71 +1,67 @@
    (async function() {
    (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 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 = '从稍后观看中移除'
    const playlistName = document.querySelector('#title a').text

    const playlistName = document.querySelector("#title a").text
    const limit = +prompt(`How many videos do you want to remove from ${playlistName}?`)
    if (!limit) return

    let 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 (let videoElement of videos) {

    const videoTitle = videoElement.querySelector('a#video-title')
    console.info(`Remove Video\n`
    + ` Title: ${videoTitle.innerText}\n`
    + ` URL: ${videoTitle.href}`)
    console.info('start...')
    let count = 0

    const actionMenuButton = videoElement.querySelector('#menu #button')
    console.debug("click actionMenuButton", actionMenuButton)
    actionMenuButton.click()
    while (true) {
    const videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    if (videos.length == 0) break

    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()
    for (let videoElement of videos) {
    const videoTitle = videoElement.querySelector('a#video-title')
    console.info(`Remove Video\n` + ` Title: ${videoTitle.innerText}\n` + ` URL: ${videoTitle.href}`)

    count++
    if (count >= limit) break

    const randDelay = 1000 + Math.random() * 400
    await sleep(randDelay)
    }
    if (count >= limit) break
    }
    console.info("done!")
    const actionMenuButton = videoElement.querySelector('#menu #button')
    console.debug('click actionMenuButton', actionMenuButton)
    actionMenuButton.click()

    // === 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)
    }
    }
    })()
    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)
    }
    }
    })()
  3. udovichenko revised this gist Feb 10, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -48,7 +48,7 @@
    count++
    if (count >= limit) break

    const randDelay = 200 + Math.random() * 500
    const randDelay = 1000 + Math.random() * 400
    await sleep(randDelay)
    }
    if (count >= limit) break
  4. udovichenko revised this gist Feb 10, 2023. 1 changed file with 14 additions and 14 deletions.
    28 changes: 14 additions & 14 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,3 @@
    // This script will remove all videos from watch later list
    //
    // Usage
    //
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script in your browser console
    // adjust REMOVE_BUTTON_TEXT accordingly to your language, see examples below
    (async function() {

    const REMOVE_BUTTON_TEXT = 'Remove from Watch later'
    @@ -15,16 +8,19 @@

    const playlistName = document.querySelector("#title a").text

    const limit = prompt(`How many videos do you want to remove from ${playlistName}?`);
    let limit = +prompt(`How many videos do you want to remove from ${playlistName}?`);
    if (!limit) return;

    console.info("start...")
    let count
    while(true) {
    let count = 0;

    while (true) {

    const videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    if(videos.length == 0) break
    if (videos.length == 0) break

    for (let videoElement of videos) {

    const videoTitle = videoElement.querySelector('a#video-title')
    console.info(`Remove Video\n`
    + ` Title: ${videoTitle.innerText}\n`
    @@ -48,12 +44,16 @@
    })
    console.debug("click removeButton", removeButton)
    removeButton.click()

    count++
    if (count >= limit) break

    const randDelay = 200 + Math.random() * 500;
    const randDelay = 200 + Math.random() * 500
    await sleep(randDelay)
    }
    if (count >= limit) break
    }
    console.info("done!");
    console.info("done!")

    // === util functions ========================================================

    @@ -68,4 +68,4 @@
    await sleep(checkInterval)
    }
    }
    })();
    })()
  5. udovichenko revised this gist Feb 10, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@

    const playlistName = document.querySelector("#title a").text

    const limit = prompt(`How many videos do you want to remove from ${playlistName}?`));
    const limit = prompt(`How many videos do you want to remove from ${playlistName}?`);
    if (!limit) return;

    console.info("start...")
  6. udovichenko revised this gist Feb 10, 2023. 1 changed file with 6 additions and 5 deletions.
    11 changes: 6 additions & 5 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -15,11 +15,11 @@

    const playlistName = document.querySelector("#title a").text

    if(!confirm(`Are you sure to delete ALL videos from ${playlistName}?`)) {
    return
    }
    const limit = prompt(`How many videos do you want to remove from ${playlistName}?`));
    if (!limit) return;

    console.info("start...")
    let count
    while(true) {
    const videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    if(videos.length == 0) break
    @@ -49,10 +49,11 @@
    console.debug("click removeButton", removeButton)
    removeButton.click()

    await sleep(200)
    const randDelay = 200 + Math.random() * 500;
    await sleep(randDelay)
    }
    }
    console.info("done!")
    console.info("done!");

    // === util functions ========================================================

  7. @qoomon qoomon revised this gist Mar 31, 2022. 1 changed file with 5 additions and 4 deletions.
    9 changes: 5 additions & 4 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -7,10 +7,11 @@
    // adjust REMOVE_BUTTON_TEXT accordingly to your language, see examples below
    (async function() {

    const REMOVE_BUTTON_TEXT = 'Remove from Watch later' // en
    // de-DE: 'Aus "Später ansehen" entfernen'
    // pt-BR: 'Remover de Assistir mais tarde'
    // zh-Hans-CN: '从稍后观看中移除'
    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 = '从稍后观看中移除'

    const playlistName = document.querySelector("#title a").text

  8. @qoomon qoomon revised this gist Mar 31, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@
    // adjust REMOVE_BUTTON_TEXT accordingly to your language, see examples below
    (async function() {

    const REMOVE_BUTTON_TEXT = 'Remove from Watch later'// en
    const REMOVE_BUTTON_TEXT = 'Remove from Watch later' // en
    // de-DE: 'Aus "Später ansehen" entfernen'
    // pt-BR: 'Remover de Assistir mais tarde'
    // zh-Hans-CN: '从稍后观看中移除'
  9. @qoomon qoomon revised this gist Mar 14, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -43,6 +43,7 @@
    }
    }
    }
    console.debug("wait for removeButton")
    })
    console.debug("click removeButton", removeButton)
    removeButton.click()
  10. @qoomon qoomon revised this gist Mar 14, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -58,11 +58,11 @@
    return new Promise(res => setTimeout(res, timeout))
    }

    async function untilDefined(factory, timeout = 100) {
    async function untilDefined(factory, checkInterval = 100) {
    while (true) {
    const value = factory()
    if (value != null) return value
    await sleep(timeout)
    await sleep(checkInterval)
    }
    }
    })();
  11. @qoomon qoomon revised this gist Mar 14, 2022. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -34,9 +34,9 @@
    actionMenuButton.click()

    const removeButton= await untilDefined(() => {
    for (const dropdown of [...document.querySelectorAll('ytd-popup-container > tp-yt-iron-dropdown')]) {
    if(dropdown => dropdown.style.display !== "none") {
    for (const actionButton of [...dropdown.querySelectorAll('tp-yt-paper-item')]) {
    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
    }
  12. @qoomon qoomon revised this gist Mar 14, 2022. 1 changed file with 10 additions and 7 deletions.
    17 changes: 10 additions & 7 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -33,14 +33,17 @@
    console.debug("click actionMenuButton", actionMenuButton)
    actionMenuButton.click()

    const actionMenuPopup = await untilDefined(() => {
    const container = document.querySelector('ytd-popup-container > tp-yt-iron-dropdown')
    if (container && container.style.display !== "none") {
    return container
    const removeButton= await untilDefined(() => {
    for (const dropdown of [...document.querySelectorAll('ytd-popup-container > tp-yt-iron-dropdown')]) {
    if(dropdown => dropdown.style.display !== "none") {
    for (const actionButton of [...dropdown.querySelectorAll('tp-yt-paper-item')]) {
    if(actionButton.innerText.trim().toLowerCase() === REMOVE_BUTTON_TEXT.toLowerCase()){
    return actionButton
    }
    }
    }
    }
    })
    const removeButton = [...actionMenuPopup.querySelectorAll('tp-yt-paper-item')]
    .find(el => el.innerText.trim().toLowerCase() === REMOVE_BUTTON_TEXT.toLowerCase())
    console.debug("click removeButton", removeButton)
    removeButton.click()

    @@ -62,4 +65,4 @@
    await sleep(timeout)
    }
    }
    })();
    })();
  13. @qoomon qoomon revised this gist Mar 3, 2022. 1 changed file with 9 additions and 5 deletions.
    14 changes: 9 additions & 5 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -6,14 +6,17 @@
    // #2 run following script in your browser console
    // adjust REMOVE_BUTTON_TEXT accordingly to your language, see examples below
    (async function() {
    const REMOVE_BUTTON_TEXT = 'Remove from Watch later'
    // en: 'Remove from Watch later'

    const REMOVE_BUTTON_TEXT = 'Remove from Watch later'// en
    // de-DE: 'Aus "Später ansehen" entfernen'
    // pt-BR: 'Remover de Assistir mais tarde'
    // zh-Hans-CN: '从稍后观看中移除'

    const playlistName = document.querySelector("#title a").text
    if(!confirm(`Are you sure to delete ALL videos from ${playlistName}?`)) return

    if(!confirm(`Are you sure to delete ALL videos from ${playlistName}?`)) {
    return
    }

    console.info("start...")
    while(true) {
    @@ -22,8 +25,9 @@

    for (let videoElement of videos) {
    const videoTitle = videoElement.querySelector('a#video-title')
    console.info("remove: " + videoTitle.innerText)
    console.info(" " + videoTitle.href)
    console.info(`Remove Video\n`
    + ` Title: ${videoTitle.innerText}\n`
    + ` URL: ${videoTitle.href}`)

    const actionMenuButton = videoElement.querySelector('#menu #button')
    console.debug("click actionMenuButton", actionMenuButton)
  14. @qoomon qoomon revised this gist Mar 3, 2022. 1 changed file with 1 addition and 4 deletions.
    5 changes: 1 addition & 4 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -13,10 +13,7 @@
    // zh-Hans-CN: '从稍后观看中移除'

    const playlistName = document.querySelector("#title a").text

    if(!confirm(`Are you sure to delete ALL videos from ${playlistName}?`)) {
    return
    }
    if(!confirm(`Are you sure to delete ALL videos from ${playlistName}?`)) return

    console.info("start...")
    while(true) {
  15. @qoomon qoomon revised this gist Mar 3, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -6,8 +6,8 @@
    // #2 run following script in your browser console
    // adjust REMOVE_BUTTON_TEXT accordingly to your language, see examples below
    (async function() {

    const REMOVE_BUTTON_TEXT = 'Remove from Watch later'// en
    const REMOVE_BUTTON_TEXT = 'Remove from Watch later'
    // en: 'Remove from Watch later'
    // de-DE: 'Aus "Später ansehen" entfernen'
    // pt-BR: 'Remover de Assistir mais tarde'
    // zh-Hans-CN: '从稍后观看中移除'
  16. @qoomon qoomon revised this gist Mar 3, 2022. 1 changed file with 38 additions and 28 deletions.
    66 changes: 38 additions & 28 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -3,52 +3,62 @@
    // Usage
    //
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script
    // adjust REMOVE_BUTTON_TEXT_MAP, if your language code is missing
    // get you location code by executing document.documentElement.lang
    // #2 run following script in your browser console
    // adjust REMOVE_BUTTON_TEXT accordingly to your language, see examples below
    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
    'en': 'Remove from Watch later',
    'en-GB': 'Remove from Watch Later',
    'de-DE': 'Aus "Später ansehen" entfernen',
    'pt-BR': 'Remover de Assistir mais tarde',
    'zh-Hans-CN': '从稍后观看中移除',

    const REMOVE_BUTTON_TEXT = 'Remove from Watch later'// en
    // de-DE: 'Aus "Später ansehen" entfernen'
    // pt-BR: 'Remover de Assistir mais tarde'
    // zh-Hans-CN: '从稍后观看中移除'

    const playlistName = document.querySelector("#title a").text

    if(!confirm(`Are you sure to delete ALL videos from ${playlistName}?`)) {
    return
    }

    const sleep = (timeout) => new Promise(res => setTimeout(res, timeout))
    const untilDefined = async (factory, timeout = 100) => {
    while (true) {
    let value = factory()
    if (value != null) return value
    await sleep(timeout)
    }
    }

    console.info("start...")
    while(true) {
    let videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    const videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    if(videos.length == 0) break

    for (let videoElement of videos) {
    let videoTitle = videoElement.querySelector('a#video-title')
    const videoTitle = videoElement.querySelector('a#video-title')
    console.info("remove: " + videoTitle.innerText)
    console.info(" " + videoTitle.href)

    let actionMenu = videoElement.querySelector('#menu')
    let actionMenuButton = actionMenu.querySelector('#button')

    const actionMenuButton = videoElement.querySelector('#menu #button')
    console.debug("click actionMenuButton", actionMenuButton)
    actionMenuButton.click()
    let languageCode = document.documentElement.lang
    let removeButtonText = REMOVE_BUTTON_TEXT_MAP[languageCode] || REMOVE_BUTTON_TEXT_MAP[languageCode.split('-')[0]]
    let removeButton = await untilDefined(() => document.evaluate(
    `//ytd-popup-container/tp-yt-iron-dropdown//tp-yt-paper-item[contains(., "${removeButtonText}")]`,
    document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);

    const actionMenuPopup = await untilDefined(() => {
    const container = document.querySelector('ytd-popup-container > tp-yt-iron-dropdown')
    if (container && container.style.display !== "none") {
    return container
    }
    })
    const removeButton = [...actionMenuPopup.querySelectorAll('tp-yt-paper-item')]
    .find(el => el.innerText.trim().toLowerCase() === REMOVE_BUTTON_TEXT.toLowerCase())
    console.debug("click removeButton", removeButton)
    removeButton.click()

    await sleep(200)
    }
    }
    console.info("done!")

    // === util functions ========================================================

    async function sleep (timeout) {
    return new Promise(res => setTimeout(res, timeout))
    }

    async function untilDefined(factory, timeout = 100) {
    while (true) {
    const value = factory()
    if (value != null) return value
    await sleep(timeout)
    }
    }
    })();
  17. @qoomon qoomon revised this gist Mar 3, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@
    // get you location code by executing document.documentElement.lang
    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
    'en': 'Remove from Watch Later',
    'en': 'Remove from Watch later',
    'en-GB': 'Remove from Watch Later',
    'de-DE': 'Aus "Später ansehen" entfernen',
    'pt-BR': 'Remover de Assistir mais tarde',
  18. @qoomon qoomon revised this gist Feb 28, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -8,8 +8,8 @@
    // get you location code by executing document.documentElement.lang
    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
    'en': 'Remove from Watch later',
    'en-GB': 'Remove from Watch later',
    'en': 'Remove from Watch Later',
    'en-GB': 'Remove from Watch Later',
    'de-DE': 'Aus "Später ansehen" entfernen',
    'pt-BR': 'Remover de Assistir mais tarde',
    'zh-Hans-CN': '从稍后观看中移除',
  19. @qoomon qoomon revised this gist Feb 8, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    //
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script
    // adjust REMOVE_BUTTON_TEXT_MAP, if your language is missing
    // adjust REMOVE_BUTTON_TEXT_MAP, if your language code is missing
    // get you location code by executing document.documentElement.lang
    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
  20. @qoomon qoomon revised this gist Feb 8, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -4,8 +4,8 @@
    //
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script
    // adjust REMOVE_BUTTON_TEXT_MAP if your language is missing
    //. get you location code by executing document.documentElement.lang
    // adjust REMOVE_BUTTON_TEXT_MAP, if your language is missing
    // get you location code by executing document.documentElement.lang
    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
    'en': 'Remove from Watch later',
  21. @qoomon qoomon revised this gist Sep 23, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,7 @@
    'en-GB': 'Remove from Watch later',
    'de-DE': 'Aus "Später ansehen" entfernen',
    'pt-BR': 'Remover de Assistir mais tarde',
    'zh-Hans-CN': '从稍后观看中移除',
    }

    const sleep = (timeout) => new Promise(res => setTimeout(res, timeout))
  22. @qoomon qoomon revised this gist Jun 17, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -11,6 +11,7 @@
    'en': 'Remove from Watch later',
    'en-GB': 'Remove from Watch later',
    'de-DE': 'Aus "Später ansehen" entfernen',
    'pt-BR': 'Remover de Assistir mais tarde',
    }

    const sleep = (timeout) => new Promise(res => setTimeout(res, timeout))
  23. @qoomon qoomon revised this gist Jun 5, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script
    // adjust REMOVE_BUTTON_TEXT_MAP if your language is missing

    //. get you location code by executing document.documentElement.lang
    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
    'en': 'Remove from Watch later',
  24. @qoomon qoomon revised this gist Apr 21, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    //
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script
    // adjust REMOVE_BUTTON_TEXT_MAP if your langanguage is missing
    // adjust REMOVE_BUTTON_TEXT_MAP if your language is missing

    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
  25. @qoomon qoomon revised this gist Apr 21, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    //
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script
    // adjust REMOVE_BUTTON_TEXT to your language (default is english)
    // adjust REMOVE_BUTTON_TEXT_MAP if your langanguage is missing

    (async function() {
    const REMOVE_BUTTON_TEXT_MAP = {
  26. @qoomon qoomon revised this gist Apr 21, 2021. 1 changed file with 8 additions and 2 deletions.
    10 changes: 8 additions & 2 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,11 @@
    // adjust REMOVE_BUTTON_TEXT to your language (default is english)

    (async function() {
    const REMOVE_BUTTON_TEXT = "Remove from Watch later"
    const REMOVE_BUTTON_TEXT_MAP = {
    'en': 'Remove from Watch later',
    'en-GB': 'Remove from Watch later',
    'de-DE': 'Aus "Später ansehen" entfernen',
    }

    const sleep = (timeout) => new Promise(res => setTimeout(res, timeout))
    const untilDefined = async (factory, timeout = 100) => {
    @@ -33,8 +37,10 @@

    console.debug("click actionMenuButton", actionMenuButton)
    actionMenuButton.click()
    let languageCode = document.documentElement.lang
    let removeButtonText = REMOVE_BUTTON_TEXT_MAP[languageCode] || REMOVE_BUTTON_TEXT_MAP[languageCode.split('-')[0]]
    let removeButton = await untilDefined(() => document.evaluate(
    `//ytd-popup-container/tp-yt-iron-dropdown//tp-yt-paper-item[contains(., "${REMOVE_BUTTON_TEXT}")]`,
    `//ytd-popup-container/tp-yt-iron-dropdown//tp-yt-paper-item[contains(., "${removeButtonText}")]`,
    document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);

    console.debug("click removeButton", removeButton)
  27. @qoomon qoomon revised this gist Apr 16, 2021. 1 changed file with 10 additions and 9 deletions.
    19 changes: 10 additions & 9 deletions youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@
    // adjust REMOVE_BUTTON_TEXT to your language (default is english)

    (async function() {
    const REMOVE_BUTTON_TEXT = "Remove from"
    const REMOVE_BUTTON_TEXT = "Remove from Watch later"

    const sleep = (timeout) => new Promise(res => setTimeout(res, timeout))
    const untilDefined = async (factory, timeout = 100) => {
    @@ -21,23 +21,24 @@
    console.info("start...")
    while(true) {
    let videos = document.querySelectorAll('#primary ytd-playlist-video-renderer')
    if(videos.length == 0) break;
    if(videos.length == 0) break

    for (let videoElement of videos) {
    let videoTitle = videoElement.querySelector('a#video-title')
    console.info("remove: " + videoTitle.innerText)
    console.info(" " + videoTitle.href)

    let actionMenu = videoElement.querySelector('#menu')
    let actionMenuButton = actionMenu.querySelector('#button');
    let actionMenuButton = actionMenu.querySelector('#button')

    console.debug("click actionMenuButton")
    actionMenuButton.click();
    let removeButton = await untilDefined(() => document.evaluate('//span[contains(text(), "' + REMOVE_BUTTON_TEXT + '")]',
    actionMenu, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
    console.debug("click actionMenuButton", actionMenuButton)
    actionMenuButton.click()
    let removeButton = await untilDefined(() => document.evaluate(
    `//ytd-popup-container/tp-yt-iron-dropdown//tp-yt-paper-item[contains(., "${REMOVE_BUTTON_TEXT}")]`,
    document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);

    console.debug("click removeButton")
    removeButton.click();
    console.debug("click removeButton", removeButton)
    removeButton.click()
    await sleep(200)
    }
    }
  28. @qoomon qoomon revised this gist Apr 16, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@

    console.debug("click actionMenuButton")
    actionMenuButton.click();
    let removeButton = await untilDefined(() => document.evaluate('//span[contains(text(), ' + REMOVE_BUTTON_TEXT + ')]',
    let removeButton = await untilDefined(() => document.evaluate('//span[contains(text(), "' + REMOVE_BUTTON_TEXT + '")]',
    actionMenu, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);

    console.debug("click removeButton")
  29. @qoomon qoomon revised this gist Apr 16, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@

    console.debug("click actionMenuButton")
    actionMenuButton.click();
    let removeButton = await untilDefined(() => document.evaluate('//span[contains(text(), REMOVE_BUTTON_TEXT)]',
    let removeButton = await untilDefined(() => document.evaluate('//span[contains(text(), ' + REMOVE_BUTTON_TEXT + ')]',
    actionMenu, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);

    console.debug("click removeButton")
  30. @qoomon qoomon revised this gist Apr 16, 2021. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion youtube_clean_watch_later_videos.js
    Original file line number Diff line number Diff line change
    @@ -4,8 +4,11 @@
    //
    // #1 go to https://www.youtube.com/playlist?list=WL
    // #2 run following script
    // adjust REMOVE_BUTTON_TEXT to your language (default is english)

    (async function() {
    const REMOVE_BUTTON_TEXT = "Remove from"

    const sleep = (timeout) => new Promise(res => setTimeout(res, timeout))
    const untilDefined = async (factory, timeout = 100) => {
    while (true) {
    @@ -30,7 +33,7 @@

    console.debug("click actionMenuButton")
    actionMenuButton.click();
    let removeButton = await untilDefined(() => document.evaluate('//span[contains(text(),"Remove from")]',
    let removeButton = await untilDefined(() => document.evaluate('//span[contains(text(), REMOVE_BUTTON_TEXT)]',
    actionMenu, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);

    console.debug("click removeButton")