您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
一款可以帮助您在洛谷轻松发送 QQ 表情信息的插件.
// ==UserScript== // @name LuoguEmojiSender // @namespace https://github.com/Maxmilite/LuoguEmojiSender // @version 1.4.4 // @description 一款可以帮助您在洛谷轻松发送 QQ 表情信息的插件. // @author Maxmilite // @match https://www.luogu.com.cn/* // @match http://www.luogu.com.cn/* // @grant unsafeWindow // @require https://code.jquery.com/jquery-2.1.1.min.js // ==/UserScript== (function () { // 这是第一代 LuoguEmojiSender 的最终版本,内容已经相当完善,此后作者将会着力于第二代的开发,第一代基本不会更新。 // 最后更新时间 2021.6.14 // 最后版本 1.4.4 // 第二代目标:实现图形化,近似于 QQ 发送表情 // 作者在这个版本留下了一个臭了的彩蛋 // 1.1 更新内容: // 优化操作逻辑,增加用户配置区 // 1.2 更新内容: // 增加了更多的 QQ 图片,更改了图床 // 1.3 更新内容: // 进一步优化操作逻辑,修复了图片加载的一个BUG,现在可以无忧无虑使用无缝模式了 // 1.3.1 更新内容: // 紧急修复一个由菜刀表情引发的严重BUG // 1.4 更新内容: // 修复了 1.3.1 版本更新日志版本号的bug,修复输入问题,第一代最终版本 // 修复光标漂移问题,修复无缝衔接问题,修复菜刀表情问题,修复若干问题 // 1.4.1 更新内容: // 更换表情源,增加 “替换表情” 按钮,具体详见说明文档 // 1.4.2 更新内容: // 修复一个无缝模式的 bug,添加了部分表情 // 1.4.3 更新内容: // 增加了一个开关自动替换按钮,现在您可以自行决定是否自动替换文中内容了,修复了一个bug,更新了雀魂表情库 // 1.4.4 更新内容: // 增加设置菜单,现在允许对插件进行有关设置了,所有设置将会保存在本地,不会因为版本更新而丢失;增加快速查询表情按钮 var functionIsOn = true, seamlessMode = false, queryIsOn = true; var prefix = "{", suffix = "}"; var userElement = { "样例1": "XXX1.com", "样例2": "XXX2.com", "样例3": "XXX3.com", "样例4": "XXX4.com" }; const replaceElement = { "/ybyb": "", "/wosl": "", "/hs": "", "/psj": "", "/na": "", "/bx": "", "/qdqd": "", "/zy": "", "/nqct": "", "/nzqk": "", "/mjl": "", "/gun": "", "/cb": "", "/my": "", "/mwbq": "", "/kx": "", "/jl": "", "/wyx": "", "/ww": "", "/mdfq": "", "/banzz": "", "/mgx": "", // ----------------- 以上为 1.4.2 更新内容 ----------------- "/aini": "", "/aiq": "", "/am": "", "/azgc": "", "/baiy": "", "/bangbangt": "", "/baojin": "", "/bb": "", "/bkx": "", "/bl": "", "/bobo": "", "/bp": "", "/bq": "", "/bs": "", "/bt": "", "/bu": "", "/bz": "", // "/cd": "", "/cengyiceng": "", "/cg": "", "/ch": "", "/chi": "", "/cj": "", "/cp": "", "/cs": "", "/cy": "", "/dan": "", "/dao": "", "/db": "", "/dg": "", "/dgg": "", "/dk": "", "/dl": "", "/doge": "", "/dx": "", "/dy": "", "/dz": "", "/ee": "", "/emm": "", "/fad": "", "/fade": "", "/fan": "", "/fd": "", "/fendou": "", "/fj": "", "/fn": "", "/fw": "", "/gg": "", "/gy": "", "/gz": "", "/hanx": "", "/haob": "", "/hb": "", "/hc": "", "/hd": "", "/hec": "", "/hhd": "", "/hn": "", "/hp": "", "/hq": "", "/hsh": "", "/ht": "", "/huaix": "", "/hx": "", "/jd": "", "/jh": "", "/jiaybb": "", "/jiaybs": "", "/jie": "", "/jk": "", "/jw": "", "/jx": "", "/jy": "", "/ka": "", "/kb": "", "/kel": "", "/kf": "", "/kg": "", "/kk": "", "/kl": "", "/kt": "", "/kuk": "", "/kun": "", "/kzht": "", "/lb": "", "/lengh": "", "/lh": "", "/ll": "", "/lm": "", "/lq": "", "/lw": "", "/lyj": "", "/meigui": "", "/mm": "", "/ng": "", "/nkt": "", "/oh": "", "/oy": "", "/pch": "", "/pj": "", "/pp": "", "/pt": "", "/px": "", "/qd": "", "/qiang": "", "/qiao": "", "/qq": "", "/qt": "", "/ruo": "", "/sa": "", "/se": "", "/sh": "", "/shd": "", "/shl": "", "/shuai": "", "/shui": "", "/shxi": "", "/sr": "", "/tiao": "", "/tl": "", "/tnl": "", "/tp": "", "/ts": "", "/tsh": "", "/tt": "", "/tuu": "", "/tx": "", "/taiyang": "", "/tyt": "", "/wbk": "", "/whl": "", "/wl": "", "/wn": "", "/wq": "", "/ws": "", "/wul": "", "/wx": "", "/wzm": "", "/xhx": "", "/xia": "", "/xig": "", "/xin": "", "/xjj": "", "/xk": "", "/xs": "", "/xu": "", "/xw": "", "/xy": "", "/xyx": "", "/yao": "", "/yb": "", "/yhh": "", "/yiw": "", "/yl": "", "/youl": "", "/youtj": "", "/yt": "", "/yun": "", "/yx": "", "/zhd": "", "/zhem": "", "/zhh": "", "/zhm": "", "/zhq": "", "/zj": "", "/zk": "", "/zq": "", "/zt": "", "/zuotj": "", "/114514": "[](https://github.com/Maxmilite/LuoguEmojiSender)", "/maj-1!": "", "/maj-2!": "", "/maj-3!": "", "/maj-4!": "", "/maj-5!": "", "/maj-6!": "", "/maj-7!": "", "/maj-8!": "", "/maj-9!": "", "/maj-10!": "", "/maj-11!": "", "/maj-12!": "", "/maj-13!": "", "/maj-14!": "", "/maj-15!": "", "/maj-16!": "", "/maj-17!": "", "/maj-18!": "", "/maj-19!": "", "/maj-20!": "", "/maj-21!": "", "/maj-22!": "", "/maj-23!": "", "/maj-24!": "", "/maj-25!": "", "/maj-26!": "", "/maj-27!": "", "/maj-28!": "", "/maj-29!": "", "/maj-30!": "", "/maj-31!": "", "/maj-32!": "", "/maj-33!": "", "/maj-34!": "", "/maj-35!": "", "/maj-36!": "", "/maj-37!": "", "/maj-38!": "", "/maj-39!": "", "/maj-40!": "", "/maj-41!": "", "/maj-42!": "", "/maj-43!": "", "/maj-44!": "", "/maj-45!": "", "/maj-46!": "", "/maj-47!": "", "/maj-48!": "", "/maj-49!": "", "/maj-50!": "", "/maj-51!": "", "/maj-52!": "", "/maj-53!": "", "/maj-54!": "", "/maj-55!": "", "/maj-56!": "", "/maj-57!": "", "/maj-58!": "", "/maj-59!": "", "/maj-60!": "", "/maj-61!": "", "/maj-62!": "", "/maj-63!": "", "/maj-64!": "", "/maj-65!": "", "/maj-66!": "", "/maj-67!": "", "/maj-68!": "", "/maj-69!": "", "/maj-70!": "", "/maj-71!": "", "/maj-72!": "", "/maj-73!": "", "/maj-74!": "", "/maj-75!": "", "/maj-76!": "", "/maj-77!": "", "/maj-78!": "", "/maj-79!": "", "/maj-80!": "", "/maj-81!": "", "/maj-82!": "", "/maj-83!": "", "/maj-84!": "", "/maj-85!": "", "/maj-86!": "", "/maj-87!": "", "/maj-88!": "", "/maj-89!": "", "/maj-90!": "", "/maj-91!": "", "/maj-92!": "", "/maj-93!": "", "/maj-94!": "", "/maj-95!": "", "/maj-96!": "", "/maj-97!": "", "/maj-98!": "" }; const $ = unsafeWindow.$ || jQuery, markdownPalettes = unsafeWindow.markdownPalettes; function ShowTip(tip, type) { var $tip = $('#tip'); if ($tip.length == 0) { $tip = $('<span id="tip" style="position:fixed; top:50px; left: 50%; z-index:9999; height: 35px; padding: 0 20px; line-height: 35px; background-color: white; border: 5px; opacity: 75%"></span>'); $('body').append($tip); } $tip.stop(true).prop('class', 'alert alert-' + type).text(tip).css('margin-left', -$tip.outerWidth() / 2).fadeIn(250).delay(500).fadeOut(250); } function ShowMsg(msg) { ShowTip(msg, 'info'); } function ShowSuccess(msg) { ShowTip(msg, 'success'); } function ShowFailure(msg) { ShowTip(msg, 'danger'); } function ShowWarn(msg, $focus, clear) { ShowTip(msg, 'warning'); if ($focus) { $focus.focus(); if (clear) $focus.val(''); } return false; } function getSubString(sourceString = "", findPos = -1) { if (findPos == -1) { return "zr.tk"; } if (findPos <= 5) { return ""; } let resultString = ""; for (let i = findPos - 5; i < findPos; i++) { resultString += sourceString[i]; } // if (resultString == "tps:/") { // return "9zr.tk"; // } return resultString; } function sliceString(sourceString = "", leftSide = 0, rightSide = 0) { let resultString = "" for (let i = leftSide; i <= rightSide; i++) { resultString += sourceString[i]; } return resultString; } function replaceString(stringToChange = "") { let isChanged = false; for (let i in replaceElement) { let changedStr = prefix + i + suffix; while (getSubString(stringToChange, stringToChange.lastIndexOf(changedStr)) != "zr.tk" && getSubString(stringToChange, stringToChange.lastIndexOf(changedStr)) != "jsoul") { // console.log(getSubString(stringToChange, stringToChange.lastIndexOf(changedStr))) isChanged = true; // stringToChange = stringToChange.replace(changedStr, replaceElement[i]); stringToChange = sliceString(stringToChange, 0, stringToChange.lastIndexOf(changedStr) - 1) + replaceElement[i] + sliceString(stringToChange, stringToChange.lastIndexOf(changedStr) + changedStr.length, stringToChange.length - 1); } } for (let i in userElement) { let changedStr = prefix + i + suffix; while (getSubString(stringToChange, stringToChange.lastIndexOf(changedStr)) != "zr.tk" && getSubString(stringToChange, stringToChange.lastIndexOf(changedStr)) != "jsoul") { isChanged = true; // stringToChange = stringToChange.replace(changedStr, userElement[i]); stringToChange = sliceString(stringToChange, 0, stringToChange.lastIndexOf(changedStr) - 1) + userElement[i] + sliceString(stringToChange, stringToChange.lastIndexOf(changedStr) + changedStr.length, stringToChange.length - 1); } } if (isChanged == true) { return stringToChange; } else { return undefined; } } function main() { if (functionIsOn == false) { return; } if (typeof markdownPalettes != "undefined") { let changedStr = replaceString($(".CodeMirror-wrap textarea").val()); if (changedStr != undefined) { $(".CodeMirror-wrap textarea").val(changedStr); $(".CodeMirror-wrap textarea").trigger("input"); } } if (document.getElementById("feed-content") != null) { let changedStr = replaceString(document.getElementById("feed-content").value); if (changedStr != undefined) { document.getElementById("feed-content").value = changedStr; } } } function replaceAll() { if (replaceString(markdownPalettes.content) != undefined) { markdownPalettes.content = replaceString(markdownPalettes.content); ShowSuccess("文中所有表情已手动替换"); return; } else { return; } } function writeConfig() { lsSet("LuoguEmojiSenderPrefix", prefix); lsSet("LuoguEmojiSenderSuffix", suffix); lsSet("LuoguEmojiSenderIsOn", JSON.stringify(functionIsOn)); lsSet("LuoguEmojiSenderIsSeamless", JSON.stringify(seamlessMode)); lsSet("LuoguEmojiSenderQueryIsOn", JSON.stringify(queryIsOn)); lsSet("LuoguEmojiSenderUserElements", JSON.stringify(userElement, null, 4)); } function readConfig() { prefix = lsGet("LuoguEmojiSenderPrefix"); suffix = lsGet("LuoguEmojiSenderSuffix"); functionIsOn = JSON.parse(lsGet("LuoguEmojiSenderIsOn")); seamlessMode = JSON.parse(lsGet("LuoguEmojiSenderIsSeamless")); queryIsOn = JSON.parse(lsGet("LuoguEmojiSenderQueryIsOn")); if (seamlessMode == true) { prefix = "", suffix = ""; } userElement = JSON.parse(lsGet("LuoguEmojiSenderUserElements")); } function lsGet(x = "") { return unsafeWindow.localStorage.getItem(x); } function lsSet(x = "", content = "") { unsafeWindow.localStorage.setItem(x, content); } var setting = new Object; setting.openSetting = function () { $("#lesSettingDiv").slideToggle(); if (seamlessMode == true) { document.getElementsByName("seamless")[0].click(); } else { document.getElementsByName("seamless")[1].click(); } if (queryIsOn == true) { document.getElementsByName("query")[0].click(); } else { document.getElementsByName("query")[1].click(); } } setting.cancelSetting = function () { if (confirm("当前设置未保存,确认取消?") == true) { location.reload(); } } setting.saveSetting = function () { if (confirm("确认保存当前设置?") == true) { seamlessMode = $("[name='seamless']")[0].checked; userElement = JSON.parse($("#userElementBox")[0].value); prefix = $("[name='prefix']")[0].value; suffix = $("[name='suffix']")[0].value; queryIsOn = $("[name='query']")[0].checked; writeConfig(); alert("保存成功"); location.reload(); } } function init() { $(`<li data-v-6d5597b1 id="replaceEmoji"> <a data-v-6d5597b1="" title="手动替换表情" unselectable="on"> <img style="margin: 2px 0; padding: 0; inline-size: 22px; align-items: center; justify-content: center" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/apple/285/grinning-face-with-sweat_1f605.png"> </a> </li>`).appendTo($(".mp-editor-menu")); $("#replaceEmoji").on("click", function () { replaceAll(); }); if (localStorage.getItem("LuoguEmojiSender") == null) { localStorage.setItem("LuoguEmojiSender", "哇这里竟然有彩蛋"); writeConfig(); ShowSuccess("自动发表情插件初始化完毕"); } else { readConfig(); } if (functionIsOn == true) { addOnButton(); } else { addOffButton(); } document.addEventListener("input", function () { main(); }) if (document.getElementById("feed-content") != null) { $(` <p> <strong>插件设置</strong><br> <a id="LuoguEmojiSenderSetting" target="_blank">LuoguEmojiSender 设置</a> <br> </p>`).appendTo($(".am-hide-sm")); $("#LuoguEmojiSenderSetting").on("click", function () { setting.openSetting(); }); $(` <div id="lesSettingDiv" style="display: none"> <p style="text-align: center; font-weight: bold">LuoguEmojiSender 设置</p> <hr> <form name="lesSetting"> <strong> 无缝模式: </strong> <input type="radio" name="seamless" value="enabled" >启用</input> <input type="radio" name="seamless" value="disabled" >禁用</input> <br> 自定义前缀: <input type="text" name="prefix" style="width: 100px; text-align: center"> <br> 自定义后缀: <input type="text" name="suffix" style="width: 100px; text-align: center"> <br> <strong> 查表情按钮: </strong> <input type="radio" name="query" value="enabled" >启用</input> <input type="radio" name="query" value="disabled" >禁用</input> <br> 用户定义表情:<br> <textarea style="height: 200px; font-size: 12px; width: 218.59px; padding: 10px" id="userElementBox"></textarea> <p style="text-align: center; color: red; user-select:none;" id=resetPlugin>点击重置 LuoguEmojiSender</p> </form> <br> <button id="saveSetting" onclick="setting.saveSetting()" style="color: white; background-color: #dd514c; border: none; width: 80px; height: 32px; font-size: 16px; float: left;"> 保存 </button> <button id="cancelSetting" onclick="setting.cancelSetting()" style="color: white; background-color: #dd514c; border: none; width: 80px; height: 32px; font-size: 16px; float: right;"> 取消 </button> <br> </div> `).appendTo($(".am-hide-sm")); $("#saveSetting").on("click", function () { setting.saveSetting(); }); $("#cancelSetting").on("click", function () { setting.cancelSetting(); }); $("#resetPlugin").on("click", function () { if (prompt("您确定要重置 LuoguEmojiSender 设置吗?如果确定,请在下面的输入框里输入 “确定” 两个汉字:") == "确定") { localStorage.removeItem("LuoguEmojiSender"); alert("重置完成") location.reload(); } }); $("#userElementBox")[0].value = JSON.stringify(userElement, null, 4); $("[name='seamless']").on("click", function () { if ($("[name='seamless']")[1].checked == true) { $("[name='prefix']")[0].disabled = false; $("[name='suffix']")[0].disabled = false; $("[name='prefix']")[0].value = prefix; $("[name='suffix']")[0].value = suffix; } else { $("[name='prefix']")[0].disabled = true; $("[name='suffix']")[0].disabled = true; $("[name='prefix']")[0].value = ""; $("[name='suffix']")[0].value = ""; } }); } if ((markdownPalettes != undefined || document.getElementById("feed-content") != null) && queryIsOn == true) { $(` <div id="queryButton" style="margin: 0; padding: 0; position: fixed; width: 100px; height: 32px; right: 0px; bottom: 50vh; color: black; background: white; opacity: 80%;"> <a href="https://maxmilite.gitee.io/archive/emoji-library.html" target="_blank"><p style="text-align: center; padding: 4px 0; margin: 0; font-size: 16px; user-select:none; color: black">查看表情</p></a> </div> <div id="switchQuery" style="margin: 0; padding: 0; position: fixed; width: 20px; height: 32px; right: 100px; bottom: 50vh; color: black; background: white; opacity: 80%;"> <p style="text-align: center; padding: 4px 4px; margin: 0;font-size: 16px; user-select:none;" id="switchContent">></p> </div> `).appendTo($("body")[0]); $("#switchQuery").on("click", function () { if ($("#queryButton").width() != 0) { $("#queryButton").animate({width: "0px"}); $("#switchQuery").animate({right: "0px"}); $("#switchContent")[0].innerText = "<"; } else { $("#queryButton").animate({width: "100px"}); $("#switchQuery").animate({right: "100px"}); $("#switchContent")[0].innerText = ">"; } }); } if (markdownPalettes != undefined || document.getElementById("feed-content") != null) { ShowSuccess("自动发表情插件已加载完毕"); } } function addOffButton() { if (document.getElementById("buttonOff") != null) { document.getElementById("buttonOff").remove(); ShowSuccess("自动替换表情功能已关闭"); } $(`<li data-v-6d5597b1 id="buttonOn"> <a data-v-6d5597b1="" title="开启自动替换" unselectable="on"> 关 </ a> </li>`).appendTo($(".mp-editor-menu")); $("#buttonOn").on("click", function () { addOnButton(); }); functionIsOn = false; writeConfig(); } function addOnButton() { if (document.getElementById("buttonOn") != null) { document.getElementById("buttonOn").remove(); ShowSuccess("自动替换表情功能已开启"); } $(`<li data-v-6d5597b1 id="buttonOff"> <a data-v-6d5597b1="" title="关闭自动替换" unselectable="on"> 开 </a> </li>`).appendTo($(".mp-editor-menu")); $("#buttonOff").on("click", function () { addOffButton(); }); functionIsOn = true; writeConfig(); } // It seemed this function didn't work :( // To be fixed // Fixed on 2021.5.30 init(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址