// ==UserScript== // @name MT论坛 // @namespace http://tampermonkey.net/ // @description MT论坛效果增强,如自动签到、自动展开帖子、滚动加载评论、显示uid、屏蔽用户、手机版小黑屋、编辑器优化等 // @version 2.5.4.3 // @author WhiteSevs // @icon https://bbs.binmt.cc/favicon.ico // @match *://bbs.binmt.cc/* // @compatible edge Beta/Dev/Candy 测试通过 // @compatible Yandex 测试通过 // @compatible Kiwi 测试通过 // @license GPL-3.0-only // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_setClipboard // @grant GM_xmlhttpRequest // @grant unsafeWindow // @run-at document-start // @supportURL https://github.com/893177236/Monkey_script // @require https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.4.1/jquery.min.js // @require https://unpkg.com/any-touch/dist/any-touch.umd.min.js // @require https://greasyfork.org/scripts/449471-viewer/code/Viewer.js?version=1081056 // @require https://greasyfork.org/scripts/449512-xtiper/code/Xtiper.js?version=1081249 // @require https://greasyfork.org/scripts/449562-nzmsgbox/code/NZMsgBox.js?version=1082044 // @downloadURL none // ==/UserScript== (function () { 'use strict'; const log = { success: (str) => { console.log("%c" + str, "color: #00a5ff"); }, error: (str) => { console.trace("%c" + str, "color: #f20000"); } } function tryCatch(func, params, errorFunc) { /* 捕获错误 */ try { func(params); } catch (error) { console.log("%c" + (func.name + "出现错误"), "color: #f20000"); console.log("%c" + ("错误原因:" + error), "color: #f20000"); window.eval(errorFunc); } } let mt_config = { dom_obj: { beauty_select: function () { /* 下拉列表对象 */ return document.getElementsByClassName("beauty-select")[0]; }, combobox_switch: function () { /* 复选框对象 */ return document.getElementsByClassName("whitesevcheckbox")[0]; }, comiis_verify: function () { /* 帖子内各个人的信息节点【list】 */ return document.getElementsByClassName("comiis_verify"); }, comiis_formlist: function () { /* 导航中最新、热门、精华、恢复、抢沙发的各个帖子【list】 */ return document.getElementsByClassName("forumlist_li"); }, comiis_mmlist: function () { return document.getElementsByClassName("comiis_mmlist"); }, comiis_postli: function () { /* 帖子内评论,包括帖子内容主体,第一个就是主体【list】 */ return document.getElementsByClassName("comiis_postli comiis_list_readimgs nfqsqi") }, post_bottom_controls: function () { /* 帖子底部一栏控件 */ return document.getElementsByClassName("comiis_znalist_bottom b_t cl") }, post_list_of_comments: function () { /* 帖子内评论列表 */ return $jq(".comiis_postlist.kqide"); }, post_next_commect: function () { /* 帖子内评论下一页的按钮 */ return document.querySelector("div.comiis_page.bg_f>a:nth-child(3)"); } }, rexp: { bbs: /bbs.binmt.cc/, /* 论坛 */ search_url: /bbs.binmt.cc\/search.php/g, /* 搜索页 */ chat_url: /home.php\?mod=space&do=pm&subop=view/g, /* 聊天页 */ home_url: /home.php\?mod=spacecp&ac=profile&op=info/g, /* 个人空间页 */ home_url_brief: /home.php\?mod=space/g, /* 个人空间页简略url */ home_url_at: /bbs.binmt.cc\/space-uid-/g, /* 个人空间页的@点进去 */ home_kmisign_url: /bbs.binmt.cc\/(forum.php\?mod=guide&view=hot(|&mobile=2)|k_misign-sign.html)/g, /* 主页和签到页链接 */ home_space_url: /bbs\.binmt\.cc\/home\.php\?mod=space/g, /* 【我的】 个人信息页链接 */ home_space_pc_uid_url: /space-uid-(.*?).html/, /* PC 个人空间链接uid */ reply_forum: /bbs.binmt.cc\/forum.php\?mod=post&action=reply/g, /* 回复的界面url */ sign_url: "", navigation_url: "", community_url: /forum.php\?forumlist/, /* 社区 */ forum_post: /(bbs.binmt.cc\/thread-|bbs.binmt.cc\/forum.php\?mod=viewthread)/g, /* 帖子链接 */ forum_post_pc: /.*:\/\/bbs.binmt.cc\/thread.*/, /* 帖子链接-PC */ forum_guide_url: /bbs.binmt.cc\/forum.php\?mod=guide/g, /* 导航链接 */ forum_post_reply: /forum.php\?mod=post&action=reply/g, /* 帖子中回复的链接 */ forum_post_page: '&page=(.*)', /* 帖子链接的当前所在页 page */ forum_post_pc_page: 'thread-(.*?)-', /* PC帖子链接的当前所在页 page */ forum_plate_text: /休闲灌水|求助问答|逆向教程|资源共享|综合交流|编程开发|玩机教程|建议反馈/g, /* 各版块名称 */ plate_url: /bbs.binmt.cc\/forum-[0-9]{1,2}-[0-9]{1,2}.html/g, /* 板块链接 */ formhash: /formhash=(.*)&/, /* 论坛账号的凭证 */ font_special: /|<\/font>|||||align=".*?"/g, /* 帖子内特殊字体格式 */ forum_post_guide_url: /bbs.binmt.cc\/page-[1-5].html|bbs.binmt.cc\/forum.php\?mod=guide/g, /* 帖子链接和导航链接 */ mt_uid: /uid=(\d+)/, nologin: /member.php\?mod=logging&action=login(|&mobile=2)/g, /* 未登录 */ pc_useragent: 'Windows', /* pc识别 */ k_misign_sign: "bbs.binmt.cc\/k_misign-sign.html", post_forum: /forum.php\?mod=post&action=newthread/, /* 发布帖子 */ edit_forum: /forum.php\?mod=post&action=edit/, /* 编辑帖子 */ } } /* mt全屏遮罩调用 popup.open(''); 关闭方式 popup.close() */ let utils = { dateStringFormatToStamp(datastring) { let date = datastring; date = date.substring(0, 19); date = date.replace(/-/g, '/'); let timestamp = new Date(date).getTime(); /* let newDate = new Date(timestamp); */ return timestamp; }, timeStringFormatToStamp(timestring) { let today = new Date(); let date = today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate() + " " + timestring; date = date.substring(0, 19); date = date.replace(/-/g, '/'); let timestamp = new Date(date).getTime(); /* let newDate = new Date(timestamp); */ return timestamp }, listCompareDescByValue(propertyName) { /* json根据 字段(int)降序 */ return function (object1, object2) { var value1 = object1[propertyName]; var value2 = object2[propertyName]; if (value2 < value1) { return -1; } else if (value2 > value1) { return 1; } else { return 0; } } }, listCompareAscByValue(propertyName) { /* json根据 字段(int)升 */ return function (object1, object2) { var value1 = object1[propertyName]; var value2 = object2[propertyName]; if (value2 > value1) { /* -1表示前对象小,1表示后对象小,0表示相等 */ return -1; } else if (value2 < value1) { return 1; } else { return 0; } } }, listToStringByValue(_list_, propertyName) { /* json根据 字段(int)合并 */ let content = ""; Array.from(_list_).forEach((item) => { content = content + item[propertyName]; }) return content }, /* 随机数组 */ randomArr(items) { var item = items[Math.floor(Math.random() * items.length)]; return item; }, /* 随机小数点 */ randbix(n, m) { bix = Math.random().toFixed(2); num = Number(utils.randomNum(n, m)) + Number(bix); r2 = utils.randomNum(2, 10); return num.toFixed(r2); }, /* 随机数字 */ randomNum(n, m) { var rander = Math.round(Math.random() * (m - n)) + n; return rander; }, getFormatTime(formatStr) { /* 获取自定义格式化时间, yyyy-MM-dd HH:mm:ss 2022-08-21 23:59:00 */ /** * yyyy 年 * MM 月 * dd 天 * HH 时 (24小时制) * hh 时 (12小时制) * mm 分 * ss 秒 */ function checkTime(i) { if (i < 10) return "0" + i; return i; } function timeSystemChange(_hour_) { /* 时间制修改 24小时制转12小时制 */ return _hour_ > 12 ? _hour_ - 12 : _hour_; } var time = new Date(); var yyyy = time.getFullYear(); /* 获取 年 */ var MM = checkTime(time.getMonth() + 1); /* 获取 月 */ var dd = checkTime(time.getDate()); /* 获取 日 */ var HH = checkTime(time.getHours()); /* 获取 时 (24小时制) */ var hh = checkTime(timeSystemChange(time.getHours())); /* 获取 时 (12小时制) */ var mm = checkTime(time.getMinutes()); /* 获取 分 */ var ss = checkTime(time.getSeconds()); /* 获取 秒 */ /****当时、分、秒、小于10时,则添加0****/ formatStr = formatStr.replace(/yyyy/g, yyyy); formatStr = formatStr.replace(/MM/g, MM); formatStr = formatStr.replace(/dd/g, dd); formatStr = formatStr.replace(/HH/g, HH); formatStr = formatStr.replace(/hh/g, hh); formatStr = formatStr.replace(/mm/g, mm); formatStr = formatStr.replace(/ss/g, ss); return formatStr; }, checkClickInDOM(obj) { /* 检测点击范围是否在该元素区域内 */ var x = Number(window.event.clientX) /* 鼠标相对屏幕横坐标 */ var y = Number(window.event.clientY) /* 鼠标相对屏幕纵坐标 */ var obj_x_left = Number(obj.getBoundingClientRect().left) /* obj相对屏幕的横坐标 */ var obj_x_right = Number( obj.getBoundingClientRect().left + obj.clientWidth ) /* obj相对屏幕的横坐标+width */ var obj_y_bottom = Number( obj.getBoundingClientRect().top + obj.clientHeight ) /* obj相对屏幕的纵坐标+height */ var obj_y_top = Number(obj.getBoundingClientRect().top) /* obj相对屏幕的纵坐标 */ if ((x >= obj_x_left && x <= obj_x_right && y >= obj_y_top && y <= obj_y_bottom) || obj.outerHTML.indexOf(window.event.target.innerHTML) != -1) { return true } else { return false } } } function envCheck() { /* 脚本运行环境修复,兼容部分函数 GM_xmlhttpRequest x浏览器进行了兼容,调用方式为GM.xmlHttpRequest,但会检测是否同源请求,所以不可修改headers */ let checkStatus = true; let isFailedFunction = []; console.log("正在检测脚本环境..."); if (typeof GM_xmlhttpRequest == "undefined") { if (typeof GM != "undefined" && typeof GM.xmlHttpRequest != "undefined") { window.GM_xmlhttpRequest = (param) => { GM.xmlHttpRequest(param); }; console.log("check: %c GM_xmlhttpRequest %c √ 替换成当前环境的GM中", "background:#24272A; color:#ffffff"); } else { isFailedFunction = isFailedFunction.concat("GM_xmlhttpRequest"); console.log(`%c GM_xmlhttpRequest %c 该函数不存在,替换成$.ajax只能同源请求`, "background:#24272A; color:#ffffff", "background:#fff;"); window.GM_xmlhttpRequest = (f) => { console.log(`$jq.ajax请求 url: ${f.url}`); $jq.ajax({ url: f.url, type: f.method, data: f.data, timeout: f.timeout, dataType: f.responseType, success: (r) => { f.onload(r) }, error: (r) => { if (r.status == 200) { f.onload(r) } else { f.onerror(r); } } }) } } } else { console.log("check: %c GM_xmlhttpRequest %c √", "background:#24272A; color:#ffffff", "color:#00a5ff"); } if (typeof $ != 'undefined') { window.$jq = $.noConflict(true); /* 为什么这么写,X浏览器加载jq会替换网页上的jq */ console.log(`check: %c $ %c √ jQuery版本:${$jq.fn.jquery}`, "background:#24272A; color:#ffffff", "color:#00a5ff"); if ($jq.fn.jquery != "3.4.1") { console.log("jQuery加载错误,如果是非油猴加载本脚本方式,请放到网页加载完毕后执行"); return false; } if (typeof $ != 'undefined') { console.log(`检测到网页使用的jQuery版本: %c ${$.fn.jquery}`, "color:#00a5ff"); } } else { checkStatus = false; isFailedFunction = isFailedFunction.concat("GM_xmlhttpRequest"); console.log("check: %c $ %c ×", "background:#24272A; color:#ffffff", "color:#f90000"); } var loadNetworkResource = []; window.GM_asyncLoadScriptContent = (url, replaceStatus) => { /* 异步执行跨域js资源 js */ if (loadNetworkResource.indexOf(url) != -1) { console.log("已加载该js:", url); return } replaceStatus = replaceStatus == null ? true : replaceStatus; return new Promise(res => { GM_xmlhttpRequest({ url: url, method: "GET", async: false, timeout: 10000, onload: (r) => { let execStatus = false; let retText = r.responseText; if (replaceStatus) { retText = retText.replace(/\$/g, "$jq"); retText = retText.replace(/jQuery/g, "$jq"); } try { eval(retText); execStatus = true; loadNetworkResource = loadNetworkResource.concat(url); } catch (error) { console.log("eval执行失败" + error); execStatus = false; } /* try { window.eval(retText); execStatus = true; loadNetworkResource = loadNetworkResource.concat(url); }catch (error) { console.log("window.eval执行失败 " + error); execStatus = false; }*/ res(execStatus); }, onerror: () => { console.log("网络异常,加载JS失败", url); res(false); } }) }) } window.GM_asyncLoadScriptNode = (url) => { return new Promise(res => { let tempNode = document.createElement("script"); tempNode.setAttribute("src", url); document.head.append(tempNode); tempNode.onload = () => { res(); } }) } window.GM_asyncLoadStyleSheet = (url) => { /* 异步添加跨域css资源 */ if (loadNetworkResource.indexOf(url) != -1) { console.log("已加载该css:", url); return } loadNetworkResource = loadNetworkResource.concat(url); let cssNode = document.createElement("link"); cssNode.setAttribute("rel", "stylesheet"); cssNode.setAttribute("href", url); cssNode.setAttribute("type", "text/css"); document.head.append(cssNode); } if (typeof GM_getValue == "undefined") { window.GM_getValue = (key) => { let value = window.localStorage.getItem(key); if (typeof value == "string" && value.trim() != String()) { value = JSON.parse(value); } return value }; console.log("check: %c GM_xmlhttpRequest %c √ 修复", "background:#24272A; color:#ffffff", "color:#00a5ff"); } else { console.log("check: %c GM_getValue %c √", "background:#24272A; color:#ffffff", "color:#00a5ff"); } if (typeof GM_setValue == "undefined") { window.GM_setValue = (key, value) => { window.localStorage.setItem(key, JSON.stringify(value)); }; console.log("check: %c GM_setValue %c √ 修复", "background:#24272A; color:#ffffff", "color:#00a5ff"); } else { console.log("check: %c GM_setValue %c √", "background:#24272A; color:#ffffff", "color:#00a5ff"); } if (typeof GM_deleteValue == "undefined") { window.GM_deleteValue = (key) => { window.localStorage.removeItem(key); }; console.log("check: %c GM_deleteValue %c √ 修复", "background:#24272A; color:#ffffff", "color:#00a5ff"); } else { console.log("check: %c GM_deleteValue %c √", "background:#24272A; color:#ffffff", "color:#00a5ff"); } if (typeof GM_addStyle == "undefined") { window.GM_addStyle = (styleText) => { let cssDOM = document.createElement("style"); cssDOM.setAttribute("type", "text/css"); cssDOM.innerHTML = styleText; document.head.appendChild(cssDOM); return cssDOM; }; console.log("check: %c GM_addStyle %c √ 修复", "background:#24272A; color:#ffffff", "color:#00a5ff"); } else { console.log("check: %c GM_addStyle %c √", "background:#24272A; color:#ffffff", "color:#00a5ff"); } if (typeof GM_setClipboard == "undefined") { window.GM_setClipboard = (text) => { let clipBoardDOM = document.createElement("input"); clipBoardDOM.type = "text"; clipBoardDOM.setAttribute("style", "opacity:0;position:absolute;"); clipBoardDOM.id = "whitesevClipBoardInput"; document.body.append(clipBoardDOM); let clipBoardInputNode = document.getElementById("whitesevClipBoardInput"); clipBoardInputNode.value = text; clipBoardInputNode.removeAttribute("disabled"); clipBoardInputNode.select(); document.execCommand('copy'); clipBoardInputNode.remove(); }; console.log("check: %c GM_setClipboard %c √ 修复", "background:#24272A; color:#ffffff", "color:#00a5ff"); } else { console.log("check: %c GM_setClipboard %c √", "background:#24272A; color:#ffffff", "color:#00a5ff"); } if (typeof unsafeWindow == "undefined") { window.unsafeWindow = window; console.log("check: %c unsafeWindow %c √ 修复", "background:#24272A; color:#ffffff", "color:#00a5ff"); } else { console.log("check: %c unsafeWindow %c √", "background:#24272A; color:#ffffff", "color:#00a5ff"); } if (checkStatus) { console.log(`脚本环境检测结果: 通过`); } else { let isFailedStr = ""; Array.from(isFailedFunction).forEach(item => { isFailedStr += (item + "、"); }) isFailedStr = isFailedStr.replace(/、$/, '') console.log(`脚本环境检测结果: ${isFailedStr}失败`); } return checkStatus; } async function loadCheckboxTipResource() { /* 加载checkbox值变化的显示的提示的资源 */ await GM_asyncLoadScriptContent("https://whitesev.gitee.io/static_resource/ios_loading/js/iosOverlay.js"); await GM_asyncLoadStyleSheet("https://whitesev.gitee.io/static_resource/ios_loading/css/iosOverlay.css"); } async function repairPCNoLoadResource() { /* 修复电脑版未加载的js资源 */ await GM_asyncLoadScriptNode("https://cdn-bbs.mt2.cn/static/js/smilies.js?x6L", false); await GM_asyncLoadScriptNode("https://cdn-bbs.mt2.cn/static/js/common.js?hsy", false); } function latestReleaseForumPost() { /* 最新发表 */ var latestReleaseNode = $jq(`
  • 最新发表
  • `); $jq("#comiis_nv .wp.comiis_nvbox.cl ul").append(latestReleaseNode); if (window.location.href == "https://bbs.binmt.cc/forum.php?mod=guide&view=newthread") { $jq("#mn_forum_10").removeClass("a"); latestReleaseNode.find("a").css("background", 'url("https://cdn-bbs.mt2.cn/template/comiis_mi/img/nv_a.png") repeat-x 50% -50px'); } } function removeForumPostFontStyle() { /* 移除帖子内的字体style */ if (GM_getValue("v1") && window.location.href.match(mt_config.rexp.forum_post)) { $jq(".comiis_a.comiis_message_table.cl").eq(0).html($jq(".comiis_a.comiis_message_table.cl").eq(0).html().replace(mt_config.rexp.font_special, '')); } } function autoSignIn() { /* mt签到 */ function getFormHash() { /* 获取账号的formhash */ return document.querySelector("input[name=formhash]") ? document.querySelector("input[name=formhash]").value : document.querySelector("div[class=sidenv_exit]>a").href.match(mt_config.rexp.formhash)[1]; } function signIn(_formhash_) { /* 签到 */ console.log("发送签到请求"); $jq.get("/k_misign-sign.html?operation=qiandao&format=button&formhash=" + _formhash_ + "&inajax=1&ajaxtarget=midaben_sign", function (data, status) { console.log(data); /* 没签到的签到完了这是空白的 */ GM_setValue("mt_sign", parseInt(utils.getFormatTime("yyyyMMdd"))); function danmurun(run_time) { /* 弹幕 */ function randDanmu() { let icon = utils.randomArr(['', 's', 'e', 'w', 'a', 'h', 'https://cdn-bbs.mt2.cn/template/comiis_app/comiis/img/favicon.ico']); let type = utils.randomArr(['w', 'b']); let randTip = utils.randomArr(["已签到", "请刷新", "不要呆着了", "快点滴", "手机要爆炸了", "麻溜的", "说的就是你", "看什么看", "懂不懂自动签到的含金量啊", "别迷恋哥,哥只是个传说", "你不懂自动签到的含金量", "花会枯萎,自动签到永不凋零"]); xtip.danmu(randTip, { icon: icon, type: type, }); } return setInterval(function () { randDanmu(); }, run_time); } if (typeof data == "string") { var intervalId = danmurun(450); setTimeout(function () { /* 10秒后关闭 */ clearInterval(intervalId); }, 50000); return; }; let signInContent = data.lastChild.firstChild.nodeValue; if (signInContent.indexOf("您已经被列入黑名单") != -1) { popup.open("签到: 您已经被列入黑名单", "alert"); return } if (signInContent.indexOf("今日已签" != -1)) { popup.open("签到: 今日已签", "alert"); return } }); } if (!GM_getValue("v17")) { return; } if ((document.querySelector("div[class=comiis_dlq]>a") != null) || (document.getElementsByClassName("sidenv_user")[0].href.match(mt_config.rexp.nologin) != null)) { console.log("当前账号尚未登录"); popup.open("当前账号尚未登录", "alert"); return; } let formhash = getFormHash(); if (formhash == null) { console.log("获取账号formhash失败"); popup.open("获取账号formhash失败", "alert"); return; } if (utils.getFormatTime("HH") == "23" && parseInt(utils.getFormatTime("mm")) >= 55) { /* 倒计时开启 */ console.log("开启倒计时自动签到"); let intervalId = setInterval(() => { let current_time = utils.getFormatTime("HH:mm:ss"); if (utils.getFormatTime("hh:mm") == "00:00") { signIn(formhash); clearInterval(intervalId); } else { popup.open(`倒计时: ${current_time}`, "alert"); } }, 1000); return; } if (GM_getValue("mt_sign") == parseInt(utils.getFormatTime("yyyyMMdd"))) { return; } else { signIn(formhash); } } function searchHistory() { /* 搜索历史 */ if (GM_getValue("v19") && location.href.match(mt_config.rexp.search_url)) { function search_event() { /* 搜索历史事件 */ /* 搜索界面增加关闭按钮事件,清空input内容 */ /* 点击搜索保存搜索记录 */ $jq("#scform_submit").click(function () { let getsearchtext = $jq("#scform_srchtxt").val(); if ((getsearchtext != null) && (getsearchtext != "")) { let search_history_array = new Array(getsearchtext); let has_history = GM_getValue("search_history"); if (has_history != null) { if ($jq.inArray(getsearchtext, has_history) != -1) { console.log("已有该搜索历史记录") search_history_array = has_history } else { console.log("无该记录,追加"); search_history_array = search_history_array.concat(has_history); } } else { console.log("空记录,添加") } GM_setValue("search_history", search_history_array); } }) } function add_search_history() { /* 搜索界面添加搜索历史记录 */ $jq("#scform_srchtxt").attr("list", "search_history"); var search_history_list = GM_getValue("search_history"); var dom_datalist = document.createElement("datalist"); dom_datalist.id = "search_history"; var option_text = ""; if (search_history_list) { for (var i = 0; i < search_history_list.length; i++) { option_text = option_text + '