심야식당 도우미

심야식당을 좀 더 편하고 내 입맛에 맞게 이용

目前为 2023-06-30 提交的版本。查看 最新版本

// ==UserScript==
// @name         심야식당 도우미
// @description  심야식당을 좀 더 편하고 내 입맛에 맞게 이용
// @version      0.2
// @author       Yoonu
// @match        https://arca.live/b/*
// @match        https://kioskloud.io/e/*
// @match        https://mega.nz/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=arca.live
// @grant       GM.setValue
// @grant       GM.getValue
// @license      MIT
// @namespace https://gf.qytechs.cn/users/64556
// ==/UserScript==

(async function() {
    'use strict';
    const RULE_PASSWORD = atob("c21wZW9wbGU=");

    const arcalive = async () => {
        const settings = {
            switch: {
                passwordDecoder: await GM.getValue("passwordDecoder", true),
                base64Decoder: await GM.getValue("base64Decoder", true),
                imageOriginalizer: await GM.getValue("imageOriginalizer", true),
            },
            passwordDecoder: {
                id: "arca_eh_password",
                origin: "국룰",
                rulePassword: await GM.getValue("rulePassword"),
            },
            pageMaxWidth: await GM.getValue("pageMaxWidth", "1800px"),
        };

        const styles = {
            password: "color: rgb(61, 142, 185); cursor: pointer; font-weight: bold;",
            copiedPassword: "color: rgb(61, 142, 185); cursor: pointer;",
        };

        // Change content area width
        const wrapper = document.querySelector("div.content-wrapper");
        if(settings.pageMaxWidth) wrapper.style.maxWidth = settings.pageMaxWidth;

        // Get article
        const article = wrapper.querySelector("div.article-body > div.article-content");
        if(!article) return;

        let articleHtml = article.innerHTML;

        // Decode base64
        if(settings.switch.base64Decoder) {
            articleHtml = articleHtml.replace(/(YUhSMGN|aHR0c)[0-9A-Za-z+]{8,}[=]{0,2}/g, (matcher) => {
                let decoded;
                try {
                    decoded = atob(matcher.startsWith("Y") ? atob(matcher) : matcher);
                    return `<a href="${decoded}" target="_blank">${decoded}</a>`;
                } catch(e) {
                    return matcher + `<span style="font-size: 9pt; color: red;" title="${e}">코드 복호화 실패</span>`;
                }
            });
        }

        // Find password
        if(settings.switch.passwordDecoder) {
            if(settings.passwordDecoder.rulePassword !== RULE_PASSWORD) {
                const inputText = prompt("국룰 확인");

                if(inputText?.toLowerCase() === RULE_PASSWORD) {
                    GM.setValue("rulePassword", RULE_PASSWORD);
                    settings.passwordDecoder.rulePassword = RULE_PASSWORD;
                } else {
                    GM.setValue("passwordDecoder", false);
                    alert("국룰 비밀번호가 일치하지 않습니다. 국룰 해석 기능을 비활성화합니다.");
                }
            }

            if(settings.passwordDecoder.rulePassword === RULE_PASSWORD) {
                articleHtml = articleHtml.replace(/&nbsp;/g, " ").replace(new RegExp("[^\\s>]*" + settings.passwordDecoder.origin + "[^\\s\n<]*"), (matcher) => {
                    let preText = "", postText = "";

                    matcher = matcher.replace(/(비밀번호|암호|비번|패스워드)?(\s*[-:=]*\s*)([은|는])?국룰(과|은|이|이며|이고|임|입니다|임다|이다)?([\.,\(\[])?$/g, (matcher2, ...args) => {
                        preText = (args[0] || "") + (args[1] || "") + (args[3] || "");
                        postText = (args[2] || "") + (args[3] || "");
                        return settings.passwordDecoder.origin;
                    });

                    const id = settings.passwordDecoder.id;
                    const decodedPassword = matcher.replace(settings.passwordDecoder.origin, settings.passwordDecoder.rulePassword);

                    let result = preText + matcher + ` <a href="#" id="${id}" style="${styles.password}" data-password="${RULE_PASSWORD}" title="클릭 시 비밀번호가 복사됩니다.">🔑${RULE_PASSWORD}</a>`;
                    if(RULE_PASSWORD !== decodedPassword) result += ` / <a href="#" id="${id}_decoded" style="${styles.password}" data-password="${decodedPassword}" title="클릭 시 비밀번호가 복사됩니다.">🔑${decodedPassword}</a>`
                    result += postText;

                    return result
                });
            }
        }

        // Change original image
        if(settings.switch.imageOriginalizer) {
            articleHtml = articleHtml.replace(/<img[^>]+src="([^"]+)[^>]+loading="lazy"[^>]*>/g, (matcher, src) => `<img src="${src}&type=orig&dummy" loading="lazy">`);
        }

        // Apply article changed
        if(Object.values(settings.switch).some(Boolean))
            article.innerHTML = articleHtml;

        // Password copy event
        const copyPassword = async (e) => {
            // Prevent page move
            e.preventDefault();

            await navigator.clipboard.writeText(e.target.dataset.password);
            e.target.style = styles.copiedPassword;
        };

        // Set event password clicked
        document.getElementById(settings.passwordDecoder.id)?.addEventListener("click", copyPassword);
        document.getElementById(settings.passwordDecoder.id + "_decoded")?.addEventListener("click", copyPassword);
    }

    // Set password at inputbox
    const setPassword = async (container, inputSelector) => {
        const clipboard = await navigator.clipboard.readText();
        const password = clipboard?.toLowerCase().indexOf(RULE_PASSWORD) > -1 ? clipboard : RULE_PASSWORD;

        // Callback
        const callback = (mutationList, observer) => {
            const inputBox = inputSelector();
            if(!inputBox) return;

            inputBox.value = password;
            observer.disconnect();
        };

        // Mutation observing
        const observer = new MutationObserver(callback);
        observer.observe(container, {
            attributes: true,
            childList: true,
            subtree: true
        });
    }

    // Execute function by host
    switch(document.URL.split("/")[2]) {
        case "arca.live":
            arcalive();
            break;

        case "mega.nz":
            setPassword(document.getElementById("bodyel"), () => document.getElementById("password-decrypt-input"));
            break;

        case "kioskloud.io":
            setPassword(document.getElementById("app"), () => document.getElementById("swal2-title")?.parentNode.querySelector("input"));
            break;
    }
})();

QingJ © 2025

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