xmoj-script 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/.config.yml +21 -0
- package/.github/ISSUE_TEMPLATE/bug.yml +30 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/docs.yml +25 -0
- package/.github/ISSUE_TEMPLATE/feature.yml +25 -0
- package/.github/dependabot.yml +12 -0
- package/.github/labeler.yml +12 -0
- package/.github/pull_request_template.md +10 -0
- package/.github/workflows/AutoLabelIssue.yml +24 -0
- package/.github/workflows/AutoLablePR.yml +23 -0
- package/.github/workflows/CodeQL.yml +29 -0
- package/.github/workflows/Daily.yml +23 -0
- package/.github/workflows/DependencyScan.yml +13 -0
- package/.github/workflows/Prerelease.yml +43 -0
- package/.github/workflows/Release.yml +45 -0
- package/.github/workflows/UpdateToRelease.yml +30 -0
- package/.github/workflows/UpdateVersion.yml +26 -0
- package/.gitmodules +3 -0
- package/.vscode/settings.json +148 -0
- package/404.html +362 -0
- package/AddonScript.js +10 -0
- package/CNAME +1 -0
- package/CODE_OF_CONDUCT.md +218 -0
- package/Compare.md +21 -0
- package/Images/1.png +0 -0
- package/Images/10.png +0 -0
- package/Images/11.png +0 -0
- package/Images/12.png +0 -0
- package/Images/13.png +0 -0
- package/Images/14.png +0 -0
- package/Images/15.png +0 -0
- package/Images/16.png +0 -0
- package/Images/17.png +0 -0
- package/Images/2.png +0 -0
- package/Images/3.png +0 -0
- package/Images/4.png +0 -0
- package/Images/5.png +0 -0
- package/Images/6.png +0 -0
- package/Images/7.png +0 -0
- package/Images/8.png +0 -0
- package/Images/9.png +0 -0
- package/LICENSE +674 -0
- package/README.md +86 -0
- package/SECURITY.md +12 -0
- package/Update/AutoLabel.js +179 -0
- package/Update/GetVersion.js +20 -0
- package/Update/UpdateToRelease.js +73 -0
- package/Update/UpdateVersion.js +80 -0
- package/Update/package.json +7 -0
- package/Update.json +702 -0
- package/XMOJ.png +0 -0
- package/XMOJ.user.js +4490 -0
- package/backend/.github/.config.yml +21 -0
- package/backend/.github/ISSUE_TEMPLATE/bug.yml +30 -0
- package/backend/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/backend/.github/ISSUE_TEMPLATE/feature.yml +25 -0
- package/backend/.github/dependabot.yml +12 -0
- package/backend/.github/labeler.yml +14 -0
- package/backend/LICENSE +661 -0
- package/backend/README.md +3 -0
- package/backend/Source/BBSSpider.js +50 -0
- package/backend/Source/Database.ts +188 -0
- package/backend/Source/Initial.sql +95 -0
- package/backend/Source/Output.ts +14 -0
- package/backend/Source/Process.ts +1227 -0
- package/backend/Source/Result.ts +24 -0
- package/backend/Source/XMOJ-bbs.code-workspace +11 -0
- package/backend/Source/index.ts +31 -0
- package/backend/bun.lockb +0 -0
- package/backend/package.json +19 -0
- package/backend/wrangler.toml +17 -0
- package/eula.md +121 -0
- package/favicon.ico +0 -0
- package/index.html +947 -0
- package/package.json +22 -0
- package/robots.txt +2 -0
- package/sitemap-live/0.xml +26 -0
- package/sitemap.xml +6 -0
package/XMOJ.user.js
ADDED
@@ -0,0 +1,4490 @@
|
|
1
|
+
// ==UserScript==
|
2
|
+
// @name XMOJ
|
3
|
+
// @version 1.1.1
|
4
|
+
// @description XMOJ增强脚本
|
5
|
+
// @author @XMOJ-Script-dev, @langningchen and the community
|
6
|
+
// @namespace https://github/langningchen
|
7
|
+
// @match http://*.xmoj.tech/*
|
8
|
+
// @match https://*.xmoj.tech/*
|
9
|
+
// @match http://116.62.212.172/*
|
10
|
+
// @require https://cdn.bootcdn.net/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
|
11
|
+
// @require https://cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/codemirror.min.js
|
12
|
+
// @require https://cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/mode/clike/clike.min.js
|
13
|
+
// @require https://cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/addon/merge/merge.js
|
14
|
+
// @require https://cdn.bootcdn.net/ajax/libs/diff_match_patch/20121119/diff_match_patch_uncompressed.js
|
15
|
+
// @require https://cdn.bootcdn.net/ajax/libs/dompurify/3.0.2/purify.min.js
|
16
|
+
// @require https://cdn.bootcdn.net/ajax/libs/marked/4.3.0/marked.min.js
|
17
|
+
// @grant GM_registerMenuCommand
|
18
|
+
// @grant GM_xmlhttpRequest
|
19
|
+
// @grant GM_setClipboard
|
20
|
+
// @grant unsafeWindow
|
21
|
+
// @connect api.xmoj-bbs.tech
|
22
|
+
// @connect challenges.cloudflare.com
|
23
|
+
// @connect cppinsights.io
|
24
|
+
// @connect 127.0.0.1
|
25
|
+
// @license GPL
|
26
|
+
// @icon data:image/x-icon;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQDmOhEA5gwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQDlGhEA5acSAObREQDl5xIA5WgRAOYEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgDoAhIA5moSAOW9EgDlNBEA5WYSAOb/EgDm/xEA5tcRAOY8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEA5TISAOa5EgDmaiELxR4jDcNSEQDlZhIA5v8SAOb/EgDm/xEA5pEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAOUUEQDmnxYD3R4iDcN4IgzC8yMNwpsRAOVmEgDm/xIA5v8SAOb/EQDmkQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiDcNMIg3D2yMNw/8jDcP/Iw3CmxEA5WYSAOb/EgDm/xIA5v8RAOaREwDmCAAA/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiDcMkIwzCtSMNw/8jDcP/Iw3D/yMNw/8jDcKbEQDlZhIA5v8SAOb/EgDm/xEA5ZMRAOU+EQDmrxEA5hgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiDcMMIwzChyMMw/kjDcP/Iw3D/yMNw/8jDcP/Iw3D/yMNwpsRAOVmEgDm/xIA5v8SAOb/EQDlkxEA5j4SAOb/EQDl7RIA5VoAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlDb8AIg3DWiMMwuMjDcP/Iw3D/yMNw/8jDcP/Iw3D/yMNw/8jDcP/Iw3CmxEA5WYSAOb/EgDm/xIA5v8RAOWTEQDmPhIA5v8SAOb/EgDm/xIA5a8RAOYWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIgzDMCMMwsEjDcP/Iw3D/yMNw/8jDcP/Iw3D/yMNw/8jDcP/Iw3D/yMNw/8iDcOZEQDlZhIA5v8SAOb/EgDm/xEA5ZMRAOY+EgDm/xIA5v8SAOb/EgDm/xEA5usSAOVYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjDMP5Iw3D/yMNw/8jDcP/Iw3D/yMNw/8jDMLrIwzCtSMNw/8jDcP/Iw3D/yINw5kRAOVmEgDm/xIA5v8SAOb/EQDlkxEA5iwSAOb3EgDm/xIA5v8SAOb/EgDm/xIA5v8SAOUsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMNw/sjDcP/Iw3D/yMNw/8iDcL7IgzDkyIMwxIjDcJiIw3D/yMNw/8jDcP/Ig3DmREA5WYSAOb/EgDm/xIA5v8SAOWTAAAAABIA5ioRAObLEgDm/xIA5v8SAOb/EgDm/xIA5jAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIw3D+yMNw/8jDcP/IwzC+SINwyoAAAAAAAAAACMNwmIjDcP/Iw3D/yMNw/8iDcOZEQDlZhIA5v8SAOb/EgDm/xIA5ZMAAAAAAAAAABIA5QQRAObREgDm/xIA5v8SAOb/EgDmMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjDcP7Iw3D/yMNw/8jDMP1AAD/AAAAAAAAAAAAIw3CYiMNw/8jDcP/Iw3D/yINw5kRAOVmEgDm/xIA5v8SAOb/EgDlkwAAAAAAAAAAAAAAABEA5sUSAOb/EgDm/xIA5v8SAOYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMNw/sjDcP/Iw3D/yMMw/UVAOkAAAAAAAAAAAAiDcNgIw3D/yMNw/8jDcP/Ig3DmREA5WYSAOb/EgDm/xIA5v8SAOWTAAAAAAAAAAAAAAAAEQDmxRIA5v8SAOb/EgDm/xIA5jAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIw3D+yMNw/8jDcP/Iw3D90AAvwAAAAAAAAAAACINw2AjDcP/Iw3D/yMNw/8iDcOZEQDlZhIA5v8SAOb/EgDm/xIA5ZMAAAAAAAAAAAAAAAARAObDEgDm/xIA5v8SAOb/EgDmMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjDcP7Iw3D/yMNw/8jDcP3QAC/AAAAAAAAAAAAIg3DYCMNw/8jDcP/Iw3D/yINw5kRAOVmEgDm/xIA5v8SAOb/EgDmlQAAAAAAAAAAAAAAABEA5sMSAOb/EgDm/xIA5v8SAOYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMNw/sjDcP/Iw3D/yMNw/dAAL8AAAAAAAAAAAAiDcNgIw3D/yMNw/8jDcP/Ig3DmREA5WYSAOb/EgDm/xIA5v8SAOaVAAAAAAAAAAAAAAAAEQDmwxIA5v8SAOb/EgDm/xIA5jAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIw3D+yMNw/8jDcP/IwzD+SMMwxgAAAAAAAAAACINw2AjDcP/Iw3D/yMNw/8iDcOZEQDlZhIA5v8SAOb/EgDm/xIA5pUAAAAAAAAAABIA5goRAObTEgDm/xIA5v8SAOb/EgDmMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjDcP7Iw3D/yMNw/8jDcP/IwzD6yINwlYAAAAAIg3DYCMNw/8jDcP/Iw3D/yINw5kRAOVmEgDm/xIA5v8SAOb/EgDmlRYA6AARAOZYEQDl4RIA5v8SAOb/EgDm/xIA5v8SAOYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMNw/sjDcP/Iw3D/yMNw/8jDcP/Iw3D/yINw2AjDMNeIw3D/yMNw/8jDcP/Ig3DmREA5WYSAOb/EgDm/xIA5v8SAOW7EQDmwxIA5v8SAOb/EgDm/xIA5v8SAOb/EgDm/xIA5jAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIg3CUiINw+kjDcP/Iw3D/yMNw/8jDcP/Ig3DciMMw14jDcP/Iw3D/yMNw/8iDcOZEQDlZhIA5v8SAOb/EgDm/xIA5v8SAOb/EgDm/xIA5v8SAOb/EgDm/xIA5usRAOVmEgDoAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIg3DFCMMw6kjDcP/Iw3D/yMNw/8iDcNyIwzDXiMNw/8jDcP/Iw3D/yINw5kRAOVmEgDm/xIA5v8SAOb/EgDm/xIA5v8SAOb/EgDm/xIA5fsSAOaVEQDlEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIMw1QiDMPpIw3D/yINw3IjDMNeIw3D/yMNw/8jDcP/Ig3DmREA5WYSAOb/EgDm/xIA5v8SAOb/EgDm/xIA5v8RAObBEgDlLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMMwhYiDcKrIg3DciMMw14jDcP/Iw3D/yMNw/8iDcOZEQDmZhIA5v8SAOb/EgDm/xIA5v8SAOXjEQDmWA4A4wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiDMISIg3CXCMNw/8jDcP/Iw3D/yINw5kRAOZmEgDm/xIA5v8RAOb3EQDlhxEA5gwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiDcJcIw3D/yMNw/8jDcP/Ig3DmREA5mYSAOb/EQDmsxIA5SQiDMJOIg3CNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACINwlwjDcP/Iw3D/yMNw/8iDcOZEQDlSBIA5koiDMIiIwzCrSINw4EiDcIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIg3DNCMNwuUjDcP/Iw3D/yINw5kjDMMGIwzDfCIMw7UiDMImAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwzCDCMNwn4iDMPzIgzCxyINw8MjDcNcHA7GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIMwhgiDcJ0Ig3CEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////+P////Y////eH///sh///8If//8CF//8AhP/+AIQ/+ACEH/AAhA/wMIYP8PCHD/Dwhw/w8IcP8PCHD/Dwhw/w8IcP8PCHD/Bwhg/wMIAP+DCAH/wwgD//MID//7CD///wh///8J////Dn///w3////H////////////8=
|
27
|
+
// ==/UserScript==
|
28
|
+
|
29
|
+
/**
|
30
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
31
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
32
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
33
|
+
*/
|
34
|
+
|
35
|
+
const CaptchaSiteKey = "0x4AAAAAAALBT58IhyDViNmv";
|
36
|
+
const AdminUserList = ["zhuchenrui2", "shanwenxiao", "admin", "shihongxi"];
|
37
|
+
|
38
|
+
let PurifyHTML = (Input) => {
|
39
|
+
return DOMPurify.sanitize(Input, {
|
40
|
+
"ALLOWED_TAGS": ["a", "b", "blockquote", "br", "code", "dd", "del", "div", "dl", "dt", "em", "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "hr", "i", "img", "ins", "kbd", "li", "ol", "p", "pre", "q", "rp", "rt", "ruby", "s", "samp", "strike", "strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "tt", "ul", "var"],
|
41
|
+
"ALLOWED_ATTR": ["abbr", "accept", "accept-charset", "accesskey", "action", "align", "alt", "axis", "border", "cellpadding", "cellspacing", "char", "charoff", "charset", "checked", "cite", "clear", "color", "cols", "colspan", "compact", "coords", "datetime", "dir", "disabled", "enctype", "for", "frame", "headers", "height", "href", "hreflang", "hspace", "ismap", "itemprop", "label", "lang", "longdesc", "maxlength", "media", "method", "multiple", "name", "nohref", "noshade", "nowrap", "prompt", "readonly", "rel", "rev", "rows", "rowspan", "rules", "scope", "selected", "shape", "size", "span", "src", "start", "summary", "tabindex", "target", "title", "type", "usemap", "valign", "value", "vspace", "width"]
|
42
|
+
});
|
43
|
+
}
|
44
|
+
let GetRelativeTime = (Input) => {
|
45
|
+
Input = new Date(Input);
|
46
|
+
let Now = new Date().getTime();
|
47
|
+
let Delta = Now - Input.getTime();
|
48
|
+
let RelativeName = "";
|
49
|
+
if (Delta < 0) { RelativeName = "未来"; }
|
50
|
+
else if (Delta <= 1000 * 60) { RelativeName = "刚刚"; }
|
51
|
+
else if (Delta <= 1000 * 60 * 60) { RelativeName = Math.floor((Now - Input) / 1000 / 60) + "分钟前"; }
|
52
|
+
else if (Delta <= 1000 * 60 * 60 * 24) { RelativeName = Math.floor((Now - Input) / 1000 / 60 / 60) + "小时前"; }
|
53
|
+
else if (Delta <= 1000 * 60 * 60 * 24 * 31) { RelativeName = Math.floor((Now - Input) / 1000 / 60 / 60 / 24) + "天前"; }
|
54
|
+
else if (Delta <= 1000 * 60 * 60 * 24 * 365) { RelativeName = Math.floor((Now - Input) / 1000 / 60 / 60 / 24 / 31) + "个月前"; }
|
55
|
+
else { RelativeName = Math.floor((Now - Input) / 1000 / 60 / 60 / 24 / 365) + "年前"; }
|
56
|
+
return "<span title=\"" + Input.toLocaleString() + "\">" + RelativeName + "</span>";
|
57
|
+
};
|
58
|
+
let RenderMathJax = async () => {
|
59
|
+
if (document.getElementById("MathJax-script") === null) {
|
60
|
+
var ScriptElement = document.createElement("script");
|
61
|
+
ScriptElement.id = "MathJax-script";
|
62
|
+
ScriptElement.type = "text/javascript";
|
63
|
+
ScriptElement.src = "https://cdn.bootcdn.net/ajax/libs/mathjax/3.0.5/es5/tex-chtml.js";
|
64
|
+
document.body.appendChild(ScriptElement);
|
65
|
+
await new Promise((Resolve) => {
|
66
|
+
ScriptElement.onload = () => {
|
67
|
+
Resolve();
|
68
|
+
};
|
69
|
+
});
|
70
|
+
}
|
71
|
+
MathJax.startup.input[0].findTeX.options.inlineMath.push(["$", "$"]);
|
72
|
+
MathJax.startup.input[0].findTeX.getPatterns();
|
73
|
+
MathJax.typeset();
|
74
|
+
};
|
75
|
+
let GetUserInfo = async (Username) => {
|
76
|
+
if (localStorage.getItem("UserScript-User-" + Username + "-UserRating") != null &&
|
77
|
+
new Date().getTime() - parseInt(localStorage.getItem("UserScript-User-" + Username + "-LastUpdateTime")) < 1000 * 60 * 60 * 24) {
|
78
|
+
return {
|
79
|
+
"Rating": localStorage.getItem("UserScript-User-" + Username + "-UserRating"),
|
80
|
+
"EmailHash": localStorage.getItem("UserScript-User-" + Username + "-EmailHash")
|
81
|
+
}
|
82
|
+
}
|
83
|
+
return await fetch("https://www.xmoj.tech/userinfo.php?user=" + Username).then((Response) => {
|
84
|
+
return Response.text();
|
85
|
+
}).then((Response) => {
|
86
|
+
if (Response.indexOf("No such User!") !== -1) {
|
87
|
+
return null;
|
88
|
+
}
|
89
|
+
const ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
90
|
+
let Rating = (parseInt(ParsedDocument.querySelector("#statics > tbody > tr:nth-child(4) > td:nth-child(2)").innerText.trim()) /
|
91
|
+
parseInt(ParsedDocument.querySelector("#statics > tbody > tr:nth-child(3) > td:nth-child(2)").innerText.trim())).toFixed(3) * 1000;
|
92
|
+
let Temp = ParsedDocument.querySelector("#statics > tbody").children;
|
93
|
+
let Email = Temp[Temp.length - 1].children[1].innerText.trim();
|
94
|
+
let EmailHash = CryptoJS.MD5(Email).toString();
|
95
|
+
localStorage.setItem("UserScript-User-" + Username + "-UserRating", Rating);
|
96
|
+
if (Email == "") {
|
97
|
+
EmailHash = undefined;
|
98
|
+
} else {
|
99
|
+
localStorage.setItem("UserScript-User-" + Username + "-EmailHash", EmailHash);
|
100
|
+
}
|
101
|
+
localStorage.setItem("UserScript-User-" + Username + "-LastUpdateTime", new Date().getTime());
|
102
|
+
return {
|
103
|
+
"Rating": Rating,
|
104
|
+
"EmailHash": EmailHash
|
105
|
+
}
|
106
|
+
});
|
107
|
+
};
|
108
|
+
/**
|
109
|
+
* Retrieves the badge information for a given user.
|
110
|
+
*
|
111
|
+
* @param {string} Username - The username of the user.
|
112
|
+
* @returns {Promise<Object>} - A promise that resolves to an object containing the badge information.
|
113
|
+
* @property {string} BackgroundColor - The background color of the badge.
|
114
|
+
* @property {string} Color - The color of the badge.
|
115
|
+
* @property {string} Content - The content of the badge.
|
116
|
+
*/
|
117
|
+
let GetUserBadge = async (Username) => {
|
118
|
+
if (localStorage.getItem("UserScript-User-" + Username + "-Badge-LastUpdateTime") != null &&
|
119
|
+
new Date().getTime() - parseInt(localStorage.getItem("UserScript-User-" + Username + "-Badge-LastUpdateTime")) < 1000 * 60 * 60 * 24) {
|
120
|
+
return {
|
121
|
+
"BackgroundColor": localStorage.getItem("UserScript-User-" + Username + "-Badge-BackgroundColor"),
|
122
|
+
"Color": localStorage.getItem("UserScript-User-" + Username + "-Badge-Color"),
|
123
|
+
"Content": localStorage.getItem("UserScript-User-" + Username + "-Badge-Content")
|
124
|
+
}
|
125
|
+
} else {
|
126
|
+
let BackgroundColor = "";
|
127
|
+
let Color = "";
|
128
|
+
let Content = "";
|
129
|
+
await new Promise((Resolve) => {
|
130
|
+
RequestAPI("GetBadge", {
|
131
|
+
"UserID": String(Username)
|
132
|
+
}, (Response) => {
|
133
|
+
if (Response.Success) {
|
134
|
+
BackgroundColor = Response.Data.BackgroundColor;
|
135
|
+
Color = Response.Data.Color;
|
136
|
+
Content = Response.Data.Content;
|
137
|
+
}
|
138
|
+
Resolve();
|
139
|
+
});
|
140
|
+
});
|
141
|
+
localStorage.setItem("UserScript-User-" + Username + "-Badge-BackgroundColor", BackgroundColor);
|
142
|
+
localStorage.setItem("UserScript-User-" + Username + "-Badge-Color", Color);
|
143
|
+
localStorage.setItem("UserScript-User-" + Username + "-Badge-Content", Content);
|
144
|
+
localStorage.setItem("UserScript-User-" + Username + "-Badge-LastUpdateTime", String(new Date().getTime()));
|
145
|
+
return {
|
146
|
+
"BackgroundColor": BackgroundColor,
|
147
|
+
"Color": Color,
|
148
|
+
"Content": Content
|
149
|
+
}
|
150
|
+
}
|
151
|
+
};
|
152
|
+
/**
|
153
|
+
* Sets the HTML content of an element to display a username with optional additional information.
|
154
|
+
* @param {HTMLElement} Element - The element to set the HTML content.
|
155
|
+
* @param {string} Username - The username to display.
|
156
|
+
* @param {boolean} [Simple=false] - Indicates whether to display additional information or not.
|
157
|
+
* @param {string} [Href="https://www.xmoj.tech/userinfo.php?user="] - The URL to link the username to.
|
158
|
+
* @returns {Promise<void>} - A promise that resolves when the HTML content is set.
|
159
|
+
*/
|
160
|
+
let GetUsernameHTML = async (Element, Username, Simple = false, Href = "https://www.xmoj.tech/userinfo.php?user=") => {
|
161
|
+
Username = Username.replaceAll(/[^a-zA-Z0-9]/g, "");
|
162
|
+
let ID = "Username-" + Username + "-" + Math.random();
|
163
|
+
Element.id = ID;
|
164
|
+
Element.innerHTML = `<div class="spinner-border spinner-border-sm me-2" role="status"></div>`;
|
165
|
+
Element.appendChild(document.createTextNode(Username));
|
166
|
+
let UserInfo = await GetUserInfo(Username);
|
167
|
+
if (UserInfo === null) {
|
168
|
+
document.getElementById(ID).innerHTML = "";
|
169
|
+
document.getElementById(ID).appendChild(document.createTextNode(Username));
|
170
|
+
return;
|
171
|
+
}
|
172
|
+
let HTMLData = "";
|
173
|
+
if (!Simple) {
|
174
|
+
HTMLData += `<img src="`;
|
175
|
+
if (UserInfo.EmailHash == undefined) {
|
176
|
+
HTMLData += `https://cravatar.cn/avatar/00000000000000000000000000000000?d=mp&f=y`;
|
177
|
+
}
|
178
|
+
else {
|
179
|
+
HTMLData += `https://cravatar.cn/avatar/${UserInfo.EmailHash}?d=retro`;
|
180
|
+
}
|
181
|
+
HTMLData += `" class="rounded me-2" style="width: 20px; height: 20px; ">`;
|
182
|
+
}
|
183
|
+
HTMLData += `<a href="${Href}${Username}" class="link-offset-2 link-underline-opacity-50 `
|
184
|
+
if (UtilityEnabled("Rating")) {
|
185
|
+
let Rating = UserInfo.Rating;
|
186
|
+
// if(AdminUserList.includes(Username)){
|
187
|
+
// HTMLData += "link-fuchsia"
|
188
|
+
// }
|
189
|
+
// else
|
190
|
+
if (Rating > 500) {
|
191
|
+
HTMLData += "link-danger";
|
192
|
+
} else if (Rating >= 400) {
|
193
|
+
HTMLData += "link-warning";
|
194
|
+
} else if (Rating >= 300) {
|
195
|
+
HTMLData += "link-success";
|
196
|
+
} else {
|
197
|
+
HTMLData += "link-info";
|
198
|
+
}
|
199
|
+
}
|
200
|
+
else {
|
201
|
+
HTMLData += "link-info";
|
202
|
+
}
|
203
|
+
HTMLData += `\";"></a>`;
|
204
|
+
if (!Simple) {
|
205
|
+
if (AdminUserList.includes(Username)) {
|
206
|
+
HTMLData += `<span class="badge text-bg-danger ms-2">管理员</span>`;
|
207
|
+
}
|
208
|
+
if (Username == "chenlangning") {
|
209
|
+
HTMLData += `<span class="badge ms-2" style="background-color: #6633cc; color: #ffffff">吉祥物</span>`;
|
210
|
+
}
|
211
|
+
let BadgeInfo = await GetUserBadge(Username);
|
212
|
+
if (BadgeInfo.Content != "") {
|
213
|
+
HTMLData += `<span class="badge ms-2" style="background-color: ${BadgeInfo.BackgroundColor}; color: ${BadgeInfo.Color}">${BadgeInfo.Content}</span>`;
|
214
|
+
}
|
215
|
+
}
|
216
|
+
document.getElementById(ID).innerHTML = HTMLData;
|
217
|
+
document.getElementById(ID).getElementsByTagName("a")[0].appendChild(document.createTextNode(Username));
|
218
|
+
};
|
219
|
+
/**
|
220
|
+
* Converts the given number of seconds to a formatted string representation of hours, minutes, and seconds.
|
221
|
+
* @param {number} InputSeconds - The number of seconds to convert.
|
222
|
+
* @returns {string} The formatted string representation of the input seconds.
|
223
|
+
*/
|
224
|
+
let SecondsToString = (InputSeconds) => {
|
225
|
+
let Hours = Math.floor(InputSeconds / 3600);
|
226
|
+
let Minutes = Math.floor((InputSeconds % 3600) / 60);
|
227
|
+
let Seconds = InputSeconds % 60;
|
228
|
+
return (Hours < 10 ? "0" : "") + Hours + ":" +
|
229
|
+
(Minutes < 10 ? "0" : "") + Minutes + ":" +
|
230
|
+
(Seconds < 10 ? "0" : "") + Seconds;
|
231
|
+
}
|
232
|
+
/**
|
233
|
+
* Converts a string in the format "hh:mm:ss" to the equivalent number of seconds.
|
234
|
+
* @param {string} InputString - The input string to convert.
|
235
|
+
* @returns {number} The number of seconds equivalent to the input string.
|
236
|
+
*/
|
237
|
+
let StringToSeconds = (InputString) => {
|
238
|
+
let SplittedString = InputString.split(":");
|
239
|
+
return parseInt(SplittedString[0]) * 60 * 60 +
|
240
|
+
parseInt(SplittedString[1]) * 60 +
|
241
|
+
parseInt(SplittedString[2]);
|
242
|
+
}
|
243
|
+
/**
|
244
|
+
* Converts a memory size in bytes to a human-readable string representation.
|
245
|
+
* @param {number} Memory - The memory size in bytes.
|
246
|
+
* @returns {string} The human-readable string representation of the memory size.
|
247
|
+
*/
|
248
|
+
let SizeToStringSize = (Memory) => {
|
249
|
+
if (UtilityEnabled("AddUnits")) {
|
250
|
+
if (Memory < 1024) {
|
251
|
+
return Memory + "B";
|
252
|
+
} else if (Memory < 1024 * 1024) {
|
253
|
+
return (Memory / 1024).toFixed(2) + "KB";
|
254
|
+
} else if (Memory < 1024 * 1024 * 1024) {
|
255
|
+
return (Memory / 1024 / 1024).toFixed(2) + "MB";
|
256
|
+
} else {
|
257
|
+
return (Memory / 1024 / 1024 / 1024).toFixed(2) + "GB";
|
258
|
+
}
|
259
|
+
}
|
260
|
+
else {
|
261
|
+
return Memory;
|
262
|
+
}
|
263
|
+
};
|
264
|
+
/**
|
265
|
+
* Converts a time value to a string representation.
|
266
|
+
* @param {number} Time - The time value to convert.
|
267
|
+
* @returns {string|number} - The converted time value as a string, or the original value if UtilityEnabled("AddUnits") is false.
|
268
|
+
*/
|
269
|
+
let TimeToStringTime = (Time) => {
|
270
|
+
if (UtilityEnabled("AddUnits")) {
|
271
|
+
if (Time < 1000) {
|
272
|
+
return Time + "ms";
|
273
|
+
} else if (Time < 1000 * 60) {
|
274
|
+
return (Time / 1000).toFixed(2) + "s";
|
275
|
+
}
|
276
|
+
}
|
277
|
+
else {
|
278
|
+
return Time;
|
279
|
+
}
|
280
|
+
};
|
281
|
+
/**
|
282
|
+
* Tidies up the given table by applying Bootstrap styling and removing unnecessary attributes.
|
283
|
+
*
|
284
|
+
* @param {HTMLElement} Table - The table element to be tidied up.
|
285
|
+
*/
|
286
|
+
let TidyTable = (Table) => {
|
287
|
+
if (UtilityEnabled("NewBootstrap") && Table != null) {
|
288
|
+
Table.className = "table table-hover";
|
289
|
+
Table.querySelector("thead > tr").removeAttribute("class");
|
290
|
+
Table.querySelector("thead > tr").removeAttribute("align");
|
291
|
+
Table.querySelector("thead > tr").innerHTML = Table.querySelector("thead > tr").innerHTML.replaceAll("td", "th");
|
292
|
+
let Temp = Table.querySelector("thead > tr").children;
|
293
|
+
for (let j = 0; j < Temp.length; j++) {
|
294
|
+
let Width = Temp[j].style.width;
|
295
|
+
Temp[j].removeAttribute("style");
|
296
|
+
Temp[j].style.width = Width;
|
297
|
+
Temp[j].removeAttribute("onclick");
|
298
|
+
Temp[j].removeAttribute("align");
|
299
|
+
}
|
300
|
+
Table.querySelector("tbody").className = "table-group-divider";
|
301
|
+
Temp = Table.querySelector("tbody").children;
|
302
|
+
for (let j = 0; j < Temp.length; j++) {
|
303
|
+
Temp[j].removeAttribute("align");
|
304
|
+
let Temp2 = Temp[j].querySelectorAll("*");
|
305
|
+
for (let k = 0; k < Temp2.length; k++) {
|
306
|
+
Temp2[k].classList.remove("left");
|
307
|
+
Temp2[k].classList.remove("center");
|
308
|
+
if (Temp2[k].className == "") {
|
309
|
+
Temp2[k].removeAttribute("class");
|
310
|
+
}
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
};
|
315
|
+
let UtilityEnabled = (Name) => {
|
316
|
+
if (localStorage.getItem("UserScript-Setting-" + Name) == null) {
|
317
|
+
//DebugMode is off by default
|
318
|
+
localStorage.setItem("UserScript-Setting-" + Name, (Name == "DebugMode" ? "false" : "true"));
|
319
|
+
}
|
320
|
+
return localStorage.getItem("UserScript-Setting-" + Name) == "true";
|
321
|
+
};
|
322
|
+
let RequestAPI = (Action, Data, CallBack) => {
|
323
|
+
let Session = "";
|
324
|
+
let Temp = document.cookie.split(";");
|
325
|
+
for (let i = 0; i < Temp.length; i++) {
|
326
|
+
if (Temp[i].includes("PHPSESSID")) {
|
327
|
+
Session = Temp[i].split("=")[1];
|
328
|
+
}
|
329
|
+
}
|
330
|
+
let PostData = {
|
331
|
+
"Authentication": {
|
332
|
+
"SessionID": Session,
|
333
|
+
"Username": CurrentUsername,
|
334
|
+
},
|
335
|
+
"Data": Data,
|
336
|
+
"Version": GM_info.script.version,
|
337
|
+
"DebugMode": UtilityEnabled("DebugMode")
|
338
|
+
};
|
339
|
+
let DataString = JSON.stringify(PostData);
|
340
|
+
GM_xmlhttpRequest({
|
341
|
+
method: "POST",
|
342
|
+
url: "https://api.xmoj-bbs.tech/" + Action,
|
343
|
+
// url: "http://127.0.0.1:8787/" + Action,
|
344
|
+
headers: {
|
345
|
+
"Content-Type": "application/json"
|
346
|
+
},
|
347
|
+
data: DataString,
|
348
|
+
onload: (Response) => {
|
349
|
+
try {
|
350
|
+
CallBack(JSON.parse(Response.responseText));
|
351
|
+
} catch (Error) {
|
352
|
+
console.log(Response.responseText);
|
353
|
+
CallBack({
|
354
|
+
"Success": false,
|
355
|
+
"Message": "JSON解析错误:" + Error,
|
356
|
+
"Data": null
|
357
|
+
});
|
358
|
+
}
|
359
|
+
}
|
360
|
+
});
|
361
|
+
};
|
362
|
+
|
363
|
+
GM_registerMenuCommand("清除缓存", () => {
|
364
|
+
let Temp = [];
|
365
|
+
for (let i = 0; i < localStorage.length; i++) {
|
366
|
+
if (localStorage.key(i).startsWith("UserScript-User-")) {
|
367
|
+
Temp.push(localStorage.key(i));
|
368
|
+
}
|
369
|
+
}
|
370
|
+
for (let i = 0; i < Temp.length; i++) {
|
371
|
+
localStorage.removeItem(Temp[i]);
|
372
|
+
}
|
373
|
+
location.reload();
|
374
|
+
});
|
375
|
+
GM_registerMenuCommand("重置数据", () => {
|
376
|
+
if (confirm("确定要重置数据吗?")) {
|
377
|
+
localStorage.clear();
|
378
|
+
location.reload();
|
379
|
+
}
|
380
|
+
});
|
381
|
+
|
382
|
+
let SearchParams = new URLSearchParams(location.search);
|
383
|
+
let ServerURL = (UtilityEnabled("DebugMode") ? "https://ghpages.xmoj-bbs.tech/" : "https://web.xmoj-bbs.tech")
|
384
|
+
let CurrentUsername = document.querySelector("#profile").innerText;
|
385
|
+
CurrentUsername = CurrentUsername.replaceAll(/[^a-zA-Z0-9]/g, "");
|
386
|
+
let IsAdmin = AdminUserList.indexOf(CurrentUsername) !== -1;
|
387
|
+
if (location.href.startsWith('http://')){
|
388
|
+
//use https
|
389
|
+
location.href = location.href.replace('http://', 'https://');
|
390
|
+
}
|
391
|
+
if (location.host != "www.xmoj.tech") {
|
392
|
+
location.host = "www.xmoj.tech";
|
393
|
+
}
|
394
|
+
else {
|
395
|
+
document.body.classList.add("placeholder-glow");
|
396
|
+
if (document.querySelector("#navbar") != null) {
|
397
|
+
if (document.querySelector("body > div > div.jumbotron") != null) {
|
398
|
+
document.querySelector("body > div > div.jumbotron").className = "mt-3";
|
399
|
+
}
|
400
|
+
|
401
|
+
if (UtilityEnabled("AutoLogin") &&
|
402
|
+
document.querySelector("#profile") != null &&
|
403
|
+
document.querySelector("#profile").innerHTML == "登录" &&
|
404
|
+
location.pathname != "/login.php" &&
|
405
|
+
location.pathname != "/loginpage.php" &&
|
406
|
+
location.pathname != "/lostpassword.php") {
|
407
|
+
localStorage.setItem("UserScript-LastPage", location.pathname + location.search);
|
408
|
+
location.href = "https://www.xmoj.tech/loginpage.php";
|
409
|
+
}
|
410
|
+
|
411
|
+
let Discussion = null;
|
412
|
+
if (UtilityEnabled("Discussion")) {
|
413
|
+
Discussion = document.createElement("li");
|
414
|
+
document.querySelector("#navbar > ul:nth-child(1)").appendChild(Discussion);
|
415
|
+
Discussion.innerHTML = "<a href=\"https://www.xmoj.tech/discuss3/discuss.php\">讨论</a>";
|
416
|
+
}
|
417
|
+
|
418
|
+
if (document.querySelector("#navbar > ul:nth-child(1)").childElementCount > 8 && UtilityEnabled("ACMRank")) {
|
419
|
+
let ACMRank = document.createElement("li");
|
420
|
+
document.querySelector("#navbar > ul:nth-child(1)").insertBefore(ACMRank, document.querySelector("#navbar > ul:nth-child(1) > li:nth-child(9)"));
|
421
|
+
ACMRank.innerHTML = "<a href=\"https://www.xmoj.tech/contestrank-oi.php?cid=" + Number(SearchParams.get("cid")) + "&ByUserScript=1\">ACM 排名</a>";
|
422
|
+
ACMRank.classList.add("active");
|
423
|
+
}
|
424
|
+
if (UtilityEnabled("Translate")) {
|
425
|
+
document.querySelector("#navbar > ul:nth-child(1) > li:nth-child(2) > a").innerText = "题库";
|
426
|
+
}
|
427
|
+
//send analytics
|
428
|
+
RequestAPI("SendData", {}, (result) => {
|
429
|
+
if (UtilityEnabled("DebugMode")) {
|
430
|
+
console.log(result);
|
431
|
+
}
|
432
|
+
});
|
433
|
+
if (UtilityEnabled("ReplaceLinks")) {
|
434
|
+
document.body.innerHTML =
|
435
|
+
String(document.body.innerHTML).replaceAll(
|
436
|
+
/\[<a href="([^"]*)">([^<]*)<\/a>\]/g,
|
437
|
+
"<button onclick=\"location.href='$1'\" class=\"btn btn-outline-secondary\">$2</button>");
|
438
|
+
}
|
439
|
+
if (UtilityEnabled("ReplaceXM")) {
|
440
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("我", "高老师");
|
441
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("小明", "高老师");
|
442
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("下海", "上海");
|
443
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("海上", "上海");
|
444
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("小红", "徐师娘");
|
445
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("小粉", "彩虹");
|
446
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("高老师们", "我们");
|
447
|
+
document.body.innerHTML = String(document.body.innerHTML).replaceAll("自高老师", "自我");
|
448
|
+
document.title = String(document.title).replaceAll("小明", "高老师");
|
449
|
+
}
|
450
|
+
|
451
|
+
if (UtilityEnabled("NewBootstrap")) {
|
452
|
+
let Temp = document.querySelectorAll("link");
|
453
|
+
for (var i = 0; i < Temp.length; i++) {
|
454
|
+
if (Temp[i].href.indexOf("bootstrap.min.css") != -1) {
|
455
|
+
Temp[i].remove();
|
456
|
+
}
|
457
|
+
else if (Temp[i].href.indexOf("white.css") != -1) {
|
458
|
+
Temp[i].remove();
|
459
|
+
}
|
460
|
+
else if (Temp[i].href.indexOf("semantic.min.css") != -1) {
|
461
|
+
Temp[i].remove();
|
462
|
+
}
|
463
|
+
else if (Temp[i].href.indexOf("bootstrap-theme.min.css") != -1) {
|
464
|
+
Temp[i].remove();
|
465
|
+
}
|
466
|
+
else if (Temp[i].href.indexOf("problem.css") != -1) {
|
467
|
+
Temp[i].remove();
|
468
|
+
}
|
469
|
+
}
|
470
|
+
if (UtilityEnabled("DarkMode")) {
|
471
|
+
document.querySelector("html").setAttribute("data-bs-theme", "dark");
|
472
|
+
}
|
473
|
+
else {
|
474
|
+
document.querySelector("html").setAttribute("data-bs-theme", "light");
|
475
|
+
}
|
476
|
+
|
477
|
+
let PopperScriptElement = document.createElement("script"); document.head.appendChild(PopperScriptElement);
|
478
|
+
PopperScriptElement.type = "module";
|
479
|
+
PopperScriptElement.src = "https://cdn.bootcdn.net/ajax/libs/popper.js/2.11.7/umd/popper.min.js";
|
480
|
+
let CodeMirrorStyleElement = document.createElement("link"); document.head.appendChild(CodeMirrorStyleElement);
|
481
|
+
CodeMirrorStyleElement.rel = "stylesheet";
|
482
|
+
CodeMirrorStyleElement.href = "https://cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/codemirror.min.css";
|
483
|
+
let CodeMirrorThemeStyleElement = document.createElement("link"); document.head.appendChild(CodeMirrorThemeStyleElement);
|
484
|
+
CodeMirrorThemeStyleElement.rel = "stylesheet";
|
485
|
+
CodeMirrorThemeStyleElement.href = "https://cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/theme/darcula.min.css";
|
486
|
+
let CodeMirrorMergeStyleElement = document.createElement("link"); document.head.appendChild(CodeMirrorMergeStyleElement);
|
487
|
+
CodeMirrorMergeStyleElement.rel = "stylesheet";
|
488
|
+
CodeMirrorMergeStyleElement.href = "https://cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/addon/merge/merge.min.css";
|
489
|
+
let BootstrapStyleElement = document.createElement("link"); document.head.appendChild(BootstrapStyleElement);
|
490
|
+
BootstrapStyleElement.rel = "stylesheet";
|
491
|
+
BootstrapStyleElement.href = "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0-alpha3/css/bootstrap.min.css";
|
492
|
+
await new Promise((Resolve) => {
|
493
|
+
PopperScriptElement.onload = () => {
|
494
|
+
Resolve();
|
495
|
+
};
|
496
|
+
});
|
497
|
+
Temp = document.querySelectorAll("script");
|
498
|
+
for (var i = 0; i < Temp.length; i++) {
|
499
|
+
if (Temp[i].src.indexOf("bootstrap.min.js") != -1) {
|
500
|
+
Temp[i].remove();
|
501
|
+
let BootstrapScriptElement = document.createElement("script"); document.head.appendChild(BootstrapScriptElement);
|
502
|
+
BootstrapScriptElement.type = "module";
|
503
|
+
BootstrapScriptElement.src = "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0-alpha3/js/bootstrap.min.js";
|
504
|
+
await new Promise((Resolve) => {
|
505
|
+
BootstrapScriptElement.onload = () => {
|
506
|
+
Resolve();
|
507
|
+
};
|
508
|
+
});
|
509
|
+
}
|
510
|
+
}
|
511
|
+
document.querySelector("nav").className = "navbar navbar-expand-lg bg-body-tertiary";
|
512
|
+
document.querySelector("#navbar > ul:nth-child(1)").classList = "navbar-nav me-auto mb-2 mb-lg-0";
|
513
|
+
document.querySelector("body > div > nav > div > div.navbar-header").outerHTML = `<a class="navbar-brand" href="https://www.xmoj.tech/">${UtilityEnabled("ReplaceXM") ? "高老师" : "小明"}的OJ</a><button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navbar"><span class="navbar-toggler-icon"></span></button>`;
|
514
|
+
document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li").classList = "nav-item dropdown";
|
515
|
+
document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > a").className = "nav-link dropdown-toggle";
|
516
|
+
document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > a > span.caret").remove();
|
517
|
+
Temp = document.querySelector("#navbar > ul:nth-child(1)").children;
|
518
|
+
for (var i = 0; i < Temp.length; i++) {
|
519
|
+
if (Temp[i].classList.contains("active")) {
|
520
|
+
Temp[i].classList.remove("active");
|
521
|
+
Temp[i].children[0].classList.add("active");
|
522
|
+
}
|
523
|
+
Temp[i].classList.add("nav-item");
|
524
|
+
Temp[i].children[0].classList.add("nav-link");
|
525
|
+
}
|
526
|
+
document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > a").setAttribute("data-bs-toggle", "dropdown");
|
527
|
+
document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > a").removeAttribute("data-toggle");
|
528
|
+
}
|
529
|
+
if (UtilityEnabled("RemoveUseless") && document.getElementsByTagName("marquee")[0] != undefined) {
|
530
|
+
document.getElementsByTagName("marquee")[0].remove();
|
531
|
+
}
|
532
|
+
|
533
|
+
let Style = document.createElement("style");
|
534
|
+
document.body.appendChild(Style);
|
535
|
+
Style.innerHTML = `
|
536
|
+
nav {
|
537
|
+
border-bottom-left-radius: 5px;
|
538
|
+
border-bottom-right-radius: 5px;
|
539
|
+
}
|
540
|
+
blockquote {
|
541
|
+
border-left: 5px solid var(--bs-secondary-bg);
|
542
|
+
padding: 0.5em 1em;
|
543
|
+
}
|
544
|
+
.status_y:hover {
|
545
|
+
box-shadow: #52c41a 1px 1px 10px 0px !important;
|
546
|
+
}
|
547
|
+
.status_n:hover {
|
548
|
+
box-shadow: #fe4c61 1px 1px 10px 0px !important;
|
549
|
+
}
|
550
|
+
.test-case {
|
551
|
+
border-radius: 5px !important;
|
552
|
+
}
|
553
|
+
.test-case:hover {
|
554
|
+
box-shadow: rgba(0, 0, 0, 0.3) 0px 10px 20px 3px !important;
|
555
|
+
}
|
556
|
+
.data[result-item] {
|
557
|
+
border-bottom-left-radius: 5px;
|
558
|
+
border-bottom-right-radius: 5px;
|
559
|
+
}
|
560
|
+
.software_list {
|
561
|
+
width: unset !important;
|
562
|
+
}
|
563
|
+
.software_item {
|
564
|
+
margin: 5px 10px !important;
|
565
|
+
background-color: var(--bs-secondary-bg) !important;
|
566
|
+
}
|
567
|
+
.item-txt {
|
568
|
+
color: var(--bs-emphasis-color) !important;
|
569
|
+
}
|
570
|
+
.cnt-row {
|
571
|
+
justify-content: inherit;
|
572
|
+
align-items: stretch;
|
573
|
+
width: 100% !important;
|
574
|
+
padding: 1rem 0;
|
575
|
+
}
|
576
|
+
.cnt-row-head {
|
577
|
+
padding: 0.8em 1em;
|
578
|
+
background-color: var(--bs-secondary-bg);
|
579
|
+
border-radius: 0.3rem 0.3rem 0 0;
|
580
|
+
width: 100%;
|
581
|
+
}
|
582
|
+
.cnt-row-body {
|
583
|
+
padding: 1em;
|
584
|
+
border: 1px solid var(--bs-secondary-bg);
|
585
|
+
border-top: none;
|
586
|
+
border-radius: 0 0 0.3rem 0.3rem;
|
587
|
+
}`;
|
588
|
+
if (UtilityEnabled("AddAnimation")) {
|
589
|
+
Style.innerHTML += `.status, .test-case {
|
590
|
+
transition: 0.5s !important;
|
591
|
+
}`;
|
592
|
+
}
|
593
|
+
if (UtilityEnabled("AddColorText")) {
|
594
|
+
Style.innerHTML += `.red {
|
595
|
+
color: red !important;
|
596
|
+
}
|
597
|
+
.green {
|
598
|
+
color: green !important;
|
599
|
+
}
|
600
|
+
.blue {
|
601
|
+
color: blue !important;
|
602
|
+
}`;
|
603
|
+
}
|
604
|
+
|
605
|
+
if (UtilityEnabled("RemoveUseless")) {
|
606
|
+
if (document.getElementsByClassName("footer")[0] != null) {
|
607
|
+
document.getElementsByClassName("footer")[0].remove();
|
608
|
+
}
|
609
|
+
}
|
610
|
+
|
611
|
+
if (UtilityEnabled("ReplaceYN")) {
|
612
|
+
Temp = document.getElementsByClassName("status_y");
|
613
|
+
for (let i = 0; i < Temp.length; i++) {
|
614
|
+
Temp[i].innerText = "✓";
|
615
|
+
}
|
616
|
+
Temp = document.getElementsByClassName("status_n");
|
617
|
+
for (let i = 0; i < Temp.length; i++) {
|
618
|
+
Temp[i].innerText = "✗";
|
619
|
+
}
|
620
|
+
}
|
621
|
+
|
622
|
+
Temp = document.getElementsByClassName("page-item");
|
623
|
+
for (let i = 0; i < Temp.length; i++) {
|
624
|
+
Temp[i].children[0].className = "page-link";
|
625
|
+
}
|
626
|
+
if (document.getElementsByClassName("pagination")[0] != null) {
|
627
|
+
document.getElementsByClassName("pagination")[0].classList.add("justify-content-center");
|
628
|
+
}
|
629
|
+
|
630
|
+
Temp = document.getElementsByTagName("table");
|
631
|
+
for (let i = 0; i < Temp.length; i++) {
|
632
|
+
if (Temp[i].querySelector("thead") != null) {
|
633
|
+
TidyTable(Temp[i]);
|
634
|
+
}
|
635
|
+
}
|
636
|
+
|
637
|
+
setInterval(() => {
|
638
|
+
try {
|
639
|
+
let CurrentDate = new Date(new Date().getTime() + diff);
|
640
|
+
let Year = CurrentDate.getFullYear();
|
641
|
+
if (Year > 3000) {
|
642
|
+
Year -= 1900;
|
643
|
+
}
|
644
|
+
let Month = CurrentDate.getMonth() + 1;
|
645
|
+
let _Date = CurrentDate.getDate();
|
646
|
+
let Hours = CurrentDate.getHours();
|
647
|
+
let Minutes = CurrentDate.getMinutes();
|
648
|
+
let Seconds = CurrentDate.getSeconds();
|
649
|
+
document.getElementById("nowdate").innerHTML =
|
650
|
+
Year + "-" +
|
651
|
+
(Month < 10 ? "0" : "") + Month + "-" +
|
652
|
+
(_Date < 10 ? "0" : "") + _Date + " " +
|
653
|
+
(Hours < 10 ? "0" : "") + Hours + ":" +
|
654
|
+
(Minutes < 10 ? "0" : "") + Minutes + ":" +
|
655
|
+
(Seconds < 10 ? "0" : "") + Seconds;
|
656
|
+
} catch (Error) { }
|
657
|
+
|
658
|
+
if (UtilityEnabled("ResetType")) {
|
659
|
+
if (document.querySelector("#profile") != undefined &&
|
660
|
+
document.querySelector("#profile").innerHTML == "登录") {
|
661
|
+
if (document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > ul").childNodes.length == 3) {
|
662
|
+
document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > ul").childNodes[3].remove();
|
663
|
+
}
|
664
|
+
}
|
665
|
+
else if (document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > ul > li:nth-child(3) > a > span") != undefined &&
|
666
|
+
document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > ul > li:nth-child(3) > a > span").innerText != "个人中心") {
|
667
|
+
let PopupUL = document.querySelector("#navbar > ul.nav.navbar-nav.navbar-right > li > ul");
|
668
|
+
PopupUL.innerHTML = `<li class="dropdown-item">修改帐号</li>
|
669
|
+
<li class="dropdown-item">个人中心</li>
|
670
|
+
<li class="dropdown-item">短消息</li>
|
671
|
+
<li class="dropdown-item">插件设置</li>
|
672
|
+
<li class="dropdown-item">注销</li>`
|
673
|
+
PopupUL.children[0].addEventListener("click", () => {
|
674
|
+
location.href = "https://www.xmoj.tech/modifypage.php";
|
675
|
+
});
|
676
|
+
PopupUL.children[1].addEventListener("click", () => {
|
677
|
+
location.href = "https://www.xmoj.tech/userinfo.php?user=" + CurrentUsername;
|
678
|
+
});
|
679
|
+
PopupUL.children[2].addEventListener("click", () => {
|
680
|
+
location.href = "https://www.xmoj.tech/mail.php";
|
681
|
+
});
|
682
|
+
PopupUL.children[3].addEventListener("click", () => {
|
683
|
+
location.href = "https://www.xmoj.tech/index.php?ByUserScript=1";
|
684
|
+
});
|
685
|
+
PopupUL.children[4].addEventListener("click", () => {
|
686
|
+
localStorage.removeItem("UserScript-Username");
|
687
|
+
localStorage.removeItem("UserScript-Password");
|
688
|
+
location.href = "https://www.xmoj.tech/logout.php";
|
689
|
+
});
|
690
|
+
Style.innerHTML += ".dropdown-item {";
|
691
|
+
Style.innerHTML += " cursor: pointer;";
|
692
|
+
Style.innerHTML += "}";
|
693
|
+
}
|
694
|
+
}
|
695
|
+
if (UtilityEnabled("AutoCountdown")) {
|
696
|
+
let Temp = document.getElementsByClassName("UpdateByJS");
|
697
|
+
for (let i = 0; i < Temp.length; i++) {
|
698
|
+
let EndTime = Temp[i].getAttribute("EndTime");
|
699
|
+
if (EndTime === null) {
|
700
|
+
Temp[i].classList.remove("UpdateByJS");
|
701
|
+
continue;
|
702
|
+
}
|
703
|
+
let TimeStamp = parseInt(EndTime) - new Date().getTime();
|
704
|
+
if (TimeStamp < 3000) {
|
705
|
+
Temp[i].classList.remove("UpdateByJS");
|
706
|
+
location.reload();
|
707
|
+
}
|
708
|
+
let CurrentDate = new Date(TimeStamp);
|
709
|
+
let Day = parseInt((TimeStamp / 1000 / 60 / 60 / 24).toFixed(0));
|
710
|
+
let Hour = CurrentDate.getUTCHours();
|
711
|
+
let Minute = CurrentDate.getUTCMinutes();
|
712
|
+
let Second = CurrentDate.getUTCSeconds();
|
713
|
+
Temp[i].innerHTML = (Day !== 0 ? Day + "天" : "") +
|
714
|
+
(Hour !== 0 ? (Hour < 10 ? "0" : "") + Hour + "小时" : "") +
|
715
|
+
(Minute !== 0 ? (Minute < 10 ? "0" : "") + Minute + "分" : "") +
|
716
|
+
(Second !== 0 ? (Second < 10 ? "0" : "") + Second + "秒" : "");
|
717
|
+
}
|
718
|
+
}
|
719
|
+
}, 100);
|
720
|
+
|
721
|
+
fetch(ServerURL + "/Update.json", { cache: "no-cache" })
|
722
|
+
.then((Response) => {
|
723
|
+
return Response.json();
|
724
|
+
})
|
725
|
+
.then((Response) => {
|
726
|
+
let CurrentVersion = GM_info.script.version;
|
727
|
+
let LatestVersion;
|
728
|
+
for (let i = Object.keys(Response.UpdateHistory).length - 1; i >= 0; i--) {
|
729
|
+
let VersionInfo = Object.keys(Response.UpdateHistory)[i];
|
730
|
+
if (UtilityEnabled("DebugMode") || Response.UpdateHistory[VersionInfo].Prerelease == false) {
|
731
|
+
LatestVersion = VersionInfo;
|
732
|
+
break;
|
733
|
+
}
|
734
|
+
}
|
735
|
+
if (CurrentVersion < LatestVersion) {
|
736
|
+
let UpdateDiv = document.createElement("div");
|
737
|
+
UpdateDiv.innerHTML = `<div class="alert alert-warning alert-dismissible fade show mt-2" role="alert">
|
738
|
+
<div>
|
739
|
+
XMOJ用户脚本发现新版本${LatestVersion},当前版本${CurrentVersion},点击
|
740
|
+
<a href="${ServerURL}/XMOJ.user.js" target="_blank" class="alert-link">此处</a>
|
741
|
+
更新
|
742
|
+
</div>
|
743
|
+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
744
|
+
</div>`;
|
745
|
+
document.querySelector("body > div").insertBefore(UpdateDiv, document.querySelector("body > div > div.mt-3"));
|
746
|
+
}
|
747
|
+
if (localStorage.getItem("UserScript-Update-LastVersion") != GM_info.script.version) {
|
748
|
+
localStorage.setItem("UserScript-Update-LastVersion", GM_info.script.version);
|
749
|
+
let UpdateDiv = document.createElement("div"); document.querySelector("body").appendChild(UpdateDiv);
|
750
|
+
UpdateDiv.className = "modal fade";
|
751
|
+
UpdateDiv.id = "UpdateModal";
|
752
|
+
UpdateDiv.tabIndex = -1;
|
753
|
+
let UpdateDialog = document.createElement("div"); UpdateDiv.appendChild(UpdateDialog);
|
754
|
+
UpdateDialog.className = "modal-dialog";
|
755
|
+
let UpdateContent = document.createElement("div"); UpdateDialog.appendChild(UpdateContent);
|
756
|
+
UpdateContent.className = "modal-content";
|
757
|
+
let UpdateHeader = document.createElement("div"); UpdateContent.appendChild(UpdateHeader);
|
758
|
+
UpdateHeader.className = "modal-header";
|
759
|
+
let UpdateTitle = document.createElement("h5"); UpdateHeader.appendChild(UpdateTitle);
|
760
|
+
UpdateTitle.className = "modal-title";
|
761
|
+
UpdateTitle.innerText = "更新日志";
|
762
|
+
let UpdateCloseButton = document.createElement("button"); UpdateHeader.appendChild(UpdateCloseButton);
|
763
|
+
UpdateCloseButton.type = "button";
|
764
|
+
UpdateCloseButton.className = "btn-close";
|
765
|
+
UpdateCloseButton.setAttribute("data-bs-dismiss", "modal");
|
766
|
+
let UpdateBody = document.createElement("div"); UpdateContent.appendChild(UpdateBody);
|
767
|
+
UpdateBody.className = "modal-body";
|
768
|
+
let UpdateFooter = document.createElement("div"); UpdateContent.appendChild(UpdateFooter);
|
769
|
+
UpdateFooter.className = "modal-footer";
|
770
|
+
let UpdateButton = document.createElement("button"); UpdateFooter.appendChild(UpdateButton);
|
771
|
+
UpdateButton.type = "button";
|
772
|
+
UpdateButton.className = "btn btn-secondary";
|
773
|
+
UpdateButton.setAttribute("data-bs-dismiss", "modal");
|
774
|
+
UpdateButton.innerText = "关闭";
|
775
|
+
let Version = Object.keys(Response.UpdateHistory)[Object.keys(Response.UpdateHistory).length - 1]
|
776
|
+
let Data = Response.UpdateHistory[Version];
|
777
|
+
let UpdateDataCard = document.createElement("div"); UpdateBody.appendChild(UpdateDataCard);
|
778
|
+
UpdateDataCard.className = "card mb-3";
|
779
|
+
let UpdateDataCardBody = document.createElement("div"); UpdateDataCard.appendChild(UpdateDataCardBody);
|
780
|
+
UpdateDataCardBody.className = "card-body";
|
781
|
+
let UpdateDataCardTitle = document.createElement("h5"); UpdateDataCardBody.appendChild(UpdateDataCardTitle);
|
782
|
+
UpdateDataCardTitle.className = "card-title";
|
783
|
+
UpdateDataCardTitle.innerText = Version;
|
784
|
+
let UpdateDataCardSubtitle = document.createElement("h6"); UpdateDataCardBody.appendChild(UpdateDataCardSubtitle);
|
785
|
+
UpdateDataCardSubtitle.className = "card-subtitle mb-2 text-muted";
|
786
|
+
UpdateDataCardSubtitle.innerHTML = GetRelativeTime(Data.UpdateDate);
|
787
|
+
let UpdateDataCardText = document.createElement("p"); UpdateDataCardBody.appendChild(UpdateDataCardText);
|
788
|
+
UpdateDataCardText.className = "card-text";
|
789
|
+
let UpdateDataCardList = document.createElement("ul"); UpdateDataCardText.appendChild(UpdateDataCardList);
|
790
|
+
UpdateDataCardList.className = "list-group list-group-flush";
|
791
|
+
for (let j = 0; j < Data.UpdateContents.length; j++) {
|
792
|
+
let UpdateDataCardListItem = document.createElement("li"); UpdateDataCardList.appendChild(UpdateDataCardListItem);
|
793
|
+
UpdateDataCardListItem.className = "list-group-item";
|
794
|
+
UpdateDataCardListItem.innerHTML =
|
795
|
+
"(<a href=\"https://github.com/XMOJ-Script-dev/XMOJ-Script/pull/" + Data.UpdateContents[j].PR + "\" target=\"_blank\">" +
|
796
|
+
"#" + Data.UpdateContents[j].PR + "</a>) " +
|
797
|
+
Data.UpdateContents[j].Description;
|
798
|
+
}
|
799
|
+
let UpdateDataCardLink = document.createElement("a"); UpdateDataCardBody.appendChild(UpdateDataCardLink);
|
800
|
+
UpdateDataCardLink.className = "card-link";
|
801
|
+
UpdateDataCardLink.href = "https://github.com/XMOJ-Script-dev/XMOJ-Script/releases/tag/" + Version;
|
802
|
+
UpdateDataCardLink.target = "_blank";
|
803
|
+
UpdateDataCardLink.innerText = "查看该版本";
|
804
|
+
new bootstrap.Modal(document.getElementById("UpdateModal")).show();
|
805
|
+
}
|
806
|
+
});
|
807
|
+
fetch(ServerURL + "/AddonScript.js", { cache: "no-cache" })
|
808
|
+
.then((Response) => {
|
809
|
+
return Response.text();
|
810
|
+
})
|
811
|
+
.then((Response) => {
|
812
|
+
eval(Response);
|
813
|
+
});
|
814
|
+
|
815
|
+
let ToastContainer = document.createElement("div");
|
816
|
+
ToastContainer.classList.add("toast-container", "position-fixed", "bottom-0", "end-0", "p-3");
|
817
|
+
document.body.appendChild(ToastContainer);
|
818
|
+
addEventListener("focus", () => {
|
819
|
+
if (UtilityEnabled("BBSPopup")) {
|
820
|
+
RequestAPI("GetBBSMentionList", {}, (Response) => {
|
821
|
+
if (Response.Success) {
|
822
|
+
ToastContainer.innerHTML = "";
|
823
|
+
let MentionList = Response.Data.MentionList;
|
824
|
+
for (let i = 0; i < MentionList.length; i++) {
|
825
|
+
let Toast = document.createElement("div");
|
826
|
+
Toast.classList.add("toast");
|
827
|
+
Toast.setAttribute("role", "alert");
|
828
|
+
let ToastHeader = document.createElement("div");
|
829
|
+
ToastHeader.classList.add("toast-header");
|
830
|
+
let ToastTitle = document.createElement("strong");
|
831
|
+
ToastTitle.classList.add("me-auto");
|
832
|
+
ToastTitle.innerHTML = "提醒:有人@你";
|
833
|
+
ToastHeader.appendChild(ToastTitle);
|
834
|
+
let ToastTime = document.createElement("small");
|
835
|
+
ToastTime.classList.add("text-body-secondary");
|
836
|
+
ToastTime.innerHTML = GetRelativeTime(MentionList[i].MentionTime);
|
837
|
+
ToastHeader.appendChild(ToastTime);
|
838
|
+
let ToastCloseButton = document.createElement("button");
|
839
|
+
ToastCloseButton.type = "button";
|
840
|
+
ToastCloseButton.classList.add("btn-close");
|
841
|
+
ToastCloseButton.setAttribute("data-bs-dismiss", "toast");
|
842
|
+
ToastHeader.appendChild(ToastCloseButton);
|
843
|
+
Toast.appendChild(ToastHeader);
|
844
|
+
let ToastBody = document.createElement("div");
|
845
|
+
ToastBody.classList.add("toast-body");
|
846
|
+
ToastBody.innerHTML = "讨论" + MentionList[i].PostTitle + "有新回复";
|
847
|
+
let ToastFooter = document.createElement("div");
|
848
|
+
ToastFooter.classList.add("mt-2", "pt-2", "border-top");
|
849
|
+
let ToastDismissButton = document.createElement("button");
|
850
|
+
ToastDismissButton.type = "button";
|
851
|
+
ToastDismissButton.classList.add("btn", "btn-secondary", "btn-sm", "me-2");
|
852
|
+
ToastDismissButton.innerText = "忽略";
|
853
|
+
ToastDismissButton.addEventListener("click", () => {
|
854
|
+
RequestAPI("ReadBBSMention", {
|
855
|
+
"MentionID": Number(MentionList[i].MentionID)
|
856
|
+
}, () => { });
|
857
|
+
Toast.remove();
|
858
|
+
});
|
859
|
+
ToastFooter.appendChild(ToastDismissButton);
|
860
|
+
let ToastViewButton = document.createElement("button");
|
861
|
+
ToastViewButton.type = "button";
|
862
|
+
ToastViewButton.classList.add("btn", "btn-primary", "btn-sm");
|
863
|
+
ToastViewButton.innerText = "查看";
|
864
|
+
ToastViewButton.addEventListener("click", () => {
|
865
|
+
open("https://www.xmoj.tech/discuss3/thread.php?tid=" + MentionList[i].PostID, "_blank");
|
866
|
+
RequestAPI("ReadBBSMention", {
|
867
|
+
"MentionID": Number(MentionList[i].MentionID)
|
868
|
+
}, () => { });
|
869
|
+
});
|
870
|
+
ToastFooter.appendChild(ToastViewButton);
|
871
|
+
ToastBody.appendChild(ToastFooter);
|
872
|
+
Toast.appendChild(ToastBody);
|
873
|
+
ToastContainer.appendChild(Toast);
|
874
|
+
new bootstrap.Toast(Toast).show();
|
875
|
+
}
|
876
|
+
}
|
877
|
+
});
|
878
|
+
}
|
879
|
+
if (UtilityEnabled("MessagePopup")) {
|
880
|
+
RequestAPI("GetMailMentionList", {}, async (Response) => {
|
881
|
+
if (Response.Success) {
|
882
|
+
if (!UtilityEnabled("BBSPopup")) {
|
883
|
+
ToastContainer.innerHTML = "";
|
884
|
+
}
|
885
|
+
let MentionList = Response.Data.MentionList;
|
886
|
+
for (let i = 0; i < MentionList.length; i++) {
|
887
|
+
let Toast = document.createElement("div");
|
888
|
+
Toast.classList.add("toast");
|
889
|
+
Toast.setAttribute("role", "alert");
|
890
|
+
let ToastHeader = document.createElement("div");
|
891
|
+
ToastHeader.classList.add("toast-header");
|
892
|
+
let ToastTitle = document.createElement("strong");
|
893
|
+
ToastTitle.classList.add("me-auto");
|
894
|
+
ToastTitle.innerHTML = "提醒:有新消息";
|
895
|
+
ToastHeader.appendChild(ToastTitle);
|
896
|
+
let ToastTime = document.createElement("small");
|
897
|
+
ToastTime.classList.add("text-body-secondary");
|
898
|
+
ToastTime.innerHTML = GetRelativeTime(MentionList[i].MentionTime);
|
899
|
+
ToastHeader.appendChild(ToastTime);
|
900
|
+
let ToastCloseButton = document.createElement("button");
|
901
|
+
ToastCloseButton.type = "button";
|
902
|
+
ToastCloseButton.classList.add("btn-close");
|
903
|
+
ToastCloseButton.setAttribute("data-bs-dismiss", "toast");
|
904
|
+
ToastHeader.appendChild(ToastCloseButton);
|
905
|
+
Toast.appendChild(ToastHeader);
|
906
|
+
let ToastBody = document.createElement("div");
|
907
|
+
ToastBody.classList.add("toast-body");
|
908
|
+
let ToastUser = document.createElement("span");
|
909
|
+
GetUsernameHTML(ToastUser, MentionList[i].FromUserID);
|
910
|
+
ToastBody.appendChild(ToastUser);
|
911
|
+
ToastBody.innerHTML += " 给你发了一封短消息";
|
912
|
+
let ToastFooter = document.createElement("div");
|
913
|
+
ToastFooter.classList.add("mt-2", "pt-2", "border-top");
|
914
|
+
let ToastDismissButton = document.createElement("button");
|
915
|
+
ToastDismissButton.type = "button";
|
916
|
+
ToastDismissButton.classList.add("btn", "btn-secondary", "btn-sm", "me-2");
|
917
|
+
ToastDismissButton.innerText = "忽略";
|
918
|
+
ToastDismissButton.addEventListener("click", () => {
|
919
|
+
RequestAPI("ReadMailMention", {
|
920
|
+
"MentionID": Number(MentionList[i].MentionID)
|
921
|
+
}, () => { });
|
922
|
+
});
|
923
|
+
ToastFooter.appendChild(ToastDismissButton);
|
924
|
+
let ToastViewButton = document.createElement("button");
|
925
|
+
ToastViewButton.type = "button";
|
926
|
+
ToastViewButton.classList.add("btn", "btn-primary", "btn-sm");
|
927
|
+
ToastViewButton.innerText = "查看";
|
928
|
+
ToastViewButton.addEventListener("click", () => {
|
929
|
+
open("https://www.xmoj.tech/mail.php?other=" + MentionList[i].FromUserID, "_blank");
|
930
|
+
RequestAPI("ReadMailMention", {
|
931
|
+
"MentionID": Number(MentionList[i].MentionID)
|
932
|
+
}, () => { });
|
933
|
+
});
|
934
|
+
ToastFooter.appendChild(ToastViewButton);
|
935
|
+
ToastBody.appendChild(ToastFooter);
|
936
|
+
Toast.appendChild(ToastBody);
|
937
|
+
ToastContainer.appendChild(Toast);
|
938
|
+
new bootstrap.Toast(Toast).show();
|
939
|
+
}
|
940
|
+
}
|
941
|
+
});
|
942
|
+
}
|
943
|
+
});
|
944
|
+
dispatchEvent(new Event("focus"));
|
945
|
+
|
946
|
+
|
947
|
+
if (location.pathname == "/index.php" || location.pathname == "/") {
|
948
|
+
if (new URL(location.href).searchParams.get("ByUserScript") != null) {
|
949
|
+
localStorage.setItem("UserScript-Opened", "true");
|
950
|
+
let Container = document.getElementsByClassName("mt-3")[0];
|
951
|
+
Container.innerHTML = "";
|
952
|
+
let Alert = document.createElement("div");
|
953
|
+
Alert.classList.add("alert");
|
954
|
+
Alert.classList.add("alert-primary");
|
955
|
+
Alert.role = "alert";
|
956
|
+
Alert.innerHTML = `欢迎您使用XMOJ增强脚本!点击
|
957
|
+
<a class="alert-link" href="https://www.xmoj.tech/modifypage.php?ByUserScript=1" target="_blank">此处</a>
|
958
|
+
查看更新日志。`;
|
959
|
+
Container.appendChild(Alert);
|
960
|
+
let UtilitiesCard = document.createElement("div");
|
961
|
+
UtilitiesCard.classList.add("card");
|
962
|
+
UtilitiesCard.classList.add("mb-3");
|
963
|
+
let UtilitiesCardHeader = document.createElement("div");
|
964
|
+
UtilitiesCardHeader.classList.add("card-header");
|
965
|
+
UtilitiesCardHeader.innerText = "XMOJ增强脚本功能列表";
|
966
|
+
UtilitiesCard.appendChild(UtilitiesCardHeader);
|
967
|
+
let UtilitiesCardBody = document.createElement("div");
|
968
|
+
UtilitiesCardBody.classList.add("card-body");
|
969
|
+
let CreateList = (Data) => {
|
970
|
+
let List = document.createElement("ul");
|
971
|
+
List.classList.add("list-group");
|
972
|
+
for (let i = 0; i < Data.length; i++) {
|
973
|
+
let Row = document.createElement("li");
|
974
|
+
Row.classList.add("list-group-item");
|
975
|
+
if (Data[i].Type == "A") {
|
976
|
+
Row.classList.add("list-group-item-success");
|
977
|
+
}
|
978
|
+
else if (Data[i].Type == "F") {
|
979
|
+
Row.classList.add("list-group-item-warning");
|
980
|
+
}
|
981
|
+
else if (Data[i].Type == "D") {
|
982
|
+
Row.classList.add("list-group-item-danger");
|
983
|
+
}
|
984
|
+
if (Data[i].Children == undefined) {
|
985
|
+
let CheckBox = document.createElement("input");
|
986
|
+
CheckBox.classList.add("form-check-input");
|
987
|
+
CheckBox.classList.add("me-1");
|
988
|
+
CheckBox.type = "checkbox";
|
989
|
+
CheckBox.id = Data[i].ID;
|
990
|
+
if (localStorage.getItem("UserScript-Setting-" + Data[i].ID) == null) {
|
991
|
+
localStorage.setItem("UserScript-Setting-" + Data[i].ID, "true");
|
992
|
+
}
|
993
|
+
if (localStorage.getItem("UserScript-Setting-" + Data[i].ID) == "false") {
|
994
|
+
CheckBox.checked = false;
|
995
|
+
}
|
996
|
+
else {
|
997
|
+
CheckBox.checked = true;
|
998
|
+
}
|
999
|
+
CheckBox.addEventListener("change", () => {
|
1000
|
+
return localStorage.setItem("UserScript-Setting-" + Data[i].ID, CheckBox.checked);
|
1001
|
+
});
|
1002
|
+
|
1003
|
+
Row.appendChild(CheckBox);
|
1004
|
+
let Label = document.createElement("label");
|
1005
|
+
Label.classList.add("form-check-label");
|
1006
|
+
Label.htmlFor = Data[i].ID;
|
1007
|
+
Label.innerText = Data[i].Name;
|
1008
|
+
Row.appendChild(Label);
|
1009
|
+
}
|
1010
|
+
else {
|
1011
|
+
let Label = document.createElement("label");
|
1012
|
+
Label.innerText = Data[i].Name;
|
1013
|
+
Row.appendChild(Label);
|
1014
|
+
}
|
1015
|
+
if (Data[i].Children != undefined) {
|
1016
|
+
Row.appendChild(CreateList(Data[i].Children));
|
1017
|
+
}
|
1018
|
+
List.appendChild(Row);
|
1019
|
+
}
|
1020
|
+
return List;
|
1021
|
+
};
|
1022
|
+
UtilitiesCardBody.appendChild(CreateList([
|
1023
|
+
{ "ID": "ACMRank", "Type": "A", "Name": "比赛ACM排名,并且能下载ACM排名" },
|
1024
|
+
{ "ID": "Discussion", "Type": "F", "Name": "恢复讨论与短消息功能" },
|
1025
|
+
{ "ID": "MoreSTD", "Type": "F", "Name": "查看到更多标程" },
|
1026
|
+
{
|
1027
|
+
"ID": "StudyMode", "Type": "A", "Name": "学术模式", "Children": [
|
1028
|
+
{ "ID": "ApplyData", "Type": "A", "Name": "获取数据功能" },
|
1029
|
+
{ "ID": "AutoCheat", "Type": "A", "Name": "自动提交当年代码" }
|
1030
|
+
]
|
1031
|
+
},
|
1032
|
+
{ "ID": "Rating", "Type": "A", "Name": "添加用户评分和用户名颜色" },
|
1033
|
+
{ "ID": "AutoRefresh", "Type": "A", "Name": "比赛列表、比赛排名界面自动刷新" },
|
1034
|
+
{ "ID": "AutoCountdown", "Type": "A", "Name": "比赛列表等界面的时间自动倒计时" },
|
1035
|
+
{ "ID": "DownloadPlayback", "Type": "A", "Name": "回放视频增加下载功能" },
|
1036
|
+
{ "ID": "ImproveACRate", "Type": "A", "Name": "自动提交已AC题目以提高AC率" },
|
1037
|
+
{ "ID": "AutoO2", "Type": "F", "Name": "代码提交界面自动选择O2优化" },
|
1038
|
+
{
|
1039
|
+
"ID": "Beautify", "Type": "F", "Name": "美化界面", "Children": [
|
1040
|
+
{ "ID": "NewBootstrap", "Type": "F", "Name": "使用新版的Bootstrap样式库*" },
|
1041
|
+
{ "ID": "ResetType", "Type": "F", "Name": "重新排版*" },
|
1042
|
+
{ "ID": "AddColorText", "Type": "A", "Name": "增加彩色文字" },
|
1043
|
+
{ "ID": "AddUnits", "Type": "A", "Name": "状态界面内存与耗时添加单位" },
|
1044
|
+
{ "ID": "DarkMode", "Type": "A", "Name": "使用暗色模式" },
|
1045
|
+
{ "ID": "AddAnimation", "Type": "A", "Name": "增加动画" },
|
1046
|
+
{ "ID": "ReplaceYN", "Type": "F", "Name": "题目前对错的Y和N替换为勾和叉" },
|
1047
|
+
{ "ID": "RemoveAlerts", "Type": "D", "Name": "去除多余反复的提示" },
|
1048
|
+
{ "ID": "Translate", "Type": "F", "Name": "统一使用中文,翻译了部分英文*" },
|
1049
|
+
{ "ID": "ReplaceLinks", "Type": "F", "Name": "将网站中所有以方括号包装的链接替换为按钮" },
|
1050
|
+
{ "ID": "RemoveUseless", "Type": "D", "Name": "删去无法使用的功能*" },
|
1051
|
+
{ "ID": "ReplaceXM", "Type": "F", "Name": "将网站中所有“小明”和“我”关键字替换为“高老师”,所有“小红”替换为“徐师娘”,所有“小粉”替换为“彩虹”,所有“下海”、“海上”替换为“上海”" }
|
1052
|
+
]
|
1053
|
+
},
|
1054
|
+
{ "ID": "AutoLogin", "Type": "A", "Name": "在需要登录的界面自动跳转到登陆界面" },
|
1055
|
+
{ "ID": "SavePassword", "Type": "A", "Name": "自动保存用户名与密码,免去每次手动输入密码的繁琐" },
|
1056
|
+
{ "ID": "CopySamples", "Type": "F", "Name": "题目界面测试样例有时复制无效" },
|
1057
|
+
{ "ID": "RefreshSolution", "Type": "F", "Name": "状态页面结果自动刷新每次只能刷新一个" },
|
1058
|
+
{ "ID": "CopyMD", "Type": "A", "Name": "复制题目或题解内容" },
|
1059
|
+
{ "ID": "OpenAllProblem", "Type": "A", "Name": "比赛题目界面一键打开所有题目" },
|
1060
|
+
{
|
1061
|
+
"ID": "CheckCode", "Type": "A", "Name": "提交代码前对代码进行检查", "Children": [
|
1062
|
+
{ "ID": "IOFile", "Type": "A", "Name": "是否使用了文件输入输出(如果需要使用)" },
|
1063
|
+
{ "ID": "CompileError", "Type": "A", "Name": "是否有编译错误" }
|
1064
|
+
]
|
1065
|
+
},
|
1066
|
+
{ "ID": "ExportACCode", "Type": "F", "Name": "导出AC代码每一道题目一个文件" },
|
1067
|
+
{ "ID": "LoginFailed", "Type": "F", "Name": "修复登录后跳转失败*" },
|
1068
|
+
{ "ID": "NewDownload", "Type": "A", "Name": "下载页面增加下载内容" },
|
1069
|
+
{ "ID": "CompareSource", "Type": "A", "Name": "比较代码" },
|
1070
|
+
{ "ID": "BBSPopup", "Type": "A", "Name": "讨论提醒" },
|
1071
|
+
{ "ID": "MessagePopup", "Type": "A", "Name": "短消息提醒" },
|
1072
|
+
{ "ID": "DebugMode", "Type": "A", "Name": "调试模式(仅供开发者使用)" }
|
1073
|
+
]));
|
1074
|
+
let UtilitiesCardFooter = document.createElement("div");
|
1075
|
+
UtilitiesCardFooter.className = "card-footer text-muted";
|
1076
|
+
UtilitiesCardFooter.innerText = "* 不建议关闭,可能会导致系统不稳定、界面错乱、功能缺失等问题\n绿色:增加功能 黄色:修改功能 红色:删除功能";
|
1077
|
+
UtilitiesCardBody.appendChild(UtilitiesCardFooter);
|
1078
|
+
UtilitiesCard.appendChild(UtilitiesCardBody);
|
1079
|
+
Container.appendChild(UtilitiesCard);
|
1080
|
+
let FeedbackCard = document.createElement("div");
|
1081
|
+
FeedbackCard.className = "card mb-3";
|
1082
|
+
let FeedbackCardHeader = document.createElement("div");
|
1083
|
+
FeedbackCardHeader.className = "card-header";
|
1084
|
+
FeedbackCardHeader.innerText = "反馈、源代码、联系作者";
|
1085
|
+
FeedbackCard.appendChild(FeedbackCardHeader);
|
1086
|
+
let FeedbackCardBody = document.createElement("div");
|
1087
|
+
FeedbackCardBody.className = "card-body";
|
1088
|
+
let FeedbackCardText = document.createElement("p");
|
1089
|
+
FeedbackCardText.className = "card-text";
|
1090
|
+
FeedbackCardText.innerText = "如果您有任何建议或者发现了bug,请前往本项目的GitHub页面并提交issue。提交issue前请先搜索是否有相同的issue,如果有请在该issue下留言。请在issue中尽可能详细地描述您的问题,并且附上您的浏览器版本、操作系统版本、脚本版本、复现步骤等信息。谢谢您支持本项目。";
|
1091
|
+
FeedbackCardBody.appendChild(FeedbackCardText);
|
1092
|
+
let FeedbackCardLink = document.createElement("a");
|
1093
|
+
FeedbackCardLink.className = "card-link";
|
1094
|
+
FeedbackCardLink.innerText = "GitHub";
|
1095
|
+
FeedbackCardLink.href = "https://github.com/XMOJ-Script-dev/XMOJ-Script";
|
1096
|
+
FeedbackCardBody.appendChild(FeedbackCardLink);
|
1097
|
+
FeedbackCard.appendChild(FeedbackCardBody);
|
1098
|
+
Container.appendChild(FeedbackCard);
|
1099
|
+
}
|
1100
|
+
else {
|
1101
|
+
let Temp = document.querySelector("body > div > div.mt-3 > div > div.col-md-8").children;
|
1102
|
+
let NewsData = [];
|
1103
|
+
for (let i = 0; i < Temp.length; i += 2) {
|
1104
|
+
let Title = Temp[i].children[0].innerText;
|
1105
|
+
let Time = 0;
|
1106
|
+
if (Temp[i].children[1] != null) {
|
1107
|
+
Time = Temp[i].children[1].innerText;
|
1108
|
+
}
|
1109
|
+
let Body = Temp[i + 1].innerHTML;
|
1110
|
+
NewsData.push({ "Title": Title, "Time": new Date(Time), "Body": Body });
|
1111
|
+
}
|
1112
|
+
document.querySelector("body > div > div.mt-3 > div > div.col-md-8").innerHTML = "";
|
1113
|
+
for (let i = 0; i < NewsData.length; i++) {
|
1114
|
+
let NewsRow = document.createElement("div");
|
1115
|
+
NewsRow.className = "cnt-row";
|
1116
|
+
let NewsRowHead = document.createElement("div");
|
1117
|
+
NewsRowHead.className = "cnt-row-head title";
|
1118
|
+
NewsRowHead.innerText = NewsData[i].Title;
|
1119
|
+
if (NewsData[i].Time != 0) {
|
1120
|
+
NewsRowHead.innerHTML += "<small class=\"ms-3\">" + NewsData[i].Time.toLocaleDateString() + "</small>";
|
1121
|
+
}
|
1122
|
+
NewsRow.appendChild(NewsRowHead);
|
1123
|
+
let NewsRowBody = document.createElement("div");
|
1124
|
+
NewsRowBody.className = "cnt-row-body";
|
1125
|
+
NewsRowBody.innerHTML = NewsData[i].Body;
|
1126
|
+
NewsRow.appendChild(NewsRowBody);
|
1127
|
+
document.querySelector("body > div > div.mt-3 > div > div.col-md-8").appendChild(NewsRow);
|
1128
|
+
}
|
1129
|
+
let CountDownData = document.querySelector("#countdown_list").innerHTML;
|
1130
|
+
document.querySelector("body > div > div.mt-3 > div > div.col-md-4").innerHTML = `<div class="cnt-row">
|
1131
|
+
<div class="cnt-row-head title">倒计时</div>
|
1132
|
+
<div class="cnt-row-body">${CountDownData}</div>
|
1133
|
+
</div>`;
|
1134
|
+
}
|
1135
|
+
} else if (location.pathname == "/problemset.php") {
|
1136
|
+
if (UtilityEnabled("Translate")) {
|
1137
|
+
document.querySelector("body > div > div.mt-3 > center > table:nth-child(2) > tbody > tr > td:nth-child(2) > form > input").placeholder = "题目编号";
|
1138
|
+
document.querySelector("body > div > div.mt-3 > center > table:nth-child(2) > tbody > tr > td:nth-child(2) > form > button").innerText = "确认";
|
1139
|
+
document.querySelector("body > div > div.mt-3 > center > table:nth-child(2) > tbody > tr > td:nth-child(3) > form > input").placeholder = "标题或内容";
|
1140
|
+
document.querySelector("#problemset > thead > tr > th:nth-child(1)").innerText = "状态";
|
1141
|
+
}
|
1142
|
+
if (UtilityEnabled("ResetType")) {
|
1143
|
+
document.querySelector("#problemset > thead > tr > th:nth-child(1)").style.width = "5%";
|
1144
|
+
document.querySelector("#problemset > thead > tr > th:nth-child(2)").style.width = "10%";
|
1145
|
+
document.querySelector("#problemset > thead > tr > th:nth-child(3)").style.width = "75%";
|
1146
|
+
document.querySelector("#problemset > thead > tr > th:nth-child(4)").style.width = "5%";
|
1147
|
+
document.querySelector("#problemset > thead > tr > th:nth-child(5)").style.width = "5%";
|
1148
|
+
}
|
1149
|
+
document.querySelector("body > div > div.mt-3 > center > table:nth-child(2)").outerHTML = `
|
1150
|
+
<div class="row">
|
1151
|
+
<div class="center col-md-3"></div>
|
1152
|
+
<div class="col-md-2">
|
1153
|
+
<form action="problem.php" class="input-group">
|
1154
|
+
<input class="form-control" type="number" name="id" placeholder="题目编号" min="0">
|
1155
|
+
<button class="btn btn-outline-secondary" type="submit">跳转</button>
|
1156
|
+
</form>
|
1157
|
+
</div>
|
1158
|
+
<div class="col-md-4">
|
1159
|
+
<form action="problemset.php" class="input-group">
|
1160
|
+
<input class="form-control" type="text" name="search" placeholder="标题或内容">
|
1161
|
+
<button class="btn btn-outline-secondary" type="submit">查找</button>
|
1162
|
+
</form>
|
1163
|
+
</div>
|
1164
|
+
</div>`;
|
1165
|
+
if (SearchParams.get("search") != null) {
|
1166
|
+
document.querySelector("body > div > div.mt-3 > center > div > div:nth-child(3) > form > input").value = SearchParams.get("search");
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
let Temp = document.querySelector("#problemset").rows;
|
1170
|
+
for (let i = 1; i < Temp.length; i++) {
|
1171
|
+
localStorage.setItem("UserScript-Problem-" + Temp[i].children[1].innerText + "-Name",
|
1172
|
+
Temp[i].children[2].innerText);
|
1173
|
+
}
|
1174
|
+
} else if (location.pathname == "/problem.php") {
|
1175
|
+
if (SearchParams.get("cid") != null) {
|
1176
|
+
document.getElementsByTagName("h2")[0].innerHTML += " (" +
|
1177
|
+
localStorage.getItem("UserScript-Contest-" + SearchParams.get("cid") +
|
1178
|
+
"-Problem-" + SearchParams.get("pid") + "-PID") +
|
1179
|
+
")";
|
1180
|
+
}
|
1181
|
+
if (document.querySelector("body > div > div.mt-3 > h2") != null) {
|
1182
|
+
document.querySelector("body > div > div.mt-3").innerHTML = "没有此题目或题目对你不可见";
|
1183
|
+
setTimeout(() => {
|
1184
|
+
location.href = "https://www.xmoj.tech/problemset.php";
|
1185
|
+
}, 1000);
|
1186
|
+
}
|
1187
|
+
else {
|
1188
|
+
let PID = localStorage.getItem("UserScript-Contest-" + SearchParams.get("cid") +
|
1189
|
+
"-Problem-" + SearchParams.get("pid") + "-PID");
|
1190
|
+
|
1191
|
+
document.querySelector("body > div > div.mt-3 > center").lastChild.style.marginLeft = "10px";
|
1192
|
+
//修复提交按钮
|
1193
|
+
let SubmitLink = document.querySelector('.mt-3 > center:nth-child(1) > a:nth-child(12)');
|
1194
|
+
if (SubmitLink == null) { //如果是比赛题目
|
1195
|
+
SubmitLink = document.querySelector('.mt-3 > center:nth-child(1) > a:nth-child(10)');
|
1196
|
+
}
|
1197
|
+
if (SubmitLink == null) {
|
1198
|
+
SubmitLink = document.querySelector('.mt-3 > center:nth-child(1) > a:nth-child(11)');
|
1199
|
+
}
|
1200
|
+
if (SubmitLink == null) {
|
1201
|
+
SubmitLink = document.querySelector('.mt-3 > center:nth-child(1) > a:nth-child(13)');
|
1202
|
+
}
|
1203
|
+
if (SubmitLink == null) {
|
1204
|
+
SubmitLink = document.querySelector('.mt-3 > center:nth-child(1) > a:nth-child(9)');
|
1205
|
+
}
|
1206
|
+
let SubmitButton = document.createElement('button');
|
1207
|
+
SubmitButton.id = 'SubmitButton';
|
1208
|
+
SubmitButton.className = 'btn btn-outline-secondary';
|
1209
|
+
SubmitButton.textContent = '提交';
|
1210
|
+
SubmitButton.href = SubmitLink.href;
|
1211
|
+
SubmitButton.onclick = function () {
|
1212
|
+
window.location.href = SubmitLink.href;
|
1213
|
+
console.log(SubmitLink.href);
|
1214
|
+
};
|
1215
|
+
|
1216
|
+
// Replace the <a> element with the button
|
1217
|
+
SubmitLink.parentNode.replaceChild(SubmitButton, SubmitLink);
|
1218
|
+
// Remove the button's outer []
|
1219
|
+
let str = document.querySelector('.mt-3 > center:nth-child(1)').innerHTML;
|
1220
|
+
let target = SubmitButton.outerHTML;
|
1221
|
+
let result = str.replace(new RegExp(`(.?)${target}(.?)`, 'g'), target);
|
1222
|
+
document.querySelector('.mt-3 > center:nth-child(1)').innerHTML = result;
|
1223
|
+
document.querySelector('html body.placeholder-glow div.container div.mt-3 center button#SubmitButton.btn.btn-outline-secondary').onclick = function () {
|
1224
|
+
window.location.href = SubmitLink.href;
|
1225
|
+
console.log(SubmitLink.href);
|
1226
|
+
};
|
1227
|
+
Temp = document.querySelectorAll(".sampledata");
|
1228
|
+
for (var i = 0; i < Temp.length; i++) {
|
1229
|
+
Temp[i].parentElement.className = "card";
|
1230
|
+
}
|
1231
|
+
if (UtilityEnabled("RemoveUseless")) {
|
1232
|
+
document.querySelector("h2.lang_en").remove();
|
1233
|
+
document.getElementsByTagName("center")[1].remove();
|
1234
|
+
}
|
1235
|
+
if (UtilityEnabled("CopySamples")) {
|
1236
|
+
$(".copy-btn").click((Event) => {
|
1237
|
+
let CurrentButton = $(Event.currentTarget);
|
1238
|
+
let span = CurrentButton.parent().last().find(".sampledata");
|
1239
|
+
if (!span.length) {
|
1240
|
+
CurrentButton.text("未找到代码块").addClass("done");
|
1241
|
+
setTimeout(() => {
|
1242
|
+
$(".copy-btn").text("复制").removeClass("done");
|
1243
|
+
}, 1000);
|
1244
|
+
return;
|
1245
|
+
}
|
1246
|
+
GM_setClipboard(span.text());
|
1247
|
+
CurrentButton.text("复制成功").addClass("done");
|
1248
|
+
setTimeout(() => {
|
1249
|
+
$(".copy-btn").text("复制").removeClass("done");
|
1250
|
+
}, 1000);
|
1251
|
+
//document.body.removeChild(textarea[0]);
|
1252
|
+
});
|
1253
|
+
}
|
1254
|
+
let IOFileElement = document.querySelector("body > div > div.mt-3 > center > h3");
|
1255
|
+
if (IOFileElement != null) {
|
1256
|
+
while (IOFileElement.childNodes.length >= 1) {
|
1257
|
+
IOFileElement.parentNode.insertBefore(IOFileElement.childNodes[0], IOFileElement);
|
1258
|
+
}
|
1259
|
+
IOFileElement.parentNode.insertBefore(document.createElement("br"), IOFileElement);
|
1260
|
+
IOFileElement.remove();
|
1261
|
+
let Temp = document.querySelector("body > div > div.mt-3 > center").childNodes[2].data.trim();
|
1262
|
+
let IOFilename = Temp.substring(0, Temp.length - 3);
|
1263
|
+
localStorage.setItem("UserScript-Problem-" + PID + "-IOFilename", IOFilename);
|
1264
|
+
}
|
1265
|
+
|
1266
|
+
if (UtilityEnabled("CopyMD")) {
|
1267
|
+
await fetch(location.href).then((Response) => {
|
1268
|
+
return Response.text();
|
1269
|
+
}).then((Response) => {
|
1270
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
1271
|
+
let Temp = ParsedDocument.querySelectorAll(".cnt-row");
|
1272
|
+
for (let i = 0; i < Temp.length; i++) {
|
1273
|
+
if (Temp[i].children[1].children[0].className == "content") {
|
1274
|
+
let CopyMDButton = document.createElement("button");
|
1275
|
+
CopyMDButton.className = "btn btn-sm btn-outline-secondary copy-btn";
|
1276
|
+
CopyMDButton.innerText = "复制";
|
1277
|
+
CopyMDButton.style.marginLeft = "10px";
|
1278
|
+
CopyMDButton.type = "button";
|
1279
|
+
document.querySelectorAll(".cnt-row")[i].children[0].appendChild(CopyMDButton);
|
1280
|
+
CopyMDButton.addEventListener("click", () => {
|
1281
|
+
GM_setClipboard(Temp[i].children[1].children[0].innerText.trim().replaceAll("\n\t", "\n").replaceAll("\n\n", "\n").replaceAll("\n\n", "\n"));
|
1282
|
+
CopyMDButton.innerText = "复制成功";
|
1283
|
+
setTimeout(() => {
|
1284
|
+
CopyMDButton.innerText = "复制";
|
1285
|
+
}, 1000);
|
1286
|
+
});
|
1287
|
+
}
|
1288
|
+
}
|
1289
|
+
});
|
1290
|
+
}
|
1291
|
+
|
1292
|
+
if (UtilityEnabled("Discussion")) {
|
1293
|
+
let DiscussButton = document.createElement("button");
|
1294
|
+
DiscussButton.className = "btn btn-outline-secondary position-relative";
|
1295
|
+
DiscussButton.innerHTML = `讨论`;
|
1296
|
+
DiscussButton.style.marginLeft = "10px";
|
1297
|
+
DiscussButton.type = "button";
|
1298
|
+
DiscussButton.addEventListener("click", () => {
|
1299
|
+
if (SearchParams.get("cid") != null) {
|
1300
|
+
open("https://www.xmoj.tech/discuss3/discuss.php?pid=" + PID, "_blank");
|
1301
|
+
}
|
1302
|
+
else {
|
1303
|
+
open("https://www.xmoj.tech/discuss3/discuss.php?pid=" + SearchParams.get("id"), "_blank");
|
1304
|
+
}
|
1305
|
+
});
|
1306
|
+
document.querySelector("body > div > div.mt-3 > center").appendChild(DiscussButton);
|
1307
|
+
let UnreadBadge = document.createElement("span");
|
1308
|
+
UnreadBadge.className = "position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger";
|
1309
|
+
UnreadBadge.style.display = "none";
|
1310
|
+
DiscussButton.appendChild(UnreadBadge);
|
1311
|
+
|
1312
|
+
let RefreshCount = () => {
|
1313
|
+
RequestAPI("GetPostCount", {
|
1314
|
+
"ProblemID": Number(PID)
|
1315
|
+
}, (Response) => {
|
1316
|
+
if (Response.Success) {
|
1317
|
+
if (Response.Data.DiscussCount != 0) {
|
1318
|
+
UnreadBadge.innerText = Response.Data.DiscussCount;
|
1319
|
+
UnreadBadge.style.display = "";
|
1320
|
+
}
|
1321
|
+
}
|
1322
|
+
});
|
1323
|
+
};
|
1324
|
+
RefreshCount();
|
1325
|
+
addEventListener("focus", RefreshCount);
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
let Tables = document.getElementsByTagName("table");
|
1329
|
+
for (let i = 0; i < Tables.length; i++) {
|
1330
|
+
TidyTable(Tables[i]);
|
1331
|
+
}
|
1332
|
+
}
|
1333
|
+
Style.innerHTML += "code, kbd, pre, samp {";
|
1334
|
+
Style.innerHTML += " font-family: monospace, Consolas, 'Courier New';";
|
1335
|
+
Style.innerHTML += " font-size: 1rem;";
|
1336
|
+
Style.innerHTML += "}";
|
1337
|
+
Style.innerHTML += "pre {";
|
1338
|
+
Style.innerHTML += " padding: 0.3em 0.5em;";
|
1339
|
+
Style.innerHTML += " margin: 0.5em 0;";
|
1340
|
+
Style.innerHTML += "}";
|
1341
|
+
Style.innerHTML += ".in-out {";
|
1342
|
+
Style.innerHTML += " overflow: hidden;";
|
1343
|
+
Style.innerHTML += " display: flex;";
|
1344
|
+
Style.innerHTML += " padding: 0.5em 0;";
|
1345
|
+
Style.innerHTML += "}";
|
1346
|
+
Style.innerHTML += ".in-out .in-out-item {";
|
1347
|
+
Style.innerHTML += " flex: 1;";
|
1348
|
+
Style.innerHTML += " overflow: hidden;";
|
1349
|
+
Style.innerHTML += "}";
|
1350
|
+
Style.innerHTML += ".cnt-row .title {";
|
1351
|
+
Style.innerHTML += " font-weight: bolder;";
|
1352
|
+
Style.innerHTML += " font-size: 1.1rem;";
|
1353
|
+
Style.innerHTML += "}";
|
1354
|
+
Style.innerHTML += ".cnt-row .content {";
|
1355
|
+
Style.innerHTML += " overflow: hidden;";
|
1356
|
+
Style.innerHTML += "}";
|
1357
|
+
Style.innerHTML += "a.copy-btn {";
|
1358
|
+
Style.innerHTML += " float: right;";
|
1359
|
+
Style.innerHTML += " padding: 0 0.4em;";
|
1360
|
+
Style.innerHTML += " border: 1px solid var(--bs-primary);";
|
1361
|
+
Style.innerHTML += " border-radius: 3px;";
|
1362
|
+
Style.innerHTML += " color: var(--bs-primary);";
|
1363
|
+
Style.innerHTML += " cursor: pointer;";
|
1364
|
+
Style.innerHTML += "}";
|
1365
|
+
Style.innerHTML += "a.copy-btn:hover {";
|
1366
|
+
Style.innerHTML += " background-color: var(--bs-secondary-bg);";
|
1367
|
+
Style.innerHTML += "}";
|
1368
|
+
Style.innerHTML += "a.done, a.done:hover {";
|
1369
|
+
Style.innerHTML += " background-color: var(--bs-primary);";
|
1370
|
+
Style.innerHTML += " color: white;";
|
1371
|
+
Style.innerHTML += "}";
|
1372
|
+
} else if (location.pathname == "/status.php") {
|
1373
|
+
if (SearchParams.get("ByUserScript") == null) {
|
1374
|
+
document.querySelector("body > script:nth-child(5)").remove();
|
1375
|
+
if (UtilityEnabled("NewBootstrap")) {
|
1376
|
+
document.querySelector("#simform").outerHTML = `<form id="simform" class="justify-content-center form-inline row g-2" action="status.php" method="get" style="padding-bottom: 7px;">
|
1377
|
+
<input class="form-control" type="text" size="4" name="user_id" value="${CurrentUsername} "style="display: none;">
|
1378
|
+
<div class="col-md-1">
|
1379
|
+
<label for="problem_id" class="form-label">题目编号</label>
|
1380
|
+
<input type="text" class="form-control" id="problem_id" name="problem_id" size="4">
|
1381
|
+
</div>
|
1382
|
+
<div class="col-md-1">
|
1383
|
+
<label for="language" class="form-label">语言</label>
|
1384
|
+
<select id="language" name="language" class="form-select">
|
1385
|
+
<option value="-1" selected="">全部</option>
|
1386
|
+
<option value="0">C</option>
|
1387
|
+
<option value="1">C++</option>
|
1388
|
+
<option value="2">Pascal</option>
|
1389
|
+
</select>
|
1390
|
+
</div><div class="col-md-1">
|
1391
|
+
<label for="jresult" class="form-label">结果</label>
|
1392
|
+
<select id="jresult" name="jresult" class="form-select">
|
1393
|
+
<option value="-1" selected="">全部</option>
|
1394
|
+
<option value="4">正确</option>
|
1395
|
+
<option value="5">格式错误</option>
|
1396
|
+
<option value="6">答案错误</option>
|
1397
|
+
<option value="7">时间超限</option>
|
1398
|
+
<option value="8">内存超限</option>
|
1399
|
+
<option value="9">输出超限</option>
|
1400
|
+
<option value="10">运行错误</option>
|
1401
|
+
<option value="11">编译错误</option>
|
1402
|
+
<option value="0">等待</option>
|
1403
|
+
<option value="1">等待重判</option>
|
1404
|
+
<option value="2">编译中</option>
|
1405
|
+
<option value="3">运行并评判</option>
|
1406
|
+
</select>
|
1407
|
+
</div>
|
1408
|
+
<div class="col-md-1">
|
1409
|
+
<button type="submit" class="btn btn-primary">查找</button>
|
1410
|
+
</div><div id="csrf"></div></form>`;
|
1411
|
+
}
|
1412
|
+
|
1413
|
+
if (UtilityEnabled("ImproveACRate")) {
|
1414
|
+
let ImproveACRateButton = document.createElement("button");
|
1415
|
+
document.querySelector("body > div.container > div > div.input-append").appendChild(ImproveACRateButton);
|
1416
|
+
ImproveACRateButton.className = "btn btn-outline-secondary";
|
1417
|
+
ImproveACRateButton.innerText = "提高正确率";
|
1418
|
+
ImproveACRateButton.disabled = true;
|
1419
|
+
let ACProblems = [];
|
1420
|
+
await fetch("https://www.xmoj.tech/userinfo.php?user=" + CurrentUsername)
|
1421
|
+
.then((Response) => {
|
1422
|
+
return Response.text();
|
1423
|
+
}).then((Response) => {
|
1424
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
1425
|
+
ImproveACRateButton.innerText += "(" + (parseInt(ParsedDocument.querySelector("#statics > tbody > tr:nth-child(4) > td:nth-child(2)").innerText) / parseInt(ParsedDocument.querySelector("#statics > tbody > tr:nth-child(3) > td:nth-child(2)").innerText) * 100).toFixed(2) + "%)";
|
1426
|
+
let Temp = ParsedDocument.querySelector("#statics > tbody > tr:nth-child(2) > td:nth-child(3) > script").innerText.split("\n")[5].split(";");
|
1427
|
+
for (let i = 0; i < Temp.length; i++) {
|
1428
|
+
ACProblems.push(Number(Temp[i].substring(2, Temp[i].indexOf(","))));
|
1429
|
+
}
|
1430
|
+
ImproveACRateButton.disabled = false;
|
1431
|
+
});
|
1432
|
+
ImproveACRateButton.addEventListener("click", async () => {
|
1433
|
+
ImproveACRateButton.disabled = true;
|
1434
|
+
let SubmitTimes = 3;
|
1435
|
+
let Count = 0;
|
1436
|
+
let SubmitInterval = setInterval(async () => {
|
1437
|
+
if (Count >= SubmitTimes) {
|
1438
|
+
clearInterval(SubmitInterval);
|
1439
|
+
location.reload();
|
1440
|
+
return;
|
1441
|
+
}
|
1442
|
+
ImproveACRateButton.innerText = "正在提交 (" + (Count + 1) + "/" + SubmitTimes + ")";
|
1443
|
+
let PID = ACProblems[Math.floor(Math.random() * ACProblems.length)];
|
1444
|
+
let SID = 0;
|
1445
|
+
await fetch("https://www.xmoj.tech/status.php?problem_id=" + PID + "&jresult=4")
|
1446
|
+
.then((Result) => {
|
1447
|
+
return Result.text();
|
1448
|
+
}).then((Result) => {
|
1449
|
+
let ParsedDocument = new DOMParser().parseFromString(Result, "text/html");
|
1450
|
+
SID = ParsedDocument.querySelector("#result-tab > tbody > tr:nth-child(1) > td:nth-child(2)").innerText;
|
1451
|
+
});
|
1452
|
+
let Code = "";
|
1453
|
+
await fetch("https://www.xmoj.tech/getsource.php?id=" + SID)
|
1454
|
+
.then((Response) => {
|
1455
|
+
return Response.text();
|
1456
|
+
}).then((Response) => {
|
1457
|
+
Code = Response.substring(0, Response.indexOf("/**************************************************************")).trim();
|
1458
|
+
});
|
1459
|
+
await fetch("https://www.xmoj.tech/submit.php", {
|
1460
|
+
"headers": {
|
1461
|
+
"content-type": "application/x-www-form-urlencoded"
|
1462
|
+
},
|
1463
|
+
"referrer": "https://www.xmoj.tech/submitpage.php?id=" + PID,
|
1464
|
+
"method": "POST",
|
1465
|
+
"body": "id=" + PID + "&" +
|
1466
|
+
"language=1&" +
|
1467
|
+
"source=" + encodeURIComponent(Code) + "&" +
|
1468
|
+
"enable_O2=on"
|
1469
|
+
});
|
1470
|
+
Count++;
|
1471
|
+
}, 1000);
|
1472
|
+
});
|
1473
|
+
ImproveACRateButton.style.marginBottom = ImproveACRateButton.style.marginRight = "7px";
|
1474
|
+
ImproveACRateButton.style.marginRight = "7px";
|
1475
|
+
}
|
1476
|
+
if (UtilityEnabled("CompareSource")) {
|
1477
|
+
let CompareButton = document.createElement("button");
|
1478
|
+
document.querySelector("body > div.container > div > div.input-append").appendChild(CompareButton);
|
1479
|
+
CompareButton.className = "btn btn-outline-secondary";
|
1480
|
+
CompareButton.innerText = "比较提交记录";
|
1481
|
+
CompareButton.addEventListener("click", () => {
|
1482
|
+
location.href = "https://www.xmoj.tech/comparesource.php";
|
1483
|
+
});
|
1484
|
+
CompareButton.style.marginBottom = "7px";
|
1485
|
+
}
|
1486
|
+
if (UtilityEnabled("ResetType")) {
|
1487
|
+
document.querySelector("#result-tab > thead > tr > th:nth-child(1)").remove();
|
1488
|
+
document.querySelector("#result-tab > thead > tr > th:nth-child(2)").remove();
|
1489
|
+
document.querySelector("#result-tab > thead > tr > th:nth-child(10)").innerHTML = "开启O2";
|
1490
|
+
}
|
1491
|
+
let Temp = document.querySelector("#result-tab > tbody").childNodes;
|
1492
|
+
let SolutionIDs = [];
|
1493
|
+
for (let i = 1; i < Temp.length; i += 2) {
|
1494
|
+
let SID = Number(Temp[i].childNodes[1].innerText);
|
1495
|
+
SolutionIDs.push(SID);
|
1496
|
+
if (UtilityEnabled("ResetType")) {
|
1497
|
+
Temp[i].childNodes[0].remove();
|
1498
|
+
Temp[i].childNodes[0].innerHTML = "<a href=\"https://www.xmoj.tech/showsource.php?id=" + SID + "\">" + SID + "</a> " +
|
1499
|
+
"<a href=\"" + Temp[i].childNodes[6].children[1].href + "\">重交</a>";
|
1500
|
+
Temp[i].childNodes[1].remove();
|
1501
|
+
Temp[i].childNodes[1].children[0].removeAttribute("class");
|
1502
|
+
Temp[i].childNodes[3].childNodes[0].innerText = SizeToStringSize(Temp[i].childNodes[3].childNodes[0].innerText);
|
1503
|
+
Temp[i].childNodes[4].childNodes[0].innerText = TimeToStringTime(Temp[i].childNodes[4].childNodes[0].innerText);
|
1504
|
+
Temp[i].childNodes[5].innerText = Temp[i].childNodes[5].childNodes[0].innerText;
|
1505
|
+
Temp[i].childNodes[6].innerText = SizeToStringSize(Temp[i].childNodes[6].innerText.substring(0, Temp[i].childNodes[6].innerText.length - 1));
|
1506
|
+
Temp[i].childNodes[9].innerText = (Temp[i].childNodes[9].innerText == "" ? "否" : "是");
|
1507
|
+
}
|
1508
|
+
if (SearchParams.get("cid") === null) {
|
1509
|
+
localStorage.setItem("UserScript-Solution-" + SID + "-Problem",
|
1510
|
+
Temp[i].childNodes[1].innerText);
|
1511
|
+
}
|
1512
|
+
else {
|
1513
|
+
localStorage.setItem("UserScript-Solution-" + SID + "-Contest",
|
1514
|
+
SearchParams.get("cid"));
|
1515
|
+
localStorage.setItem("UserScript-Solution-" + SID + "-PID-Contest",
|
1516
|
+
Temp[i].childNodes[1].innerText.charAt(0));
|
1517
|
+
}
|
1518
|
+
}
|
1519
|
+
|
1520
|
+
if (UtilityEnabled("RefreshSolution")) {
|
1521
|
+
let StdList;
|
1522
|
+
await new Promise((Resolve) => {
|
1523
|
+
RequestAPI("GetStdList", {}, async (Result) => {
|
1524
|
+
if (Result.Success) {
|
1525
|
+
StdList = Result.Data.StdList;
|
1526
|
+
Resolve();
|
1527
|
+
}
|
1528
|
+
})
|
1529
|
+
});
|
1530
|
+
|
1531
|
+
let Rows = document.getElementById("result-tab").rows;
|
1532
|
+
let Points = Array();
|
1533
|
+
for (let i = 1; i <= SolutionIDs.length; i++) {
|
1534
|
+
Rows[i].cells[2].className = "td_result";
|
1535
|
+
let SolutionID = SolutionIDs[i - 1];
|
1536
|
+
if (Rows[i].cells[2].children.length == 2) {
|
1537
|
+
Points[SolutionID] = Rows[i].cells[2].children[1].innerText;
|
1538
|
+
Rows[i].cells[2].children[1].remove();
|
1539
|
+
}
|
1540
|
+
Rows[i].cells[2].innerHTML += "<img style=\"margin-left: 10px\" height=\"18\" width=\"18\" src=\"image/loader.gif\">";
|
1541
|
+
setTimeout(() => {
|
1542
|
+
RefreshResult(SolutionID);
|
1543
|
+
}, 0);
|
1544
|
+
}
|
1545
|
+
|
1546
|
+
let RefreshResult = async (SolutionID) => {
|
1547
|
+
let CurrentRow = null;
|
1548
|
+
let Rows = document.getElementById("result-tab").rows;
|
1549
|
+
for (let i = 0; i < SolutionIDs.length; i++) {
|
1550
|
+
if (SolutionIDs[i] == SolutionID) {
|
1551
|
+
CurrentRow = Rows[i + 1];
|
1552
|
+
break;
|
1553
|
+
}
|
1554
|
+
}
|
1555
|
+
await fetch("status-ajax.php?solution_id=" + SolutionID)
|
1556
|
+
.then((Response) => {
|
1557
|
+
return Response.text();
|
1558
|
+
})
|
1559
|
+
.then((Response) => {
|
1560
|
+
let PID = 0;
|
1561
|
+
if (SearchParams.get("cid") === null) {
|
1562
|
+
PID = localStorage.getItem("UserScript-Solution-" + SolutionID + "-Problem");
|
1563
|
+
} else {
|
1564
|
+
PID = localStorage.getItem("UserScript-Contest-" + SearchParams.get("cid") + "-Problem-" + (CurrentRow.cells[1].innerText.charCodeAt(0) - 65) + "-PID");
|
1565
|
+
}
|
1566
|
+
let ResponseData = Response.split(",");
|
1567
|
+
CurrentRow.cells[3].innerHTML = "<div id=\"center\" class=\"red\">" + SizeToStringSize(ResponseData[1]) + "</div>";
|
1568
|
+
CurrentRow.cells[4].innerHTML = "<div id=\"center\" class=\"red\">" + TimeToStringTime(ResponseData[2]) + "</div>";
|
1569
|
+
let TempHTML = "<a href=\"" + (ResponseData[0] == 11 ? "ce" : "re") + "info.php?sid=" + SolutionID + "\" class=\"" + judge_color[ResponseData[0]] + "\">";
|
1570
|
+
TempHTML += judge_result[ResponseData[0]];
|
1571
|
+
TempHTML += "</a>";
|
1572
|
+
if (Points[SolutionID] != undefined) {
|
1573
|
+
TempHTML += "<span style=\"margin-left: 5px\" class=\"badge text-bg-info\">" + Points[SolutionID] + "</span>";
|
1574
|
+
if (Points[SolutionID].substring(0, Points[SolutionID].length - 1) >= 50) {
|
1575
|
+
TempHTML += `<a href="https://www.xmoj.tech/showsource.php?pid=${PID}&ByUserScript=1" class="ms-1 link-secondary">查看标程</a>`;
|
1576
|
+
}
|
1577
|
+
}
|
1578
|
+
if (ResponseData[0] < 4) {
|
1579
|
+
setTimeout(() => {
|
1580
|
+
RefreshResult(SolutionID)
|
1581
|
+
}, 500);
|
1582
|
+
TempHTML += "<img style=\"margin-left: 5px\" height=\"18\" width=\"18\" src=\"image/loader.gif\">";
|
1583
|
+
}
|
1584
|
+
else if (ResponseData[0] == 4 && UtilityEnabled("UploadStd")) {
|
1585
|
+
if (SearchParams.get("cid") == null)
|
1586
|
+
CurrentRow.cells[1].innerText;
|
1587
|
+
let Std = StdList.find((Element) => {
|
1588
|
+
return Element == Number(PID);
|
1589
|
+
});
|
1590
|
+
if (Std != undefined) {
|
1591
|
+
TempHTML += "✅";
|
1592
|
+
}
|
1593
|
+
else {
|
1594
|
+
RequestAPI("UploadStd", {
|
1595
|
+
"ProblemID": Number(PID),
|
1596
|
+
}, (Result) => {
|
1597
|
+
if (Result.Success) {
|
1598
|
+
CurrentRow.cells[2].innerHTML += "🆗";
|
1599
|
+
}
|
1600
|
+
else {
|
1601
|
+
CurrentRow.cells[2].innerHTML += "⚠️";
|
1602
|
+
}
|
1603
|
+
});
|
1604
|
+
}
|
1605
|
+
}
|
1606
|
+
CurrentRow.cells[2].innerHTML = TempHTML;
|
1607
|
+
});
|
1608
|
+
};
|
1609
|
+
}
|
1610
|
+
}
|
1611
|
+
} else if (location.pathname == "/contest.php") {
|
1612
|
+
if (UtilityEnabled("AutoCountdown")) {
|
1613
|
+
clock = () => { }
|
1614
|
+
}
|
1615
|
+
if (location.href.indexOf("?cid=") == -1) {
|
1616
|
+
if (UtilityEnabled("ResetType")) {
|
1617
|
+
document.querySelector("body > div > div.mt-3 > center").innerHTML =
|
1618
|
+
String(document.querySelector("body > div > div.mt-3 > center").innerHTML).replaceAll("ServerTime:", "服务器时间:");
|
1619
|
+
document.querySelector("body > div > div.mt-3 > center > table").style.marginTop = "10px";
|
1620
|
+
|
1621
|
+
document.querySelector("body > div > div.mt-3 > center > form").outerHTML = `<div class="row">
|
1622
|
+
<div class="col-md-4"></div>
|
1623
|
+
<form method="post" action="contest.php" class="col-md-4">
|
1624
|
+
<div class="input-group">
|
1625
|
+
<input name="keyword" type="text" class="form-control" spellcheck="false" data-ms-editor="true">
|
1626
|
+
<input type="submit" value="搜索" class="btn btn-outline-secondary">
|
1627
|
+
</div>
|
1628
|
+
</form>
|
1629
|
+
</div>`;
|
1630
|
+
}
|
1631
|
+
if (UtilityEnabled("Translate")) {
|
1632
|
+
document.querySelector("body > div > div.mt-3 > center > table > thead > tr").childNodes[0].innerText = "编号";
|
1633
|
+
document.querySelector("body > div > div.mt-3 > center > table > thead > tr").childNodes[1].innerText = "标题";
|
1634
|
+
document.querySelector("body > div > div.mt-3 > center > table > thead > tr").childNodes[2].innerText = "状态";
|
1635
|
+
document.querySelector("body > div > div.mt-3 > center > table > thead > tr").childNodes[3].remove();
|
1636
|
+
document.querySelector("body > div > div.mt-3 > center > table > thead > tr").childNodes[3].innerText = "创建者";
|
1637
|
+
}
|
1638
|
+
let Temp = document.querySelector("body > div > div.mt-3 > center > table > tbody").childNodes;
|
1639
|
+
for (let i = 1; i < Temp.length; i++) {
|
1640
|
+
let CurrentElement = Temp[i].childNodes[2].childNodes;
|
1641
|
+
if (CurrentElement[1].childNodes[0].data.indexOf("运行中") != -1) {
|
1642
|
+
let Time = String(CurrentElement[1].childNodes[1].innerText).substring(4);
|
1643
|
+
let Day = parseInt(Time.substring(0, Time.indexOf("天"))) || 0;
|
1644
|
+
let Hour = parseInt(Time.substring((Time.indexOf("天") == -1 ? 0 : Time.indexOf("天") + 1), Time.indexOf("小时"))) || 0;
|
1645
|
+
let Minute = parseInt(Time.substring((Time.indexOf("小时") == -1 ? 0 : Time.indexOf("小时") + 2), Time.indexOf("分"))) || 0;
|
1646
|
+
let Second = parseInt(Time.substring((Time.indexOf("分") == -1 ? 0 : Time.indexOf("分") + 1), Time.indexOf("秒"))) || 0;
|
1647
|
+
let TimeStamp = new Date().getTime() + diff + ((((isNaN(Day) ? 0 : Day) * 24 + Hour) * 60 + Minute) * 60 + Second) * 1000;
|
1648
|
+
CurrentElement[1].childNodes[1].setAttribute("EndTime", TimeStamp);
|
1649
|
+
CurrentElement[1].childNodes[1].classList.add("UpdateByJS");
|
1650
|
+
} else if (CurrentElement[1].childNodes[0].data.indexOf("开始于") != -1) {
|
1651
|
+
let TimeStamp = Date.parse(String(CurrentElement[1].childNodes[0].data).substring(4)) + diff;
|
1652
|
+
CurrentElement[1].setAttribute("EndTime", TimeStamp);
|
1653
|
+
CurrentElement[1].classList.add("UpdateByJS");
|
1654
|
+
} else if (CurrentElement[1].childNodes[0].data.indexOf("已结束") != -1) {
|
1655
|
+
let TimeStamp = String(CurrentElement[1].childNodes[0].data).substring(4);
|
1656
|
+
CurrentElement[1].childNodes[0].data = " 已结束 ";
|
1657
|
+
CurrentElement[1].className = "red";
|
1658
|
+
let Temp = document.createElement("span");
|
1659
|
+
CurrentElement[1].appendChild(Temp);
|
1660
|
+
Temp.className = "green";
|
1661
|
+
Temp.innerHTML = TimeStamp;
|
1662
|
+
}
|
1663
|
+
Temp[i].childNodes[3].style.display = "none";
|
1664
|
+
Temp[i].childNodes[4].innerHTML = "<a href=\"https://www.xmoj.tech/userinfo.php?user=" + Temp[i].childNodes[4].innerHTML + "\">" + Temp[i].childNodes[4].innerHTML + "</a>";
|
1665
|
+
localStorage.setItem("UserScript-Contest-" + Temp[i].childNodes[0].innerText + "-Name", Temp[i].childNodes[1].innerText);
|
1666
|
+
}
|
1667
|
+
} else {
|
1668
|
+
document.getElementsByTagName("h3")[0].innerHTML =
|
1669
|
+
"比赛" + document.getElementsByTagName("h3")[0].innerHTML.substring(7);
|
1670
|
+
if (document.querySelector("#time_left") != null) {
|
1671
|
+
let EndTime = document.querySelector("body > div > div.mt-3 > center").childNodes[3].data;
|
1672
|
+
EndTime = EndTime.substring(EndTime.indexOf("结束时间是:") + 6, EndTime.lastIndexOf("。"));
|
1673
|
+
EndTime = new Date(EndTime).getTime();
|
1674
|
+
if (new Date().getTime() < EndTime) {
|
1675
|
+
document.querySelector("#time_left").classList.add("UpdateByJS");
|
1676
|
+
document.querySelector("#time_left").setAttribute("EndTime", EndTime);
|
1677
|
+
}
|
1678
|
+
}
|
1679
|
+
let HTMLData = document.querySelector("body > div > div.mt-3 > center > div").innerHTML;
|
1680
|
+
HTMLData = HTMLData.replaceAll(" \n ", " ")
|
1681
|
+
HTMLData = HTMLData.replaceAll("<br>开始于: ", "开始时间:")
|
1682
|
+
HTMLData = HTMLData.replaceAll("\n结束于: ", "<br>结束时间:")
|
1683
|
+
HTMLData = HTMLData.replaceAll("\n订正截止日期: ", "<br>订正截止日期:")
|
1684
|
+
HTMLData = HTMLData.replaceAll("\n现在时间: ", "当前时间:")
|
1685
|
+
HTMLData = HTMLData.replaceAll("\n状态:", "<br>状态:")
|
1686
|
+
document.querySelector("body > div > div.mt-3 > center > div").innerHTML = HTMLData;
|
1687
|
+
if (UtilityEnabled("RemoveAlerts") && document.querySelector("body > div > div.mt-3 > center").innerHTML.indexOf("尚未开始比赛") != -1) {
|
1688
|
+
document.querySelector("body > div > div.mt-3 > center > a").setAttribute("href",
|
1689
|
+
"start_contest.php?cid=" + SearchParams.get("cid"));
|
1690
|
+
}
|
1691
|
+
else if (UtilityEnabled("AutoRefresh")) {
|
1692
|
+
addEventListener("focus", async () => {
|
1693
|
+
await fetch(location.href)
|
1694
|
+
.then((Response) => {
|
1695
|
+
return Response.text();
|
1696
|
+
})
|
1697
|
+
.then((Response) => {
|
1698
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
1699
|
+
let Temp = ParsedDocument.querySelector("#problemset > tbody").children;
|
1700
|
+
if (UtilityEnabled("ReplaceYN")) {
|
1701
|
+
for (let i = 0; i < Temp.length; i++) {
|
1702
|
+
let Status = Temp[i].children[0].innerText;
|
1703
|
+
if (Status.indexOf("Y") != -1) {
|
1704
|
+
document.querySelector("#problemset > tbody").children[i].children[0].children[0].className = "status status_y";
|
1705
|
+
document.querySelector("#problemset > tbody").children[i].children[0].children[0].innerText = "✓";
|
1706
|
+
}
|
1707
|
+
else if (Status.indexOf("N") != -1) {
|
1708
|
+
document.querySelector("#problemset > tbody").children[i].children[0].children[0].className = "status status_n";
|
1709
|
+
document.querySelector("#problemset > tbody").children[i].children[0].children[0].innerText = "✗";
|
1710
|
+
}
|
1711
|
+
}
|
1712
|
+
}
|
1713
|
+
});
|
1714
|
+
});
|
1715
|
+
document.querySelector("body > div > div.mt-3 > center > br:nth-child(2)").remove();
|
1716
|
+
document.querySelector("body > div > div.mt-3 > center > br:nth-child(2)").remove();
|
1717
|
+
document.querySelector("body > div > div.mt-3 > center > div > .red").innerHTML =
|
1718
|
+
String(document.querySelector("body > div > div.mt-3 > center > div > .red").innerHTML).replaceAll("<br>", "<br><br>");
|
1719
|
+
let StaticButton = document.createElement("button");
|
1720
|
+
document.querySelectorAll("body > div > div.mt-3 > center > div > .red")[1].appendChild(StaticButton);
|
1721
|
+
StaticButton.className = "btn btn-outline-secondary";
|
1722
|
+
StaticButton.innerText = "统计";
|
1723
|
+
StaticButton.addEventListener("click", () => {
|
1724
|
+
location.href = "https://www.xmoj.tech/conteststatistics.php?cid=" + SearchParams.get("cid");
|
1725
|
+
});
|
1726
|
+
|
1727
|
+
document.querySelector("#problemset > tbody").innerHTML =
|
1728
|
+
String(document.querySelector("#problemset > tbody").innerHTML).replaceAll(
|
1729
|
+
/\t ([0-9]*) 问题 ([^<]*)/g,
|
1730
|
+
"$2. $1");
|
1731
|
+
|
1732
|
+
document.querySelector("#problemset > tbody").innerHTML =
|
1733
|
+
String(document.querySelector("#problemset > tbody").innerHTML).replaceAll(
|
1734
|
+
/\t\*([0-9]*) 问题 ([^<]*)/g,
|
1735
|
+
"拓展$2. $1");
|
1736
|
+
|
1737
|
+
if (UtilityEnabled("MoreSTD") && document.querySelector("#problemset > thead > tr").innerHTML.indexOf("标程") != -1) {
|
1738
|
+
let Temp = document.querySelector("#problemset > thead > tr").children;
|
1739
|
+
for (let i = 0; i < Temp.length; i++) {
|
1740
|
+
if (Temp[i].innerText == "标程") {
|
1741
|
+
Temp[i].remove();
|
1742
|
+
let Temp2 = document.querySelector("#problemset > tbody").children;
|
1743
|
+
for (let j = 0; j < Temp2.length; j++) {
|
1744
|
+
if (Temp2[j].children[i] != undefined) {
|
1745
|
+
Temp2[j].children[i].remove();
|
1746
|
+
}
|
1747
|
+
}
|
1748
|
+
}
|
1749
|
+
}
|
1750
|
+
document.querySelector("#problemset > thead > tr").innerHTML += "<td width=\"5%\">标程</td>";
|
1751
|
+
Temp = document.querySelector("#problemset > tbody").children;
|
1752
|
+
for (let i = 0; i < Temp.length; i++) {
|
1753
|
+
Temp[i].innerHTML += "<td><a href=\"https://www.xmoj.tech/problem_std.php?cid=" + Number(SearchParams.get("cid")) + "&pid=" + i + "\" target=\"_blank\">打开</a></td>";
|
1754
|
+
}
|
1755
|
+
}
|
1756
|
+
|
1757
|
+
Temp = document.querySelector("#problemset > tbody").rows;
|
1758
|
+
for (let i = 0; i < Temp.length; i++) {
|
1759
|
+
if (Temp[i].childNodes[0].children.length == 0) {
|
1760
|
+
Temp[i].childNodes[0].innerHTML = "<div class=\"status\"></div>";
|
1761
|
+
}
|
1762
|
+
let PID = Temp[i].childNodes[1].innerHTML;
|
1763
|
+
if (PID.substring(0, 2) == "拓展") {
|
1764
|
+
PID = PID.substring(2);
|
1765
|
+
}
|
1766
|
+
Temp[i].children[2].children[0].target = "_blank";
|
1767
|
+
localStorage.setItem("UserScript-Contest-" + SearchParams.get("cid") + "-Problem-" + i + "-PID",
|
1768
|
+
PID.substring(3));
|
1769
|
+
localStorage.setItem("UserScript-Problem-" + PID.substring(3) + "-Name",
|
1770
|
+
Temp[i].childNodes[2].innerText);
|
1771
|
+
}
|
1772
|
+
let CheatDiv = document.createElement("div");
|
1773
|
+
CheatDiv.style.marginTop = "20px";
|
1774
|
+
CheatDiv.style.textAlign = "left";
|
1775
|
+
document.querySelector("body > div > div.mt-3 > center").insertBefore(CheatDiv, document.querySelector("#problemset"));
|
1776
|
+
if (UtilityEnabled("AutoCheat")) {
|
1777
|
+
let AutoCheatButton = document.createElement("button");
|
1778
|
+
CheatDiv.appendChild(AutoCheatButton);
|
1779
|
+
AutoCheatButton.className = "btn btn-outline-secondary";
|
1780
|
+
AutoCheatButton.innerText = "自动提交当年代码";
|
1781
|
+
AutoCheatButton.style.marginRight = "5px";
|
1782
|
+
AutoCheatButton.disabled = true;
|
1783
|
+
let ACProblems = [], ContestProblems = [];
|
1784
|
+
const UrlParams = new URLSearchParams(window.location.search);
|
1785
|
+
const CID = UrlParams.get("cid");
|
1786
|
+
await fetch("https://www.xmoj.tech/userinfo.php?user=" + CurrentUsername)
|
1787
|
+
.then((Response) => {
|
1788
|
+
return Response.text();
|
1789
|
+
}).then((Response) => {
|
1790
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
1791
|
+
let Temp = ParsedDocument.querySelector("#statics > tbody > tr:nth-child(2) > td:nth-child(3) > script").innerText.split("\n")[5].split(";");
|
1792
|
+
for (let i = 0; i < Temp.length; i++) {
|
1793
|
+
ACProblems.push(Number(Temp[i].substring(2, Temp[i].indexOf(","))));
|
1794
|
+
}
|
1795
|
+
AutoCheatButton.disabled = false;
|
1796
|
+
});
|
1797
|
+
let Rows = document.querySelector("#problemset > tbody").rows;
|
1798
|
+
for (let i = 0; i < Rows.length; i++) {
|
1799
|
+
ContestProblems.push(Rows[i].children[1].innerText.substring(Rows[i].children[1].innerText.indexOf('.') + 2)).toFixed;
|
1800
|
+
}
|
1801
|
+
AutoCheatButton.addEventListener("click", async () => {
|
1802
|
+
AutoCheatButton.disabled = true;
|
1803
|
+
let Submitted = false;
|
1804
|
+
for (let i = 0; i < ContestProblems.length; i++) {
|
1805
|
+
let PID = ContestProblems[i];
|
1806
|
+
if (ACProblems.indexOf(Number(PID)) == -1) {
|
1807
|
+
console.log("Ignoring problem " + PID + " as it has not been solved yet.");
|
1808
|
+
continue;
|
1809
|
+
}
|
1810
|
+
if (Rows[i].children[0].children[0].classList.contains("status_y")) {
|
1811
|
+
console.log("Ignoring problem " + PID + " as it has already been solved in this contest.");
|
1812
|
+
continue;
|
1813
|
+
}
|
1814
|
+
console.log("Submitting problem " + PID);
|
1815
|
+
Submitted = true;
|
1816
|
+
AutoCheatButton.innerHTML = "正在提交 " + PID;
|
1817
|
+
let SID = 0;
|
1818
|
+
await fetch("https://www.xmoj.tech/status.php?problem_id=" + PID + "&jresult=4")
|
1819
|
+
.then((Result) => {
|
1820
|
+
return Result.text();
|
1821
|
+
}).then((Result) => {
|
1822
|
+
let ParsedDocument = new DOMParser().parseFromString(Result, "text/html");
|
1823
|
+
SID = ParsedDocument.querySelector("#result-tab > tbody > tr:nth-child(1) > td:nth-child(2)").innerText;
|
1824
|
+
});
|
1825
|
+
let Code = "";
|
1826
|
+
await fetch("https://www.xmoj.tech/getsource.php?id=" + SID)
|
1827
|
+
.then((Response) => {
|
1828
|
+
return Response.text();
|
1829
|
+
}).then((Response) => {
|
1830
|
+
Code = Response.substring(0, Response.indexOf("/**************************************************************")).trim();
|
1831
|
+
});
|
1832
|
+
await fetch("https://www.xmoj.tech/submit.php", {
|
1833
|
+
"headers": {
|
1834
|
+
"content-type": "application/x-www-form-urlencoded"
|
1835
|
+
},
|
1836
|
+
"referrer": "https://www.xmoj.tech/submitpage.php?id=" + PID,
|
1837
|
+
"method": "POST",
|
1838
|
+
"body": "cid=" + CID + "&pid=" + i + "&" +
|
1839
|
+
"language=1&" +
|
1840
|
+
"source=" + encodeURIComponent(Code) + "&" +
|
1841
|
+
"enable_O2=on"
|
1842
|
+
});
|
1843
|
+
}
|
1844
|
+
if (!Submitted) {
|
1845
|
+
AutoCheatButton.innerHTML = "没有可以提交的题目!";
|
1846
|
+
await new Promise(r => setTimeout(r, 1000));
|
1847
|
+
}
|
1848
|
+
AutoCheatButton.disabled = false;
|
1849
|
+
if (Submitted) location.reload();
|
1850
|
+
else AutoCheatButton.innerHTML = "自动提交当年代码";
|
1851
|
+
});
|
1852
|
+
}
|
1853
|
+
|
1854
|
+
if (UtilityEnabled("OpenAllProblem")) {
|
1855
|
+
let OpenAllButton = document.createElement("button");
|
1856
|
+
OpenAllButton.className = "btn btn-outline-secondary";
|
1857
|
+
OpenAllButton.innerText = "打开全部题目";
|
1858
|
+
OpenAllButton.style.marginRight = "5px";
|
1859
|
+
CheatDiv.appendChild(OpenAllButton);
|
1860
|
+
OpenAllButton.addEventListener("click", () => {
|
1861
|
+
let Rows = document.querySelector("#problemset > tbody").rows;
|
1862
|
+
for (let i = 0; i < Rows.length; i++) {
|
1863
|
+
open(Rows[i].children[2].children[0].href, "_blank");
|
1864
|
+
}
|
1865
|
+
});
|
1866
|
+
let OpenUnsolvedButton = document.createElement("button");
|
1867
|
+
OpenUnsolvedButton.className = "btn btn-outline-secondary";
|
1868
|
+
OpenUnsolvedButton.innerText = "打开未解决题目";
|
1869
|
+
CheatDiv.appendChild(OpenUnsolvedButton);
|
1870
|
+
OpenUnsolvedButton.addEventListener("click", () => {
|
1871
|
+
let Rows = document.querySelector("#problemset > tbody").rows;
|
1872
|
+
for (let i = 0; i < Rows.length; i++) {
|
1873
|
+
if (!Rows[i].children[0].children[0].classList.contains("status_y")) {
|
1874
|
+
open(Rows[i].children[2].children[0].href, "_blank");
|
1875
|
+
}
|
1876
|
+
}
|
1877
|
+
});
|
1878
|
+
}
|
1879
|
+
|
1880
|
+
if (UtilityEnabled("ResetType")) {
|
1881
|
+
document.querySelector("#problemset > thead > tr > th:nth-child(1)").style.width = "5%";
|
1882
|
+
}
|
1883
|
+
localStorage.setItem("UserScript-Contest-" + SearchParams.get("cid") + "-ProblemCount",
|
1884
|
+
document.querySelector("#problemset > tbody").rows.length);
|
1885
|
+
}
|
1886
|
+
}
|
1887
|
+
} else if (location.pathname == "/contestrank-oi.php") {
|
1888
|
+
if (document.querySelector("#rank") == null) {
|
1889
|
+
document.querySelector("body > div > div.mt-3").innerHTML = "<center><h3>比赛排名</h3><a></a><table id=\"rank\"></table>";
|
1890
|
+
}
|
1891
|
+
if (SearchParams.get("ByUserScript") == null) {
|
1892
|
+
if (document.querySelector("body > div > div.mt-3 > center > h3").innerText == "比赛排名") {
|
1893
|
+
document.querySelector("#rank").innerText = "比赛暂时还没有排名";
|
1894
|
+
}
|
1895
|
+
else {
|
1896
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText =
|
1897
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText.substring(
|
1898
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText.indexOf(" -- ") + 4)
|
1899
|
+
+ "(OI排名)";
|
1900
|
+
document.querySelector("#rank > thead > tr > :nth-child(1)").innerText = "排名";
|
1901
|
+
document.querySelector("#rank > thead > tr > :nth-child(2)").innerText = "用户";
|
1902
|
+
document.querySelector("#rank > thead > tr > :nth-child(3)").innerText = "昵称";
|
1903
|
+
document.querySelector("#rank > thead > tr > :nth-child(4)").innerText = "AC数";
|
1904
|
+
document.querySelector("#rank > thead > tr > :nth-child(5)").innerText = "得分";
|
1905
|
+
let RefreshOIRank = async () => {
|
1906
|
+
await fetch(location.href)
|
1907
|
+
.then((Response) => {
|
1908
|
+
return Response.text()
|
1909
|
+
})
|
1910
|
+
.then(async (Response) => {
|
1911
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
1912
|
+
TidyTable(ParsedDocument.getElementById("rank"));
|
1913
|
+
let Temp = ParsedDocument.getElementById("rank").rows;
|
1914
|
+
for (var i = 1; i < Temp.length; i++) {
|
1915
|
+
let MetalCell = Temp[i].cells[0];
|
1916
|
+
let Metal = document.createElement("span");
|
1917
|
+
Metal.innerText = MetalCell.innerText;
|
1918
|
+
Metal.className = "badge text-bg-primary";
|
1919
|
+
MetalCell.innerText = "";
|
1920
|
+
MetalCell.appendChild(Metal);
|
1921
|
+
GetUsernameHTML(Temp[i].cells[1], Temp[i].cells[1].innerText);
|
1922
|
+
Temp[i].cells[2].innerHTML = Temp[i].cells[2].innerText;
|
1923
|
+
Temp[i].cells[3].innerHTML = Temp[i].cells[3].innerText;
|
1924
|
+
for (let j = 5; j < Temp[i].cells.length; j++) {
|
1925
|
+
let InnerText = Temp[i].cells[j].innerText;
|
1926
|
+
let BackgroundColor = Temp[i].cells[j].style.backgroundColor;
|
1927
|
+
let Red = BackgroundColor.substring(4, BackgroundColor.indexOf(","));
|
1928
|
+
let Green = BackgroundColor.substring(BackgroundColor.indexOf(",") + 2, BackgroundColor.lastIndexOf(","));
|
1929
|
+
let Blue = BackgroundColor.substring(BackgroundColor.lastIndexOf(",") + 2, BackgroundColor.lastIndexOf(")"));
|
1930
|
+
let NoData = (Red == 238 && Green == 238 && Blue == 238);
|
1931
|
+
let FirstBlood = (Red == 170 && Green == 170 && Blue == 255);
|
1932
|
+
let Solved = (Green == 255);
|
1933
|
+
let ErrorCount = "";
|
1934
|
+
if (Solved) {
|
1935
|
+
ErrorCount = (Blue == 170 ? 5 : (Blue - 51) / 32);
|
1936
|
+
}
|
1937
|
+
else {
|
1938
|
+
ErrorCount = (Blue == 22 ? 15 : (170 - Blue) / 10);
|
1939
|
+
}
|
1940
|
+
if (NoData) {
|
1941
|
+
BackgroundColor = "";
|
1942
|
+
}
|
1943
|
+
else if (FirstBlood) {
|
1944
|
+
BackgroundColor = "rgb(127, 127, 255)";
|
1945
|
+
}
|
1946
|
+
else if (Solved) {
|
1947
|
+
BackgroundColor = "rgb(0, 255, 0, " + Math.max(1 / 10 * (10 - ErrorCount), 0.2) + ")";
|
1948
|
+
if (ErrorCount != 0) {
|
1949
|
+
InnerText += " (" + (ErrorCount == 5 ? "4+" : ErrorCount) + ")";
|
1950
|
+
}
|
1951
|
+
}
|
1952
|
+
else {
|
1953
|
+
BackgroundColor = "rgba(255, 0, 0, " + Math.min(ErrorCount / 10 + 0.2, 1) + ")";
|
1954
|
+
if (ErrorCount != 0) {
|
1955
|
+
InnerText += " (" + (ErrorCount == 15 ? "14+" : ErrorCount) + ")";
|
1956
|
+
}
|
1957
|
+
}
|
1958
|
+
Temp[i].cells[j].innerHTML = InnerText;
|
1959
|
+
Temp[i].cells[j].style.backgroundColor = BackgroundColor;
|
1960
|
+
Temp[i].cells[j].style.color = (UtilityEnabled("DarkMode") ? "white" : "black");
|
1961
|
+
}
|
1962
|
+
}
|
1963
|
+
document.querySelector("#rank > tbody").innerHTML = ParsedDocument.querySelector("#rank > tbody").innerHTML;
|
1964
|
+
});
|
1965
|
+
};
|
1966
|
+
RefreshOIRank();
|
1967
|
+
if (UtilityEnabled("AutoRefresh")) {
|
1968
|
+
addEventListener("focus", RefreshOIRank);
|
1969
|
+
}
|
1970
|
+
}
|
1971
|
+
}
|
1972
|
+
else if (UtilityEnabled("ACMRank")) {
|
1973
|
+
if (document.querySelector("body > div > div.mt-3 > center > h3").innerText != "比赛排名") {
|
1974
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText =
|
1975
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText.substring(
|
1976
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText.indexOf(" -- ") + 4)
|
1977
|
+
+ "(ACM排名)";
|
1978
|
+
}
|
1979
|
+
let RankData = [];
|
1980
|
+
let RefreshACMRank = async (ProblemCount) => {
|
1981
|
+
let LastPositionX = scrollX;
|
1982
|
+
let LastPositionY = scrollY;
|
1983
|
+
let NewURL = new URL(location.href);
|
1984
|
+
NewURL.pathname = "/contestrank2.php";
|
1985
|
+
await fetch(NewURL.toString())
|
1986
|
+
.then((Response) => {
|
1987
|
+
return Response.text()
|
1988
|
+
})
|
1989
|
+
.then(async (Response) => {
|
1990
|
+
RankData = [];
|
1991
|
+
|
1992
|
+
let Table = document.querySelector("#rank"); Table.innerHTML = "";
|
1993
|
+
let StartPosition = Response.indexOf("var solutions=") + 14;
|
1994
|
+
let EndPosition = Response.indexOf("}];", StartPosition) + 2;
|
1995
|
+
if (EndPosition == 1) {
|
1996
|
+
Table.innerHTML = "暂时还没有人提交呢";
|
1997
|
+
}
|
1998
|
+
else {
|
1999
|
+
let SubmitRecord = JSON.parse(Response.substring(StartPosition, EndPosition));
|
2000
|
+
|
2001
|
+
for (let i = 0; i < SubmitRecord.length; i++) {
|
2002
|
+
let CurrentSubmission = SubmitRecord[i];
|
2003
|
+
let CurrentRow = RankData.find((CurrentRow) => {
|
2004
|
+
if (CurrentRow.Username == CurrentSubmission.user_id) {
|
2005
|
+
return true;
|
2006
|
+
}
|
2007
|
+
});
|
2008
|
+
if (CurrentRow == null) {
|
2009
|
+
CurrentRow = {
|
2010
|
+
Username: CurrentSubmission.user_id,
|
2011
|
+
Nickname: CurrentSubmission.nick,
|
2012
|
+
Solved: 0,
|
2013
|
+
Penalty: 0,
|
2014
|
+
Problem: [],
|
2015
|
+
QuickSubmitCount: 0
|
2016
|
+
};
|
2017
|
+
RankData.push(CurrentRow);
|
2018
|
+
}
|
2019
|
+
let CurrentProblem = CurrentRow.Problem.find((CurrentRow) => {
|
2020
|
+
if (CurrentRow.Index == CurrentSubmission.num) {
|
2021
|
+
return true;
|
2022
|
+
}
|
2023
|
+
});
|
2024
|
+
if (CurrentProblem == null) {
|
2025
|
+
CurrentProblem = {
|
2026
|
+
Index: CurrentSubmission.num,
|
2027
|
+
Attempts: [],
|
2028
|
+
SolveTime: 0
|
2029
|
+
};
|
2030
|
+
CurrentRow.Problem.push(CurrentProblem);
|
2031
|
+
}
|
2032
|
+
if (CurrentSubmission.result == 4 && CurrentProblem.SolveTime == 0) {
|
2033
|
+
CurrentProblem.SolveTime = parseInt(CurrentSubmission.in_date);
|
2034
|
+
CurrentRow.Solved++;
|
2035
|
+
CurrentRow.Penalty += parseInt(CurrentSubmission.in_date) + CurrentProblem.Attempts.length * 20 * 60;
|
2036
|
+
}
|
2037
|
+
CurrentProblem.Attempts.push({
|
2038
|
+
Time: CurrentSubmission.in_date,
|
2039
|
+
Result: CurrentSubmission.result
|
2040
|
+
});
|
2041
|
+
}
|
2042
|
+
|
2043
|
+
for (let i = 0; i < RankData.length; i++) {
|
2044
|
+
for (let j = 0; j < RankData[i].Problem.length; j++) {
|
2045
|
+
for (let k = 0; k < RankData[i].Problem.length; k++) {
|
2046
|
+
if (j != k && RankData[i].Problem[j].SolveTime != 0 && RankData[i].Problem[k].SolveTime != 0 &&
|
2047
|
+
Math.abs(RankData[i].Problem[j].SolveTime - RankData[i].Problem[k].SolveTime) < 60) {
|
2048
|
+
RankData[i].QuickSubmitCount++;
|
2049
|
+
}
|
2050
|
+
}
|
2051
|
+
}
|
2052
|
+
}
|
2053
|
+
|
2054
|
+
RankData.sort((a, b) => {
|
2055
|
+
if (a.Solved != b.Solved) {
|
2056
|
+
return a.Solved < b.Solved ? 1 : -1;
|
2057
|
+
} else if (a.Penalty != b.Penalty) {
|
2058
|
+
return a.Penalty > b.Penalty ? 1 : -1;
|
2059
|
+
}
|
2060
|
+
return 0;
|
2061
|
+
});
|
2062
|
+
|
2063
|
+
let Header = document.createElement("thead"); Table.appendChild(Header);
|
2064
|
+
let RowHeader = document.createElement("tr"); Header.appendChild(RowHeader);
|
2065
|
+
let MetalHeader = document.createElement("th"); RowHeader.appendChild(MetalHeader); MetalHeader.innerText = "排名"; MetalHeader.style.width = "5%";
|
2066
|
+
let UsernameHeader = document.createElement("th"); RowHeader.appendChild(UsernameHeader); UsernameHeader.innerText = "用户"; UsernameHeader.style.width = "10%";
|
2067
|
+
let NicknameHeader = document.createElement("th"); RowHeader.appendChild(NicknameHeader); NicknameHeader.innerText = "昵称"; NicknameHeader.style.width = "10%";
|
2068
|
+
let NameHeader = document.createElement("th"); RowHeader.appendChild(NameHeader); NameHeader.innerText = "姓名"; NameHeader.style.width = "5%";
|
2069
|
+
let SolvedHeader = document.createElement("th"); RowHeader.appendChild(SolvedHeader); SolvedHeader.innerText = "AC数"; SolvedHeader.style.width = "5%";
|
2070
|
+
let PenaltyHeader = document.createElement("th"); RowHeader.appendChild(PenaltyHeader); PenaltyHeader.innerText = "罚时"; PenaltyHeader.style.width = "10%";
|
2071
|
+
|
2072
|
+
for (let i = 0; i < ProblemCount; i++) {
|
2073
|
+
let ProblemHeader = document.createElement("th"); RowHeader.appendChild(ProblemHeader);
|
2074
|
+
let ProblemLink = document.createElement("a"); ProblemHeader.appendChild(ProblemLink);
|
2075
|
+
ProblemLink.href = "problem.php?cid=" + SearchParams.get("cid") + "&pid=" + i; ProblemLink.innerText = String.fromCharCode(65 + i);
|
2076
|
+
ProblemHeader.classList.add("header"); ProblemHeader.style.width = (50 / ProblemCount) + "%";
|
2077
|
+
}
|
2078
|
+
|
2079
|
+
let Body = document.createElement("tbody"); Table.appendChild(Body);
|
2080
|
+
Body.className = "table-group-divider";
|
2081
|
+
for (let i = 0; i < RankData.length; i++) {
|
2082
|
+
let RowData = RankData[i];
|
2083
|
+
let Row = document.createElement("tr"); Body.appendChild(Row);
|
2084
|
+
let MetalCell = document.createElement("td"); Row.appendChild(MetalCell);
|
2085
|
+
let UsernameCell = document.createElement("td"); Row.appendChild(UsernameCell);
|
2086
|
+
let NicknameCell = document.createElement("td"); Row.appendChild(NicknameCell);
|
2087
|
+
let NameCell = document.createElement("td"); Row.appendChild(NameCell);
|
2088
|
+
let SolvedCell = document.createElement("td"); Row.appendChild(SolvedCell);
|
2089
|
+
let PenaltyCell = document.createElement("td"); Row.appendChild(PenaltyCell);
|
2090
|
+
|
2091
|
+
let Medal = document.createElement("span"); MetalCell.appendChild(Medal);
|
2092
|
+
Medal.innerText = i + 1;
|
2093
|
+
Medal.classList.add("badge");
|
2094
|
+
if (i <= RankData.length * 0.05) {
|
2095
|
+
Medal.classList.add("text-bg-danger");
|
2096
|
+
}
|
2097
|
+
else if (i <= RankData.length * 0.15) {
|
2098
|
+
Medal.classList.add("text-bg-warning");
|
2099
|
+
}
|
2100
|
+
else if (i <= RankData.length * 0.4) {
|
2101
|
+
Medal.classList.add("text-bg-primary");
|
2102
|
+
}
|
2103
|
+
else {
|
2104
|
+
Medal.classList.add("text-bg-secondary");
|
2105
|
+
}
|
2106
|
+
|
2107
|
+
let UsernameSpan = document.createElement("span"); UsernameCell.appendChild(UsernameSpan);
|
2108
|
+
GetUsernameHTML(UsernameSpan, RowData.Username);
|
2109
|
+
if (RowData.Username == CurrentUsername) {
|
2110
|
+
Row.classList.add("table-primary");
|
2111
|
+
}
|
2112
|
+
if (RowData.QuickSubmitCount >= 2) {
|
2113
|
+
let QuickSubmitBadge = document.createElement("span"); UsernameCell.appendChild(QuickSubmitBadge);
|
2114
|
+
QuickSubmitBadge.innerText = "作弊者";
|
2115
|
+
QuickSubmitBadge.className = "badge text-bg-warning ms-2";
|
2116
|
+
}
|
2117
|
+
|
2118
|
+
NicknameCell.innerText = (RowData.Nickname.length < 16 ? RowData.Nickname : RowData.Nickname.substring(0, 15) + "...");
|
2119
|
+
|
2120
|
+
let Names = {
|
2121
|
+
"huangkai": "黄开", "chenlangning": "陈朗宁", "chensiru": "陈斯如", "chentianle": "陈天乐", "chenxuanhe": "陈宣合", "chenzecong": "陈泽聪", "chenzerui": "陈泽睿", "danwenxiao": "单文骁", "dongminghui": "董明辉", "gaochenming": "高晨茗", "guoqingtong": "郭庆桐", "guoruiqun": "郭睿群", "guyuchen": "顾毓辰",
|
2122
|
+
"hanshujian": "韩书简", "heshuhan": "贺书瀚", "hexinyi": "何昕弈", "huangmingxuan": "黄铭宣", "huangruina": "黄睿纳", "huangwei": "黄唯", "huyiyang": "胡以杨", "jiangxingyu": "姜星宇", "jingtaiyu": "荆泰宇", "jinweizhe": "金炜喆", "leijiahan": "雷家涵",
|
2123
|
+
"lianzhongzhe": "连中哲", "liaoyanxu": "廖彦旭", "lingzixiang": "凌梓翔", "linziyi": "林子懿", "liujianhao": "刘健豪", "liujiankun": "刘健坤", "liuxianyong": "刘先勇", "liuxixian": "刘希贤", "liyihan": "李亦涵", "luojinyang": "罗金阳", "lutianfeng": "陆天枫",
|
2124
|
+
"meitianyi": "梅天一", "panyinliang": "潘胤良", "pengyixuan": "彭议萱", "putong": "蒲通", "qianqingyuan": "钱清源", "qidekai": "戚得凯", "shanwenxiao": "单文骁", "shenxichen": "沈熙晨", "shihongxi": "施泓熙", "shimufan": "施慕梵", "shiyichen": "施奕辰",
|
2125
|
+
"shiyunhao": "施云浩", "shuxinmo": "舒馨墨", "suiruochen": "隋若宸", "sunyihan": "孙艺涵", "sunyimiao": "孙义淼", "tangchao": "唐潮", "tangyuhan": "唐钰涵", "tanhaoxuan": "谭皓轩", "taoxianyu": "陶羡榆", "wangkangming": "王康明", "wangminghao": "王明浩",
|
2126
|
+
"wangmingshuo": "王茗铄", "wangpengyu": "王芃雨", "wangsiyuan3": "王思源", "wangtianqi": "王天琦", "wangzetong": "王泽通", "wanxinlian": "万馨联", "wensiyi": "闻思奕", "wujinhong": "吴锦鸿", "wurunze": "吴润泽", "wuyukai": "巫昱恺", "xiangjicheng": "项际诚",
|
2127
|
+
"xiaoguanxun": "肖贯勋", "xiaojiasheng": "肖嘉盛", "xiaruicheng": "夏瑞成", "xiaweimin": "夏蔚民", "xiaxuran": "夏诩然", "xiebingxiu": "谢秉修", "xiebingxiu": "谢秉修", "xieliren": "谢立仁", "xinyihan": "辛轶涵", "xuconghan": "徐从瀚", "xukan": "徐衎",
|
2128
|
+
"xuweiyi": "徐维易", "yanghaochen": "杨皓宸", "yezijiong": "叶梓炅", "youzhouhang": "尤周杭", "yuanruiqing": "袁瑞擎", "yutingjun": "于庭郡", "zhangchenming": "张宸铭", "zhangqiuze": "张秋泽", "zhangshuxuan": "张澍萱", "zhangwenda": "张闻达", "zhangyifu": "张亦夫",
|
2129
|
+
"zhangyouheng": "张佑恒", "zhaochenshen": "赵晨神", "zhaochenwei": "赵晨伟", "zhengyinan": "郑逸楠", "zhonghongyi": "钟弘毅", "zhoujunyu": "周峻瑜", "zhouziyi": "周子逸", "zhouziyou": "周子游", "zhuchenrui2": "朱晨瑞", "zhuruichen": "朱睿宸", "zhuxule": "朱徐乐",
|
2130
|
+
"zhuyikun": "朱奕坤", "leiwenda": "雷文达", "wangyuancheng": "王源成", "zhuyiyang": "朱奕阳", "hanjialin": "韩佳霖", "zhaozichen": "赵紫辰", "zhuaiwei": "朱艾薇", "linlitong": "林立桐", "xuyan": "徐衍", "fenghaochen": "冯皓宸", "lutianlang": "陆天朗", "tangyuhan": "唐钰涵",
|
2131
|
+
"jiangbowen": "姜博文", "shangguanbocheng": "上官伯呈", "wangchengqi": "王呈齐", "yanpeitong": "颜培桐", "gongcheng": "龚橙", "weijiefu": "韦杰夫", "": ""
|
2132
|
+
};
|
2133
|
+
NameCell.innerText = (Names[RowData.Username] == undefined ? "" : Names[RowData.Username]);
|
2134
|
+
|
2135
|
+
SolvedCell.innerText = RowData.Solved;
|
2136
|
+
|
2137
|
+
PenaltyCell.innerText = SecondsToString(RowData.Penalty);
|
2138
|
+
|
2139
|
+
for (let j = 0; j < ProblemCount; j++) {
|
2140
|
+
let Problem = document.createElement("td"); Row.appendChild(Problem);
|
2141
|
+
let ProblemData = RowData.Problem.find((CurrentRow) => {
|
2142
|
+
if (CurrentRow.Index == j) {
|
2143
|
+
return true;
|
2144
|
+
}
|
2145
|
+
});
|
2146
|
+
if (ProblemData == undefined) {
|
2147
|
+
Problem.style.backgroundColor = "rgba(0, 0, 0, 0)";
|
2148
|
+
}
|
2149
|
+
else if (ProblemData.SolveTime != 0) {
|
2150
|
+
Problem.innerText = SecondsToString(ProblemData.SolveTime) + "(" + ProblemData.Attempts.length + ")";
|
2151
|
+
let Color = Math.max(1 / 10 * (10 - ProblemData.Attempts.length), 0.2);
|
2152
|
+
Problem.style.backgroundColor = "rgba(0, 255, 0, " + Color + ")";
|
2153
|
+
}
|
2154
|
+
else {
|
2155
|
+
Problem.innerText = "(" + ProblemData.Attempts.length + ")";
|
2156
|
+
let Color = Math.min(ProblemData.Attempts.length / 10 + 0.2, 1);
|
2157
|
+
Problem.style.backgroundColor = "rgba(255, 0, 0, " + Color + ")";
|
2158
|
+
}
|
2159
|
+
Problem.style.color = (UtilityEnabled("DarkMode") ? "white" : "black");
|
2160
|
+
}
|
2161
|
+
}
|
2162
|
+
|
2163
|
+
TidyTable(Table);
|
2164
|
+
|
2165
|
+
scrollTo({
|
2166
|
+
left: LastPositionX,
|
2167
|
+
top: LastPositionY,
|
2168
|
+
behavior: "instant"
|
2169
|
+
});
|
2170
|
+
}
|
2171
|
+
});
|
2172
|
+
}
|
2173
|
+
document.getElementById("rank").style.width = "100%";
|
2174
|
+
let DownloadButton = document.createElement("button");
|
2175
|
+
document.querySelector("body > div.container > div > center").insertBefore(DownloadButton, document.querySelector("body > div.container > div > center > a"));
|
2176
|
+
DownloadButton.className = "btn btn-outline-secondary";
|
2177
|
+
DownloadButton.innerText = "下载ACM排名";
|
2178
|
+
DownloadButton.style.marginBottom = "20px";
|
2179
|
+
DownloadButton.addEventListener("click", () => {
|
2180
|
+
location.href = "https://www.xmoj.tech/contestrank.xls.php?cid=" + SearchParams.get("cid");
|
2181
|
+
});
|
2182
|
+
let ProblemCount = localStorage.getItem("UserScript-Contest-" + SearchParams.get("cid") + "-ProblemCount");
|
2183
|
+
RefreshACMRank(ProblemCount);
|
2184
|
+
if (UtilityEnabled("AutoRefresh")) {
|
2185
|
+
addEventListener("focus", () => {
|
2186
|
+
RefreshACMRank(ProblemCount);
|
2187
|
+
});
|
2188
|
+
}
|
2189
|
+
}
|
2190
|
+
Style.innerHTML += "td {";
|
2191
|
+
Style.innerHTML += " white-space: nowrap;";
|
2192
|
+
Style.innerHTML += "}";
|
2193
|
+
document.querySelector("body > div.container > div > center").style.paddingBottom = "10px";
|
2194
|
+
document.querySelector("body > div.container > div > center > a").style.display = "none";
|
2195
|
+
} else if (location.pathname == "/contestrank-correct.php") {
|
2196
|
+
if (document.querySelector("#rank") == null) {
|
2197
|
+
document.querySelector("body > div > div.mt-3").innerHTML = "<center><h3>比赛排名</h3><a></a><table id=\"rank\"></table>";
|
2198
|
+
}
|
2199
|
+
if (document.querySelector("body > div > div.mt-3 > center > h3").innerText == "比赛排名") {
|
2200
|
+
document.querySelector("#rank").innerText = "比赛暂时还没有排名";
|
2201
|
+
}
|
2202
|
+
else {
|
2203
|
+
if (UtilityEnabled("ResetType")) {
|
2204
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText =
|
2205
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText.substring(
|
2206
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText.indexOf(" -- ") + 4)
|
2207
|
+
+ "(订正排名)";
|
2208
|
+
document.querySelector("body > div > div.mt-3 > center > a").remove();
|
2209
|
+
}
|
2210
|
+
document.querySelector("#rank > thead > tr > :nth-child(1)").innerText = "排名";
|
2211
|
+
document.querySelector("#rank > thead > tr > :nth-child(2)").innerText = "用户";
|
2212
|
+
document.querySelector("#rank > thead > tr > :nth-child(3)").innerText = "昵称";
|
2213
|
+
document.querySelector("#rank > thead > tr > :nth-child(4)").innerText = "AC数";
|
2214
|
+
document.querySelector("#rank > thead > tr > :nth-child(5)").innerText = "得分";
|
2215
|
+
let RefreshCorrectRank = async () => {
|
2216
|
+
await fetch(location.href)
|
2217
|
+
.then((Response) => {
|
2218
|
+
return Response.text()
|
2219
|
+
})
|
2220
|
+
.then(async (Response) => {
|
2221
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
2222
|
+
TidyTable(ParsedDocument.getElementById("rank"));
|
2223
|
+
let Temp = ParsedDocument.getElementById("rank").rows;
|
2224
|
+
for (var i = 1; i < Temp.length; i++) {
|
2225
|
+
let MetalCell = Temp[i].cells[0];
|
2226
|
+
let Metal = document.createElement("span");
|
2227
|
+
Metal.innerText = MetalCell.innerText;
|
2228
|
+
Metal.className = "badge text-bg-primary";
|
2229
|
+
MetalCell.innerText = "";
|
2230
|
+
MetalCell.appendChild(Metal);
|
2231
|
+
GetUsernameHTML(Temp[i].cells[1], Temp[i].cells[1].innerText);
|
2232
|
+
Temp[i].cells[2].innerHTML = Temp[i].cells[2].innerText;
|
2233
|
+
Temp[i].cells[3].innerHTML = Temp[i].cells[3].innerText;
|
2234
|
+
for (let j = 5; j < Temp[i].cells.length; j++) {
|
2235
|
+
let InnerText = Temp[i].cells[j].innerText;
|
2236
|
+
let BackgroundColor = Temp[i].cells[j].style.backgroundColor;
|
2237
|
+
let Red = BackgroundColor.substring(4, BackgroundColor.indexOf(","));
|
2238
|
+
let Green = BackgroundColor.substring(BackgroundColor.indexOf(",") + 2, BackgroundColor.lastIndexOf(","));
|
2239
|
+
let Blue = BackgroundColor.substring(BackgroundColor.lastIndexOf(",") + 2, BackgroundColor.lastIndexOf(")"));
|
2240
|
+
let NoData = (Red == 238 && Green == 238 && Blue == 238);
|
2241
|
+
let FirstBlood = (Red == 170 && Green == 170 && Blue == 255);
|
2242
|
+
let Solved = (Green == 255);
|
2243
|
+
let ErrorCount = "";
|
2244
|
+
if (Solved) {
|
2245
|
+
ErrorCount = (Blue == 170 ? "4+" : (Blue - 51) / 32);
|
2246
|
+
}
|
2247
|
+
else {
|
2248
|
+
ErrorCount = (Blue == 22 ? "14+" : (170 - Blue) / 10);
|
2249
|
+
}
|
2250
|
+
if (NoData) {
|
2251
|
+
BackgroundColor = "";
|
2252
|
+
}
|
2253
|
+
else if (FirstBlood) {
|
2254
|
+
BackgroundColor = "rgba(127, 127, 255, 0.5)";
|
2255
|
+
}
|
2256
|
+
else if (Solved) {
|
2257
|
+
BackgroundColor = "rgba(0, 255, 0, 0.5)";
|
2258
|
+
if (ErrorCount != 0) {
|
2259
|
+
InnerText += " (" + ErrorCount + ")";
|
2260
|
+
}
|
2261
|
+
}
|
2262
|
+
else {
|
2263
|
+
BackgroundColor = "rgba(255, 0, 0, 0.5)";
|
2264
|
+
if (ErrorCount != 0) {
|
2265
|
+
InnerText += " (" + ErrorCount + ")";
|
2266
|
+
}
|
2267
|
+
}
|
2268
|
+
Temp[i].cells[j].innerHTML = InnerText;
|
2269
|
+
Temp[i].cells[j].style.backgroundColor = BackgroundColor;
|
2270
|
+
}
|
2271
|
+
}
|
2272
|
+
document.querySelector("#rank > tbody").innerHTML = ParsedDocument.querySelector("#rank > tbody").innerHTML;
|
2273
|
+
});
|
2274
|
+
};
|
2275
|
+
RefreshCorrectRank();
|
2276
|
+
if (UtilityEnabled("AutoRefresh")) {
|
2277
|
+
addEventListener("focus", RefreshCorrectRank);
|
2278
|
+
}
|
2279
|
+
}
|
2280
|
+
} else if (location.pathname == "/submitpage.php") {
|
2281
|
+
document.querySelector("body > div > div.mt-3").innerHTML = `<center class="mb-3">` +
|
2282
|
+
`<h3>提交代码</h3>` +
|
2283
|
+
(SearchParams.get("id") != null ?
|
2284
|
+
`题目<span class="blue">${Number(SearchParams.get("id"))}</span>` :
|
2285
|
+
`比赛<span class="blue">${Number(SearchParams.get("cid")) + `</span> 题目<span class="blue">` + String.fromCharCode(65 + parseInt(SearchParams.get("pid")))}</span>`) +
|
2286
|
+
`</center>
|
2287
|
+
<textarea id="CodeInput"></textarea>
|
2288
|
+
<center class="mt-3">
|
2289
|
+
<input id="enable_O2" name="enable_O2" type="checkbox"><label for="enable_O2">打开O2开关</label>
|
2290
|
+
<br>
|
2291
|
+
<input id="Submit" class="btn btn-info mt-2" type="button" value="提交">
|
2292
|
+
<div id="ErrorElement" class="mt-2" style="display: none; text-align: left; padding: 10px;">
|
2293
|
+
<div id="ErrorMessage" style="white-space: pre; background-color: rgba(0, 0, 0, 0.1); padding: 10px; border-radius: 5px;"></div>
|
2294
|
+
<button id="PassCheck" class="btn btn-outline-secondary mt-2" style="display: none">强制提交</button>
|
2295
|
+
</div>
|
2296
|
+
</center>`;
|
2297
|
+
if (UtilityEnabled("AutoO2")) {
|
2298
|
+
document.querySelector("#enable_O2").checked = true;
|
2299
|
+
}
|
2300
|
+
let CodeMirrorElement;
|
2301
|
+
(() => {
|
2302
|
+
CodeMirrorElement = CodeMirror.fromTextArea(document.querySelector("#CodeInput"), {
|
2303
|
+
lineNumbers: true,
|
2304
|
+
matchBrackets: true,
|
2305
|
+
mode: "text/x-c++src",
|
2306
|
+
indentUnit: 4,
|
2307
|
+
indentWithTabs: true,
|
2308
|
+
enterMode: "keep",
|
2309
|
+
tabMode: "shift",
|
2310
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default"),
|
2311
|
+
extraKeys: {
|
2312
|
+
"Ctrl-Space": "autocomplete",
|
2313
|
+
"Ctrl-Enter": function (instance) {
|
2314
|
+
Submit.click();
|
2315
|
+
}
|
2316
|
+
}
|
2317
|
+
})
|
2318
|
+
})();
|
2319
|
+
CodeMirrorElement.setSize("100%", "auto");
|
2320
|
+
CodeMirrorElement.getWrapperElement().style.border = "1px solid #ddd";
|
2321
|
+
|
2322
|
+
if (SearchParams.get("sid") !== null) {
|
2323
|
+
await fetch("https://www.xmoj.tech/getsource.php?id=" + SearchParams.get("sid"))
|
2324
|
+
.then((Response) => {
|
2325
|
+
return Response.text()
|
2326
|
+
})
|
2327
|
+
.then((Response) => {
|
2328
|
+
CodeMirrorElement.setValue(Response.substring(0, Response.indexOf("/**************************************************************")).trim());
|
2329
|
+
});
|
2330
|
+
}
|
2331
|
+
|
2332
|
+
PassCheck.addEventListener("click", async () => {
|
2333
|
+
ErrorElement.style.display = "none";
|
2334
|
+
document.querySelector("#Submit").disabled = true;
|
2335
|
+
document.querySelector("#Submit").value = "正在提交...";
|
2336
|
+
await fetch("https://www.xmoj.tech/submit.php", {
|
2337
|
+
"headers": {
|
2338
|
+
"content-type": "application/x-www-form-urlencoded"
|
2339
|
+
},
|
2340
|
+
"referrer": location.href,
|
2341
|
+
"method": "POST",
|
2342
|
+
"body":
|
2343
|
+
(SearchParams.get("id") != null ?
|
2344
|
+
"id=" + SearchParams.get("id") :
|
2345
|
+
"cid=" + SearchParams.get("cid") + "&pid=" + SearchParams.get("pid")) +
|
2346
|
+
"&language=1&" +
|
2347
|
+
"source=" + encodeURIComponent(CodeMirrorElement.getValue()) + "&" +
|
2348
|
+
"enable_O2=on"
|
2349
|
+
}).then((Response) => {
|
2350
|
+
if (Response.redirected) {
|
2351
|
+
location.href = Response.url;
|
2352
|
+
}
|
2353
|
+
else {
|
2354
|
+
ErrorElement.style.display = "block";
|
2355
|
+
ErrorMessage.style.color = "red";
|
2356
|
+
ErrorMessage.innerText = "提交失败!请关闭脚本后重试!";
|
2357
|
+
Submit.disabled = false;
|
2358
|
+
Submit.value = "提交";
|
2359
|
+
}
|
2360
|
+
})
|
2361
|
+
});
|
2362
|
+
|
2363
|
+
Submit.addEventListener("click", async () => {
|
2364
|
+
PassCheck.style.display = "none";
|
2365
|
+
ErrorElement.style.display = "none";
|
2366
|
+
document.querySelector("#Submit").disabled = true;
|
2367
|
+
document.querySelector("#Submit").value = "正在检查...";
|
2368
|
+
let Source = CodeMirrorElement.getValue();
|
2369
|
+
let PID = 0;
|
2370
|
+
let IOFilename = "";
|
2371
|
+
if (SearchParams.get("cid") != null && SearchParams.get("pid") != null) {
|
2372
|
+
PID = localStorage.getItem("UserScript-Contest-" + SearchParams.get("cid") + "-Problem-" + SearchParams.get("pid") + "-PID")
|
2373
|
+
}
|
2374
|
+
else {
|
2375
|
+
PID = SearchParams.get("id");
|
2376
|
+
}
|
2377
|
+
IOFilename = localStorage.getItem("UserScript-Problem-" + PID + "-IOFilename");
|
2378
|
+
if (UtilityEnabled("IOFile") && IOFilename != null) {
|
2379
|
+
if (Source.indexOf(IOFilename) == -1) {
|
2380
|
+
PassCheck.style.display = "";
|
2381
|
+
ErrorElement.style.display = "block";
|
2382
|
+
ErrorMessage.style.color = "red";
|
2383
|
+
ErrorMessage.innerText = "此题输入输出文件名为" + IOFilename + ",请检查是否填错";
|
2384
|
+
document.querySelector("#Submit").disabled = false;
|
2385
|
+
document.querySelector("#Submit").value = "提交";
|
2386
|
+
return false;
|
2387
|
+
}
|
2388
|
+
else if (RegExp("//.*freopen").test(Source)) {
|
2389
|
+
PassCheck.style.display = "";
|
2390
|
+
ErrorElement.style.display = "block";
|
2391
|
+
ErrorMessage.style.color = "red";
|
2392
|
+
ErrorMessage.innerText = "请不要注释freopen语句";
|
2393
|
+
document.querySelector("#Submit").disabled = false;
|
2394
|
+
document.querySelector("#Submit").value = "提交";
|
2395
|
+
return false;
|
2396
|
+
}
|
2397
|
+
}
|
2398
|
+
if (Source == "") {
|
2399
|
+
PassCheck.style.display = "";
|
2400
|
+
ErrorElement.style.display = "block";
|
2401
|
+
ErrorMessage.style.color = "red";
|
2402
|
+
ErrorMessage.innerText = "源代码为空";
|
2403
|
+
document.querySelector("#Submit").disabled = false;
|
2404
|
+
document.querySelector("#Submit").value = "提交";
|
2405
|
+
return false;
|
2406
|
+
}
|
2407
|
+
if (UtilityEnabled("CompileError")) {
|
2408
|
+
let ResponseData = await new Promise((Resolve) => {
|
2409
|
+
GM_xmlhttpRequest({
|
2410
|
+
method: "POST",
|
2411
|
+
url: "https://cppinsights.io/api/v1/transform",
|
2412
|
+
headers: {
|
2413
|
+
"content-type": "application/json;charset=UTF-8"
|
2414
|
+
},
|
2415
|
+
referrer: "https://cppinsights.io/",
|
2416
|
+
data: JSON.stringify({
|
2417
|
+
"insightsOptions": [
|
2418
|
+
"cpp14"
|
2419
|
+
],
|
2420
|
+
"code": Source
|
2421
|
+
}),
|
2422
|
+
onload: (Response) => {
|
2423
|
+
Resolve(Response);
|
2424
|
+
}
|
2425
|
+
});
|
2426
|
+
});
|
2427
|
+
let Response = JSON.parse(ResponseData.responseText);
|
2428
|
+
if (Response.returncode) {
|
2429
|
+
PassCheck.style.display = "";
|
2430
|
+
ErrorElement.style.display = "block";
|
2431
|
+
ErrorMessage.style.color = "red";
|
2432
|
+
ErrorMessage.innerText = "编译错误:\n" + Response.stderr.trim();
|
2433
|
+
document.querySelector("#Submit").disabled = false;
|
2434
|
+
document.querySelector("#Submit").value = "提交";
|
2435
|
+
return false;
|
2436
|
+
}
|
2437
|
+
else {
|
2438
|
+
PassCheck.click();
|
2439
|
+
}
|
2440
|
+
}
|
2441
|
+
else {
|
2442
|
+
PassCheck.click();
|
2443
|
+
}
|
2444
|
+
});
|
2445
|
+
} else if (location.pathname == "/modifypage.php") {
|
2446
|
+
if (SearchParams.get("ByUserScript") != null) {
|
2447
|
+
document.querySelector("body > div > div.mt-3").innerHTML = "";
|
2448
|
+
await fetch(ServerURL + "/Update.json", { cache: "no-cache" })
|
2449
|
+
.then((Response) => {
|
2450
|
+
return Response.json();
|
2451
|
+
})
|
2452
|
+
.then((Response) => {
|
2453
|
+
for (let i = Object.keys(Response.UpdateHistory).length - 1; i >= 0; i--) {
|
2454
|
+
let Version = Object.keys(Response.UpdateHistory)[i];
|
2455
|
+
let Data = Response.UpdateHistory[Version];
|
2456
|
+
let UpdateDataCard = document.createElement("div"); document.querySelector("body > div > div.mt-3").appendChild(UpdateDataCard);
|
2457
|
+
UpdateDataCard.className = "card mb-3";
|
2458
|
+
if (Data.Prerelease)
|
2459
|
+
UpdateDataCard.classList.add("text-secondary");
|
2460
|
+
let UpdateDataCardBody = document.createElement("div"); UpdateDataCard.appendChild(UpdateDataCardBody);
|
2461
|
+
UpdateDataCardBody.className = "card-body";
|
2462
|
+
let UpdateDataCardTitle = document.createElement("h5"); UpdateDataCardBody.appendChild(UpdateDataCardTitle);
|
2463
|
+
UpdateDataCardTitle.className = "card-title";
|
2464
|
+
UpdateDataCardTitle.innerText = Version;
|
2465
|
+
if (Data.Prerelease) {
|
2466
|
+
UpdateDataCardTitle.innerHTML += "(预览版)";
|
2467
|
+
}
|
2468
|
+
let UpdateDataCardSubtitle = document.createElement("h6"); UpdateDataCardBody.appendChild(UpdateDataCardSubtitle);
|
2469
|
+
UpdateDataCardSubtitle.className = "card-subtitle mb-2 text-muted";
|
2470
|
+
UpdateDataCardSubtitle.innerHTML = GetRelativeTime(Data.UpdateDate);
|
2471
|
+
let UpdateDataCardText = document.createElement("p"); UpdateDataCardBody.appendChild(UpdateDataCardText);
|
2472
|
+
UpdateDataCardText.className = "card-text";
|
2473
|
+
let UpdateDataCardList = document.createElement("ul"); UpdateDataCardText.appendChild(UpdateDataCardList);
|
2474
|
+
UpdateDataCardList.className = "list-group list-group-flush";
|
2475
|
+
for (let j = 0; j < Data.UpdateContents.length; j++) {
|
2476
|
+
let UpdateDataCardListItem = document.createElement("li"); UpdateDataCardList.appendChild(UpdateDataCardListItem);
|
2477
|
+
UpdateDataCardListItem.className = "list-group-item";
|
2478
|
+
UpdateDataCardListItem.innerHTML =
|
2479
|
+
"(<a href=\"https://github.com/XMOJ-Script-dev/XMOJ-Script/pull/" + Data.UpdateContents[j].PR + "\" target=\"_blank\">" +
|
2480
|
+
"#" + Data.UpdateContents[j].PR + "</a>) " +
|
2481
|
+
Data.UpdateContents[j].Description;
|
2482
|
+
}
|
2483
|
+
let UpdateDataCardLink = document.createElement("a"); UpdateDataCardBody.appendChild(UpdateDataCardLink);
|
2484
|
+
UpdateDataCardLink.className = "card-link";
|
2485
|
+
UpdateDataCardLink.href = "https://github.com/XMOJ-Script-dev/XMOJ-Script/releases/tag/" + Version;
|
2486
|
+
UpdateDataCardLink.target = "_blank";
|
2487
|
+
UpdateDataCardLink.innerText = "查看该版本";
|
2488
|
+
}
|
2489
|
+
});
|
2490
|
+
}
|
2491
|
+
else {
|
2492
|
+
let Nickname = document.getElementsByName("nick")[0].value;
|
2493
|
+
let School = document.getElementsByName("school")[0].value;
|
2494
|
+
let EmailAddress = document.getElementsByName("email")[0].value;
|
2495
|
+
let CodeforcesAccount = document.getElementsByName("acc_cf")[0].value;
|
2496
|
+
let AtcoderAccount = document.getElementsByName("acc_atc")[0].value;
|
2497
|
+
let USACOAccount = document.getElementsByName("acc_usaco")[0].value;
|
2498
|
+
let LuoguAccount = document.getElementsByName("acc_luogu")[0].value;
|
2499
|
+
document.querySelector("body > div > div").innerHTML = `<div class="row g-2 align-items-center col-6 mb-1">
|
2500
|
+
<div class="col-3"><label for="UserID" class="col-form-label">用户ID</label></div>
|
2501
|
+
<div class="col-9"><input id="UserID" class="form-control" disabled readonly value="${CurrentUsername}"></div>
|
2502
|
+
</div>
|
2503
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2504
|
+
<div class="col-3"><label for="Avatar" class="col-form-label">头像</label></div>
|
2505
|
+
<div class="col-9">
|
2506
|
+
<img width="64" height="64" src="https://cravatar.cn/avatar/` + (await GetUserInfo(CurrentUsername)).EmailHash + `?d=retro">
|
2507
|
+
<a href="https://cravatar.cn/avatars" target="_blank">修改头像</a>
|
2508
|
+
</div>
|
2509
|
+
</div>
|
2510
|
+
<div class="row g-2 align-items-center col-6 pb-1 ps-2 pe-2 mt-3 mb-3 border" id="BadgeRow" style="display: none">
|
2511
|
+
<div class="col-3">标签</div>
|
2512
|
+
<div class="col-9">
|
2513
|
+
<div class="row g-2 align-items-center mb-1">
|
2514
|
+
<div class="col-3"><label for="BadgeContent" class="col-form-label">内容</label></div>
|
2515
|
+
<div class="col-9"><input class="form-control" id="BadgeContent"></div>
|
2516
|
+
</div>
|
2517
|
+
<div class="row g-2 align-items-center mb-1">
|
2518
|
+
<div class="col-3"><label for="BadgeBackgroundColor" class="col-form-label">背景颜色</label></div>
|
2519
|
+
<div class="col-9"><input class="form-control form-control-color" type="color" id="BadgeBackgroundColor"></div>
|
2520
|
+
</div>
|
2521
|
+
<div class="row g-2 align-items-center mb-1">
|
2522
|
+
<div class="col-3"><label for="BadgeColor" class="col-form-label">文字颜色</label></div>
|
2523
|
+
<div class="col-9"><input class="form-control form-control-color" type="color" id="BadgeColor"></div>
|
2524
|
+
</div>
|
2525
|
+
</div>
|
2526
|
+
</div>
|
2527
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2528
|
+
<div class="col-3"><label for="Nickname" class="col-form-label">昵称</label></div>
|
2529
|
+
<div class="col-9"><input id="Nickname" class="form-control"></div>
|
2530
|
+
</div>
|
2531
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2532
|
+
<div class="col-3"><label for="OldPassword" class="col-form-label">旧密码</label></div>
|
2533
|
+
<div class="col-9"><input type="password" id="OldPassword" class="form-control"></div>
|
2534
|
+
</div>
|
2535
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2536
|
+
<div class="col-3"><label for="NewPassword" class="col-form-label">新密码</label></div>
|
2537
|
+
<div class="col-9"><input type="password" id="NewPassword" class="form-control"></div>
|
2538
|
+
</div>
|
2539
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2540
|
+
<div class="col-3"><label for="NewPasswordAgain" class="col-form-label">请重复密码</label></div>
|
2541
|
+
<div class="col-9"><input type="password" id="NewPasswordAgain" class="form-control"></div>
|
2542
|
+
</div>
|
2543
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2544
|
+
<div class="col-3"><label for="School" class="col-form-label">学校</label></div>
|
2545
|
+
<div class="col-9"><input id="School" class="form-control"></div>
|
2546
|
+
</div>
|
2547
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2548
|
+
<div class="col-3"><label for="EmailAddress" class="col-form-label">电子邮箱</label></div>
|
2549
|
+
<div class="col-9"><input id="EmailAddress" class="form-control"></div>
|
2550
|
+
</div>
|
2551
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2552
|
+
<div class="col-3"><label for="CodeforcesAccount" class="col-form-label">Codeforces账号</label></div>
|
2553
|
+
<div class="col-9"><input id="CodeforcesAccount" class="form-control"></div>
|
2554
|
+
</div>
|
2555
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2556
|
+
<div class="col-3"><label for="AtcoderAccount" class="col-form-label">Atcoder账号</label></div>
|
2557
|
+
<div class="col-9"><input id="AtcoderAccount" class="form-control"></div>
|
2558
|
+
</div>
|
2559
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2560
|
+
<div class="col-3"><label for="USACOAccount" class="col-form-label">USACO账号</label></div>
|
2561
|
+
<div class="col-9"><input id="USACOAccount" class="form-control"></div>
|
2562
|
+
</div>
|
2563
|
+
<div class="row g-2 align-items-center col-6 mb-1">
|
2564
|
+
<div class="col-3"><label for="LuoguAccount" class="col-form-label">洛谷账号</label></div>
|
2565
|
+
<div class="col-9"><input id="LuoguAccount" class="form-control"></div>
|
2566
|
+
</div>
|
2567
|
+
<button type="submit" class="btn btn-primary mb-2" id="ModifyInfo">
|
2568
|
+
修改
|
2569
|
+
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="display: none"></span>
|
2570
|
+
</button>
|
2571
|
+
<div class="alert alert-danger mb-3" role="alert" id="ErrorElement" style="display: none;"></div>
|
2572
|
+
<div class="alert alert-success mb-3" role="alert" id="SuccessElement" style="display: none;">修改成功</div>
|
2573
|
+
<br>`;
|
2574
|
+
document.getElementById("Nickname").value = Nickname;
|
2575
|
+
document.getElementById("School").value = School;
|
2576
|
+
document.getElementById("EmailAddress").value = EmailAddress;
|
2577
|
+
document.getElementById("CodeforcesAccount").value = CodeforcesAccount;
|
2578
|
+
document.getElementById("AtcoderAccount").value = AtcoderAccount;
|
2579
|
+
document.getElementById("USACOAccount").value = USACOAccount;
|
2580
|
+
document.getElementById("LuoguAccount").value = LuoguAccount;
|
2581
|
+
RequestAPI("GetBadge", {
|
2582
|
+
"UserID": String(CurrentUsername)
|
2583
|
+
}, (Response) => {
|
2584
|
+
if (Response.Success) {
|
2585
|
+
BadgeRow.style.display = "";
|
2586
|
+
BadgeContent.value = Response.Data.Content;
|
2587
|
+
BadgeBackgroundColor.value = Response.Data.BackgroundColor;
|
2588
|
+
BadgeColor.value = Response.Data.Color;
|
2589
|
+
SuccessElement.innerText += ",用户标签会在一天内生效";
|
2590
|
+
}
|
2591
|
+
});
|
2592
|
+
ModifyInfo.addEventListener("click", async () => {
|
2593
|
+
ModifyInfo.disabled = true;
|
2594
|
+
ModifyInfo.querySelector("span").style.display = "";
|
2595
|
+
ErrorElement.style.display = "none";
|
2596
|
+
SuccessElement.style.display = "none";
|
2597
|
+
let BadgeContent = document.querySelector("#BadgeContent").value;
|
2598
|
+
let BadgeBackgroundColor = document.querySelector("#BadgeBackgroundColor").value;
|
2599
|
+
let BadgeColor = document.querySelector("#BadgeColor").value;
|
2600
|
+
await new Promise((Resolve) => {
|
2601
|
+
RequestAPI("EditBadge", {
|
2602
|
+
"UserID": String(CurrentUsername),
|
2603
|
+
"Content": String(BadgeContent),
|
2604
|
+
"BackgroundColor": String(BadgeBackgroundColor),
|
2605
|
+
"Color": String(BadgeColor)
|
2606
|
+
}, (Response) => {
|
2607
|
+
if (Response.Success) {
|
2608
|
+
Resolve();
|
2609
|
+
}
|
2610
|
+
else {
|
2611
|
+
ModifyInfo.disabled = false;
|
2612
|
+
ModifyInfo.querySelector("span").style.display = "none";
|
2613
|
+
ErrorElement.style.display = "block";
|
2614
|
+
ErrorElement.innerText = Response.Message;
|
2615
|
+
}
|
2616
|
+
});
|
2617
|
+
});
|
2618
|
+
let Nickname = document.querySelector("#Nickname").value;
|
2619
|
+
let OldPassword = document.querySelector("#OldPassword").value;
|
2620
|
+
let NewPassword = document.querySelector("#NewPassword").value;
|
2621
|
+
let NewPasswordAgain = document.querySelector("#NewPasswordAgain").value;
|
2622
|
+
let School = document.querySelector("#School").value;
|
2623
|
+
let EmailAddress = document.querySelector("#EmailAddress").value;
|
2624
|
+
let CodeforcesAccount = document.querySelector("#CodeforcesAccount").value;
|
2625
|
+
let AtcoderAccount = document.querySelector("#AtcoderAccount").value;
|
2626
|
+
let USACOAccount = document.querySelector("#USACOAccount").value;
|
2627
|
+
let LuoguAccount = document.querySelector("#LuoguAccount").value;
|
2628
|
+
await fetch("https://www.xmoj.tech/modify.php", {
|
2629
|
+
"headers": {
|
2630
|
+
"content-type": "application/x-www-form-urlencoded"
|
2631
|
+
},
|
2632
|
+
"referrer": location.href,
|
2633
|
+
"method": "POST",
|
2634
|
+
"body":
|
2635
|
+
"nick=" + encodeURIComponent(Nickname) + "&" +
|
2636
|
+
"opassword=" + encodeURIComponent(OldPassword) + "&" +
|
2637
|
+
"npassword=" + encodeURIComponent(NewPassword) + "&" +
|
2638
|
+
"rptpassword=" + encodeURIComponent(NewPasswordAgain) + "&" +
|
2639
|
+
"school=" + encodeURIComponent(School) + "&" +
|
2640
|
+
"email=" + encodeURIComponent(EmailAddress) + "&" +
|
2641
|
+
"acc_cf=" + encodeURIComponent(CodeforcesAccount) + "&" +
|
2642
|
+
"acc_atc=" + encodeURIComponent(AtcoderAccount) + "&" +
|
2643
|
+
"acc_usaco=" + encodeURIComponent(USACOAccount) + "&" +
|
2644
|
+
"acc_luogu=" + encodeURIComponent(LuoguAccount)
|
2645
|
+
});
|
2646
|
+
ModifyInfo.disabled = false;
|
2647
|
+
ModifyInfo.querySelector("span").style.display = "none";
|
2648
|
+
SuccessElement.style.display = "block";
|
2649
|
+
});
|
2650
|
+
if (UtilityEnabled("ExportACCode")) {
|
2651
|
+
let ExportACCode = document.createElement("button");
|
2652
|
+
document.querySelector("body > div.container > div").appendChild(ExportACCode);
|
2653
|
+
ExportACCode.innerText = "导出AC代码";
|
2654
|
+
ExportACCode.className = "btn btn-outline-secondary";
|
2655
|
+
ExportACCode.addEventListener("click", () => {
|
2656
|
+
ExportACCode.disabled = true;
|
2657
|
+
let ExportProgressBar = document.getElementsByTagName("progress")[0] || document.createElement("progress");
|
2658
|
+
ExportProgressBar.removeAttribute("value");
|
2659
|
+
ExportProgressBar.removeAttribute("max");
|
2660
|
+
document.querySelector("body > div.container > div").appendChild(ExportProgressBar);
|
2661
|
+
ExportACCode.innerText = "正在导出...";
|
2662
|
+
let Request = new XMLHttpRequest();
|
2663
|
+
Request.addEventListener("readystatechange", () => {
|
2664
|
+
if (Request.readyState == 4) {
|
2665
|
+
if (Request.status == 200) {
|
2666
|
+
let Response = Request.responseText;
|
2667
|
+
let ACCode = Response.split("------------------------------------------------------\r\n");
|
2668
|
+
ExportProgressBar.max = ACCode.length - 1;
|
2669
|
+
let DownloadCode = (i) => {
|
2670
|
+
if (i >= ACCode.length) {
|
2671
|
+
ExportACCode.innerText = "AC代码导出成功";
|
2672
|
+
ExportACCode.disabled = false;
|
2673
|
+
ExportProgressBar.remove();
|
2674
|
+
setTimeout(() => {
|
2675
|
+
ExportACCode.innerText = "导出AC代码";
|
2676
|
+
}, 1000);
|
2677
|
+
return;
|
2678
|
+
}
|
2679
|
+
let CurrentCode = ACCode[i];
|
2680
|
+
if (CurrentCode != "") {
|
2681
|
+
let CurrentQuestionID = CurrentCode.substring(7, 11);
|
2682
|
+
CurrentCode = CurrentCode.substring(14);
|
2683
|
+
ExportProgressBar.value = i + 1;
|
2684
|
+
let DownloadLink = document.createElement("a");
|
2685
|
+
DownloadLink.href = window.URL.createObjectURL(new Blob([CurrentCode]));
|
2686
|
+
DownloadLink.download = CurrentQuestionID + ".cpp";
|
2687
|
+
DownloadLink.click();
|
2688
|
+
}
|
2689
|
+
setTimeout(() => {
|
2690
|
+
DownloadCode(i + 1);
|
2691
|
+
}, 50);
|
2692
|
+
};
|
2693
|
+
DownloadCode(0);
|
2694
|
+
} else {
|
2695
|
+
ExportACCode.disabled = false;
|
2696
|
+
ExportACCode.innerText = "AC代码导出失败";
|
2697
|
+
setTimeout(() => {
|
2698
|
+
ExportACCode.innerText = "导出AC代码";
|
2699
|
+
}, 1000);
|
2700
|
+
}
|
2701
|
+
}
|
2702
|
+
});
|
2703
|
+
Request.open("GET", "https://www.xmoj.tech/export_ac_code.php", true);
|
2704
|
+
Request.send();
|
2705
|
+
});
|
2706
|
+
}
|
2707
|
+
}
|
2708
|
+
} else if (location.pathname == "/userinfo.php") {
|
2709
|
+
if (SearchParams.get("ByUserScript") === null) {
|
2710
|
+
if (UtilityEnabled("RemoveUseless")) {
|
2711
|
+
let Temp = document.getElementById("submission").childNodes;
|
2712
|
+
for (let i = 0; i < Temp.length; i++) {
|
2713
|
+
Temp[i].remove();
|
2714
|
+
}
|
2715
|
+
}
|
2716
|
+
eval(document.querySelector("body > script:nth-child(5)").innerHTML);
|
2717
|
+
document.querySelector("#statics > tbody > tr:nth-child(1)").remove();
|
2718
|
+
|
2719
|
+
let Temp = document.querySelector("#statics > tbody").children;
|
2720
|
+
for (let i = 0; i < Temp.length; i++) {
|
2721
|
+
if (Temp[i].children[0] != undefined) {
|
2722
|
+
if (Temp[i].children[0].innerText == "Statistics") {
|
2723
|
+
Temp[i].children[0].innerText = "统计";
|
2724
|
+
}
|
2725
|
+
else if (Temp[i].children[0].innerText == "Email:") {
|
2726
|
+
Temp[i].children[0].innerText = "电子邮箱";
|
2727
|
+
}
|
2728
|
+
else {
|
2729
|
+
Temp[i].children[1].innerText = Temp[i].children[1].innerText;
|
2730
|
+
}
|
2731
|
+
Temp[i].children[1].removeAttribute("align");
|
2732
|
+
}
|
2733
|
+
}
|
2734
|
+
|
2735
|
+
Temp = document.querySelector("#statics > tbody > tr:nth-child(1) > td:nth-child(3)").childNodes;
|
2736
|
+
let ACProblems = [];
|
2737
|
+
for (let i = 0; i < Temp.length; i++) {
|
2738
|
+
if (Temp[i].tagName == "A" && Temp[i].href.indexOf("problem.php?id=") != -1) {
|
2739
|
+
ACProblems.push(Number(Temp[i].innerText.trim()));
|
2740
|
+
}
|
2741
|
+
}
|
2742
|
+
document.querySelector("#statics > tbody > tr:nth-child(1) > td:nth-child(3)").remove();
|
2743
|
+
|
2744
|
+
let UserID, UserNick;
|
2745
|
+
[UserID, UserNick] = document.querySelector("#statics > caption").childNodes[0].data.trim().split("--");
|
2746
|
+
document.querySelector("#statics > caption").remove();
|
2747
|
+
|
2748
|
+
let Row = document.createElement("div"); Row.className = "row";
|
2749
|
+
let LeftDiv = document.createElement("div"); LeftDiv.className = "col-md-5"; Row.appendChild(LeftDiv);
|
2750
|
+
|
2751
|
+
let LeftTopDiv = document.createElement("div"); LeftTopDiv.className = "row mb-2"; LeftDiv.appendChild(LeftTopDiv);
|
2752
|
+
let AvatarContainer = document.createElement("div");
|
2753
|
+
AvatarContainer.classList.add("col-auto");
|
2754
|
+
let AvatarElement = document.createElement("img");
|
2755
|
+
let UserEmailHash = (await GetUserInfo(UserID)).EmailHash;
|
2756
|
+
if (UserEmailHash == undefined) {
|
2757
|
+
AvatarElement.src = `https://cravatar.cn/avatar/00000000000000000000000000000000?d=mp&f=y`;
|
2758
|
+
}
|
2759
|
+
else {
|
2760
|
+
AvatarElement.src = `https://cravatar.cn/avatar/${UserEmailHash}?d=retro`;
|
2761
|
+
}
|
2762
|
+
AvatarElement.classList.add("rounded", "me-2");
|
2763
|
+
AvatarElement.style.height = "120px";
|
2764
|
+
AvatarContainer.appendChild(AvatarElement);
|
2765
|
+
LeftTopDiv.appendChild(AvatarContainer);
|
2766
|
+
|
2767
|
+
let UserInfoElement = document.createElement("div");
|
2768
|
+
UserInfoElement.classList.add("col-auto");
|
2769
|
+
UserInfoElement.style.lineHeight = "40px";
|
2770
|
+
UserInfoElement.innerHTML += "用户名:" + UserID + "<br>";
|
2771
|
+
UserInfoElement.innerHTML += "昵称:" + UserNick + "<br>";
|
2772
|
+
if (UtilityEnabled("Rating")) {
|
2773
|
+
UserInfoElement.innerHTML += "评分:" + ((await GetUserInfo(UserID)).Rating) + "<br>";
|
2774
|
+
}
|
2775
|
+
// Create a placeholder for the last online time
|
2776
|
+
let lastOnlineElement = document.createElement('div');
|
2777
|
+
lastOnlineElement.innerHTML = "最后在线:加载中...<br>";
|
2778
|
+
UserInfoElement.appendChild(lastOnlineElement);
|
2779
|
+
|
2780
|
+
RequestAPI("LastOnline", {"Username": UserID}, (result) => {
|
2781
|
+
if (result.Success) {
|
2782
|
+
if (UtilityEnabled("DebugMode")) {
|
2783
|
+
console.log('lastOnline:' + result.Data.logintime);
|
2784
|
+
}
|
2785
|
+
lastOnlineElement.innerHTML = "最后在线:" + GetRelativeTime(result.Data.logintime) + "<br>";
|
2786
|
+
} else {
|
2787
|
+
lastOnlineElement.innerHTML = "最后在线:近三个月内从未<br>";
|
2788
|
+
}
|
2789
|
+
});
|
2790
|
+
LeftTopDiv.appendChild(UserInfoElement);
|
2791
|
+
LeftDiv.appendChild(LeftTopDiv);
|
2792
|
+
|
2793
|
+
let LeftTable = document.querySelector("body > div > div > center > table"); LeftDiv.appendChild(LeftTable);
|
2794
|
+
let RightDiv = document.createElement("div"); RightDiv.className = "col-md-7"; Row.appendChild(RightDiv);
|
2795
|
+
RightDiv.innerHTML = "<h5>已解决题目</h5>";
|
2796
|
+
for (let i = 0; i < ACProblems.length; i++) {
|
2797
|
+
RightDiv.innerHTML += "<a href=\"https://www.xmoj.tech/problem.php?id=" + ACProblems[i] + "\" target=\"_blank\">" + ACProblems[i] + "</a> ";
|
2798
|
+
}
|
2799
|
+
document.querySelector("body > div > div").innerHTML = "";
|
2800
|
+
document.querySelector("body > div > div").appendChild(Row);
|
2801
|
+
} else {
|
2802
|
+
document.querySelector("body > div > div.mt-3").innerHTML = `<button id="UploadStd" class="btn btn-primary mb-2">上传标程</button>
|
2803
|
+
<div class="alert alert-danger mb-3" role="alert" id="ErrorElement" style="display: none;"></div>
|
2804
|
+
<div class="progress" role="progressbar">
|
2805
|
+
<div id="UploadProgress" class="progress-bar progress-bar-striped" style="width: 0%">0%</div>
|
2806
|
+
</div>
|
2807
|
+
<p class="mt-2 text-muted">
|
2808
|
+
您必须要上传标程以后才能使用“查看标程”功能。点击“上传标程”按钮以后,系统会自动上传标程,请您耐心等待。<br>
|
2809
|
+
首次上传标程可能会比较慢,请耐心等待。后续上传标程将会快很多。请不要直接抄袭或递交标程,否则会给予"作弊者"badge的惩罚!<br>
|
2810
|
+
上传的内容不是您AC的程序,而是您AC的题目对应的用户std的程序。所以您可以放心上传,不会泄露您的代码。<br>
|
2811
|
+
系统每过30天会自动提醒您上传标程,您必须要上传标程,否则将会被禁止使用“查看标程”功能。<br>
|
2812
|
+
</p>`;
|
2813
|
+
UploadStd.addEventListener("click", async () => {
|
2814
|
+
UploadStd.disabled = true;
|
2815
|
+
ErrorElement.style.display = "none";
|
2816
|
+
ErrorElement.innerText = "";
|
2817
|
+
UploadProgress.classList.remove("bg-success");
|
2818
|
+
UploadProgress.classList.remove("bg-warning");
|
2819
|
+
UploadProgress.classList.remove("bg-danger");
|
2820
|
+
UploadProgress.classList.add("progress-bar-animated");
|
2821
|
+
UploadProgress.style.width = "0%";
|
2822
|
+
UploadProgress.innerText = "0%";
|
2823
|
+
let ACList = [];
|
2824
|
+
await fetch("https://www.xmoj.tech/userinfo.php?user=" + CurrentUsername)
|
2825
|
+
.then((Response) => {
|
2826
|
+
return Response.text();
|
2827
|
+
}).then((Response) => {
|
2828
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
2829
|
+
let ScriptData = ParsedDocument.querySelector("#statics > tbody > tr:nth-child(2) > td:nth-child(3) > script").innerText;
|
2830
|
+
ScriptData = ScriptData.substr(ScriptData.indexOf("}") + 1).trim();
|
2831
|
+
ScriptData = ScriptData.split(";");
|
2832
|
+
for (let i = 0; i < ScriptData.length; i++) {
|
2833
|
+
ACList.push(Number(ScriptData[i].substring(2, ScriptData[i].indexOf(","))));
|
2834
|
+
}
|
2835
|
+
});
|
2836
|
+
RequestAPI("GetStdList", {}, async (Result) => {
|
2837
|
+
if (Result.Success) {
|
2838
|
+
let StdList = Result.Data.StdList;
|
2839
|
+
for (let i = 0; i < ACList.length; i++) {
|
2840
|
+
if (StdList.indexOf(ACList[i]) === -1) {
|
2841
|
+
await new Promise((Resolve) => {
|
2842
|
+
RequestAPI("UploadStd", {
|
2843
|
+
"ProblemID": Number(ACList[i])
|
2844
|
+
}, (Result) => {
|
2845
|
+
if (!Result.Success) {
|
2846
|
+
ErrorElement.style.display = "block";
|
2847
|
+
ErrorElement.innerText += Result.Message + "<br>";
|
2848
|
+
UploadProgress.classList.add("bg-warning");
|
2849
|
+
}
|
2850
|
+
UploadProgress.innerText = (i / ACList.length * 100).toFixed(1) + "% (" + ACList[i] + ")";
|
2851
|
+
UploadProgress.style.width = (i / ACList.length * 100) + "%";
|
2852
|
+
Resolve();
|
2853
|
+
});
|
2854
|
+
});
|
2855
|
+
}
|
2856
|
+
}
|
2857
|
+
UploadProgress.classList.add("bg-success");
|
2858
|
+
UploadProgress.classList.remove("progress-bar-animated");
|
2859
|
+
UploadProgress.innerText = "100%";
|
2860
|
+
UploadProgress.style.width = "100%";
|
2861
|
+
UploadStd.disabled = false;
|
2862
|
+
localStorage.setItem("UserScript-LastUploadedStdTime", new Date().getTime());
|
2863
|
+
}
|
2864
|
+
else {
|
2865
|
+
ErrorElement.style.display = "block";
|
2866
|
+
ErrorElement.innerText = Result.Message;
|
2867
|
+
UploadStd.disabled = false;
|
2868
|
+
}
|
2869
|
+
});
|
2870
|
+
});
|
2871
|
+
}
|
2872
|
+
} else if (location.pathname == "/conteststatistics.php") {
|
2873
|
+
document.querySelector("body > div > div.mt-3 > center > h3").innerText = "比赛统计";
|
2874
|
+
if (UtilityEnabled("ResetType")) {
|
2875
|
+
let Temp = document.getElementById("submission").childNodes;
|
2876
|
+
for (let i = 0; i < Temp.length; i++) {
|
2877
|
+
Temp[i].remove();
|
2878
|
+
}
|
2879
|
+
eval(document.querySelector("body > div.container > div > center > table:nth-child(4) > script:nth-child(6)").innerHTML);
|
2880
|
+
document.querySelector("#cs > thead > tr > th:nth-child(1)").innerText = "题目编号";
|
2881
|
+
document.querySelector("#cs > thead > tr > th:nth-child(10)").remove();
|
2882
|
+
document.querySelector("#cs > thead > tr > th:nth-child(11)").innerText = "总和";
|
2883
|
+
document.querySelector("#cs > thead > tr > th:nth-child(12)").remove();
|
2884
|
+
document.querySelector("#cs > thead > tr > th:nth-child(12)").remove();
|
2885
|
+
document.querySelector("#cs > thead > tr > th:nth-child(12)").remove();
|
2886
|
+
document.querySelector("#cs > tbody > tr:last-child > td").innerText = "总和";
|
2887
|
+
TidyTable(document.getElementById("cs"));
|
2888
|
+
Temp = document.querySelector("#cs > tbody").children;
|
2889
|
+
for (let i = 0; i < Temp.length; i++) {
|
2890
|
+
let CurrentRowChildren = Temp[i].children;
|
2891
|
+
CurrentRowChildren[9].remove();
|
2892
|
+
CurrentRowChildren[11].remove();
|
2893
|
+
CurrentRowChildren[11].remove();
|
2894
|
+
CurrentRowChildren[11].remove();
|
2895
|
+
for (let j = 0; j < CurrentRowChildren.length; j++) {
|
2896
|
+
if (CurrentRowChildren[j].innerText == "") {
|
2897
|
+
CurrentRowChildren[j].innerText = "0";
|
2898
|
+
}
|
2899
|
+
}
|
2900
|
+
}
|
2901
|
+
}
|
2902
|
+
} else if (location.pathname == "/comparesource.php") {
|
2903
|
+
if (UtilityEnabled("CompareSource")) {
|
2904
|
+
if (location.search == "") {
|
2905
|
+
document.querySelector("body > div.container > div").innerHTML = "";
|
2906
|
+
let LeftCodeText = document.createElement("span");
|
2907
|
+
document.querySelector("body > div.container > div").appendChild(LeftCodeText);
|
2908
|
+
LeftCodeText.innerText = "左侧代码的运行编号:";
|
2909
|
+
let LeftCode = document.createElement("input");
|
2910
|
+
document.querySelector("body > div.container > div").appendChild(LeftCode);
|
2911
|
+
LeftCode.classList.add("form-control");
|
2912
|
+
LeftCode.style.width = "40%";
|
2913
|
+
LeftCode.style.marginBottom = "5px";
|
2914
|
+
let RightCodeText = document.createElement("span");
|
2915
|
+
document.querySelector("body > div.container > div").appendChild(RightCodeText);
|
2916
|
+
RightCodeText.innerText = "右侧代码的运行编号:";
|
2917
|
+
let RightCode = document.createElement("input");
|
2918
|
+
document.querySelector("body > div.container > div").appendChild(RightCode);
|
2919
|
+
RightCode.classList.add("form-control");
|
2920
|
+
RightCode.style.width = "40%";
|
2921
|
+
RightCode.style.marginBottom = "5px";
|
2922
|
+
let CompareButton = document.createElement("button");
|
2923
|
+
document.querySelector("body > div.container > div").appendChild(CompareButton);
|
2924
|
+
CompareButton.innerText = "比较";
|
2925
|
+
CompareButton.className = "btn btn-primary";
|
2926
|
+
CompareButton.addEventListener("click", () => {
|
2927
|
+
location.href = "https://www.xmoj.tech/comparesource.php?left=" + Number(LeftCode.value) + "&right=" + Number(RightCode.value);
|
2928
|
+
});
|
2929
|
+
}
|
2930
|
+
else {
|
2931
|
+
document.querySelector("body > div > div.mt-3").innerHTML = `
|
2932
|
+
<div class="form-check">
|
2933
|
+
<input class="form-check-input" type="checkbox" checked id="IgnoreWhitespace">
|
2934
|
+
<label class="form-check-label" for="IgnoreWhitespace">忽略空白</label>
|
2935
|
+
</div>
|
2936
|
+
<div id="CompareElement"></div>`;
|
2937
|
+
|
2938
|
+
let LeftCode = "";
|
2939
|
+
await fetch("https://www.xmoj.tech/getsource.php?id=" + SearchParams.get("left"))
|
2940
|
+
.then((Response) => {
|
2941
|
+
return Response.text();
|
2942
|
+
}).then((Response) => {
|
2943
|
+
LeftCode = Response.substring(0, Response.indexOf("/**************************************************************")).trim();
|
2944
|
+
});
|
2945
|
+
let RightCode = "";
|
2946
|
+
await fetch("https://www.xmoj.tech/getsource.php?id=" + SearchParams.get("right"))
|
2947
|
+
.then((Response) => {
|
2948
|
+
return Response.text();
|
2949
|
+
}).then((Response) => {
|
2950
|
+
RightCode = Response.substring(0, Response.indexOf("/**************************************************************")).trim();
|
2951
|
+
});
|
2952
|
+
|
2953
|
+
let MergeViewElement = CodeMirror.MergeView(CompareElement, {
|
2954
|
+
value: LeftCode,
|
2955
|
+
origLeft: null,
|
2956
|
+
orig: RightCode,
|
2957
|
+
lineNumbers: true,
|
2958
|
+
mode: "text/x-c++src",
|
2959
|
+
collapseIdentical: "true",
|
2960
|
+
readOnly: true,
|
2961
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default"),
|
2962
|
+
revertButtons: false,
|
2963
|
+
ignoreWhitespace: true
|
2964
|
+
});
|
2965
|
+
|
2966
|
+
IgnoreWhitespace.addEventListener("change", () => {
|
2967
|
+
MergeViewElement.ignoreWhitespace = ignorews.checked;
|
2968
|
+
});
|
2969
|
+
}
|
2970
|
+
}
|
2971
|
+
} else if (location.pathname == "/loginpage.php") {
|
2972
|
+
if (UtilityEnabled("NewBootstrap")) {
|
2973
|
+
document.querySelector("#login").innerHTML = `<form id="login" action="login.php" method="post">
|
2974
|
+
<div class="row g-3 align-items-center mb-3">
|
2975
|
+
<div class="col-auto">
|
2976
|
+
<label for="user_id" class="col-form-label">用户名(学号)</label>
|
2977
|
+
</div>
|
2978
|
+
<div class="col-auto">
|
2979
|
+
<input type="text" id="user_id" name="user_id" class="form-control">
|
2980
|
+
</div>
|
2981
|
+
</div>
|
2982
|
+
<div class="row g-3 align-items-center mb-3">
|
2983
|
+
<div class="col-auto">
|
2984
|
+
<label for="password" class="col-form-label">密码</label>
|
2985
|
+
</div>
|
2986
|
+
<div class="col-auto">
|
2987
|
+
<input type="password" id="password" name="password" class="form-control">
|
2988
|
+
</div>
|
2989
|
+
</div>
|
2990
|
+
<div class="row g-3 align-items-center mb-3">
|
2991
|
+
<div class="col-auto">
|
2992
|
+
<button name="submit" type="button" class="btn btn-primary">登录</button>
|
2993
|
+
</div>
|
2994
|
+
<div class="col-auto">
|
2995
|
+
<a class="btn btn-warning" href="https://www.xmoj.tech/lostpassword.php">忘记密码</a>
|
2996
|
+
</div>
|
2997
|
+
</div>
|
2998
|
+
</form > `;
|
2999
|
+
}
|
3000
|
+
let ErrorText = document.createElement("div");
|
3001
|
+
ErrorText.style.color = "red";
|
3002
|
+
ErrorText.style.marginBottom = "5px";
|
3003
|
+
document.querySelector("#login").appendChild(ErrorText);
|
3004
|
+
let LoginButton = document.getElementsByName("submit")[0];
|
3005
|
+
LoginButton.addEventListener("click", async () => {
|
3006
|
+
let Username = document.getElementsByName("user_id")[0].value;
|
3007
|
+
let Password = document.getElementsByName("password")[0].value;
|
3008
|
+
if (Username == "" ||
|
3009
|
+
Password == "") {
|
3010
|
+
ErrorText.innerText = "用户名或密码不能为空";
|
3011
|
+
} else {
|
3012
|
+
await fetch("https://www.xmoj.tech/login.php", {
|
3013
|
+
method: "POST",
|
3014
|
+
headers: {
|
3015
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
3016
|
+
},
|
3017
|
+
body: "user_id=" + encodeURIComponent(Username) +
|
3018
|
+
"&password=" + hex_md5(Password)
|
3019
|
+
})
|
3020
|
+
.then((Response) => {
|
3021
|
+
return Response.text();
|
3022
|
+
})
|
3023
|
+
.then((Response) => {
|
3024
|
+
if (UtilityEnabled("LoginFailed")) {
|
3025
|
+
if (Response.indexOf("history.go(-2);") != -1) {
|
3026
|
+
if (UtilityEnabled("SavePassword")) {
|
3027
|
+
localStorage.setItem("UserScript-Username", Username);
|
3028
|
+
localStorage.setItem("UserScript-Password", Password);
|
3029
|
+
}
|
3030
|
+
let NewPage = localStorage.getItem("UserScript-LastPage");
|
3031
|
+
if (NewPage == null) {
|
3032
|
+
NewPage = "https://www.xmoj.tech/index.php";
|
3033
|
+
}
|
3034
|
+
location.href = NewPage;
|
3035
|
+
} else {
|
3036
|
+
if (UtilityEnabled("SavePassword")) {
|
3037
|
+
localStorage.removeItem("UserScript-Username");
|
3038
|
+
localStorage.removeItem("UserScript-Password");
|
3039
|
+
}
|
3040
|
+
Response = Response.substring(Response.indexOf("alert('") + 7);
|
3041
|
+
Response = Response.substring(0, Response.indexOf("');"));
|
3042
|
+
if (Response == "UserName or Password Wrong!") {
|
3043
|
+
ErrorText.innerText = "用户名或密码错误!";
|
3044
|
+
}
|
3045
|
+
else {
|
3046
|
+
ErrorText.innerText = Response;
|
3047
|
+
}
|
3048
|
+
}
|
3049
|
+
}
|
3050
|
+
else {
|
3051
|
+
document.innerHTML = Response;
|
3052
|
+
}
|
3053
|
+
});
|
3054
|
+
}
|
3055
|
+
});
|
3056
|
+
if (UtilityEnabled("SavePassword") &&
|
3057
|
+
localStorage.getItem("UserScript-Username") != null &&
|
3058
|
+
localStorage.getItem("UserScript-Password") != null) {
|
3059
|
+
document.querySelector("#login > div:nth-child(1) > div > input").value = localStorage.getItem("UserScript-Username");
|
3060
|
+
document.querySelector("#login > div:nth-child(2) > div > input").value = localStorage.getItem("UserScript-Password");
|
3061
|
+
LoginButton.click();
|
3062
|
+
}
|
3063
|
+
} else if (location.pathname == "/contest_video.php" || location.pathname == "/problem_video.php") {
|
3064
|
+
let ScriptData = document.querySelector("body > div > div.mt-3 > center > script").innerHTML;
|
3065
|
+
if (document.getElementById("J_prismPlayer0").innerHTML != "") {
|
3066
|
+
document.getElementById("J_prismPlayer0").innerHTML = "";
|
3067
|
+
if (player) {
|
3068
|
+
player.dispose();
|
3069
|
+
}
|
3070
|
+
eval(ScriptData);
|
3071
|
+
}
|
3072
|
+
if (UtilityEnabled("DownloadPlayback")) {
|
3073
|
+
ScriptData = ScriptData.substring(ScriptData.indexOf("{"));
|
3074
|
+
ScriptData = ScriptData.substring(0, ScriptData.indexOf("}") + 1);
|
3075
|
+
ScriptData = ScriptData.replace(/([a-zA-Z0-9]+) ?:/g, "\"$1\":");
|
3076
|
+
ScriptData = ScriptData.replace(/'/g, "\"");
|
3077
|
+
let VideoData = JSON.parse(ScriptData);
|
3078
|
+
let RandomUUID = () => {
|
3079
|
+
let t = "0123456789abcdef";
|
3080
|
+
let e = [];
|
3081
|
+
for (let r = 0; r < 36; r++)
|
3082
|
+
e[r] = t.substr(Math.floor(16 * Math.random()), 1);
|
3083
|
+
e[14] = "4";
|
3084
|
+
e[19] = t.substr(3 & e[19] | 8, 1);
|
3085
|
+
e[8] = e[13] = e[18] = e[23] = "-";
|
3086
|
+
return e.join("");
|
3087
|
+
};
|
3088
|
+
let URLParams = new URLSearchParams({
|
3089
|
+
"AccessKeyId": VideoData.accessKeyId,
|
3090
|
+
"Action": "GetPlayInfo",
|
3091
|
+
"VideoId": VideoData.vid,
|
3092
|
+
"Formats": "",
|
3093
|
+
"AuthTimeout": 7200,
|
3094
|
+
"Rand": RandomUUID(),
|
3095
|
+
"SecurityToken": VideoData.securityToken,
|
3096
|
+
"StreamType": "video",
|
3097
|
+
"Format": "JSON",
|
3098
|
+
"Version": "2017-03-21",
|
3099
|
+
"SignatureMethod": "HMAC-SHA1",
|
3100
|
+
"SignatureVersion": "1.0",
|
3101
|
+
"SignatureNonce": RandomUUID(),
|
3102
|
+
"PlayerVersion": "2.9.3",
|
3103
|
+
"Channel": "HTML5"
|
3104
|
+
});
|
3105
|
+
URLParams.sort();
|
3106
|
+
await fetch("https://vod." + VideoData.region + ".aliyuncs.com/?" +
|
3107
|
+
URLParams.toString() +
|
3108
|
+
"&Signature=" +
|
3109
|
+
encodeURIComponent(CryptoJS.HmacSHA1("GET&%2F&" + encodeURIComponent(URLParams.toString()),
|
3110
|
+
VideoData.accessKeySecret + "&").toString(CryptoJS.enc.Base64)))
|
3111
|
+
.then((Response) => {
|
3112
|
+
return Response.json();
|
3113
|
+
})
|
3114
|
+
.then((Response) => {
|
3115
|
+
let DownloadButton = document.createElement("a");
|
3116
|
+
DownloadButton.className = "btn btn-outline-secondary";
|
3117
|
+
DownloadButton.innerText = "下载";
|
3118
|
+
DownloadButton.href = Response.PlayInfoList.PlayInfo[0].PlayURL;
|
3119
|
+
DownloadButton.download = Response.VideoBase.Title;
|
3120
|
+
document.querySelector("body > div > div.mt-3 > center").appendChild(DownloadButton);
|
3121
|
+
});
|
3122
|
+
}
|
3123
|
+
} else if (location.pathname == "/reinfo.php") {
|
3124
|
+
if (document.querySelector("#results > div") == undefined) {
|
3125
|
+
document.querySelector("#results").parentElement.innerHTML = "没有测试点信息";
|
3126
|
+
}
|
3127
|
+
else {
|
3128
|
+
for (let i = 0; i < document.querySelector("#results > div").children.length; i++) {
|
3129
|
+
let CurrentElement = document.querySelector("#results > div").children[i].children[0].children[0].children[0];
|
3130
|
+
let Temp = CurrentElement.innerText.substring(0, CurrentElement.innerText.length - 2).split("/");
|
3131
|
+
CurrentElement.innerText = TimeToStringTime(Temp[0]) + "/" + SizeToStringSize(Temp[1]);
|
3132
|
+
}
|
3133
|
+
if (document.getElementById("apply_data")) {
|
3134
|
+
let ApplyDiv = document.getElementById("apply_data").parentElement;
|
3135
|
+
console.log("启动!!!");
|
3136
|
+
if (UtilityEnabled("ApplyData")) {
|
3137
|
+
let GetDataButton = document.createElement("button");
|
3138
|
+
GetDataButton.className = "ms-2 btn btn-outline-secondary";
|
3139
|
+
GetDataButton.innerText = "获取数据";
|
3140
|
+
console.log("按钮创建成功");
|
3141
|
+
ApplyDiv.appendChild(GetDataButton);
|
3142
|
+
GetDataButton.addEventListener("click", async () => {
|
3143
|
+
GetDataButton.disabled = true;
|
3144
|
+
GetDataButton.innerText = "正在获取数据...";
|
3145
|
+
let PID = localStorage.getItem("UserScript-Solution-" + SearchParams.get("sid") + "-Problem");
|
3146
|
+
let Code = "";
|
3147
|
+
if (localStorage.getItem(`UserScript-Problem-${PID}-IOFilename`) !== null) {
|
3148
|
+
Code = `#define IOFile "${localStorage.getItem(`UserScript-Problem-${PID}-IOFilename`)}"\n`;
|
3149
|
+
}
|
3150
|
+
Code += `//XMOJ-Script 获取数据代码
|
3151
|
+
#include <bits/stdc++.h>
|
3152
|
+
using namespace std;
|
3153
|
+
string Base64Encode(string Input)
|
3154
|
+
{
|
3155
|
+
const string Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
3156
|
+
string Output;
|
3157
|
+
for (int i = 0; i < Input.length(); i += 3)
|
3158
|
+
{
|
3159
|
+
Output.push_back(i + 0 > Input.length() ? '=' : Base64Chars[(Input[i + 0] & 0xfc) >> 2]);
|
3160
|
+
Output.push_back(i + 1 > Input.length() ? '=' : Base64Chars[((Input[i + 0] & 0x03) << 4) + ((Input[i + 1] & 0xf0) >> 4)]);
|
3161
|
+
Output.push_back(i + 2 > Input.length() ? '=' : Base64Chars[((Input[i + 1] & 0x0f) << 2) + ((Input[i + 2] & 0xc0) >> 6)]);
|
3162
|
+
Output.push_back(i + 3 > Input.length() ? '=' : Base64Chars[Input[i + 2] & 0x3f]);
|
3163
|
+
}
|
3164
|
+
return Output;
|
3165
|
+
}
|
3166
|
+
int main()
|
3167
|
+
{
|
3168
|
+
#ifdef IOFile
|
3169
|
+
freopen(IOFile ".in", "r", stdin);
|
3170
|
+
freopen(IOFile ".out", "w", stdout);
|
3171
|
+
#endif
|
3172
|
+
string Input;
|
3173
|
+
while (1)
|
3174
|
+
{
|
3175
|
+
char Data = getchar();
|
3176
|
+
if (Data == EOF)
|
3177
|
+
break;
|
3178
|
+
Input.push_back(Data);
|
3179
|
+
}
|
3180
|
+
throw runtime_error("[" + Base64Encode(Input.c_str()) + "]");
|
3181
|
+
return 0;
|
3182
|
+
}`;
|
3183
|
+
|
3184
|
+
await fetch("https://www.xmoj.tech/submit.php", {
|
3185
|
+
"headers": {
|
3186
|
+
"content-type": "application/x-www-form-urlencoded"
|
3187
|
+
},
|
3188
|
+
"referrer": "https://www.xmoj.tech/submitpage.php?id=" + PID,
|
3189
|
+
"method": "POST",
|
3190
|
+
"body": "id=" + PID + "&" +
|
3191
|
+
"language=1&" +
|
3192
|
+
"source=" + encodeURIComponent(Code) + "&" +
|
3193
|
+
"enable_O2=on"
|
3194
|
+
});
|
3195
|
+
|
3196
|
+
let SID = await fetch("https://www.xmoj.tech/status.php").then((Response) => {
|
3197
|
+
return Response.text();
|
3198
|
+
}).then((Response) => {
|
3199
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
3200
|
+
return ParsedDocument.querySelector("#result-tab > tbody > tr:nth-child(1) > td:nth-child(2)").innerText;
|
3201
|
+
});
|
3202
|
+
|
3203
|
+
await new Promise((Resolve) => {
|
3204
|
+
let Interval = setInterval(async () => {
|
3205
|
+
await fetch("status-ajax.php?solution_id=" + SID).then((Response) => {
|
3206
|
+
return Response.text();
|
3207
|
+
}).then((Response) => {
|
3208
|
+
if (Response.split(",")[0] >= 4) {
|
3209
|
+
clearInterval(Interval);
|
3210
|
+
Resolve();
|
3211
|
+
}
|
3212
|
+
});
|
3213
|
+
}, 500);
|
3214
|
+
});
|
3215
|
+
|
3216
|
+
await fetch(`https://www.xmoj.tech/reinfo.php?sid=${SID}`).then((Response) => {
|
3217
|
+
return Response.text();
|
3218
|
+
}).then((Response) => {
|
3219
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
3220
|
+
let ErrorData = ParsedDocument.getElementById("errtxt").innerText;
|
3221
|
+
let MatchResult = ErrorData.match(/\what\(\): \[([A-Za-z0-9+\/=]+)\]/g);
|
3222
|
+
for (let i = 0; i < MatchResult.length; i++) {
|
3223
|
+
let Data = CryptoJS.enc.Base64.parse(MatchResult[i].substring(10, MatchResult[i].length - 1)).toString(CryptoJS.enc.Utf8);
|
3224
|
+
ApplyDiv.appendChild(document.createElement("hr"));
|
3225
|
+
ApplyDiv.appendChild(document.createTextNode("数据" + (i + 1) + ":"));
|
3226
|
+
let CodeElement = document.createElement("div");
|
3227
|
+
ApplyDiv.appendChild(CodeElement);
|
3228
|
+
CodeMirror(CodeElement, {
|
3229
|
+
value: Data,
|
3230
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default"),
|
3231
|
+
lineNumbers: true,
|
3232
|
+
readOnly: true
|
3233
|
+
}).setSize("100%", "auto");
|
3234
|
+
}
|
3235
|
+
GetDataButton.innerText = "获取数据成功";
|
3236
|
+
GetDataButton.disabled = false;
|
3237
|
+
});
|
3238
|
+
});
|
3239
|
+
}
|
3240
|
+
document.getElementById("apply_data").addEventListener("click", () => {
|
3241
|
+
let ApplyElements = document.getElementsByClassName("data");
|
3242
|
+
for (let i = 0; i < ApplyElements.length; i++) {
|
3243
|
+
ApplyElements[i].style.display = (ApplyElements[i].style.display == "block" ? "" : "block");
|
3244
|
+
}
|
3245
|
+
});
|
3246
|
+
}
|
3247
|
+
let ApplyElements = document.getElementsByClassName("data");
|
3248
|
+
for (let i = 0; i < ApplyElements.length; i++) {
|
3249
|
+
ApplyElements[i].addEventListener("click", async () => {
|
3250
|
+
await fetch("https://www.xmoj.tech/data_distribute_ajax_apply.php", {
|
3251
|
+
method: "POST",
|
3252
|
+
headers: {
|
3253
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
3254
|
+
},
|
3255
|
+
body: "user_id=" + CurrentUsername + "&" +
|
3256
|
+
"solution_id=" + SearchParams.get("sid") + "&" +
|
3257
|
+
"name=" + ApplyElements[i].getAttribute("name")
|
3258
|
+
}).then((Response) => {
|
3259
|
+
return Response.json();
|
3260
|
+
}).then((Response) => {
|
3261
|
+
ApplyElements[i].innerText = Response.msg;
|
3262
|
+
setTimeout(() => {
|
3263
|
+
ApplyElements[i].innerText = "申请数据";
|
3264
|
+
}, 1000);
|
3265
|
+
});
|
3266
|
+
});
|
3267
|
+
}
|
3268
|
+
}
|
3269
|
+
} else if (location.pathname == "/downloads.php") {
|
3270
|
+
let SoftwareList = document.querySelector("body > div > ul");
|
3271
|
+
SoftwareList.remove();
|
3272
|
+
SoftwareList = document.createElement("ul");
|
3273
|
+
SoftwareList.className = "software_list";
|
3274
|
+
let Container = document.createElement("div"); document.querySelector("body > div").appendChild(Container);
|
3275
|
+
Container.className = "mt-3";
|
3276
|
+
Container.appendChild(SoftwareList);
|
3277
|
+
if (UtilityEnabled("NewDownload")) {
|
3278
|
+
let Softwares = [{
|
3279
|
+
"Name": "Bloodshed Dev-C++",
|
3280
|
+
"Image": "https://a.fsdn.com/allura/p/dev-cpp/icon",
|
3281
|
+
"URL": "https://sourceforge.net/projects/dev-cpp/"
|
3282
|
+
}, {
|
3283
|
+
"Name": "Orwell Dev-C++",
|
3284
|
+
"Image": "https://a.fsdn.com/allura/p/orwelldevcpp/icon",
|
3285
|
+
"URL": "https://sourceforge.net/projects/orwelldevcpp/"
|
3286
|
+
}, {
|
3287
|
+
"Name": "Embarcadero Dev-C++",
|
3288
|
+
"Image": "https://a.fsdn.com/allura/s/embarcadero-dev-cpp/icon",
|
3289
|
+
"URL": "https://sourceforge.net/software/product/Embarcadero-Dev-Cpp/"
|
3290
|
+
}, {
|
3291
|
+
"Name": "RedPanda C++",
|
3292
|
+
"Image": "https://a.fsdn.com/allura/p/redpanda-cpp/icon",
|
3293
|
+
"URL": "https://sourceforge.net/projects/redpanda-cpp/"
|
3294
|
+
}, {
|
3295
|
+
"Name": "CP Editor",
|
3296
|
+
"Image": "https://a.fsdn.com/allura/mirror/cp-editor/icon",
|
3297
|
+
"URL": "https://sourceforge.net/projects/cp-editor.mirror/"
|
3298
|
+
}, {
|
3299
|
+
"Name": "Code::Blocks",
|
3300
|
+
"Image": "https://a.fsdn.com/allura/p/codeblocks/icon",
|
3301
|
+
"URL": "https://sourceforge.net/projects/codeblocks/"
|
3302
|
+
}, {
|
3303
|
+
"Name": "Visual Studio Code",
|
3304
|
+
"Image": "https://code.visualstudio.com/favicon.ico",
|
3305
|
+
"URL": "https://code.visualstudio.com/Download"
|
3306
|
+
}, {
|
3307
|
+
"Name": "Lazarus",
|
3308
|
+
"Image": "https://a.fsdn.com/allura/p/lazarus/icon",
|
3309
|
+
"URL": "https://sourceforge.net/projects/lazarus/"
|
3310
|
+
}, {
|
3311
|
+
"Name": "Geany",
|
3312
|
+
"Image": "https://www.geany.org/static/img/geany.svg",
|
3313
|
+
"URL": "https://www.geany.org/download/releases/"
|
3314
|
+
}, {
|
3315
|
+
"Name": "NOI Linux",
|
3316
|
+
"Image": "https://www.noi.cn/upload/resources/image/2021/07/16/163780.jpg",
|
3317
|
+
"URL": "https://www.noi.cn/gynoi/jsgz/2021-07-16/732450.shtml"
|
3318
|
+
}, {
|
3319
|
+
"Name": "VirtualBox",
|
3320
|
+
"Image": "https://www.virtualbox.org/graphics/vbox_logo2_gradient.png",
|
3321
|
+
"URL": "https://www.virtualbox.org/wiki/Downloads"
|
3322
|
+
}, {
|
3323
|
+
"Name": "MinGW",
|
3324
|
+
"Image": "https://www.mingw-w64.org/logo.svg",
|
3325
|
+
"URL": "https://sourceforge.net/projects/mingw/"
|
3326
|
+
}];
|
3327
|
+
for (let i = 0; i < Softwares.length; i++) {
|
3328
|
+
SoftwareList.innerHTML +=
|
3329
|
+
"<li class=\"software_item\">" +
|
3330
|
+
"<a href=\"" + Softwares[i].URL + "\">" +
|
3331
|
+
"<div class=\"item-info\">" +
|
3332
|
+
"<div class=\"item-img\">" +
|
3333
|
+
"<img height=\"50\" src=\"" + Softwares[i].Image + "\" alt=\"点击下载\">" +
|
3334
|
+
"</div>" +
|
3335
|
+
"<div class=\"item-txt\">" + Softwares[i].Name + "</div>" +
|
3336
|
+
"</div>" +
|
3337
|
+
"</a>" +
|
3338
|
+
"</li>";
|
3339
|
+
}
|
3340
|
+
}
|
3341
|
+
} else if (location.pathname == "/problemstatus.php") {
|
3342
|
+
document.querySelector("body > div > div.mt-3 > center").insertBefore(document.querySelector("#statics"), document.querySelector("body > div > div.mt-3 > center > table"));
|
3343
|
+
document.querySelector("body > div > div.mt-3 > center").insertBefore(document.querySelector("#problemstatus"), document.querySelector("body > div > div.mt-3 > center > table"));
|
3344
|
+
|
3345
|
+
document.querySelector("body > div > div.mt-3 > center > table:nth-child(3)").remove();
|
3346
|
+
let Temp = document.querySelector("#statics").rows;
|
3347
|
+
for (let i = 0; i < Temp.length; i++) {
|
3348
|
+
Temp[i].removeAttribute("class");
|
3349
|
+
if (Temp[i].children.length == 2) {
|
3350
|
+
Temp[i].children[1].innerText = Temp[i].children[1].innerText;
|
3351
|
+
}
|
3352
|
+
}
|
3353
|
+
|
3354
|
+
document.querySelector("#problemstatus > thead > tr").innerHTML =
|
3355
|
+
document.querySelector("#problemstatus > thead > tr").innerHTML.replaceAll("td", "th");
|
3356
|
+
document.querySelector("#problemstatus > thead > tr > th:nth-child(2)").innerText = "运行编号";
|
3357
|
+
document.querySelector("#problemstatus > thead > tr > th:nth-child(4)").remove();
|
3358
|
+
document.querySelector("#problemstatus > thead > tr > th:nth-child(4)").remove();
|
3359
|
+
document.querySelector("#problemstatus > thead > tr > th:nth-child(4)").remove();
|
3360
|
+
document.querySelector("#problemstatus > thead > tr > th:nth-child(4)").remove();
|
3361
|
+
Temp = document.querySelector("#problemstatus > thead > tr").children;
|
3362
|
+
for (let i = 0; i < Temp.length; i++) {
|
3363
|
+
Temp[i].removeAttribute("class");
|
3364
|
+
}
|
3365
|
+
Temp = document.querySelector("#problemstatus > tbody").children;
|
3366
|
+
for (let i = 0; i < Temp.length; i++) {
|
3367
|
+
if (Temp[i].children[5].children[0] != null) {
|
3368
|
+
Temp[i].children[1].innerHTML = `<a href="${Temp[i].children[5].children[0].href}">${Temp[i].children[1].innerText.trim()}</a>`;
|
3369
|
+
}
|
3370
|
+
GetUsernameHTML(Temp[i].children[2], Temp[i].children[2].innerText);
|
3371
|
+
Temp[i].children[3].remove();
|
3372
|
+
Temp[i].children[3].remove();
|
3373
|
+
Temp[i].children[3].remove();
|
3374
|
+
Temp[i].children[3].remove();
|
3375
|
+
}
|
3376
|
+
|
3377
|
+
|
3378
|
+
let CurrentPage = parseInt(SearchParams.get("page") || 1);
|
3379
|
+
let PID = Number(SearchParams.get("id"));
|
3380
|
+
let Pagination = `<nav class="center"><ul class="pagination justify-content-center">`;
|
3381
|
+
if (CurrentPage != 1) {
|
3382
|
+
Pagination += `<li class="page-item"><a href="https://www.xmoj.tech/problemstatus.php?id=${PID + `&page=1" class="page-link">«</a></li><li class="page-item"><a href="https://www.xmoj.tech/problemstatus.php?id=` + PID + `&page=` + (CurrentPage - 1) + `" class="page-link">` + (CurrentPage - 1)}</a></li>`;
|
3383
|
+
}
|
3384
|
+
Pagination += `<li class="active page-item"><a href="https://www.xmoj.tech/problemstatus.php?id=${PID + `&page=` + CurrentPage + `" class="page-link">` + CurrentPage}</a></li>`;
|
3385
|
+
if (document.querySelector("#problemstatus > tbody").children != null && document.querySelector("#problemstatus > tbody").children.length == 20) {
|
3386
|
+
Pagination += `<li class="page-item"><a href="https://www.xmoj.tech/problemstatus.php?id=${PID + `&page=` + (CurrentPage + 1) + `" class="page-link">` + (CurrentPage + 1) + `</a></li><li class="page-item"><a href="https://www.xmoj.tech/problemstatus.php?id=` + PID + `&page=` + (CurrentPage + 1)}" class="page-link">»</a></li>`;
|
3387
|
+
}
|
3388
|
+
Pagination += `</ul></nav>`;
|
3389
|
+
document.querySelector("body > div > div.mt-3 > center").innerHTML += Pagination;
|
3390
|
+
} else if (location.pathname == "/problem_solution.php") {
|
3391
|
+
if (UtilityEnabled("CopyMD")) {
|
3392
|
+
await fetch(location.href).then((Response) => {
|
3393
|
+
return Response.text();
|
3394
|
+
}).then((Response) => {
|
3395
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
3396
|
+
let CopyMDButton = document.createElement("button");
|
3397
|
+
CopyMDButton.className = "btn btn-sm btn-outline-secondary copy-btn";
|
3398
|
+
CopyMDButton.innerText = "复制";
|
3399
|
+
CopyMDButton.style.marginLeft = "10px";
|
3400
|
+
CopyMDButton.type = "button";
|
3401
|
+
document.querySelector("body > div > div.mt-3 > center > h2").appendChild(CopyMDButton);
|
3402
|
+
CopyMDButton.addEventListener("click", () => {
|
3403
|
+
GM_setClipboard(ParsedDocument.querySelector("body > div > div > div").innerText.trim().replaceAll("\n\t", "\n").replaceAll("\n\n", "\n").replaceAll("\n\n", "\n"));
|
3404
|
+
CopyMDButton.innerText = "复制成功";
|
3405
|
+
setTimeout(() => {
|
3406
|
+
CopyMDButton.innerText = "复制";
|
3407
|
+
}, 1000);
|
3408
|
+
});
|
3409
|
+
});
|
3410
|
+
}
|
3411
|
+
let Temp = document.getElementsByClassName("prettyprint");
|
3412
|
+
for (let i = 0; i < Temp.length; i++) {
|
3413
|
+
let Code = Temp[i].innerText;
|
3414
|
+
Temp[i].outerHTML = `<textarea class="prettyprint"></textarea>`;
|
3415
|
+
Temp[i].value = Code;
|
3416
|
+
}
|
3417
|
+
for (let i = 0; i < Temp.length; i++) {
|
3418
|
+
CodeMirror.fromTextArea(Temp[i], {
|
3419
|
+
lineNumbers: true,
|
3420
|
+
mode: "text/x-c++src",
|
3421
|
+
readOnly: true,
|
3422
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default")
|
3423
|
+
}).setSize("100%", "auto");
|
3424
|
+
}
|
3425
|
+
} else if (location.pathname == "/open_contest.php") {
|
3426
|
+
let Temp = document.querySelector("body > div > div.mt-3 > div > div.col-md-8").children;
|
3427
|
+
let NewsData = [];
|
3428
|
+
for (let i = 0; i < Temp.length; i += 2) {
|
3429
|
+
let Title = Temp[i].children[0].innerText;
|
3430
|
+
let Time = 0;
|
3431
|
+
if (Temp[i].children[1] != null) {
|
3432
|
+
Time = Temp[i].children[1].innerText;
|
3433
|
+
}
|
3434
|
+
let Body = Temp[i + 1].innerHTML;
|
3435
|
+
NewsData.push({ "Title": Title, "Time": new Date(Time), "Body": Body });
|
3436
|
+
}
|
3437
|
+
document.querySelector("body > div > div.mt-3 > div > div.col-md-8").innerHTML = "";
|
3438
|
+
for (let i = 0; i < NewsData.length; i++) {
|
3439
|
+
let NewsRow = document.createElement("div");
|
3440
|
+
NewsRow.className = "cnt-row";
|
3441
|
+
let NewsRowHead = document.createElement("div");
|
3442
|
+
NewsRowHead.className = "cnt-row-head title";
|
3443
|
+
NewsRowHead.innerText = NewsData[i].Title;
|
3444
|
+
if (NewsData[i].Time.getTime() != 0) {
|
3445
|
+
NewsRowHead.innerHTML += "<small class=\"ms-3\">" + NewsData[i].Time.toLocaleDateString() + "</small>";
|
3446
|
+
}
|
3447
|
+
NewsRow.appendChild(NewsRowHead);
|
3448
|
+
let NewsRowBody = document.createElement("div");
|
3449
|
+
NewsRowBody.className = "cnt-row-body";
|
3450
|
+
NewsRowBody.innerHTML = NewsData[i].Body;
|
3451
|
+
NewsRow.appendChild(NewsRowBody);
|
3452
|
+
document.querySelector("body > div > div.mt-3 > div > div.col-md-8").appendChild(NewsRow);
|
3453
|
+
}
|
3454
|
+
let MyContestData = document.querySelector("body > div > div.mt-3 > div > div.col-md-4 > div:nth-child(2)").innerHTML;
|
3455
|
+
let CountDownData = document.querySelector("#countdown_list").innerHTML;
|
3456
|
+
document.querySelector("body > div > div.mt-3 > div > div.col-md-4").innerHTML = `<div class="cnt-row">
|
3457
|
+
<div class="cnt-row-head title">我的月赛</div>
|
3458
|
+
<div class="cnt-row-body">${MyContestData}</div>
|
3459
|
+
</div>
|
3460
|
+
<div class="cnt-row">
|
3461
|
+
<div class="cnt-row-head title">倒计时</div>
|
3462
|
+
<div class="cnt-row-body">${CountDownData}</div>
|
3463
|
+
</div>`;
|
3464
|
+
} else if (location.pathname == "/showsource.php") {
|
3465
|
+
let Code = "";
|
3466
|
+
if (SearchParams.get("ByUserScript") == null) {
|
3467
|
+
await fetch("https://www.xmoj.tech/getsource.php?id=" + SearchParams.get("id"))
|
3468
|
+
.then((Response) => {
|
3469
|
+
return Response.text();
|
3470
|
+
}).then((Response) => {
|
3471
|
+
Code = Response.substring(0, Response.indexOf("/**************************************************************")).trim();
|
3472
|
+
});
|
3473
|
+
}
|
3474
|
+
else {
|
3475
|
+
if (localStorage.getItem("UserScript-LastUploadedStdTime") === undefined ||
|
3476
|
+
new Date().getTime() - localStorage.getItem("UserScript-LastUploadedStdTime") > 1000 * 60 * 60 * 24 * 30) {
|
3477
|
+
location.href = "https://www.xmoj.tech/userinfo.php?ByUserScript=1";
|
3478
|
+
}
|
3479
|
+
await new Promise((Resolve) => {
|
3480
|
+
RequestAPI("GetStd", {
|
3481
|
+
"ProblemID": Number(SearchParams.get("pid"))
|
3482
|
+
}, (Response) => {
|
3483
|
+
if (Response.Success) {
|
3484
|
+
Code = Response.Data.StdCode;
|
3485
|
+
}
|
3486
|
+
else {
|
3487
|
+
Code = Response.Message;
|
3488
|
+
}
|
3489
|
+
Resolve();
|
3490
|
+
});
|
3491
|
+
});
|
3492
|
+
}
|
3493
|
+
document.querySelector("body > div > div.mt-3").innerHTML = `<textarea>${Code}</textarea>`;
|
3494
|
+
CodeMirror.fromTextArea(document.querySelector("body > div > div.mt-3 > textarea"), {
|
3495
|
+
lineNumbers: true,
|
3496
|
+
mode: "text/x-c++src",
|
3497
|
+
readOnly: true,
|
3498
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default")
|
3499
|
+
}).setSize("100%", "auto");
|
3500
|
+
} else if (location.pathname == "/ceinfo.php") {
|
3501
|
+
await fetch(location.href)
|
3502
|
+
.then((Result) => {
|
3503
|
+
return Result.text();
|
3504
|
+
}).then((Result) => {
|
3505
|
+
let ParsedDocument = new DOMParser().parseFromString(Result, "text/html");
|
3506
|
+
document.querySelector("body > div > div.mt-3").innerHTML = "";
|
3507
|
+
let CodeElement = document.createElement("div");
|
3508
|
+
CodeElement.className = "mb-3";
|
3509
|
+
document.querySelector("body > div > div.mt-3").appendChild(CodeElement);
|
3510
|
+
CodeMirror(CodeElement, {
|
3511
|
+
value: ParsedDocument.getElementById("errtxt").innerHTML.replaceAll("<", "<").replaceAll(">", ">"),
|
3512
|
+
lineNumbers: true,
|
3513
|
+
mode: "text/x-c++src",
|
3514
|
+
readOnly: true,
|
3515
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default")
|
3516
|
+
}).setSize("100%", "auto");
|
3517
|
+
});
|
3518
|
+
} else if (location.pathname == "/problem_std.php") {
|
3519
|
+
await fetch("https://www.xmoj.tech/problem_std.php?cid=" + SearchParams.get("cid") + "&pid=" + SearchParams.get("pid"))
|
3520
|
+
.then((Response) => {
|
3521
|
+
return Response.text();
|
3522
|
+
}).then((Response) => {
|
3523
|
+
let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
|
3524
|
+
let Temp = ParsedDocument.getElementsByTagName("pre");
|
3525
|
+
document.querySelector("body > div > div.mt-3").innerHTML = "";
|
3526
|
+
for (let i = 0; i < Temp.length; i++) {
|
3527
|
+
let CodeElement = document.createElement("div");
|
3528
|
+
CodeElement.className = "mb-3";
|
3529
|
+
document.querySelector("body > div > div.mt-3").appendChild(CodeElement);
|
3530
|
+
CodeMirror(CodeElement, {
|
3531
|
+
value: Temp[i].innerText,
|
3532
|
+
lineNumbers: true,
|
3533
|
+
mode: "text/x-c++src",
|
3534
|
+
readOnly: true,
|
3535
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default")
|
3536
|
+
}).setSize("100%", "auto");
|
3537
|
+
}
|
3538
|
+
});
|
3539
|
+
} else if (location.pathname == "/mail.php") {
|
3540
|
+
if (SearchParams.get("other") == null) {
|
3541
|
+
document.querySelector("body > div > div.mt-3").innerHTML = `<div class="row g-2 align-items-center">
|
3542
|
+
<div class="col-auto form-floating">
|
3543
|
+
<input class="form-control" id="Username" placeholder=" " spellcheck="false" data-ms-editor="true">
|
3544
|
+
<label for="Username">搜索新用户</label>
|
3545
|
+
</div>
|
3546
|
+
<div class="col-auto form-floating">
|
3547
|
+
<button class="btn btn-outline-secondary" id="AddUser">
|
3548
|
+
添加
|
3549
|
+
<div class="spinner-border spinner-border-sm" role="status" style="display: none;">
|
3550
|
+
</button>
|
3551
|
+
</div>
|
3552
|
+
</div>
|
3553
|
+
<table class="table mb-3" id="ReceiveTable">
|
3554
|
+
<thead>
|
3555
|
+
<tr>
|
3556
|
+
<td class="col-3">接收者</td>
|
3557
|
+
<td class="col-7">最新消息</td>
|
3558
|
+
<td class="col-2">最后联系时间</td>
|
3559
|
+
</tr>
|
3560
|
+
</thead>
|
3561
|
+
<tbody></tbody>
|
3562
|
+
</table>
|
3563
|
+
<div class="alert alert-danger mb-3" role="alert" id="ErrorElement" style="display: none;"></div>`;
|
3564
|
+
let RefreshMessageList = (Silent = true) => {
|
3565
|
+
if (!Silent) {
|
3566
|
+
ReceiveTable.children[1].innerHTML = "";
|
3567
|
+
for (let i = 0; i < 10; i++) {
|
3568
|
+
let Row = document.createElement("tr"); ReceiveTable.children[1].appendChild(Row);
|
3569
|
+
for (let j = 0; j < 3; j++) {
|
3570
|
+
let Cell = document.createElement("td"); Row.appendChild(Cell);
|
3571
|
+
Cell.innerHTML = `<span class="placeholder col-${Math.ceil(Math.random() * 12)}"></span>`;
|
3572
|
+
}
|
3573
|
+
}
|
3574
|
+
}
|
3575
|
+
RequestAPI("GetMailList", {}, async (ResponseData) => {
|
3576
|
+
if (ResponseData.Success) {
|
3577
|
+
ErrorElement.style.display = "none";
|
3578
|
+
let Data = ResponseData.Data.MailList;
|
3579
|
+
ReceiveTable.children[1].innerHTML = "";
|
3580
|
+
for (let i = 0; i < Data.length; i++) {
|
3581
|
+
let Row = document.createElement("tr"); ReceiveTable.children[1].appendChild(Row);
|
3582
|
+
let UsernameCell = document.createElement("td"); Row.appendChild(UsernameCell);
|
3583
|
+
let UsernameSpan = document.createElement("span"); UsernameCell.appendChild(UsernameSpan);
|
3584
|
+
GetUsernameHTML(UsernameSpan, Data[i].OtherUser, false, "https://www.xmoj.tech/mail.php?other=");
|
3585
|
+
if (Data[i].UnreadCount != 0) {
|
3586
|
+
let UnreadCountSpan = document.createElement("span"); UsernameCell.appendChild(UnreadCountSpan);
|
3587
|
+
UnreadCountSpan.className = "ms-1 badge text-bg-danger";
|
3588
|
+
UnreadCountSpan.innerText = Data[i].UnreadCount;
|
3589
|
+
}
|
3590
|
+
let LastsMessageCell = document.createElement("td"); Row.appendChild(LastsMessageCell);
|
3591
|
+
LastsMessageCell.innerText = Data[i].LastsMessage;
|
3592
|
+
let SendTimeCell = document.createElement("td"); Row.appendChild(SendTimeCell);
|
3593
|
+
SendTimeCell.innerHTML = GetRelativeTime(Data[i].SendTime);
|
3594
|
+
}
|
3595
|
+
}
|
3596
|
+
else {
|
3597
|
+
ErrorElement.innerText = ResponseData.Message;
|
3598
|
+
ErrorElement.style.display = "";
|
3599
|
+
}
|
3600
|
+
});
|
3601
|
+
};
|
3602
|
+
Username.addEventListener("input", () => {
|
3603
|
+
Username.classList.remove("is-invalid");
|
3604
|
+
});
|
3605
|
+
AddUser.addEventListener("click", () => {
|
3606
|
+
let UsernameData = Username.value;
|
3607
|
+
if (UsernameData == "") {
|
3608
|
+
Username.classList.add("is-invalid");
|
3609
|
+
return;
|
3610
|
+
}
|
3611
|
+
AddUser.children[0].style.display = "";
|
3612
|
+
AddUser.disabled = true;
|
3613
|
+
RequestAPI("SendMail", {
|
3614
|
+
"ToUser": String(UsernameData),
|
3615
|
+
"Content": String("您好,我是" + localStorage.getItem("UserScript-Username"))
|
3616
|
+
}, (ResponseData) => {
|
3617
|
+
AddUser.children[0].style.display = "none";
|
3618
|
+
AddUser.disabled = false;
|
3619
|
+
if (ResponseData.Success) {
|
3620
|
+
ErrorElement.style.display = "none";
|
3621
|
+
RefreshMessageList();
|
3622
|
+
}
|
3623
|
+
else {
|
3624
|
+
ErrorElement.innerText = ResponseData.Message;
|
3625
|
+
ErrorElement.style.display = "";
|
3626
|
+
}
|
3627
|
+
});
|
3628
|
+
});
|
3629
|
+
RefreshMessageList(false);
|
3630
|
+
addEventListener("focus", RefreshMessageList);
|
3631
|
+
}
|
3632
|
+
else {
|
3633
|
+
document.querySelector("body > div > div.mt-3").innerHTML = `<div class="row g-2 mb-3">
|
3634
|
+
<div class="col-md form-floating">
|
3635
|
+
<div class="form-control" id="ToUser"></div>
|
3636
|
+
<label for="ToUser">接收用户</label>
|
3637
|
+
</div>
|
3638
|
+
<div class="col-md form-floating">
|
3639
|
+
<input class="form-control" id="Content" placeholder=" ">
|
3640
|
+
<label for="Content">内容</label>
|
3641
|
+
</div>
|
3642
|
+
</div>
|
3643
|
+
<button id="Send" type="submit" class="btn btn-primary mb-1">
|
3644
|
+
发送
|
3645
|
+
<div class="spinner-border spinner-border-sm" role="status" style="display: none;">
|
3646
|
+
</button>
|
3647
|
+
<div id="ErrorElement" class="alert alert-danger mb-3" role="alert" style="display: none;"></div>
|
3648
|
+
<table class="table mb-3" id="MessageTable">
|
3649
|
+
<thead>
|
3650
|
+
<tr>
|
3651
|
+
<td class="col-3">发送者</td>
|
3652
|
+
<td class="col-7">内容</td>
|
3653
|
+
<td class="col-1">发送时间</td>
|
3654
|
+
<td class="col-1">阅读状态</td>
|
3655
|
+
</tr>
|
3656
|
+
</thead>
|
3657
|
+
<tbody></tbody>
|
3658
|
+
</table>`;
|
3659
|
+
GetUsernameHTML(ToUser, SearchParams.get("other"));
|
3660
|
+
let RefreshMessage = (Silent = true) => {
|
3661
|
+
if (!Silent) {
|
3662
|
+
MessageTable.children[1].innerHTML = "";
|
3663
|
+
for (let i = 0; i < 10; i++) {
|
3664
|
+
let Row = document.createElement("tr"); MessageTable.children[1].appendChild(Row);
|
3665
|
+
for (let j = 0; j < 4; j++) {
|
3666
|
+
let Cell = document.createElement("td"); Row.appendChild(Cell);
|
3667
|
+
Cell.innerHTML = `<span class="placeholder col-${Math.ceil(Math.random() * 12)}"></span>`;
|
3668
|
+
}
|
3669
|
+
}
|
3670
|
+
}
|
3671
|
+
RequestAPI("GetMail", {
|
3672
|
+
"OtherUser": String(SearchParams.get("other"))
|
3673
|
+
}, async (ResponseData) => {
|
3674
|
+
if (ResponseData.Success) {
|
3675
|
+
ErrorElement.style.display = "none";
|
3676
|
+
let Data = ResponseData.Data.Mail;
|
3677
|
+
MessageTable.children[1].innerHTML = "";
|
3678
|
+
for (let i = 0; i < Data.length; i++) {
|
3679
|
+
let Row = document.createElement("tr"); MessageTable.children[1].appendChild(Row);
|
3680
|
+
if (!Data[i].IsRead && Data[i].FromUser != CurrentUsername) {
|
3681
|
+
Row.className = "table-info";
|
3682
|
+
}
|
3683
|
+
let UsernameCell = document.createElement("td"); Row.appendChild(UsernameCell);
|
3684
|
+
GetUsernameHTML(UsernameCell, Data[i].FromUser);
|
3685
|
+
let ContentCell = document.createElement("td"); Row.appendChild(ContentCell);
|
3686
|
+
ContentCell.innerHTML = PurifyHTML(Data[i].Content);
|
3687
|
+
let SendTimeCell = document.createElement("td"); Row.appendChild(SendTimeCell);
|
3688
|
+
SendTimeCell.innerHTML = GetRelativeTime(Data[i].SendTime);
|
3689
|
+
let IsReadCell = document.createElement("td"); Row.appendChild(IsReadCell);
|
3690
|
+
IsReadCell.innerHTML = (Data[i].IsRead ? "已读" : "未读");
|
3691
|
+
}
|
3692
|
+
}
|
3693
|
+
else {
|
3694
|
+
ErrorElement.innerText = ResponseData.Message;
|
3695
|
+
ErrorElement.style.display = "";
|
3696
|
+
}
|
3697
|
+
});
|
3698
|
+
};
|
3699
|
+
Content.addEventListener("input", () => {
|
3700
|
+
Content.classList.remove("is-invalid");
|
3701
|
+
});
|
3702
|
+
Content.addEventListener("keydown", (Event) => {
|
3703
|
+
if (Event.keyCode == 13) {
|
3704
|
+
Send.click();
|
3705
|
+
}
|
3706
|
+
});
|
3707
|
+
Send.addEventListener("click", () => {
|
3708
|
+
if (Content.value == "") {
|
3709
|
+
Content.classList.add("is-invalid");
|
3710
|
+
return;
|
3711
|
+
}
|
3712
|
+
Send.disabled = true;
|
3713
|
+
Send.children[0].style.display = "";
|
3714
|
+
let ContentData = Content.value;
|
3715
|
+
RequestAPI("SendMail", {
|
3716
|
+
"ToUser": String(SearchParams.get("other")),
|
3717
|
+
"Content": String(ContentData)
|
3718
|
+
}, (ResponseData) => {
|
3719
|
+
Send.disabled = false;
|
3720
|
+
Send.children[0].style.display = "none";
|
3721
|
+
if (ResponseData.Success) {
|
3722
|
+
ErrorElement.style.display = "none";
|
3723
|
+
Content.value = "";
|
3724
|
+
RefreshMessage();
|
3725
|
+
}
|
3726
|
+
else {
|
3727
|
+
ErrorElement.innerText = ResponseData.Message;
|
3728
|
+
ErrorElement.style.display = "";
|
3729
|
+
}
|
3730
|
+
});
|
3731
|
+
});
|
3732
|
+
RefreshMessage(false);
|
3733
|
+
addEventListener("focus", RefreshMessage);
|
3734
|
+
}
|
3735
|
+
} else if (location.pathname.indexOf("/discuss3") != -1) {
|
3736
|
+
if (UtilityEnabled("Discussion")) {
|
3737
|
+
Discussion.classList.add("active");
|
3738
|
+
if (location.pathname == "/discuss3/discuss.php") {
|
3739
|
+
let ProblemID = parseInt(SearchParams.get("pid"));
|
3740
|
+
let Page = Number(SearchParams.get("page")) || 1;
|
3741
|
+
document.querySelector("body > div > div").innerHTML = `<h3>讨论列表${(isNaN(ProblemID) ? "" : ` - 题目` + ProblemID)}</h3>
|
3742
|
+
<button id="NewPost" type="button" class="btn btn-primary">发布新讨论</button>
|
3743
|
+
<nav>
|
3744
|
+
<ul class="pagination justify-content-center" id="DiscussPagination">
|
3745
|
+
<li class="page-item"><a class="page-link" href="#"><span>«</span></a></li>
|
3746
|
+
<li class="page-item"><a class="page-link" href="#">${Page - 1}</a></li>
|
3747
|
+
<li class="page-item"><a class="page-link active" href="#">${Page}</a></li>
|
3748
|
+
<li class="page-item"><a class="page-link" href="#">${Page + 1}</a></li>
|
3749
|
+
<li class="page-item"><a class="page-link" href="#"><span>»</span></a></li>
|
3750
|
+
</ul>
|
3751
|
+
</nav>
|
3752
|
+
<div id="GotoBoard"></div>
|
3753
|
+
<div id="ErrorElement" class="alert alert-danger" role="alert" style="display: none;"></div>
|
3754
|
+
<table id="PostList" class="table table-hover">
|
3755
|
+
<thead>
|
3756
|
+
<tr>
|
3757
|
+
<th class="col-1">编号</th>
|
3758
|
+
<th class="col-3">标题</th>
|
3759
|
+
<th class="col-3">作者</th>
|
3760
|
+
<th class="col-1">题目编号</th>
|
3761
|
+
<th class="col-1">发布时间</th>
|
3762
|
+
<th class="col-1">回复数</th>
|
3763
|
+
<th class="col-1">最后回复</th>
|
3764
|
+
</tr>
|
3765
|
+
</thead>
|
3766
|
+
<tbody>
|
3767
|
+
</tbody>
|
3768
|
+
</table>`;
|
3769
|
+
NewPost.addEventListener("click", () => {
|
3770
|
+
if (!isNaN(ProblemID)) {
|
3771
|
+
location.href = "https://www.xmoj.tech/discuss3/newpost.php?pid=" + ProblemID;
|
3772
|
+
}
|
3773
|
+
else if (SearchParams.get("bid") != null) {
|
3774
|
+
location.href = "https://www.xmoj.tech/discuss3/newpost.php?bid=" + SearchParams.get("bid");
|
3775
|
+
}
|
3776
|
+
else {
|
3777
|
+
location.href = "https://www.xmoj.tech/discuss3/newpost.php";
|
3778
|
+
}
|
3779
|
+
});
|
3780
|
+
const RefreshPostList = (Silent = true) => {
|
3781
|
+
if (!Silent) {
|
3782
|
+
PostList.children[1].innerHTML = "";
|
3783
|
+
for (let i = 0; i < 10; i++) {
|
3784
|
+
let Row = document.createElement("tr"); PostList.children[1].appendChild(Row);
|
3785
|
+
for (let j = 0; j < 7; j++) {
|
3786
|
+
let Cell = document.createElement("td"); Row.appendChild(Cell);
|
3787
|
+
Cell.innerHTML = `<span class="placeholder col-${Math.ceil(Math.random() * 12)}"></span>`;
|
3788
|
+
}
|
3789
|
+
}
|
3790
|
+
}
|
3791
|
+
RequestAPI("GetPosts", {
|
3792
|
+
"ProblemID": Number(ProblemID || 0),
|
3793
|
+
"Page": Number(Page),
|
3794
|
+
"BoardID": Number(SearchParams.get("bid") || -1)
|
3795
|
+
}, async (ResponseData) => {
|
3796
|
+
if (ResponseData.Success == true) {
|
3797
|
+
ErrorElement.style.display = "none";
|
3798
|
+
if (!Silent) {
|
3799
|
+
DiscussPagination.children[0].children[0].href = "https://www.xmoj.tech/discuss3/discuss.php?" + (isNaN(ProblemID) ? "" : "pid=" + ProblemID + "&") + "page=1";
|
3800
|
+
DiscussPagination.children[1].children[0].href = "https://www.xmoj.tech/discuss3/discuss.php?" + (isNaN(ProblemID) ? "" : "pid=" + ProblemID + "&") + "page=" + (Page - 1);
|
3801
|
+
DiscussPagination.children[2].children[0].href = "https://www.xmoj.tech/discuss3/discuss.php?" + (isNaN(ProblemID) ? "" : "pid=" + ProblemID + "&") + "page=" + Page;
|
3802
|
+
DiscussPagination.children[3].children[0].href = "https://www.xmoj.tech/discuss3/discuss.php?" + (isNaN(ProblemID) ? "" : "pid=" + ProblemID + "&") + "page=" + (Page + 1);
|
3803
|
+
DiscussPagination.children[4].children[0].href = "https://www.xmoj.tech/discuss3/discuss.php?" + (isNaN(ProblemID) ? "" : "pid=" + ProblemID + "&") + "page=" + ResponseData.Data.PageCount;
|
3804
|
+
if (Page <= 1) {
|
3805
|
+
DiscussPagination.children[0].classList.add("disabled");
|
3806
|
+
DiscussPagination.children[1].remove();
|
3807
|
+
}
|
3808
|
+
if (Page >= ResponseData.Data.PageCount) {
|
3809
|
+
DiscussPagination.children[DiscussPagination.children.length - 1].classList.add("disabled");
|
3810
|
+
DiscussPagination.children[DiscussPagination.children.length - 2].remove();
|
3811
|
+
}
|
3812
|
+
}
|
3813
|
+
let Posts = ResponseData.Data.Posts;
|
3814
|
+
PostList.children[1].innerHTML = "";
|
3815
|
+
if (Posts.length == 0) {
|
3816
|
+
PostList.children[1].innerHTML = `<tr><td colspan="7">暂无数据</td></tr>`;
|
3817
|
+
}
|
3818
|
+
for (let i = 0; i < Posts.length; i++) {
|
3819
|
+
let Row = document.createElement("tr"); PostList.children[1].appendChild(Row);
|
3820
|
+
let IDCell = document.createElement("td"); Row.appendChild(IDCell);
|
3821
|
+
IDCell.innerText = Posts[i].PostID + " " + Posts[i].BoardName;
|
3822
|
+
let TitleCell = document.createElement("td"); Row.appendChild(TitleCell);
|
3823
|
+
let TitleLink = document.createElement("a"); TitleCell.appendChild(TitleLink);
|
3824
|
+
TitleLink.href = "https://www.xmoj.tech/discuss3/thread.php?tid=" + Posts[i].PostID;
|
3825
|
+
if (Posts[i].Lock.Locked) {
|
3826
|
+
TitleLink.classList.add("link-secondary");
|
3827
|
+
TitleLink.innerHTML = "🔒 ";
|
3828
|
+
}
|
3829
|
+
TitleLink.innerHTML += Posts[i].Title;
|
3830
|
+
let AuthorCell = document.createElement("td"); Row.appendChild(AuthorCell);
|
3831
|
+
GetUsernameHTML(AuthorCell, Posts[i].UserID);
|
3832
|
+
let ProblemIDCell = document.createElement("td"); Row.appendChild(ProblemIDCell);
|
3833
|
+
if (Posts[i].ProblemID != 0) {
|
3834
|
+
let ProblemIDLink = document.createElement("a"); ProblemIDCell.appendChild(ProblemIDLink);
|
3835
|
+
ProblemIDLink.href = "https://www.xmoj.tech/problem.php?id=" + Posts[i].ProblemID;
|
3836
|
+
ProblemIDLink.innerText = Posts[i].ProblemID;
|
3837
|
+
}
|
3838
|
+
let PostTimeCell = document.createElement("td"); Row.appendChild(PostTimeCell);
|
3839
|
+
PostTimeCell.innerHTML = GetRelativeTime(Posts[i].PostTime);
|
3840
|
+
let ReplyCountCell = document.createElement("td"); Row.appendChild(ReplyCountCell);
|
3841
|
+
ReplyCountCell.innerText = Posts[i].ReplyCount;
|
3842
|
+
let LastReplyTimeCell = document.createElement("td"); Row.appendChild(LastReplyTimeCell);
|
3843
|
+
LastReplyTimeCell.innerHTML = GetRelativeTime(Posts[i].LastReplyTime);
|
3844
|
+
}
|
3845
|
+
}
|
3846
|
+
else {
|
3847
|
+
ErrorElement.innerText = ResponseData.Message;
|
3848
|
+
ErrorElement.style.display = "block";
|
3849
|
+
}
|
3850
|
+
});
|
3851
|
+
};
|
3852
|
+
RefreshPostList(false);
|
3853
|
+
addEventListener("focus", RefreshPostList);
|
3854
|
+
RequestAPI("GetBoards", {}, (ResponseData) => {
|
3855
|
+
if (ResponseData.Success === true) {
|
3856
|
+
let LinkElement = document.createElement("a");
|
3857
|
+
LinkElement.href = "https://www.xmoj.tech/discuss3/discuss.php";
|
3858
|
+
LinkElement.classList.add("me-2");
|
3859
|
+
LinkElement.innerText = "全部";
|
3860
|
+
GotoBoard.appendChild(LinkElement);
|
3861
|
+
for (let i = 0; i < ResponseData.Data.Boards.length; i++) {
|
3862
|
+
let LinkElement = document.createElement("a");
|
3863
|
+
LinkElement.href = "https://www.xmoj.tech/discuss3/discuss.php?bid=" + ResponseData.Data.Boards[i].BoardID;
|
3864
|
+
LinkElement.classList.add("me-2");
|
3865
|
+
LinkElement.innerText = ResponseData.Data.Boards[i].BoardName;
|
3866
|
+
GotoBoard.appendChild(LinkElement);
|
3867
|
+
}
|
3868
|
+
}
|
3869
|
+
});
|
3870
|
+
} else if (location.pathname == "/discuss3/newpost.php") {
|
3871
|
+
let ProblemID = parseInt(SearchParams.get("pid"));
|
3872
|
+
document.querySelector("body > div > div").innerHTML = `<h3>发布新讨论` + (!isNaN(ProblemID) ? ` - 题目` + ProblemID : ``) + `</h3>
|
3873
|
+
<div class="form-group mb-3" id="BoardSelect">
|
3874
|
+
<label for="Board" class="mb-1">请选择要发布的板块</label>
|
3875
|
+
<div class="row ps-3" id="Board">
|
3876
|
+
</div>
|
3877
|
+
</div>
|
3878
|
+
<div class="form-group mb-3">
|
3879
|
+
<label for="Title" class="mb-1">标题</label>
|
3880
|
+
<input type="text" class="form-control" id="TitleElement" placeholder="请输入标题">
|
3881
|
+
</div>
|
3882
|
+
<div>
|
3883
|
+
<label for="ContentElement" class="mb-1">回复</label>
|
3884
|
+
<div class="input-group">
|
3885
|
+
<textarea class="col-6 form-control" id="ContentElement" rows="3" placeholder="请输入内容"></textarea>
|
3886
|
+
<div class="col-6 form-control" id="PreviewTab"></div>
|
3887
|
+
</div>
|
3888
|
+
<div class="cf-turnstile mt-2" id="CaptchaContainer"></div>
|
3889
|
+
<button id="SubmitElement" type="button" class="btn btn-primary mb-2" disabled>
|
3890
|
+
发布
|
3891
|
+
<div class="spinner-border spinner-border-sm" role="status" style="display: none;">
|
3892
|
+
</button>
|
3893
|
+
</div>
|
3894
|
+
<div id="ErrorElement" class="alert alert-danger" role="alert" style="display: none;"></div>`;
|
3895
|
+
let CaptchaSecretKey = "";
|
3896
|
+
unsafeWindow.CaptchaLoadedCallback = () => {
|
3897
|
+
turnstile.render("#CaptchaContainer", {
|
3898
|
+
sitekey: CaptchaSiteKey,
|
3899
|
+
callback: function (CaptchaSecretKeyValue) {
|
3900
|
+
CaptchaSecretKey = CaptchaSecretKeyValue;
|
3901
|
+
SubmitElement.disabled = false;
|
3902
|
+
},
|
3903
|
+
});
|
3904
|
+
};
|
3905
|
+
let TurnstileScript = document.createElement("script");
|
3906
|
+
TurnstileScript.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=CaptchaLoadedCallback";
|
3907
|
+
document.body.appendChild(TurnstileScript);
|
3908
|
+
ContentElement.addEventListener("keydown", (Event) => {
|
3909
|
+
if (Event.ctrlKey && Event.keyCode == 13) {
|
3910
|
+
SubmitElement.click();
|
3911
|
+
}
|
3912
|
+
});
|
3913
|
+
ContentElement.addEventListener("input", () => {
|
3914
|
+
ContentElement.classList.remove("is-invalid");
|
3915
|
+
PreviewTab.innerHTML = PurifyHTML(marked.parse(ContentElement.value));
|
3916
|
+
RenderMathJax();
|
3917
|
+
});
|
3918
|
+
TitleElement.addEventListener("input", () => {
|
3919
|
+
TitleElement.classList.remove("is-invalid");
|
3920
|
+
});
|
3921
|
+
ContentElement.addEventListener("paste", (EventData) => {
|
3922
|
+
let Items = EventData.clipboardData.items;
|
3923
|
+
if (Items.length !== 0) {
|
3924
|
+
for (let i = 0; i < Items.length; i++) {
|
3925
|
+
if (Items[i].type.indexOf("image") != -1) {
|
3926
|
+
let Reader = new FileReader();
|
3927
|
+
Reader.readAsDataURL(Items[i].getAsFile());
|
3928
|
+
Reader.onload = () => {
|
3929
|
+
let Before = ContentElement.value.substring(0, ContentElement.selectionStart);
|
3930
|
+
let After = ContentElement.value.substring(ContentElement.selectionEnd, ContentElement.value.length);
|
3931
|
+
const UploadMessage = "![正在上传图片...]()";
|
3932
|
+
ContentElement.value = Before + UploadMessage + After;
|
3933
|
+
ContentElement.dispatchEvent(new Event("input"));
|
3934
|
+
RequestAPI("UploadImage", {
|
3935
|
+
"Image": Reader.result
|
3936
|
+
}, (ResponseData) => {
|
3937
|
+
if (ResponseData.Success) {
|
3938
|
+
ContentElement.value = Before + `` + After;
|
3939
|
+
ContentElement.dispatchEvent(new Event("input"));
|
3940
|
+
}
|
3941
|
+
else {
|
3942
|
+
ContentElement.value = Before + `![上传失败!]()` + After;
|
3943
|
+
ContentElement.dispatchEvent(new Event("input"));
|
3944
|
+
}
|
3945
|
+
});
|
3946
|
+
};
|
3947
|
+
}
|
3948
|
+
}
|
3949
|
+
}
|
3950
|
+
});
|
3951
|
+
SubmitElement.addEventListener("click", async () => {
|
3952
|
+
ErrorElement.style.display = "none";
|
3953
|
+
let Title = TitleElement.value;
|
3954
|
+
let Content = ContentElement.value;
|
3955
|
+
let ProblemID = parseInt(SearchParams.get("pid"));
|
3956
|
+
if (Title === "") {
|
3957
|
+
TitleElement.classList.add("is-invalid");
|
3958
|
+
return;
|
3959
|
+
}
|
3960
|
+
if (Content === "") {
|
3961
|
+
ContentElement.classList.add("is-invalid");
|
3962
|
+
return;
|
3963
|
+
}
|
3964
|
+
if (document.querySelector("#Board input:checked") === null) {
|
3965
|
+
ErrorElement.innerText = "请选择要发布的板块";
|
3966
|
+
ErrorElement.style.display = "block";
|
3967
|
+
return;
|
3968
|
+
}
|
3969
|
+
SubmitElement.disabled = true;
|
3970
|
+
SubmitElement.children[0].style.display = "inline-block";
|
3971
|
+
RequestAPI("NewPost", {
|
3972
|
+
"Title": String(Title),
|
3973
|
+
"Content": String(Content),
|
3974
|
+
"ProblemID": Number(isNaN(ProblemID) ? 0 : ProblemID),
|
3975
|
+
"CaptchaSecretKey": String(CaptchaSecretKey),
|
3976
|
+
"BoardID": Number(document.querySelector("#Board input:checked").value)
|
3977
|
+
}, (ResponseData) => {
|
3978
|
+
SubmitElement.disabled = false;
|
3979
|
+
SubmitElement.children[0].style.display = "none";
|
3980
|
+
if (ResponseData.Success == true) {
|
3981
|
+
location.href = "https://www.xmoj.tech/discuss3/thread.php?tid=" + ResponseData.Data.PostID;
|
3982
|
+
}
|
3983
|
+
else {
|
3984
|
+
ErrorElement.innerText = ResponseData.Message;
|
3985
|
+
ErrorElement.style.display = "block";
|
3986
|
+
}
|
3987
|
+
});
|
3988
|
+
});
|
3989
|
+
RequestAPI("GetBoards", {}, (ResponseData) => {
|
3990
|
+
if (ResponseData.Success === true) {
|
3991
|
+
let Data = ResponseData.Data.Boards;
|
3992
|
+
for (let i = 0; i < Data.length; i++) {
|
3993
|
+
let RadioElement = document.createElement("div");
|
3994
|
+
RadioElement.className = "col-auto form-check form-check-inline";
|
3995
|
+
let RadioInput = document.createElement("input");
|
3996
|
+
RadioInput.className = "form-check-input";
|
3997
|
+
RadioInput.type = "radio";
|
3998
|
+
RadioInput.name = "Board";
|
3999
|
+
RadioInput.id = "Board" + Data[i].BoardID;
|
4000
|
+
RadioInput.value = Data[i].BoardID;
|
4001
|
+
RadioElement.appendChild(RadioInput);
|
4002
|
+
if (SearchParams.get("bid") !== null && SearchParams.get("bid") == Data[i].BoardID) {
|
4003
|
+
RadioInput.checked = true;
|
4004
|
+
}
|
4005
|
+
if (!isNaN(ProblemID)) {
|
4006
|
+
RadioInput.disabled = true;
|
4007
|
+
}
|
4008
|
+
if (Data[i].BoardID == 4) {
|
4009
|
+
if (!isNaN(ProblemID))
|
4010
|
+
RadioInput.checked = true;
|
4011
|
+
RadioInput.disabled = true;
|
4012
|
+
}
|
4013
|
+
let RadioLabel = document.createElement("label");
|
4014
|
+
RadioLabel.className = "form-check-label";
|
4015
|
+
RadioLabel.htmlFor = "Board" + Data[i].BoardID;
|
4016
|
+
RadioLabel.innerText = Data[i].BoardName;
|
4017
|
+
RadioElement.appendChild(RadioLabel);
|
4018
|
+
Board.appendChild(RadioElement);
|
4019
|
+
}
|
4020
|
+
}
|
4021
|
+
});
|
4022
|
+
} else if (location.pathname == "/discuss3/thread.php") {
|
4023
|
+
if (SearchParams.get("tid") == null) {
|
4024
|
+
location.href = "https://www.xmoj.tech/discuss3/discuss.php";
|
4025
|
+
}
|
4026
|
+
else {
|
4027
|
+
let ThreadID = SearchParams.get("tid");
|
4028
|
+
let Page = Number(SearchParams.get("page")) || 1;
|
4029
|
+
document.querySelector("body > div > div").innerHTML = `<h3 id="PostTitle"></h3>
|
4030
|
+
<div class="row mb-3">
|
4031
|
+
<span class="col-5 text-muted">作者:<div style="display: inline-block;" id="PostAuthor"></div></span>
|
4032
|
+
<span class="col-3 text-muted">发布时间:<span id="PostTime"></span></span>
|
4033
|
+
<span class="col-2 text-muted">板块:<span id="PostBoard"></span></span>
|
4034
|
+
<span class="col-2">
|
4035
|
+
<button id="Delete" type="button" class="btn btn-sm btn-danger" style="display: none;">
|
4036
|
+
删除
|
4037
|
+
<div class="spinner-border spinner-border-sm" role="status" style="display: none;">
|
4038
|
+
</button>
|
4039
|
+
</span>
|
4040
|
+
</div>
|
4041
|
+
<div id="PostReplies"></div>
|
4042
|
+
<nav>
|
4043
|
+
<ul class="pagination justify-content-center" id="DiscussPagination">
|
4044
|
+
<li class="page-item"><a class="page-link" href="#"><span>«</span></a></li>
|
4045
|
+
<li class="page-item"><a class="page-link" href="#">${(Page - 1)}</a></li>
|
4046
|
+
<li class="page-item"><a class="page-link active" href="#">${Page}</a></li>
|
4047
|
+
<li class="page-item"><a class="page-link" href="#">${(Page + 1)}</a></li>
|
4048
|
+
<li class="page-item"><a class="page-link" href="#"><span>»</span></a></li>
|
4049
|
+
</ul>
|
4050
|
+
</nav>
|
4051
|
+
<div>
|
4052
|
+
<div class="container p-0 m-0">
|
4053
|
+
<div class="row">
|
4054
|
+
<div class="col">
|
4055
|
+
<label for="ContentElement" class="mb-1">回复</label>
|
4056
|
+
</div>
|
4057
|
+
<div class="col">
|
4058
|
+
<div class="form-check form-switch" id="ToggleLock" style="display: none">
|
4059
|
+
<input class="form-check-input" type="checkbox" role="switch" id="ToggleLockButton">
|
4060
|
+
<label class="form-check-label" for="ToggleLockButton">锁定本讨论</label>
|
4061
|
+
</div>
|
4062
|
+
</div>
|
4063
|
+
</div>
|
4064
|
+
</div>
|
4065
|
+
<div class="input-group">
|
4066
|
+
<textarea class="col-6 form-control" id="ContentElement" rows="3" placeholder="请输入内容"></textarea>
|
4067
|
+
<div class="col-6 form-control" id="PreviewTab"></div>
|
4068
|
+
</div>
|
4069
|
+
<div class="cf-turnstile mt-2" id="CaptchaContainer"></div>
|
4070
|
+
<button id="SubmitElement" type="button" class="btn btn-primary mb-2" disabled>
|
4071
|
+
发布
|
4072
|
+
<div class="spinner-border spinner-border-sm" role="status" style="display: none;">
|
4073
|
+
</button>
|
4074
|
+
</div>
|
4075
|
+
<div id="ErrorElement" class="alert alert-danger" role="alert" style="display: none;"></div>`;
|
4076
|
+
let CaptchaSecretKey = "";
|
4077
|
+
unsafeWindow.CaptchaLoadedCallback = () => {
|
4078
|
+
turnstile.render("#CaptchaContainer", {
|
4079
|
+
sitekey: CaptchaSiteKey,
|
4080
|
+
callback: function (CaptchaSecretKeyValue) {
|
4081
|
+
CaptchaSecretKey = CaptchaSecretKeyValue;
|
4082
|
+
SubmitElement.disabled = false;
|
4083
|
+
},
|
4084
|
+
});
|
4085
|
+
};
|
4086
|
+
let TurnstileScript = document.createElement("script");
|
4087
|
+
TurnstileScript.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=CaptchaLoadedCallback";
|
4088
|
+
document.body.appendChild(TurnstileScript);
|
4089
|
+
ContentElement.addEventListener("keydown", (Event) => {
|
4090
|
+
if (Event.ctrlKey && Event.keyCode == 13) {
|
4091
|
+
SubmitElement.click();
|
4092
|
+
}
|
4093
|
+
});
|
4094
|
+
ContentElement.addEventListener("input", () => {
|
4095
|
+
PreviewTab.innerHTML = PurifyHTML(marked.parse(ContentElement.value));
|
4096
|
+
RenderMathJax();
|
4097
|
+
});
|
4098
|
+
ContentElement.addEventListener("paste", (EventData) => {
|
4099
|
+
let Items = EventData.clipboardData.items;
|
4100
|
+
if (Items.length !== 0) {
|
4101
|
+
for (let i = 0; i < Items.length; i++) {
|
4102
|
+
if (Items[i].type.indexOf("image") != -1) {
|
4103
|
+
let Reader = new FileReader();
|
4104
|
+
Reader.readAsDataURL(Items[i].getAsFile());
|
4105
|
+
Reader.onload = () => {
|
4106
|
+
let Before = ContentElement.value.substring(0, ContentElement.selectionStart);
|
4107
|
+
let After = ContentElement.value.substring(ContentElement.selectionEnd, ContentElement.value.length);
|
4108
|
+
const UploadMessage = "![正在上传图片...]()";
|
4109
|
+
ContentElement.value = Before + UploadMessage + After;
|
4110
|
+
ContentElement.dispatchEvent(new Event("input"));
|
4111
|
+
RequestAPI("UploadImage", {
|
4112
|
+
"Image": Reader.result
|
4113
|
+
}, (ResponseData) => {
|
4114
|
+
if (ResponseData.Success) {
|
4115
|
+
ContentElement.value = Before + `` + After;
|
4116
|
+
ContentElement.dispatchEvent(new Event("input"));
|
4117
|
+
}
|
4118
|
+
else {
|
4119
|
+
ContentElement.value = Before + `![上传失败!]()` + After;
|
4120
|
+
ContentElement.dispatchEvent(new Event("input"));
|
4121
|
+
}
|
4122
|
+
});
|
4123
|
+
};
|
4124
|
+
}
|
4125
|
+
}
|
4126
|
+
}
|
4127
|
+
});
|
4128
|
+
let RefreshReply = (Silent = true) => {
|
4129
|
+
if (!Silent) {
|
4130
|
+
PostTitle.innerHTML = `<span class="placeholder col-${Math.ceil(Math.random() * 6)}"></span>`;
|
4131
|
+
PostAuthor.innerHTML = `<span class="placeholder col-${Math.ceil(Math.random() * 6)}"></span>`;
|
4132
|
+
PostTime.innerHTML = `<span class="placeholder col-${Math.ceil(Math.random() * 6)}"></span>`;
|
4133
|
+
PostBoard.innerHTML = `<span class="placeholder col-${Math.ceil(Math.random() * 6)}"></span>`;
|
4134
|
+
PostReplies.innerHTML = "";
|
4135
|
+
for (let i = 0; i < 10; i++) {
|
4136
|
+
PostReplies.innerHTML += `<div class="card mb-3">
|
4137
|
+
<div class="card-body">
|
4138
|
+
<div class="row mb-3">
|
4139
|
+
<span class="col-6"><span class="placeholder col-${Math.ceil(Math.random() * 6)}"></span></span>
|
4140
|
+
<span class="col-6"><span class="placeholder col-${Math.ceil(Math.random() * 6)}"></span></span>
|
4141
|
+
</div>
|
4142
|
+
<hr>
|
4143
|
+
<span class="placeholder col-${Math.ceil(Math.random() * 12)}"></span>
|
4144
|
+
<span class="placeholder col-${Math.ceil(Math.random() * 12)}"></span>
|
4145
|
+
<span class="placeholder col-${Math.ceil(Math.random() * 12)}"></span>
|
4146
|
+
</div>
|
4147
|
+
</div>`;
|
4148
|
+
}
|
4149
|
+
}
|
4150
|
+
RequestAPI("GetPost", {
|
4151
|
+
"PostID": Number(ThreadID),
|
4152
|
+
"Page": Number(Page)
|
4153
|
+
}, async (ResponseData) => {
|
4154
|
+
if (ResponseData.Success == true) {
|
4155
|
+
let OldScrollTop = document.documentElement.scrollTop;
|
4156
|
+
let LockButtons = !IsAdmin && ResponseData.Data.Lock.Locked;
|
4157
|
+
if (!Silent) {
|
4158
|
+
DiscussPagination.children[0].children[0].href = "https://www.xmoj.tech/discuss3/thread.php?tid=" + ThreadID + "&page=1";
|
4159
|
+
DiscussPagination.children[1].children[0].href = "https://www.xmoj.tech/discuss3/thread.php?tid=" + ThreadID + "&page=" + (Page - 1);
|
4160
|
+
DiscussPagination.children[2].children[0].href = "https://www.xmoj.tech/discuss3/thread.php?tid=" + ThreadID + "&page=" + Page;
|
4161
|
+
DiscussPagination.children[3].children[0].href = "https://www.xmoj.tech/discuss3/thread.php?tid=" + ThreadID + "&page=" + (Page + 1);
|
4162
|
+
DiscussPagination.children[4].children[0].href = "https://www.xmoj.tech/discuss3/thread.php?tid=" + ThreadID + "&page=" + ResponseData.Data.PageCount;
|
4163
|
+
if (Page <= 1) {
|
4164
|
+
DiscussPagination.children[0].classList.add("disabled");
|
4165
|
+
DiscussPagination.children[1].remove();
|
4166
|
+
}
|
4167
|
+
if (Page >= ResponseData.Data.PageCount) {
|
4168
|
+
DiscussPagination.children[DiscussPagination.children.length - 1].classList.add("disabled");
|
4169
|
+
DiscussPagination.children[DiscussPagination.children.length - 2].remove();
|
4170
|
+
}
|
4171
|
+
if (IsAdmin || ResponseData.Data.UserID == CurrentUsername) {
|
4172
|
+
Delete.style.display = "";
|
4173
|
+
}
|
4174
|
+
}
|
4175
|
+
PostTitle.innerText = ResponseData.Data.Title + (ResponseData.Data.ProblemID == 0 ? "" : ` - 题目` + ResponseData.Data.ProblemID);
|
4176
|
+
PostAuthor.innerHTML = "<span></span>";
|
4177
|
+
GetUsernameHTML(PostAuthor.children[0], ResponseData.Data.UserID);
|
4178
|
+
PostTime.innerHTML = GetRelativeTime(ResponseData.Data.PostTime);
|
4179
|
+
PostBoard.innerHTML = ResponseData.Data.BoardName;
|
4180
|
+
let Replies = ResponseData.Data.Reply;
|
4181
|
+
PostReplies.innerHTML = "";
|
4182
|
+
for (let i = 0; i < Replies.length; i++) {
|
4183
|
+
let CardElement = document.createElement("div"); PostReplies.appendChild(CardElement);
|
4184
|
+
CardElement.className = "card mb-3";
|
4185
|
+
let CardBodyElement = document.createElement("div"); CardElement.appendChild(CardBodyElement);
|
4186
|
+
CardBodyElement.className = "card-body row";
|
4187
|
+
let CardBodyRowElement = document.createElement("div"); CardBodyElement.appendChild(CardBodyRowElement);
|
4188
|
+
CardBodyRowElement.className = "row mb-3";
|
4189
|
+
let AuthorElement = document.createElement("span"); CardBodyRowElement.appendChild(AuthorElement);
|
4190
|
+
AuthorElement.className = "col-4 text-muted";
|
4191
|
+
let AuthorSpanElement = document.createElement("span"); AuthorElement.appendChild(AuthorSpanElement);
|
4192
|
+
AuthorSpanElement.innerText = "作者:";
|
4193
|
+
let AuthorUsernameElement = document.createElement("span"); AuthorElement.appendChild(AuthorUsernameElement);
|
4194
|
+
GetUsernameHTML(AuthorUsernameElement, Replies[i].UserID);
|
4195
|
+
let SendTimeElement = document.createElement("span"); CardBodyRowElement.appendChild(SendTimeElement);
|
4196
|
+
SendTimeElement.className = "col-4 text-muted";
|
4197
|
+
SendTimeElement.innerHTML = "发布时间:" + GetRelativeTime(Replies[i].ReplyTime);
|
4198
|
+
|
4199
|
+
let OKButton;
|
4200
|
+
if (!LockButtons) {
|
4201
|
+
let ButtonsElement = document.createElement("span"); CardBodyRowElement.appendChild(ButtonsElement);
|
4202
|
+
ButtonsElement.className = "col-4";
|
4203
|
+
let ReplyButton = document.createElement("button"); ButtonsElement.appendChild(ReplyButton);
|
4204
|
+
ReplyButton.type = "button";
|
4205
|
+
ReplyButton.className = "btn btn-sm btn-info";
|
4206
|
+
ReplyButton.innerText = "回复";
|
4207
|
+
ReplyButton.addEventListener("click", () => {
|
4208
|
+
let Content = Replies[i].Content;
|
4209
|
+
while (Content.startsWith(">")) {
|
4210
|
+
Content = Content.substring(Content.indexOf("\n") + 1);
|
4211
|
+
}
|
4212
|
+
Content = Content.trim();
|
4213
|
+
Content = Content.split("\n").map((Line) => {
|
4214
|
+
return "> " + Line;
|
4215
|
+
}).join("\n");
|
4216
|
+
ContentElement.value += Content + `\n\n@${Replies[i].UserID} `;
|
4217
|
+
ContentElement.focus();
|
4218
|
+
});
|
4219
|
+
let DeleteButton = document.createElement("button"); ButtonsElement.appendChild(DeleteButton);
|
4220
|
+
DeleteButton.type = "button";
|
4221
|
+
DeleteButton.className = "btn btn-sm btn-danger ms-1";
|
4222
|
+
DeleteButton.innerText = "删除";
|
4223
|
+
DeleteButton.style.display = (IsAdmin || Replies[i].UserID == CurrentUsername ? "" : "none");
|
4224
|
+
DeleteButton.addEventListener("click", () => {
|
4225
|
+
DeleteButton.disabled = true;
|
4226
|
+
DeleteButton.lastChild.style.display = "";
|
4227
|
+
RequestAPI("DeleteReply", {
|
4228
|
+
"ReplyID": Number(Replies[i].ReplyID)
|
4229
|
+
}, (ResponseData) => {
|
4230
|
+
if (ResponseData.Success == true) {
|
4231
|
+
RefreshReply();
|
4232
|
+
}
|
4233
|
+
else {
|
4234
|
+
DeleteButton.disabled = false;
|
4235
|
+
DeleteButton.lastChild.style.display = "none";
|
4236
|
+
ErrorElement.innerText = ResponseData.Message;
|
4237
|
+
ErrorElement.style.display = "";
|
4238
|
+
}
|
4239
|
+
});
|
4240
|
+
});
|
4241
|
+
let DeleteSpin = document.createElement("div"); DeleteButton.appendChild(DeleteSpin);
|
4242
|
+
DeleteSpin.className = "spinner-border spinner-border-sm";
|
4243
|
+
DeleteSpin.role = "status";
|
4244
|
+
DeleteSpin.style.display = "none";
|
4245
|
+
OKButton = document.createElement("button"); ButtonsElement.appendChild(OKButton);
|
4246
|
+
OKButton.type = "button";
|
4247
|
+
OKButton.style.display = "none";
|
4248
|
+
OKButton.className = "btn btn-sm btn-success ms-1";
|
4249
|
+
OKButton.innerText = "确认";
|
4250
|
+
let OKSpin = document.createElement("div"); OKButton.appendChild(OKSpin);
|
4251
|
+
OKSpin.className = "spinner-border spinner-border-sm";
|
4252
|
+
OKSpin.role = "status";
|
4253
|
+
OKSpin.style.display = "none";
|
4254
|
+
OKButton.addEventListener("click", () => {
|
4255
|
+
OKButton.disabled = true;
|
4256
|
+
OKButton.lastChild.style.display = "";
|
4257
|
+
RequestAPI("EditReply", {
|
4258
|
+
ReplyID: Number(Replies[i].ReplyID),
|
4259
|
+
Content: String(ContentEditor.value)
|
4260
|
+
}, (ResponseData) => {
|
4261
|
+
if (ResponseData.Success == true) {
|
4262
|
+
RefreshReply();
|
4263
|
+
}
|
4264
|
+
else {
|
4265
|
+
OKButton.disabled = false;
|
4266
|
+
OKButton.lastChild.style.display = "none";
|
4267
|
+
ErrorElement.innerText = ResponseData.Message;
|
4268
|
+
ErrorElement.style.display = "";
|
4269
|
+
}
|
4270
|
+
});
|
4271
|
+
});
|
4272
|
+
let CancelButton = document.createElement("button"); ButtonsElement.appendChild(CancelButton);
|
4273
|
+
CancelButton.type = "button";
|
4274
|
+
CancelButton.style.display = "none";
|
4275
|
+
CancelButton.className = "btn btn-sm btn-secondary ms-1";
|
4276
|
+
CancelButton.innerText = "取消";
|
4277
|
+
CancelButton.addEventListener("click", () => {
|
4278
|
+
CardBodyElement.children[2].style.display = "";
|
4279
|
+
CardBodyElement.children[3].style.display = "none";
|
4280
|
+
EditButton.style.display = "";
|
4281
|
+
OKButton.style.display = "none";
|
4282
|
+
CancelButton.style.display = "none";
|
4283
|
+
});
|
4284
|
+
let EditButton = document.createElement("button"); ButtonsElement.appendChild(EditButton);
|
4285
|
+
EditButton.type = "button";
|
4286
|
+
EditButton.className = "btn btn-sm btn-warning ms-1";
|
4287
|
+
EditButton.innerText = "编辑";
|
4288
|
+
EditButton.style.display = (IsAdmin || Replies[i].UserID == CurrentUsername ? "" : "none");
|
4289
|
+
EditButton.addEventListener("click", () => {
|
4290
|
+
CardBodyElement.children[2].style.display = "none";
|
4291
|
+
CardBodyElement.children[3].style.display = "";
|
4292
|
+
EditButton.style.display = "none";
|
4293
|
+
OKButton.style.display = "";
|
4294
|
+
CancelButton.style.display = "";
|
4295
|
+
});
|
4296
|
+
}
|
4297
|
+
|
4298
|
+
let CardBodyHRElement = document.createElement("hr"); CardBodyElement.appendChild(CardBodyHRElement);
|
4299
|
+
|
4300
|
+
let ReplyContentElement = document.createElement("div"); CardBodyElement.appendChild(ReplyContentElement);
|
4301
|
+
ReplyContentElement.innerHTML = PurifyHTML(marked.parse(Replies[i].Content)).replaceAll(/@([a-zA-Z0-9]+)/g, `<b>@</b><span class="ms-1 Usernames">$1</span>`);
|
4302
|
+
if (Replies[i].EditTime != null) {
|
4303
|
+
if (Replies[i].EditPerson == Replies[i].UserID) {
|
4304
|
+
ReplyContentElement.innerHTML += `<span class="text-muted" style="font-size: 12px">最后编辑于${GetRelativeTime(Replies[i].EditTime)}</span>`;
|
4305
|
+
}
|
4306
|
+
else {
|
4307
|
+
ReplyContentElement.innerHTML += `<span class="text-muted" style="font-size: 12px">最后被<span class="Usernames">${Replies[i].EditPerson}</span>编辑于${GetRelativeTime(Replies[i].EditTime)}</span>`;
|
4308
|
+
}
|
4309
|
+
}
|
4310
|
+
let ContentEditElement = document.createElement("div"); CardBodyElement.appendChild(ContentEditElement);
|
4311
|
+
ContentEditElement.classList.add("input-group");
|
4312
|
+
ContentEditElement.style.display = "none";
|
4313
|
+
let ContentEditor = document.createElement("textarea"); ContentEditElement.appendChild(ContentEditor);
|
4314
|
+
ContentEditor.className = "form-control col-6";
|
4315
|
+
ContentEditor.rows = 3;
|
4316
|
+
ContentEditor.value = Replies[i].Content;
|
4317
|
+
if (ContentEditor.value.indexOf("<br>") != -1) {
|
4318
|
+
ContentEditor.value = ContentEditor.value.substring(0, ContentEditor.value.indexOf("<br>"));
|
4319
|
+
}
|
4320
|
+
ContentEditor.addEventListener("keydown", (Event) => {
|
4321
|
+
if (Event.ctrlKey && Event.keyCode == 13) {
|
4322
|
+
OKButton.click();
|
4323
|
+
}
|
4324
|
+
});
|
4325
|
+
let PreviewTab = document.createElement("div"); ContentEditElement.appendChild(PreviewTab);
|
4326
|
+
PreviewTab.className = "form-control col-6";
|
4327
|
+
PreviewTab.innerHTML = PurifyHTML(marked.parse(ContentEditor.value));
|
4328
|
+
ContentEditor.addEventListener("input", () => {
|
4329
|
+
PreviewTab.innerHTML = PurifyHTML(marked.parse(ContentEditor.value));
|
4330
|
+
RenderMathJax();
|
4331
|
+
});
|
4332
|
+
ContentEditor.addEventListener("paste", (EventData) => {
|
4333
|
+
let Items = EventData.clipboardData.items;
|
4334
|
+
if (Items.length !== 0) {
|
4335
|
+
for (let i = 0; i < Items.length; i++) {
|
4336
|
+
if (Items[i].type.indexOf("image") != -1) {
|
4337
|
+
let Reader = new FileReader();
|
4338
|
+
Reader.readAsDataURL(Items[i].getAsFile());
|
4339
|
+
Reader.onload = () => {
|
4340
|
+
let Before = ContentEditor.value.substring(0, ContentEditor.selectionStart);
|
4341
|
+
let After = ContentEditor.value.substring(ContentEditor.selectionEnd, ContentEditor.value.length);
|
4342
|
+
const UploadMessage = "![正在上传图片...]()";
|
4343
|
+
ContentEditor.value = Before + UploadMessage + After;
|
4344
|
+
ContentEditor.dispatchEvent(new Event("input"));
|
4345
|
+
RequestAPI("UploadImage", {
|
4346
|
+
"Image": Reader.result
|
4347
|
+
}, (ResponseData) => {
|
4348
|
+
if (ResponseData.Success) {
|
4349
|
+
ContentEditor.value = Before + `` + After;
|
4350
|
+
ContentEditor.dispatchEvent(new Event("input"));
|
4351
|
+
}
|
4352
|
+
else {
|
4353
|
+
ContentEditor.value = Before + `![上传失败!]()` + After;
|
4354
|
+
ContentEditor.dispatchEvent(new Event("input"));
|
4355
|
+
}
|
4356
|
+
});
|
4357
|
+
};
|
4358
|
+
}
|
4359
|
+
}
|
4360
|
+
}
|
4361
|
+
});
|
4362
|
+
}
|
4363
|
+
|
4364
|
+
let UsernameElements = document.getElementsByClassName("Usernames");
|
4365
|
+
for (let i = 0; i < UsernameElements.length; i++) {
|
4366
|
+
GetUsernameHTML(UsernameElements[i], UsernameElements[i].innerText, true);
|
4367
|
+
}
|
4368
|
+
|
4369
|
+
let CodeElements = document.querySelectorAll("#PostReplies > div > div > div:nth-child(3) > pre > code");
|
4370
|
+
for (let i = 0; i < CodeElements.length; i++) {
|
4371
|
+
let ModeName = "text/x-c++src";
|
4372
|
+
if (CodeElements[i].className == "language-c") {
|
4373
|
+
ModeName = "text/x-csrc";
|
4374
|
+
}
|
4375
|
+
else if (CodeElements[i].className == "language-cpp") {
|
4376
|
+
ModeName = "text/x-c++src";
|
4377
|
+
}
|
4378
|
+
CodeMirror(CodeElements[i].parentElement, {
|
4379
|
+
value: CodeElements[i].innerText,
|
4380
|
+
mode: ModeName,
|
4381
|
+
theme: (UtilityEnabled("DarkMode") ? "darcula" : "default"),
|
4382
|
+
lineNumbers: true,
|
4383
|
+
readOnly: true
|
4384
|
+
}).setSize("100%", "auto");
|
4385
|
+
CodeElements[i].remove();
|
4386
|
+
}
|
4387
|
+
|
4388
|
+
if (LockButtons) {
|
4389
|
+
let LockElement = ContentElement.parentElement.parentElement;
|
4390
|
+
LockElement.innerHTML = "讨论已于 " + await GetRelativeTime(ResponseData.Data.Lock.LockTime) + " 被 ";
|
4391
|
+
let LockUsernameSpan = document.createElement("span"); LockElement.appendChild(LockUsernameSpan);
|
4392
|
+
GetUsernameHTML(LockUsernameSpan, ResponseData.Data.Lock.LockPerson);
|
4393
|
+
LockElement.innerHTML += " 锁定";
|
4394
|
+
LockElement.classList.add("mb-5");
|
4395
|
+
}
|
4396
|
+
|
4397
|
+
if (IsAdmin) {
|
4398
|
+
ToggleLock.style.display = "inline-block";
|
4399
|
+
ToggleLockButton.checked = ResponseData.Data.Lock.Locked;
|
4400
|
+
ToggleLockButton.onclick = () => {
|
4401
|
+
ToggleLockButton.disabled = true;
|
4402
|
+
ErrorElement.style.display = "none";
|
4403
|
+
RequestAPI((ToggleLockButton.checked ? "LockPost" : "UnlockPost"), {
|
4404
|
+
"PostID": Number(ThreadID)
|
4405
|
+
}, (LockResponseData) => {
|
4406
|
+
ToggleLockButton.disabled = false;
|
4407
|
+
if (LockResponseData.Success) {
|
4408
|
+
RefreshReply();
|
4409
|
+
} else {
|
4410
|
+
ErrorElement.style.display = "";
|
4411
|
+
ErrorElement.innerText = "错误:" + LockResponseData.Message;
|
4412
|
+
ToggleLockButton.checked = !ToggleLockButton.checked;
|
4413
|
+
}
|
4414
|
+
});
|
4415
|
+
};
|
4416
|
+
}
|
4417
|
+
|
4418
|
+
Style.innerHTML += "img {";
|
4419
|
+
Style.innerHTML += " width: 50%;";
|
4420
|
+
Style.innerHTML += "}";
|
4421
|
+
|
4422
|
+
RenderMathJax();
|
4423
|
+
|
4424
|
+
if (Silent) {
|
4425
|
+
scrollTo({
|
4426
|
+
top: OldScrollTop,
|
4427
|
+
behavior: "instant"
|
4428
|
+
});
|
4429
|
+
}
|
4430
|
+
}
|
4431
|
+
else {
|
4432
|
+
PostTitle.innerText = "错误:" + ResponseData.Message;
|
4433
|
+
}
|
4434
|
+
});
|
4435
|
+
};
|
4436
|
+
Delete.addEventListener("click", () => {
|
4437
|
+
Delete.disabled = true;
|
4438
|
+
Delete.children[0].style.display = "inline-block";
|
4439
|
+
RequestAPI("DeletePost", {
|
4440
|
+
"PostID": Number(SearchParams.get("tid"))
|
4441
|
+
}, (ResponseData) => {
|
4442
|
+
Delete.disabled = false;
|
4443
|
+
Delete.children[0].style.display = "none";
|
4444
|
+
if (ResponseData.Success == true) {
|
4445
|
+
location.href = "https://www.xmoj.tech/discuss3/discuss.php";
|
4446
|
+
}
|
4447
|
+
else {
|
4448
|
+
ErrorElement.innerText = ResponseData.Message;
|
4449
|
+
ErrorElement.style.display = "block";
|
4450
|
+
}
|
4451
|
+
});
|
4452
|
+
});
|
4453
|
+
SubmitElement.addEventListener("click", async () => {
|
4454
|
+
ErrorElement.style.display = "none";
|
4455
|
+
SubmitElement.disabled = true;
|
4456
|
+
SubmitElement.children[0].style.display = "inline-block";
|
4457
|
+
RequestAPI("NewReply", {
|
4458
|
+
"PostID": Number(SearchParams.get("tid")),
|
4459
|
+
"Content": String(ContentElement.value),
|
4460
|
+
"CaptchaSecretKey": String(CaptchaSecretKey)
|
4461
|
+
}, async (ResponseData) => {
|
4462
|
+
SubmitElement.disabled = false;
|
4463
|
+
SubmitElement.children[0].style.display = "none";
|
4464
|
+
if (ResponseData.Success == true) {
|
4465
|
+
RefreshReply();
|
4466
|
+
ContentElement.value = "";
|
4467
|
+
PreviewTab.innerHTML = "";
|
4468
|
+
while (PostReplies.innerHTML.indexOf("placeholder") != -1) {
|
4469
|
+
await new Promise((resolve) => {
|
4470
|
+
setTimeout(resolve, 100);
|
4471
|
+
});
|
4472
|
+
}
|
4473
|
+
ContentElement.focus();
|
4474
|
+
ContentElement.scrollIntoView();
|
4475
|
+
turnstile.reset();
|
4476
|
+
}
|
4477
|
+
else {
|
4478
|
+
ErrorElement.innerText = ResponseData.Message;
|
4479
|
+
ErrorElement.style.display = "block";
|
4480
|
+
}
|
4481
|
+
});
|
4482
|
+
});
|
4483
|
+
RefreshReply(false);
|
4484
|
+
addEventListener("focus", RefreshReply);
|
4485
|
+
}
|
4486
|
+
}
|
4487
|
+
}
|
4488
|
+
}
|
4489
|
+
}
|
4490
|
+
}
|