Skip to content

Instantly share code, notes, and snippets.

@lac5
Last active June 17, 2024 15:04
Show Gist options
  • Save lac5/585b4bd176385894900a81d53a7dec7f to your computer and use it in GitHub Desktop.
Save lac5/585b4bd176385894900a81d53a7dec7f to your computer and use it in GitHub Desktop.
Utility for getting information about a playlist. Type `window[Symbol.for('userscript::PlaylistInfo')]` in your console to use the functions.
// ==UserScript==
// @name YouTube - Playlist Info
// @namespace larryc5
// @version 1.0
// @description Utility for getting information about a playlist. Type `window[Symbol.for('userscript::PlaylistInfo')]` in your console to use the functions.
// @author Larry Costigan
// @match http://www.youtube.com/*
// @match https://www.youtube.com/*
// @grant none
// @downloadURL https://gist.githubusercontent.com/larryc5/585b4bd176385894900a81d53a7dec7f/raw/youtube-playlist-info.user.js
// @updateURL https://gist.githubusercontent.com/larryc5/585b4bd176385894900a81d53a7dec7f/raw/youtube-playlist-info.meta.js
// ==/UserScript==
// ==UserScript==
// @name YouTube - Playlist Info
// @namespace larryc5
// @version 1.0
// @description Utility for getting information about a playlist. Type `window[Symbol.for('userscript::PlaylistInfo')]` in your console to use the functions.
// @author Larry Costigan
// @match http://www.youtube.com/*
// @match https://www.youtube.com/*
// @grant none
// @downloadURL https://gist.githubusercontent.com/larryc5/585b4bd176385894900a81d53a7dec7f/raw/youtube-playlist-info.user.js
// @updateURL https://gist.githubusercontent.com/larryc5/585b4bd176385894900a81d53a7dec7f/raw/youtube-playlist-info.meta.js
// ==/UserScript==
(function() {
'use strict';
const exports = window[Symbol.for('userscript::PlaylistInfo')] = {
get items() {
return Array.from(document.querySelectorAll('span.ytd-thumbnail-overlay-time-status-renderer'));
},
time(min, max) {
return (exports.items
.slice(min, max)
.map(e => e.textContent
.trim()
.split(':')
.filter(Boolean)
.reduce((t, n, i, a)=> t + parseInt(n)*Math.pow(60, a.length - i - 1), 0))
.filter(Boolean)
.reduce((t, n)=> t + n, 0));
},
timeF(format, min, max) {
if (typeof format !== 'string') {
max = min;
min = format;
format = '+H:MM:SS';
}
const t = exports.time(min, max);
return String(format).replace(/\+D|D+|\+H|H+|\+M|M+|\+S|S+/g, ($1) => {
let n = 0;
if ($1[0] === '+') {
switch ($1[1]) {
case 'D': n = Math.floor(t / 60 / 60 / 24); break;
case 'H': n = Math.floor(t / 60 / 60); break;
case 'M': n = Math.floor(t / 60); break;
case 'S': n = Math.floor(t); break;
}
return String(n);
} else {
switch ($1[0]) {
case 'D': n = Math.floor(t / 60 / 60 / 24); break;
case 'H': n = Math.floor(t / 60 / 60) % 24; break;
case 'M': n = Math.floor(t / 60) % 60; break;
case 'S': n = Math.floor(t) % 60; break;
}
if (n > Math.pow(10, $1.length)) {
return String(n);
}
return ($1.replace(/./g, '0') + n).slice(-$1.length);
}
});
},
whereIs(percent) {
percent = Math.min(1, Math.max(0, percent));
const times = (exports.items
.map(e => e.textContent
.trim()
.split(':')
.filter(Boolean)
.reduce((t, n, i, a)=> t + parseInt(n)*Math.pow(60, a.length - i - 1), 0)));
const total = times.reduce((t, n)=> t + n, 0);
const position = total * percent;
let totalBefore = 0;
let totalAt = 0;
const index = (p => times.findIndex(n => {
if (p - n < 0) {
totalAt = n;
return true;
}
totalBefore += n;
p -= n;
return false;
}))(position);
return index + ((position - totalBefore) / totalAt);
},
};
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment