// ==UserScript==
// @name 编程猫账号保护
// @namespace https://s-lightning.github.io/
// @version 0.0.2
// @description 保护你的编程猫账号。
// @author SLIGHTNING
// @match http://*.codemao.cn/*
// @match https://*.codemao.cn/*
// @icon https://static.codemao.cn/coco/player/unstable/B1F3qc2Hj.image/svg+xml?hash=FlHXde3J3HLj1PtOWGgeN9fhcba3
// @grant none
// @license AGPL-3.0
// @run-at document-start
// ==/UserScript==
(function() {
"use strict"
window.SLIGHTNING_ACCOUNT_PROTECT = true
setInterval(() => {
document.cookie = "access-token=0;path=/;domain=.codemao.cn;max-age=" + 30 * 24 * 60 * 60
}, 100)
let interceptResponse = {
code: 403,
msg: "该操作被编程猫账号保护脚本拦截",
error_code: 403,
error_message: "该操作被编程猫账号保护脚本拦截"
}
function onIntercept(url, go, reject, modify) {
if (/https?:\/\/api\.codemao\.cn\/tiger\/v3\/web\/accounts\/username.*/.test(url)) {
reject()
} else if (/https?:\/\/api\.codemao\.cn\/tiger\/v3\/web\/accounts\/tokens\/convert/.test(url)) {
reject()
} else if (/https?:\/\/api\.codemao\.cn\/tiger\/v3\/web\/accounts\/privacy/.test(url)) {
reject()
} else if (/https?:\/\/api\.codemao\.cn\/web\/users\/details/.test(url)) {
modify(function (response) {
if (response.status == 200) {
let text = JSON.parse(response.text)
Object.assign(text, {
birthday: 0,
phone_number: "***********",
qq: "****",
real_name: "已拦截",
username: "已拦截"
})
text = JSON.stringify(text)
return { text }
} else {
return {}
}
})
} else if (/https?:\/\/api\.codemao\.cn\/api\/user\/info/.test(url)) {
modify(function (response) {
response = JSON.parse(response.text)
if (response.code == 200) {
Object.assign(response.data, {
age: 0,
username: "已拦截",
telephone: "***********",
qq: "****",
email: "****",
real_name: "已拦截"
})
return {
text: JSON.stringify(response)
}
} else {
return {}
}
})
} else {
go()
}
}
;(function () {
let originalFetch = fetch
fetch = function (url, options) {
if (url instanceof Request) {
url = url.url
}
return new Promise((resolve, reject) => {
onIntercept(url, () => {
originalFetch.apply(this, arguments).then(resolve).catch(reject)
}, () => {
return new Response(JSON.stringify(interceptResponse), {
status: 403,
statusText: "403 Forbidden"
})
}, (callback) => {
let result = originalFetch.apply(this, arguments)
result.then((response) => {
response.text().then((originalText) => {
let { status, text } = callback({
status: response.status,
text: originalText
})
let { statesText } = response
if (status == null) {
status = response.status
} else {
statesText = String(status)
}
if (text == null) {
text = originalText
}
resolve(new Response(text, {
...response, status, statesText
}))
}).catch(reject)
}).catch(reject)
})
})
}
})()
;(function () {
let originalXMLHttpRequest = XMLHttpRequest
XMLHttpRequest = function () {
let XHR = new originalXMLHttpRequest()
for (let key in XHR) {
if (typeof XHR[key] == "function") {
this[key] = XHR[key].bind(XHR)
} else {
Object.defineProperty(this, key, {
get() {
return XHR[key]
},
set(value) {
XHR[key] = value
},
configurable: true
})
}
}
Object.defineProperty(this, "open", {
value: function (method, url) {
this.__url = url
this.__openArguments = arguments
XHR.open.apply(XHR, arguments)
}
})
Object.defineProperty(this, "send", {
value: function () {
onIntercept(this.__url, () => {
XHR.send.apply(XHR, arguments)
}, reject, (callback) => {
modifyResponse(this, function (XHR) {
let { status, text } = callback({
status: XHR.status,
text: XHR.responseText
})
let result = {}
if (status != null) {
result.states = status
result.statesText = String(status)
}
if (text != null) {
result.response = text
result.responseText = text
}
return result
})
})
}
})
}
XMLHttpRequest.prototype = originalXMLHttpRequest.prototype
function forgeResponse(XHR, response) {
for (let key in response) {
delete XHR[key]
XHR[key] = response[key]
}
function dispatchEvent(eventType) {
let callback = XHR["on" + eventType]
if (callback instanceof Function) {
try {
callback.call(XHR)
} catch (error) {
console.error(error)
}
}
XHR.dispatchEvent(new Event(eventType))
}
dispatchEvent("loadstart")
delete XHR.readyState
XHR.readyState = XHR.DONE
dispatchEvent("readystatechange")
if (response.status == 200) {
dispatchEvent("load")
} else {
dispatchEvent("error")
}
dispatchEvent("loadend")
}
function modifyResponse(XHR, callback) {
let originalXHR = new originalXMLHttpRequest()
originalXHR.withCredentials = XHR.withCredentials
originalXHR.open.apply(originalXHR, XHR.__openArguments)
originalXHR.onreadystatechange = function () {
if (originalXHR.readyState == 4) {
for (let key of ["status", "statusText", "responseType", "response", "responseText"]) {
delete XHR[key]
XHR[key] = originalXHR[key]
}
forgeResponse(XHR, callback(XHR))
}
}
originalXHR.send()
}
function reject(XHR) {
forgeResponse(XHR, {
status: 403,
statusText: "403 Forbidden",
responseType: "json",
response: JSON.stringify(interceptResponse),
responseText: JSON.stringify(interceptResponse)
})
}
})()
})()