NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Youtube Video Timestamp
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Add timestamps of video uploads in end video tiles
// @author You
// @match https://www.youtube.com/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @license MIT
// @updateURL https://openuserjs.org/meta/asteriksme/Youtube_Video_Timestamp.meta.js
// @downloadURL https://openuserjs.org/install/asteriksme/Youtube_Video_Timestamp.user.js
// ==/UserScript==
(function() {
'use strict';
const getRelativeTimeString = (date, lang = navigator.language) => {
// Allow dates or times to be passed
const timeMs = typeof date === "number" ? date : date.getTime();
// Get the amount of seconds between the given date and now
const deltaSeconds = Math.round((timeMs - Date.now()) / 1000);
// Array reprsenting one minute, hour, day, week, month, etc in seconds
const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity];
// Array equivalent to the above but in the string representation of the units
const units = ["second", "minute", "hour", "day", "week", "month", "year"];
// Grab the ideal cutoff unit
const unitIndex = cutoffs.findIndex(cutoff => cutoff > Math.abs(deltaSeconds));
// Get the divisor to divide from the seconds. E.g. if our unit is "day" our divisor
// is one day in seconds, so we can divide our seconds by this to get the # of days
const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1;
// Intl.RelativeTimeFormat do its magic
const rtf = new Intl.RelativeTimeFormat(lang, { numeric: "auto" });
return rtf.format(Math.floor(deltaSeconds / divisor), units[unitIndex]);
};
const add_timestamp = () => {
if (timestampsAdded || !document.querySelector(".ytp-endscreen-content a .ytp-videowall-still-info-author")) {
return;
}
timestampsAdded = true;
document.querySelector(".ytp-endscreen-content").querySelectorAll("a").forEach(async (tag) => {
await fetch(tag.href, {
method: 'get',
}).then((response) => {
return response.text();
}).then((res) => {
const date = new Date(res.match(/publishDate":"([^"]*)"/)[1]);
tag.querySelector(".ytp-videowall-still-info-author").innerHTML += ` • ${date.toLocaleDateString()} (${getRelativeTimeString(date)})`;
console.log(tag.querySelector(".ytp-videowall-still-info-author"));
});
});
}
let timestampsAdded = false;
setInterval(add_timestamp, 5000);
const changeVideosPerRow = (changes, observer) => {
const renderer = ".ytd-rich-grid-renderer";
const itemsPerRow = "--ytd-rich-grid-items-per-row";
const minSize = 5;
if (document.querySelector(renderer) && parseInt(getComputedStyle(document.querySelector(renderer)).getPropertyValue(itemsPerRow), 10) < minSize) {
console.log("detected");
observer.disconnect();
document.querySelectorAll(renderer).forEach((elt) => elt.style.setProperty(itemsPerRow, minSize.toString()));
console.log("change");
}
};
(new MutationObserver(changeVideosPerRow)).observe(document, {childList: true, subtree: true});
})();