Rai Play video download

This script allows you to download videos on Rai Play

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name            Rai Play video download
// @namespace       Rai 2025 Video
// @version         1.0
// @description     This script allows you to download videos on Rai Play
// @description:it  Questo script ti permette di scaricare i video su Rai Play
// @license         GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// @match        *://*.raiplay.it/*
// @author          Science
// ==/UserScript==

(function() {
    'use strict';

    const interceptedUrls = new Set();

    // Funzione per creare un box informativo con 2 pulsanti
    function createInfoBox(m3u8Url) {
        const existing = document.getElementById('videoUrlInfo');
        if (existing) existing.remove();

        const box = document.createElement('div');
        box.id = 'videoUrlInfo';
        box.style = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: white;
            padding: 15px;
            z-index: 999999;
            border: 2px solid green;
            max-width: 600px;
            font-family: Arial, sans-serif;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
        `;

        box.innerHTML = `
            <h3 style="margin-top:0;color:#4CAF50">URL .m3u8 Rilevato</h3>
            <input type="text" 
                   value="${m3u8Url}" 
                   style="width:100%; margin-bottom:10px;" 
                   readonly>
            <button onclick="downloadM3U8('${m3u8Url}')"
                    style="margin-right:10px; background-color: #4CAF50; color: white; border: none; padding: 5px 10px; cursor: pointer;">
                Scarica .m3u8
            </button>
            <button onclick="copyToClipboard('${m3u8Url}')"
                    style="margin-right:10px; background-color: #2196F3; color: white; border: none; padding: 5px 10px; cursor: pointer;">
                Copia URL
            </button>
            <button onclick="this.parentNode.remove()"
                    style="background-color: #f44336; color: white; border: none; padding: 5px 10px; cursor: pointer;">
                Chiudi
            </button>
        `;

        document.body.appendChild(box);
    }

    // Funzione per scaricare il file .m3u8
    function downloadM3U8(url) {
        const filename = url.split('/').pop().split('?')[0] || 'playlist.m3u8';
        GM_download({
            url: url,
            name: filename,
            onload: () => GM_notification({ title: 'Download Completato', text: `File salvato come ${filename}` }),
            onerror: (e) => GM_notification({ title: 'Errore', text: `Download fallito: ${e.error}` })
        });
    }

    // Funzione per copiare l'URL negli appunti
    function copyToClipboard(text) {
        GM_setClipboard(text, 'text');
        GM_notification({ title: 'URL Copiato', text: 'L\'URL è stato copiato negli appunti.' });
    }

    // Intercetta le richieste XMLHttpRequest
    const originalOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url) {
        if (url && url.includes('.m3u8')) {
            this.addEventListener('load', function() {
                if (!interceptedUrls.has(url)) {
                    interceptedUrls.add(url);
                    createInfoBox(url);
                }
            });
        }
        originalOpen.apply(this, arguments);
    };

    // Intercetta le richieste fetch
    const originalFetch = window.fetch;
    window.fetch = function(input, init) {
        const url = typeof input === 'string' ? input : input.url;
        if (url && url.includes('.m3u8')) {
            return originalFetch.apply(this, arguments).then(response => {
                if (!interceptedUrls.has(url)) {
                    interceptedUrls.add(url);
                    createInfoBox(url);
                }
                return response;
            });
        }
        return originalFetch.apply(this, arguments);
    };

    // Periodicamente controlla elementi video
    setInterval(() => {
        document.querySelectorAll('video').forEach(video => {
            if (video.src && video.src.includes('.m3u8') && !interceptedUrls.has(video.src)) {
                interceptedUrls.add(video.src);
                createInfoBox(video.src);
            }
        });
    }, 3000);
})();