您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
非常好的 luogu 插件集合
当前为
// ==UserScript== // @name luogu 插件集合 // @namespace http://tampermonkey.net/ // @version 1.3.0 // @description 非常好的 luogu 插件集合 // @author konyakest // @license MIT // @match https://www.luogu.com.cn/* // @match https://www.luogu.com/* // @match https://api.loj.ac/ // @icon https://fecdn.luogu.com.cn/luogu/logo.png // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // ==/UserScript== (function() { 'use strict'; var url = window.location.href; async function user_detail(){ var button = document.createElement('button'); button.textContent = '复制Md'; button.style.position = "absolute"; button.style.top = "100px";button.style.right = "100px"; window.addEventListener('scroll', function() { var scrollY = window.scrollY; button.style.top = (100 + scrollY) + 'px'; }); button.classList.add('button-lgcm'); button.addEventListener('click', async function() { var introduction = _feInstance.currentData.user.introduction; await navigator.clipboard.writeText(introduction); alert('复制成功'); }); document.body.appendChild(button); } async function blog(){ var button = document.createElement('button'); button.textContent = '复制Md'; button.style.position = "absolute"; button.style.top = "100px";button.style.right = "100px"; window.addEventListener('scroll', function() { var scrollY = window.scrollY; button.style.top = (100 + scrollY) + 'px'; }); button.classList.add('button-lgcm'); button.addEventListener('click', async function() { fetch('/api/blog/detail/' + BlogGlobals.blogID).then(res => res.json()).then(res => navigator.clipboard.writeText(res.data.Content)); alert('复制成功'); }); document.body.appendChild(button); }; async function contest_detail(){ var button = document.createElement('button'); button.textContent = '复制Md'; button.style.position = "absolute"; button.style.top = "100px";button.style.right = "100px"; window.addEventListener('scroll', function() { var scrollY = window.scrollY; button.style.top = (100 + scrollY) + 'px'; }); button.classList.add('button-lgcm'); button.addEventListener('click', async function() { var introduction = _feInstance.currentData.contest.description; await navigator.clipboard.writeText(introduction); alert('复制成功'); }); document.body.appendChild(button); }; async function training_detail(){ var button = document.createElement('button'); button.textContent = '复制Md'; button.style.position = "absolute"; button.style.top = "100px";button.style.right = "100px"; window.addEventListener('scroll', function() { var scrollY = window.scrollY; button.style.top = (100 + scrollY) + 'px'; }); button.classList.add('button-lgcm'); button.addEventListener('click', async function() { var introduction = _feInstance.currentData.training.description; await navigator.clipboard.writeText(introduction); alert('复制成功'); }); document.body.appendChild(button); }; var style = document.createElement('style'); style.textContent = ` .button-lgcm { outline:none !important; cursor: pointer; line-height: 1.25; position: relative; display: block; margin-left: -.0625rem; padding: .5rem .75rem; color: #fff !important; border: .0625rem solid #dee2e6; font-size: 15px; font-weight: unset; display: flex; min-width: 36px; height: 36px; margin: 0 3px; border-radius: 100px!important; align-items: center; justify-content: center; transition:all .3s; background-color: #5e72e4; } .button-lgcm:hover { box-shadow: 0 7px 14px rgba(50,50,93,.1), 0 3px 6px rgba(0,0,0,.08); transform: translateY(-1px); } `; document.head.appendChild(style); if (url.includes('blog') && !url.includes('Admin') && !url.includes('admin')) { var parsedUrl = new URL(url); if (url.includes('org')) { var path = parsedUrl.pathname.split('/'); if (path.length >= 2 && path[1] != '') { window.addEventListener('load', blog); } } else { var path = parsedUrl.pathname.split('/'); if (path.length >= 4) { console.log('a'); window.addEventListener('load', blog); } } } if (url.includes('user') && !url.includes('notification')) { window.addEventListener('load', user_detail); } if (url.includes('contest') && !url.includes('list') && !url.includes('edit') && !url.includes('contestId')) { window.addEventListener('load', contest_detail); } if (url.includes('training') && !url.includes('edit') && !url.includes('list')) { window.addEventListener('load', training_detail); } })(); (function () { 'use strict'; const url = window.location.href; async function clickBotton_blog() { var x = document.querySelector("#lentille-context").text var y = JSON.parse(x) var z = y.data.article.content navigator.clipboard.writeText(z); }; if (url.includes("article")) { document.onkeydown = function (e) { if (e.keyCode == 67 && e.ctrlKey && e.altKey) { clickBotton_blog(); alert("复制成功!"); } } } // Your code here... })(); (function() { 'use strict'; function remove(){ var xpath = "/html/body/div/div[2]/main/div/section[1]/div[1]/a[2]"; var iterator = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null); var element; while (element = iterator.iterateNext()) { if (element) { element.parentNode.removeChild(element); } } } window.addEventListener("load", () => { remove(); }); })(); /* - 浏览记录 - 显示代码长度 - 简要题面 - 首页暂存内容 - 卷题情况 - 测试用例 - 显示今日AC */ const PASTEID = "1vvwrtao"/*请自行设置,如"eyb488k7"*/; const TRAINING_ID = 551473/*请自行设置,如100,**必须是团队作业题单,且您必须有题单的编辑权限***/; function URLmatch(pat){ return Boolean(window.location.href.match(pat)); } async function 显示代码长度(){ const ENABLE_CACHE = true; /* ENABLE_CACHE:是否使用缓存(缓存即将获取的结果存下来,下一次直接使用) 根据代码长度判定颜色的方案可以自行修改 makeColoredTextBySize 中的内容,我相信这部分是可以直接看懂的(*´▽`)ノノ */ function getMid(lst){ // console.log(lst); return (function(x){ if(x<1024){ return x+" B"; } return (x/1024).toFixed(2)+" K"; })(lst[Math.floor(lst.length/2)]); } function makeColoredText(color,text){ return ` <a data-v-0640126c="" data-v-beeebc6e="" colorscheme="default" class="color-default" data-v-b5709dda=""> <span data-v-71731098="" data-v-beeebc6e="" class="lfe-caption" style="background: ${color}; color: rgb(255, 255, 255);" data-v-0640126c="">${text} </span> </a> ` } let colors = { red: "rgb(254,76,97)", orange: "rgb(243,156,17)", yellow: "rgb(255,193,22)", green: "rgb(82,196,26)", blue: "rgb(52,152,219)", purple: "rgb(157,61,207)", black: "rgb(14,29,105)" }; function makeColoredTextBySize(size,text){ size = size.split(' '); size = Number(size[1]==="K"?size[0]*1024:size[0]); const K = 1024; if(size <= 1*K) return makeColoredText(colors.yellow,text); if(size <= 2*K) return makeColoredText(colors.green,text); if(size <= 3*K) return makeColoredText(colors.blue,text); if(size <= 4*K) return makeColoredText(colors.purple,text); return makeColoredText(colors.black,text); } async function sampleRecord(pid){ if(ENABLE_CACHE){ if(GM_getValue(pid)&&(GM_getValue(pid)!=="NaN K")){ return GM_getValue(pid); } } let lst = []; try{ let promiselst = []; for(let i=1;i<=5;i++){ promiselst.push( fetch( `https://www.luogu.com.cn/record/list?pid=${pid}&status=12&_contentOnly=1&page=${i}` ) .then(x=>x.json()) .then(x=>x.currentData.records.result) ); } await Promise.all(promiselst).then(function(x){ x.forEach(x=>x.forEach(x=>lst.push(x.sourceCodeLength))); lst.sort((a,b)=>a-b); }); }catch(e){}; // console.log(lst); lst.sort((a,b)=>a-b); let res = getMid(lst); if(ENABLE_CACHE){ GM_setValue(pid,res); } return res; } if(window.location.href.split('/')[3] === "problem"){ let field = document.querySelector(".color-inverse > div:nth-child(1)"); let clone = field.cloneNode(true); field.parentNode.appendChild(clone); clone.children[0].innerHTML = "平均码长"; clone.children[1].innerHTML = "正在获取中"; let size = await sampleRecord(window.location.href.split('/')[4],clone.children[1]); clone.children[1].innerHTML = makeColoredTextBySize(size,size); } else if(window.location.href.match('#').length){ let all = document.querySelector(".row-wrap"); //all.childNodes.forEach(async function(x){ for(let i=0;i<all.childNodes.length;i++){ let x = all.childNodes[i]; if(!x.innerHTML){ continue; } let element = x.children[1]; let a = document.createElement('a'); let size = await sampleRecord(element.title); a.innerHTML = makeColoredTextBySize(size,size); element.appendChild(a); }; } } async function 浏览记录(){ const MAX_COUNT = 20; const DELAY = 20;//停留超过 20s 会被记录 var has_built; function mySetTimeOut(func,tim){ let a; a = setInterval(()=>{func();clearInterval(a);},tim); } function store(problem,title,link){ let all = (GM_getValue("all") || []).slice(-MAX_COUNT); if(!all.some(x=>x.problem === problem)){ all.push({problem:problem,title:title,link:link}); } GM_setValue("all",all); } async function inPaste(){ let value = GM_getValue("doit"); if(!value){ return; } GM_deleteValue("doit"); let data = ""; GM_getValue("all").forEach(x => { data += `- [${x.title}](${x.link})` data += "\n\n" }); await fetch(`https://www.luogu.com.cn/paste/edit/${PASTEID}`, { "credentials": "include", "headers": { "Accept": "application/json, text/plain, */*", "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "X-Requested-With": "XMLHttpRequest", "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content, "Content-Type": "application/json", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin" }, "body": JSON.stringify({"data":data}), "method": "POST", "mode": "cors" }); window.location.reload(); } function buildstatisticsbutton() { if (has_built) return; let tmp = document.querySelector(".operation > span:nth-child(3)"); let tmp2 = tmp.cloneNode(true); tmp2.childNodes[0].childNodes[0].innerText = "历史记录"; tmp2.onclick = async function() { GM_setValue("doit",true); window.open(`https://www.luogu.com.cn/paste/${PASTEID}`); }; tmp.parentNode.appendChild(tmp2); has_built = true; } window.addEventListener('load',function(){ if(window.location.href.split('/')[3] === "paste"){ inPaste(); return; } let title = document.querySelector(".lfe-h1 > span:nth-child(1)")? document.querySelector(".lfe-h1 > span:nth-child(1)").title : document.querySelector(".lfe-h1").innerText; let problem = window.location.href.split('/')[4]; mySetTimeOut(function(){store(problem,title,window.location.href);console.log("store!");},1000*DELAY); }) window.addEventListener('load', buildstatisticsbutton); setTimeout(buildstatisticsbutton, 500); } async function 简要题面(){ const keywords = [ "题目大意","题意","题意简述","问题描述","题面","Description" ]; async function getSolutions(){ let problem = window.location.href.split('/')[4]; let url = "https://www.luogu.com.cn/problem/solution/" + problem; let text = await fetch(url).then(x=>x.text()); let data = text.split(`JSON.parse(decodeURIComponent("`)[1].split(`"`)[0]; let res = []; JSON.parse(decodeURIComponent(data)).currentData.solutions.result.forEach(x => { res.push(x.content.split("\n")); }); return res; } function getProblemDescr(text){ let res = []; let pre; try{ text.forEach(function(x){ if(x.split(" ")[0] === pre){ throw "parse end!"; } if(keywords.some(kwd=>x.match(kwd))&&!keywords.some(kwd=>x.split(" ")[0].match(kwd))){ pre=x.split(" ")[0]; } if(pre){ res.push(x); } }); }catch(e){ if(e === "parse end!"){ let str = ""; res.forEach(x=>str+=`> ${x}\n`); return str; } throw e; } return ""; } async function my_marked(code){ if(code === "") return ""; let tmp; await GM_xmlhttpRequest({ method:'post', url:'http://www.nfls.com.cn:10611/api/markdown', data:"s="+encodeURIComponent(code), headers:{ "Content-Type": "application/x-www-form-urlencoded" }, onload:res=>tmp=res.responseText }); async function dfs(dep){ await new Promise(resolve=>setTimeout(resolve,500)); if(typeof tmp !== 'undefined'){ return tmp; } dep === 8? tmp = '网络错误,请刷新重试': await dfs(dep+1); } await dfs(1); return new DOMParser().parseFromString(tmp,"text/html").all[3].innerHTML; } async function addElement(){ let solutions = await getSolutions(); // window.searchSolutionKeyword=function(s){ // return !!window.__solutions.some(x=>x.some(xx=>xx.match(s))); // }; // setTimeout(_=>console.log(window.searchSolutionKeyword,window),2000); let tmp = document.querySelector(".operation > span:nth-child(3)"); let tmp2 = tmp.cloneNode(true); tmp2.childNodes[0].childNodes[0].innerText = "搜索题解关键词"; tmp2.onclick = function() { let value = prompt("请输入要找的关键词"); if(value === '' || value === null){ return; } if(!!solutions.some(x=>x.some(xx=>xx.match(value)))){ alert(`恭喜!题解中有关键词"${value}",快切了此题吧!`); } else{ alert(`题解中并没有关键词"${value}"`); } // await addtrainingproblem(window.location.href.split('/')[4]); // window.open(`https://www.luogu.com.cn/training/${TRAINING_ID}#rank`); }; tmp.parentNode.appendChild(tmp2); let html = await getSolutions().then(function(x){ let res = ""; x.forEach(function(x){ x = getProblemDescr(x); if(x !== ""){ res+=x+"\n\n"; } }); return res; }); await fetch("https://www.luogu.com.cn/paste/edit/"+PASTEID, { "headers": { "X-Requested-With": "XMLHttpRequest", "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content, "Content-Type": "application/json" }, "body": JSON.stringify({"data":html}), "method": "POST" }); html = await my_marked(html); let nodes = [ document.querySelector("h2.lfe-h2:nth-child(1)"), document.querySelector("div.marked:nth-child(2)")]; let text = nodes[0].parentNode.insertBefore(nodes[1].cloneNode(true),nodes[0]); let title = nodes[0].parentNode.insertBefore(nodes[0].cloneNode(true),text); title.innerText = "简要题意"; text.innerHTML = html; let index = 0; let show = function(){ let cnt = 0; text.children.forEach(function(x){ x.style.display = (cnt === index?"":"none"); cnt ++; }); }; show(); if(text.children.length === 0){ text.innerHTML = "未找到简要题意"; return; } let but1 = document.createElement("button"); but1.innerText = "换一个"; but1.onclick = function(){ index = (index+1)%text.children.length; show(); }; if(text.children.length !== 1){ title.appendChild(but1); } let but2 = document.createElement("button"); but2.innerText = "更好的阅读体验"; but2.onclick = function(){window.open("https://www.luogu.com.cn/paste/"+PASTEID);}; title.appendChild(but2); } addElement(); } async function 首页暂存内容(){ function inMain(){ let div = document.querySelector(".am-u-lg-3 > div:nth-child(3)"); let inn = document.createElement("div"); inn.innerHTML = "<h2>暂存内容</h2>"; inn.style.marginTop = "40px"; div.appendChild(inn); let but1=document.createElement("button"); but1.innerText="编辑内容"; but1.onclick = function(){window.open(GM_getValue("pasteid"));}; let but2=document.createElement("button"); but2.innerText="删除内容"; but2.onclick = function(){GM_deleteValue("html");alert("删除成功");}; inn.appendChild(but1); inn.appendChild(but2); let tmp = document.createElement("div"); tmp.innerHTML = GM_getValue("html"); tmp.style.marginTop = "20px"; if(tmp.innerHTML === undefined){ tmp.innerHTML = ""; } inn.appendChild(tmp); } //paste function inPaste(){ let div = document.querySelector(".actions"); let button = div.childNodes[2].cloneNode(true); button.innerText="保存到首页"; div.appendChild(div.childNodes[1].cloneNode(true)); div.appendChild(button); button.onclick=function(){ GM_setValue("pasteid",window.location.href); GM_setValue("html",document.querySelector(".marked").innerHTML); alert("保存成功"); }; } (function() { 'use strict'; if(window.location.href.split('/')[3] === "paste"){ setTimeout(inPaste,10); } else{ setTimeout(inMain,10); } })(); } async function 卷题情况(){ var has_built = false; function addtrainingproblem(proName) { return fetch(`https://www.luogu.com.cn/api/training/editProblems/${TRAINING_ID}`, { "headers": { "X-Requested-With": "XMLHttpRequest", "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content, "Content-Type": "application/json", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin" }, "body": "{\"pids\":[\"" + proName + "\", \"P1001\"]}", "method": "POST", }); } function buildstatisticsbutton() { if (has_built) return; let tmp = document.querySelector(".operation > span:nth-child(3)"); let tmp2 = tmp.cloneNode(true); tmp2.childNodes[0].childNodes[0].innerText = "卷题情况"; tmp2.onclick = async function() { await addtrainingproblem(window.location.href.split('/')[4]); window.open(`https://www.luogu.com.cn/training/${TRAINING_ID}#rank`); }; tmp.parentNode.appendChild(tmp2); has_built = true; } window.addEventListener('load', buildstatisticsbutton); setTimeout(buildstatisticsbutton, 500); } async function 测试用例(){ var has_built = false; async function _getLojProblem(keyword){ return await fetch("https://api.loj.ac/api/problem/queryProblemSet", { "credentials": "include", "headers": { "Content-Type": "application/json" }, "body": JSON.stringify({ "keyword":keyword,"locale":"zh_CN","takeCount":1, "skipCount":0,"keywordMatchesId":true,"titleOnly":true }), "method": "POST", }).then((x)=>(x.json())).then(function(x){return x.result[0].meta.id;}); } async function getLojProblem(keyword){ let value; try{ value = await _getLojProblem(keyword); } catch(e){ console.log("error:",e); value = await _getLojProblem(keyword.split('」')[1]); } return value; } async function getLojSubmission(problem){ return await fetch("https://api.loj.ac/api/submission/querySubmission", { "headers": { "Content-Type": "application/json" }, "body": JSON.stringify({"problemDisplayId":problem,"locale":"zh_CN","takeCount":1,"status":"Accepted"}), "method": "POST" }).then((x)=>(x.json())).then((x)=>x.submissions[0].id); } function inLuogu(){ if(has_built || document.querySelector(".tags-wrap").innerText.search("各省省选") === -1){ return; } let tmp = document.querySelector(".operation > span:nth-child(3)"); let tmp2 = tmp.cloneNode(true); tmp2.childNodes[0].childNodes[0].innerText = "测试用例"; tmp2.onclick = function() { const p = document.querySelector(".lfe-h1 > span:nth-child(1)").title.split('[')[1].split(']'); GM_setValue("title",`「${p[0]}」${p[1].trim()}`); window.open("https://api.loj.ac"); }; tmp.parentNode.appendChild(tmp2); has_built = true; } async function inLoj(){ if(has_built){ return; } has_built = true; try{ const value = await getLojSubmission(await getLojProblem(GM_getValue("title"))); if(isNaN(value)){ throw "Cannot get submission!"; } window.location.replace("https://loj.ac/s/" + value); } catch(err){ alert("error: \n"+err); } finally{ GM_deleteValue("title"); } } function main(){ window.location.href === "https://api.loj.ac/" ? setTimeout(inLoj,500) : inLuogu(); } window.addEventListener('load', main); setTimeout(main, 500); } async function 显示今日AC(){ const today = ( (a)=>(new Date(a.getFullYear()+"/"+String(a.getMonth()+1)+"/"+String(a.getDate()))) )(new Date()).getTime()/1000; async function dfsGetTodayAC(name,page){ let ans = await fetch(`https://www.luogu.com.cn/record/list?user=${name}&status=12&page=${page}`) .then(x=>x.text()) .then(x=>x.split("JSON.parse(decodeURIComponent(\"")[1]) .then(x=>x.split("\"))")[0]) .then(x=>JSON.parse(decodeURIComponent(x))) .then(x=>x.currentData.records.result) .then(x=>x.filter(xx=>xx.submitTime>=today)); if(ans.length === 20){ let res = await dfsGetTodayAC(name,page+1); res.forEach(x=>ans.push(x)); } return ans; } console.log(today); let cards = []; while(document.querySelector(".row-wrap") === null || cards.length !== document.querySelector(".row-wrap").childElementCount){ cards = []; let app = document.querySelector("#app"); app.childNodes.forEach(function(x){if(x.className === "dropdown") cards.push(x);}); if(!cards.length){ app = document.querySelector("main.wrapped"); app.childNodes.forEach(function(x){if(x.className === "dropdown") cards.push(x);}); console.log("cards",cards); } console.log("cards",cards); await new Promise(resolve=>setTimeout(resolve,500)); } cards.forEach(async function(x){ let name = document.querySelector( `div.row:nth-child(${cards.indexOf(x)+1}) > span:nth-child(2) > `+ `span:nth-child(1) > span:nth-child(1) > span:nth-child(1)` ).innerText; let ans = await dfsGetTodayAC(name,1); let p = document.createElement("p"); p.innerText = "今日通过的题目:"; console.log(x); x.children[0].children[1].appendChild(p); ans = ans.filter((item, index) => { const duplicateIndex = ans.findIndex(otherItem => otherItem.problem.pid === item.problem.pid); return duplicateIndex === index; }); ans.forEach(function(xx){ let a = document.createElement("a"); a.innerText = xx.problem.pid + " " + xx.problem.title; a.href = "https://www.luogu.com.cn/problem/" + xx.problem.pid; x.children[0].children[1].appendChild(a); x.children[0].children[1].appendChild(document.createElement("p")); }) console.log(name,ans); }); } if(URLmatch("https://www.luogu.com.cn/problem/*") || URLmatch("https://www.luogu.com.cn/paste/*") || URLmatch("https://www.luogu.com.cn/training/*")){ try{ 浏览记录(); }catch(e){}; } if(URLmatch("https://www.luogu.com.cn/problem/*") || (URLmatch("https://www.luogu.com.cn/training/*")&&!URLmatch("rank"))){ try{ 显示代码长度(); }catch(e){}; } if(URLmatch("https://www.luogu.com.cn/problem/*")){ try{ 简要题面(); }catch(e){console.log(e);}; } if(window.location.href === "https://www.luogu.com.cn/"||URLmatch("https://www.luogu.com.cn/paste/*")){ try{ 首页暂存内容(); }catch(e){console.log(e);}; } if(URLmatch("https://www.luogu.com.cn/problem/*")||!URLmatch("https://www.luogu.com.cn/problem/list")){ try{ 卷题情况(); }catch(e){console.log(e);}; } if(URLmatch("https://www.luogu.com.cn/problem/*")||URLmatch("https://api.loj.ac/")){ try{ 测试用例(); }catch(e){console.log(e);}; } let id = setInterval(function(){ if(window.location.href.split('/')[3] === "training" && Boolean(window.location.href.split('/')[4].match("#rank"))){ console.log("123"); try{ 显示今日AC(); }catch(e){console.log(e);}; clearInterval(id); } },1000); (function(){ 'use strict'; const ob = new MutationObserver(() => { const t = document.querySelector(".introduction.marked"); if (t !== null && t.style.display === "none") { t.style.display = 'block'; for (let i = 0; i < t.parentElement.children.length; i++) { if (t.parentElement.children[i].innerText === '系统维护,该内容暂不可见。') { t.parentElement.children[i].remove(); } } } }); ob.observe(document.documentElement, {childList: true, subtree: true}); })(); 'use strict'; (function(){ const featureDict = new Map([ ['lgbot1RemoveAd', '屏蔽广告'], ['lgbot1Removeback', '移除网页出错跳转'], ['lgbot1AddMessageLink', '私信界面 Ctrl+Click 打开用户主页'], ['lgbot1RemoveCover', '移除主页遮盖'], ['lgbot1AddProblemsColor', '显示题目颜色'] ]); const problemDifficultyToColor = [[191,191,191],[254,76,97],[243,156,17],[255,193,22],[82,196,26],[52,152,219],[157,61,207],[14,29,105]]; function addSettingButton(){//增加插件设置 const navElement = document.querySelector('nav.lfe-body'); if(!navElement){ console.log("未找到侧边导航栏"); console.log(document); return; } const settingElement = document.createElement('a');//外壳,链接功能 settingElement.setAttribute('data-v-0640126c', ''); settingElement.setAttribute('data-v-639bc19b', ''); settingElement.setAttribute('data-v-33633d7e', ''); settingElement.className = 'color-none'; settingElement.style.color = 'inherit'; const settingText = document.createElement('span'); settingText.setAttribute('data-v-639bc19b', ''); settingText.className = 'text'; settingText.textContent = '插件设置'; settingElement.appendChild(settingText); navElement.appendChild(settingElement); settingElement.addEventListener('click', () => {//点击后进入临时页面 function initializeSettings(){ for(let i of featureDict.keys()){ if(localStorage.getItem(i) === null){ localStorage.setItem(i, 'true'); } } } initializeSettings(); const pageContent = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>luogu_bot1 功能设置</title> <style> body { font-family: Arial, sans-serif; } #featureBox { position: fixed; top: 20%; left: 50%; transform: translate(-50%, -50%); background-color: white; border: 1px solid #ccc; padding: 20px; z-index: 10001; } </style> </head> <body> <div id="featureBox"> <h3>选择插件功能</h3> ${Array.from(featureDict).map(([key, description]) => ` <div> <label><input type="checkbox" id="${key}">${description}</label> </div> `).join('')} <button id="selectAll">全选</button> <button id="saveFeatures">保存</button> </div> <script> document.addEventListener('DOMContentLoaded', () => {//加载设置 ${Array.from(featureDict.keys()).map(key => ` const ${key} = localStorage.getItem('${key}') === 'true'; document.getElementById('${key}').checked = ${key}; `).join('')} }); document.getElementById('saveFeatures').addEventListener('click', () => {//保存设置 ${Array.from(featureDict.keys()).map(key => ` const ${key} = document.getElementById('${key}').checked; localStorage.setItem('${key}', String(${key})); `).join('')} alert('功能已保存'); }); document.getElementById('selectAll').addEventListener('click', () => {//全选 ${Array.from(featureDict.keys()).map(key => ` document.getElementById('${key}').checked = true; `).join('')} }); </script> </body> </html> `; const newWindow = window.open(); newWindow.document.write(pageContent); newWindow.document.close(); }); } function removeAd(){//屏蔽广告 const adElement = document.querySelector('div[data-v-0a593618][data-v-1143714b]'); if(adElement) { adElement.remove(); console.log('广告已被删除'); } else console.log('没有找到广告'); } function removeBack(){//移除网页跳转 function disableRedirect(){ window.history.go = function() {// 根据实际测试,洛谷使用的是 history.go console.log("luogu_bot1:已为您屏蔽 history.go()"); }; } function checkError(){ if(document.title === '错误 - 洛谷 | 计算机科学教育新生态'){ disableRedirect(); return true; } return false; } const observer = new MutationObserver((mutations, obs) => { checkError(); }); const config = { childList: true, subtree: true, }; observer.observe(document, config);// 监视 title 变化 if(document.readyState === 'complete' || document.readyState === 'interactive'){ checkError(); } } async function getUidByUsername(username){// 获取 uid const apiUrl = `https://www.luogu.com.cn/api/user/search?keyword=${username}`; return await fetch(apiUrl) .then(response => response.json()) .then(data => { if(data.users && data.users.length > 0){ return data.users[0].uid; } }) .catch(error => { console.error('Error fetching user data:', error); }); } async function processItem(item) { // 添加 eventListener item.parentElement.parentElement.addEventListener('click', (event) => { if(event.ctrlKey){ getUidByUsername(item.textContent.trim()) .then(uid => { const userLink = `/user/${uid}`; if(userLink){ window.open(userLink, '_blank'); } }) } }); } function addMessageLink(){ // Ctrl+Click 触发,动态修改网页 let items = document.querySelectorAll('span[data-v-5b9e5f50] > span[slot="trigger"]'); console.log("asdf"); console.log(items); for(let i of items){ processItem(i); } const callback = async function(mutationsList, observer) { for (const mutation of mutationsList) { if (mutation.type === 'childList') { for (const addedNode of mutation.addedNodes) { if (addedNode.nodeType === Node.ELEMENT_NODE) { const newItems = addedNode.querySelectorAll('span[data-v-5b9e5f50] > span[slot="trigger"]'); for (const newItem of newItems) { processItem(newItem); } } } } } }; const observer = new MutationObserver(callback); observer.observe(document, { childList: true, subtree: true }); } function removeCover(){ let profile = document.querySelector(".introduction.marked"); if(profile && profile.style.display === "none"){ profile.style.display = "block"; for(let i=0;i<profile.parentElement.children.length;++i){ if(profile.parentElement.children[i].innerText === "系统维护,该内容暂不可见。"){ profile.parentElement.children[i].remove(); } } } } function alwaysRemoveCover(){ const observer = new MutationObserver(() => removeCover()); observer.observe(document,{ childList: true, subtree: true }); removeCover(); } const problemToColorMap = new Map(); class FetchRateLimiter{ constructor(limit) { // limit 以毫秒为单位,表示相邻两次 fetch 操作间的最小间隔 this.limit = limit; this.queue = []; this.queuePrior = []; this.active = false; this.requestCache = new Map(); } process() { this.active = 1; let resolve, reject, url; if(this.queuePrior.length > 0){ ({resolve, reject, url} = this.queuePrior.shift()); } else if(this.queue.length > 0){ ({resolve, reject, url} = this.queue.shift()); } else{ this.active = 0; return; } console.log(url); fetch(url) .then(resolve) .catch(reject); setTimeout(this.process.bind(this), this.limit); } push(url, prior) { if(this.requestCache.has(url)) return this.requestCache.get(url); const request = new Promise((resolve, reject) => { if(prior) this.queuePrior.push({url, resolve, reject}); else this.queue.push({url, resolve, reject}); if(!this.active) this.process(); }) .then((response) => { return response.text(); }); this.requestCache.set(url,request); return request; } } const limiter = new FetchRateLimiter(300); async function getProblemColor(problemid, prior=false){ if(window.location.href.startsWith('https://www.luogu.com.cn/record')){ const resultList = _feInstance.currentData.records.result; if(!resultList.lgbot1Visited){ for(const item of resultList){ problemToColorMap.set(item.problem.pid,`rgb(${problemDifficultyToColor[item.problem.difficulty].join(',')})`); } resultList.lgbot1Visited = true; } } if(/^https:\/\/www\.luogu\.com\.cn\/user\/\d+#practice$/.test(window.location.href)) { let problemList = _feInstance.currentData.submittedProblems; if(!problemList.lgbot1Visited){ for(const item of problemList){ problemToColorMap.set(item.pid,`rgb(${problemDifficultyToColor[item.difficulty].join(',')})`); } problemList.lgbot1Visited = true; } problemList = _feInstance.currentData.passedProblems; if(!problemList.lgbot1Visited){ for(const item of problemList){ problemToColorMap.set(item.pid,`rgb(${problemDifficultyToColor[item.difficulty].join(',')})`); } problemList.lgbot1Visited = true; } } if(problemToColorMap.has(problemid)) return problemToColorMap.get(problemid); const url = '/problem/'+problemid; let data; try{ data = await limiter.push(url, prior); } catch (error) { debugger; console.error('Error fetching user data:', error); console.log(problemid); return; } const parser = new DOMParser(); const doc = parser.parseFromString(data, 'text/html'); let scriptText = doc.querySelector("script").textContent; scriptText = scriptText.match(/window\._feInjection = JSON\.parse\(decodeURIComponent\("(.+)"\)\);/); if(!scriptText) return; scriptText = scriptText[1]; const _feInjection = JSON.parse(decodeURIComponent(scriptText)); const problemDifficulty = _feInjection.currentData.problem.difficulty; problemToColorMap.set(problemid,`rgb(${problemDifficultyToColor[problemDifficulty].join(',')})`); return problemToColorMap.get(problemid); } function isProblemId(problemid){ if(problemid.startsWith('AT_')) return true; if(!/[a-zA-Z]/.test(problemid)) return false; if(!/[0-9]/.test(problemid)) return false; return true; } async function addProblemColor(item){ let problemid = item.href.split('/').pop(); let prior = false; if(problemid.includes('?forum=')){ debugger; problemid = problemid.split('=').pop(); prior = true; } problemid = problemid.split('?')[0]; problemid = problemid.split('=').pop(); if(!isProblemId(problemid)) return; if(item.innerText.startsWith(problemid)){ const spanItem = item.children[0]; if(spanItem && spanItem.matches('span.pid') && spanItem.innerText === problemid){ const color = await getProblemColor(problemid, prior); spanItem.style.color = color; spanItem.style.fontWeight = 'bold'; } else{ const color = await getProblemColor(problemid, prior); const content = item.innerHTML; item.innerHTML = content.replace(problemid,`<b style="color: ${color};">${problemid}</b>`); } } } async function addProblemsColor(){ const observer = new MutationObserver(async (mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList') { for (const addedNode of mutation.addedNodes) { if (addedNode.nodeType === Node.ELEMENT_NODE) { const newItems = addedNode.querySelectorAll('a[href]'); if(addedNode.matches('a[href]')) addProblemColor(addedNode); for (const newItem of newItems) { addProblemColor(newItem); } } } } else if(mutation.type === 'characterData') { if(mutation.target.parentElement.matches('span.pid')){ mutation.target.parentElement.style.color = await getProblemColor(mutation.target.textContent); mutation.target.parentElement.style.fontWeight = 'bold'; } } } }); observer.observe(document, { childList: true, subtree: true, characterData: true, }); const nodelist = document.querySelectorAll('a[href]'); for(const i of nodelist){ addProblemColor(i); } } setTimeout(addSettingButton, 500); if(localStorage.getItem('lgbot1RemoveAd') === 'true'){ setTimeout(removeAd, 500); } if(localStorage.getItem('lgbot1Removeback') === 'true'){ removeBack(); } if(localStorage.getItem('lgbot1AddMessageLink') === 'true'){ if(window.location.href.startsWith('https://www.luogu.com.cn/chat')){ setTimeout(addMessageLink,500); } } if(localStorage.getItem('lgbot1RemoveCover') === 'true'){ setTimeout(alwaysRemoveCover, 500); } if(localStorage.getItem('lgbot1AddProblemsColor') === 'true'){ setTimeout(addProblemsColor, 500); } var html = '<button id="clearbenben">清除犇犇</button>' var TNode = document.createElement('div'); TNode.className = 'lg-article'; TNode.id = 're_log'; TNode.innerHTML = html; document.querySelector('div.lg-index-benben > div:nth-child(3)').insertAdjacentElement('afterend', TNode); document.getElementById('clearbenben').addEventListener('click', function() { switchMode('my'); function load() { console.log('page ' + feedPage); $.get("/feed/" + feedMode + "?page=" + feedPage, function (resp) { $feed.append(resp); $("#feed-more").children("a").text("点击查看更多...") $("[name=feed-delete]").click(function () { $.post("/api/feed/delete/" + $(this).attr('data-feed-id'), function () { switchMode('all'); }) }); feedPage++; if (resp.indexOf('没有更多动态了') != -1) {var l = $('#feed > li > div.am-comment-main > header > div > a:nth-child(2)'); function f(i) { $ .post("/api/feed/delete/"+ $(l[i]).attr('data-feed-id'), function() { console.log(i); if(i<l.length-1)setTimeout(`f(${i+1})`,200); }) } f(0); } else setTimeout(load, 200); }); } setTimeout(load, 1000); }); })(); document.querySelector(".operation").children.forEach(x=>x.style.zIndex=9999);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址