Magnet Link Handler for qBittorrent WebUI

Intercept magnet links and open qBittorrent download dialog in a popup.

目前為 2025-01-25 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Magnet Link Handler for qBittorrent WebUI
// @namespace    http://tampermonkey.net/
// @version      1.2
// @author       down_to_earth
// @description  Intercept magnet links and open qBittorrent download dialog in a popup.
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==

(async function() {
    'use strict';

    async function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    function setValue(node, value) {
        if (!node || value === undefined) {
            return;
        }

        function triggerChangeEvent(node) {
            const event = new Event('change', { bubbles: true });
            node.dispatchEvent(event);
        }

        if (node.type === 'checkbox' || node.type === 'radio') {
            if (node.checked !== value) {
                node.checked = value;
                triggerChangeEvent(node);
            }
        } else {
            if (node.value !== value) {
                node.value = value;
                triggerChangeEvent(node);
            }
        }
    }

    function saveSettings(sourceHostname) {
        const settings = {};

        // Save all <select> elements
        document.querySelectorAll('select:not([disabled]):not([hidden])').forEach(select => {
            const key = select.name || select.id;
            settings[key] = select.value;
        });

        // Save all <input> elements
        document.querySelectorAll('input:not([disabled]):not([hidden])').forEach(input => {
            const key = input.name ||input.id;
            if (input.type === 'checkbox' || input.type === 'radio') {
                settings[key] = input.checked;
            } else {
                settings[key] = input.value;
            }
        });

        // Save to localStorage
        localStorage.setItem(`settings_${sourceHostname}`, JSON.stringify(settings));
    }

    async function restoreSettings(sourceHostname) {
        const settings = JSON.parse(localStorage.getItem(`settings_${sourceHostname}`) || 'null');
        if (!settings) {
            return;
        }

        const categoryValue = settings.categorySelect;
        const categorySelect = document.querySelector('#categorySelect');
        if (categoryValue && categorySelect) {
            // Wait for categories to load
            while (!Array.from(categorySelect.options).some(option => option.value === categoryValue)) {
                await sleep(10);
            }
            setValue(categorySelect, categoryValue);
        }

        // Restore all <select> elements
        document.querySelectorAll('select:not([disabled]):not([hidden])').forEach(select => {
            const key = select.name || select.id;
            if (key === 'categorySelect') {
                return;
            }
            setValue(select, settings[key]);
        });

        // Restore all <input> elements
        document.querySelectorAll('input:not([disabled]):not([hidden])').forEach(input => {
            const key = input.name || input.id;
            setValue(input, settings[key]);
        });
    }

    // Define the default qBittorrent WebUI URL
    const defaultQbWebUIHost = 'http://localhost:8080';

    // Retrieve the saved qBittorrent WebUI URL or use the default
    let qbWebUIHost = GM_getValue('qbWebUIHost', defaultQbWebUIHost);

    // Add a menu command to set the qBittorrent WebUI URL
    GM_registerMenuCommand('Set qBittorrent WebUI URL', () => {
        const newUrl = prompt('Enter the qBittorrent WebUI URL:', qbWebUIHost);
        if (newUrl) {
            GM_setValue('qbWebUIHost', newUrl); // Save the new URL
            qbWebUIHost = newUrl; // Update the script's URL
            alert(`qBittorrent WebUI URL set to: ${newUrl}`);
        }
    });

    // Check if the current page is the qBittorrent WebUI's download.html
    const isDownloadPage = window.location.href.startsWith(qbWebUIHost) && window.location.pathname === '/download.html';

    if (isDownloadPage) {
        // Check if the URL contains the `?url=` parameter
        const urlParams = new URLSearchParams(window.location.search);
        const encodedMagnetLink = urlParams.get('url');
        if (!encodedMagnetLink) {
            return; // Exit if no `?url=` parameter is found
        }

        // Fill the textarea with the magnet link
        setValue(document.querySelector('#urls'), decodeURIComponent(encodedMagnetLink));

        // Wait for the preferences to load
        const savePath = document.querySelector('#savepath');
        while (!savePath.value) {
            await sleep(10);
        }

        const sourceHostname = decodeURIComponent(urlParams.get('source'));

        // Register close handler
        document.querySelector('#download_frame').addEventListener("load", function() {
            if (sourceHostname) {
                saveSettings(sourceHostname);
            }
            window.close();
        });

        await restoreSettings(sourceHostname);

        const autoDownload = urlParams.get('autoDownload') === 'true';
        if (autoDownload) {
            document.querySelector('#submitButton')?.click();
        }
    } else {
        // Function to handle magnet link clicks
        function handleMagnetLinkClick(event) {
            let target = event.target;

            while (target && target.tagName !== 'A') {
                target = target.parentElement;
            }

            // Check if the clicked element is a magnet link
            if (target?.href.startsWith('magnet:')) {
                event.preventDefault(); // Prevent the default behavior

                // Encode the magnet link for use in a URL
                const encodedMagnetLink = encodeURIComponent(target.href);

                // Get the source website hostname
                const sourceHostname = window.location.hostname;

                // Check if Ctrl key is pressed
                const autoDownload = event.ctrlKey;

                // Open the qBittorrent WebUI's download.html in a popup
                const popupUrl = `${qbWebUIHost}/download.html?url=${encodedMagnetLink}&source=${sourceHostname}&autoDownload=${autoDownload}`;

                // Define the popup dimensions
                const popupWidth = 500;
                const popupHeight = 600;

                // Calculate the position to center the popup
                const left = (window.screen.width - popupWidth) / 2;
                const top = (window.screen.height - popupHeight) / 2;

                // Open the popup with centered position
                let popupName = 'qBittorrentAddMagnet';
                if (autoDownload) {
                    popupName += crypto.randomUUID()
                }
                window.open(
                    popupUrl,
                    popupName,
                    `width=${popupWidth},height=${popupHeight},left=${left},top=${top}`
                );
            }
        }

        // Attach the event listener to the document
        document.addEventListener('click', handleMagnetLinkClick, true);
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址