// ==UserScript== // @name Luogu Search AnyWhere // @namespace https://greasyfork.org/zh-CN/scripts/446614 // @version 0.3.4-X6 // @description Search AnyWhere in Luogu! // @author tiger2005 & d0j1a_1701 & accomplishment // @match https://www.luogu.com.cn/* // @grant GM.xmlHttpRequest // @connect lgbbs.oiso.cf // @icon https://cdn.luogu.com.cn/upload/usericon/3.png // @license MIT // @require https://code.jquery.com/jquery-3.6.0.min.js // @downloadURL https://update.greasyfork.icu/scripts/446614/Luogu%20Search%20AnyWhere.user.js // @updateURL https://update.greasyfork.icu/scripts/446614/Luogu%20Search%20AnyWhere.meta.js // ==/UserScript== (function($, undefined) { 'use strict'; $(function(){ Date.prototype.pattern = function(format) { var date = { "y+": this.getYear(), "M+": this.getMonth() + 1, "d+": this.getDate(), "h+": this.getHours(), "m+": this.getMinutes(), "s+": this.getSeconds(), "q+": Math.floor((this.getMonth() + 3) / 3), "S+": this.getMilliseconds() }; if (/(y+)/i.test(format)) { format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length)); } for (var k in date) { if (new RegExp("(" + k + ")").test(format)) { format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? date[k] : ("00" + date[k]).substr(("" + date[k]).length)); } } return format; }; var settings = localStorage.getItem("lsaw_settings"); if(settings == undefined || settings == 'undefined') settings = {}; else settings = JSON.parse(settings); var majorSettings = [ ["lsawUserDisplay", true], ["lsawProblemDisplay", true], ["lsawOfficialListDisplay", false], ["lsawSelectListDisplay", false], ["lsawDiscussDisplay", true], ["lsawProblemDisplayNumber", 50], ["lsawListDisplayNumber", 50], ]; for(var i=0; i .searchAnywhere{ position: fixed; top: 0px; left: 0px; height: 100%; width: 100%; background-color: rgba(0, 0, 0, 0.8); z-index: 999; transition: 0.2s; color: white; } .searchAnywhereMain{ height: min(600px, 100% - 10px); width: min(750px, 100% - 10px); position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; flex-direction: column; } .inputArea{ display: block; width: 100%; height: 48px; color: #aaa; position: relative; transition: 0.2s; margin-bottom: 10px; } .inputArea > input{ border-radius: 5px; border: 2px solid #aaa; height: 48px; width: 100%; font-size: 18px; color: #aaa; padding: 14px 24px; outline: 0; background: transparent; box-sizing: border-box; } .inputArea.onHover > input, .inputArea.onFocus > input{ border: 2px solid white; } .inputArea.onHover, .inputArea.onFocus, .inputArea.withContent{ color: white !important; } .inputArea.onHover > input, .inputArea.onFocus > input, .inputArea.withContent > input{ color: white !important; } .inputArea.withIconLeft > input{ padding-left: 42px; } .inputArea.withIconRight > input{ padding-right: 42px; } .inputArea > div.iconLeft{ height: 48px; width: 48px; position: absolute; display: grid; place-items: center; top: 0px; left: 0px; } .inputArea > div.iconRight{ height: 48px; width: 48px; position: absolute; display: grid; place-items: center; top: 0px; right: 0px; } .inputArea > div.iconLeft > svg{ width: 20px !important; height: 20px !important; } .inputArea > div.iconRight > svg{ width: 20px !important; height: 20px !important; } .inputAreaSmall{ display: block; width: 100%; height: 30px; color: #aaa; position: relative; transition: 0.2s; } .inputAreaSmall > input{ border-radius: 5px; border: 2px solid #aaa; height: 30px; width: 100%; font-size: 18px; color: #aaa; padding: 5px 10px; outline: 0; background: transparent; box-sizing: border-box; } .inputAreaSmall.onHover > input, .inputAreaSmall.onFocus > input{ border: 2px solid white; } .inputAreaSmall.onHover, .inputAreaSmall.onFocus, .inputAreaSmall.withContent{ color: white !important; } .inputAreaSmall.onHover > input, .inputAreaSmall.onFocus > input, .inputAreaSmall.withContent > input{ color: white !important; } .userPurple{ color: #cf5bff; font-weight: bold; } .userRed{ color: #e74c3c; font-weight: bold; } .userOrange{ color: #e67e22; font-weight: bold; } .userYellow{ color: #d9a71d; font-weight: bold; } .userGreen{ color: #5eb95e; font-weight: bold; } .userGray{ color: #aaa; font-weight: bold; } .userCheater{ color: #d3961c; font-weight: bold; } .userBlue{ color: #07a2f1; font-weight: bold; } .userGold{ color: #f1c40f; font-weight: bold; } .badgePurple{ background-color: #cf5bff; } .badgeRed{ background-color: #e74c3c; } .badgeOrange{ background-color: #e67e22; } .badgeYellow{ background-color: #d9a71d; } .badgeGreen{ background-color: #5eb95e; } .badgeGray{ background-color: #999; } .badgeCheater{ background-color: #d3961c; } .badgeBlue{ background-color: #07a2f1; } .badgeBlack{ background-color: #0e1d69; } .badgeGold{ background-color: #f1c40f; } .searchAnywhereContent{ color: white; flex: 1; scrollbar-width: none; -ms-overflow-style: none; overflow-x: hidden; overflow-y: auto; } .searchAnywhereContent::-webkit-scrollbar { width: 0 !important; } .searchUserCard{ background: #444; border-radius: 10px; display: flex; flex-direction: column; cursor: pointer; color: white; padding: 10px; line-height: 1; margin-bottom: 10px; border: 2px solid #888; box-sizing: border-box; } .searchCard.light{ border: 2px solid white; } .searchUserCard > div{ width: 100%; } .searchUserCardBody{ display: flex; flex-direction: row; } .searchUserCardImg{ height: 36px; width: 36px; border-radius: 50%; margin-right: 10px; } .searchUserCardInfo > span:first-child{ font-size: 14px; margin-bottom: 3px; display: inline-block; color: #bbb; } .searchUserCardInfo > span:last-child{ font-size: 20px; } .searchUserCardMedia{ display: flex; flex-direction: row; } .searchUserCardMedia > div{ margin-top: 5px; flex: 1; display: inline-block; height: 23px; verticle-align: center; } .searchUserCardMedia > div > div{ padding: 4px; position: relative; display: inline-block; background: #777; margin-right: 15px; } .searchUserCardMedia > div > div:after{ width: 10px; height: 100%; content: ""; border: 5px; position: absolute; top: 0px; left: 100%; clip-path: polygon(0 0,100% 50%,0 100%); background-color: inherit; } .userBadgeInfo{ font-size: 14px; padding: 2px 5px; border-radius: 5px; color: white; font-weight: bold; margin: 0px 3px; display: inline-block; } .searchProblemCard{ background: #444; border-radius: 10px; display: flex; flex-direction: column; cursor: pointer; color: white; padding: 10px; line-height: 1; margin-bottom: 10px; border: 2px solid #888; box-sizing: border-box; } .searchProblemCard > div{ width: 100%; display: flex; flex-direction: row; } .searchProblemCard > div:last-child{ margin-top: 5px; } .searchProblemCardTag{ margin-right: 12px; display: inline-flex; flex-direction: row; line-height: 24px; height: 24px; overflow: hidden; } .searchProblemCardTag > div{ padding: 2px; position: relative; display: inline-block; margin-right: 5px; } .searchListCardTag{ margin-right: 12px; display: inline-flex; flex-direction: row; line-height: 24px; height: 24px; overflow: hidden; } .searchListCardTag > div{ padding: 2px; position: relative; display: inline-block; margin-right: 5px; } .searchListCardTag svg, .searchProblemCardTag svg{ height: 20px !important; width: 20px !important; } .problemTagInfo{ font-size: 16px; padding: 4px 7px; border-radius: 5px; color: white; display: inline-block; } .searchProblemCardBody > div:first-child{ margin-right: 5px; } .searchListCard{ background: #444; border-radius: 10px; display: flex; flex-direction: column; cursor: pointer; color: white; padding: 10px; line-height: 1; margin-bottom: 10px; border: 2px solid #888; box-sizing: border-box; position: relative; } .searchListCard > div{ width: 100%; display: flex; flex-direction: row; } .searchListCardBody > div:first-child{ margin-right: 5px; } .searchListCardBody{ margin-bottom: 5px; } .searchAnywhereSettings{ position: fixed; top: 0px; left: 0px; height: 100%; width: 100%; background-color: rgba(0, 0, 0, 0.8); z-index: 1000; transition: 0.2s; color: white; } .searchAnywhereSettingsMain{ height: min(300px, 100% - 10px); width: min(450px, 100% - 10px); position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; flex-direction: column; } .searchAnywhereSettingsContent{ flex: 1; scrollbar-width: none; -ms-overflow-style: none; overflow-x: hidden; overflow-y: auto; } .searchAnywhereSettingsBag{ margin-bottom: 8px; user-select: none; font-size: 20px; position: relative; line-height: 30px; } .searchAnywhereClicky{ position: relative; height: 30px; width: 30px; } .searchAnywhereClicky div{ transition: 0.2s; position: absolute; top: 0px; left: 0px; cursor: pointer; } .searchAnywhereClicky div svg{ height: 30px; width: 30px; } .searchAnywhereClicky[flag=false] .falseBlock{ opacity: 1; } .searchAnywhereClicky[flag=true] .falseBlock{ opacity: 0; } .searchAnywhereClicky[flag=true] .trueBlock{ opacity: 1; } .searchAnywhereClicky[flag=false] .trueBlock{ opacity: 0; } .searchAnywhereSettingsContent::-webkit-scrollbar { width: 0 !important; } .searchAnywhereCloseSettings{ display: inline-grid; place-items: center; width: 32px; height: 32px; cursor: pointer; border-radius: 50%; background: white; } .searchAnywhereCloseSettings:hover{ background: #aaa; } .searchCard.light, .searchCard{ color: white !important; } .searchAnywhereContent > div > div > a:hover{ color: #83c4ef; } `); $(".inputArea > input").focus(function(){ $(this).parent().addClass("onFocus"); }); $(".inputArea > input").blur(function(){ $(this).parent().removeClass("onFocus"); if($(this).val().length != 0) $(this).parent().addClass("withContent"); else $(this).parent().removeClass("withContent"); }); $(".inputArea").mouseenter(function(){ $(this).addClass("onHover"); }); $(".inputArea").mouseleave(function(){ $(this).removeClass("onHover"); }); $(".inputAreaSmall > input").focus(function(){ $(this).parent().addClass("onFocus"); }); $(".inputAreaSmall > input").blur(function(){ $(this).parent().removeClass("onFocus"); if($(this).val().length != 0) $(this).parent().addClass("withContent"); else $(this).parent().removeClass("withContent"); }); $(".inputAreaSmall").mouseenter(function(){ $(this).addClass("onHover"); }); $(".inputAreaSmall").mouseleave(function(){ $(this).removeClass("onHover"); }); $(".searchAnywhereClicky").click(function(){ var a = $(this).attr("flag"); if(a == "false"){ a = true; $(this).attr("flag", a); } else{ a = false; $(this).attr("flag", a); } var settingsName = $(this).parent().attr("for"); settings[settingsName] = a; localStorage.setItem("lsaw_settings", JSON.stringify(settings)); }) $(".inputAreaSmall input").change(function(){ var a = Number($(this).val()); var settingsName = $(this).parent().parent().parent().attr("for"); settings[settingsName] = a; localStorage.setItem("lsaw_settings", JSON.stringify(settings)); }) $(".searchAnywhereCloseSettings").click(function(){ $(".searchAnywhereSettings").css("opacity", "0"); setTimeout(() => { $(".searchAnywhereSettings").css("display", "none"); }, 200); }) $(".searchAnywhereSettingsLink").click(function(){ $(".searchAnywhereSettings").css("display", "block"); setTimeout(() => { $(".searchAnywhereSettings").css("opacity", "1"); }, 20); }) const getColorFromPercent = (x, opa) => { let r = 0, g = 0, b = 0; let rr = 231, gg = 76, bb = 60; let rrr = 82, ggg = 196, bbb = 26; // if(x < 0.5){ // r = 255; // g = one * x; // } // else{ // r = 255 - ((x - 0.5) * one); // g = 255; // } r = rr + (rrr - rr) * x; g = gg + (ggg - gg) * x; b = bb + (bbb - bb) * x; r += (60 - r) * (1 - opa); g += (60 - g) * (1 - opa); b += (60 - b) * (1 - opa); r = Math.floor(r); g = Math.floor(g); b = Math.floor(b); return `rgb(${r}, ${g}, ${b})`; }; const problemColors = [ "Gray", "Red", "Orange", "Yellow", "Green", "Blue", "Purple", "Black" ]; const problemNames = [ "暂无评定", "入门", "普及-", "普及/提高-", "普及+/提高", "提高+/省选-", "省选/NOI-", "NOI/NOI+/CTSC" ]; var searchTimeout = null; var currentHoverCard = undefined; const changeHoverCard = (x, scroll = true, align = false) => { $(".searchCard.light").removeClass("light"); if(x != undefined && scroll) $(".searchAnywhereMainInput > input").blur(); if(x != undefined){ x.addClass("light").focus(align); if(scroll){ var heg = x[0].offsetTop; var prr = x.parent().parent(); var scr = prr.scrollTop(); var r = heg - x.outerHeight() + 5, l = r - prr.outerHeight() + x.outerHeight() + 10; scr = Math.max(l, Math.min(r, scr)); prr.scrollTop(scr); } } if(scroll){ // remove mouse event $(".searchCard").unbind('mouseenter').unbind('mouseleave'); $(document).mousemove(() => { $(document).unbind('mousemove'); $(".searchCard").unbind('mouseenter').unbind('mouseleave').hover(function(){ changeHoverCard($(this), false); }, function(){ changeHoverCard(undefined, false); }); }) } currentHoverCard = x; } const searchInfo = () => { searchTimeout = null; var info = $(".inputArea > input").val(); info = $.trim(info); if(info == ""){ $(".searchAnywhereContent").html(""); return; } //$(".searchAnywhereContent").html(`
加载中……
`); $(".searchAnywhereContent > div").unbind('click').click((event) => { event.stopPropagation(); }) var userHtml = ""; var problemHtml = ""; var officialHtml = ""; var selectHtml = ""; var discussHtml = ""; var networkError = false; var lastHtml = ""; var refreshInterval = setInterval(function(){ let Html = ""; if(networkError) Html = `
网络错误
` else if(userHtml == "" && problemHtml == "" && officialHtml == "" && selectHtml == "" && discussHtml == "") Html = `
未搜索到相关内容
` else{ changeHoverCard(undefined, false); Html = `
` + userHtml + discussHtml + problemHtml + officialHtml + selectHtml + `
`; $(".searchAnywhereContent > div").unbind('click').click((event) => { event.stopPropagation(); }) $(".searchCard").unbind('mouseenter').unbind("mouseleave").hover(function(){ changeHoverCard($(this), false); }, function(){ changeHoverCard(undefined, false); }); } if(Html!=lastHtml){ $(".searchAnywhereContent").html(Html); lastHtml = Html; } },500); const getProblemStatus = (x, y) => { if(!x && !y) return ``; if(!y) return ``; return ``; } const getCCFLevel = (x) => { if(x == null || x < 3) return ""; var color = ""; if(x <= 5) color = "#5eb95e"; else if(x <= 7) color = "#07a2f1"; else color = "#f1c40f"; return `` } if(settings.lsawUserDisplay != false) $.ajax({ url: `/api/user/search?keyword=${info}`, type: 'GET', success: function(json){ json = json.users; if(json.length != 0 && json[0] != null){ userHtml = `
用户
`; json.forEach((item) => { if(item == null) return; if(item.color == "Cheater") item.badge = "作弊者"; userHtml += `
UID ${item.uid}
${item.name}${getCCFLevel(item.ccfLevel)}${item.badge != null && item.badge != "" ? `
${item.badge}
` : ""}
` }); } }, error: () => { networkError = true; } }); if(settings.lsawProblemDisplay != false) $.ajax({ url: `/problem/list`, type: 'GET', headers: {"x-luogu-type": "content-only"}, data: { keyword: info, page: 1, type: "P|B|CF|SP|AT|UVA" }, success: function(json){ if(json.code != 200){ return; } json = json.currentData.problems; if(json.count != 0){ problemHtml = `
题目查看所有 ${json.count} 道题目
`; for(var i=0; i
${getProblemStatus(item.submitted, item.accepted)}
${item.title}
${item.pid}
${item.totalSubmit}
${item.totalAccepted}
${problemNames[item.difficulty]}
`; }; } }, error: () => { networkError = true; } }); if(settings.lsawOfficialListDisplay != false) $.ajax({ url: `/training/list`, type: "GET", data: { keyword: info, page: 1, type: "official" }, headers: {"x-luogu-type": "content-only"}, success: (json) => { if(json.code != 200){ return; } json = json.currentData; if(json.trainings.result.length != 0){ officialHtml = `
官方题单查看所有 ${json.trainings.count} 份题单
`; for(var i=0; i
#${item.id}
${item.title}
${acs} / ${item.problemCount}
${item.markCount}
`; } } }, error: () => { networkError = true; } }) if(settings.lsawSelectListDisplay != false) $.ajax({ url: `/training/list`, type: "GET", data: { keyword: info, page: 1, type: "select" }, headers: {"x-luogu-type": "content-only"}, success: (json) => { if(json.code != 200){ return; } json = json.currentData; if(json.trainings.result.length != 0){ selectHtml = `
用户题单查看所有 ${json.trainings.count} 份题单
`; for(var i=0; i
#${item.id}
${item.title}
${item.problemCount}
${(new Date(item.createTime * 1000)).pattern("yyyy/MM/dd")}
${item.markCount}
`; } } }, error: () => { networkError = true; } }) if(settings.lsawDiscussDisplay != false){ GM.xmlHttpRequest({ method: "get", url: `https://lgbbs.oiso.cf/search.php?s=${info}`, headers: { "Content-Type": "text/html" }, onload: function(res){ if(res.status != 200){ return; } let parser = new DOMParser(); let htmlDoc=parser.parseFromString(res.responseText, "text/html"); let discuss_a = htmlDoc.querySelectorAll('.am-u-md-6 > a'); let first = true; for(let a of discuss_a){ if(a.href == null) continue; let d_id_l = a.href.match(/[0-9]/g); let d_id = ''; for(let x of d_id_l) d_id += x; $.ajax({ url: `/discuss/${d_id}`, type: "GET", headers: {"x-luogu-type": "content-only"}, success: (html) => { if(html.code==404) return; let parser2 = new DOMParser(); let dom=parser.parseFromString(html, "text/html"); let user_a = dom.querySelector('.am-comment-meta > a'); let username = user_a.innerHTML; $.ajax({ url: `/api/user/search?keyword=${username}`, type: 'GET', success: function(json){ if(first==true){ discussHtml = `
讨论查看所有 ${discuss_a.length} 个保存的讨论
`; first = false; } json = json.users; if(json.length != 0 && json[0] != null){ json.forEach((item) => { if(item == null) return; if(item.color == "Cheater") item.badge = "作弊者"; //console.info(`Discus:${username}:${a.innerHTML}`) discussHtml += `
${a.innerHTML}
${username}${getCCFLevel(item.ccfLevel)}${item.badge != null && item.badge != "" ? `
${item.badge}
` : ""}
` }); } } }); } }) } }, onerror: function(res){ } }); } }; $(".searchAnywhereMainInput > input").unbind('input propertychange').on('input propertychange', function(){ if(searchTimeout != null) clearTimeout(searchTimeout); searchTimeout = setTimeout(searchInfo, 500); }); let searchAnywhereOpen = false; let inject_interval = setInterval(function(){ if($('.search-wrap').length == 0) return; let en = $('.user-nav .search-wrap').next(); $(".user-nav .search-wrap").remove(); en.css("margin-left", "10px"); en.unbind('click').click(function(){ if(! searchAnywhereOpen){ $(".searchAnywhere").css("display", "block"); setTimeout(() => { $(".searchAnywhere").css("opacity", "1"); $(".searchAnywhereMainInput > input").focus(); }, 20); } else{ $(".searchAnywhere").css("opacity", "0"); setTimeout(() => { $(".searchAnywhere").css("display", "none"); }, 200); } searchAnywhereOpen = !searchAnywhereOpen; }); clearInterval(inject_interval); },500); $(".searchAnywhere").unbind('click').click(() => { $(".searchAnywhere").css("opacity", "0"); setTimeout(() => { $(".searchAnywhere").css("display", "none"); }, 200); searchAnywhereOpen = false; }) $(".searchAnywhereMainInput").unbind('click').click((event) => { event.stopPropagation(); }) $(document).keydown(function(event){ if((event.keyCode == 186) && (event.ctrlKey || event.metaKey)){ if(! searchAnywhereOpen){ $(".searchAnywhere").css("display", "block"); setTimeout(() => { $(".searchAnywhere").css("opacity", "1"); $(".searchAnywhereMainInput > input").focus(); }, 20); } else{ $(".searchAnywhere").css("opacity", "0"); setTimeout(() => { $(".searchAnywhere").css("display", "none"); }, 200); } searchAnywhereOpen = !searchAnywhereOpen; event.preventDefault(); } if(searchAnywhereOpen){ if(event.keyCode == 38){ // Up if(currentHoverCard == undefined){ var lis = $(".searchCard"); if(lis.length == 0) $(".searchAnywhereMainInput > input").focus(); else{ currentHoverCard = lis.eq(lis.length - 1); changeHoverCard(currentHoverCard); } } else{ currentHoverCard = currentHoverCard.prev(); while(1){ if(currentHoverCard.length == 0 || currentHoverCard.hasClass("searchCard")) break; currentHoverCard = currentHoverCard.prev(); } if(currentHoverCard.length == 0){ $(".searchAnywhereMainInput > input").focus(); currentHoverCard = undefined; } changeHoverCard(currentHoverCard); } event.preventDefault(); } else if(event.keyCode == 40){ // Down if(currentHoverCard == undefined){ var lis = $(".searchCard"); if(lis.length == 0) $(".searchAnywhereMainInput > input").focus(); else{ currentHoverCard = lis.eq(0); changeHoverCard(currentHoverCard); } } else{ currentHoverCard = currentHoverCard.next(); while(1){ if(currentHoverCard.length == 0 || currentHoverCard.hasClass("searchCard")) break; currentHoverCard = currentHoverCard.next(); } if(currentHoverCard.length == 0){ $(".searchAnywhereMainInput > input").focus(); currentHoverCard = undefined; } changeHoverCard(currentHoverCard); } event.preventDefault(); } else if(event.keyCode == 13){ // Enter if(currentHoverCard != undefined) window.open(currentHoverCard.attr("href"), "_blank"); event.preventDefault(); } else if(event.keyCode == 9) event.preventDefault(); else $(".searchAnywhereMainInput > input").focus(); } }) }); })(window.jQuery.noConflict(true));