Skip to content

Instantly share code, notes, and snippets.

@neonfuz
Created April 5, 2022 00:15
Show Gist options
  • Save neonfuz/feda23764f5e89365e54164fc93b4fa4 to your computer and use it in GitHub Desktop.
Save neonfuz/feda23764f5e89365e54164fc93b4fa4 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Youtube Sorter
// @description client side playlist sorting on youtube
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://www.youtube.com/*
// @icon https://www.google.com/s2/favicons?domain=youtube.com
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
const indexWeight = 0;
const sortMax = 5000;
const parseVid = (vid, i) => ({
vid,
data: vid.data,
title: vid.data.title && vid.data.title.runs.map(({text}) => text).join(' '),
channel: vid.data.shortBylineText && vid.data.shortBylineText.runs.map(({text}) => text).join(' '),
time: vid.data.lengthText && (Number(vid.data.lengthText.simpleText.replace(/:/g,'')) + i * indexWeight)
});
function sortBy(sort) {
return () => {
const container = document.querySelector('ytd-playlist-video-list-renderer #contents');
const spinner = container.querySelector('ytd-continuation-item-renderer');
const items = [...container.children];
const sorted = sort(items.slice(0, sortMax));
sorted.forEach(item => container.appendChild(item.vid));
items.slice(sortMax).forEach(item => container.appendChild(item));
spinner && container.appendChild(spinner);
}
}
const sortList = sortBy(items => (
items
.map(parseVid)
.filter(item => item.time)
.sort((a,b)=>a.time-b.time)
));
const bubbleSortList = sortBy(items => {
items = items.map(parseVid).filter(item => item.time);
for (let i=0; i<items.length-1; ++i) {
if (items[i].time > items[i+1].time) {
const tmp = items[i];
items[i] = items[i+1];
items[i+1] = tmp;
}
}
return items;
});
const sortByTitle = sortBy(items => (
items
.map(parseVid)
.filter(item => item.title)
.sort((a,b)=>a.title.localeCompare(b.title))
));
const sortByChannel = sortBy(items => (
items
.map(parseVid)
.filter(item => item.channel)
.sort((a,b) => a.channel.localeCompare(b.channel))
));
const sortProgress = sortBy(items => (
items
.map(parseVid)
));
function addButton(text, fn, target) {
const sortMenu = target.querySelector('#sort-filter-menu');
sortMenu.style.display = 'flex';
const button = document.createElement('button');
button.innerHTML = text;
button.onclick = fn;
button.style['margin-left'] = '1em';
sortMenu.appendChild(button);
}
function appendButtons(target) {
addButton('Full Sort', sortList, target);
addButton('Bubble Sort', bubbleSortList, target);
}
document.body.querySelectorAll('YTD-PLAYLIST-VIDEO-LIST-RENDERER').forEach(appendButtons);
new MutationObserver(function(mutationList, observer) {
for (const mutation of mutationList) {
if (mutation.target.tagName === 'YTD-PLAYLIST-VIDEO-LIST-RENDERER') {
appendButtons(mutation.target);
}
}
}).observe(document.body, {childList: true, subtree: true});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment