YouTube → SkipCut 链接重写器

在打开之前将 YouTube 链接重写为 SkipCut 链接

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         YouTube → SkipCut Link Rewriter
// @name:en      YouTube → SkipCut Link Rewriter
// @name:nl      YouTube → SkipCut Link Herschrijver
// @name:es      Reescritor de Enlaces de YouTube a SkipCut
// @name:fr      Réécriture des Liens YouTube vers SkipCut
// @name:de      YouTube → SkipCut Link-Umschreiber
// @name:zh-CN   YouTube → SkipCut 链接重写器
// @name:ja      YouTube → SkipCut リンク書き換え
// @name:ru      Переписчик ссылок YouTube на SkipCut
// @name:pt      Reescritor de Links do YouTube para SkipCut
// @name:it      Riscrittore di Link da YouTube a SkipCut
// @namespace    https://greasyfork.org/nl/users/1197317-opus-x
// @version      1.06
// @description  Rewrite YouTube links to SkipCut links before they are opened
// @description:en Rewrite YouTube links to SkipCut links before they are opened
// @description:nl Herschrijf YouTube-links naar SkipCut-links voordat ze worden geopend
// @description:es Reescribe los enlaces de YouTube a enlaces de SkipCut antes de que se abran
// @description:fr Réécrit les liens YouTube en liens SkipCut avant leur ouverture
// @description:de Schreibe YouTube-Links in SkipCut-Links um, bevor sie geöffnet werden
// @description:zh-CN 在打开之前将 YouTube 链接重写为 SkipCut 链接
// @description:ja YouTubeリンクをSkipCutリンクに書き換えてから開く
// @description:ru Переписывает ссылки YouTube на ссылки SkipCut перед их открытием
// @description:pt Reescreve links do YouTube para links SkipCut antes de serem abertos
// @description:it Riscrive i link di YouTube in link SkipCut prima che vengano aperti
// @author       Opus-X
// @license      MIT
// @icon         https://www.skipcut.com/favicon.ico
// @match        *://*/*
// @exclude      *://skipcut.com/*
// @exclude      *://www.skipcut.com/*
// @exclude      *://youtube.com/*
// @exclude      *://www.youtube.com/*
// @exclude      *://youtube-nocookie.com/*
// @exclude      *://www.youtube-nocookie.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
})();