Greasy Fork

Greasy Fork is available in English.

又双叒叕增强

自动检测页面中的又双叒叕内容

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         又双叒叕增强
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  自动检测页面中的又双叒叕内容
// @author       iwpz
// @match        *://*/*
// @grant        GM_addStyle
// @license      mit
// ==/UserScript==

(function() {
    'use strict';

    // 添加自定义样式
    GM_addStyle(`
        .ysrz-container {
            display: flex;
            align-items: flex-start;
            margin: 5px 0;
            position: relative;
        }
        .ysrz-decoded {
            flex: 1;
            background-color: #f0f8ff;
            border: 1px solid #c3d9ff;
            border-radius: 4px;
            padding: 8px;
            min-height: 40px;
        }
        .ysrz-original-btn {
            margin-left: 8px;
            background: #4b6cb7;
            color: white;
            border: none;
            border-radius: 3px;
            padding: 5px 10px;
            font-size: 12px;
            cursor: pointer;
            opacity: 0.7;
            transition: opacity 0.3s;
            white-space: nowrap;
            height: fit-content;
        }
        .ysrz-original-btn:hover {
            opacity: 1;
        }
        .ysrz-modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.5);
            z-index: 10000;
            justify-content: center;
            align-items: center;
        }
        .ysrz-modal-content {
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            max-width: 80%;
            max-height: 80%;
            overflow: auto;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }
        .ysrz-modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            border-bottom: 1px solid #eee;
            padding-bottom: 10px;
        }
        .ysrz-modal-title {
            font-weight: bold;
            font-size: 18px;
        }
        .ysrz-modal-close {
            background: none;
            border: none;
            font-size: 20px;
            cursor: pointer;
            color: #666;
        }
        .ysrz-modal-body {
            word-break: break-all;
            line-height: 1.5;
            font-family: monospace;
            background-color: #f5f5f5;
            padding: 10px;
            border-radius: 4px;
            white-space: pre-wrap;
            font-size: 16px;
        }
        .ysrz-badge {
            position: absolute;
            top: -8px;
            left: 5px;
            background: #4b6cb7;
            color: white;
            font-size: 10px;
            padding: 2px 6px;
            border-radius: 10px;
            z-index: 1;
        }
    `);

    // 定义字符映射
    const charMap = {
        0: '又',
        1: '双',
        2: '叒',
        3: '叕'
    };

    const reverseCharMap = {
        '又': 0,
        '双': 1,
        '叒': 2,
        '叕': 3
    };

    // 解码函数
    function decodeYSRZ(encodedText) {
        // 去除所有空白字符
        const pureEncodedText = encodedText.replace(/\s/g, '');

        // 检查是否只包含又双叒叕字符
        const validChars = /^[又双叒叕]+$/;
        if (!validChars.test(pureEncodedText)) {
            return null;
        }

        try {
            // 将又双叒叕字符转换为二进制字符串
            let binaryString = '';
            for (let i = 0; i < pureEncodedText.length; i++) {
                const char = pureEncodedText[i];
                const base4Value = reverseCharMap[char];
                binaryString += base4Value.toString(2).padStart(2, '0');
            }

            // 将二进制字符串转换为字节数组
            const byteArray = [];
            for (let i = 0; i < binaryString.length; i += 8) {
                const byteString = binaryString.substr(i, 8);
                // 如果最后不足8位,忽略(可能是填充位)
                if (byteString.length === 8) {
                    byteArray.push(parseInt(byteString, 2));
                }
            }

            // 将字节数组解码为文本
            const decoder = new TextDecoder();
            const decodedString = decoder.decode(new Uint8Array(byteArray));

            return decodedString;
        } catch (error) {
            console.error('解码错误:', error);
            return null;
        }
    }

    // 判断文本是否有意义
    function isMeaningful(text) {
        if (!text) return false;

        // 检查是否包含可打印字符(排除纯控制字符)
        const hasPrintableChars = /[\p{L}\p{N}\p{P}\p{S}]/gu.test(text);
        if (!hasPrintableChars) return false;

        // 检查是否包含常见语言字符(中英日韩等)
        const hasLanguageChars = /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7afa-zA-Z]/.test(text);
        if (hasLanguageChars) return true;

        // 检查是否包含常见标点和数字
        const hasCommonSymbols = /[0-9.,!?;:'"()\[\]{}]/.test(text);

        return hasPrintableChars && (hasLanguageChars || hasCommonSymbols);
    }

    // 检查节点是否在模态框内
    function isInModal(node) {
        // 对于元素节点,使用closest方法
        if (node.nodeType === Node.ELEMENT_NODE) {
            return node.closest('.ysrz-modal') !== null;
        }
        // 对于文本节点,检查其父节点
        else if (node.nodeType === Node.TEXT_NODE && node.parentNode) {
            return node.parentNode.closest && node.parentNode.closest('.ysrz-modal') !== null;
        }
        return false;
    }

    // 创建模态框
    function createModal() {
        const modal = document.createElement('div');
        modal.className = 'ysrz-modal';
        modal.innerHTML = `
            <div class="ysrz-modal-content">
                <div class="ysrz-modal-header">
                    <div class="ysrz-modal-title">又双叒叕原文</div>
                    <button class="ysrz-modal-close">&times;</button>
                </div>
                <div class="ysrz-modal-body"></div>
            </div>
        `;

        modal.querySelector('.ysrz-modal-close').addEventListener('click', function() {
            modal.style.display = 'none';
        });

        modal.addEventListener('click', function(e) {
            if (e.target === modal) {
                modal.style.display = 'none';
            }
        });

        document.body.appendChild(modal);
        return modal;
    }

    // 显示原文模态框
    function showOriginalText(originalYSRZ) {
        let modal = document.querySelector('.ysrz-modal');
        if (!modal) {
            modal = createModal();
        }

        // 直接设置文本内容为原始的又双叒叕密文
        const modalBody = modal.querySelector('.ysrz-modal-body');

        // 使用textContent而不是innerHTML,确保只显示纯文本
        modalBody.textContent = originalYSRZ;

        modal.style.display = 'flex';

        console.log('弹窗显示内容:', originalYSRZ);
    }

    // 处理文本节点
    function processTextNode(textNode) {
        // 检查文本节点是否仍然在DOM中
        if (!textNode.parentNode) {
            return;
        }

        // 跳过模态框内的文本节点
        if (isInModal(textNode)) {
            return;
        }

        const textContent = textNode.textContent.trim();

        // 如果文本太短,可能不是编码内容
        if (textContent.length < 4) return;

        // 检查是否只包含又双叒叕字符
        const validChars = /^[又双叒叕]+$/;
        if (!validChars.test(textContent)) {
            return;
        }

        // 尝试解码
        const decodedText = decodeYSRZ(textContent);

        // 如果解码成功且有意义的文本
        if (decodedText && isMeaningful(decodedText)) {
            // 保存原始文本(又双叒叕密文)
            const originalYSRZ = textContent;

            // 创建容器
            const container = document.createElement('div');
            container.className = 'ysrz-container';

            // 添加解码后的内容区域
            const decodedContainer = document.createElement('div');
            decodedContainer.className = 'ysrz-decoded';
            decodedContainer.textContent = decodedText;

            // 添加标识徽章
            const badge = document.createElement('div');
            badge.className = 'ysrz-badge';
            badge.textContent = '已解码';
            decodedContainer.appendChild(badge);

            // 添加查看原文按钮
            const originalBtn = document.createElement('button');
            originalBtn.className = 'ysrz-original-btn';
            originalBtn.textContent = '原文';
            originalBtn.title = '查看又双叒叕原文';

            // 为按钮添加事件监听器 - 使用闭包确保传递正确的originalYSRZ
            originalBtn.addEventListener('click', (function(ysrzText) {
                return function(e) {
                    e.stopPropagation();
                    // 传递原始的又双叒叕密文
                    showOriginalText(ysrzText);
                };
            })(originalYSRZ));

            // 组装容器
            container.appendChild(decodedContainer);
            container.appendChild(originalBtn);

            // 再次检查父节点是否存在
            if (textNode.parentNode) {
                // 替换文本节点
                textNode.parentNode.replaceChild(container, textNode);
            } else {
                console.warn('文本节点没有父节点,无法替换');
            }

            console.log('检测到又双叒叕编码内容并已解码:', {
                original: originalYSRZ,
                decoded: decodedText
            });
        }
    }

    // 遍历DOM树查找文本节点
    function walkDOM(node, callback) {
        if (node.nodeType === Node.TEXT_NODE) {
            callback(node);
        } else if (node.nodeType === Node.ELEMENT_NODE) {
            // 跳过script和style标签,以及模态框内的元素
            if (node.tagName !== 'SCRIPT' && node.tagName !== 'STYLE' &&
                !node.classList.contains('ysrz-decoded') &&
                !node.classList.contains('ysrz-container') &&
                !isInModal(node)) { // 跳过模态框内的元素
                for (let i = 0; i < node.childNodes.length; i++) {
                    walkDOM(node.childNodes[i], callback);
                }
            }
        }
    }

    // 初始化函数
    function init() {
        console.log('又双叒叕内容检测器已启动');

        // 处理现有内容
        walkDOM(document.body, processTextNode);

        // 监听DOM变化,处理动态加载的内容
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.addedNodes) {
                    mutation.addedNodes.forEach(function(node) {
                        // 跳过模态框内的元素
                        if (isInModal(node)) {
                            return;
                        }

                        if (node.nodeType === Node.ELEMENT_NODE) {
                            walkDOM(node, processTextNode);
                        } else if (node.nodeType === Node.TEXT_NODE) {
                            // 跳过模态框内的文本节点
                            if (isInModal(node)) {
                                return;
                            }

                            // 延迟处理,确保节点已完全添加到DOM中
                            setTimeout(() => {
                                if (node.parentNode) {
                                    processTextNode(node);
                                }
                            }, 0);
                        }
                    });
                }
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    // 页面加载完成后初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();