Bouton Téléchargement Multi-Sites (Y2Mate, SaveTheVideo pour X)

Ajoute des boutons pour télécharger des vidéos via Y2Mate (FR) et SaveTheVideo (X/Twitter), avec une option pour les masquer via un raccourci clavier

目前為 2025-01-31 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Bouton Téléchargement Multi-Sites (Y2Mate, SaveTheVideo pour X)
// @namespace    https://gf.qytechs.cn/
// @version      1.10
// @description  Ajoute des boutons pour télécharger des vidéos via Y2Mate (FR) et SaveTheVideo (X/Twitter), avec une option pour les masquer via un raccourci clavier
// @author       TonNom
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let isButtonVisible = true;

    function addDownloadButtons() {
        const videos = document.querySelectorAll('video');
        if (videos.length === 0) return;

        videos.forEach(video => {
            if (video.dataset.hasDownloadButtons) return;
            video.dataset.hasDownloadButtons = true;

            const container = document.createElement('div');
            container.style.position = 'absolute';
            container.style.top = '10px';
            container.style.right = '10px';
            container.style.zIndex = '1000';
            container.style.display = 'flex';
            container.style.flexDirection = 'column';
            container.style.gap = '5px';

            // Bouton pour Y2Mate
            const y2mateButton = document.createElement('button');
            y2mateButton.innerText = 'Télécharger via Y2Mate (FR)';
            y2mateButton.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
            y2mateButton.style.color = 'white';
            y2mateButton.style.border = 'none';
            y2mateButton.style.padding = '8px 12px';
            y2mateButton.style.fontSize = '12px';
            y2mateButton.style.cursor = 'pointer';
            y2mateButton.style.borderRadius = '5px';
            y2mateButton.style.opacity = '0.8';
            y2mateButton.onmouseenter = () => { y2mateButton.style.opacity = '1'; };
            y2mateButton.onmouseleave = () => { y2mateButton.style.opacity = '0.8'; };
            y2mateButton.onclick = () => openY2Mate(video);
            container.appendChild(y2mateButton);

            // Bouton pour SaveTheVideo (X/Twitter)
            const saveTheVideoButton = document.createElement('button');
            saveTheVideoButton.innerText = 'Télécharger via SaveTheVideo (X/Twitter)';
            saveTheVideoButton.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
            saveTheVideoButton.style.color = 'white';
            saveTheVideoButton.style.border = 'none';
            saveTheVideoButton.style.padding = '8px 12px';
            saveTheVideoButton.style.fontSize = '12px';
            saveTheVideoButton.style.cursor = 'pointer';
            saveTheVideoButton.style.borderRadius = '5px';
            saveTheVideoButton.style.opacity = '0.8';
            saveTheVideoButton.onmouseenter = () => { saveTheVideoButton.style.opacity = '1'; };
            saveTheVideoButton.onmouseleave = () => { saveTheVideoButton.style.opacity = '0.8'; };
            saveTheVideoButton.onclick = () => openSaveTheVideo(video);
            container.appendChild(saveTheVideoButton);

            video.parentNode.style.position = 'relative';
            video.parentNode.appendChild(container);
        });
    }

    function openY2Mate(video) {
        let videoUrl = video.querySelector('source')?.src || video.src;
        if (!videoUrl) {
            alert('Impossible de détecter la vidéo');
            return;
        }

        if (window.location.hostname.includes('youtube.com')) {
            const videoId = new URLSearchParams(window.location.search).get('v');
            if (videoId) {
                // Version française de Y2Mate pour YouTube
                window.open(`https://www.y2mate.com/fr/youtube/${videoId}`, '_blank');
                return;
            }
        }

        alert("Ce site ne permet pas la récupération directe via Y2Mate.");
    }

    function openSaveTheVideo(video) {
        let videoUrl = video.querySelector('source')?.src || video.src;
        if (!videoUrl) {
            alert('Impossible de détecter la vidéo');
            return;
        }

        // Vérification si l'URL provient de X (anciennement Twitter)
        if (window.location.hostname.includes('x.com')) {
            // Tentative d'extraction de l'URL de la vidéo à partir des données de la page
            const videoElement = document.querySelector('video');
            if (videoElement) {
                const videoSrc = videoElement.src || videoElement.querySelector('source')?.src;
                if (videoSrc && !videoSrc.startsWith('blob:')) {
                    window.open(`https://www.savethevideo.com/?url=${encodeURIComponent(videoSrc)}`, '_blank');
                    return;
                } else {
                    // Si c'est un `blob:` URL, essayer d'extraire l'URL du réseau ou du média
                    fetchVideoUrlFromNetwork().then((finalUrl) => {
                        if (finalUrl) {
                            window.open(`https://www.savethevideo.com/?url=${encodeURIComponent(finalUrl)}`, '_blank');
                        } else {
                            alert('Impossible de récupérer l\'URL de la vidéo depuis X.com.');
                        }
                    });
                    return;
                }
            }
        }

        alert("Impossible de récupérer l'URL de la vidéo depuis X (anciennement Twitter).");
    }

    async function fetchVideoUrlFromNetwork() {
        // Vérifier le réseau pour l'URL de la vidéo
        try {
            const response = await fetch(window.location.href, { method: 'GET' });
            const text = await response.text();

            // Chercher un modèle d'URL vidéo dans la page (X.com spécifique)
            const regex = /"video_url":"(https:\/\/video\.x\.com\/.*?\.mp4)"/;
            const match = text.match(regex);

            if (match && match[1]) {
                return match[1];
            }
        } catch (error) {
            console.error('Erreur lors de la récupération de l\'URL de la vidéo :', error);
        }
        return null;
    }

    function observeDOMChanges() {
        const observer = new MutationObserver(addDownloadButtons);
        observer.observe(document.body, { childList: true, subtree: true });
    }

    function toggleButtonsVisibility() {
        isButtonVisible = !isButtonVisible;
        document.querySelectorAll('div').forEach(container => {
            if (container.childNodes.length && container.childNodes[0].innerText.includes('Télécharger via')) {
                container.style.display = isButtonVisible ? 'block' : 'none';
            }
        });
    }

    document.addEventListener('keydown', (event) => {
        if (event.key === 'h') { // Appuyer sur 'h' pour masquer/afficher les boutons
            toggleButtonsVisibility();
        }
    });

    window.addEventListener('load', () => {
        addDownloadButtons();
        observeDOMChanges();
    });

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址