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

绕过 CoCo 作品分享的审核机制,让别人可以运行你分享的作品,请低调使用

目前為 2024-06-22 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         编程猫 CoCo 作品分享审核绕过
// @namespace    https://s-lightning.github.io/
// @version      0.1.7
// @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 objectSet(object, properties) {
        for (let key in properties) {
            object[key] = properties[key]
        }
    }

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

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

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

        let wrapElement = document.getElementById("webPlayer").children[0]
        let originalAppendChild = wrapElement.appendChild
        wrapElement.appendChild = function() {
            originalAppendChild.apply(this, arguments)
            setTimeout(function() {
                let playerElement = document.getElementById("rootPlayer")

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

                let startButton = document.createElement("img")
                startButton.src = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iOTZweCIgaGVpZ2h0PSI5NnB4IiB2aWV3Qm94PSIwIDAgOTYgOTYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+aWNvbi85Ni9kZXRhaWwvcGxheTwvdGl0bGU+CiAgICA8ZyBpZD0iaWNvbi85Ni9kZXRhaWwvcGxheSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPHJlY3QgaWQ9IlJlY3RhbmdsZSIgZmlsbC1ydWxlPSJub256ZXJvIiB4PSIwIiB5PSIwIiB3aWR0aD0iOTYiIGhlaWdodD0iOTYiPjwvcmVjdD4KICAgICAgICA8ZyBpZD0iaWNvbi85Ni9wbGF5IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS4wMDAwMDAsIDExLjAwMDAwMCkiIGZpbGwtcnVsZT0ibm9uemVybyI+CiAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwiIGZpbGwtb3BhY2l0eT0iMC43IiBmaWxsPSIjRkZGRkZGIiBjeD0iMzciIGN5PSIzNyIgcj0iMzciPjwvY2lyY2xlPgogICAgICAgICAgICA8cGF0aCBkPSJNNTEuMDAyOTkzNiwzOC43MzYzMjY1IEwyOS44Njg3MDU1LDUwLjc1MTMyMDggQzI4LjkzNDg1NDIsNTEuMjgyMjIxOSAyNy43NTg3NDQ2LDUwLjkzNTE0MDkgMjcuMjQxNzkxMiw0OS45NzYwOTM3IEMyNy4wODMxOTk5LDQ5LjY4MTg3NjYgMjcsNDkuMzUxMTAxMyAyNyw0OS4wMTQ4MTIxIEwyNywyNC45ODQ4MjM2IEMyNywyMy44ODg2MzU4IDI3Ljg2NTI4OTcsMjMgMjguOTMyNjc4NiwyMyBDMjkuMjYwMTMyNywyMyAyOS41ODIyMTgsMjMuMDg1NDQ0NyAyOS44Njg3MDU1LDIzLjI0ODMxNDkgTDUxLjAwMjk5MzYsMzUuMjYzMzA5MiBDNTEuOTM2ODQ0OSwzNS43OTQyMTAzIDUyLjI3NDgwNzQsMzcuMDAyMDUyMiA1MS43NTc4NTQsMzcuOTYxMDk5NCBDNTEuNTgyMDk0OCwzOC4yODcxNjYzIDUxLjMyMDQ5NDEsMzguNTU1ODI1MiA1MS4wMDI5OTM2LDM4LjczNjMyNjUgWiIgaWQ9IlRyaWFuZ2xlIiBmaWxsPSIjMzMzMzMzIj48L3BhdGg+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4="
                objectSet(startButton.style, {
                    cursor: "pointer"
                })
                startCoverElement.append(startButton)

                playerElement.append(startCoverElement)

                startButton.addEventListener("click", function() {
                    if (confirm("该作品包含未经审核的自定义控件,确定要运行该作品吗?若确定要运行该作品,请点击“取消”,否则请点击“确定”。")) {
                        return
                    }
                    if (!confirm("确定要运行该作品吗?")) {
                        return
                    }

                    let iframe = document.createElement("iframe")
                    iframe.src = location.href
                    objectSet(iframe.style, {
                        border: "none",
                        position: "fixed",
                        left: "0px",
                        top: "0px",
                        width: "100%",
                        height: "100%"
                    })
                    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 (input == "https://static.codemao.cn/coco/whitelist.json") {
                            let workID = Number(location.pathname.split("/").pop())
                            let whiteList = await response.json()
                            whiteList.push(workID)
                            return new Response(JSON.stringify(whiteList), {
                                ...response
                            })
                        }
                        return response
                    }
                })
            }, 0)
            wrapElement.appendChild = originalAppendChild
        }
    }

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

    function moveUnsafeToSafe(unsafeList, safeList) {
        let safeMap = {}
        safeList.forEach(safe => {
            safeMap[safe.type] = safe
        })
        let unsafe
        while (unsafe = unsafeList.shift()) {
            let safe,
                cdnUrl = `data:text/plain;charset=UTF-8,${encodeURIComponent(unsafe.code)}//`,
                {type} = unsafe
            if (safe = safeMap[type]) {
                safe.cdnUrl = cdnUrl
            } else {
                let safe = {
                    id: Math.floor(Math.random() * 10000) + 10000,
                    type: type,
                    cdnUrl: cdnUrl
                }
                safeList.push(safe)
            }
        }
    }

    function addExtension(file) {
        file.extensionWidgetList.push({
            id: 0,
            type: "EXTENSION_SLIGHTNING_BYPASS_AUDIT",
            cdnUrl:
                "data:text/plain;charset=UTF-8," +
                encodeURIComponent(`
                    new Function(\`
                    ${objectSet.toString()}
                    ;(\${${
                        bypassAudit.toString()
                    }}) ()\`) ()
                    const types = {
                        type: "SLIGHTNING_BYPASS_AUDIT",
                        title: "审核绕过",
                        icon: "",
                        isInvisibleWidget: true,
                        isGlobalWidget: true,
                        properties: [],
                        methods: [],
                        events: []
                    }
                    class Widget extends InvisibleWidget {
                        constructor(props) {
                            super(props)
                        }
                    }
                    exports.types = types
                    exports.widget = Widget
                //`)
        })
    }

    ;(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.replaceAll("UNSAFE_EXTENSION_", "EXTENSION_"))
                            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)
            }
        }
    })()
})()