BiliBili稿件批量举报实验型号
// ==UserScript==
// @name BiliBili稿件批量举报实验型号
// @namespace https://bbs.tampermonkey.net.cn/
// @version 1.1.1 Prototype
// @description 批量举报B站稿件(请谨慎使用)
// @author You
// @match https://space.bilibili.com/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @connect api.bilibili.com
// @connect www.bilibili.com
// ==/UserScript==
const SubmitText = '涉嫌考试作弊,违法违规。'
GM_registerMenuCommand("自动举报所有稿件", fuckBilibiliShitVideo, "h");
let csrfText = ''
// 更健壮的CSRF获取方式
function getCsrf() {
if (!csrfText) {
const cookies = document.cookie.split(';')
for (const cookie of cookies) {
const [key, value] = cookie.trim().split('=')
if (key === 'bili_jct') {
csrfText = decodeURIComponent(value)
break
}
}
}
if (!csrfText) {
throw new Error('未找到CSRF token,请确保已登录')
}
return csrfText
}
// 改用GM_xmlhttpRequest并添加Promise封装
function fuckVideo(aid) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST",
url: 'https://api.bilibili.com/x/web-interface/appeal/v2/submit',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: new URLSearchParams({
aid: aid,
attach: "",
block_author: false,
csrf: getCsrf(),
desc: SubmitText,
tid: 2
}).toString(),
onload: (response) => {
try {
const data = JSON.parse(response.responseText)
if (data.code === 0) {
resolve(true)
} else {
reject(new Error(`API错误: ${data.message}`))
}
} catch (e) {
reject(new Error('响应解析失败'))
}
},
onerror: (error) => reject(error)
})
})
}
// 添加错误处理和更安全的aid提取
async function getVideoAid(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: url,
method: "GET",
onload: function(xhr) {
try {
const match = xhr.responseText.match(/"aid":"?(\d+)"?/)
if (match && match[1]) {
resolve(match[1])
} else {
reject(new Error('未找到视频aid'))
}
} catch (e) {
reject(e)
}
},
onerror: (error) => reject(error)
})
})
}
// 添加延迟防止请求过频
async function getPageAllVideoAid() {
const idList = [...document.querySelectorAll('.bili-cover-card')]
.map(dom => dom.href)
.filter(url => url && url.includes('video/BV'))
for (const [index, url] of idList.entries()) {
try {
const aid = await getVideoAid(url)
await fuckVideo(aid)
console.log(`已处理第 ${index + 1}/${idList.length} 个稿件`)
// 添加1秒间隔防止请求过频
await new Promise(r => setTimeout(r, 1000))
} catch (error) {
console.error(`处理失败(${url}):`, error)
}
}
}
// 添加全局错误处理
async function fuckBilibiliShitVideo() {
if (!confirm('确定要批量举报本页所有稿件吗?此操作不可逆!')) return
try {
await getPageAllVideoAid()
alert('本页稿件处理完成,请查看控制台了解详情')
} catch (error) {
alert('操作失败: ' + error.message)
}
}