您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
能按照用户和关键词屏蔽不想看的贴,屏蔽低于指定等级用户,也可以给用户打标签帮助自己记忆此人的特点,屏蔽置顶直播
// ==UserScript== // @name 贴吧助手 // @namespace 蒋晓楠 // @version 20240307 // @description 能按照用户和关键词屏蔽不想看的贴,屏蔽低于指定等级用户,也可以给用户打标签帮助自己记忆此人的特点,屏蔽置顶直播 // @author 蒋晓楠 // @license MIT // @match https://tieba.baidu.com/p/* // @match https://tieba.baidu.com/f?*kw=* // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_notification // @grant GM_addStyle // @grant GM_addElement // @grant GM_registerMenuCommand // ==/UserScript== //执行间隔(秒) let Interval = 1; //过期数据清理延时(秒) let ClearExpireDataDelay = 30; //过期数据清理几率百分比,范围0-100 let ClearExpireDataPercent = 2; //以下不懂的不要修改 //页面类型 const PAGE_TYPE_LIST = 0;//列表 const PAGE_TYPE_POST = 1;//帖子 let PageType = location.pathname === "/f" ? PAGE_TYPE_LIST : PAGE_TYPE_POST; //获取数据 function GetData() { return GM_getValue("List", { User: [], UserTime: {}, Keyword: { Title: {}, Content: {} }, UserTag: {} }); } //保存数据 function SaveData(Data) { GM_setValue("List", Data); } //修改配置 function SetConfig(Key, Value) { GM_setValue("Config:" + Key, Value); } //获取配置 function GetConfig(Key, Default) { return GM_getValue("Config:" + Key, Default); } //删除配置 function RemoveConfig(Key) { GM_deleteValue("Config:" + Key); } //提醒 function Tips(Message) { GM_notification({ title: "贴吧助手", text: Message, timeout: 3000 }); } //初始化样式 function InitCSS() { GM_addStyle(`.JXNButton{border:1px solid;margin-right:10px}.BlockUser{width:90%}.JXNInput{width:50px;}.JXNTag{border:1px solid black;margin:5px 1px;display:inline-block;min-width:50px;}.JXNTagBox{width:90px;}.JXNHolder{width:250px;position:absolute;left:10px;z-index:1;top:135px}.PostListBlockUser{position:absolute;right:0;margin-right:0;z-index:1}`); } //获取有效天数 function GetExpireDay() { return GetConfig("ExpireDay", 180); } //设置有效天数 function SetExpireDay(Value) { SetConfig("ExpireDay", parseInt(Value)); } //获取当前时间 function GetNowTime() { let Now = new Date(); return parseInt(Now.getFullYear().toString() + (Now.getMonth() + 1).toString().padStart(2, "0") + Now.getDate().toString().padStart(2, "0")); } //获取新的过期时间 function GetNewExpiredDay() { let Now = new Date(); Now.setDate(Now.getDate() + GetExpireDay()); return parseInt(Now.getFullYear().toString() + (Now.getMonth() + 1).toString().padStart(2, "0") + Now.getDate().toString().padStart(2, "0")); } //屏蔽用户存在 function BlockUserIsExist(Id) { return GetData().User.indexOf(Id) > -1; } //添加屏蔽用户 function AddBlockUser(Id) { let Data = GetData(); Data.User.push(Id); Data.UserTime[Id] = GetNewExpiredDay(); SaveData(Data); } //移除屏蔽用户 function RemoveBlockUser(Id) { let Data = GetData(); let Index = Data.User.indexOf(Id); if (Index > -1) { Data.User.splice(Index, 1); delete Data.UserTime[Id]; SaveData(Data); } } //获取当前关键词类型 function GetNowKeyWordType() { return parseInt(document.querySelector(".JXNMatchType").value); } //获取当前关键词模式 function GetNowKeyWordMode() { return parseInt(document.querySelector(".JXNMatchMode").value); } //屏蔽关键词存在 function BlockKeywordIsExist(Type, Value) { return GetData().Keyword[Type === 0 ? "Title" : "Content"][Value] !== undefined; } //添加屏蔽关键词 function AddBlockKeyword(Type, Mode, Value) { let Data = GetData(); Data.Keyword[Type === 0 ? "Title" : "Content"][Value] = { Mode: Mode, Time: GetNewExpiredDay() }; SaveData(Data); } //移除屏蔽关键词 function RemoveBlockKeyword(Type, Value) { let Data = GetData(); let KeyWord = Data.Keyword; let Key = Type === 0 ? "Title" : "Content"; if (KeyWord[Key][Value] !== undefined) { delete Data.Keyword[Key][Value]; SaveData(Data); } } //获取用户标签 function GetUserTags(UserId) { let Data = GetData(); if (Data.UserTag[UserId] === undefined) { return {}; } else { return Data.UserTag[UserId]; } } //用户添加标签 function UserAddTag(UserId, Tag) { let Data = GetData(); //初始化该用户的标签 if (Data.UserTag[UserId] === undefined) { Data.UserTag[UserId] = {}; } Data.UserTag[UserId][Tag] = GetNewExpiredDay(); SaveData(Data); } //用户移除标签 function UserRemoveTag(UserId, Tag) { let Data = GetData(); let UserTags = Data.UserTag[UserId]; if (UserTags !== undefined && UserTags[Tag] !== undefined) { Object.getOwnPropertyNames(UserTags).length === 1 ? delete Data.UserTag[UserId] : delete UserTags[Tag]; SaveData(Data); } } //帖子列表的额外屏蔽 function PostListExtraBlock() { //置顶直播 if (GetConfig("BlockTopLive") === true && document.querySelector("[id^=pagelet_live]") !== null) { document.querySelector("[id^=pagelet_live]").remove(); } //关闭会员红贴 if (GetConfig("BanMemberPost", true) && document.querySelector(".member_thread_title_frs") !== null) { document.querySelectorAll(".member_thread_title_frs").forEach((TitleHolder) => { TitleHolder.classList.remove("member_thread_title_frs"); }); } } //内容过滤 function ContentFilter(Content) { Content = Content.trim(); if (Content !== "") { //过滤非中文/英文/数字 Content = Content.replace(/[^\da-zA-Z\u4e00-\u9fa5]/g, ""); } return Content; } //检测标题关键词 function CheckKeywordTitle(Title) { let TitleKeyWords = GetData().Keyword.Title; for (const Keyword in TitleKeyWords) { if (TitleKeyWords[Keyword].Mode === 0) { if (Title.indexOf(Keyword) > -1) { return Keyword; } } else if (Keyword === Title) { return Keyword; } } return false; } //检测内容关键词 function CheckKeywordContent(Content) { let ContentWords = GetData().Keyword.Content; for (const Keyword in ContentWords) { if (ContentWords[Keyword].Mode === 0) { if (Content.indexOf(Keyword) > -1) { return Keyword; } } else if (Keyword === Content) { return Keyword; } } return false; } //帖子列表初始化 function InitPostList() { let StartTime = (new Date()).getTime(); let Posts = document.querySelectorAll(".j_thread_list:not(.JXNProcessed)"); let Number = Posts.length; if (Number > 0) { let BlockAlphaNumberTitle = GetConfig("BlockAlphaNumberTitle", false), EnableContentFilter = GetConfig("ContentFilter", false); for (let i = 0; i < Posts.length; i++) { let Post = Posts[i]; let User = Post.querySelector(".tb_icon_author"); if (User === null) { //添加已处理标记 Post.classList.add("JXNProcessed"); } else { let DisplayName = Post.querySelector(".frs-author-name").textContent; let UserId = JSON.parse(Post.querySelector(".tb_icon_author").getAttribute("data-field")).user_id; let Title = Post.querySelector(".threadlist_title>a").getAttribute("title"); //屏蔽纯字母数字标题 if (BlockAlphaNumberTitle && /^[0-9a-zA-Z]*$/.test(Title)) { console.log(`${DisplayName}(${UserId})的帖子[${Title}]被屏蔽因为标题为纯字母数字`); Post.remove(); } //按用户ID屏蔽 else if (BlockUserIsExist(UserId)) { console.log(`${DisplayName}(${UserId})的帖子[${Title}]被屏蔽因为在用户屏蔽列表内`); Post.remove(); } else { //按关键词屏蔽 let Result = CheckKeywordTitle(Title); if (Result === false) { let Content = Post.querySelector(".threadlist_abs_onlyline"); if (Content !== null) { Content = Content.textContent; if (EnableContentFilter) Content = ContentFilter(Content); if (Content !== "") { Result = CheckKeywordContent(Content); if (Result !== false) { console.log(`${DisplayName}(${UserId})的帖子[${Title}]被屏蔽因为内容触发关键词[${Result}]`); Post.remove(); continue; } } } //添加屏蔽按钮 let BlockButton = document.createElement("button"); BlockButton.classList.add("JXNButton"); BlockButton.classList.add("PostListBlockUser"); BlockButton.textContent = "屏蔽用户"; BlockButton.onclick = () => { if (BlockUserIsExist(UserId)) { Tips("此用户已存在"); } else { AddBlockUser(UserId) //添加取消屏蔽按钮 let CancelButton = document.createElement("button"); CancelButton.classList.add("JXNButton"); CancelButton.classList.add("PostListBlockUser"); CancelButton.textContent = "取消屏蔽"; CancelButton.onclick = () => { if (BlockUserIsExist(UserId)) { RemoveBlockUser(UserId); CancelButton.remove(); Tips("已取消对此用户的屏蔽"); } else { Tips("此用户不存在"); } } Post.prepend(CancelButton); Tips("添加成功,刷新后将自动屏蔽此用户的发帖与回复"); BlockButton.remove(); } } Post.prepend(BlockButton); Post.classList.add("JXNProcessed"); } else { console.log(`${DisplayName}(${UserId})的帖子[${Title}]被屏蔽因为标题触发关键词[${Result}]`); Post.remove(); } } } } //额外屏蔽 PostListExtraBlock(); console.log("屏蔽用时:" + ((new Date()).getTime() - StartTime) + "毫秒"); } } //初始化用户面板 function InitUserPanel(UserId, UserBlock) { setTimeout(() => { let BlockButton = GM_addElement(UserBlock, "button", { class: "JXNButton BlockUser", textContent: "屏蔽" }); BlockButton.onclick = () => { if (BlockUserIsExist(UserId)) { Tips("此用户已存在"); } else { AddBlockUser(UserId) //添加取消屏蔽按钮 let CancelButton = GM_addElement(UserBlock, "button", { textContent: "取消屏蔽", class: "JXNButton BlockUser" }); CancelButton.onclick = () => { if (BlockUserIsExist(UserId)) { RemoveBlockUser(UserId); Tips("已取消对此用户的屏蔽"); } else { Tips("此用户不存在"); } } Tips("添加成功,刷新后将自动屏蔽此用户的发帖与回复"); BlockButton.remove(); } } let Tags = GetUserTags(UserId); for (const Tag in Tags) { let NowTag = GM_addElement(UserBlock, "button", { textContent: Tag, class: "JXNTag", title: "点击删除此标签" }); NowTag.onclick = () => { UserRemoveTag(UserId, Tag); Tips("删除完成"); NowTag.remove(); } } //创建添加标签框 let TagBox = GM_addElement(UserBlock, "input", { type: "text", class: "JXNInput JXNTagBox" }); let Button = GM_addElement(UserBlock, "button", { textContent: "添加", class: "JXNButton JXNTagRemove", title: "添加标签" }); Button.onclick = () => { let Tag = TagBox.value; if (Tag !== "") { UserAddTag(UserId, Tag); Tips("添加完成,刷新后会正确显示"); } } }, Interval); } //帖子内初始化 function InitPosts() { let StartTime = (new Date()).getTime(); let Posts = document.querySelectorAll(".l_post:not([data-index]):not(.JXNProcessed)"); let Number = Posts.length; if (Number > 0) { let BlockLevelUserValue = GetConfig("BlockLevelUser", 2), EnableContentFilter = GetConfig("ContentFilter", false); let ContentResult; for (let i = 0; i < Number; i++) { let Post = Posts[i]; //按等级屏蔽用户 if (BlockLevelUserValue > 18) { Post.remove(); continue; } let UserBlock = Post.querySelector(".p_author"); let DisplayName = UserBlock.querySelector(".p_author_name").textContent; let UserId = JSON.parse(Post.querySelector(".d_name").getAttribute("data-field")).user_id; if (BlockLevelUserValue > 1 && parseInt(UserBlock.querySelector(".d_badge_lv").textContent) < BlockLevelUserValue) { console.log(`${DisplayName}(${UserId})的楼层被屏蔽因为等级低于${BlockLevelUserValue}`); Post.remove(); continue; } if (BlockUserIsExist(UserId)) { console.log(`${DisplayName}(${UserId})的楼层被屏蔽因为在用户屏蔽列表内`); Post.remove(); } else { let Content = Post.querySelector(".d_post_content").textContent; if (EnableContentFilter) Content = ContentFilter(Content); //检测内容关键词 if (Content.length > 0 && (ContentResult = CheckKeywordContent(Content)) !== false) { console.log(`${DisplayName}(${UserId})的楼层被屏蔽因为内容触发关键词[${ContentResult}]`); Post.remove(); continue; } //初始化用户面板 InitUserPanel(UserId, UserBlock); //添加已处理标记 Post.classList.add("JXNProcessed"); } } console.log("屏蔽用时:" + ((new Date()).getTime() - StartTime) + "毫秒"); } } //通过地址初始化相应功能 function InitFunctionByURL() { let Function = PageType === PAGE_TYPE_LIST ? InitPostList : InitPosts; //初始执行 Function(); //定期执行 setInterval(() => { Function(); }, Interval * 1000); } //初始化操作界面 function InitUI() { //脚本菜单 //屏蔽置顶直播 GM_registerMenuCommand((GetConfig("BlockTopLive", false) === true ? "✅" : "❎") + "屏蔽置顶直播", () => { SetConfig("BlockTopLive", GetConfig("BlockTopLive", false) !== true); }); //屏蔽纯字母数字标题 GM_registerMenuCommand((GetConfig("BlockAlphaNumberTitle", false) === true ? "✅" : "❎") + "屏蔽纯字母数字标题", () => { SetConfig("BlockAlphaNumberTitle", GetConfig("BlockAlphaNumberTitle", false) !== true); }); //关闭会员红贴 GM_registerMenuCommand((GetConfig("BanMemberPost", true) === true ? "✅" : "❎") + "关闭会员红贴", () => { SetConfig("BanMemberPost", GetConfig("BanMemberPost", false) !== true); }); //内容预过滤 GM_registerMenuCommand((GetConfig("ContentFilter", false) === true ? "✅" : "❎") + "内容预过滤", () => { SetConfig("ContentFilter", GetConfig("ContentFilter", false) !== true); }); //导出数据 GM_registerMenuCommand("导出数据", () => { let ExportJson = document.createElement("a"); ExportJson.download = "贴吧助手.json"; ExportJson.href = URL.createObjectURL(new Blob([JSON.stringify(GetData())])); ExportJson.click(); }); //页面菜单 //油猴脚本不提供在指定元素后面创建的api let Holder = document.createElement("div"); Holder.classList.add("JXNHolder"); let PositionElement = document.getElementById("head"); PositionElement.after(Holder); //有效天数 GM_addElement(Holder, "span", { textContent: "有效天数" }); let Expire = GM_addElement(Holder, "input", { type: "number", min: 1, step: 1, value: GetExpireDay(), class: "JXNInput" }); GM_addElement(Holder, "br", {}); if (PageType === PAGE_TYPE_POST) { //按等级屏蔽用户 GM_addElement(Holder, "span", { textContent: "屏蔽低于此等级用户" }); let BlockLevelUser = GM_addElement(Holder, "input", { type: "number", value: GetConfig("BlockLevelUser", 2), min: 1, max: 19, step: 1 }); BlockLevelUser.onchange = () => { SetConfig("BlockLevelUser", this.value); } GM_addElement(Holder, "br", {}); } //关键词 GM_addElement(Holder, "span", { textContent: "关键词" }); let Keyword = GM_addElement(Holder, "input", { type: "text", }); GM_addElement(Holder, "br", {}); //匹配类型 GM_addElement(Holder, "span", { textContent: "匹配类型" }); let MatchType = GM_addElement(Holder, "select", { class: "JXNMatchType" }); MatchType.add(new Option("标题", 0)); MatchType.add(new Option("内容", 1)); MatchType.value = GetConfig("MatchType", 0); //匹配模式 GM_addElement(Holder, "span", { textContent: "匹配模式" }); let MatchMode = GM_addElement(Holder, "select", { class: "JXNMatchMode" }); MatchMode.add(new Option("部分", 0)); MatchMode.add(new Option("全部", 1)); MatchMode.value = GetConfig("MatchMode", 0); GM_addElement(Holder, "br", {}); let AddKeyword = GM_addElement(Holder, "button", { textContent: "添加", class: "JXNButton" }); let RemoveKeyword = GM_addElement(Holder, "button", { textContent: "删除", class: "JXNButton" }); //导入选择块 let ImportFile = GM_addElement(Holder, "input", { type: "file", hidden: true, accept: "application/json", value: false }); //导入数据 let ImportList = GM_addElement(Holder, "button", { textContent: "导入数据", class: "JXNButton" }); //绑定事件 //有效天数 Expire.onchange = () => { SetExpireDay(Expire.value); } //匹配类型 MatchType.onchange = () => { SetConfig("MatchType", MatchType.value); } //匹配模式 MatchMode.onchange = () => { SetConfig("MatchMode", MatchMode.value); } //添加删除关键词 AddKeyword.onclick = () => { let Value = Keyword.value; if (Value !== "") { if (BlockKeywordIsExist(GetNowKeyWordType(), Value)) { Tips("此关键词已存在"); } else { AddBlockKeyword(GetNowKeyWordType(), GetNowKeyWordMode(), Value); Tips("添加成功"); } } }; RemoveKeyword.onclick = () => { let Value = Keyword.value; if (Value !== "") { if (BlockKeywordIsExist(GetNowKeyWordType(), Value)) { RemoveBlockKeyword(GetNowKeyWordType(), Value); Tips("删除成功"); } else { Tips("此关键词不存在"); } } } //导入数据 ImportFile.onchange = () => { if (ImportFile.files.length > 0) { let JsonList = ImportFile.files[0]; let Reader = new FileReader(); Reader.onload = (Result) => { try { SaveData(JSON.parse(Result.target.result)); Tips("导入完成"); } catch (e) { alert("读取的文件格式不正确"); } }; Reader.readAsText(JsonList); } } ImportList.onclick = () => { ImportFile.click(); } } //清理过期数据 function ClearExpireData() { //浏览帖子达到一定时间才去执行清理 setTimeout(() => { if (1 + Math.round(Math.random() * 99) <= ClearExpireDataPercent) { let NowDate = GetNowTime(); let Data = GetData(); //清理用户 for (let i = 0; i < Data.User.length; i++) { let Id = Data.User[i]; if (Data.UserTime[Id] < NowDate) { console.log(`删除过期用户[${Id}]因为它的时间${Data.UserTime[Id]}]小于当前时间`); RemoveBlockUser(Id); } } //清理标签 let UserTag = Data.UserTag; for (const UserId in UserTag) { let Tags = UserTag[UserId]; for (const Tag in Tags) { if (Tags[Tag] < NowDate) { console.log(`删除过期用户[${UserId}]的标签[${Tag}]因为它的时间${Tags[Tag]}小于当前时间`); UserRemoveTag(UserId, Tag); } } } //清理关键词 let KeyWord = Data.Keyword; for (const BaseKey in KeyWord) { let Value = KeyWord[BaseKey]; for (const Key in Value) { let TheKeyWord = Value[Key]; if (TheKeyWord.Time < NowDate) { console.log(`删除过期${BaseKey === "Title" ? "标题" : "内容"}关键词[${Key}]因为它的时间[${TheKeyWord.Time}]小于当前时间`); RemoveBlockKeyword(BaseKey === "Title" ? 0 : 1, Key); } } } } }, ClearExpireDataDelay * 1000); } //显示信息 function DisplayInfo() { setTimeout(() => { let Data = GetData(); console.log("完整数据", Data); console.log("屏蔽数量:关键词-标题(" + Object.keys(Data.Keyword.Title).length + "),关键词-内容(" + Object.keys(Data.Keyword.Content).length + "),用户(" + Data.User.length + ")"); console.log("当前时间:" + GetNowTime()); }, 1000); } //运行 function Run() { InitCSS(); InitUI(); ClearExpireData(); InitFunctionByURL(); DisplayInfo(); } Run();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址