RD-MagnetDL

Real-Debrid.com magnet link converter with streaming support, adds a tab for a converted magnet to RD download and streaming link and then copies to the clipboard when you click on it

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         RD-MagnetDL
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Real-Debrid.com magnet link converter with streaming support, adds a tab for a converted magnet to RD download and streaming link and then copies to the clipboard when you click on it
// @author       goodchoice
// @license      MIT
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';

    const API_KEY = '';
    const BASE_URL = 'https://api.real-debrid.com/rest/1.0/';

    function convertMagnetToRD(magnetLink, isStreaming = false, button) {
        console.log(`Converting magnet link: ${magnetLink}, isStreaming: ${isStreaming}`);
        GM_xmlhttpRequest({
            method: 'POST',
            url: `${BASE_URL}torrents/addMagnet`,
            data: `magnet=${encodeURIComponent(magnetLink)}`,
            headers: {
                Authorization: `Bearer ${API_KEY}`,
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            onload: function(response) {
                console.log('addMagnet response:', response);
                if (response.status === 201) {
                    const torrentId = JSON.parse(response.responseText).id;
                    console.log('Torrent ID:', torrentId);
                    // Select files regardless of the action (download or stream)
                    selectFiles(torrentId, isStreaming, button);
                } else {
                    console.error('Error adding magnet:', response.status, response.responseText);
                    alert('Error adding magnet link. Check console for details.');
                    resetButton(button);
                }
            },
            onerror: function(error) {
                console.error('Request failed:', error);
                alert('Network error. Check console for details.');
                resetButton(button);
            }
        });
    }

    function selectFiles(torrentId, isStreaming, button) {
        console.log(`Selecting files for torrent ID: ${torrentId}`);
        GM_xmlhttpRequest({
            method: 'POST',
            url: `${BASE_URL}torrents/selectFiles/${torrentId}`,
            data: 'files=all',
            headers: {
                Authorization: `Bearer ${API_KEY}`,
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            onload: function(response) {
                console.log('selectFiles response:', response);
                if (response.status === 204) {
                    if (isStreaming) {
                        getStreamingLink(torrentId, button);
                    } else {
                        getDownloadLink(torrentId, button);
                    }
                } else {
                    console.error('Error selecting files:', response.status, response.responseText);
                    alert('Error selecting files. Check console for details.');
                    resetButton(button);
                }
            },
            onerror: function(error) {
                console.error('Request failed:', error);
                alert('Network error. Check console for details.');
                resetButton(button);
            }
        });
    }

    function getDownloadLink(torrentId, button) {
        console.log(`Getting download link for torrent ID: ${torrentId}`);
        GM_xmlhttpRequest({
            method: 'GET',
            url: `${BASE_URL}torrents/info/${torrentId}`,
            headers: {
                'Authorization': `Bearer ${API_KEY}`
            },
            onload: function(response) {
                console.log('getDownloadLink response:', response);
                if (response.status === 200) {
                    const downloadLinks = JSON.parse(response.responseText).links;
                    unrestrictLinks(downloadLinks, button);
                } else {
                    console.error('Error getting download link:', response.status, response.responseText);
                    alert('Error getting download link. Check console for details.');
                    resetButton(button);
                }
            },
            onerror: function(error) {
                console.error('Request failed:', error);
                alert('Network error. Check console for details.');
                resetButton(button);
            }
        });
    }

    function unrestrictLinks(links, button) {
        console.log('Unrestricting links:', links);
        const unrestrictedLinks = [];

        function processLink(index) {
            if (index >= links.length) {
                console.log('Unrestricted download links:', unrestrictedLinks);
                GM_setClipboard(unrestrictedLinks.join('\n'));
                alert('Unrestricted download links copied to clipboard!');
                resetButton(button);
                return;
            }

            const link = links[index];
            GM_xmlhttpRequest({
                method: 'POST',
                url: `${BASE_URL}unrestrict/link`,
                data: `link=${encodeURIComponent(link)}`,
                headers: {
                    Authorization: `Bearer ${API_KEY}`,
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                onload: function(response) {
                    console.log(`Unrestricting link ${link}:`, response);
                    if (response.status === 200) {
                        const unrestrictedLink = JSON.parse(response.responseText).download;
                        unrestrictedLinks.push(unrestrictedLink);
                        processLink(index + 1);
                    } else {
                        console.error('Error unrestricting link:', response.status, response.responseText);
                        alert(`Error unrestricting link: ${link}`);
                        resetButton(button);
                    }
                },
                onerror: function(error) {
                    console.error('Request failed:', error);
                    alert('Network error during link unrestriction. Check console for details.');
                    resetButton(button);
                }
            });
        }

        processLink(0);
    }

    function getStreamingLink(torrentId, button) {
        console.log(`Getting streaming link for torrent ID: ${torrentId}`);

        GM_xmlhttpRequest({
            method: 'GET',
            url: `${BASE_URL}torrents/info/${torrentId}`,
            headers: {
                'Authorization': `Bearer ${API_KEY}`
            },
            onload: function(response) {
                console.log('getTorrentInfo response:', response);
                if (response.status === 200) {
                    const torrentInfo = JSON.parse(response.responseText);
                    if (torrentInfo.status === 'downloaded') {
                        const links = torrentInfo.links;
                        if (links && links.length > 0) {
                            // First unrestrict the download link
                            GM_xmlhttpRequest({
                                method: 'POST',
                                url: `${BASE_URL}unrestrict/link`,
                                data: `link=${encodeURIComponent(links[0])}`,
                                headers: {
                                    Authorization: `Bearer ${API_KEY}`,
                                    'Content-Type': 'application/x-www-form-urlencoded'
                                },
                                onload: function(unrestrictResponse) {
                                    console.log('Unrestrict response:', unrestrictResponse);
                                    if (unrestrictResponse.status === 200) {
                                        const unrestrictedInfo = JSON.parse(unrestrictResponse.responseText);
                                        const downloadUrl = unrestrictedInfo.download;
                                        const match = downloadUrl.match(/\/d\/([^/]+)/);
                                        if (match && match[1]) {
                                            const streamingId = match[1];
                                            const streamingUrl = `https://real-debrid.com/streaming-${streamingId}`;
                                            console.log('Streaming URL:', streamingUrl);
                                            GM_setClipboard(streamingUrl);
                                            alert('Streaming link copied to clipboard!');
                                            resetButton(button);
                                        } else {
                                            console.error('Could not extract streaming ID');
                                            alert('Error generating streaming link');
                                            resetButton(button);
                                        }
                                    } else {
                                        console.error('Error unrestricting link:', unrestrictResponse.status);
                                        alert('Error generating streaming link');
                                        resetButton(button);
                                    }
                                },
                                onerror: function(error) {
                                    console.error('Request failed:', error);
                                    alert('Network error during link unrestriction');
                                    resetButton(button);
                                }
                            });
                        } else {
                            console.error('No download links available');
                            alert('No download links available');
                            resetButton(button);
                        }
                    } else {
                        console.log('Torrent not ready, waiting...');
                        setTimeout(() => getStreamingLink(torrentId, button), 2000);
                    }
                } else {
                    console.error('Error checking torrent status:', response.status);
                    alert('Error checking torrent status');
                    resetButton(button);
                }
            },
            onerror: function(error) {
                console.error('Request failed:', error);
                alert('Network error checking torrent status');
                resetButton(button);
            }
        });
    }
        function createRDButton(type) {
        const button = document.createElement('button');
        button.textContent = type === 'download' ? 'RD DL' : 'RD Stream';
        button.classList.add('rd-button', `rd-${type}`);
        button.style.cssText = `
            margin-left: 5px;
            padding: 2px 8px;
            border-radius: 4px;
            border: 1px solid #ccc;
            background: #f0f0f0;
            cursor: pointer;
        `;
        return button;
    }

    function resetButton(button) {
        button.disabled = false;
        button.textContent = button.classList.contains('rd-download') ? 'RD DL' : 'RD Stream';
    }

    function addRDButton(magnetLink) {
        if (magnetLink.nextSibling?.classList?.contains('rd-button')) return;

        const buttonContainer = document.createElement('span');
        buttonContainer.style.display = 'inline-block';

        const dlButton = createRDButton('download');
        const streamButton = createRDButton('stream');

        dlButton.addEventListener('click', (e) => {
            e.preventDefault();
            dlButton.disabled = true;
            dlButton.textContent = 'Converting...';
            convertMagnetToRD(magnetLink.href, false, dlButton);
        });

        streamButton.addEventListener('click', (e) => {
            e.preventDefault();
            streamButton.disabled = true;
            streamButton.textContent = 'Converting...';
            convertMagnetToRD(magnetLink.href, true, streamButton);
        });

        buttonContainer.appendChild(dlButton);
        buttonContainer.appendChild(streamButton);
        magnetLink.parentNode.insertBefore(buttonContainer, magnetLink.nextSibling);
    }

    function processMagnetLinks() {
        const magnetLinks = document.querySelectorAll('a[href^="magnet:"]');
        magnetLinks.forEach(addRDButton);
    }

    // Initialize
    processMagnetLinks();

    // Watch for new magnet links
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.nodeType === 1) { // Element node
                    const magnetLinks = node.querySelectorAll('a[href^="magnet:"]');
                    magnetLinks.forEach(addRDButton);
                }
            });
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();