Export Youtube Playlist in plaintext

Shows a list of the playlist video names/channels/URLs in plaintext to be easily copied

< Feedback on Export Youtube Playlist in plaintext

Review: Good - script works

§
Posted: 2024-01-30

I really liked your script Here's the code, converted to vanilla JavaScript and removing jQuery dependencies: (function() {
'use strict';

var getVideoTitle = GM_getValue("getVideoTitle", true);
var getVideoChannel = GM_getValue("getVideoChannel", false);
var getVideoURL = GM_getValue("getVideoURL", false);
var videoListSeperator = GM_getValue("videoListSeperator", "|:|");

var listCreationAllowed = true;
var urlAtLastCheck = "";

// Function to add a global style without jQuery
function addGlobalStyle(css) {
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
}

// Insert CSS for the export button and list display
addGlobalStyle(`
tp-yt-paper-listbox#items { overflow-x: hidden; }

#exportPlainTextList {
cursor: pointer;
height: 36px;
width: 100%;
display: flex;
align-items: center;
}
#exportPlainTextList > img {
height: 24px; width: 24px;
color: rgb(144, 144, 144);
padding: 0 13px 0 16px;
filter: contrast(0%);
}
#exportPlainTextList > span {
font-family: "Roboto","Arial",sans-serif;
color: var(--yt-spec-text-primary);
white-space: nowrap;
font-size: 1.4rem;
line-height: 2rem;
font-weight: 400;
}

#exportPlainTextList:hover { background-color: rgba(255,255,255,0.1); }
ytd-menu-popup-renderer.ytd-popup-container { overflow-x: hidden !important; max-height: none !important; }

#listDisplayContainer {
position: fixed;
z-index: 9999;
margin: 0 auto;
background-color: #464646;
padding: 10px;
border-radius: 5px;
left: 0;
right: 0;
max-width: 100vw;
width: 1200px;
height: 900px;
max-height: 90vh;
top: 5vh;
resize: both;
overflow: hidden;
}
#listDisplayContainer > textarea {
box-sizing: border-box;
width: 100%;
margin: 10px 0;
height: calc(100% - 40px);
background-color: #262626;
border: none;
color: #EEE;
border-radius: 5px;
resize: none;
}
#closeTheListThing {
float: right;
font-weight: bold;
background-color: RGBA(255,255,255,0.25);
border: none;
font-size: 17px;
border-radius: 10px;
height: 25px;
width: 25px;
cursor: pointer;
}

#closeTheListThing:hover { background-color: rgba(255,255,255,0.5); }
`);

// Check for playlist URLs and insert the export button
setInterval(function() {
if (urlAtLastCheck !== window.location.href) {
urlAtLastCheck = window.location.href;
if (urlAtLastCheck.includes("/playlist?list=")) {
InsertButtonASAP();
}
}
}, 100);

// Function to insert the export button
function InsertButtonASAP() {
let buttonInsertInterval = setInterval(function() {
// Wait for the space for the button to be available
if (!document.querySelector("#exportPlainTextList") && document.querySelector("tp-yt-paper-listbox#items")) {
const itemsListbox = document.querySelector("tp-yt-paper-listbox#items");
const exportButton = document.createElement("div");
exportButton.id = "exportPlainTextList";
exportButton.innerHTML = `

Export Playlist
`;
itemsListbox.appendChild(exportButton);
exportButton.addEventListener("click", ScrollUntillAllVisible);
setTimeout(function() { clearInterval(buttonInsertInterval); }, 5000);
}
}, 100);
}

// Function to scroll the playlist until all videos are visible
function ScrollUntillAllVisible() {
if (!listCreationAllowed) {
return;
}

document.querySelector("ytd-browse[page-subtype='playlist']").click();

listCreationAllowed = false;
const exportButton = document.querySelector("#exportPlainTextList");
const message = document.createElement("p");
message.id = "listBuildMessage";
message.style.color = "red";
message.style.fontSize = "1.33em";
message.textContent = "Getting list...
please click out of the popup to continue autoscrolling...";
exportButton.after(message);

let scrollInterval = setInterval(function() {
if (document.querySelector("ytd-continuation-item-renderer.ytd-playlist-video-list-renderer")) {
window.scrollTo(0, document.body.scrollHeight);
} else {
message.remove();
DisplayListOptions();
clearInterval(scrollInterval);
}
}, 100);
}

// Function to display options for list generation
function DisplayListOptions() {
const body = document.querySelector("body");
const listContainer = document.createElement("div");
listContainer.id = "listDisplayContainer";
listContainer.innerHTML = `


Playlist in plain text
X


  • Get titles
  • Get channel names
  • Get URLs
  • Name/Author/URL seperator
  • Get list

`;
body.appendChild(listContainer);

// Add event listeners for options and list generation
const getVideoTitleCheckbox = document.getElementById("getVideoTitleCB");
getVideoTitleCheckbox.addEventListener("change", function() {
getVideoTitle = this.checked;
GM_setValue("getVideoTitle", getVideoTitle);
});

const getVideoChannelCheckbox = document.getElementById("getVideoChannelCB");
getVideoChannelCheckbox.addEventListener("change", function() {
getVideoChannel = this.checked;
GM_setValue("getVideoChannel", getVideoChannel);
});

const getVideoURLCheckbox = document.getElementById("getVideoURLCB");
getVideoURLCheckbox.addEventListener("change", function() {
getVideoURL = this.checked;
GM_setValue("getVideoURL", getVideoURL);
});

const videoListSeperatorInput = document.getElementById("videoListSeperatorInput");
videoListSeperatorInput.addEventListener("change", function() {
videoListSeperator = this.value;
GM_setValue("videoListSeperator", videoListSeperator);
});

const getListButton = document.getElementById("listDisplayGetListButton");
getListButton.addEventListener("click", BuildAndDisplayList);

const closeButton = document.getElementById("closeTheListThing");
closeButton.addEventListener("click", function() {
listContainer.remove();
listCreationAllowed = true;
});
}

// Function to build and display the playlist text
function BuildAndDisplayList() {
const listOptionsContainer = document.getElementById("listDisplayOptions");
listOptionsContainer.style.display = "none";
const listTextarea = document.querySelector("#listDisplayContainer > textarea");
listTextarea.style.display = "block";

let videoTitleArr = [];
let videoChannelArr = [];
let videoURLArr = [];
let videoCount = 0;

const videoListItems = document.querySelectorAll("ytd-playlist-video-list-renderer > #contents.ytd-playlist-video-list-renderer > ytd-playlist-video-renderer #content");

// Loop through each video in the playlist
for (const item of videoListItems) {
if (getVideoTitle) {
videoTitleArr.push(item.querySelector("#video-title").getAttribute("title"));
}

if (getVideoURL) {
videoURLArr.push("https://www.youtube.com" + item.querySelector("#video-title").getAttribute("href").split("&")[0]);
}

if (getVideoChannel) {
videoChannelArr.push(item.querySelector("#channel-name yt-formatted-string.ytd-channel-name > a").textContent);
}

videoCount++;
}

// Build the playlist text
let list = "";
for (let i = 0; i < videoCount; i++) {
if (getVideoTitle) {
list += videoTitleArr[i] + " ";
}

if (getVideoChannel) {
list += (getVideoTitle ? videoListSeperator : "") + videoChannelArr[i];
}

if (getVideoURL) {
list += (getVideoTitle || getVideoChannel ? videoListSeperator : "") + videoURLArr[i];
}

list += "\n";
}

// Display the playlist text in the textarea
listTextarea.value = list;
}
})();

Post reply

Sign in to post a reply.