知乎回答删除

删除问题指定回答,便于降低cpu和内存占用,也可以过滤不想看的回答

// ==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();