// ==UserScript==
// @name 知乎回答删除
// @namespace 蒋晓楠
// @version 20240513
// @description 删除问题指定回答,便于降低cpu和内存占用,也可以过滤不想看的回答
// @author 蒋晓楠
// @license MIT
// @match https://www.zhihu.com/question/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @grant GM_addElement
// @grant GM_registerMenuCommand
// ==/UserScript==
//检测间隔秒数
let Interval = 1;
//清理几率,1-100
let ClearPercent = 5;
//清理延时,秒
let ClearDelay = 30;
//取消删除按钮持续时间,秒
let CancelButtonDuration = 30;
//以下为逻辑代码,不懂的不要修改
//修改配置
function SetConfig(Key, Value) {
GM_setValue("Config:" + Key, Value);
}
//获取配置
function GetConfig(Key, Default) {
return GM_getValue("Config:" + Key, Default);
}
//获取当前问题id
function GetNowQuestionId() {
return parseInt(location.pathname.substring(10));
}
//获取当前时间
function GetNowTime() {
return parseInt((new Date().getTime() / 86400000).toString());
}
//保存数据
function SaveData(Data) {
GM_setValue("Data", Data);
}
//获取数据
function GetData() {
return GM_getValue("Data", {});
}
//检测指定问题的指定回答是否被标记为删除
function AnswerIsRemove(QuestionId, AnswerId) {
let Data = GetData();
return !(Data[QuestionId] === undefined || Data[QuestionId][AnswerId] === undefined);
}
//给指定问题添加回答标记
function QuestionAddAnswer(QuestionId, AnswerId) {
let Data = GetData();
if (Data[QuestionId] === undefined) {
Data[QuestionId] = {}
}
Data[QuestionId][AnswerId] = GetNowTime() + GetConfig("ExpireDay", 180);
SaveData(Data);
}
//删除指定问题的指定回答标记
function QuestionRemoveAnswer(QuestionId, AnswerId) {
let Data = GetData();
if (Data[QuestionId] !== undefined && Data[QuestionId][AnswerId] !== undefined) {
delete Data[QuestionId][AnswerId];
SaveData(Data);
}
}
//清理回答数据
function ClearAnswerData() {
let Data = GetData();
let NowDay = GetNowTime();
let ClearCount = 0;
for (const QuestionId in Data) {
let Item = Data[QuestionId]
for (const Key in Item) {
if (Item[Key] < NowDay) {
console.log("清理" + QuestionId + "的" + Key);
delete Item[Key];
ClearCount++;
}
}
if (Object.keys(Item).length === 0) {
delete Data[QuestionId];
} else {
Data[QuestionId] = Item;
}
}
SaveData(Data);
if (ClearCount > 0) {
console.log("已清理" + ClearCount + "个过期的回答");
}
}
//从页面删除指定回答
function PageRemoveAnswer(HolderBlock, Type, AnswerId) {
switch (Type) {
case 0://一般回答
console.log("删除指定回答" + AnswerId);
HolderBlock.textContent = "此回答已被删除";
break;
case 1://已删除的
console.log("屏蔽已删除回答" + AnswerId);
HolderBlock.style.display = "none";
break;
case 2://盐选
console.log("屏蔽严选回答" + AnswerId);
HolderBlock.style.display = "none";
break;
}
//添加已删除标记
HolderBlock.classList.add("JXNRemoved");
//延时删除,避免崩溃
setTimeout(function () {
HolderBlock.remove();
}, CancelButtonDuration * 1000);
}
//执行屏蔽功能
function DoBlock() {
let QuestionId = GetNowQuestionId();
//屏蔽数量统计变量
let BlockElement = document.querySelector(".JXNRemoveAnswerNumber"), AutoScroll = GetConfig("AutoScroll", false)
setInterval(function () {
let Items = document.querySelectorAll(".List-item:not(.JXNProcessed)");
if (Items.length > 0) {
Items.forEach(function (Item) {
let Answer = Item.querySelector(".AnswerItem");
if (Answer !== null) {
let AnswerId = JSON.parse(Answer.getAttribute("data-zop")).itemId;
if (AnswerIsRemove(QuestionId, AnswerId)) {
PageRemoveAnswer(Item, 1, AnswerId);
//增加屏蔽数量
BlockElement.textContent = (parseInt(BlockElement.textContent) + 1).toString();
} else {
//屏蔽盐选
if (GetConfig("BanYanxuan", true) && Item.querySelector(".KfeCollection-AnswerTopCard-Container") !== null) {
PageRemoveAnswer(Item, 2, AnswerId);
} else {
//添加上方删除按钮
let ButtonTop = GM_addElement(Item.querySelector(".ContentItem-meta"), "button", {
class: "JXNButton",
textContent: "删除这个回答"
});
ButtonTop.onclick = function () {
PageRemoveAnswer(Item, 0, AnswerId);
//添加取消删除按钮
let CancelRemoveButton = GM_addElement(Item, "button", {
class: "JXNButton",
textContent: "取消删除"
});
CancelRemoveButton.onclick = function () {
QuestionRemoveAnswer(QuestionId, AnswerId);
Item.textContent = "此回答在刷新页面后恢复";
};
QuestionAddAnswer(QuestionId, AnswerId);
}
//添加下方删除按钮
let ButtonBottom = GM_addElement(Item.querySelector(".ContentItem-time"), "button", {
class: "JXNButton",
textContent: "删除这个回答"
});
ButtonBottom.onclick = function () {
PageRemoveAnswer(Item, 0, AnswerId);
//添加取消删除按钮
let CancelRemoveButton = GM_addElement(Item, "button", {
class: "JXNButton",
textContent: "取消删除"
});
CancelRemoveButton.onclick = function () {
QuestionRemoveAnswer(QuestionId, AnswerId);
Item.textContent = "此回答在刷新页面后恢复";
};
QuestionAddAnswer(QuestionId, AnswerId);
}
}
}
}
//为回答添加已处理标记
Item.classList.add("JXNProcessed");
});
} else if (AutoScroll && document.querySelector(".List-item:not(.JXNRemoved)") === null && document.querySelector(".QuestionAnswers-answerButton") === null) {
console.log("开始滚动");
window.scrollBy(0, 1);
}
}, Interval * 1000);
}
//初始化界面
function InitUI() {
//初始化样式
GM_addStyle(`.JXNButton{border:1px solid black;padding:5px;margin-top:10px;width:100%;}.JXNButton:hover{background-color:gray;color:white;}.JXNRemoveAnswer{background-color:white;padding:10px;}.JXNInput{width:100px}`);
let Holder = document.createElement("div");
Holder.classList.add("JXNRemoveAnswer");
document.querySelector(".Question-sideColumn").prepend(Holder);
//禁止知乎盐选
let BanYanxuan = GM_addElement(Holder, "input", {type: "checkbox", value: "true", title: "会自动删除盐选的回答"});
GM_addElement(Holder, "span", {textContent: "屏蔽知乎盐选"});
BanYanxuan.checked = GetConfig("BanYanxuan", true);
BanYanxuan.onclick = function () {
SetConfig("BanYanxuan", BanYanxuan.checked);
};
//自动滚动
let AutoScroll = GM_addElement(Holder, "input", {
type: "checkbox",
value: "true",
title: "自动滚动删除的回答直到有新的回答或展示全部回答"
});
GM_addElement(Holder, "span", {textContent: "自动滚动回答"});
AutoScroll.checked = GetConfig("AutoScroll", false);
AutoScroll.onclick = function () {
SetConfig("AutoScroll", AutoScroll.checked);
};
//有效期调整
let Expire = GM_addElement(Holder, "p", {textContent: "删除有效期"});
let ExpireValue = GM_addElement(Expire, "input", {
type: "number",
min: 1,
class: "JXNInput",
value: GetConfig("ExpireDay", 180)
});
GM_addElement(Expire, "span", {textContent: "天"});
ExpireValue.onchange = function () {
SetConfig("ExpireDay", parseInt(ExpireValue.value));
}
//屏蔽个数
let BanNumberHolder = GM_addElement(Holder, "p", {textContent: "已为你屏蔽"});
GM_addElement(BanNumberHolder, "span", {class: "JXNRemoveAnswerNumber", textContent: "0"});
BanNumberHolder.append("个回答");
//清理数据
GM_registerMenuCommand("清理数据", () => {
ClearAnswerData();
});
GM_registerMenuCommand("清理全部数据", () => {
if (confirm("将会清除所有数据,无论是否过期,是否确定?")) {
GM_setValue("Data", {});
alert("清理完成");
}
});
}
//显示信息
function DisplayInfo() {
setTimeout(function () {
console.log("时间:" + GetNowTime(), "问题Id:" + GetNowQuestionId() + " 所有数据:", GetData());
}, Interval * 1000);
}
//清理过期数据
function ClearExpiredData() {
setTimeout(() => {
if (1 + Math.round(Math.random() * 99) <= ClearPercent) {
console.log("执行过期数据清理");
ClearAnswerData();
}
//删除取消的配置
GM_deleteValue("Config:CancelButtonDuration")
}, ClearDelay * 1000);
}
//运行
function Run() {
InitUI();
DoBlock();
DisplayInfo();
ClearExpiredData();
}
Run();