您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
屏蔽黑名單內頻道在其他影片下的留言,可以查看和移除黑名單內的頻道。
当前为
// ==UserScript== // @name Youtube留言黑名單 // @namespace http://tampermonkey.net/ // @version 1.6.0 // @description 屏蔽黑名單內頻道在其他影片下的留言,可以查看和移除黑名單內的頻道。 // @author Microdust // @match https://*.youtube.com/* // @icon https://www.google.com/s2/favicons?domain=youtube.com // @grant GM_getResourceText // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js // @license MIT // ==/UserScript== (function() { 'use strict'; //以下設定將在重載網頁後生效 //是否刪除在黑名單內的留言true=刪除/false=不刪除留言但用deleteText裡的文字覆蓋 const deleteComment = true; //不刪除留言時用deleteText裡的文字覆蓋 const deleteText = "留言被屏蔽"; //#黑名單-導出的檔名(不可為空) const exportName = "黑名單"; //#黑名單-佔整個畫面的寬度比例 const blacklistWidth = "50%"; //#黑名單-名字顯示最長字數(超過此限制將會以'...'省略,數字為負將不限制) const nameLength = -1; //留言最小字數過濾,小於0則不限制(需小於留言最大字數) const commentMinLength = 0; //留言最大字數過濾,小於0則不限制(需大於留言最小字數) const commentMaxLength = 0; //關鍵字過濾 const banWords = [ // "將要過濾的關鍵字填入雙引號中","刪除註解以啟用過濾","可自由增減關鍵字" ]; // //以下為範例: //--------------------------------- //- const banWords=[ //- "關","鍵字","範例" //- ]; //--------------------------------- // let btnSetting; let prelink; let link; let thisPath; let text; let viewURL; let workArea = true; let list = []; // let checkedComment; let path; let comment; let commentUserId; let commentUserName; let commentValue; let btnBlackList; let precomment = []; // let threadPath; let checkedReply; let replyPath; let reply; let replyUserId; let replyUserName; let replyValue; let replyBtn; let replyCount = []; let replyBan = []; let noReply = []; if (GM_getValue("list")) list = blacklist("init"); //list.length=0; //blacklist("save"); setInterval(function() { link = window.location.href; if (prelink != link) { prelink = window.location.href; workArea = true; checkedComment = 0; viewURL = false; noReply.length = 0; } if (workArea) workArea = fnNameListCheck(); }, 1000); function fnNameListCheck() { let pathName = window.location.pathname.split('/'); if (!viewTypeFn(pathName, window.location.search.toString())) return false; if (checkedComment) btnSettingFn(); while (getComment()) { defData(); checkedComment++; } getReplyExist(); return true; } function viewTypeFn(viewType, val) { if (viewType[1] == "watch") viewURL = "ytd-watch-flexy/div[5]/div[1]/div/div[2]"; if (viewType[1] == "post") viewURL = "/ytd-browse/ytd-two-column-browse-results-renderer/div[1]/ytd-section-list-renderer/div[2]"; if (viewType[3] == "community" && val != "") viewURL = "/ytd-browse/ytd-two-column-browse-results-renderer/div[1]/ytd-section-list-renderer/div[2]"; threadPath = "/html/body/ytd-app/div[1]/ytd-page-manager/" + viewURL + "/ytd-comments/ytd-item-section-renderer/div[3]"; return viewURL; } function btnSettingFn() { btnSetting = getElementByXpath("/html/body/ytd-app/div[1]/ytd-page-manager/" + viewURL + "/ytd-comments/ytd-item-section-renderer/div[1]/ytd-comments-header-renderer/div[5]/ytd-comment-simplebox-renderer/yt-img-shadow/img"); //console.log(btnSetting); if (!btnSetting) return; var oBlackList = document.createElement("div"); for (let i = 0; i < list.length; i++) { var banner = document.createElement('button'); banner.onclick = function() { let id = list[i].id; let name = list[i].name; wordPure(name); Swal.fire({ title: '確定要將 ' + name + ' 從黑名單移除嗎?', text: '頻道ID(' + id + ')', icon: 'warning', showCancelButton: true, confirmButtonColor: '#3085d6', cancelButtonColor: '#d33', confirmButtonText: '從黑名單移除', cancelButtonText: '取消' }).then((result) => { if (result.isConfirmed) { Swal.fire( '已將 ' + name + ' 從黑名單移除', '頻道ID(' + id + ')', 'info' ).then(() => { list.splice(banlistSearch(id) - 1, 1); //list.length = 0; blacklist("save"); }) } }) } banner.innerText = wordPure(list[i].name) + " (" + list[i].id + ")"; let br = document.createElement('br'); oBlackList.append(banner); oBlackList.append(br); } if (list.length == 0) { banner = document.createElement('p'); banner.innerText = "沒有任何人被你列入黑名單"; oBlackList.append(banner); } btnSetting.onclick = function() { Swal.fire({ title: '黑名單', width: blacklistWidth, html: this.appendChild(oBlackList), confirmButtonText: '確認', showDenyButton: true, denyButtonText: '導出/導入', backdrop: 'rgba(0,0,0,0.6)' }).then((result) => { if (result.isDenied) { Swal.fire({ title: '黑名單(導出/導入)', icon: 'question', confirmButtonText: '導入', showDenyButton: true, denyButtonText: '導出', backdrop: 'rgba(0,0,0,0.6)' }).then((result) => { if (result.isConfirmed) { importFn(); } else if (result.isDenied) { exportFn(GM_getValue("list"), exportName + ".json"); } }) } }) } } function getReplyExist() { for (let i = 1; i < checkedComment + 1; i++) { if (noReply[i]) continue; let oreplyCountMain = getElementByXpath(threadPath + "/ytd-comment-thread-renderer[" + i + "]/div/ytd-comment-replies-renderer/div[1]/div[1]/div[1]/ytd-button-renderer/a/tp-yt-paper-button/yt-formatted-string"); let oreplyCount = oreplyCountMain; if (!(oreplyCountMain && !oreplyCount)) { if (!oreplyCount) noReply[i] = true; if (!oreplyCount) continue; if (parseInt(oreplyCount.textContent) === replyCount[i]) noReply[i] = true; if (parseInt(oreplyCount.textContent) === replyCount[i]) continue; } else { if (replyCount[i] === 1) noReply[i] = true; if (replyCount[i] === 1) continue; } checkedReply = 1; if (replyCount[i] > 0 && replyCount[i] % 10 === 0) checkedReply = replyCount[i] + 1; while (getReply(i)) { foldedData(i); checkedReply++; } replyCount[i] = checkedReply - 1; } } function getReply(thread) { replyPath = threadPath + "/ytd-comment-thread-renderer[" + thread + "]/div/ytd-comment-replies-renderer/div[1]/div[2]/div[1]/ytd-comment-renderer[" + checkedReply + "]"; reply = document.evaluate(replyPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; return reply; } function foldedData(thread) { replyUserId = getElementByXpath(replyPath + "/div[3]/div[2]/div[1]/div[2]/h3/a").href.toString().replace(/https:\/\/www.youtube.com\/channel\//g, ""); replyUserName = getElementByXpath(replyPath + "/div[3]/div[2]/div[1]/div[2]/h3/a/span"); if (replyUserName) replyUserName = replyUserName.textContent.toString().replace(/\n /g, "").replace(/\n /g, ""); replyValue = getElementByXpath(replyPath + "/div[3]/div[2]/div[2]/ytd-expander/div/yt-formatted-string"); btnBlackList = getElementByXpath(replyPath); btnBlackList.setAttribute("data-commentID", replyUserId); btnBlackList.setAttribute("data-commentName", replyUserName); btnBlackList.setAttribute("data-commentSeq", thread); if (banlistSearch(replyUserId) || wordFilter(replyValue.textContent)) { if (reply && deleteComment) reply.style.display = 'none'; if (replyValue) { replyValue.innerText = deleteText; replyValue.setAttribute("style", "font-style: italic;"); } } btnBlackList.ondblclick = function() { banCheck( this.getAttribute('data-commentID'), this.getAttribute('data-commentName'), this.getAttribute('data-commentSeq'), true ); } //console.log(checkedReply,replyUserName,"reply"); } function getComment() { path = "/html/body/ytd-app/div[1]/ytd-page-manager/" + viewURL + "/ytd-comments/ytd-item-section-renderer/div[3]/ytd-comment-thread-renderer[" + (checkedComment + 1) + "]"; comment = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; if (comment === precomment[(checkedComment + 1)]) return false; precomment[(checkedComment + 1)] = comment return comment; } function defData() { commentUserId = getElementByXpath(path + "/ytd-comment-renderer/div[3]/div[2]/div[1]/div[2]/h3/a").href.toString().replace(/https:\/\/www.youtube.com\/channel\//g, ""); commentUserName = getElementByXpath(path + "/ytd-comment-renderer/div[3]/div[2]/div[1]/div[2]/h3/a/span"); if (commentUserName) commentUserName = commentUserName.textContent.toString().replace(/\n /g, "").replace(/\n /g, ""); commentValue = getElementByXpath(path + "/ytd-comment-renderer/div[3]/div[2]/div[2]/ytd-expander/div/yt-formatted-string"); //console.log(commentValue); btnBlackList = getElementByXpath(path + "/ytd-comment-renderer"); btnBlackList.setAttribute("data-commentID", commentUserId); btnBlackList.setAttribute("data-commentName", commentUserName); btnBlackList.setAttribute("data-commentSeq", checkedComment + 1); if (banlistSearch(commentUserId) || wordFilter(commentValue.textContent)) { if (comment && deleteComment) comment.style.display = 'none'; if (commentValue) { commentValue.innerText = deleteText; commentValue.setAttribute("style", "font-style: italic;"); } } btnBlackList.ondblclick = function() { banCheck( this.getAttribute('data-commentID'), this.getAttribute('data-commentName'), this.getAttribute('data-commentSeq') ); } //console.log(checkedComment,commentUserName); } function banCheck(id, name, seq, fold) { thisPath = "/html/body/ytd-app/div/ytd-page-manager" + viewURL + "/ytd-comments/ytd-item-section-renderer/div[3]/ytd-comment-thread-renderer[" + seq + "]"; if (!fold) text = getElementByXpath(thisPath + "/ytd-comment-renderer/div[3]/div[2]/div[2]/ytd-expander/div/yt-formatted-string"); if (fold) text = false; wordPure(name); if (!banlistSearch(id)) { Swal.fire({ title: '確定要將 ' + name + ' 列入黑名單嗎?', text: '頻道ID(' + id + ')', icon: 'warning', showCancelButton: true, confirmButtonColor: '#3085d6', cancelButtonColor: '#d33', confirmButtonText: '列入黑名單', cancelButtonText: '取消' }).then((result) => { if (result.isConfirmed) { Swal.fire( '已將 ' + name + ' 列入黑名單', '頻道ID(' + id + ')', 'info' ).then(() => { list.unshift({ "id": id, "name": name }); //list.length = 0; blacklist("save"); if (text) { let info = document.createElement('span'); text.innerText = ""; while (text.length > 0) { text.pop(); } info.innerText = "留言將在之後屏蔽"; info.setAttribute("style", "font-style: italic;color:red;"); text.append(info); } else { replyCount[seq] = 0; noReply[seq] = false; } }) } }) } else { Swal.fire({ title: '確定要將 ' + name + ' 從黑名單移除嗎?', text: '頻道ID(' + id + ')', icon: 'warning', showCancelButton: true, confirmButtonColor: '#3085d6', cancelButtonColor: '#d33', confirmButtonText: '從黑名單移除', cancelButtonText: '取消' }).then((result) => { if (result.isConfirmed) { Swal.fire( '已將 ' + name + ' 從黑名單移除', '頻道ID(' + id + ')', 'info' ).then(() => { list.splice(banlistSearch(id) - 1, 1); //list.length = 0; blacklist("save"); if (text) { let info = document.createElement('span'); text.innerText = ""; while (text.length > 0) { text.pop(); } info.innerText = "此留言者已從黑名單解封,之後就能再次看見"; info.setAttribute("style", "font-style: italic;color:orange;"); text.append(info); } }) } }) } } function blacklist(event) { if (event == "save") return GM_setValue("list", JSON.stringify(list)); return JSON.parse(GM_getValue("list")); } function banlistSearch(id) { for (let i = 0; i < list.length; i++) { if (list[i].id == id) { return i + 1; break; } } } function exportFn(content, filename) { let odownload = document.createElement("a"); odownload.download = filename; odownload.style.display = "none"; let jsonBlob = new Blob([encodeURI(content, "utf-8")], { type: "text/plain;charset=utf-8" }); odownload.href = URL.createObjectURL(jsonBlob); document.body.appendChild(odownload); odownload.click(); document.body.removeChild(odownload); } function importFn() { let oimport = document.createElement("input"); oimport.style.display = "none"; oimport.type = "file"; oimport.accept = ".json"; oimport.onchange = function() { if (oimport.files.length != 0 && oimport.files[0].type.match(/json.*/)) { let reader = new FileReader(); reader.onload = function(e) { let loadData = JSON.parse(e.target.result); Swal.fire({ title: '導入黑名單', text: "請選擇要對新資料的處理方式", confirmButtonText: '和原資料合併', showDenyButton: true, denyButtonText: '覆蓋原資料', backdrop: 'rgba(0,0,0,0.6)' }).then((result) => { if (result.isDenied) { list = loadData; blacklist("save"); Swal.fire('已覆蓋原資料'); } else if (result.isConfirmed) { for (let i = 0; i < loadData.length; i++) { if (!list.find(element => element.id === loadData[i].id)) { //console.log(loadData[i]); list.unshift(loadData[i]); } } blacklist("save"); Swal.fire('已合併兩資料'); } }) reader.onerror = function(e) { Swal.fire('無法讀取檔案'); } } reader.readAsText(oimport.files[0], "ISO-8859-1"); } else { Swal.fire('上傳的檔案非json檔'); } } oimport.click(); } function wordFilter(commentText) { if (commentMinLength > 0 && commentText.length < commentMinLength) return commentText.length; if (commentMaxLength > 0 && commentText.length > commentMaxLength) return commentText.length; if (banWords.length <= 0) return false; for (let i = 0; i < banWords.length; i++) { if (commentText.indexOf(banWords[i]) + 1) return banWords[i]; } } function wordPure(word) { if (nameLength >= 0 && word.length > nameLength) { return word.substring(0, nameLength) + "..."; } else { return word; } } function getElementByXpath(paths) { return document.evaluate(paths, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址