Greasy Fork 支持简体中文。

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

// ==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
    });
})();