Skip to content

Instantly share code, notes, and snippets.

@mshannongit
Created June 21, 2023 10:23
Show Gist options
  • Save mshannongit/1445130b3876a044b97a59c5df50e92d to your computer and use it in GitHub Desktop.
Save mshannongit/1445130b3876a044b97a59c5df50e92d to your computer and use it in GitHub Desktop.
Bulk Unlike Youtube videos
// ==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