从春卷老师的脚本改的,桌面端使用方法:
- 安装tampermonkey(Firefox/Chrome/Edge, etc.)
- tampermonkey打开dashboard
- 点+号,新建脚本,copy&paste(覆盖掉TM自己生成的脚本模板)
- 在proflat主题下无效
如何汇报问题
- 1. 确保所有的code全部copy & paste进了油猴
- 2. 你是用的什么浏览器
- 3. 你用的什么主题(控制面板->偏好设置->我的论坛风格)
- 4. 最好有浏览器截图,可以把书签地址栏隐藏,只需要在某个主题下的截图
手机端
- 推荐使用Firefox Mobile,同样可以用tampermonkey, https://addons.mozilla.org/en-US/androi ... permonkey/
- 10/17/22, 修复版面上失效的问题
- 7/9/23, 修复无法添加部分含有空格id的问题
- 2/20/25, 添加了屏蔽部分版面的功能; 添加F2开关
- 2/23/25, 修复checkbox无法立即生效的bug
代码: 全选
// ==UserScript==
// @name NewMitbbs-bot-blocker
// @namespace http://tampermonkey.net/
// @version 0.2.3
// @description Manages and blocks bot generated content. Shamelessly modified from chunjuan's script at https://greasyfork.org/en/scripts/29195-mitbbs-bot-blocker/code, which was inspired by Smalltalk80's original GM script, http://userscripts-mirror.org/scripts/review/78633
// @author Sagittarius A*
// @match http://newmitbbs.com/*
// @match https://newmitbbs.com/*
// @grant GM_addStyle
// @run-at document-idle
// ==/UserScript==
(function () {
'use strict';
var storageKey = 'new.mitbbs.blocklist';
function getBlocklist() {
var blockList = localStorage.getItem(storageKey);
if (blockList === null) {
setBlocklist([]);
blockList = localStorage.getItem(storageKey);
}
try {
blockList = JSON.parse(blockList);
} catch (error) {
blockList = [];
setBlocklist(blockList);
}
blockList = Array.isArray(blockList) ? blockList : [];
return blockList;
}
function setBlocklist(idNameList) {
// remove duplicate items
// todo: babel output for this one doesn't really work, have to revert back to old fashion way
// idNameList = [...new Set(idNameList)]
var uniqueidNameList = idNameList.filter(function (elem, index, self) {
return index === self.indexOf(elem);
});
uniqueidNameList = uniqueidNameList.sort(function (a, b) {
// defer from localeCompare for better browser support
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
});
localStorage.setItem(storageKey, JSON.stringify(uniqueidNameList));
document.getElementById('blockListInput').value = uniqueidNameList;
}
function getBlockFlag() {
var blockFlag = localStorage.getItem(storageKey + '.flag');
if (blockFlag === null) {
setBlockFlag(0);
blockFlag = localStorage.getItem(storageKey + '.flag');
}
// js, just being js
return parseInt(blockFlag);
}
function setBlockFlag(flag) {
localStorage.setItem(storageKey + '.flag', flag);
}
function updateBoardVisibility() {
var pathname = window.location.pathname;
if(pathname != "/" && pathname != "/index.php"){
console.log("1: not at main page, not supposed to happen something is wrong");
return;
}
// update list of board
var boardMap = new Map(JSON.parse(localStorage.getItem(storageKey + ".boardMap")));
if(boardMap == null)
boardMap = new Map();
Array.from(document.getElementsByClassName("forumtitle")).forEach((v, i, a) => {
//boardMap.set(v.text, [v.getAttribute("href"), "1"])
if(!boardMap.has(v.text)) // a new board
boardMap.set(v.text, [v.getAttribute("href"), "1"]) // 1st elem of arr is href of board, 2nd elem of arr is board switch flag, "1" allow, "0" disabled
});
localStorage.setItem(storageKey + ".boardMap", JSON.stringify(Array.from(boardMap.entries())));
var boardCheckList = document.getElementById('checkboxes').getElementsByTagName("ul")[0]
boardCheckList.innerHTML = '';
boardMap.forEach((v, k) => {
var li = document.createElement("li");
var inputNode = document.createElement("input");
inputNode.type = "checkbox";
inputNode.checked = v[1] == "1" ? true : false;
inputNode.addEventListener('change', function(){
if(this.checked){
boardMap.set(k, [v[0], "1"]);
localStorage.setItem(storageKey + ".boardMap", JSON.stringify(Array.from(boardMap.entries())));
}else{
boardMap.set(k, [v[0], "0"]);
localStorage.setItem(storageKey + ".boardMap", JSON.stringify(Array.from(boardMap.entries())));
}
});
li.appendChild(inputNode);
li.appendChild(document.createTextNode(k));
boardCheckList.appendChild(li);
});
// block boards
boardMap = new Map(JSON.parse(localStorage.getItem(storageKey + ".boardMap")));
if(boardMap == null) {
boardMap = new Map();
}
var setOfBlockedBoardUrls = new Set();
boardMap.forEach((v, k) => {
if(v[1] == "0"){
setOfBlockedBoardUrls.add(v[0]);
}
});
Array.from(document.getElementsByClassName("topiclist forums")).forEach(it => { // forum sections
Array.from(it.getElementsByClassName("row")).forEach(iit => { // forums under each section
if(setOfBlockedBoardUrls.has(iit.getElementsByClassName("forumtitle")[0].getAttribute("href")))
iit.style.display = "none";
else
iit.style.display = "";
});
});
}
function updatePostVisibility() {
var blockList = getBlocklist();
var flag = getBlockFlag();
// if list is not empty
var counter = 0;
if (blockList) {
var taolunDiv = document.querySelector('div.forumbg:not(.announcement)');
if (taolunDiv == null)
taolunDiv = document.querySelector('div.sn-cat-header:not(.announcement)');
// yeah yeah yeah magic number, whatever
// this will miss the first one though, nice try langfang coder
var userIDtdNodeList = taolunDiv.querySelectorAll('li.row');
// console.log(userIDtdNodeList.length);
userIDtdNodeList.forEach(function (td) {
// damn, now i miss jquery/zepto
var id;
if (td.querySelector('div.topic-poster') != null) {
id = td.querySelector('div.topic-poster').querySelector('span.username').textContent;
// console.log("debug 3");
} else if (td.querySelector('div.responsive-show:not([style*="display:none"]') != null) {
id = td.querySelector('div.responsive-show:not([style*="display:none"]').querySelector('span.username').textContent;
// console.log("debug 2");
} else {
console.log("couldn't find td");
}
// reset all reply to visible. This is a hack-ish method to fix content not being displayed after userID has been removed from blocklist.
// TODO: maybe in the near future, we should keep a local copy of blocklist so that we can compare the changes and show/hide content intelligently, maybe
td.style.display = '';
// yeah, nested if statements
// console.log("op's id is " + id);
if (blockList.indexOf(id) > -1) {
if (flag) {
td.style.display = 'none';
// console.log(id + "'s post has been set as invisible");
counter += 1;
} else {
td.style.display = '';
}
}
});
counter = flag ? counter : 0;
document.getElementById('blockCounter').innerHTML = counter;
}
}
function updateReplyVisibility() {
// console.log("changeReplyVisibility called")
// now we on individual post page
var blockList = getBlocklist();
var flag = getBlockFlag();
var counter = 0;
var sideBarBG = document.querySelectorAll('div.post.has-profile');
sideBarBG.forEach(function (reply) {
// var post = reply.parentElement.parentElement.parentElement.parentElement.parentElement;
var userID = reply.querySelector('span.username').textContent;
// another magic number!
var userMenu = reply.querySelector('strong');
var hasButton = userMenu.querySelector('span.button') !== null;
if (!hasButton) {
var blockButton = document.createElement('span');
blockButton.setAttribute('class', 'button');
blockButton.innerHTML = ' <button class="addToBlock" title="' + userID + '">屏蔽!</button>';
userMenu.appendChild(blockButton);
}
if (!flag) userMenu.querySelector('span.button').style.display = 'none';
else userMenu.querySelector('span.button').style.display = '';
// reset all reply to visible. This is a hack-ish method to fix content not being displayed after userID has been removed from blocklist.
// TODO: maybe in the near future, we should keep a local copy of blocklist so that we can compare the changes and show/hide content intelligently, maybe
reply.style.display = '';
if (blockList.indexOf(userID) > -1) {
if (flag) {
reply.style.display = 'none';
counter += 1;
} else {
reply.style.display = '';
}
}
counter = flag ? counter : 0;
document.getElementById('blockCounter').innerHTML = counter;
});
var allBlockButton = document.querySelectorAll('.addToBlock');
Array.from(allBlockButton).forEach(function (button) {
var userID = button.getAttribute('title');
button.addEventListener('click', function () {
var yesBlock = confirm('Block ' + userID + ' ?');
if (yesBlock) {
blockList.push(userID);
setBlocklist(blockList);
document.getElementById('blockListInput').value = getBlocklist().join();
// updateGlobalVisibility();
// copy & paste from above code to refresh the page with newly added id
sideBarBG.forEach(function (reply) {
// var post = reply.parentElement.parentElement.parentElement.parentElement.parentElement;
var userID = reply.querySelector('span.username').textContent;
// another magic number!
var userMenu = reply.querySelector('strong');
var hasButton = userMenu.querySelector('span.button') !== null;
if (!hasButton) {
var blockButton = document.createElement('span');
blockButton.setAttribute('class', 'button');
blockButton.innerHTML = ' <button class="addToBlock" title="' + userID + '">屏蔽!</button>';
userMenu.appendChild(blockButton);
}
if (!flag) userMenu.querySelector('span.button').style.display = 'none';
else userMenu.querySelector('span.button').style.display = '';
// reset all reply to visible. This is a hack-ish method to fix content not being displayed after userID has been removed from blocklist.
// TODO: maybe in the near future, we should keep a local copy of blocklist so that we can compare the changes and show/hide content intelligently, maybe
reply.style.display = '';
if (blockList.indexOf(userID) > -1) {
if (flag) {
reply.style.display = 'none';
counter += 1;
} else {
reply.style.display = '';
}
}
counter = flag ? counter : 0;
document.getElementById('blockCounter').innerHTML = counter;
});
}
});
});
}
// callback of block switch checkbox. state of checkbox should be read from localStorage by getBlockFlag() to determine state of switch
function updateGlobalVisibility() {
//if(getBlockFlag() === 0) return; //
switch(locationGuesser()) {
case 0:
updateBoardVisibility();
break;
case 1:
updatePostVisibility();
break;
case 2:
updateReplyVisibility();
break;
default:
break;
}
}
function locationGuesser() {
var pageType = void 0;
var pathname = window.location.pathname;
if(pathname === "/" || pathname === "/index.php"){
pageType = 0; // at main page
} else if(pathname === "/viewforum.php") {
pageType = 1; // inside a board
} else if(pathname === "/viewtopic.php") {
pageType = 2; // inside a post
} else {
pageType = -1; // placeholder
}
return pageType;
}
// callback for when clicking "block" checkbox
function toggleBlockSwitch() {
setBlockFlag(document.getElementById('isBlocking').checked ? 1 : 0);
updateGlobalVisibility();
}
// callback for when clicking 黑名单 button
function toggleBlockListVisibility() {
var notVisible = document.getElementById('blockListPop').style.display === 'none';
if (notVisible) {
// show block list pop up
document.getElementById('blockListInput').value = getBlocklist().join();
document.getElementById('blockListPop').style.display = '';
} else {
// close block list pop up
document.getElementById('blockListPop').style.display = 'none';
// update blocklist when closing the pop up
updateBlockList();
//var pathname = window.location.pathname;
//if(pathname === "/" || pathname === "/index.php")
// blockBoards();
updateGlobalVisibility();
}
}
function updateBlockList() {
// update ids list
var newBlockList = document.getElementById('blockListInput').value;
//// remove line break, space, trailing comma
//newBlockList = newBlockList.replace(/(\r\n|\n|\r)/gm, '').replace(/\s/g, '').replace(/,+$/, '');
// remove line break, trailing comma
newBlockList = newBlockList.replace(/(\r\n|\n|\r)/gm, '').replace(/,+$/, '');
newBlockList = newBlockList.split(',');
setBlocklist(newBlockList);
// update board list
// WIP
// re-filter existing content
updateGlobalVisibility();
}
function hideBlockList() {
document.getElementById('blockListPop').style.display = 'none';
}
function prepPage() {
getBlocklist();
document.getElementById('isBlocking').checked = (getBlockFlag() === 1 ? true : false);
updateGlobalVisibility();
}
function pageOnLoad() {
// build blocker control gui
var blockerDiv = document.createElement('div');
blockerDiv.innerHTML = '<button id="showBlocklist" class="button">黑名单</button><input type="checkbox" id="isBlocking" /><span id="blockCounter" title="Currently Blocked"></span>';
blockerDiv.style.cssText = 'position:fixed; bottom:2em; right:0.5em; width:9em; padding:0.5em; border-radius:0.25em; background-color:#D7EAF9; box-shadow:2px 2px 4px 0px rgba(0,0,0,0.5); text-align:center; cursor:pointer;';
document.body.appendChild(blockerDiv);
document.getElementById('showBlocklist').addEventListener('click', toggleBlockListVisibility);
document.getElementById('blockCounter').style.cssText = 'padding:0 4px; font-weight:bold';
document.getElementById('isBlocking').addEventListener('change', toggleBlockSwitch);
// block list
var blockListDiv = document.createElement('div');
blockListDiv.setAttribute('id', 'blockListPop');
blockListDiv.innerHTML = '<div id="checkboxes", style="overflow-y:auto;"><label style="color:blue">版面列表</label><ul style="text-align:left;margin:0;padding:10;color:blue"></ul></div><br/><span>修改ID,用逗号分隔,大小写敏感!</span>' + '<br/>' + '<textarea rows="10" cols="40" id="blockListInput" style="background-color:orange;color:black;font-size:10pt;"></textarea>';
blockListDiv.style.cssText = 'position:fixed; bottom:5.3em; right:0.5em; padding:0.5em; border-radius:0.25em; background-color:#D7EAF9; box-shadow:2px 2px 4px 0px rgba(0,0,0,0.5); text-align:center; display:none';
document.body.appendChild(blockListDiv);
prepPage();
}
function ready(fn) {
if (document.readyState !== 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
ready(pageOnLoad);
// hotkey (F2) to toggle switch
document.addEventListener('keydown', function(event) {
event.stopImmediatePropagation();
if(event.code === "F2"){
// toggle checkbox
document.getElementById('isBlocking').checked = !document.getElementById('isBlocking').checked;
setBlockFlag(document.getElementById('isBlocking').checked ? 1 : 0);
updateGlobalVisibility()
}
}, true);
})();