// ==UserScript== // @name B站动态批量删除助手 // @version 0.23 // @description 这是一个帮助B站用户高效管理个人动态的脚本,支持多种类型动态的批量删除操作。 // @author 梦把我 // @match https://space.bilibili.com/* // @match http://space.bilibili.com/* // @require https://greasyfork.org/scripts/38220-mscststs-tools/code/MSCSTSTS-TOOLS.js?version=713767 // @require https://cdn.jsdelivr.net/npm/axios@1.7.3/dist/axios.min.js // @icon https://static.hdslb.com/images/favicon.ico // @license MIT // @grant none // @namespace https://greasyfork.org/users/1383389 // @downloadURL none // ==/UserScript== (function () { 'use strict'; const uid = window.location.pathname.split("/")[1]; function getUserCSRF() { return document.cookie.split("; ").find(row => row.startsWith("bili_jct="))?.split("=")[1]; } const csrfToken = getUserCSRF(); class Api { constructor() { } async spaceHistory(offset = 0) { // 获取个人动态 return this.retryOn429(() => this._api( `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history?visitor_uid=${uid}&host_uid=${uid}&offset_dynamic_id=${offset}`, {}, "get" )); } async removeDynamic(id) { // 删除动态 return this._api( "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/rm_dynamic", { dynamic_id: id, csrf_token: csrfToken } ); } async _api(url, data, method = "post") { // 通用请求 return axios({ url, method, data: this.transformRequest(data), withCredentials: true, headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(res => res.data); } transformRequest(data) { // 转换请求参数 return Object.entries(data).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'); } async fetchJsonp(url) { // jsonp请求 return fetchJsonp(url).then(res => res.json()); } async retryOn429(func, retries = 5, delay = 100) { // 出现429错误时冷却100ms重试,出现412错误时提示并退出 while (retries > 0) { try { return await func(); } catch (err) { if (err.response && err.response.status === 429) { await this.sleep(delay); retries--; } else if (err.response && err.response.status === 412) { alert('由于请求过于频繁,IP暂时被ban,请更换IP或稍后再试。'); throw new Error('IP blocked, please retry later.'); } else { throw err; } } } throw new Error('Too many retries, request failed.'); } sleep(ms) { // 睡眠 return new Promise(resolve => setTimeout(resolve, ms)); } } const api = new Api(); const buttons = [".onlyDeleteRepost", ".deleteVideo", ".deleteImage", ".deleteText", ".deleteCustomType"]; let logNode; // 添加确认状态管理 const confirmStates = { deleteStates: {}, resetTimer: null }; async function init() { const shijiao = await mscststs.wait(".h-version-state", true, 100); if (!shijiao || shijiao.innerText != "我自己") { console.log('当前不是自己的个人动态'); return; } await Promise.all([ mscststs.wait("#page-dynamic"), mscststs.wait("#page-dynamic .col-2") ]); const node = createControlPanel(); document.querySelector("#page-dynamic .col-2").append(node); logNode = document.querySelector(".msc_panel .log"); setEventListeners(); // 设置教程链接 document.querySelector('.tutorial-btn').href = '占位符URL'; // 添加样式 const style = document.createElement('style'); style.textContent = ` .msc_panel { max-width: 800px; margin: 20px auto; padding: 20px; background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .panel-section { margin-bottom: 24px; padding-bottom: 20px; border-bottom: 1px solid #eee; } .panel-section:last-child { border-bottom: none; margin-bottom: 0; } .panel-section h3 { font-size: 16px; color: #18191c; margin-bottom: 16px; font-weight: 500; } .type-table table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 14px; } .type-table th, .type-table td { padding: 8px; text-align: center; border: 1px solid #eee; } .type-table th { background: #f6f7f8; } .input-group { display: flex; gap: 10px; margin-bottom: 10px; } .type-input { flex: 1; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; } .button-group { display: flex; flex-wrap: wrap; gap: 10px; } .msc_panel button { padding: 8px 16px; border-radius: 4px; border: 1px solid #ddd; background: #fff; cursor: pointer; font-size: 14px; transition: all 0.2s; } .msc_panel button:hover { background: #f6f7f8; } .msc_panel button.primary-btn { background: #00aeec; color: #fff; border-color: #00aeec; } .msc_panel button.primary-btn:hover { background: #0096cc; } .msc_panel button.warning-btn { background: #fb7299; color: #fff; border-color: #fb7299; } .msc_panel button.warning-btn:hover { background: #e45c80; } .msc_panel button:disabled { background: #eee; color: #999; cursor: not-allowed; border-color: #ddd; } .tutorial-btn { display: inline-block; padding: 8px 16px; background: #6c757d; color: #fff; text-decoration: none; border-radius: 4px; transition: all 0.2s; } .tutorial-btn:hover { background: #5a6268; } .log { margin-top: 16px; padding: 12px; background: #f6f7f8; border-radius: 4px; font-size: 14px; color: #666; } @keyframes buttonBlink { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } } .msc_panel button.confirming { background-color: #ff6b6b !important; color: white !important; } .msc_panel button:disabled { animation: none !important; opacity: 0.5 !important; } `; document.head.appendChild(style); addConfirmationStyles(); } function createControlPanel() { const node = document.createElement("div"); node.className = "msc_panel"; node.innerHTML = `
类型值 | 含义 |
---|---|
1 | 转发 |
2 | 图片动态 |
4 | 文字动态 |
8 | 视频动态 |
16 | 小视频 |
64 | 专栏 |
256 | 音频 |