Premiumize.me Premium Link Converter

Convert standard links into premium links using premiumize.me

// ==UserScript==
// @name         Premiumize.me Premium Link Converter
// @version      2.1
// @grant        GM.xmlHttpRequest
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @namespace    https://greasyfork.org/en/users/807108-jeremy-r
// @include      *://*
// @match        https://www.premiumize.me/
// @description  Convert standard links into premium links using premiumize.me
// @icon         https://icons.duckduckgo.com/ip2/Premiumize.me.ico
// @author       JRem
// @license      MIT
// ==/UserScript==

let targetURLs = GM_getValue('targetURLs', []);
const processedURLs = new Set(); // Track processed URLs

// Cache structure
let domainCache = {
    cache: [],
    directdl: [],
    queue: [],
    fairusefactor: [],
    aliases: []
};

// Fetch the domains from the Premiumize API and update the domainCache
function updateDDLDomains() {
    console.log("Updating DDL Domains...");

    GM.xmlHttpRequest({
        method: "GET",
        url: "https://www.premiumize.me/api/services/list",
        onload: (response) => {
            try {
                const data = JSON.parse(response.responseText);
                console.log("Raw API Response:", response.responseText); // Log the raw response text

                // Check if the API response contains expected fields
                if (data && data.cache && data.directdl && data.queue && data.fairusefactor && data.aliases) {
                    // Directly access the properties based on the response you provided
                    domainCache.cache = data.cache || [];
                    domainCache.directdl = data.directdl || [];
                    domainCache.queue = data.queue || [];

                    // Handle fairusefactor separately as it has a different format
                    domainCache.fairusefactor = Object.keys(data.fairusefactor || []).map(domain => domain);

                    domainCache.aliases = [];
                    // Collect domains from aliases
                    Object.values(data.aliases || {}).forEach(aliases => {
                        domainCache.aliases.push(...aliases);
                    });

                    // Merge all domains into targetURLs
                    targetURLs = [
                        ...domainCache.cache,
                        ...domainCache.directdl,
                        ...domainCache.queue,
                        ...domainCache.fairusefactor,  // Only domain names here, not the fairusefactor values
                        ...domainCache.aliases
                    ];

                    // Log the updated domains
                    console.log("Updated Domains:", targetURLs);

                    // Persist the domains in GM storage
                    GM_setValue('targetURLs', targetURLs);
                    alert("DDL Domains Updated Successfully!");
                } else {
                    console.error("API response is missing expected fields:", data);
                    alert("Error fetching DDL domains: Missing expected fields.");
                }
            } catch (error) {
                console.error("Error parsing API response:", error);
                alert("Error processing DDL domains.");
            }
        },
        onerror: (error) => {
            console.error("Error in fetching DDL domains:", error);
            alert("Error fetching DDL domains.");
        }
    });
}

// Create dropdown menu with options using GM_registerMenuCommand
function createMenu() {
    GM_registerMenuCommand("Update DDL Domains", updateDDLDomains);
    console.log("Menu command registered.");
}

// Check if the current URL contains any of the target URLs
function isTargetURL() {
    const currentUrl = window.location.href;
    return targetURLs.some(target => currentUrl.includes(target));
}

// Generate a regex pattern based on targetURLs for HTTP-based links
function generateHttpUrlRegex() {
    const domains = targetURLs.map(url => url.replace(/\./g, '\\.') + '[^\s"]*');
    const pattern = `https:\\/\\/(?:${domains.join('|')})`;
    return new RegExp(pattern, 'g');
}

// Function to create the "Send to Premiumize" button for magnet links
function createMagnetButton(linkElement, magnetURL) {
    let button = document.createElement('button');
    button.innerHTML = 'Send to Premiumize';
    button.style.marginLeft = '2px'; // Add space to the left of the button
    button.style.backgroundColor = 'red'; // Set button background color to red
    button.style.color = 'white'; // Optional: Set button text color to white for better contrast
    button.style.borderRadius = '5px'; // Add rounded corners
    button.onclick = () => {
        window.open(`https://www.premiumize.me/transfers?magnet=${encodeURIComponent(magnetURL)}`, '_blank');
    };
    linkElement.setAttribute('premiumize', 'true');
    linkElement.insertAdjacentElement('afterend', button);
}

// Function to process regular HTTP-based URLs
function processHttpLinks() {
    const urlRegex = generateHttpUrlRegex();
    const links = document.querySelectorAll('a');

    links.forEach(link => {
        const href = link.href;
        if (processedURLs.has(href) || !urlRegex.test(href)) {
            return;
        }

        // Check if the link matches any of the domains in targetURLs
        for (let targetURL of targetURLs) {
            if (href.includes(targetURL)) {
                createFastDownloadButton(link, href);
                processedURLs.add(href); // Mark URL as processed
                break;
            }
        }
    });
}

// Function to create the "Send to Premiumize" button for HTTP links
function createFastDownloadButton(linkElement, fileURL) {
    let button = document.createElement('button');
    button.innerHTML = 'Send to Premiumize';
    button.style.marginLeft = '2px'; // Add space to the left of the button
    button.style.backgroundColor = 'red'; // Set button background color to red
    button.style.color = 'white'; // Optional: Set button text color to white for better contrast
    button.style.borderRadius = '5px'; // Add rounded corners
    button.onclick = () => {
        window.open(`https://www.premiumize.me/transfers?url=${encodeURIComponent(fileURL)}`, '_blank');
    };
    linkElement.setAttribute('premiumize', 'true');
    linkElement.insertAdjacentElement('afterend', button);
}

// Function to create the "Send to Premiumize" button for magnet links in text nodes
function processMagnetLinks() {
    const magnetLinks = document.querySelectorAll('a[href^="magnet:"]');

    magnetLinks.forEach(link => {
        const href = link.href;
        if (processedURLs.has(href)) {
            return;
        }

        createMagnetButton(link, href);
        processedURLs.add(href); // Mark URL as processed
    });
}

// Process and observe new links
function observeLinks() {
    if (!isTargetURL()) {
        // Process regular HTTP links
        processHttpLinks();

        // Process magnet links
        processMagnetLinks();
    }
}

// Debounce function to limit how often observeLinks is called
function debounce(func, wait) {
    let timeout;
    return function (...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
    };
}

// Observe the document body for changes
const observer = new MutationObserver(debounce(observeLinks, 500));
observer.observe(document.body, { childList: true, subtree: true });

// Also observe the links when the page first loads
window.onload = () => {
    createMenu(); // Create the menu on initial load
    observeLinks(); // Start observing links
};