Created
June 21, 2023 10:27
-
-
Save mshannongit/81b722ab71d3b85a372412af51e12eac to your computer and use it in GitHub Desktop.
Youtube - Add liked videos to a playlist
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 - 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