Created
June 21, 2023 10:23
-
-
Save mshannongit/1445130b3876a044b97a59c5df50e92d to your computer and use it in GitHub Desktop.
Bulk Unlike Youtube videos
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// forked from js6pak youtube-playlist-cleanser.user.js script | |
// @name Youtube - Unlike youtube videos | |
const config = { | |
// Delay between requests (seems to need to be quite high for consistent results) | |
delay: 600, | |
}; | |
const sleep = (timeout) => new Promise((res) => setTimeout(res, timeout)); | |
function waitForElement(selector) { | |
return new Promise((resolve) => { | |
if (document.querySelector(selector)) { | |
return resolve(document.querySelector(selector)); | |
} | |
const observer = new MutationObserver(() => { | |
if (document.querySelector(selector)) { | |
resolve(document.querySelector(selector)); | |
observer.disconnect(); | |
} | |
}); | |
observer.observe(app, { | |
childList: true, | |
subtree: true, | |
}); | |
}); | |
} | |
function createButtons(menu) { | |
const unlikeAllButton = document.createElement("button"); | |
{ | |
unlikeAllButton.textContent = "Unlike all videos"; | |
unlikeAllButton.style.padding = "10px"; | |
unlikeAllButton.style.backgroundColor = "#181717"; | |
unlikeAllButton.style.color = "white"; | |
unlikeAllButton.style.textAlign = "center"; | |
unlikeAllButton.style.fontSize = "14px"; | |
unlikeAllButton.style.border = "0"; | |
unlikeAllButton.style.cursor = "pointer"; | |
unlikeAllButton.style.fontFamily = "Roboto, Arial, sans-serif"; | |
unlikeAllButton.style.borderRadius = "2px"; | |
unlikeAllButton.style.marginRight = "10px"; | |
unlikeAllButton.addEventListener("click", function () { | |
unlikeAll(); | |
}); | |
} | |
menu.prepend(unlikeAllButton); | |
} | |
function* getVideos() { | |
const videos = document.querySelectorAll("ytd-playlist-video-renderer"); | |
for (const video of videos) { | |
const title = video.querySelector("#video-title").innerText; | |
const menu = video.querySelector("ytd-menu-renderer"); | |
const menuButton = menu.querySelector("yt-icon-button#button"); | |
yield { | |
container: video, | |
title, | |
menu, | |
menuButton, | |
}; | |
} | |
} | |
async function unlikeVideo(video) { | |
video.menuButton.click(); | |
const popup = await waitForElement("ytd-menu-popup-renderer"); | |
// 'ADD_TO_QUEUE_TAIL' | |
// 'WATCH_LATER' | |
// 'PLAYLIST_ADD' | |
// 'SHARE' | |
// 'DELETE' | |
console.log(`Unliking ${video.title} ...`); | |
Array.from(popup.querySelectorAll("ytd-menu-service-item-renderer")) | |
.find((x) => x.icon === "DELETE") | |
.click(); | |
await sleep(config.delay); | |
} | |
async function unlikeAll() { | |
console.log("Unliking videos ..."); | |
let unlikedCount = 0; | |
for (const video of getVideos()) { | |
await unlikeVideo(video); | |
unlikedCount ++; | |
} | |
console.log(`Done! Processed ${unlikedCount} videos`); | |
} | |
waitForElement("ytd-playlist-header-renderer ytd-menu-renderer").then((menu) => { | |
createButtons(menu); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment