Skip to content
This repository was archived by the owner on Aug 4, 2024. It is now read-only.

Commit 4c38a8f

Browse files
committed
Implementation: Remote CAPTCHA solver
1 parent 3eddae4 commit 4c38a8f

File tree

5 files changed

+187
-20
lines changed

5 files changed

+187
-20
lines changed

css/pjw.css

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,11 @@ body {
375375
.pjw-xk-welcome-card {
376376
padding: 12px 24px;
377377
background: linear-gradient(50deg, rgba(99, 6, 95, 0.9) 0%, rgba(93, 42, 175, 0.9) 60%, rgba(255, 71, 71, 0.9) 100%);
378+
color: white;
378379
}
379380

380381
.pjw-xk-welcome-card > p {
381-
color: rgba(255, 255, 255, .87);
382+
opacity: .87;
382383
}
383384

384385
.pjw-xk-welcome-link-container {
@@ -389,16 +390,23 @@ body {
389390
margin: 12px 0;
390391
}
391392

392-
.pjw-xk-welcome-link-container > a {
393-
color: rgba(255, 255, 255, .6);
394-
display: flex;
393+
.pjw-xk-welcome-card a {
394+
color: white;
395+
opacity: 0.6;
396+
display: inline-flex;
395397
flex-direction: row;
396398
align-items: center;
399+
}
400+
401+
.pjw-xk-welcome-card a:hover {
402+
opacity: 0.9;
403+
}
404+
405+
.pjw-xk-welcome-link-container > a {
397406
margin-right: 16px;
398407
}
399408

400409
.pjw-xk-welcome-link-container > a:hover {
401-
color: rgba(255, 255, 255, .9);
402410
margin-right: 4px;
403411
}
404412

@@ -407,6 +415,18 @@ body {
407415
font-family: "Material Icons Round";
408416
}
409417

418+
#pjw-captcha-config {
419+
cursor: pointer;
420+
user-select: none;
421+
border: 1px solid #c1c1c1;
422+
border-radius: 4px;
423+
padding: 1px 3px;
424+
}
425+
426+
#pjw-captcha-config:hover {
427+
font-weight: bold;
428+
}
429+
410430
.login-div,.cv-login,.cv-user {
411431
height: auto !important;
412432
}

js/inject.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ for (const mode_name in modes_reg) {
6565
(() => {
6666
const info = document.createElement("meta");
6767
info.setAttribute("name", "pjw");
68-
info.setAttribute("version", browser?.runtime?.getManifest()?.version || GM_info?.script?.version || "");
68+
info.setAttribute("version",
69+
(typeof GM_info == "undefined" ? "" : GM_info?.script?.version)
70+
|| (browser?.runtime?.getManifest()?.version || ""));
6971
info.setAttribute("mode", pjw_mode);
7072
document.documentElement.appendChild(info);
7173
})();

js/pjw-core.js

Lines changed: 157 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const pjw = {
44
site: "",
55
mode: "",
66
initialized: false,
7-
version_description: "PotatoPlus 0.3.7 包含诸多界面更新与错误修复。",
7+
version_description: "PotatoPlus 0.3.8 包含界面更新与错误修复。",
88
data: new Proxy(JSON.parse(localStorage.getItem("potatoplus_data")) || {}, {
99
get(target, property, receiver) {
1010
if (property === "clear") {
@@ -31,7 +31,9 @@ const pjw = {
3131

3232
},
3333
deleteProperty(target, property) {
34-
return delete target[property];
34+
let delete_res = delete target[property];
35+
localStorage.setItem("potatoplus_data", JSON.stringify(target));
36+
return delete_res;
3537
}
3638
}),
3739
preferences: {},
@@ -50,13 +52,14 @@ const pjw = {
5052
},
5153
};
5254

53-
window.pjw = pjw;
54-
pjw.preferences = pjw.data;
55-
56-
const info = document.querySelector("meta[name=\"pjw\"]");
57-
pjw.version = info.getAttribute("version");
58-
pjw.mode = info.getAttribute("mode");
59-
pjw.site = (window.location.host == "xk.nju.edu.cn" ? "xk" : "jw");
55+
(() => {
56+
window.pjw = pjw;
57+
pjw.preferences = pjw.data;
58+
const info = document.querySelector("meta[name=\"pjw\"]");
59+
pjw.version = info.getAttribute("version");
60+
pjw.mode = info.getAttribute("mode");
61+
pjw.site = (window.location.host == "xk.nju.edu.cn" ? "xk" : "jw");
62+
})();
6063

6164
window.potatojw_intl = function() {
6265
if (pjw.initialized == true) return;
@@ -85,7 +88,7 @@ window.potatojw_intl = function() {
8588
'custom_map': {'dimension1': 'version'}
8689
});
8790
gtag('event', 'version_dimension', {'version': pjw.version + " " + pjw.platform});
88-
</script>
91+
</script>
8992
`;
9093

9194
if (pjw.site == "jw") {
@@ -158,7 +161,7 @@ window.potatojw_intl = function() {
158161
}
159162
}
160163
} else if (pjw.site == "xk") {
161-
pjw.preferences.share_usage_data && $("head").append($(google_analytics_js));
164+
pjw.preferences.enabled && pjw.preferences.share_usage_data && $("head").append($(google_analytics_js));
162165
}
163166

164167
console.log(`PotatoPlus v${pjw.version} (${pjw.platform}) by Limos`);
@@ -467,7 +470,65 @@ window.potatojw_intl = function() {
467470
</button>
468471
<label for="pjw-share-usage-data-switch">发送匿名统计数据</label>
469472
</div>
473+
474+
<div class="pjw-xk-welcome-option">
475+
<button id="pjw-solve-captcha-switch" class="mdc-switch mdc-switch--unselected" type="button" role="switch" aria-checked="false" data-mdc-auto-init="MDCRipple">
476+
<div class="mdc-switch__track"></div>
477+
<div class="mdc-switch__handle-track">
478+
<div class="mdc-switch__handle">
479+
<div class="mdc-switch__shadow">
480+
<div class="mdc-elevation-overlay"></div>
481+
</div>
482+
<div class="mdc-switch__ripple"></div>
483+
</div>
484+
</div>
485+
<span class="mdc-switch__focus-ring-wrapper">
486+
<div class="mdc-switch__focus-ring"></div>
487+
</span>
488+
</button>
489+
<label for="pjw-solve-captcha-switch">验证码识别服务</label>
490+
<label id="pjw-captcha-config">配置</label>
491+
</div>
492+
</div>
493+
</div>
494+
495+
<div id="pjw-captcha-config-dialog" class="mdc-dialog">
496+
<div class="mdc-dialog__container">
497+
<div class="mdc-dialog__surface"
498+
role="alertdialog"
499+
aria-modal="true"
500+
aria-labelledby="pjw-captcha-config-dialog-title"
501+
aria-describedby="pjw-captcha-config-dialog-content">
502+
<!-- Title cannot contain leading whitespace due to mdc-typography-baseline-top() -->
503+
<h2 class="mdc-dialog__title" id="pjw-captcha-config-dialog-title">
504+
验证码识别服务配置
505+
</h2>
506+
<div class="mdc-dialog__content" id="pjw-captcha-config-dialog-content">
507+
<p>启用验证码识别后,当前页面用于生成及校验验证码的 vtoken 将会被自动发送到远程服务器进行处理。您可以在此配置远程服务器的 URL,或留空以使用默认服务器。</p>
508+
<label id="pjw-captcha-config-dialog-url" class="mdc-text-field mdc-text-field--filled" style="width: 100%;" data-mdc-auto-init="MDCRipple">
509+
<span class="mdc-text-field__ripple"></span>
510+
<span class="mdc-floating-label" id="pjw-captcha-config-dialog-urllabel">URL</span>
511+
<input class="mdc-text-field__input" type="text" aria-labelledby="pjw-captcha-config-dialog-urllabel" placeholder="https://example.com/captcha-solver/?data={%data}">
512+
<span class="mdc-line-ripple"></span>
513+
</label>
514+
<section style="font-size: 12px;">
515+
<span>URL 中的 {%data} 将会在使用时被替换为 vtoken 的值。</span> <br>
516+
<span>声明:默认服务器为实验性质,不保证准确度和稳定性。您的个人数据不会被服务器存储。</span>
517+
</section>
518+
</div>
519+
<div class="mdc-dialog__actions">
520+
<button type="button" class="mdc-button mdc-dialog__button" style="color: gray;" data-mdc-dialog-action="close">
521+
<div class="mdc-button__ripple"></div>
522+
<span class="mdc-button__label">撤销更改</span>
523+
</button>
524+
<button type="button" class="mdc-button mdc-dialog__button" data-mdc-dialog-action="accept">
525+
<div class="mdc-button__ripple"></div>
526+
<span class="mdc-button__label">保存</span>
527+
</button>
528+
</div>
529+
</div>
470530
</div>
531+
<div class="mdc-dialog__scrim"></div>
471532
</div>
472533
`;
473534
$("div.language").before(pjw_options_html);
@@ -486,6 +547,90 @@ window.potatojw_intl = function() {
486547
$(".pjw-xk-welcome-subsection").hide();
487548
$("#pjw-share-usage-data-switch").on("click", () => { pjw.preferences.share_usage_data = !pjw.preferences.share_usage_data; });
488549

550+
const solve_captcha_switch = new window.mdc.switchControl.MDCSwitch(document.getElementById("pjw-solve-captcha-switch"));
551+
solve_captcha_switch.selected = (pjw.preferences.solve_captcha === true);
552+
553+
const captcha_config_dialog = new window.mdc.dialog.MDCDialog(document.getElementById("pjw-captcha-config-dialog"));
554+
$("#pjw-solve-captcha-switch").on("click", null, {
555+
dialog: captcha_config_dialog,
556+
switch: solve_captcha_switch
557+
}, (e) => {
558+
if (pjw.data.captcha_solver_link === null) {
559+
e.data.switch.selected = false;
560+
pjw.preferences.solve_captcha = false;
561+
e.data.dialog.open();
562+
} else {
563+
pjw.preferences.solve_captcha = !pjw.preferences.solve_captcha;
564+
initCAPTCHASolver();
565+
}
566+
});
567+
$("#pjw-captcha-config").on("click", null, {
568+
dialog: captcha_config_dialog
569+
}, (e) => {
570+
e.data.dialog.open();
571+
});
572+
573+
const captcha_config_dialog_urlfield = new mdc.textField.MDCTextField(
574+
document.getElementById("pjw-captcha-config-dialog-url"));
575+
captcha_config_dialog_urlfield.value = pjw.data.captcha_solver_link || "";
576+
captcha_config_dialog.buttons[1].addEventListener("click", function () {
577+
pjw.data.captcha_solver_link = captcha_config_dialog_urlfield.value;
578+
});
579+
580+
function initCAPTCHASolver() {
581+
if (pjw.captcha_initialized === true) {
582+
if (document.getElementById("vcodeImg").complete) {
583+
solveXKCAPTCHA();
584+
}
585+
return;
586+
}
587+
588+
$(window).on("message", (e) => {
589+
if (!e.originalEvent.isTrusted) return;
590+
if (e?.originalEvent?.data) {
591+
let data = {};
592+
try {
593+
data = JSON.parse(e.originalEvent.data);
594+
} catch (e) {
595+
console.warn(e);
596+
} finally {
597+
if (data["type"] == "captcha" && data["content"].length == 4)
598+
$("input#verifyCode").val(data["content"]);
599+
}
600+
}
601+
});
602+
603+
$("#vcodeImg").css("cursor", "pointer");
604+
$("#vcodeImg").on("click", () => {
605+
$("input#verifyCode").val("");
606+
})
607+
608+
function solveXKCAPTCHA() {
609+
if (pjw.preferences.solve_captcha && $("#loginDiv").css("display") != "none") {
610+
let link = pjw.data.captcha_solver_link || "https://cubiccm.ddns.net/captcha-solver/?mode=xk&data={%data}";
611+
link = link.replace("{%data}", sessionStorage.getItem("vtoken"));
612+
if ($("iframe[data-type=captcha]").length) {
613+
$("iframe[data-type=captcha]").attr("src", link);
614+
} else {
615+
$("body").append(`<iframe src="${link}" width="300" height="300" data-type="captcha" style="display: none;"></iframe>`);
616+
}
617+
}
618+
}
619+
620+
if (document.getElementById("vcodeImg").complete) {
621+
solveXKCAPTCHA();
622+
}
623+
624+
$("#vcodeImg").on("load", () => {
625+
solveXKCAPTCHA();
626+
});
627+
628+
pjw.captcha_initialized = true;
629+
}
630+
631+
pjw.preferences.solve_captcha && initCAPTCHASolver();
632+
633+
489634
const welcome_html = `
490635
<div class="pjw-xk-welcome-card">
491636
<p id="pjw-bulletin-content" style="font-size: 14px;">${pjw.data.bulletin_content || ""}</p>
@@ -502,7 +647,7 @@ window.potatojw_intl = function() {
502647
`;
503648

504649
$("div.language").before(welcome_html);
505-
if (pjw.preferences.enabled)
650+
if (!pjw.preferences.enabled)
506651
$(".pjw-xk-welcome-card").hide();
507652

508653
getBulletin();

manifest-v2.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 2,
33
"name": "PotatoPlus",
4-
"version": "0.3.7",
4+
"version": "0.3.8",
55
"description": "Potato Overflow! NJU土豆改善工程",
66
"icons": {
77
"96": "img/logo96.png",

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "PotatoPlus",
4-
"version": "0.3.7",
4+
"version": "0.3.8",
55
"description": "Potato Overflow! NJU土豆改善工程",
66
"icons": {
77
"96": "img/logo96.png",

0 commit comments

Comments
 (0)