// ==UserScript== // @name MCBBS Extender // @namespace https://i.zapic.cc // @version release-1.1.0 // @description MCBBS行为拓展/样式修复 // @author Zapic // @match https://*.mcbbs.net/* // @run-at document-body // @downloadURL none // ==/UserScript== (() => { // jQuery检查 if (typeof jQuery == "undefined") { console.error("This page does NOT contain JQuery,MCBBS Extender will not work."); return false; } // 基本信息初始化 let version = "v1.1.0"; let vercode = 111140; let updatelist = [ '1.新增 查看警告功能,在每个楼层或者个人主页都会添加查看警告记录按钮.', '2.重写了代码,插入了关键注释,可能会有严重的Bug,如发现请及时向Zapic反馈' ]; let configableList = [{ "id": "fixCodeBlock", "default": true, "type": "check", "name": "美化代码块样式", "desc": "修正代码块的一些样式,如滚动条." }, { "id": "fixCodeCopy", "default": true, "type": "check", "name": "\"复制代码\"修复", "desc": "修复复制代码时换行全部消失的问题." }, { "id": "fixTableLayout", "default": true, "type": "check", "name": "修复表格样式", "desc": "使用快捷键Shift+F快速修复当前页面表格样式." }, { "id": "queryMessage", "default": true, "type": "check", "name": "后台轮询消息", "desc": "在后台自动查询是否有新的消息并推送,需保证至少打开一个页面." }, { "id": "queryMessageInterval", "default": 60, "type": "num", "name": "后台轮询消息间隔", "desc": "两次轮询消息之间的间隔,单位秒." }, { "id": "rememberPage", "default": true, "type": "check", "name": "板块内翻页记忆", "desc": "点击板块内下一页按钮时记忆当前页." }, { "id": "animateGoToTopButton", "default": true, "name": "回到顶部按钮美化", "type": "check", "desc": "为右侧回到顶部按钮增加动画以及位置修正." }, { "id": "pinnedTopBar", "default": true, "name": "固定顶栏", "type": "check", "desc": "将顶栏固定到页面顶部,不随页面滚动." }, { "id": "fixTopBarPopMenu", "default": true, "type": "check", "name": "弹出菜单美化", "desc": "美化弹出菜单的样式,如个人信息菜单." }, { "id": "hoverPreviewTheme", "default": true, "name": "主题悬浮预览", "type": "check", "desc": "将鼠标指针放在切换主题按钮上即可预览主题." }, { "id": "hoverableMedal", "default": true, "name": "玻璃质感勋章", "type": "check", "desc": "亮闪闪的勋章~" }, { "id": "ljyysSearch", "default": true, "name": "ljyys搜索", "type": "check", "desc": "使用站外搜索代替站内搜索,绕过搜索限制,降低论坛负载,提高搜索效率." }, { "id": "quickAtList", "default": "", "name": "快速 @ 列表", "type": "text", "desc": "按下Ctrl+Shift+A以快速在当前输入框内插入预定义的@用户名代码.用户名之间用\",\"(半角逗号)分隔." }, { "id": "viewWarns", "default": true, "name": "查看警告记录", "type": "check", "desc": "为每一层楼和每一个个人主页(除自己)添加查看警告记录按钮" }]; //初始化jQuery和基本封装方法 let $ = jQuery; let dlg = (m) => { console.debug("[MCBBS Extender]" + m); }; //配置初始化 let initConfig = () => { $(configableList).each((i, v) => { conf[v.id] = typeof conf[v.id] == "undefined" ? v.default : conf[v.id]; }); setcookie("MExt_config", JSON.stringify(conf), 2147483647); } let conf = ''; try { conf = JSON.parse(getcookie("MExt_config")); } catch (e) { dlg("Failed to load config\n" + e); } if (!conf) { conf = {}; conf.version = vercode; initConfig(); showDialog("欢迎使用MCBBS Extender.
本脚本的设置按钮已经放进入了您的个人信息菜单里,如需调整设置请在个人信息菜单里寻找.", "right", "欢迎", () => { showMenu('user_info'); $("#MExt_config").css("background-color", "#E91E63").css("color", "#fff"); setTimeout(() => { hideMenu('user_info_menu'); $("#MExt_config").css("background-color", "").css("color", ""); }, 3000); }); dlg("Config init."); } if (typeof conf.version == "undefined" || conf.version < vercode) { let updateContent = ''; $(updatelist).each((i, v) => { updateContent += "
" + v; }); showDialog("MCBBS Extender 已经更新至 " + version + "" + updateContent, "right"); conf.version = vercode; initConfig(); } $(() => { // 设置界面初始化 $("#user_info_menu .user_info_menu_btn").append("
  • MCBBS Extender 设置
  • "); dlg("Appended Config button"); $("head").append(''); dlg("Appended Config window style"); $("#MExt_config").on("click", () => { let confwinContent = '
    '; $(configableList).each((i, v) => { let inputType = ''; switch (v.type) { case "check": inputType = ''; break; case "num": inputType = ''; break; case "text": inputType = ''; break; default: inputType = ''; break; } confwinContent += '

    ' + v.name + '
    ' + v.desc + '' + inputType + '

    '; }); confwinContent += '
    '; showDialog( confwinContent, "confirm", "MCBBS Extender 设置", () => { $(configableList).each((i, v) => { let val = ''; if (v.type == "num" || v.type == "text") { val = $("#in_" + v.id).val(); } else { val = $("#in_" + v.id).prop("checked"); } conf[v.id] = val; }); initConfig(); setTimeout(() => { showDialog("设置已保存,刷新生效", "right"); }); }, true, () => {}, "MCBBS Extender " + version + " - 世予可爱w" ); $(configableList).each((i, v) => { if (v.type == "num" || v.type == "text") { $("#in_" + v.id).val(conf[v.id]); } else { $("#in_" + v.id).prop("checked", conf[v.id]); } }); dlg("Config cookie loaded."); }); dlg("Config button event attached."); // 钩住DiscuzAjax函数,使其触发全局事件 let __ajaxpost = ajaxpost; ajaxpost = (formid, showid, waitid, showidclass, submitbtn, recall) => { let relfunc = () => { if (typeof recall == 'function') { recall(); } else { eval(recall); } $(this).trigger('DiscuzAjaxPostFinished'); } __ajaxpost(formid, showid, waitid, showidclass, submitbtn, relfunc); } let __ajaxget = ajaxget; ajaxget = (url, showid, waitid, loading, display, recall) => { let relfunc = () => { if (typeof recall == 'function') { recall(); } else { eval(recall); } $(this).trigger('DiscuzAjaxGetFinished'); } __ajaxget(url, showid, waitid, loading, display, relfunc); } dlg("Hooked into Discuz Ajax event"); }); if (conf.fixCodeBlock) { // 代码块美化样式 $("head").append(""); dlg("Code block fix style appended."); } if (conf.fixTableLayout) { // 监听快捷键事件 $(document).on("keydown", (e) => { if (e.shiftKey && e.keyCode == 70 && $("#fixTableLayout").length == 0) { dlg("Table layout fix actived"); showDialog("是否尝试修复此页表格?", "confirm", "MCBBS Extender", () => { // 添加修复样式 $("head").append(""); }) } }); dlg("Table layout fix event attached."); } if (conf.fixCodeCopy) { // 重写copycode函数,手动添加换行 copycode = (obj) => { if (!obj) { dlg("Code copy with invalid object."); return false; } let code = ''; $(obj).find("li").each((i, v) => { code += v.innerText + "\r\n"; }); // 复制代码 setCopy(code, '代码已复制到剪贴板'); dlg("Code copied."); }; dlg("Code copy fix actived."); } // 垃圾代码,下个版本重写 if (conf.queryMessage) { let getRequest = function (variable) { let query = window.location.search.substring(1); let vars = query.split("&"); for (let i = 0; i < vars.length; i++) { let pair = vars[i].split("="); if (pair[0] == variable) { return pair[1]; } } return (false); } if (location.pathname == "/home.php") { let action = getRequest('do'); if (action == "pm" || action == "notice") { $.getJSON("/api/mobile/index.php?module=profile", (data) => { setcookie("MExt_LastNoticeContent", JSON.stringify(data.Variables.notice), 0); dlg("Recived msg,flush cache."); }); } } else if (new Date().getTime() - localStorage.getItem("notifica-time") > 200000) { $.getJSON("/api/mobile/index.php?module=profile", (data) => { setcookie("MExt_LastNoticeContent", JSON.stringify(data.Variables.notice), 0); dlg("Last notice is 200s or more ago,flush cache."); }); } var queryId = hash(new Date().getTime().toLocaleString(), 16); dlg("Query id is " + queryId + "."); if (!window.Html5notification) { $.getScript("data/cache/html5notification.js?xm6"); dlg("Html5notification added."); } setInterval(() => { if (getcookie("MExt_LastQuery") == "") { setcookie("MExt_LastQuery", 0, 0); } var nowtime = Math.floor(new Date().getTime() / 1000); if ((getcookie("MExt_ActiveQueryId") == "" || nowtime - getcookie("MExt_LastQuery") > 5) && getcookie("MExt_ActiveQueryId") != queryId) { setcookie("MExt_ActiveQueryId", queryId, 0); dlg("Kick off inactive querier,start query."); } if (getcookie("MExt_ActiveQueryId") == queryId) { setcookie("MExt_LastQuery", nowtime, 0); } }, 1000); dlg("Running checker actived."); setInterval(() => { dlg("Start to check message."); localStorage.setItem('notifica-time', new Date().getTime()); $.getJSON("/api/mobile/index.php?module=profile", (data) => { var notices = data.Variables.notice; var noticecontent = JSON.stringify(notices); $.get("/forum.php?mod=misc", (d) => { var dom = $(d); var ut = dom.find(".user_tools"); var pum = dom.filter("#myprompt_menu"); $(".user_tools").html(ut.html()); $("#myprompt_menu").html(pum.html()); $("title").text(NOTICECURTITLE); var s = dom.filter("script[src*=html5notification]").nextUntil("div").last().text(); if (getcookie("MExt_ActiveQueryId") == queryId && noticecontent != getcookie("MExt_LastNoticeContent")) { localStorage.setItem('notifica-time', 1); eval(s); dlg("Notification sent."); } setcookie("MExt_LastNoticeContent", noticecontent, 0); }); }); }, conf.queryMessageInterval * 1000); dlg("Message querier actived."); } if (conf.rememberPage) { // 记住当前页 $(() => { let npbtn = $("#autobtn"); if(npbtn.length){ let orgfunc = npbtn[0].onclick; npbtn.on("click",()=>{ let nextpageurl = npbtn.prop('rel'); let curpage = parseInt(npbtn.prop('curpage')); npbtn.prop('curpage', curpage + 1); nextpageurl = nextpageurl.replace(/&page=\d+/, '&page=' + (curpage + 1)); history.replaceState(null, null, nextpageurl); orgfunc(); }); } dlg("Page remember actived."); }); } if (conf.animateGoToTopButton) { // 添加侧边按钮样式 $("head").append(""); dlg("Animate go to top buttom style appended."); // 重写showTopLink函数,使其使用侧边栏样式 showTopLink = () => { let ft = $('#ft')[0]; if (ft) { let scrolltop = $('#scrolltop')[0]; if (!scrolltop) { return false; } let scrolltopbtn = $(".scrolltopa"); let scrollHeight = parseInt(document.body.getBoundingClientRect().top); let basew = parseInt(ft.clientWidth); let sw = scrolltop.clientWidth; if (basew < 1000) { let left = parseInt(fetchOffset(ft)['left']); left = left < sw ? left * 2 - sw : left; scrolltop.style.left = (basew + left + 44) + 'px'; } else { scrolltop.style.left = 'auto'; scrolltop.style.right = 0; } if (scrollHeight < -100) { scrolltopbtn.addClass("scrolltopashow"); } else { scrolltopbtn.removeClass("scrolltopashow"); } } } showTopLink(); dlg("Animate go to top buttom actived."); } if (conf.pinnedTopBar) { // 添加固定顶栏样式 $("head").append(""); $(() => { // 重写editorcontrolpos函数,与固定顶栏兼容 editorcontrolpos = () => { if (editorisfull) { return; } var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop); if (scrollTop + 47 > editorcontroltop && editorcurrentheight > editorminheight) { $("#" + editorid + '_controls').prop("style", "z-index:0!important").css("position", 'fixed').css("top", '47px').css("width", editorcontrolwidth + 'px'); $("#" + editorid + '_controls_mask').css("display", ''); } else { $("#" + editorid + '_controls').css("position", '').css('top', '').css('width', ''); $("#" + editorid + '_controls_mask').css('display', 'none'); } } }); dlg("Pinned top bar style appended."); } if (conf.fixTopBarPopMenu) { // 添加弹出菜单美化样式 $("head").append(""); dlg("Pop menu fix style appended."); // 重写extstyle函数,使更换主题时同步更新样式 let __extstyle = extstyle; let checkStyle = () => { let theme = getcookie('extstyle'); if (theme == "./template/mcbbs/style/winter") { if (!$("#fixTopBarPopMenuWinter").length) { $("head").append(""); } } else { $("#fixTopBarPopMenuWinter").remove(); } } extstyle = (style) => { __extstyle(style); checkStyle(); } checkStyle(); dlg("Overwrite extstyle function"); } if (conf.hoverPreviewTheme) { //悬浮预览主题 $(() => { $(".sslct_btn").on("mouseenter", function () { let that = this; let timer = setTimeout(function () { clearTimeout(timer); var previewstyle = getcookie('extstyle'); $(that).trigger('click'); setcookie('extstyle', previewstyle); }, 300); }); $(".sslct_btn").on("mouseleave", () => { extstyle(getcookie('extstyle')); }); dlg("Hover preview theme event attached."); }); } if (conf.hoverableMedal) { // 重写勋章结构函数 let rewriteMedal = () => { // 遍历所有未重写楼层 $('.md_ctrl:not([glassmedal])').attr("glassmedal", "true").each((t, v) => { // 遍历楼层所有勋章 $(v).children(0).children('img').each((b, n) => { // 获得勋章ID let id = 'md' + /\_\d*$/.exec($(n).attr('id'))[0]; // 重写勋章结构 $(v).append( $('
    ').on('mouseover', () => { showMenu({ 'ctrlid': $(n).attr('id'), 'menuid': id + '_menu', 'pos': '12!' }); }) ); // 重写提示样式 $("#" + id + "_menu .tip_horn").css("background-image", "url(" + $(n).attr('src') + ")"); // 移除旧的勋章 $(n).remove(); }); }); dlg("Hoverable medal rewrote."); }; //调用重写勋章函数 $(rewriteMedal); // 在Ajax时重新调用Ajax函数,保存勋章样式 $(this).on("DiscuzAjaxGetFinished", rewriteMedal).on("DiscuzAjaxPostFinished", rewriteMedal); // 添加勋章样式 $("head").append(""); dlg("Hoverable medal style appended."); } if (conf.ljyysSearch) { // ljyys serach $(() => { $("#scbar_form [type*=hidden]").remove(); $("#scbar_txt").attr("name", "search").css("background-color", "#00000000"); $(".scbar_type_td").html("ljyys搜索").css("background", "url(https://www.mcbbs.net/template/mcbbs/image/scbar_txt.png) -94px center no-repeat").css("width", "62px").css("cursor", "pointer"); $("#scbar_form").attr("method", "get").attr("action", "//search.ljyys.xyz/search.php"); dlg("ljyys search actived"); }); } if (conf.quickAtList) { // 获得At代码函数 let getAtCode = () => { // 分隔list let quickAtList = conf.quickAtList.split(","); let atstr = ""; //拼接@代码 $(quickAtList).each((i, v) => { atstr += "@" + v + " "; }); return atstr; } // 监听按键事件 $(document).on("keydown", (e) => { if (e.shiftKey && e.ctrlKey && e.keyCode == 65) { // 判断是否在输入框内 if (($(document.activeElement).prop("nodeName") == "INPUT" && $(document.activeElement).prop("type") == "text")) { // 拼接方法插入 $(document.activeElement).val($(document.activeElement).val() + getAtCode()); dlg("@ string added"); } else if ($(document.activeElement).prop("nodeName") == "TEXTAREA") { // discuz内建函数插入 seditor_insertunit('fastpost', '', getAtCode()); dlg("@ string added"); } } }); // 高级编辑模式插入@代码 $(() => { if ($("#e_iframe").length) { // 由于高级模式的输入框是iFrame,无法直接监听,故再次监听高级输入框的按键事件 $($("#e_iframe")[0].contentWindow).on("keydown", (e) => { if (e.shiftKey && e.ctrlKey && e.keyCode == 65) { // 判断是否在输入框内 if ($(document.activeElement).prop("nodeName") == "IFRAME") { //discuz内建函数插入 insertText(getAtCode()); dlg("@ string added"); } } }); } }); } if (conf.viewWarns) { // 添加查看警告样式 $("head").append(""); // 添加查看警告按钮函数 let addVWLink = () => { $(".plhin").each((i, v) => { let href = $(v).find(".authi .xw1").attr("href"); if (!href) { return false; } let uid = /uid=(\d*)/.exec(href)[1]; $(v).find("ul.xl.xl2.o.cl:not([vw_added*=true])").attr("vw_added", "true").append($('
  • 查看警告记录
  • ')); }); dlg("In-posts view warns link added"); } // 在DiscuzAjax时重新调用添加函数,防止失效 $(this).on("DiscuzAjaxGetFinished", addVWLink).on("DiscuzAjaxPostFinished", addVWLink); dlg("adddVWLink Ajax Event attached."); $(() => { // 添加查看警告按钮 addVWLink(); // 用户信息界面添加查看警告按钮 let href = $("#uhd .cl a").attr("href"); if (!href) { return false; } let uid = /uid=(\d*)/.exec(href)[1]; if (!uid) { return false; } $("#uhd .mn ul").append('
  • 查看警告记录
  • '); dlg("Home page view warns link added.") }); } })();