YouTube → SkipCut Link Rewriter

Rewrite YouTube links to SkipCut links before they are opened

// ==UserScript==
// @name         YouTube → SkipCut Link Rewriter
// @namespace    https://greasyfork.org/nl/users/1197317-opus-x
// @version      1.04
// @description  Rewrite YouTube links to SkipCut links before they are opened
// @author       Opus-X
// @license      MIT
// @icon         https://www.skipcut.com/favicon.ico
// @match        *://*/*
// @exclude      *://skipcut.com/*
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    const TARGET_TAB_NAME = 'SkipCutTab';

    // Convert a YouTube URL to the corresponding SkipCut URL
    function convertYouTubeToSkipCut(url) {
        // Quick check to avoid parsing non-YouTube links
        if (!url.includes('youtube.com') && !url.includes('youtu.be')) return null;

        try {
            const u = new URL(url);
            const { hostname, pathname, searchParams } = u;

            // Handle normal YouTube domain
            if (hostname.match(/(^|\.)youtube\.com$/)) {
                // Regular video links: /watch?v=...
                if (pathname === '/watch' && searchParams.has('v')) {
                    return `https://www.skipcut.com/watch?v=${searchParams.get('v')}`;
                }

                // Live streams: /live/<id>
                if (pathname.startsWith('/live/')) {
                    const liveId = pathname.split('/')[2];
                    if (liveId) return `https://www.skipcut.com/live/${liveId}`;
                }

                // Playlists: /playlist?list=...
                if (pathname === '/playlist' && searchParams.has('list')) {
                    return `https://www.skipcut.com/playlist?list=${searchParams.get('list')}`;
                }
            }

            // Handle youtu.be short links: https://youtu.be/<id>
            if (hostname === 'youtu.be') {
                const videoId = pathname.slice(1); // remove leading "/"
                if (videoId) return `https://www.skipcut.com/watch?v=${videoId}`;
            }
        } catch (e) {
            // Ignore invalid URLs
        }

        return null; // Not a YouTube link we can convert
    }

    // Rewrite YouTube links to SkipCut links with target attribute
    function rewriteLinks() {
        const links = document.querySelectorAll('a[href*="youtube.com"], a[href*="youtu.be"]');
        links.forEach(link => {
            const newUrl = convertYouTubeToSkipCut(link.href);
            if (newUrl) {
                link.href = newUrl;
                link.setAttribute('target', TARGET_TAB_NAME);
            }
        });
    }

    // Run rewrite on page load
    document.addEventListener('DOMContentLoaded', rewriteLinks);

    // Observe DOM changes to rewrite dynamically added links
    const observer = new MutationObserver(rewriteLinks);
    observer.observe(document.body, { childList: true, subtree: true });

    // Intercept clicks to ensure direct opening in TARGET_TAB_NAME
    document.addEventListener('click', e => {
        // Only handle left-clicks without modifier keys
        if (e.button !== 0 || e.ctrlKey || e.shiftKey || e.metaKey) return;

        const a = e.target.closest('a[href]'); // Find closest link
        if (!a) return;

        const newUrl = convertYouTubeToSkipCut(a.href);
        if (!newUrl) return;

        // Prevent normal navigation
        e.preventDefault();
        e.stopImmediatePropagation(); // Stop site scripts like YouTube router

        // Open directly in the named tab
        window.open(newUrl, TARGET_TAB_NAME);
    }, true); // Capture phase to run before site handlers
})();