Skip to content

Instantly share code, notes, and snippets.

@Decicus
Last active May 9, 2024 16:26
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Decicus/ec4745e680e06cfff5b1fa0a53fcff72 to your computer and use it in GitHub Desktop.
Save Decicus/ec4745e680e06cfff5b1fa0a53fcff72 to your computer and use it in GitHub Desktop.
A userscript for displaying the actual date & time (relative to local time) of when a Twitch clip was created.

Twitch clip datetime userscript

A userscript for displaying the actual date & time (relative to local time) of when a Twitch clip (and video) was created.

FYI: It only works on URLs that start with https://clips.twitch.tv/.
This script does not work with URLs that are on the Twitch "channel pages" (https://www.twitch.tv/CHANNEL_NAME_HERE/clip/...).
This has been added as of v0.5.0.

"Under the hood" the script uses Date.toLocaleString() to format the date. The format of the date & time may differ from the screenshots below.

Requirements

  • Something like the Violentmonkey extension installed for your browser.

Installation

  1. Install a userscript extension (such as Violentmonkey).
  2. Click on this link when Violentmonkey is installed, and it will prompt you to install the userscript.

Support / Requests

If you have any requests or suggestions, feel free to join my Discord server for all my projects.

Changelog

  • v0.7.0 - 2024-05-09
    • Fixed the script so it now supports the new clip.twitch.tv layout.
      • Since they now use a similar layout as the main Twitch website, the position of the timestamp has been moved below the player. See screenshots at the bottom of this README.
  • v0.6.0 - 2022-01-03
    • Added support for Twitch videos (VODs, highlights)
    • Switched API to use the new Twitch API (Helix) via an "API proxy" I host using Cloudflare Workers.
    • The observer should no longer disconnect after the first timestamp, allowing browsing to other videos/clips to work.
  • v0.5.1 - 2021-12-30
    • Minor bug where it tried to fetch the date & time of a clip when watching highlights/VODs.
      • At some point I'll update the script to support VODs/highlights, but for now I'm sticking to clips.
  • v0.5.0 - 2021-12-30
    • Script now supports clips on Twitch channel pages (e.g. https://www.twitch.tv/$channelName/clip/$clipSlug)
      • The @match rule will say https://www.twitch.tv/* to support navigating from the channel page to the clip page, otherwise script wouldn't load on regular Twitch browsing.
  • v0.4.1 - 2021-08-29
    • Make script compatible with Tampermonkey again.
  • v0.4.0 - 2021-08-29
    • Date/time placement was adjusted due to changes in the page on Twitch's end. See screenshots.
    • Previously I used Tampermonkey, but later switched to Violentmonkey. During my testing, I tested with Violentmonkey and it worked fine. However, if you're currently using Tampermonkey, v0.4.0 does not work. I'm unsure as to why, but I'll try to look into it.
    • Fixed in v0.4.1

Screenshots

As of v0.4.0, the timestamp shows up a bit different compared to earlier versions.
As of v0.7.0, the script was updated to support the new clips.twitch.tv layout. The timestamp was moved to be below the video player.

On clips.twitch.tv

Screenshot of userscript on clips.twitch.tv

Main Twitch website

When browsing Twitch channel clips on the main Twitch website.
Only v0.5.0 (December 30th, 2021) and newer

Screenshot of userscript on main Twitch website

As of v0.6.0 (January 3rd, 2022), the script also works with Twitch videos (VODs, highlights).

// ==UserScript==
// @name Twitch Clips - Show date & time
// @version 0.7.0
// @description Displays the actual date & time of when a clip (or video/VOD/highlight) was created, instead of the useless "xxx days/months/weeks ago"
// @author Decicus
// @updateURL https://gist.github.com/Decicus/ec4745e680e06cfff5b1fa0a53fcff72/raw/twitch-clips-datetime.user.js
// @downloadURL https://gist.github.com/Decicus/ec4745e680e06cfff5b1fa0a53fcff72/raw/twitch-clips-datetime.user.js
// @homepageURL https://gist.github.com/Decicus/ec4745e680e06cfff5b1fa0a53fcff72
// @icon https://i.alex.lol/2021-08-29_PmO4zo.png
// @match https://clips.twitch.tv/*
// @match https://www.twitch.tv/*
// @license MIT
// ==/UserScript==
/**
* Insert timestamp for the `clips.twitch.tv` website.
*/
function clipsSubdomain(createdAt, dateAndTime)
{
// The new layout for clips.twitch.tv (as of May 2024) uses a similar layout to the main website,
// so this has been simplified until they change it again.
insertMainWebsite(createdAt, dateAndTime, false);
}
/**
* Insert timestamp for the `www.twitch.tv` (main) website.
* E.g. https://www.twitch.tv/$channelName/clip/$clipSlug
* Or: https://www.twitch.tv/videos/$videoId
*/
function insertMainWebsite(createdAt, dateAndTime, isVideo)
{
const timestampBar = document.querySelector('.timestamp-metadata__bar');
const parent = timestampBar.parentElement;
// Use for text styling
const textElement = document.querySelector('p[class*="CoreText"]');
const textClass = textElement.classList[0];
let element = document.querySelector('#twitch-datetime-script');
let newElement = false;
if (!element) {
element = document.createElement('p');
element.className = textClass;
element.setAttribute('style', 'margin-left: 0.25em;');
element.setAttribute('id', 'twitch-datetime-script');
newElement = true;
}
element.innerHTML = `- ${isVideo ? 'Video' : 'Clip'} created: <strong>${dateAndTime}</strong>`;
element.setAttribute('title', createdAt);
if (!newElement) {
return;
}
parent.insertAdjacentElement('beforeend', element);
}
/**
* Get the timestamp of a clip or video.
*
* @param {string} id The id of the clip or video.
* @param {string} type Type: `clip` or `video`
* @returns {Promise<{createdAt: string, dateAndTime: string}>}
*/
async function getTimestamp(id, type)
{
if (!type) {
type = 'clip';
}
const response = await fetch(`https://twitch-api-proxy.cactus.workers.dev/timestamps/${type}?id=${id}`);
const data = await response.json();
if (!data.created_at) {
return;
}
const createdAt = data.created_at;
const created = new Date(createdAt);
const dateAndTime = created.toLocaleString();
return {createdAt, dateAndTime};
}
/**
* Fetch clip information via getTimestamp() and insert accordingly.
*
* @param {URL} url
* @returns {void}
*/
async function fetchClip(url) {
const pathFragments = url.pathname.split('/');
const clipSlug = pathFragments[pathFragments.length - 1];
const slug = clipSlug.match(/([A-z0-9-_]+)/m)[1];
if (!slug) {
return;
}
const { createdAt, dateAndTime } = await getTimestamp(slug, 'clip');
if (url.hostname === 'clips.twitch.tv') {
clipsSubdomain(createdAt, dateAndTime);
return;
}
insertMainWebsite(createdAt, dateAndTime, false);
}
/**
* Fetch video information via getTimestamp() and insert accordingly.
*
* @param {URL} url
* @returns {void}
*/
async function fetchVideo(url)
{
const pathFragments = url.pathname.split('/');
const videoFragment = pathFragments[pathFragments.length - 1];
const videoId = videoFragment.match(/(^\d+$)/m)[1];
if (!videoId) {
return;
}
const { createdAt, dateAndTime } = await getTimestamp(videoId, 'video');
insertMainWebsite(createdAt, dateAndTime, true);
}
/**
* Observe the DOM until we find the element we're interested in.
* Once complete, disconnect the observer and call the `fetchClip()` function which actually inserts the
* timestamp into the DOM.
*/
let checkedUrl = null;
function observerHandler(mutations, observer)
{
// clips.twitch.tv
const clipsInfo = document.querySelector('.clips-chat-info span[class*="CoreText"]');
// www.twitch.tv
const timestampBar = document.querySelector('.timestamp-metadata__bar');
if (!clipsInfo && !timestampBar) {
return;
}
const urlString = window.location.href;
if (urlString === checkedUrl) {
return;
}
checkedUrl = urlString;
console.log('Clips page', clipsInfo !== null);
console.log('Main website', timestampBar !== null);
const url = new URL(urlString);
if (url.hostname === 'www.twitch.tv' && url.pathname.includes('/videos/')) {
fetchVideo(url);
}
else {
fetchClip(url);
}
}
const observer = new MutationObserver(observerHandler);
observer.observe(document, {
attributes: false,
childList: true,
characterData: false,
subtree: true,
});
@jis5ey
Copy link

jis5ey commented Apr 25, 2020

great script! ty so much! 👍

@willywaggler
Copy link

Does this script still work? Not showing up for me

@Decicus
Copy link
Author

Decicus commented Jul 20, 2020

@willywaggler

Does this script still work? Not showing up for me

Yep, just tested it. Works for me without any issues on both Firefox and Chrome.

@whodatboi
Copy link

I feel lame asking this but how do I use it? I have it all downloaded i just have no clue how to us it.

@Decicus
Copy link
Author

Decicus commented Oct 26, 2020

I feel lame asking this but how do I use it? I have it all downloaded i just have no clue how to us it.

Once you've followed the installation steps then you just have to open a clip page (https://clips.twitch.tv/ConfidentPlainWrenchBuddhaBar) and it should show the date/time like the screenshot.
Keep in mind it only works on clips that are on URLs that look like https://clips.twitch.tv/ and not https://www.twitch.tv/CHANNEL_NAME/clip/...

@KaiStarkk
Copy link

@Decicus

Here's a version to automatically replace video timestamps to make them more useful.

Not an expert on GitHub gists and making pull requests / etc., would be awesome if you could include this in the next script update though.

// @match        https://www.twitch.tv/videos/*
// ==/UserScript==

async function fetchVideo() {
    const slug = window.location.href.match(/https\:\/\/www\.twitch\.tv\/videos\/([0-9-_]+)/m)[1];
    
    if (!slug) {
        return;
    }

    const response = await fetch(`https://api.twitch.tv/kraken/videos/${slug}`, {
        headers: {
            Accept: 'application/vnd.twitchtv.v5+json',
            'Client-ID': 'zs377ogpzz01ogfx26pvbddx9jodg1',
        },
    });

    const data = await response.json();

    if (!data.created_at) {
        return;
    }

    const created = new Date(data.created_at);
    const dateAndTime = created.toLocaleString('en-GB', { timeZone: 'UTC' });

    document.getElementsByClassName('CoreText-sc-cpl358-0 eVTFAj')[0].innerHTML = dateAndTime;

}

/**
 * Observe the DOM until we find the element we're interested in.
 * Once complete, disconnect the observer and call the `fetchClip()` function which actually inserts the
 * timestamp into the DOM.
 */
function observerHandler(mutations, observer)
{
    const textElement = document.querySelector('p[class*="CoreText-sc-cpl358-0 eVTFAj"]');
    
    if (!textElement) {
        return;
    }
    
    fetchVideo();
    observer.disconnect();
}

const observer = new MutationObserver(observerHandler);
observer.observe(document, {
    attributes: false,
    childList: true,
    characterData: false,
    subtree: true,
});

@Decicus
Copy link
Author

Decicus commented Sep 1, 2021

@KaiStarkk

@Decicus

Here's a version to automatically replace video timestamps to make them more useful.

Not an expert on GitHub gists and making pull requests / etc., would be awesome if you could include this in the next script update though.

Thanks for the suggestion. I don't really watch VODs/highlights, so never really thought of it, but maybe I'll add support for those alongside adding support for the clip pages that aren't on clips.twitch.tv. Though I'd likely handle it a bit differently than your example.

@dani1113
Copy link

dani1113 commented May 9, 2024

Hi! I know its been a while since the last update, but Twitch has make changes to his UI (-.-) and the script doesn't work anymore con the clips.twitch.tv website. Im wondering if you are going to update the script, I love this tool, its really useful to me to search old clips. I use it along TwitchTracker filtering the clips by date. I cant even count how many times it has helped me finding great moments clipped while ago, without it, those clips would probably have been lost in the insane amount of clips created everyday. Thanks a lot! <33

@Decicus
Copy link
Author

Decicus commented May 9, 2024

@dani1113

Hi! I know its been a while since the last update, but Twitch has make changes to his UI (-.-) and the script doesn't work anymore con the clips.twitch.tv website. Im wondering if you are going to update the script, I love this tool, its really useful to me to search old clips. I use it along TwitchTracker filtering the clips by date. I cant even count how many times it has helped me finding great moments clipped while ago, without it, those clips would probably have been lost in the insane amount of clips created everyday. Thanks a lot! <33

Yeah, I noticed the layout changed on clips.twitch.tv, but I honestly forgot about the script 🙃

Script has been updated to v0.7.0 to support the new clips.twitch.tv layout. It seems they made it a bit more consistent with the layout they have on the main website, so in a sense I don't consider it a bad change.
Do note that the timestamp has now moved to be below the video player instead of on top of chat now.

You can either just click the "check for updates" button in your userscript manager, or alternatively click this link which should prompt to "reinstall" the userscript.

@dani1113
Copy link

dani1113 commented May 9, 2024

@Decicus

Yeah, I noticed the layout changed on clips.twitch.tv, but I honestly forgot about the script 🙃

Script has been updated to v0.7.0 to support the new clips.twitch.tv layout. It seems they made it a bit more consistent with the layout they have on the main website, so in a sense I don't consider it a bad change. Do note that the timestamp has now moved to be below the video player instead of on top of chat now.

You can either just click the "check for updates" button in your userscript manager, or alternatively click this link which should prompt to "reinstall" the userscript.

Thanks a lot for the fix, this tool deserves a lot more recognition than it has, its so so usefull, i dont understand why Twitch dont show the full info of the clip created instead of the "3 years ago" thing.
Again, thanks! <33 😊👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment