🏠 Home 

v2ex 快速屏蔽用户和帖子

在用户评论区域添加一个 block 按钮,不用点进用户主页,点击即可 block 用户。


Install this script?
// ==UserScript==
// @name         v2ex 快速屏蔽用户和帖子
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  在用户评论区域添加一个 block 按钮,不用点进用户主页,点击即可 block 用户。
// @author       3989364
// @match        *://*.v2ex.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=v2ex.com
// @grant        none
// @license      MIT
// @note         0.3 实现屏蔽帖子功能
// @note         0.2 扩展 v2ex.com 的域名匹配规则
// ==/UserScript==
// TODO:
// 1. 帖子外面加个屏蔽用户按钮
// 2. 直接在用户头像链接里面取 userID
// 3. 判断用户是否登录,如果没登录直接跳过所有功能
const BASE_URL = window.location.origin;
if (!BASE_URL.includes("v2ex.com")) {
throw Error("This script only works at v2ex.com, " + BASE_URL);
}
class OnceCode {
/**
* onceCode 类似验证码,目测用一次就会失效;目前获取 once code 的方式是请求设置页面提取出 once code
*/
static async getOnceCode() {
const resp = await fetch(`/settings/block`);
const text = await resp.text();
const html = document.createElement("html");
html.innerHTML = text;
const fn = html
.querySelector('input[value="一键清除所有忽略主题"]')
.onclick.toString();
return this.parseOnceCode(fn);
}
static parseOnceCodeURL(text) {
return text.match("location.href ?= ?'(.+)'")[1];
}
static parseOnceCode(text) {
return text.match(/once=(\d+)/)[1];
}
}
class User {
async fetchUserPage(username) {
const resp = await fetch(`/member/${username}`);
return await resp.text();
}
parseBlockURL(page) {
const html = document.createElement("html");
html.innerHTML = page;
const fn = html.querySelector('input[value="Block"]').onclick;
if (fn) {
// /block/xxxx?once=19604
return OnceCode.parseOnceCodeURL(fn.toString());
}
return null;
}
async blockUser(username) {
const page = await this.fetchUserPage(username);
const url = await this.parseBlockURL(page);
if (url) {
// just dont redirect
try {
await fetch(url, {
redirect: "error",
});
} catch {}
}
}
hideUserAllReply(username) {
if (!username) {
return;
}
document.querySelectorAll("#Main .cell").forEach((cell) => {
const u = cell.querySelector("strong> a")?.textContent;
if (u === username) {
cell.remove();
}
});
}
}
class Topic {
async ignoreTopic(topicId) {
const onceCode = await OnceCode.getOnceCode();
try {
await fetch(`/ignore/topic/${topicId}?once=${onceCode}`, {
redirect: "error",
});
} catch {}
}
}
function createBlockButton(
text = "block",
className = "thank",
styleText = ""
) {
const blockButton = document.createElement("a");
blockButton.textContent = text;
blockButton.className = className;
blockButton.style.marginLeft = "0.5rem";
styleText && (blockButton.style = styleText);
blockButton.href = "#;";
return blockButton;
}
function initUserBlockFunction() {
function addChildInThankArea(node, thankArea) {
thankArea.appendChild(node, thankArea);
}
const user = new User();
document.querySelectorAll(".thank_area").forEach((thankArea) => {
const blockButton = createBlockButton();
addChildInThankArea(blockButton, thankArea);
blockButton.addEventListener("click", async function (event) {
event.preventDefault();
const wrapper = thankArea.parentNode.parentNode;
const username = wrapper.querySelector("strong > a").textContent;
if (username && confirm(`确认要屏蔽 ${username} ?`)) {
await user.blockUser(username);
user.hideUserAllReply(username);
}
});
});
}
function initTopicBlockFunction() {
const topic = new Topic();
document
.querySelectorAll('#Main .cell.item td[valign="middle"]')
.forEach((cell) => {
const titleElement = cell.querySelector(".item_title > a");
const infoElement = cell.querySelector(".topic_info");
if (!titleElement) {
return;
}
const topicId = titleElement.href.match(/\/t\/(\d+)/)[1];
const ignoreButton = createBlockButton(
"忽略",
"title",
"color: #ccc; float: right;"
);
infoElement.appendChild(ignoreButton);
ignoreButton.addEventListener("click", async function () {
if (confirm("确定不想再看到这个主题?")) {
// debugger
await topic.ignoreTopic(topicId);
// delete this topic
let element = cell.parentElement;
const body = document.body;
// 向上找到 className = "cell item" 的元素即认为找到了帖子元素
while (element.className !== "cell item" && element !== body) {
element = element.parentElement;
}
if (element !== body) {
element.remove();
} else {
throw Error("Can't find topic cell");
}
}
});
});
}
(function () {
"use strict";
if (location.href.match(/\/t\/\d+/)) {
console.log("Init user block function");
initUserBlockFunction();
}
initTopicBlockFunction();
})();