@@ -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
6164window . 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 ( ) ;
0 commit comments