Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mshannongit/81b722ab71d3b85a372412af51e12eac to your computer and use it in GitHub Desktop.
Save mshannongit/81b722ab71d3b85a372412af51e12eac to your computer and use it in GitHub Desktop.
Youtube - Add liked videos to a playlist
// ==UserScript==
// forked from js6pak youtube-playlist-cleanser.user.js script
// @name Youtube - Add liked videos to playlist
const config = {
// Name of playlist to which Liked video will be added
playlistName: 'Music',
// 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 addAllToPlaylistButton = document.createElement("button");
{
addAllToPlaylistButton.textContent = "Add all videos to playlist";
addAllToPlaylistButton.style.padding = "10px";
addAllToPlaylistButton.style.backgroundColor = "#181717";
addAllToPlaylistButton.style.color = "white";
addAllToPlaylistButton.style.textAlign = "center";
addAllToPlaylistButton.style.fontSize = "14px";
addAllToPlaylistButton.style.border = "0";
addAllToPlaylistButton.style.cursor = "pointer";
addAllToPlaylistButton.style.fontFamily = "Roboto, Arial, sans-serif";
addAllToPlaylistButton.style.borderRadius = "2px";
addAllToPlaylistButton.style.marginRight = "10px";
addAllToPlaylistButton.addEventListener("click", function () {
addAllToPlaylist();
});
}
menu.prepend(addAllToPlaylistButton);
}
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 addVideoToPlaylist(video, playlist) {
video.menuButton.click();
const popup = await waitForElement("ytd-menu-popup-renderer");
Array.from(popup.querySelectorAll("ytd-menu-service-item-renderer"))
.find((x) => x.icon === "PLAYLIST_ADD")
.click();
await sleep(config.delay);
const popup2 = await waitForElement("ytd-add-to-playlist-renderer");
await sleep(config.delay);
// click the playlist with the specified playlist name
const foundPlaylist = Array.from(popup2.querySelectorAll("ytd-playlist-add-to-option-renderer"))
.find((z) => z.querySelector('#label').title === playlist && z.querySelector('#checkbox').checked == false);
if (foundPlaylist) {
console.log(`Adding ${video.title} to ${playlist} ...`);
foundPlaylist.querySelector('#label').click();
await sleep(config.delay * 8);
}
else {
console.log(`Skipping ${video.title} - it is already saved to ${playlist}.`);
}
// close the playlist dialog
popup2.querySelector('#button').click()
await sleep(config.delay);
}
async function addAllToPlaylist() {
console.log("Adding videos to playlist " || config.playlistName || " ...");
let addCount = 0;
for (const video of getVideos()) {
await addVideoToPlaylist(video, config.playlistName);
addCount++;
}
console.log(`Done! Processed ${addCount} 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