// ==UserScript==
// @name 【已失效】编程猫 CoCo 作品分享审核绕过
// @namespace https://s-lightning.github.io/
// @version 0.1.9
// @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 (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)
}
}
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`
if (!JSON.parse(localStorage.getItem(storageKey) || "false")) {
if (confirm("该作品包含未经审核的自定义控件,确定要运行该作品吗?若确定要运行该作品,请点击“取消”,否则请点击“确定”。")) {
return
}
if (!confirm("确定要运行该作品吗?")) {
return
}
localStorage.setItem(storageKey, JSON.stringify(true))
}
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
})
}
return response
}
}
function setStartButton(element) {
let startCoverElement = document.createElement("div")
Object.assign(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 = "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]
let originalAppendChild = wrapElement.appendChild
wrapElement.appendChild = function() {
originalAppendChild.apply(this, arguments)
setTimeout(function() {
setStartButton(document.getElementById("rootPlayer"))
}, 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(\`(\${${
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)
}
}
})()
})()