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}); })();