您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
This script allows you to download videos on Rai Play
当前为
// ==UserScript== // @name Rai Play video download // @namespace http://andrealazzarotto.com // @version 11.0.11 // @description This script allows you to download videos on Rai Play // @description:it Questo script ti permette di scaricare i video su Rai Play // @author Andrea Lazzarotto // @match https://www.raiplay.it/* // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/foundation-essential/6.2.2/js/foundation.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/arrive/2.4.1/arrive.min.js // @require https://unpkg.com/@ungap/[email protected]/min.js // @grant GM_xmlhttpRequest // @grant GM.xmlHttpRequest // @connect rai.it // @connect akamaized.net // @connect msvdn.net // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html // ==/UserScript== /* Greasemonkey 4 wrapper */ if (typeof GM !== "undefined" && !!GM.xmlHttpRequest) { GM_xmlhttpRequest = GM.xmlHttpRequest; } function fetch(params) { return new Promise(function(resolve, reject) { params.onload = resolve; params.onerror = reject; GM_xmlhttpRequest(params); }); } (function() { 'use strict'; var Foundation = window.Foundation; var download_icon = '<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"><path d="M42 40v4H6v-4h36zM20 24v-8h8v8h7L24 37 13 24h7zm8-14v4h-8v-4h8zm0-6v4h-8V4h8z" /></svg>'; var showModal = (title, content) => { var modal = $(` <div id="video-download-modal" class="small reveal" data-reveal aria-labelledby="Download video"> <h2 id="modal-title">${title}</h2> <div id="modal-content"></div> <button class="close-button" data-close aria-label="Chiudi finestrella" type="button"> <span aria-hidden="true">×</span> </button> </div> `); modal.css({ 'background-color': '#001623', }); modal.find('#modal-content').append(content); var instance = new Foundation.Reveal(modal); instance.open(); modal.find('.close-button').css({ 'color': 'white', }).click(() => instance.close()); // Prevent fullscreen issues $(".vjs-fullscreen-control:contains('Exit')").click(); }; var checkQuality = (url, rate) => { return fetch({ method: 'GET', url: url, headers: { 'User-Agent': 'raiweb', 'Range': 'bytes=0-255', }, }).then( (response) => { let headers = fromEntries(response.responseHeaders.split("\n").map(element => element.trim().toLowerCase().split(":"))); let range = headers['content-range'] || '/0'; let size = +(range.split('/').slice(1,)[0] || 0); let megabytes = Math.round(size / 1024 / 1024); if (size > 102400) { return { quality: rate, url: url, megabytes: megabytes }; } else { return null; } }, () => null ); } var qualities = async (url) => { var ending = url.match(/_[1-9]+0?00\.mp4/); if (!ending || !ending.length) { let result = await checkQuality(url, ''); return [result]; } var results = await Promise.all([5000, 3200, 2401, 2400, 1800, 1500, 1200, 800, 600, 400].map(rate => { var quality_url = url.replace(/_[1-9]+0?00\.mp4/, `_${rate}.mp4`); return checkQuality(quality_url, rate); })); return results.filter(value => (value !== null)); }; var DRMError = () => { showModal('Niente da fare...', "<p>Non è stato possibile trovare un link del video in formato MP4. Il video sembra essere protetto da DRM.</p>"); }; var getVideo = () => { var path = location.href.replace(/\.html(\?.*)?$/, '.json'); $.getJSON(path).then((data) => { var secure = data.video.content_url.replace('http://', 'https://'); return fetch({ method: 'HEAD', url: secure, headers: { 'User-Agent': 'raiweb', }, }).then( (response) => { var valid = response.finalUrl.indexOf('mp4') > 0 && response.finalUrl.indexOf('DRM_') < 0; if (!valid) { DRMError(); } else { qualities(response.finalUrl).then(results => { var buttons = ''; results.forEach(video => { buttons += `<a href="${video.url}" class="button" target="_blank">MP4 ${video.quality} (${video.megabytes} MB)</a>`; }); showModal('Link diretti', ` <p>Clicca un bottone per aprire il video in formato MP4. Usa il tasto destro per salvarlo.</p> <p><strong>Per evitare interruzioni è raccomandato l'uso di un download manager.</strong></p> <p>${buttons}</p>`); }); } }, (response) => { console.log(response); var drm = response.finalUrl.indexOf('DRM_') > 0 || response.status === 0; if (drm) { DRMError(); } else { showModal('Errore di rete', "<p>Si è verificato un errore di rete. Riprova più tardi.</p>"); } } ); }); }; var downloadButton = () => { if ($('#video-download-button').length) { return; } $('rai-player .vjs-custom-control-spacer').after(` <button id="video-download-button" class="vjs-control vjs-button" aria-disabled="false"> <span aria-hidden="true" class="vjs-icon-placeholder">${download_icon}</span> <span class="vjs-control-text" aria-live="polite">Download</span> </button> `); $('#video-download-button').css({ 'order': 110, }).click(getVideo).find('svg').css({ 'fill': '#039cf9', 'height': '1.5em', }); }; $(document).arrive('rai-player .vjs-custom-control-spacer', () => { downloadButton(); }); var isAnon = function() { return !!$('#accountPanelLoginPanel').is(':visible'); }; $(document).ready(() => { if (location.pathname.startsWith('/video')) { $('rai-sharing').after(` <a id="inline-download-button" class="cell small-4 medium-shrink highlight__share" aria-label="Download"> <div class="leaf__share__button button button--light-ghost button--circle float-center">${download_icon}</div> <span class="button-label">Download</span> </a> `); $('#inline-download-button').click(getVideo); } $('body').on('touchstart mousedown', 'a.card-item__link', (event) => { if (isAnon() && event.which !== 3) { location.href = $(event.currentTarget).attr('href'); } }); $('body').on('touchstart mousedown', 'button[data-video-json]', (event) => { if (isAnon() && event.which !== 3) { location.href = $(event.currentTarget).data('video-json').replace(/\.json/, '.html'); } }); }); })();