This script allows you to easily obtain the URL of the current live Twitch stream and its VOD with the exact timestamp
// ==UserScript==
// @name TwichVODLinker
// @version 1.0
// @description This script allows you to easily obtain the URL of the current live Twitch stream and its VOD with the exact timestamp
// @author alejandroxv
// @match *://*.twitch.tv/*
// @grant none
// @require https://code.jquery.com/jquery-3.6.0.min.js
// @namespace https://greasyfork.org/users/1351311
// ==/UserScript==
(function() {
'use strict';
let videoId = null;
// Recursive function to find the video ID
function findVideoId(obj) {
if (typeof obj !== 'object' || obj === null) return null;
if (obj.user && obj.user.videos && obj.user.videos.edges && obj.user.videos.edges[0] && obj.user.videos.edges[0].node) {
return obj.user.videos.edges[0].node.id;
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
let result = findVideoId(obj[key]);
if (result) return result;
}
}
return null;
}
// Save the original fetch function
const originalFetch = window.fetch;
// Override the fetch function
window.fetch = function() {
const args = arguments;
if (args[0].includes('https://gql.twitch.tv/gql')) {
const requestBody = args[1]?.body;
if (requestBody && requestBody.includes("ChannelRoot_AboutPanel")) {
return originalFetch.apply(this, arguments).then(response => {
const clonedResponse = response.clone();
clonedResponse.json().then(data => {
videoId = findVideoId(data);
if (videoId) {
console.log("Video ID found: ", videoId);
} else {
console.log("No video ID found in the response.");
}
});
return response;
});
}
}
return originalFetch.apply(this, arguments);
};
// Function to show the modal with the URL
function showModal(url) {
const modalHtml = `
<div id="videoUrlModal" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
background-color: white; padding: 20px; box-shadow: 0 0 10px rgba(0,0,0,0.5); z-index: 10000;">
<h3>Video URL</h3>
<input type="text" value="${url}" style="width: 100%;" readonly>
<button id="closeModal" style="margin-top: 10px;">Close</button>
</div>
`;
$('body').append(modalHtml);
$('#closeModal').on('click', function() {
$('#videoUrlModal').remove();
});
}
// Function to transform live-time elements
function transformLiveTime() {
$('.live-time').each(function() {
const $this = $(this);
if (!$this.data('transformed')) {
$this.css('cursor', 'pointer');
$this.attr('title', 'Click to show video URL');
$this.data('transformed', true);
$this.on('click', function() {
if (videoId) {
const timeParts = $this.text().split(':');
const hours = timeParts.length === 3 ? timeParts[0] : '00';
const minutes = timeParts.length >= 2 ? timeParts[timeParts.length - 2] : '00';
const seconds = timeParts[timeParts.length - 1];
const url = `https://www.twitch.tv/videos/${videoId}?t=${hours}h${minutes}m${seconds}s`;
showModal(url);
} else {
alert('No video ID found to display.');
}
});
}
});
}
// Mutation observer to detect DOM changes
const observer = new MutationObserver(transformLiveTime);
observer.observe(document.body, { childList: true, subtree: true });
// Call the function initially
$(document).ready(transformLiveTime);
})();