Switch520下载优化

Switch520点击下载按钮后,直接弹出下载地址,无需反复跳转、输入密码

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Switch520下载优化
// @namespace    http://tampermonkey.net/
// @version      1.7
// @description  Switch520点击下载按钮后,直接弹出下载地址,无需反复跳转、输入密码
// @author       一身惆怅
// @match        http*://*.gamer520.com/*
// @icon         https://img.piclabo.xyz/2023/10/25/d67adcffb89dd.jpg
// @run-at       document-idle
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      gamer520.com
// @connect      xxxxx528.com
// @connect      freer.blog
// @license      MIT
// ==/UserScript==

(() => {
    'use strict';

    GM_addStyle(`
        .swal2-content { 
            text-align: left !important; 
            line-height: unset !important; 
        } 
        .disabled { 
            pointer-events: none; opacity: 0.7; 
        }
        .settings-dialog {
            position: fixed;
            top: 50%;
            left: 50%;
            height: 80px;
            width: 360px;
            transform: translate(-50%, -50%);
            background-color: #333;
            box-shadow: 0 0 8px #00a96f;
            color: white;
            padding: 20px;
            border-radius: 12px;
            z-index: 1000;
        }
        .settings-content {
            position: relative;
        }
        .settings-close {
            position: fixed;
            top: 1px;
            right: 10px;
            font-size: 30px;
            cursor: pointer;
        }
        .switch {
            position: relative;
            display: inline-block;
            width: 60px;
            height: 34px;
        }
        .switch input { 
            opacity: 0;
            width: 0;
            height: 0;
        }
        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            -webkit-transition: .4s;
            transition: .4s;
        }
        .slider:before {
            position: absolute;
            content: "";
            height: 26px;
            width: 26px;
            left: 4px;
            bottom: 4px;
            background-color: white;
            -webkit-transition: .4s;
            transition: .4s;
        }
        input:checked + .slider {
            background-color: #00a96f;
        }
        input:focus + .slider {
            box-shadow: 0 0 1px #00a96f;
        }
        input:checked + .slider:before {
            -webkit-transform: translateX(26px);
            -ms-transform: translateX(26px);
            transform: translateX(26px);
        }
        .slider.round {
            border-radius: 34px;
        }
        .slider.round:before {
            border-radius: 50%;
        }
    `);

    const registerMenuCommand = () => {
        GM_registerMenuCommand('⚙️ 设置', openSettingsDialog);
    };

    const openSettingsDialog = () => {
        const settingsDialogHTML = `
        <div id="settings-dialog" class="settings-dialog">
            <div class="settings-content">
                <span class="settings-close">&times;</span>
                <label class="switch">
                    <input type="checkbox" id="onedrive-link-toggle" ${GM_getValue("onedriveLinkEnabled", false) ? "checked" : ""}>
                    <span class="slider round"></span>
                </label>
                <span>Onedrive盘链接显示</span>
            </div>
        </div>
        `;

        document.body.insertAdjacentHTML('beforeend', settingsDialogHTML);
        document.getElementById('onedrive-link-toggle').addEventListener('change', toggleOnedriveLink);
        document.querySelector('.settings-close').addEventListener('click', closeSettingsDialog);
    };

    const toggleOnedriveLink = () => {
        const isChecked = document.getElementById('onedrive-link-toggle').checked;
        GM_setValue("onedriveLinkEnabled", isChecked);
    };

    const closeSettingsDialog = () => {
        const settingsDialog = document.getElementById('settings-dialog');
        if (settingsDialog) {
            settingsDialog.remove();
        }
    };

    const swalOptions = {
        warning: (message) => ({ title: message, type: "warning" }),
        success: (title, htmlContent) => ({ title, type: "success", html: htmlContent })
    };

    const showMessage = (type, ...args) => Swal.fire(swalOptions[type](...args));

    const request = async (url, method, headers = {}, data = null) => {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({ method, url, headers, data, onload: (response) => resolve(response.responseText), onerror: reject });
        });
    };

    const disableButton = button => button.classList.add('disabled');
    const enableButton = button => button.classList.remove('disabled');

    const parseHTML = responseText => new DOMParser().parseFromString(responseText, "text/html");

    const copyTextToClipboard = async (text) => {
        try {
            await navigator.clipboard.writeText(text);
        } catch {
            const textarea = document.createElement('textarea');
            textarea.value = text;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);
        }
    };

    const handleCopyCodeClick = event => {
        if (event.target.matches('.copy-code-link')) {
            copyTextToClipboard(event.target.dataset.code);
            event.preventDefault();
        }
    };

    const extractCodeAndModifyLink = (linkElement, siblingParagraph) => {
        const codeRegex = /(?:提取码|解压密码|如遇到有带x的提取码请手打输入)[::]\s*(\w+)/;
        const codeMatch = siblingParagraph?.textContent.match(codeRegex);
        if (codeMatch) {
            const [, code] = codeMatch;
            linkElement.href = `${linkElement.href}?pwd=${code}`;
            linkElement.textContent += `?pwd=${code}`;
            siblingParagraph.remove();
        }
    };

    const modifyContentElement = (contentElement) => {
        contentElement.querySelectorAll('p').forEach((paragraph) => {
            paragraph.querySelectorAll('a').forEach((link) => {
                link.setAttribute('target', '_blank');
                if (link.href.includes('pan.baidu.com') && !link.href.includes('pwd=')) {
                    extractCodeAndModifyLink(link, paragraph.nextElementSibling);
                }
            });

            const codeMatch = paragraph.textContent.match(/(?:提取码|解压密码)[::]\s*([\w.]+)/);
            if (codeMatch) {
                const codeType = paragraph.textContent.includes('提取码') ? '提取码' : '解压密码';
                paragraph.innerHTML = `<a href="#" class="copy-code-link" data-code="${codeMatch[1]}">点击复制${codeType}: ${codeMatch[1]}</a>`;
            } else if (paragraph.textContent.includes('Onedrive盘下载')) {
                paragraph.innerHTML = `<br>`;
            }
        });
    };

    const getDownloadHTML = async (url) => {
        try {
            const responseText = await request(url, 'GET');
            const doc = parseHTML(responseText);
            const contentElement = doc.querySelector('div.entry-content.u-text-format.u-clearfix');
            const downloadButton = doc.querySelector('a.go-down.btn.btn--secondary.btn--block');
            if (contentElement) {
                modifyContentElement(contentElement);
                let messageHTML = contentElement.innerHTML;
                if (GM_getValue("onedriveLinkEnabled", false) && downloadButton) {
                    const postId = downloadButton.dataset.id;
                    const urlObject = new URL(url);
                    const redirectUrl = await getRedirectUrl(`${urlObject.origin}/go/?post_id=${postId}`);
                    if (redirectUrl) {
                        messageHTML += `<p><strong>Onedrive盘下载:</strong> <a href="${redirectUrl}" target="_blank">点击下载</a>(推荐浏览器直接下载)</p>`;
                    }
                }
                showMessage("success", "已获取下载内容", messageHTML);
            } else {
                showMessage("warning", "未找到下载内容");
            }
        } catch (error) {
            showMessage("warning", "请求失败");
        }
    };

    const submitPassword = async (password, url) => {
        const urlObject = new URL(url);
        const passwordUrl = `${urlObject.origin}/wp-login.php?action=postpass`;
        console.log(passwordUrl);
        const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
        const data = `post_password=${password}&Submit=%E6%8F%90%E4%BA%A4`;
        try {
            await request(passwordUrl, 'POST', headers, data);
            await getDownloadHTML(url);
        } catch (error) {
            showMessage("warning", "提交密码失败");
        }
    };

    const readPassword = async (shareUrl) => {
        try {
            const responseText = await request(shareUrl, 'GET');
            const doc = parseHTML(responseText);
            const passwordElement = doc.querySelector('h1.entry-title');
            if (passwordElement) {
                const passwordMatch = passwordElement.textContent.match(/[A-Za-z0-9]+/);
                if (passwordMatch) {
                    await submitPassword(passwordMatch[0], shareUrl);
                } else {
                    showMessage("warning", "未能成功读取分享页密码");
                }
            } else {
                showMessage("warning", "未找到分享页密码");
            }
        } catch (error) {
            showMessage("warning", "请求失败");
        }
    };

    const getRedirectUrl = async (url) => {
        try {
            const responseText = await request(url, 'GET');
            const redirectRegex = /window.location\s*=\s*['"]([^'"]+)['"]/;
            const redirectMatch = responseText.match(redirectRegex);
            if (redirectMatch && redirectMatch[1]) {
                return redirectMatch[1];
            } else {
                showMessage("warning", "未找到跳转网址");
                return null;
            }
        } catch (error) {
            showMessage("warning", "请求失败,请查看控制台以获取更多信息");
            console.error(error);
            return null;
        }
    };

    const handleButtonClick = async (event) => {
        event.stopPropagation();
        const button = event.target;
        disableButton(button);
        const postId = button.dataset.id;
        const targetUrl = await getRedirectUrl(`https://www.gamer520.com/go/?post_id=${postId}`);
        if (targetUrl) {
            await readPassword(targetUrl);
        }
        enableButton(button);
    };

    const init = () => {
        const payBoxElement = document.querySelector('.go-down');
        if (payBoxElement) {
            registerMenuCommand();
            payBoxElement.addEventListener('click', handleButtonClick, true);
            document.addEventListener('click', handleCopyCodeClick);
        }
    };

    init();
})();