编程猫 CoCo 作品分享审核绕过

绕过 CoCo 作品分享的审核机制,让他人可以看到你分享的作品,请低调使用

נכון ליום 21-08-2024. ראה הגרסה האחרונה.

// ==UserScript==
// @name         编程猫 CoCo 作品分享审核绕过
// @namespace    https://s-lightning.github.io/
// @version      0.1.11
// @description  绕过 CoCo 作品分享的审核机制,让他人可以看到你分享的作品,请低调使用
// @author       SLIGHTNING
// @match        http://coco.codemao.cn/editor/*
// @match        https://coco.codemao.cn/editor/*
// @icon         https://coco.codemao.cn/favicon.ico
// @grant        none
// @license      AGPL-3.0
// ==/UserScript==

(function() {
    "use strict";

    ;(function() {
        if (location.pathname != "/editor/") {
            return
        }
        let originalFetch = fetch
        fetch = async function(input, init) {
            let response = await originalFetch(input, init)
            if (input == "https://static.codemao.cn/coco/whitelist.json") {
                try {
                    let workID = location.search.match(/(?<=(\?|&)workId=)[0-9]+(?=$|&)/)
                    if (workID == null) {
                        throw new Error("获取作品 ID 失败,可能因为作品未保存到云端,请将作品保存到云端后再尝试。")
                    }
                    workID = Number(workID[0])
                    if (workID == 0 || isNaN(workID)) {
                        throw new Error("获取作品 ID 失败,可能因为作品未保存到云端,请将作品保存到云端后再尝试。")
                    }
                    let whiteList = await response.json()
                    whiteList.push(workID)
                    return new Response(JSON.stringify(whiteList), {
                        ...response
                    })
                } catch (error) {
                    error.message = `绕过审核失败:${error.message}`
                    console.error(error)
                    return response
                }
            }
            return response
        }
    })()

    function bypassAudit() {
        if (location.search.includes("playerBcmUrl")) {
            if (!parent.SLIGHTNING_BYPASS_AUDIT_STOP) {
                let scriptElement = document.createElement("script")
                scriptElement.innerHTML = `(${bypassAudit})()`
                parent.document.body.appendChild(scriptElement)
            }
            return
        }

        if (window.SLIGHTNING_BYPASS_AUDIT_STOP) {
            return
        }
        window.SLIGHTNING_BYPASS_AUDIT_STOP = true

        document.getElementById("editor-iframe")?.remove()

        let originalAlert = alert
        alert = function(message) {
            if (message == "作品审核中,请稍后再试。") {
                console.log(message)
            } else {
                originalAlert.apply(this, arguments)
            }
        }

        let hintElement = document.createElement("div")
        hintElement.innerText = "该作品包含未经审核的第三方自定义控件,需要手动点击按钮运行作品。"
        Object.assign(hintElement.style, {
            width: "100%",
            position: "fixed",
            top: "0px",
            color: "white",
            backgroundColor: "#FF000080",
            backdropFilter: "blur(16px)",
            fontSize: "2em",
            textAlign: "center",
            zIndex: 1000
        })
        document.body.appendChild(hintElement)

        function start() {
            const stringWorkID = location.pathname.split("/").pop()
            if (stringWorkID == null) {
                alert("绕过审核失败:获取作品 ID 失败。")
                return
            }
            const workID = parseInt(stringWorkID)
            const storageKey = `SLIGHTNING_BYPASS_AUDIT_@${workID}_ALLOW_RUN`
            localStorage.removeItem(storageKey)

            let iframe = document.createElement("iframe")
            iframe.src = location.href
            Object.assign(iframe.style, {
                border: "none",
                position: "fixed",
                left: "0px",
                top: "0px",
                width: "100%",
                height: "100%",
                zIndex: 10000
            })
            document.body.append(iframe)
            let { contentWindow } = iframe
            contentWindow.SLIGHTNING_BYPASS_AUDIT_STOP = true

            let originalFetch = contentWindow.fetch
            contentWindow.fetch = async function(input, init) {
                let response = await originalFetch(input, init)
                if (/https?:\/\/static.codemao.cn\/coco\/whitelist.json/.test(input.toString())) {
                    let whiteList = await response.json()
                    whiteList.push(workID)
                    return new Response(JSON.stringify(whiteList), response)
                } else if (/https?:\/\/creation\.bcmcdn\.com\/716\/appcraft\/JSON_([0-9]|[a-z]|[A-Z])*_[0-9]*.json/.test(input.toString())) {
                    let work = await response.json()
                    let { blockCode } = work
                    let element = contentWindow.document.getElementById("editor-iframe")
                    let { contentWindow: editorWindow } = element
                    editorWindow.addEventListener("load", () => {
                        new editorWindow.Function("blockCode", `(${function (blockCode) {
                            parent.postMessage({
                                type: "PLAYER_BLOCK_CODE",
                                payload: blockCode
                            }, "http://coco.codemao.cn")
                            parent.postMessage({
                                type: "PLAYER_BLOCK_CODE",
                                payload: blockCode
                            }, "https://coco.codemao.cn")
                        }.toString()})(blockCode)`)(blockCode)
                        contentWindow.document.getElementById("editor-iframe")?.remove()
                    })
                    return new Response(JSON.stringify(work), response)
                }
                return response
            }
        }

        function setStartButton(element) {
            let startCoverElement = document.createElement("div")
            Object.assign(startCoverElement.style, {
                width: "100%",
                height: "100%",
                position: "absolute",
                top: "0px",
                zIndex: 100,
                backgroundColor: "#00000080",
                display: "flex",
                alignItems: "center",
                justifyContent: "center"
            })

            let startButton = document.createElement("img")
            startButton.src = "https://cdn-community.codemao.cn/community_frontend/asset/play_btn_76b2a.png"
            Object.assign(startButton.style, {
                width: "96px",
                height: "96px",
                cursor: "pointer"
            })
            startCoverElement.append(startButton)

            element.append(startCoverElement)

            startButton.addEventListener("click", start)
        }

        let styleElement = document.createElement("style")
        styleElement.innerHTML = "#rootPlayer:after { content: none !important; }"
        document.body.append(styleElement)

        let wrapElement = document.getElementById("webPlayer")
        if (wrapElement == null) {
            setStartButton(document.getElementById("root"))
        } else {
            wrapElement = wrapElement.children[0]
            setStartButton(wrapElement)
        }
    }

    function modifyReleaseFile(file) {
        if (file.unsafeExtensionWidgetList.length == 0) {
            return
        }
        addExtension(file)
    }

    function addExtension(file) {
        file.unsafeExtensionWidgetList.push({
            code: `
                new Function(\`(\${${
                    bypassAudit.toString()
                }}) ()\`) ()
                const types = {
                    type: "SLIGHTNING_BYPASS_AUDIT_WIDTH",
                    title: "审核绕过",
                    icon: "",
                    isInvisibleWidget: true,
                    isGlobalWidget: true,
                    properties: [],
                    methods: [],
                    events: []
                }
                class Widget extends InvisibleWidget {
                    constructor(props) {
                        super(props)
                    }
                }
                exports.types = types
                exports.widget = Widget
                //`,
            type: "EXTENSION_SLIGHTNING_BYPASS_AUDIT_WIDTH"
        })
    }

    ;(function () {
        let originalSend = XMLHttpRequest.prototype.send
        XMLHttpRequest.prototype.send = function(data) {
            if (data instanceof FormData) {
                let fileName = data.get("fname"),
                    originalFile = data.get("file")
                if (fileName == "test.json") {
                    let xhr = this,
                        xhrArguments = arguments
                    let reader = new FileReader()
                    reader.readAsText(originalFile)
                    reader.onload = async function() {
                        try {
                            let fileContent = JSON.parse(this.result)
                            modifyReleaseFile(fileContent)
                            let blob = new Blob([JSON.stringify(fileContent)], { type: "text/plain" })
                            let file = new File([blob], originalFile.name, { type: originalFile.type })
                            data.set("file", file)
                        } catch (error) {
                            console.error(error)
                            alert(`绕过审核失败:${error.message}`)
                        }
                        originalSend.apply(xhr, xhrArguments)
                    }
                } else {
                    originalSend.apply(this, arguments)
                }
            } else {
                originalSend.apply(this, arguments)
            }
        }
    })()
})()
长期地址
遇到问题?请前往 GitHub 提 Issues。