YouTube Stream Timestamp Logger

Logs the current YouTube stream URL, timestamp, and timestamped URL in shortened format

// ==UserScript==
// @name         YouTube Stream Timestamp Logger
// @namespace    http://tampermonkey.net/
// @version      420.69
// @description  Logs the current YouTube stream URL, timestamp, and timestamped URL in shortened format
// @author       Kai Amamiya / ModernDisappointment | using the help of ChatGPT 3.0
// @license      MIT
// @match        *://www.youtube.com/watch*
// ==/UserScript==

(function() {
    'use strict';

    // Function to convert seconds to HH:MM:SS.sss format
    function formatTime(seconds) {
        let hours = Math.floor(seconds / 3600);
        let minutes = Math.floor((seconds % 3600) / 60);
        let secs = (seconds % 60).toFixed(3);
        return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(6, '0')}`;
    }

    // Function to convert seconds to URL timestamp format
    function secondsToURLTimestamp(seconds) {
        return Math.floor(seconds); // Round down to the nearest whole number
    }

    // Function to copy text to clipboard
    function copyToClipboard(text) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);
    }

    // Function to log and copy the current media time and video URL
    function logVideoDetails() {
        const ytPlayer = document.querySelector('video');
        if (ytPlayer) {
            const currentTime = ytPlayer.currentTime;
            const videoURL = window.location.href;
            const timestamp = formatTime(currentTime);
            const urlTimestamp = secondsToURLTimestamp(currentTime);
            // Extract video ID from the URL
            const videoIdMatch = videoURL.match(/[?&]v=([a-zA-Z0-9_-]+)/);
            const videoId = videoIdMatch ? videoIdMatch[1] : '';
            const timestampedURL = `https://youtu.be/${videoId}?t=${urlTimestamp}`;
            const output = `Note: \nVideo URL: ${videoURL}\nTimestamp: ${timestamp}\nVideo URL w/ Time: ${timestampedURL}`;
            console.log(output);
            copyToClipboard(output);
            alert('Video URL, Timestamp, and Timestamped URL copied to clipboard!');
        } else {
            console.log('YouTube video element not found.');
        }
    }
    // Function to create or remove the button based on the page state
    function updateButton() {
        // Check if we are on a YouTube video or stream page
        const isYouTubeVideoPage = /\/watch\?v=/.test(window.location.href) || /\/live/.test(window.location.href);
        const isVideoPage = document.querySelector('video') !== null;
        const isFullscreen = document.fullscreenElement !== null;

        if (isYouTubeVideoPage && isVideoPage && !isFullscreen) {
            if (!document.getElementById('copyTimestampButton')) {
                const button = document.createElement('button');
                button.id = 'copyTimestampButton';
                button.innerHTML = 'Timestamp';
                button.style.position = 'fixed';
                button.style.bottom = '10px';
                button.style.left = '10px';
                button.style.zIndex = '9999';
                button.style.padding = '10px';
                button.style.backgroundColor = '#404040';
                button.style.color = '#FFFFFF';
                button.style.border = 'none';
                button.style.cursor = 'pointer';
                button.addEventListener('click', logVideoDetails);
                document.body.appendChild(button);
            }
        } else {
            const button = document.getElementById('copyTimestampButton');
            if (button) {
                button.remove();
            }
        }
    }

    // Set up observers to check for changes
    function setupObservers() {
        // Monitor for changes in the page that might indicate a video or fullscreen state change
        const observer = new MutationObserver(updateButton);
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // Also check for fullscreen changes
        document.addEventListener('fullscreenchange', updateButton);
    }

    // Initialize observers when the page loads
    window.addEventListener('load', setupObservers);
    // Also check initially if on a video page
    window.addEventListener('load', updateButton);
})();