您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
让讨厌的苍蝇走开!屏蔽指定用户的主帖和回帖,感谢原作者 taxidriver、jun4rui
当前为
// ==UserScript== // @name TGFC ban troll // @namespace http://club.tgfcer.com/20060602 // @version 0.85 // @license MIT // @description 让讨厌的苍蝇走开!屏蔽指定用户的主帖和回帖,感谢原作者 taxidriver、jun4rui // @author 20060602 // @supportURL [email protected] // @include http://*.tgfcer.com/* // @include http://*.tgfcer.net/* // @include https://*.tgfcer.com/* // @include https://*.tgfcer.net/* // @grant GM.xmlHttpRequest // ==/UserScript== // console.log('Hello Tgfcer from "tgfc-ban-troll.js".'); // global datas for storage var BanList, BanListArray, ShowBanTip, BanTip, BanNegJisao, JisaoMin, BanQuote; var CookieName = "TgfcBanTrollData"; var MenuTitle = "让TGFCER更美好的设置,由 taxidriver、jun4rui 两位坛友原创 v" + GM_info.script.version; var MenuText = 'TGGM<span style="font-size:.75em">(v' + GM_info.script.version + ')</span>' var UserName = null; var DownloadSuccessMessage = `数据下载成功,请:\n\n 点击"TGGM"关闭面板,保存到本地;或者\n (不点"TGGM")刷新页面,继续用本地数据。`; var UpDownTitle = "相同用户名的数据,可跨设备、浏览器、域名同步,\n纯手动,每次同步都需要先上传、再下载。\n免费存储服务,服务器数据可能不定期清除。" // console.log('The Begin of logic.'); main(); function main() { Array.prototype.contains = contains; loadData(); test(); //console.log('Data loaded.'); if (underWapUrls()) { processWap(); } else if (underWebUrls()) { // console.log('gonna execute processWeb.'); processWeb(); } } // UserName related start function getUserName() { return UserName; } function setUserName(userName) { UserName = userName; } // UserName related end function underWapUrls() { // console.log('Using new underWapUrls().'); var wapUrls = [ 'http://club.tgfcer.com/wap/', 'http://wap.tgfcer.com/', 'http://club.tgfcer.net/wap/', 'http://wap.tgfcer.net/', 'https://club.tgfcer.com/wap/', 'https://wap.tgfcer.com/', 'https://club.tgfcer.net/wap/', 'https://wap.tgfcer.net/', 'http://s.tgfcer.com/wap/', 'https://s.tgfcer.com/wap/', 'http://s.tgfcer.net/wap/', 'https://s.tgfcer.net/wap/' ]; return underURLs(wapUrls); } function underWebUrls() { // console.log('Using new underWebUrls().'); var webUrls = [ 'http://club.tgfcer.com/', 'http://club.tgfcer.net/', 'https://club.tgfcer.com/', 'https://club.tgfcer.net/', 'http://bbs.tgfcer.com/', 'http://bbs.tgfcer.net/', 'https://bbs.tgfcer.com/', 'https://bbs.tgfcer.net/', 'http://s.tgfcer.com/', 'http://s.tgfcer.net/', 'https://s.tgfcer.com/', 'https://s.tgfcer.net/' ]; return underURLs(webUrls); } //console.log('The End of logic.'); function getLocalStorage(name, defaultValue) { if (typeof (localStorage[name]) === 'undefined') { localStorage[name] = defaultValue; // console.log(name + ' initialed with:' + defaultValue); } return localStorage[name]; } function postLoad() { BanListArray = BanList.split(','); JisaoMin = parseInt(localStorage.JisaoMin); var idxEmpty = BanListArray.indexOf(''); if (idxEmpty !== -1) { BanListArray.splice(idxEmpty, 1); } } function loadData() { //先判断有没有localStorage保存的设置数据,没有则新建 BanList = getLocalStorage('BanList', ''); ShowBanTip = getLocalStorage('ShowBanTip', true) === 'true'; BanTip = getLocalStorage('BanTip', 'Blocked!!!!!'); BanNegJisao = getLocalStorage('BanNegJisao', false) === 'true'; JisaoMin = getLocalStorage('JisaoMin', 0); BanQuote = getLocalStorage('BanQuote', false) === 'true'; postLoad(); // console.log(localStorage); } function getJsonValue(key, defaultValue, jobj) { if (!jobj.hasOwnProperty(key)) { jobj[key] = defaultValue; } return jobj[key]; } function saveData(banList, showTip, banTip, banNegJisao, jisaoMin, banQuote) { BanList = banList; ShowBanTip = showTip; BanListArray = BanList.split(','); localStorage.BanList = BanList; localStorage.ShowBanTip = ShowBanTip; localStorage.BanTip = banTip; if (banNegJisao !== undefined) { localStorage.BanNegJisao = banNegJisao; } if (jisaoMin !== undefined) { localStorage.JisaoMin = jisaoMin; } if (banQuote !== undefined) { localStorage.BanQuote = banQuote; } BanTip = localStorage.BanTip; } function getJson(banList, showBanTip, banTip, banNegJisao, jisaoMin, banQuote) { json = { BanList: banList, ShowBanTip: showBanTip, BanTip: banTip, BanNegJisao: banNegJisao, JisaoMin: jisaoMin, BanQuote: banQuote, un: getUserName() }; var jstr = JSON.stringify(json); return jstr; } function loadJson(jstr) { var jdata; try { jdata = JSON.parse(jstr); } catch (err) { console.log(err); return false; } if (!jdata.hasOwnProperty('BanList')) { return false; } BanList = getJsonValue('BanList', '', jdata); ShowBanTip = getJsonValue('ShowBanTip', true, jdata); BanTip = getJsonValue('BanTip', 'Blocked!!!!!', jdata); BanNegJisao = getJsonValue('BanNegJisao', false, jdata); JisaoMin = getJsonValue('JisaoMin', 0, jdata); BanQuote = getJsonValue('BanQuote', false, jdata); // console.log(getJsonValue('ShowBanTip', true, jdata)); postLoad(); return true; } function getTopLevelDomain() { var parts = document.domain.split('.'); var l = parts.length; if (l < 2) { return document.domain; } return '.' + parts[l - 2] + '.' + parts[l - 1]; } function instanceEditBanList(funcEdit) { loadData(); funcEdit(); saveData(BanListArray.join(','), ShowBanTip, BanTip, BanNegJisao, JisaoMin.toString(), BanQuote); } function removeFromBanList(username) { instanceEditBanList(function () { while (true) { var idx = BanListArray.indexOf(username); if (idx === -1) break; BanListArray.splice(idx, 1); } }); location.reload(); } function addToBanList(username) { // console.log("gonna remove username:" + username); // console.log(BanListArray); instanceEditBanList(function () { var idx = BanListArray.indexOf(username); if (idx !== -1) return; BanListArray.push(username); }); // console.log(BanListArray); location.reload(); } function processWap() { //不让图片尺寸超过屏幕的最大宽度,有时候图片太大了看起来好累 addGlobalStyle('div.message>img {max-width:100%;}'); addGlobalStyle('#tgbs>button {padding:2px .8em;margin-right:.5em;}'); //让顶部导航栏浮动固定 addGlobalStyle('#scroller>.navbar {position:fixed;height:28px;line-height:28px;width:100%;top:0;left:0;box-shadow: 5px 1px 5px #888888;} body {padding-top:36px;}'); addGlobalStyle('#scroller>.navigation {position:fixed;height:28px;line-height:28px;width:100%;top:0;left:0;box-shadow: 5px 1px 5px #888888;} body {padding-top:36px;}'); addWapLink(); //在原生导航栏中加入设置模块 //console.log($('a[href="#bottom"]').parent().parent()); var hookPoint = $('div.navbar'); if (hookPoint.length === 0) { hookPoint = $('a[href="#bottom"]').parent().parent(); hookPoint.append('<li><a href="#" class="nav_link" id="tgbs-btn" title="' + MenuTitle + '">' + MenuText + '</a></li>'); } else { hookPoint.append(' | <a href="#" class="nav_link" id="tgbs-btn" title="' + MenuTitle + '">' + MenuText + '</a>'); hookPoint.css('z-index', 2); } //点击模块的处理 $('#scroller').delegate('#tgbs-btn', 'click', function (e) { e.preventDefault(); if ($('#tgbs').css('display') == 'none') { loadData(); wapLoadUserName(); $('#tgbs').css({ 'display': '' }); // $('#tgbs').css('top', $('#tgbs-btn').position().top + 20); $('#tgbs').css('top', '32px'); $('#tgbs').css('left', 2); $('#tgbs textarea').focus(); } else { //关闭设置菜单时,关闭设置面板 $('#tgbs').css({ 'display': 'none' }); // 保存数据到localStorage savePanelData(); } }); // save panel data function savePanelData() { BanList = $('#banlist-textarea').val(); BanListArray = BanList.split(','); ShowBanTip = $("#showBanTip").prop('checked'); BanTip = $('#ban-tip').val(); BanQuote = $("#banQuote").prop('checked'); saveData(BanList, ShowBanTip, BanTip, undefined, undefined, BanQuote); } // pop panel data function popWapPanelData(banList, showBanTip, banTip, banQuote,) { $('#banlist-textarea').val(banList); $("#showBanTip").prop('checked', showBanTip); $('#ban-tip').val(banTip); $("#banQuote").prop('checked', banQuote); } //在原生导航栏下面加入设置表单 //$('div.navbar') hookPoint.append('<div id="tgbs" class="list_item_top" style="z-index:999;color:#FFF; width:356px;padding:.5em;position:fixed; display:none; overflow:hidden;box-shadow: rgb(51, 51, 51) 1px 1px 19px;background-color: #436193;">' + '<div style="padding-bottom:.25em;">屏蔽ID列表:</div>' + '<textarea id="banlist-textarea" style="width:100%;height:160px;resize:vertical;">' + BanList + '</textarea>' + '<form><input id="showBanTip" type="checkbox" name="showBanTip" ' + (ShowBanTip ? "checked" : "") + ' /> 显示屏蔽提示 | ' + '提示信息 <input id="ban-tip" style="font-size : 1em; padding : 0px; margin : 0px; margin-top: 5px; width : 200px;" value="' + BanTip + '"/>' + '<hr/> <input id="banQuote" type="checkbox" name="banQuote" ' + (BanQuote ? "checked" : "") + ' /> 如果该用户位于屏蔽列表,屏蔽其被引用的发言' + '</form>' + '<hr/> <button id="sort-list">排序屏蔽列表</button>' + '<button id="download" title="' + UpDownTitle + '">下载</button>' + '<button id="upload" title="' + UpDownTitle + '">上传</button>' + '</div>'); //点击屏蔽区将展开屏蔽内容 $('#scroller').delegate('.list-ban-section', 'click', function (e) { e.preventDefault(); var targetNode = $(this).parent().parent(); if (targetNode.css('height') == '21px') { targetNode.css({ 'height': 'auto' }); } else { targetNode.css({ 'height': '21px' }); } }); var btnSortList = document.getElementById("sort-list"); btnSortList.onclick = function (e) { e.preventDefault(); var textareaBanList = document.getElementById('banlist-textarea'); sortBanList(textareaBanList); } var btnDownload = document.getElementById("download"); btnDownload.onclick = function (e) { e.preventDefault(); fetchFromCloud((json) => { // console.log(json); popWapPanelData(json.BanList, json.ShowBanTip, json.BanTip, json.BanQuote); notify(DownloadSuccessMessage) }); } var btnUpload = document.getElementById("upload"); btnUpload.onclick = function (e) { e.preventDefault(); pushToCloud((json) => { // console.log(json); }); } //列表页面 var ForumPagePart = 'index.php?action=forum'; //帖子内文页面 var ThreadPagePart = 'index.php?action=thread'; //如果当前页面是列表页面的处理 if (hasURLPart(ForumPagePart)) { //console.log('当前在列表页面'); $('.dTitle').each(function () { var author = $(this).find('span.author').text(); for (var i in BanListArray) { //判断发帖人是否在屏蔽列表中 if (author.indexOf(BanListArray[i]) == 1) { //console.log(BanListArray[i]); if (!ShowBanTip) { $(this).css({ display: 'none' }); continue; } //console.log(author.indexOf(BanListArray[i]),BanListArray[i]); // $(this).addClass('list-ban-section'); $(this).prepend('<div style="width:auto;text-align:center;border:1px dashed #AAAAAA;color:#AAAAAA; line-height:19px;"><a class="list-ban-section" href="#">查看标题</a> <strong><s> ' + BanListArray[i] + ' </s></strong>' + BanTip + ' <a class="remove-ban" href="#" value="' + BanListArray[i] + '">不再屏蔽</a>' + '</div>'); $(this).css({ 'height': '21px', 'overflow': 'hidden' }); } } }); } var setDisplay = function (startNode, val) { startNode.css({ 'display': val }); startNode.next().css({ 'display': val }); startNode.next().next().css({ 'display': val }); // startNode.next().next().next().css({ 'display': val }); // startNode.next().next().next().next().css({ 'display': val }); } $('#scroller').delegate('.info-ban-section', 'click', function (e) { e.preventDefault(); if ($(this).parent().next().css('display') == 'none') { setDisplay($(this).parent().next(), 'inherit'); } else { setDisplay($(this).parent().next(), 'none'); } }); $('#scroller').delegate('.remove-ban', 'click', function (e) { e.preventDefault(); removeFromBanList($(this).attr('value')); }); //如果当前页面是内容页的处理 if (hasURLPart(ThreadPagePart)) { markJiSao(); if (BanQuote) { filterQuote(BanListArray, function () { return document.getElementsByClassName("quote"); }, function (node) { return node.getElementsByClassName("quote-bd"); }, function (author, reason) { return author + '</s> ' + BanTip + reason; }); } $('.infobar').each(function () { var author = $(this).find('a').eq(1).text(); for (var i in BanListArray) { //判断发帖人是否在屏蔽列表中 if (author == BanListArray[i]) { // console.log(author.indexOf(BanListArray[i]), BanListArray[i]); if (ShowBanTip) { $(this).before('<div style="width:auto;text-align:center;border:1px dashed #BCBCBC;color:#BCBCBC; line-height:19px;"><a class="info-ban-section" href="#">查看内容</a> <strong><s>' + author + '</s></strong>' + BanTip + ' <a class="remove-ban" href="#" value="' + author + '">不再屏蔽</a>' + '</div>'); } //依次连续隐藏5个(含自己)元素 setDisplay($(this), 'none'); } } var authorA = $(this).find('a').eq(1); authorA.after(' <a class="ban-author" href="#" value="' + author + '">屏蔽</a> '); }); $('#scroller').delegate('.ban-author', 'click', function (e) { e.preventDefault(); addToBanList($(this).attr('value')); }); } } function processWeb() { // console.log('processWeb begin'); // 调整 “最后发表” 列的宽度,避免部分较长的 ID 导致此栏换行 addGlobalStyle('.threadlist td.lastpost {width:160px;}'); closeLeftAdv(); // console.log('processWeb end'); //在原生导航栏中加入设置模块 var newSpan = document.createElement('span'); newSpan.innerHTML = '<a href="#" class="nav_link" id="tgbs-btn" title="' + MenuTitle + '">' + MenuText + '</a> | '; // console.log(newSpan); var myTag = document.getElementById('my'); setUserName(myTag.textContent); var hookPoint = myTag.parentNode.parentNode; // console.log(hookPoint); hookPoint.appendChild(newSpan); // console.log(navP); var btn = document.getElementById('tgbs-btn'); // console.log(btn); var floatDiv = createFloatDiv(); newSpan.appendChild(floatDiv); var banlistTextarea = document.getElementById('ban-list'); var showCheckbox = document.getElementById('show-ban-info'); var banTip = document.getElementById('ban-tip'); var banNegJisaoCheckbox = document.getElementById('ban-neg-jisao'); var jisaoMin = document.getElementById('jisao-min'); var banQuote = document.getElementById('ban-quote'); //console.log(floatDiv); // 显示、隐藏tggm面板 btn.onclick = function (e) { e.preventDefault(); // console.log('showCheckbox.checked:' + showCheckbox.checked + ' ShowBanTip:' + ShowBanTip); if (floatDiv.style.display === 'none') { loadData(); floatDiv.style.display = ''; floatDiv.style.top = getElementTop(newSpan) + 20 + 'px'; floatDiv.style.left = getElementLeft(newSpan) - 365 + 'px'; showCheckbox.checked = ShowBanTip; banlistTextarea.value = BanList; banlistTextarea.focus(); } else { floatDiv.style.display = 'none'; saveData(banlistTextarea.value, showCheckbox.checked, banTip.value, banNegJisaoCheckbox.checked, jisaoMin.value, banQuote.checked); } }; function addBanLink(cite, author) { cite.innerHTML += '<a class="ban-author" href="#" value="' + author + '">屏蔽</a>'; } // 列表页面 filterBlackList( function () { return document.getElementsByTagName('tbody'); }, 2, function (author, reason) { return '<tr><td style="background-color:#e5e5e5" class="folder"></td><td style="background-color:#e5e5e5" class="icon"></td><th class="" style="text-align:center;"><label></label><span>' + '<a class="show-thread-title" href="#">查看标题</a> ' + '<s>' + author + '</s> ' + BanTip + reason + ' <a class="remove-ban" href="#" value="' + author + '">不再屏蔽</a>' + '</span></th><td style="background-color:#e5e5e5;text-align:center" class="author"></td><td class="nums"></td><td style="background-color:#e5e5e5" class="lastpost"></td></tr>'; } ); // 内容页面 filterBlackList( function () { return document.getElementsByClassName('viewthread'); }, 1, function (author, reason) { return '<table cellspacing="0" cellpadding="0"><tbody><tr><td class="postauthor"></td><td class="postcontent">' + '<a class="show-content" href="#">查看内容</a> <s>' + author + '</s> ' + BanTip + reason + ' <a class="remove-ban" href="#" value="' + author + '">不再屏蔽</a>' + '</td></tr></tbody></table></div>'; }, addBanLink ); var contentA = document.getElementsByClassName("show-content"); for (var i = 0; i < contentA.length; ++i) { var link = contentA[i]; link.onclick = function (e) { e.preventDefault(); var targetNode = this.parentElement.parentElement.parentElement.parentElement.parentElement.nextSibling; if (targetNode.style.display === 'none') { targetNode.style.display = 'block'; } else { targetNode.style.display = 'none'; } } } var titleA = document.getElementsByClassName("show-thread-title"); for (i = 0; i < titleA.length; ++i) { link = titleA[i]; link.onclick = function (e) { e.preventDefault(); var targetNode = this.parentElement.parentElement.parentElement.parentElement.nextSibling; if (targetNode.style.display === 'none') { targetNode.style.display = 'table-row-group'; } else { targetNode.style.display = 'none'; } } } var removeBanA = document.getElementsByClassName("remove-ban"); for (i = 0; i < removeBanA.length; ++i) { link = removeBanA[i]; link.onclick = function (e) { e.preventDefault(); console.log(this.getAttribute('value')); removeFromBanList(this.getAttribute('value')); } } var banA = document.getElementsByClassName("ban-author"); for (i = 0; i < banA.length; ++i) { link = banA[i]; link.onclick = function (e) { e.preventDefault(); console.log(this.getAttribute('value')); addToBanList(this.getAttribute('value')); } } if (BanQuote) { filterQuote(BanListArray, function () { return document.getElementsByClassName('quote'); }, function (node) { return node.getElementsByTagName('blockquote'); }, function (author, reason) { return author + '</s> ' + BanTip + reason; }); } } //添加全局CSS样式的方法 function addGlobalStyle(css) { var head, style; head = document.getElementsByTagName('head')[0]; if (!head) { return; } style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); } function markJiSao() { //正激骚 addGlobalStyle('a.positive-sao {color:#f00;}'); //负激骚 addGlobalStyle('a.negative-sao {color:#00bb00;}'); var regex = /^骚\((-?\d+)\)$/g; $('a').each(function () { var atag = $(this); var match = regex.exec(atag.text()); if (match && match[1] != '0') { //console.log(match[1]); if (match[1].indexOf('-') === 0) { atag.addClass("negative-sao"); } else { atag.addClass("positive-sao"); } } }); } function addWapLink() { var webLink = /^http:\/\/club\.tgfcer\.com\/thread-([\d]+)-.+html/ig; var webLinkNet = /^http:\/\/club\.tgfcer\.net\/thread-([\d]+)-.+html/ig; var tidStr = 'http://wap.tgfcer.com/index.php?action=thread&tid=TidDummy&sid=&vt=1&tp=100&pp=100&sc=0&vf=0&sm=0&iam=&css=&verify=&fontsize=0'; var tidStrNet = 'http://club.tgfcer.net/wap/index.php?action=thread&tid=TidDummy&sid=&vt=1&tp=100&pp=100&sc=0&vf=0&sm=0&iam=&css=&verify=&fontsize=0'; var webLinkS = /^https:\/\/club\.tgfcer\.com\/thread-([\d]+)-.+html/ig; var webLinkNetS = /^https:\/\/club\.tgfcer\.net\/thread-([\d]+)-.+html/ig; var tidStrS = 'https://wap.tgfcer.com/index.php?action=thread&tid=TidDummy&sid=&vt=1&tp=100&pp=100&sc=0&vf=0&sm=0&iam=&css=&verify=&fontsize=0'; var tidStrNetS = 'https://club.tgfcer.net/wap/index.php?action=thread&tid=TidDummy&sid=&vt=1&tp=100&pp=100&sc=0&vf=0&sm=0&iam=&css=&verify=&fontsize=0'; var tags = document.getElementsByTagName('a'); for (var i = 0; i < tags.length; ++i) { var tag = tags[i]; tryConvert(tag, webLink, tidStr); tryConvert(tag, webLinkNet, tidStrNet); tryConvert(tag, webLinkS, tidStrS); tryConvert(tag, webLinkNetS, tidStrNetS); continue; var href = tag.href; var execResult = webLink.exec(href); if (execResult) { var threadId = execResult[1]; var wapLink = tidStr.replace('TidDummy', threadId); //console.log(wapLink); var newSpan = document.createElement('span'); newSpan.innerHTML = ' <a href="' + wapLink + '" title="">(wap点我)</a> '; tag.parentNode.insertBefore(newSpan, tag.nextSibling); } } } function tryConvert(aTag, regex, targetPattern) { var href = aTag.href; var execResult = regex.exec(href); if (execResult) { var threadId = execResult[1]; var wapLink = targetPattern.replace('TidDummy', threadId); //console.log(wapLink); var newSpan = document.createElement('span'); newSpan.innerHTML = ' <a href="' + wapLink + '" title="">(wap点我)</a> '; aTag.parentNode.insertBefore(newSpan, aTag.nextSibling); } } function getElementTop(element) { var actualTop = element.offsetTop; var current = element.offsetParent; while (current !== null) { actualTop += current.offsetTop; current = current.offsetParent; } return actualTop; } function getElementLeft(element) { var actualLeft = element.offsetLeft; var current = element.offsetParent; while (current !== null) { actualLeft += current.offsetLeft; current = current.offsetParent; } return actualLeft; } function popPanel(banList, showBanTip, banTip, banNegJisao, jisaoMin, banQuote) { var banlistTextarea = document.getElementById('ban-list'); var showCheckbox = document.getElementById('show-ban-info'); var banTipText = document.getElementById('ban-tip'); var banNegJisaoCheckbox = document.getElementById('ban-neg-jisao'); var jisaoMinNumber = document.getElementById('jisao-min'); var banQuoteCheckBox = document.getElementById('ban-quote'); banlistTextarea.value = banList; showCheckbox.checked = showBanTip; banTipText.value = banTip; banNegJisaoCheckbox.checked = banNegJisao; jisaoMinNumber.value = jisaoMin; banQuoteCheckBox.checked = banQuote; } function createFloatDiv() { var floatDiv = document.createElement('div'); floatDiv.setAttribute('id', 'tgbs'); floatDiv.setAttribute('style', 'color:#FFF; width:400px;padding:.5em;position:fixed; display:none; overflow:hidden;box-shadow: rgb(51, 51, 51) 1px 1px 19px;background-color: #00b23d;text-align:left;'); var titleText = document.createElement('div'); titleText.innerHTML = '屏蔽ID列表:'; floatDiv.appendChild(titleText); var banlistTextarea = document.createElement('textarea'); banlistTextarea.setAttribute('id', 'ban-list'); banlistTextarea.style.width = '99%'; banlistTextarea.style.height = '160px'; banlistTextarea.style.marginBottom = '4px'; banlistTextarea.style.resize = 'vertical'; banlistTextarea.value = BanList; floatDiv.appendChild(banlistTextarea); var form = document.createElement('form'); floatDiv.appendChild(form); var showCheckbox = document.createElement('input'); form.appendChild(showCheckbox); showCheckbox.setAttribute('type', 'checkbox'); showCheckbox.setAttribute('id', 'show-ban-info'); showCheckbox.checked = ShowBanTip; var checkText = document.createElement('span'); checkText.innerHTML = '显示屏蔽提示 | 提示信息 '; form.appendChild(checkText); var banTip = document.createElement('input'); form.appendChild(banTip); banTip.setAttribute('type', 'text'); banTip.setAttribute('id', 'ban-tip'); banTip.style.fontSize = '1em'; banTip.style.padding = '0px 5px'; banTip.style.margin = '0px'; banTip.style.width = '200px'; // banTip.style.color = '#cc0000'; banTip.value = BanTip; var lineBreak = document.createElement('hr'); form.appendChild(lineBreak); var banNegJisaoCheckbox = document.createElement('input'); form.appendChild(banNegJisaoCheckbox); banNegJisaoCheckbox.setAttribute('type', 'checkbox'); banNegJisaoCheckbox.setAttribute('id', 'ban-neg-jisao'); banNegJisaoCheckbox.checked = BanNegJisao; var checkTextBanNegJiSao = document.createElement('span'); checkTextBanNegJiSao.innerHTML = '屏蔽,如果该用户激骚小于 '; form.appendChild(checkTextBanNegJiSao); var jisaoMin = document.createElement('input'); form.appendChild(jisaoMin); jisaoMin.setAttribute('type', 'number'); jisaoMin.setAttribute('id', 'jisao-min'); jisaoMin.style.fontSize = '1em'; jisaoMin.style.padding = '0px 5px'; jisaoMin.style.margin = '0px'; jisaoMin.style.width = '112px'; // jisaoMin.style.color = '#cc0000'; jisaoMin.value = JisaoMin; lineBreak = document.createElement('hr'); form.appendChild(lineBreak); var banQuoteCheckbox = document.createElement('input'); form.appendChild(banQuoteCheckbox); banQuoteCheckbox.setAttribute('type', 'checkbox'); banQuoteCheckbox.setAttribute('id', 'ban-quote'); banQuoteCheckbox.checked = BanQuote; var checkTextBanQuote = document.createElement('span'); checkTextBanQuote.innerHTML = '如果该用户位于屏蔽列表,屏蔽其被引用的发言'; form.appendChild(checkTextBanQuote); lineBreak = document.createElement('hr'); form.appendChild(lineBreak); function createButton(caption, onclick, id = null) { var btn = document.createElement('BUTTON'); var text = document.createTextNode(caption); // Create a text node btn.appendChild(text); // Append the text to <button> btn.style.marginRight = '0.5em'; if (id) btn.setAttribute('id', id); form.appendChild(btn); if (onclick) btn.onclick = onclick; return btn; } function jisaoEditable(e) { e?.preventDefault(); var taReason = document.getElementsByName('reason'); //console.log(taReason); if (taReason) { for (var i = 0, len = taReason.length; i < len; i++) { var ta = taReason[i]; ta.removeAttribute('readonly'); } } jisaoNoPM(); return false; } var btnJisaoEdit = createButton('让“激骚理由”可编辑', jisaoEditable); function sortList(e) { e.preventDefault(); sortBanList(banlistTextarea); } var btnSortBanList = createButton('排序屏蔽列表', sortList); function downloadData(e) { e.preventDefault(); fetchFromCloud((json) => { console.log(json); popPanel(json.BanList, json.ShowBanTip, json.BanTip, json.BanNegJisao, json.JisaoMin, json.BanQuote); notify(DownloadSuccessMessage) }); } var btnDownload = createButton('下载', downloadData, 'btn-download'); btnDownload.setAttribute('title', UpDownTitle) function uploadData(e) { e.preventDefault(); pushToCloud((json) => { // console.log(json); }); } var btnUpload = createButton('上传', uploadData, 'btn-upload'); btnUpload.setAttribute('title', UpDownTitle) return floatDiv; } function jisaoNoPM(event) { var taReason = document.getElementsByName('sendreasonpm'); //console.log(taReason); if (taReason) { for (var i = 0, len = taReason.length; i < len; i++) { var ta = taReason[i]; ta.removeAttribute('disabled'); } } //event.preventDefault(); return false; } function sortBanList(textareaBanList) { function onlyUnique(value, index, self) { return value && self.indexOf(value) === index; } function startWithASCII(s) { if (s.length > 0) { var code = s.charCodeAt(0); return code < 256; } return false; } function pinyinCompare(a, b) { var aIsASCII = startWithASCII(a); var bIsASCII = startWithASCII(b); if (aIsASCII == bIsASCII) { return a.localeCompare(b, "zh"); } if (aIsASCII) { return -1; } return 1; } BanListArray.sort(pinyinCompare); BanListArray = BanListArray.filter(onlyUnique); BanList = BanListArray.join(','); // console.log(BanList); textareaBanList.value = BanList; } function banReason(node, cite, author) { if (cite[0].getElementsByTagName('a')[0] == null) { return null; } author = cite[0].getElementsByTagName('a')[0].innerHTML; if (BanListArray.contains(author)) { return ''; } if (BanNegJisao) { var dl = node.getElementsByTagName('dl'); if (dl && dl.length > 0) { dl = dl[0]; var dds = dl.getElementsByTagName('dd'); var jisaoText = dds[3].innerText; var jisao = parseInt(jisaoText); // console.log(jisao); if (jisao < JisaoMin) { return ' 激骚值:' + jisao; } } } return null; } function filterBlackList(nodeFunc, citeCount, tipFunc, citeFunc = null) { var allTextareas, cite, author; allTextareas = nodeFunc(); // console.log(allTextareas); if (!allTextareas.length) { return; } var nodesToProcess = []; for (var index = 0; index < allTextareas.length; index++) { var node = allTextareas[index]; cite = node.getElementsByTagName('cite'); if (cite.length < citeCount) { continue; } var mainCite = cite[0]; author = mainCite.getElementsByTagName('a')[0].innerHTML; if (citeFunc) { citeFunc(mainCite, author); } //console.log(author); var reason = banReason(node, cite, author); if (reason !== null) { // can't insert node in for loop, process later nodesToProcess.push(node); } } nodesToProcess.forEach(function (node) { var cite = node.getElementsByTagName('cite'); var author = cite[0].getElementsByTagName('a')[0].innerHTML; var reason = banReason(node, cite, author); if (ShowBanTip) { var tipNode = node.cloneNode(false); if (tipNode.id !== null) { console.log(tipNode.id) tipNode.id = tipNode.id + "-shadow"; } tipNode.innerHTML = tipFunc(author, reason); node.parentNode.insertBefore(tipNode, node); node.style.display = 'none'; } else { node.style.display = 'none'; } }); } var BqStart = undefined; function isQuoteBanned(array, quoteText) { if (BqStart === undefined) { BqStart = {} array.forEach(elem => { BqStart["原帖由 @" + elem] = elem }); array.forEach(elem => { BqStart["原帖由 " + elem] = elem }); } for (var key in BqStart) { if (BqStart.hasOwnProperty(key)) { if (quoteText.startsWith(key)) { return BqStart[key]; } } } return null; } function filterQuote(banListArray, nodeFunc, bqFunc, tipFunc) { var allTextareas, blockquote, author; allTextareas = nodeFunc(); // console.log(allTextareas.length); if (!allTextareas.length) { return; } for (var index = 0; index < allTextareas.length; index++) { var node = allTextareas[index]; blockquote = bqFunc(node); if (blockquote.length <= 0) { continue; } // console.log(blockquote); author = isQuoteBanned(banListArray, blockquote[0].innerText); // console.log("got author: " + author); var inBanList = author !== null; // console.log("inBanList = " + inBanList); if (!inBanList) { continue; } //console.log(author); var reason = " (勾选屏蔽)"; if (reason !== null) { if (ShowBanTip) { var div = document.createElement("div"); div.appendChild(createReadA()); div.appendChild(crerateTip(author, reason)); div.appendChild(createRemoveA(author)); node.prepend(div); setDisplay(div.nextSibling, 'none'); } else { var br = document.createElement("br"); node.parentNode.insertBefore(br, node); node.style.display = 'none'; } function setDisplay(targetNode, val) { targetNode.style.display = val; if (targetNode.nextSibling) { targetNode.nextSibling.style.display = val; } } function createReadA() { var readA = document.createElement("a"); var text = document.createTextNode("查看内容"); readA.appendChild(text); readA.href = "#" readA.onclick = function (e) { e.preventDefault(); var targetNode = this.parentElement.nextSibling; if (targetNode.style.display == 'none') { setDisplay(targetNode, 'block'); } else { setDisplay(targetNode, 'none'); } }; return readA; } function crerateTip(a, r) { var span = document.createElement('span'); span.innerHTML = ' <s>' + tipFunc(a, r) + ' '; return span; } function createRemoveA(a) { var removeA = document.createElement("a"); var text = document.createTextNode("不再屏蔽"); removeA.appendChild(text); removeA.href = "#" removeA.onclick = function (e) { e.preventDefault(); removeFromBanList(a); }; return removeA; } } } } function underURLs(urls) { //console.log('underURLs begin') var PageCurrent = window.location.href; var result = false; for (var i = 0; i < urls.length; i++) { var prefix = urls[i]; if (PageCurrent.indexOf(prefix) === 0) { result = true; break; } } //console.log('underURL returned with: ' + result); return result; } function hasURLPart(part) { var PageCurrent = window.location.href; return PageCurrent.indexOf(part) >= 0; } function contains(obj) { var index = this.length; while (index--) { if (this[index] === obj) { return true; } } return false; } function closeLeftAdv() { if (true) { return; } console.log('closeLeftAdv begin'); writeCookie('leftadv1', '1', 700); document.getElementById('leftadv').style.display = 'none'; document.getElementById('content_main').style.margin = '0 0 0 0'; console.log('closeLeftAdv end'); } function wapLoadUserName(callback = null) { if (getUserName() !== null) { // already fetched if (callback != null) { callback(getUserName()); } return; } var aTag = Array.from(document.querySelectorAll("#footer a")).find(a => a.textContent == "我的") // console.log(aTag); if (!aTag) return; var url = aTag.href; GM.xmlHttpRequest({ method: "GET", url: url, onload: function (response) { var parser = new DOMParser(); var doc = parser.parseFromString(response.responseText, "text/html"); var a = Array.from(doc.querySelectorAll('#scroller a')).find(a => a.textContent === '>>web') var un = a.parentElement.getElementsByTagName('b')[0].textContent; setUserName(un); if (callback != null) { callback(getUserName()); } // console.log(`UserName is: ${getUserName()}`) } }); } // // test function to test newly developing feature // async function test() { } function notify(message) { alert(message); } // cloud storage related start var SALT = "fd6ca0ea-5bad-438e-8be5-be26e7d9ead0"; async function genKey(userStr) { // console.log(`gonna genKey for userStr: ${userStr}`); var key = await sha256(userStr + SALT); return key; } function UrlBase() { // return "http://localhost:5000/kv"; // return "http://localhost:3000/kv"; // return "https://housekeeper1997.pythonanywhere.com/kv"; return "https://kvlite.vercel.app/kv"; } async function fetchFromCloud(callback) { var userKey = await genKey(getUserName()); // console.log(`gonna fetch for userKey: ${userKey}`); GM.xmlHttpRequest({ method: "GET", url: UrlBase() + "/" + userKey, onload: function (response) { console.log(response.responseText); var data = JSON.parse(response.responseText) if (!data.hasOwnProperty('value')) { notify(`下载操作结果:${data.result}(${data.desc})`); return; } var time = new Date(parseFloat(data.time) * 1000) // console.log(`last upload time: ${time}`); var jobj = JSON.parse(data.value); callback(jobj); }, onerror: function (response) { notify(`下载操作结果:失败(数据未传输)`); } }); } async function pushToCloud(callback) { var userKey = await genKey(getUserName()); var banData = getJson(BanList, ShowBanTip, BanTip, BanNegJisao, JisaoMin, BanQuote); // console.log(banData); var data = { key: userKey, value: banData }; // console.log(data); GM.xmlHttpRequest({ method: "POST", url: UrlBase(), data: JSON.stringify(data), headers: { "Content-Type": "application/json" }, onload: function (response) { // console.log(response.responseText); var json = JSON.parse(response.responseText); notify(`上传操作结果:${json.result}(${json.desc})`); // console.log(json); callback(json); }, onerror: function (response) { notify(`上传操作结果:失败(数据未传输)`); } }); } // cloud storage related end // digest functions async function sha1(d) { return await digest(d, "SHA-1"); } async function sha256(d) { return await digest(d, 'SHA-256'); } async function digest(data, algorithm) { // console.log(`gonna digest for data: ${data} with algorithm: ${algorithm}`); // encode as UTF-8 const msgBuffer = new TextEncoder('utf-8').encode(data); // hash the message const hashBuffer = await window.crypto.subtle.digest(algorithm, msgBuffer); // convert ArrayBuffer to Array const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert bytes to hex string const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join(''); // console.log(hashHex); return hashHex; }