Bilibili Black Deque

Make blacklist of bilibili a deque

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name Bilibili Black Deque
// @version 0.0.6
// @namespace http://tampermonkey.net/
// @description Make blacklist of bilibili a deque
// @author Zxilly
// @source https://github.com/Zxilly/bili-black-deque
// @license https://opensource.org/licenses/MIT
// @match *://www.bilibili.com/*
// @require https://cdn.jsdelivr.net/npm/[email protected]
// ==/UserScript==

/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 242:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getBlackListCnt = getBlackListCnt;
const axios_1 = __importDefault(__webpack_require__(719));
function getBlackListCnt() {
    return __awaiter(this, void 0, void 0, function* () {
        const result = (yield axios_1.default.get('https://api.bilibili.com/x/relation/blacks', {
            withCredentials: true
        })).data;
        return result.data.total;
    });
}


/***/ }),

/***/ 449:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const pop_1 = __webpack_require__(74);
const count_1 = __webpack_require__(242);
function manualRemove() {
    return __awaiter(this, void 0, void 0, function* () {
        let total = yield (0, count_1.getBlackListCnt)();
        const uin = window.prompt(`现在黑名单有 ${total} 人,想移除:`);
        if (uin === null) {
            alert("必须输入一个整数");
            return;
        }
        const deleteNum = Number.parseInt(uin);
        if (Number.isNaN(deleteNum)) {
            alert(`${uin} 不能被解释为合法整数`);
            return;
        }
        if (deleteNum <= 0) {
            alert("数字必须大于 0");
        }
        if (total < deleteNum) {
            alert(`当前黑名单中的人数 ${total} 少于 ${deleteNum}`);
            return;
        }
        yield (0, pop_1.popBlack)(deleteNum, total);
        const current = yield (0, count_1.getBlackListCnt)();
        alert(`处理完成,当前黑名单有 ${current} 人`);
    });
}
function configureAndSet() {
    return __awaiter(this, void 0, void 0, function* () {
        let total = yield (0, count_1.getBlackListCnt)();
        const uin = window.prompt(`当前黑名单有 ${total} 人,想保持在:`);
        if (uin === null) {
            alert("必须输入一个整数");
            return;
        }
        const target = Number.parseInt(uin);
        if (Number.isNaN(target)) {
            alert(`${uin} 不能被解释为合法整数`);
            return;
        }
        if (target <= 0) {
            alert("数字必须大于 0");
        }
        if (target > total) {
            console.warn(`当前黑名单中的人数 ${total} 少于 ${target}`);
        }
        localStorage.setItem(KEEP_TARGET, target.toString());
        localStorage.removeItem(LAST_TASK_DATE);
        yield task();
    });
}
function task() {
    return __awaiter(this, void 0, void 0, function* () {
        const keepTarget = localStorage.getItem(KEEP_TARGET);
        if (keepTarget === null) {
            return;
        }
        const target = Number.parseInt(keepTarget);
        if (Number.isNaN(target)) {
            console.error(`target ${keepTarget} is not a number`);
            return;
        }
        const lastTaskDate = localStorage.getItem(LAST_TASK_DATE);
        const today = new Date().toDateString();
        if (lastTaskDate === today) {
            return;
        }
        let total = yield (0, count_1.getBlackListCnt)();
        if (total > target) {
            yield (0, pop_1.popBlack)(total - target, total);
        }
        localStorage.setItem(LAST_TASK_DATE, today);
    });
}
document.addEventListener("keydown", (ev) => __awaiter(void 0, void 0, void 0, function* () {
    if (ev.altKey && ev.key === "b") {
        yield manualRemove();
    }
    if (ev.altKey && ev.key === "c") {
        yield configureAndSet();
    }
}));
const KEEP_TARGET = "keep-target";
const LAST_TASK_DATE = "last-task-date";
(() => __awaiter(void 0, void 0, void 0, function* () {
    console.info("alt + b to run");
    console.info("alt + c to set target");
    yield task();
}))();


/***/ }),

/***/ 74:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.popBlack = popBlack;
const axios_1 = __importDefault(__webpack_require__(719));
const csrf_token = document.cookie.split('; ').find(row => row.startsWith('bili_jct')).split('=')[1];
function popBlack(num, total) {
    return __awaiter(this, void 0, void 0, function* () {
        const last_page = Math.ceil(total / 50);
        const toRemove = [];
        for (let current_page = last_page; current_page > 0; current_page--) {
            const resp = (yield axios_1.default.get('https://api.bilibili.com/x/relation/blacks', {
                params: {
                    ps: 20,
                    pn: current_page
                },
                withCredentials: true
            })).data;
            const list = resp.data.list;
            list.reverse();
            for (const user of list) {
                const id = user['mid'];
                toRemove.push(id);
                if (toRemove.length >= num) {
                    break;
                }
            }
            if (toRemove.length >= num) {
                break;
            }
        }
        console.log(JSON.stringify(toRemove));
        console.log("收集完成,准备解除");
        console.groupCollapsed("解除请求细节");
        for (let id of toRemove) {
            const params = new URLSearchParams();
            params.append("fid", id);
            params.append("csrf", csrf_token);
            params.append("act", "6");
            params.append("re_src", "116");
            let retries = 3;
            while (retries > 0) {
                const resp = (yield axios_1.default.post("https://api.bilibili.com/x/relation/modify", params, {
                    withCredentials: true
                })).data;
                console.debug(JSON.stringify(resp));
                if (resp.code === 0) {
                    break;
                }
                retries--;
                console.log("限流中,等待2秒");
                yield new Promise(r => setTimeout(r, 2000));
            }
        }
        console.groupEnd();
    });
}


/***/ }),

/***/ 719:
/***/ ((module) => {

module.exports = axios;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module is referenced by other modules so it can't be inlined
/******/ 	var __webpack_exports__ = __webpack_require__(449);
/******/ 	
/******/ })()
;