DownArchive Link Extractor

Extract links from DownArchive and copy them to clipboard

目前為 2025-02-28 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         DownArchive Link Extractor
// @namespace   https://greasyfork.org/users/30331-setcher
// @version      0.4
// @description  Extract links from DownArchive and copy them to clipboard
// @author       Setcher
// @match        *://downarchive.org/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @connect      rg.to
// @connect      rapidgator.net
// @connect      uploadgig.com
// @connect      nitroflare.com
// @connect      filextras.com
// ==/UserScript==

(function() {
    'use strict';

    // Utility function to create copy button
    function createCopyButton(container, text, links, placeholder) {
        const button = document.createElement('button');
        button.innerText = text;
        button.style.marginTop = '10px';
        button.style.marginBottom = '10px'; // Add space below button
        button.style.marginRight = '10px'; // Add space between buttons
        button.onclick = function() {
            const clipboardText = links.join('\n');
            GM_setClipboard(clipboardText);
            alert(`Copied ${links.length} links to clipboard!`);
        };

        // Replace placeholder with the button
        container.replaceChild(button, placeholder);
    }

    // Function to create a placeholder (disabled button with "Loading" text)
    function createPlaceholder(domain) {
        const placeholder = document.createElement('button');
        placeholder.disabled = true;
        placeholder.innerText = `Loading ${domain} links...`;
        placeholder.style.marginTop = '10px';
        placeholder.style.marginBottom = '10px'; // Add space below button
        placeholder.style.marginRight = '10px'; // Add space between buttons
        return placeholder;
    }

    // Extract links from a given folder URL (e.g., rg.to folder)
    function extractRGLinks(folderUrl, container, placeholder) {
        GM_xmlhttpRequest({
            method: 'GET',
            url: folderUrl,
            onload: function(response) {
                const doc = new DOMParser().parseFromString(response.responseText, 'text/html');
                const fileLinks = Array.from(doc.querySelectorAll('a[href^="/file/"]')).map(link => "https://rapidgator.net/" + link.getAttribute('href'));

                // Replace placeholder with the button once the links are loaded
                createCopyButton(container, `Copy all ${fileLinks.length} rapidgator.net links`, fileLinks, placeholder);
            }
        });
    }

    // Main function to process each quote div (excluding rg.to/folder)
    function processQuoteDiv(quoteDiv) {
        const links = Array.from(quoteDiv.querySelectorAll('a'));

        let rgLink = null;
        const otherLinks = {
            'rapidgator.net': [],
            'uploadgig.com': [],
            'nitroflare.com': [],
            'filextras.com': []
        };

        const placeholders = [];

        // Step 1: Check for supported servers and add placeholders immediately
        links.forEach(link => {
            const href = link.href;

            if (href.startsWith('https://rg.to/folder/')) {
                rgLink = href;
            } else if (href.includes('rapidgator.net/file/')) {
                otherLinks['rapidgator.net'].push(href);
            } else if (href.includes('uploadgig.com/file/')) {
                otherLinks['uploadgig.com'].push(href);
            } else if (href.includes('nitroflare.com/')) {
                otherLinks['nitroflare.com'].push(href);
            } else if (href.includes('filextras.com/')) {
                otherLinks['filextras.com'].push(href);
            }
        });

        // Step 2: Place placeholders for supported servers immediately
        for (const domain in otherLinks) {
            if (otherLinks[domain].length > 0) {
                const placeholder = createPlaceholder(domain);
                quoteDiv.appendChild(placeholder);
                placeholders.push({ domain, placeholder, links: otherLinks[domain] });
            }
        }

        // Step 3: Replace the placeholders for other domains immediately
        placeholders.forEach(({ domain, placeholder, links }) => {
            createCopyButton(quoteDiv, `Copy all ${links.length} ${domain} links`, links, placeholder);
        });

        // Step 4: Place placeholder for rg.to/folder, but don't process yet
        if (rgLink) {
            const rgPlaceholder = createPlaceholder('rg.to');
            quoteDiv.appendChild(rgPlaceholder);
            // Store rg.to link to process later
            window.rgLinksToProcess = window.rgLinksToProcess || [];
            window.rgLinksToProcess.push({ rgLink, quoteDiv, rgPlaceholder });
        }
    }

    // Function to process all rg.to/folder links after page load
    function processRGFolders() {
        if (window.rgLinksToProcess && window.rgLinksToProcess.length > 0) {
            window.rgLinksToProcess.forEach(({ rgLink, quoteDiv, rgPlaceholder }) => {
                extractRGLinks(rgLink, quoteDiv, rgPlaceholder);
            });
            // Clear the queue after processing
            window.rgLinksToProcess = [];
        }
    }

    // Main function to run on page load
    window.addEventListener('load', function() {
        // Process all quote divs, except rg.to/folder processing
        const quoteDivs = document.querySelectorAll('div.quote');
        quoteDivs.forEach(quoteDiv => {
            processQuoteDiv(quoteDiv);
        });

        // Trigger rg.to folder processing separately after everything else is done
        processRGFolders();
    });
})();