// ==UserScript== // @name Luogu Tasks // @namespace http://tampermonkey.net/ // @version 2.4.2 // @run-at document-start // @description 在洛谷侧边栏显示题单与自己存的题 // @author __OwO__ // @match https://www.luogu.com.cn/* // @grant GM_setValue // @grant GM_getValue // @grant unsafeWindow // @require https://cdn.staticfile.org/jquery/3.5.1/jquery.min.js // @require https://cdn.staticfile.org/sweetalert/2.1.2/sweetalert.min.js // @downloadURL https://update.greasyfork.icu/scripts/424363/Luogu%20Tasks.user.js // @updateURL https://update.greasyfork.icu/scripts/424363/Luogu%20Tasks.meta.js // ==/UserScript== // == define config == const inject_lantency = 300; // in ms // configs store in browser let configs = { set train(v) { GM_setValue("problem-helper-local-train-list", v); }, get train() { return GM_getValue("problem-helper-local-train-list") || {}; }, set local(v) { GM_setValue("problem-helper-local-id", v); }, get local() { return GM_getValue("problem-helper-local-id") || null; }, set hide_ac(v) { GM_setValue("problem-helper-hide-aced", v); }, get hide_ac() { return GM_getValue("problem-helper-hide-aced") || false; }, }; // == end config == // == lib functions == // get task info function getTask(id) { return new Promise((r) => { $.get(`https://www.luogu.com.cn/training/${id}?_contentOnly=any`).then( (u) => r(u.currentData.training) ); }); } // save train list let saveTrain = async (problems) => { return new Promise((r) => { $.ajax({ type: "POST", url: `https://www.luogu.com.cn/api/training/editProblems/${configs.local}`, beforeSend: function (request) { request.setRequestHeader( "x-csrf-token", $("meta[name='csrf-token']")[0].content ); }, contentType: "application/json;charset=UTF-8", data: JSON.stringify({ pids: problems }), success: () => r(), }); }); }; // save config let saveConfig = async (config) => { return new Promise((r) => { $.ajax({ type: "POST", url: `https://www.luogu.com.cn/paste/new`, beforeSend: function (request) { request.setRequestHeader( "x-csrf-token", $("meta[name='csrf-token']")[0].content ); }, contentType: "application/json;charset=UTF-8", data: JSON.stringify({ public: false, data: "#lgtsk" + JSON.stringify(config), }), success: () => r(), }); }); }; // load config let loadConfig = () => { return new Promise((r) => { $.get("https://www.luogu.com.cn/paste?_contentOnly").then((u) => { u = u.currentData.pastes.result; let nc = null; for (let i in u) { try { if (u[i].data.substr(0, 6) !== "#lgtsk") continue; let k = u[i].data; nc = JSON.parse(k.substr(6, k.lentgh)); break; } catch (e) {} } if (!nc) return r(0); configs.train = nc.train; configs.local = nc.local; configs.hide_ac = nc.hide_ac; r(1); }); }); }; // == end lib functions == $(document).ready(async () => { let local_problems; // == get verdict icon == let geticon = (pid, uid, your_score, full_score, is_aced = null) => { let res; let ua = (uid, pid) => ``; let ac = (uid, pid) => ``; let nt = (uid, pid) => ``; if (your_score == full_score || is_aced) res = ac(uid, pid); else if (your_score == null) res = nt(uid, pid); else res = ua(uid, pid); return `${res}`; }; // == render one list == let renderList = (title, content, float, id = "") => `
${float}

${title}

查看列表
`; let loadProblemList = async (id) => { return renderList( "...", "...", `删除`, id ); }; async function loadContent(id) { let task; let getList = (x, is_local) => { let id = task.problems[x].problem.pid; if (configs.hide_ac && task.userScore.status[id] && id != configs.local) return ""; return `
${geticon( id, task.userScore.user.uid, task.userScore.score[id], task.problems[x].problem.fullScore, task.userScore.status[id] )} ${ is_local ? ` ` : "" } ${id} ${task.problems[x].problem.title}
`; }; task = await getTask(id); let content = ""; if (id == configs.local) { $(`#list-float-${id}`).text(""); local_problems = task.problems.map((u) => u.problem.pid); } for (let i in task.problems) content += getList(i, id == configs.local); $(`#list-content-${id}`).html(content); $(`#list-${id} > h4`).text(task.title); $(`#list-float-${id}`).attr("data", task.id); } let getScore = async (sett) => { if (sett.method == "train") return { uid: sett.task.userScore.user.uid, scr: sett.task.userScore.score[sett.id], fscr: sett.task.problems[sett.id].problem.fullScore, }; else if (sett.method == "local") return new Promise((res, rej) => { $.get(`https://www.luogu.com.cn/problem/${sett.id}?_contentOnly`).then( (u) => { res({ uid: u.currentUser.uid, scr: u.currentData.problem.score, fscr: u.currentData.problem.fullScore, }); } ); }); }; function renderItem(title, id) { return `
${geticon( id, task.userScore.user.uid, task.userScore.score[id], task.problems[x].problem.fullScore, task.userScore.status[id] )} ${id} ${task.problems[x].problem.title}
`; } function loadListener() { $("#problem-helper-hide-aced").click((u) => { u = $(u.target); configs.hide_ac = u[0].checked; unsafeWindow._feInstance.$swalToastSuccess("修改成功"); loaderProblemEntry(); }); $("#problem-helper-save").click((u) => { saveConfig(configs); unsafeWindow._feInstance.$swalToastSuccess("保存成功"); loaderProblemEntry(); }); $("#problem-helper-load").click(async (u) => { if (await loadConfig()) unsafeWindow._feInstance.$swalToastSuccess("加载成功"); else unsafeWindow._feInstance.$swalToastError("加载失败"); loaderProblemEntry(); }); $("#problem-helper-set-local-list").keydown(function (e) { if (e.keyCode == 13) { configs.local = $("#problem-helper-set-local-list").val(); unsafeWindow._feInstance.$swalToastSuccess("修改成功"); loaderProblemEntry(); } }); $("#problem-helper-import").keydown(async (e) => { if (e.keyCode == 13) { let u = $("#problem-helper-import").val().trim().split(","); local_problems = (await getTask(configs.local)).problems.map( (u) => u.problem.pid ); let t = local_problems; for (let i in u) if (t.indexOf(u[i]) == -1) t.push(u[i]); saveTrain(t); unsafeWindow._feInstance.$swalToastSuccess("导入成功"); loaderProblemEntry(); } }); $("#problem-helper-add-to-list").click(async (u) => { let r = unsafeWindow.location.href.split("/"); r = r[r.length - 1]; while (r[r.length - 1] == "#") r = r.slice(0, r.length - 1); if (!unsafeWindow._feInjection.currentData.problem.title) return; local_problems = (await getTask(configs.local)).problems.map( (u) => u.problem.pid ); if (local_problems.indexOf(r) == -1) local_problems.push(r); saveTrain(local_problems); unsafeWindow._feInstance.$swalToastSuccess("添加成功"); loaderProblemEntry(); }); $(".problem-helper-delete-from-list").click(async (u) => { u = $(u.target).parents(".problem-helper-delete-from-list"); let r = u.attr("data"); local_problems = (await getTask(configs.local)).problems.map( (u) => u.problem.pid ); let now = local_problems; let newone = []; for (let i in now) if (now[i] != r) newone.push(now[i]); saveTrain(newone); unsafeWindow._feInstance.$swalToastSuccess("删除成功"); loaderProblemEntry(); }); $(".problem-helper-train-remove").click((u) => { u = $(u.target); let r = u.attr("data"); let now = configs.train; let newone = {}; for (let i in now) if (i != r) newone[i] = now[i]; configs.train = now; unsafeWindow._feInstance.$swalToastSuccess("删除成功"); loaderProblemEntry(); }); } async function loaderProblemEntry() { let lists = ""; let urls = configs.train; // console.log(urls); if (configs.local && !urls[configs.local]) urls[configs.local] = "本地列表"; for (let i in urls) lists += await loadProblemList(i); let content_promise = []; for (let i in urls) content_promise.push(loadContent(i)); Promise.all(content_promise).then(loadListener); lists += renderList( "设置", `
隐藏已通过题目
保存到洛谷云剪贴板
从洛谷云剪贴板加载
`, "" ); $("#problem-helper-entry").html(lists); $(".problem-helper-fold-on").click((u) => { u = $(u.target); u.parent().prev(".problem-helper-inner").removeAttr("style"); u.attr("style", "display:none;"); u.prev(".problem-helper-fold-off").removeAttr("style"); }); $(".problem-helper-fold-off").click((u) => { u = $(u.target); u.parent().prev(".problem-helper-inner").attr("style", "display:none;"); u.attr("style", "display:none;"); u.next(".problem-helper-fold-on").removeAttr("style"); }); } let deferredInjectProblemPage = () => { $(".problem-helper-container").remove(); $(".side").prepend( renderList( "做题助手", '
', '添加至列表' ) ); loaderProblemEntry(); }; let loadTrainList = (id) => { let local = configs.train; let getList = (id) => { return `
${id} ${local[id]}
`; }; let lists = ""; for (let i in local) lists += getList(i); return lists; }; let loaderTrainEntry = async () => { let lists = loadTrainList(); $("#problem-helper-entry").html(lists); $(".problem-helper-fold-on").click((u) => { u = $(u.target); u.parent().prev(".problem-helper-inner").removeAttr("style"); u.attr("style", "display:none;"); u.prev(".problem-helper-fold-off").removeAttr("style"); }); $(".problem-helper-fold-off").click((u) => { u = $(u.target); u.parent().prev(".problem-helper-inner").attr("style", "display:none;"); u.attr("style", "display:none;"); u.next(".problem-helper-fold-on").removeAttr("style"); }); $("#problem-helper-add-to-list").click((u) => { let r = unsafeWindow.location.href.split("/"); r = r[r.length - 1].split("#")[0]; if (!unsafeWindow._feInjection.currentData.training.title) return; let now = configs.train; if (!now) now = {}; now[r] = unsafeWindow._feInjection.currentData.training.title; configs.train = now; unsafeWindow._feInstance.$swalToastSuccess("添加成功"); loaderTrainEntry(); }); $(".problem-helper-delete-from-list").click((u) => { u = $(u.target).parents(".problem-helper-delete-from-list"); let r = u.attr("data"); let now = configs.train; let newone = {}; for (let i in now) if (i != r) newone[i] = now[i]; configs.train = newone; unsafeWindow._feInstance.$swalToastSuccess("删除成功"); loaderProblemEntry(); }); }; let deferredInjectTrainPage = () => { $(".problem-helper-container").remove(); $(".side").prepend( renderList( "做题助手", '
', '添加至列表' ) ); loaderTrainEntry(); }; let deferredInjectProblemlist = async () => { local_problems = (await getTask(configs.local)).problems.map( (u) => u.problem.pid ); $(".problem-helper-inlist-adder").remove(); let pid = "", name = ""; let h = (pid, name) => ` 添加 `; let rows = $(".row"); let trim = (s) => { return s.replace(/(^\s*)|(\s*$)/g, ""); }; rows.each((u) => { u = $(rows[u]); pid = u.children(".pid").text(); name = u.children(".title").children(".title").text(); name = trim(name); u.children(".title").prepend(h(pid, name)); }); $(".problem-helper-inlist-adder").click(async (u) => { u = $(u.target); let r = u.attr("data"); local_problems = (await getTask(configs.local)).problems.map( (u) => u.problem.pid ); let now = local_problems; if (now.indexOf(r) == -1) now.push(r); saveTrain(now); unsafeWindow._feInstance.$swalToastSuccess("添加成功"); }); }; /* main controller */ function inject() { if (unsafeWindow.location.href.includes("problem/list")) deferredInjectProblemlist(); else if (unsafeWindow.location.href.includes("training")) deferredInjectTrainPage(), deferredInjectProblemlist(); else if (unsafeWindow.location.href.includes("problem")) deferredInjectProblemPage(); } window.addEventListener("popstate", function (e) { setTimeout(inject, inject_lantency); }); setTimeout(inject, inject_lantency); $(document.body).append( `` ); });