From b7cfc8541c322afab67d55d6df080759df63ae0c Mon Sep 17 00:00:00 2001 From: "lzyme.dev@gmail.com" Date: Mon, 31 Aug 2026 08:38:26 +0800 Subject: [PATCH] update --- dist/jhs-enhance.user.js | 29884 ++++++++++++++++++------------------- src/plugins/setting.js | 2 +- 2 files changed, 14886 insertions(+), 15000 deletions(-) diff --git a/dist/jhs-enhance.user.js b/dist/jhs-enhance.user.js index e73d573..de87c81 100644 --- a/dist/jhs-enhance.user.js +++ b/dist/jhs-enhance.user.js @@ -1,8 +1,8 @@ // ==UserScript== // @name JHS-enhance // @namespace JHS-enhance -// @version 3.3.7 -// @author xie bro,fireinrain +// @version 3.3.9 +// @author xiebro,fireinrain // @description Jav-鉴黄师 增强脚本。列表页:作品状态标签、一键筛选、新作品检测、演员黑名单过滤;详情页:磁力链接高亮、DMM 多画质预览视频、标题翻译、整合字幕搜索(迅雷+SubTitleCat)并支持 115 直传、多源预览图(javfree/projectjav/javstore)含来源切换;数据:115 网盘目录匹配与多目录选择、云盘备份/恢复、跨 Tab 同步;其他:自动翻页、分类折叠、Top250、以图识图、热门榜单、评论查看、相关清单。支持 JavDB / JavBus / JavSee / SeeJav / FC2 / JavTrailers // @license MIT // @icon https://www.google.com/s2/favicons?sz=64&domain=javdb.com @@ -78,249 +78,248 @@ // ==/UserScript== (a => { - if (typeof GM_addStyle == "function") { - GM_addStyle(a); - return - } - const A = document.createElement("style"); - A.textContent = a, document.head.append(A) + if (typeof GM_addStyle == "function") { + GM_addStyle(a); + return + } + const A = document.createElement("style"); + A.textContent = a, document.head.append(A) })(" html #layuicss-skinlayercss{display:none;position:absolute;width:1989px}.layui-layer-shade,.layui-layer{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%}.layui-layer{-webkit-overflow-scrolling:touch}.layui-layer{top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;box-shadow:1px 1px 50px #0000004d}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px #0003}.layui-layer-load{background:url(data:image/gif;base64,R0lGODlhJQAlAJECAL3L2AYrTv///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAAJQAlAAACi5SPqcvtDyGYIFpF690i8xUw3qJBwUlSadmcLqYmGQu6KDIeM13beGzYWWy3DlB4IYaMk+Dso2RWkFCfLPcRvFbZxFLUDTt21BW56TyjRep1e20+i+eYMR145W2eefj+6VFmgTQi+ECVY8iGxcg35phGo/iDFwlTyXWphwlm1imGRdcnuqhHeop6UAAAIfkEBQoAAgAsEAACAAQACwAAAgWMj6nLXAAh+QQFCgACACwVAAUACgALAAACFZQvgRi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwXABEADAADAAACBYyPqcsFACH5BAUKAAIALBUAFQAKAAsAAAITlGKZwWoMHYxqtmplxlNT7ixGAQAh+QQFCgACACwQABgABAALAAACBYyPqctcACH5BAUKAAIALAUAFQAKAAsAAAIVlC+BGL3Z3IlxUmUuhtR2LzHhsiEFACH5BAUKAAIALAEAEQAMAAMAAAIFjI+pywUAIfkEBQoAAgAsBQAFAAoACwAAAhOUYJnAagwdjGq2amXGU1PuLEYBACH5BAUKAAIALBAAAgAEAAsAAAIFhI+py1wAIfkEBQoAAgAsFQAFAAoACwAAAhWUL4AIvdnciXFSZS6G1HYvMeGyIQUAIfkEBQoAAgAsFwARAAwAAwAAAgWEj6nLBQAh+QQFCgACACwVABUACgALAAACE5RgmcBqDB2MarZqZcZTU+4sRgEAIfkEBQoAAgAsEAAYAAQACwAAAgWEj6nLXAAh+QQFCgACACwFABUACgALAAACFZQvgAi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwBABEADAADAAACBYSPqcsFADs=) #eee center center no-repeat}.layui-layer-ico{background:url(data:image/png;base64,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) no-repeat}.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a,.layui-layer-btn a{display:inline-block;*display: inline;*zoom: 1;vertical-align:top}.layui-layer-move{display:none;position:fixed;*position: absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layui-layer{border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}to{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}to{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translate(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translate(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translate(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translate(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translate(-100%) rotate(-120deg)}to{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);transform:translate(0) rotate(0)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translate(-100%) rotate(-120deg)}to{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);-ms-transform:translateX(0px) rotate(0deg);transform:translate(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:rollIn;animation-name:rollIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.layer-anim-05{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes shake{0%,to{-webkit-transform:translateX(0);transform:translate(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translate(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translate(10px)}}@keyframes shake{0%,to{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translate(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translate(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translate(10px)}}.layer-anim-06{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@-webkit-keyframes bounceOut{to{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceOut{to{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background-color:#f8f8f8;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right: 0;top:15px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2e2d3c;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2d93ca}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:0 -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right: -18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 10px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:0 6px;padding:0 15px;border:1px #dedede solid;background-color:#f1f1f1;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:260px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:#0009;color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-page .layui-layer-btn,.layui-layer-iframe .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:none}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:none;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(data:image/gif;base64,R0lGODlhPAAYALMPAPPJp/HYxfSwkf50Df5TD/+HAPe5bvqHR/twOviZavyrMu/m3f9EAP9mAP+ZAO7u7iH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wUmlnaHRzPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvcmlnaHRzLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcFJpZ2h0czpNYXJrZWQ9IkZhbHNlIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6QUNDRERBRjMxRTIwNjgxMTg4QzZERjVGQ0I0MDI1NDkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTlDMEI5MzU5RTY2MTFFMTkxRDY5NkVCMDBGOTBFRUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTlDMEI5MzQ5RTY2MTFFMTkxRDY5NkVCMDBGOTBFRUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpENzU2N0YwMTMyMjA2ODExODhDNkRGNUZDQjQwMjU0OSIgc3RS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) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(data:image/gif;base64,R0lGODlhJQAlAJECAL3L2AYrTv///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAAJQAlAAACi5SPqcvtDyGYIFpF690i8xUw3qJBwUlSadmcLqYmGQu6KDIeM13beGzYWWy3DlB4IYaMk+Dso2RWkFCfLPcRvFbZxFLUDTt21BW56TyjRep1e20+i+eYMR145W2eefj+6VFmgTQi+ECVY8iGxcg35phGo/iDFwlTyXWphwlm1imGRdcnuqhHeop6UAAAIfkEBQoAAgAsEAACAAQACwAAAgWMj6nLXAAh+QQFCgACACwVAAUACgALAAACFZQvgRi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwXABEADAADAAACBYyPqcsFACH5BAUKAAIALBUAFQAKAAsAAAITlGKZwWoMHYxqtmplxlNT7ixGAQAh+QQFCgACACwQABgABAALAAACBYyPqctcACH5BAUKAAIALAUAFQAKAAsAAAIVlC+BGL3Z3IlxUmUuhtR2LzHhsiEFACH5BAUKAAIALAEAEQAMAAMAAAIFjI+pywUAIfkEBQoAAgAsBQAFAAoACwAAAhOUYJnAagwdjGq2amXGU1PuLEYBACH5BAUKAAIALBAAAgAEAAsAAAIFhI+py1wAIfkEBQoAAgAsFQAFAAoACwAAAhWUL4AIvdnciXFSZS6G1HYvMeGyIQUAIfkEBQoAAgAsFwARAAwAAwAAAgWEj6nLBQAh+QQFCgACACwVABUACgALAAACE5RgmcBqDB2MarZqZcZTU+4sRgEAIfkEBQoAAgAsEAAYAAQACwAAAgWEj6nLXAAh+QQFCgACACwFABUACgALAAACFZQvgAi92dyJcVJlLobUdi8x4bIhBQAh+QQFCgACACwBABEADAADAAACBYSPqcsFADs=) no-repeat}.layui-layer-loading .layui-layer-loading2,.layui-layer-ico16{width:32px;height:32px;background:url(data:image/gif;base64,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) no-repeat}.layui-layer-tips{background:none;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:5px 10px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px #0003;background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow: hidden}.layui-layer-tips i.layui-layer-TipsT,.layui-layer-tips i.layui-layer-TipsB{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsR,.layui-layer-tips i.layui-layer-TipsL{top:1px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476a7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#bbb5b5;border:none}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#c9c5c5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92b8b1}.layui-layer-iconext{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABkCAYAAAAv8xodAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNS8xMS8xNNdPc0oAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAWb0lEQVR4nO2de2wU172Av5l92t4Hti/YQHmVmFcSE7+WR0h0uRRVVC2pKldpCFJQEJAiFwg4diikgLEghEhpVLVQNblBSFEUVYoi+hc0FQoE87B52JQAiQnBJDY2wfix633O7P1jdwbbxe9d7yx3PgnJc87iM2M+js+cx+8nhMNhdHQeFcRE34COTizRhdZ5pNCF1nmk0IXWeaQwPqxQEIRYtpEKOABL9NoLtAKhWDbSDRF4EsgAbEBHtL3LAIN9CV6+fHlSvS0fOXLkof9oj8pzDJZ499A2YCxgWbJkiSUnJ8cApADZgCEO7ZmAImAyYFuxYsV4Iv+ZpgIFcWhPR2PEU2gbkAlQU1Mz67PPPvvvq1ev/s/f/va3LCIyp8e4PROQD4wrLi7Oam9vP/Dhhx/+9f79+3/Kz8+3AxPi0KaOxoiX0KrM169ff6KgoGAKgMFgEF944YWZ0c9Y+vrLw8BEpAceV1xcnHX48OE3HQ7HRIAxY8ZM2bdv39Lo5zJi2KaOBomH0D1knjFjxsTulX6/Pxj9Uo5Re4rMY1esWDH+8OHDb6akpGR2/4Db7fZEv4zXuF1HI8Ra6H5lDgQC0ttvv/1l9NIfg/Z6yPzee+/t6S1zY2PjpdWrV/8retkagzZ1NEwshR5Q5j179pzfu3dvOxBg5HINKHNTU1Ody+WqbG1tDQENQOcI29TROA+dthsGGYAd+pd5165d94nIfHeE7Q1K5qKioorvv/8+ANwGakfYZlwIh8MEg0F1OtFoNGIwxGMCKL4Eg0G6urqQJAlRFElNTcVsNo/6fcSih84A7BaLRRiCzCMZy5qAQoYm86URtBc3FJnNZjMzZswgKyuLQCCAJEmJvrUhEQwGcbvdZGdn88ILL5CTk0NnZ2dCnmOkPbQqc11d3eMPk3n37t01lZWVbcRW5v966aWXJh44cKAyWWWWZZlgMIjD4aCoqIj09HRkWeb48eO0tbUlTS+tyDxz5kz2799Peno6LS0trFq1Cr/fT2pq6qjez0iE1mUeJorM6enpFBUVkZaWRigUIhgMEgwGB/4GGiEQCOB2u5kzZw779u0jPT0yze/xeJAkKdYrzoNiuELrMg8TSZIIBoNkZWVRWFiI2WwmHA7j8/k4d+4cnZ2dCRl7DhWlZ37iiSd46623cDgcANy5c4c33ngDj8eD0+kc9fsajtC6zMMkGAwiSRKTJk0iLy9PHVZ4PB7Onj1LR0cHZrMZUdT2njGlZ87Ly2P//v1YrVYAmpqaKC0tpaGhAbvdnpBh01CFHm2ZzURmMx4ZmadNm0Zubi6iKCIIAm1tbZw5cwav14vJZNK8zH6/H7fbTWFhIXv27Okh85YtW7h9+zY2mw2TyZSQ+xuK0KrMly9ffiInJ2dC98pEyNzY2HjJ5XJVJoPMoVCI2bNnM2vWLCCyo/Hu3bucPXuWUCiE2WxOyJhzKCgyL1y4kMrKSiyWyO6Fb7/9li1bttDS0pJQmWHwQidU5oMHD+6xWq09NhYlg8zKtJwsy+Tm5vLYY48RDocRRZGmpiaqq6uRZRmTyaR5mX0+Hx6Ph2eeeYbdu3er0jY0NFBaWqoJmWFwQg8kc2j37t3ndZl70l3mvLw8pk6dSjgcxmAw8O2333LhwgVEUUyKF0C/36/KXFFRoUpbX19PaWkp9+7dw263YzTGap1u+Ax0B7rMwyAcDhMIBDAajbhcLsaPH48sy4iiyNdff01tbS1GozHhvdlgUHrmpUuXsmPHDvU3ybVr1ygtLaW9vV0zMkP/QusyDwNljtlsNlNUVMS4ceNUma9evcrVq1eTSma3282yZcvYvn27KvP169cpKyujo6NDUzJD30Kn8UDmJ3NycsZ3r4yDzABzeURkTklJweVykZGRQTgcRhAEamtr+eabbzCZTJoSoC+UnvnnP/85W7duVWWuq6ujtLQUn8+XsKm5/ujrJ2sDuHDhwpxRktkJZC9evDg92WV2OBy4XC5sNhuyLCPLMpcuXaKhoQGj0ZgUMnu9XtxuN7/61a947bXX1PLa2lrKy8s1KzP0LbR18uTJ4uzZs3vMM0uSJMdBZohuOy0rK1vUW+bm5uZ/a11mgFAohM1mY8GCBaSmpiJJEj6fj9raWpqbmzGZTJoUoDfBYBCPx/MfMl+8eJGtW7fS1dWlWZmhn912zc3N4WCvjQUGg0H85S9/mR29NEf/xAIvQGNj43/skU5PT//xypUrp0YvHUQO2WoOWZZxOp04HA4kScJgMNDS0sKdO3cQRVGzAvQmGAwyZswY1q5dq5bduHGD9evX4/F4cDgcmn6WvoTu8vv94YMHD16WJKnHUamCgoIpNTU1s6KXY4mEKRgprQAlJSWn6+vrP+9eYTabUysqKirKy8tnEBmaFKFBqUVR5M6dO9y+fRuj0YgkSUyePJk5c+aoG4+SAYPBgMfj4cqVK2rZhAkT+NnPfoYsywQCgQTe3cD0JXQrENq4ceMPf/7zny+OgtR+4JbX65Vzc3PfSUapTSYTsixz7tw5Ghoa1F5s5syZ5Ofnq2NsraM8x86dO6mpqQEgJSWF7du3s3z5ctxuN16vN8F32Td9CS0BzYyu1HUksdSCIKiLJDU1Ndy4cQODwUA4HGbatGkUFhYC9DidokVEUcThcODz+Xj99deprq4GIs9XXl5OcXExbrebrq6uBN/pw+lvJ0wIXeoho2wwunTpEteuXUMURWRZZtKkSbhcLkRR1LzUBoMBu91OIBDg97//PefOnVPrNm/ezPPPP4/H49Gk1ANt7dKlHgbKXPOVK1e4fPkygiAgyzLZ2dksXLgQq9WaFFI7HA78fj9btmzhxIkTat2mTZt48cUXNSn1YPYq6lIPA5PJhMlk4uuvv+bChQuqvJmZmcyfP5/U1FQCgQCyHKvwJLFHGX4IgsCOHTt6SF1SUsKqVavweDx4PJ5+vsvoMtjNt7rUw0BZ4r516xbV1dWEQiHC4TBOp5OFCxfidDrVDUxaRZFalmXeeOMNjh8/rtatW7eOl19+ma6uLs1IPZTd5LrUw8BgMGAymWhsbOTs2bP4/ZH4OmlpaSxcuJCxY8eqm/+1iiiK2O12ALZv386xY8fUujVr1rBu3To8Hg9utztRt6gy1OMRutTDwGAwYDabaWlpoaqqSh13WiwWXC4X2dnZSSO10Whk9+7dHD16VK1btWoVJSUlmuiph3PeR5d6GCh7n9vb2zl16hSdnZ0IgoDRaKSoqIgpU6aoJ1u0ijL8EEWRHTt2cOTIEbVu5cqVbNiwIeE99XAPsOlSDwNRFDGZTHg8Hqqqqrh37x6CIGAwGMjPz2f69OlIkqRpqQVBwG63Y7Va2bt3L59++qlat2LFCkpLS+nq6kqY1CM5kalLPQyUntrn81FVVUVzc7N6MDY3N1cNOKNllOGHxWJh3759fPLJJ2pdcXExr776Kj6fLyHL5CM9YqxLPQwEQVCXmM+cOUNDQwMQ2bap5d65O0pPrUj90UcfqXW/+MUvyMjISMizxOLMvC71MFCkFgSB6upqTp06xcmTJ+no6EiKPdPwQOqUlBTeffddDh48yHfffcfHH39MW1tbQk7lxCoIxHCkHmkE/6FKnTvC9uKCsgBz7949fD5fUgSa6Y4gCDgcDiwWC4cOHWLdunUcOHAAs9mc1ELDIKU+fvz4tOilPQZtDkrq4uLiLGAcGk1JocxVJ0Ogmb5wOp2MGzcOg8FAdnY2NpstIfcR65/egFIXFRVNjn4ZqxwrA0q9fv36Z6KXmhRaJ3bEozvoV+qOjg5l5j2Wm4P7lbq+vv776JeJX8rSiSvxevtQpM7auHHjD62trTWrV6+e5vP5gqWlpV9HPxOLHCvdqQPwer1TcnNz3zly5MjN3Nxc16VLl86sXbv2dLQ9PcfKI47wsC2MMQxLZSTyAtj77KEXaIlVI73IBaY8pPwk0KZnktU2I80kG+/5oRDQRORwq5VIKjcf8f3VX0fkdHg2kTFza/Qe2uLYpo5GiHcPrTm0vKleZ+T010ObiaQStkavfUR6uViPfbujJJ13EOnFlaTzo74W/Kj8qn5UnmOw9DXLYQbGA9a8vDxTXl6eiYjY2TwQPNYUEEky74gmnbcRSUJfRCSKv47OgPQl9BiAo0ePTjl//vzi8+fPL/7nP/+pLIhkEXup04EJ+fn59vv37//pww8//Gt7e/uBbgsi+ehS6wyCvoROcTqdwpIlS2YIUX7yk5/M+Pzzz6dH62MtdQbAvn37lo4ZM2YKgMPhmHj48OE3dal1hkKfCys+nw9Jknpsl3r22Wcfi5PUIeiRZB6AlJSUzF5SF6BLrdMP/YYC++CDD/4d7jUt8Oyzzz526tSpx6KXsZK6FWD16tX/amxs7BGMUZE6Oq4eiy61Tj/0FwpMeuWVV+6+//77tb2lXrhw4fQYS90JNLS2toZcLldlU1NTXffKlJSUzPfee2+PLrXOQAwUCkxas2ZN8/vvv1/be5NRHKSuBW5///33gaKioopklFqSJPx+P36/n0AgkLRz3oFAgLa2NlpbW2lvb0+KmHwK/W1OCtJN6g8++KBuEFKPdBP9JZJUakmSCAQCZGVlkZOTg8lk0nx0pIchSRJut5ucnBx+85vfkJWVhdvtThqpB9ptFwTuMHipxzH6UheiAaklSSIzM5Onn36auXPnsmjRIjU+nNbPCHbH7/fjdDrZu3cvJSUlHDhwgJycnKSRerChwAaUuqqqKid6OWpSv/TSSxOB/0IjUgeDQfx+P6FQCKfTyfz580lPT9d8dKTuCIKAJElq7JDMzEz279/PrFmz6OzsTNr40L0ZUOoFCxb8eLSlPnDgQKVWpDYajbjdbk6fPo3f7yccDpOamsqCBQsYN24cgUBA04FkFMxmM263mz/84Q+0tEQ2RGZmZvL222/z+OOPa76nHmooMF3qPlBibrS2tlJVVaVGEDKbzcybN48f/ehHBINBTcsAD0Lp3rx5k82bN9Pc3AxEjli9++67PPXUU5ruqYcTCiyhUj9snlprUnd0dPDFF1/Q0dGhBpIpKChg6tSpSJKkealNJhM2m41bt26xefNm7ty5A4DVauXNN98kPz8ft9utxunTEsMNBZYwqV0uV+UgpU5IzmFFap/PxxdffMEPP/yAIAgIgsBTTz3FzJkzkyLniiJ1Q0MDJSUl3Lp1CwCbzcZbb73FvHnz8Hg8mpN6JKHAtC51AQmSWom5EQwGOX36tJoJC2DOnDk8+eSThEIhzc9VK1I3Nzfz2muvcfv2bQA1DNjTTz+N2+3G5/Ml+E4fMNJQYANKfe7cuVGV+uDBg3u0IrXZbEaWZU6fPq0mEgqHw+Tk5JCXl6cmEtK61Ha7naamJjZu3Mg333wDRN4NKioqWLRokaZ66liEAutX6qKiolGV2mq1pmtFaniQc6Wmpob6+no1PcW0adOYN28eoihqvqc2Go3Y7Xbu3r3Lpk2buH79OhAJB7x3716WLFmimZ46VqHAdKn7Qcki2z2RUDgcZuLEicybNw+z2az5BRhF6ra2NsrKyvjqq6+AyDvDrl27+OlPf4rH40m41LEMBTZUqUcaaGaoUs8dYXsjQomMdPXqVerq6hAEgXA4TFZWFvPnz1cTCSWD1Pfv3+d3v/sdly9fBiLDq+3bt7Ns2bKESx3rUGADSt0tFJgjBm32kPq777670L1SkXrx4sXpRI6POWPQ5rBRktffuHGDCxcuIEkSsiyTkZHBokWLcDgcmpdamaf2er2UlZVRVxdZGhBFkW3btiU8OWc8QoH1kLr3B+bNm6fEzIhVKDBV6vnz5+9pbm7+d/dKq9WaXlZWtih6mRmjNoeNkkiooaGB6upqvF4vsixjt9uZP38+NptN8yF1Fak9Hg/l5eXU1tYCkZ66rKyM5557Do/Hk5CpyXiEAnMABovFIixZsiS7d6XX61Veh2O1DpwSbZOVK1dOTU9P/3HvDzQ2NioRkzSR09dgMCCKIk1NTbS0tGAwGJAkCafTidPp1HQPraDkMXS73fz2t7/lxo0bQETqdevWqRm+RptYC50B2C0Wi3D16tXcadOm9RA6EAgEKysrlazosRhopRA5Fe4sLy+fUVFRUWE2m3vEnq6vr/+8pKTkdPRSE6HAlFwqc+bMYfLkyUiShNFo5Pbt2zQ1NSVNBFLlRXbZsmVMmDBBLf/yyy/p6upS852PJrGMnDSgzK+//nrNO++800Ektsf9EbY3KJlzc3Pf8Xq9MnCL+MYUGRTKGDk/P5+pU6ciyzIGg4GGhgY1QWci4ioPFa/Xi8fj4bnnnqOsrEwNTlRTU8POnTuRZTkhzxEroYcq890Rtjccmf9jPD+ahMNhdWxcWFjIpEmTVJlv3LhBXV2dmn9F6yjp237961+zefNmtby6upqtW7cSCATUbFmjTSyEzgRsQ5R5JOPnpJQ5GAxiMBgoLCxk/PjxyLKMKIpcu3aNK1euqC+LWkeR+fnnn2fTpk1q+blz59i2bRuBQAC73Z6Q4QaMXOhMwOZ0OoWLFy/qMj8ERWar1UpRUREZGRnIsowgCFy+fJmvvvoq6WR+8cUXKSkpUctPnDjBtm3b1PQUiXwHGInQuswDoOzVSEtLw+VyMWbMGMLhMOFwmIsXL3Lr1i1MJlNSJAnyeDx0dXWxatUq1q1bp5afOHGCHTt2aEJmGL7QuswDoMjsdDpxuVykpaWp4+jz58/T2NioLolrHUXml19+mTVr1qjlx48fZ+fOnQCakBmGJ7Qu8wAo2WDHjh1LYWEhFktkDcnv91NTU0NLS0vSyOx2u+nq6uKVV15h1apVavmxY8fYtWuXuhyuBZlh6ELrMg+AciJl/PjxFBQUqGPjrq4uzp49S1tbW9KkblN65pKSElauXKmWHz16lMrKSs3JDEMTWpd5AEKhEKFQiClTpjB37lxEUUQQBDo6Ojhz5gwejydpZFZ65g0bNrBixQq1/MiRI+zZsweLxYLD4dBccPzBCq3LPAChUAhJkpg+fTq5uQ9yfN67d0/ds5EseQgVmUtLSykuLlbLP/30U/bt24fVasVms2lOZhic0LrMg0CWZdLT01WZlb0a1dXVSJKE2WzWpAC9CQQC+P1+Xn311R4yf/LJJ+zfvx+LxYLdbtfsswwktC7zEAiFQni9XlJSUmhoaOD8+fM9cnonA6FQiIyMDJYvX66WffTRR/zxj38kJSVF0zJD/0LrMg8Bo9FIZ2cnJ0+eJC0tTd1FlwwLJt0xmUy0tbXx8ccfs3TpUv7xj39w6NChpJAZ+hY6jdGVGSL5BZNSZugZvsDn8yXNtFxvlJM1f/nLX/j73/9Oa2ur+gKYDPQltA2gqqpqzijJnAGMKy4uzkpGmRVEUUyKl76BsNlsavL5sWPHJvhuhkZfP32r0+kUZs+ePbF7YZxkhmiOlfXr1z+TrDLraIO+hA62t7eHOzo6upSCOMoM0cyy3ZLME73WZdYZEn0J7QcoLy+/ePPmzeabN2/e2bBhw9k4yQyRkyT+tWvXnj527Nj/trS0fPnZZ58d0mXWGSp9pUYWiIQa6J1mwgf8QGxlVhgDPPOQ8pjKrCev1zbxSl4fJpKOwsGD09l+oGMkjQ1AG3CSSAZbJen8HUZ+VEvn/xEP7aF1dJKV5J9j0tHphi60ziOFLrTOI4UutM4jhS60ziPF/wHgvbfirVNMHAAAAABJRU5ErkJggg==) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px #0000001a inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px #0006}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display: inline;*zoom: 1;vertical-align:top}.layui-layer-imguide,.layui-layer-imgbar{display:none}.layui-layer-imgprev,.layui-layer-imgnext{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:none;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px}.layui-layer-imgnext{right:10px;background-position:-5px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:#000c;background-color:#000 \\ ;filter:Alpha(opacity=80);color:#fff;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:0}.layui-layer-imgtit *{display:inline-block;*display: inline;*zoom: 1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}} "); System.addImportMap({ - imports: { - "jquery": "user:jquery", - "localforage": "user:localforage", - "toastify-js": "user:toastify-js", - "blueimp-md5": "user:blueimp-md5", - "viewerjs": "user:viewerjs", - "qrcodejs": "user:qrcodejs" - } + imports: { + "jquery": "user:jquery", + "localforage": "user:localforage", + "toastify-js": "user:toastify-js", + "blueimp-md5": "user:blueimp-md5", + "viewerjs": "user:viewerjs", + "qrcodejs": "user:qrcodejs" + } }); System.set("user:jquery", (() => { - const _ = jQuery; - ('default' in _) || (_.default = _); - return _ + const _ = jQuery; + ('default' in _) || (_.default = _); + return _ })()); System.set("user:localforage", (() => { - const _ = localforage; - ('default' in _) || (_.default = _); - return _ + const _ = localforage; + ('default' in _) || (_.default = _); + return _ })()); System.set("user:toastify-js", (() => { - const _ = Toastify; - ('default' in _) || (_.default = _); - return _ + const _ = Toastify; + ('default' in _) || (_.default = _); + return _ })()); System.set("user:blueimp-md5", (() => { - const _ = md5; - ('default' in _) || (_.default = _); - return _ + const _ = md5; + ('default' in _) || (_.default = _); + return _ })()); System.set("user:viewerjs", (() => { - const _ = Viewer; - ('default' in _) || (_.default = _); - return _ + const _ = Viewer; + ('default' in _) || (_.default = _); + return _ })()); System.set("user:qrcodejs", (() => { - const _ = QRCode; - ('default' in _) || (_.default = _); - return _ + const _ = QRCode; + ('default' in _) || (_.default = _); + return _ })()); System.register("./__entry.js", ['jquery', 'localforage', 'toastify-js', 'blueimp-md5', 'viewerjs', 'qrcodejs'], (function (exports, module) { 'use strict'; - var $$1, localforage$1, Toastify$1, md5$1, Viewer$1, QRCode$1; - return { - setters: [module => { - $$1 = module.default; - }, module => { - localforage$1 = module.default; - }, module => { - Toastify$1 = module.default; - }, module => { - md5$1 = module.default; - }, module => { - Viewer$1 = module.default; - }, module => { - QRCode$1 = module.default; - }], - execute: (async function () { + var $$1, localforage$1, Toastify$1, md5$1, Viewer$1, QRCode$1; + return { + setters: [module => { + $$1 = module.default; + }, module => { + localforage$1 = module.default; + }, module => { + Toastify$1 = module.default; + }, module => { + md5$1 = module.default; + }, module => { + Viewer$1 = module.default; + }, module => { + QRCode$1 = module.default; + }], + execute: (async function () { - var __defProp = Object.defineProperty; - var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { - enumerable: true, - configurable: true, - writable: true, - value - }) : obj[key] = value; - var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); - const scriptRel = /* @__PURE__ */ (function detectScriptRel() { - const relList = typeof document !== "undefined" && document.createElement("link").relList; - return relList && relList.supports && relList.supports("modulepreload") ? "modulepreload" : "preload"; - })(); - const assetsURL = function (dep) { - return "/" + dep; - }; - const seen = {}; - const __vitePreload = function preload(baseModule, deps, importerUrl) { - let promise = Promise.resolve(); - if (deps && deps.length > 0) { - let allSettled2 = function (promises) { - return Promise.all( - promises.map( - (p) => Promise.resolve(p).then( - (value) => ({status: "fulfilled", value}), - (reason) => ({status: "rejected", reason}) - ) - ) - ); - }; - document.getElementsByTagName("link"); - const cspNonceMeta = document.querySelector( - "meta[property=csp-nonce]" - ); - const cspNonce = (cspNonceMeta == null ? void 0 : cspNonceMeta.nonce) || (cspNonceMeta == null ? void 0 : cspNonceMeta.getAttribute("nonce")); - promise = allSettled2( - deps.map((dep) => { - dep = assetsURL(dep); - if (dep in seen) return; - seen[dep] = true; - const isCss = dep.endsWith(".css"); - const cssSelector = isCss ? '[rel="stylesheet"]' : ""; - if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) { - return; - } - const link = document.createElement("link"); - link.rel = isCss ? "stylesheet" : scriptRel; - if (!isCss) { - link.as = "script"; - } - link.crossOrigin = ""; - link.href = dep; - if (cspNonce) { - link.setAttribute("nonce", cspNonce); - } - document.head.appendChild(link); - if (isCss) { - return new Promise((res, rej) => { - link.addEventListener("load", res); - link.addEventListener( - "error", - () => rej(new Error(`Unable to preload CSS for ${dep}`)) - ); - }); - } - }) - ); + var __defProp = Object.defineProperty; + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { + enumerable: true, + configurable: true, + writable: true, + value + }) : obj[key] = value; + var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + const scriptRel = /* @__PURE__ */ (function detectScriptRel() { + const relList = typeof document !== "undefined" && document.createElement("link").relList; + return relList && relList.supports && relList.supports("modulepreload") ? "modulepreload" : "preload"; + })(); + const assetsURL = function (dep) { + return "/" + dep; + }; + const seen = {}; + const __vitePreload = function preload(baseModule, deps, importerUrl) { + let promise = Promise.resolve(); + if (deps && deps.length > 0) { + let allSettled2 = function (promises) { + return Promise.all( + promises.map( + (p) => Promise.resolve(p).then( + (value) => ({status: "fulfilled", value}), + (reason) => ({status: "rejected", reason}) + ) + ) + ); + }; + document.getElementsByTagName("link"); + const cspNonceMeta = document.querySelector( + "meta[property=csp-nonce]" + ); + const cspNonce = (cspNonceMeta == null ? void 0 : cspNonceMeta.nonce) || (cspNonceMeta == null ? void 0 : cspNonceMeta.getAttribute("nonce")); + promise = allSettled2( + deps.map((dep) => { + dep = assetsURL(dep); + if (dep in seen) return; + seen[dep] = true; + const isCss = dep.endsWith(".css"); + const cssSelector = isCss ? '[rel="stylesheet"]' : ""; + if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) { + return; } - - function handlePreloadError(err) { - const e = new Event("vite:preloadError", { - cancelable: true - }); - e.payload = err; - window.dispatchEvent(e); - if (!e.defaultPrevented) { - throw err; - } + const link = document.createElement("link"); + link.rel = isCss ? "stylesheet" : scriptRel; + if (!isCss) { + link.as = "script"; } + link.crossOrigin = ""; + link.href = dep; + if (cspNonce) { + link.setAttribute("nonce", cspNonce); + } + document.head.appendChild(link); + if (isCss) { + return new Promise((res, rej) => { + link.addEventListener("load", res); + link.addEventListener( + "error", + () => rej(new Error(`Unable to preload CSS for ${dep}`)) + ); + }); + } + }) + ); + } - return promise.then((res) => { - for (const item of res || []) { - if (item.status !== "rejected") continue; - handlePreloadError(item.reason); - } - return baseModule().catch(handlePreloadError); - }); - }; - var __defProp2 = Object.defineProperty, __typeError = (msg) => { - throw TypeError(msg); - }, __publicField2 = (obj, key, value) => ((obj2, key2, value2) => key2 in obj2 ? __defProp2(obj2, key2, { - enumerable: true, - configurable: true, - writable: true, - value: value2 - }) : obj2[key2] = value2)(obj, "symbol" != typeof key ? key + "" : key, value), - __privateMethod = (obj, member, method) => (((obj2, member2, msg) => { - member2.has(obj2) || __typeError("Cannot " + msg); - })(obj, member, "access private method"), method); - const currentHref$1 = window.location.href, isJavDb$1 = currentHref$1.includes("javdb"), - isJavBus$1 = currentHref$1.includes("javbus") || currentHref$1.includes("seejav") || currentHref$1.includes("bus") || currentHref$1.includes("javsee") || "javbus" === (() => { - try { - const _alt = $(".hidden-xs").attr("alt"); - return _alt ? _alt.trim().toLowerCase() : void 0; - } catch (_e) { - return void 0; - } - })(), - isSearchPage = currentHref$1.includes("/search?q") || currentHref$1.includes("/search/") || currentHref$1.includes("/users/"), - Status_RUNNING = "RUNNING", Status_SUCCESS = "SUCCESS", Status_FAIL = "FAIL", - Status_LOADING = "LOADING", Status_FILTER$1 = "filter", Status_FAVORITE$1 = "favorite", - Status_HAS_DOWN$1 = "hasDown", Status_HAS_WATCH$1 = "hasWatch", NO = "no", YES$1 = "yes", - qualityOptions = [{ - id: "video-mhb", - quality: "dmb_w", - text: "旧视频源-中画质宽版 (404p)", - canSelect: false - }, { - id: "video-mhb", - quality: "sm_s", - text: "旧视频源-低画质 (240p)", - canSelect: false - }, { - id: "video-mhb", - quality: "dm_s", - text: "旧视频源-中画质 (360p)", - canSelect: false - }, { - id: "video-mhb", - quality: "dmb_s", - text: "旧视频源-中画质 (480p)", - canSelect: false - }, { - id: "video-mhb", - quality: "mhb_w", - text: "旧视频源-高画质宽版 (404p)", - canSelect: false - }, { - id: "video-mmb", - quality: "mmb", - text: "中画质 (432p)", - canSelect: true - }, { - id: "video-mhb", - quality: "mhb", - text: "高画质 (576p)", - canSelect: true - }, { - id: "video-hmb", - quality: "hmb", - text: "HD (720p)", - canSelect: true - }, { - id: "video-hhb", - quality: "hhb", - text: "FullHD (1080p)", - canSelect: true - }, { - id: "video-hhbs", - quality: "hhbs", - text: "FullHD (1080p60fps)", - canSelect: true - }, { - id: "video-4k", - quality: "4k", - text: "4K (2160p)", - canSelect: true - }, { - id: "video-4ks", - quality: "4ks", - text: "4K (2160p60fps)", - canSelect: true - }]; - let detailPageCss$1 = ""; - window.location.href.includes("hideNav=1") && (detailPageCss$1 = "\n .navbar-default {\n display: none !important;\n }\n body {\n padding-top:0px!important;\n }\n "); - const javBusStyle = ` + function handlePreloadError(err) { + const e = new Event("vite:preloadError", { + cancelable: true + }); + e.payload = err; + window.dispatchEvent(e); + if (!e.defaultPrevented) { + throw err; + } + } + + return promise.then((res) => { + for (const item of res || []) { + if (item.status !== "rejected") continue; + handlePreloadError(item.reason); + } + return baseModule().catch(handlePreloadError); + }); + }; + var __defProp2 = Object.defineProperty, __typeError = (msg) => { + throw TypeError(msg); + }, __publicField2 = (obj, key, value) => ((obj2, key2, value2) => key2 in obj2 ? __defProp2(obj2, key2, { + enumerable: true, + configurable: true, + writable: true, + value: value2 + }) : obj2[key2] = value2)(obj, "symbol" != typeof key ? key + "" : key, value), + __privateMethod = (obj, member, method) => (((obj2, member2, msg) => { + member2.has(obj2) || __typeError("Cannot " + msg); + })(obj, member, "access private method"), method); + const currentHref$1 = window.location.href, isJavDb$1 = currentHref$1.includes("javdb"), + isJavBus$1 = currentHref$1.includes("javbus") || currentHref$1.includes("seejav") || currentHref$1.includes("bus") || currentHref$1.includes("javsee") || "javbus" === (() => { + try { + const _alt = $(".hidden-xs").attr("alt"); + return _alt ? _alt.trim().toLowerCase() : void 0; + } catch (_e) { + return void 0; + } + })(), + isSearchPage = currentHref$1.includes("/search?q") || currentHref$1.includes("/search/") || currentHref$1.includes("/users/"), + Status_RUNNING = "RUNNING", Status_SUCCESS = "SUCCESS", Status_FAIL = "FAIL", Status_LOADING = "LOADING", + Status_FILTER$1 = "filter", Status_FAVORITE$1 = "favorite", Status_HAS_DOWN$1 = "hasDown", + Status_HAS_WATCH$1 = "hasWatch", NO = "no", YES$1 = "yes", qualityOptions = [{ + id: "video-mhb", + quality: "dmb_w", + text: "旧视频源-中画质宽版 (404p)", + canSelect: false + }, { + id: "video-mhb", + quality: "sm_s", + text: "旧视频源-低画质 (240p)", + canSelect: false + }, { + id: "video-mhb", + quality: "dm_s", + text: "旧视频源-中画质 (360p)", + canSelect: false + }, { + id: "video-mhb", + quality: "dmb_s", + text: "旧视频源-中画质 (480p)", + canSelect: false + }, { + id: "video-mhb", + quality: "mhb_w", + text: "旧视频源-高画质宽版 (404p)", + canSelect: false + }, { + id: "video-mmb", + quality: "mmb", + text: "中画质 (432p)", + canSelect: true + }, { + id: "video-mhb", + quality: "mhb", + text: "高画质 (576p)", + canSelect: true + }, { + id: "video-hmb", + quality: "hmb", + text: "HD (720p)", + canSelect: true + }, { + id: "video-hhb", + quality: "hhb", + text: "FullHD (1080p)", + canSelect: true + }, { + id: "video-hhbs", + quality: "hhbs", + text: "FullHD (1080p60fps)", + canSelect: true + }, { + id: "video-4k", + quality: "4k", + text: "4K (2160p)", + canSelect: true + }, { + id: "video-4ks", + quality: "4ks", + text: "4K (2160p60fps)", + canSelect: true + }]; + let detailPageCss$1 = ""; + window.location.href.includes("hideNav=1") && (detailPageCss$1 = "\n .navbar-default {\n display: none !important;\n }\n body {\n padding-top:0px!important;\n }\n "); + const javBusStyle = ` `; - let detailPageCss = ""; - window.location.href.includes("hideNav=1") && (detailPageCss = "\n .main-nav,#search-bar-container {\n display: none !important;\n }\n \n html {\n padding-top:0px!important;\n }\n "); - const javdbStyle = ` + let detailPageCss = ""; + window.location.href.includes("hideNav=1") && (detailPageCss = "\n .main-nav,#search-bar-container {\n display: none !important;\n }\n \n html {\n padding-top:0px!important;\n }\n "); + const javdbStyle = ` `; - const mainCss = ` + const mainCss = ` `; - const subtitleModalCss = ` + const subtitleModalCss = ` `; - function insertStyle(css) { - if (css) if (css.includes("\n" - ); - insertStyle(mainCss); - insertStyle(subtitleModalCss); - window.$ = window.jQuery = $$1; - if (typeof $$1.trim !== "function") { - $$1.trim = function (text) { - return text == null ? "" : (text + "").trim(); - }; - } - if (typeof jQuery !== "undefined" && typeof layer === "undefined") { - await __vitePreload(() => module.import('./layer-npqWxmx4-BZXOsKge.js').then((n) => n.l), void 0); - } - window.localforage = localforage$1; - window.Toastify = Toastify$1; - window.md5 = md5$1; - window.Viewer = Viewer$1; - window.QRCode = QRCode$1; - window.currentHref = currentHref$1; - window.isJavDb = isJavDb$1; - window.isJavBus = isJavBus$1; - window.isSearchPage = isSearchPage; - window.Status_RUNNING = Status_RUNNING; - window.Status_SUCCESS = Status_SUCCESS; - window.Status_FAIL = Status_FAIL; - window.Status_LOADING = Status_LOADING; - window.Status_FILTER = Status_FILTER$1; - window.Status_FAVORITE = Status_FAVORITE$1; - window.Status_HAS_DOWN = Status_HAS_DOWN$1; - window.Status_HAS_WATCH = Status_HAS_WATCH$1; - window.NO = NO; - window.YES = YES$1; - const HAS_GM = typeof GM !== "undefined"; - const NEW_GM = ((scope, GM2) => { - if (typeof GM_info === "undefined" || GM_info.scriptHandler !== "Tampermonkey" || compareVersions(GM_info.version, "5.3.2") < 0) return; - const GM_xmlhttpRequestOrig = GM_xmlhttpRequest; - const GM_xmlHttpRequestOrig = GM2.xmlHttpRequest; + isJavBus$1 && insertStyle(javBusStyle); + isJavDb$1 && insertStyle(javdbStyle); + insertStyle( + "\n\n" + ); + insertStyle(mainCss); + insertStyle(subtitleModalCss); + window.$ = window.jQuery = $$1; + if (typeof $$1.trim !== "function") { + $$1.trim = function (text) { + return text == null ? "" : (text + "").trim(); + }; + } + if (typeof jQuery !== "undefined" && typeof layer === "undefined") { + await __vitePreload(() => module.import('./layer-npqWxmx4-BZXOsKge.js').then((n) => n.l), void 0); + } + window.localforage = localforage$1; + window.Toastify = Toastify$1; + window.md5 = md5$1; + window.Viewer = Viewer$1; + window.QRCode = QRCode$1; + window.currentHref = currentHref$1; + window.isJavDb = isJavDb$1; + window.isJavBus = isJavBus$1; + window.isSearchPage = isSearchPage; + window.Status_RUNNING = Status_RUNNING; + window.Status_SUCCESS = Status_SUCCESS; + window.Status_FAIL = Status_FAIL; + window.Status_LOADING = Status_LOADING; + window.Status_FILTER = Status_FILTER$1; + window.Status_FAVORITE = Status_FAVORITE$1; + window.Status_HAS_DOWN = Status_HAS_DOWN$1; + window.Status_HAS_WATCH = Status_HAS_WATCH$1; + window.NO = NO; + window.YES = YES$1; + const HAS_GM = typeof GM !== "undefined"; + const NEW_GM = ((scope, GM2) => { + if (typeof GM_info === "undefined" || GM_info.scriptHandler !== "Tampermonkey" || compareVersions(GM_info.version, "5.3.2") < 0) return; + const GM_xmlhttpRequestOrig = GM_xmlhttpRequest; + const GM_xmlHttpRequestOrig = GM2.xmlHttpRequest; - function compareVersions(v1, v2) { - const parts1 = v1.split(".").map(Number); - const parts2 = v2.split(".").map(Number); - const length = Math.max(parts1.length, parts2.length); - for (let i = 0; i < length; i++) { - const num1 = parts1[i] || 0; - const num2 = parts2[i] || 0; - if (num1 > num2) return 1; - if (num1 < num2) return -1; - } - return 0; - } + function compareVersions(v1, v2) { + const parts1 = v1.split(".").map(Number); + const parts2 = v2.split(".").map(Number); + const length = Math.max(parts1.length, parts2.length); + for (let i = 0; i < length; i++) { + const num1 = parts1[i] || 0; + const num2 = parts2[i] || 0; + if (num1 > num2) return 1; + if (num1 < num2) return -1; + } + return 0; + } - function GM_xmlhttpRequestWrapper(odetails) { - if (odetails.redirect !== void 0) { - return GM_xmlhttpRequestOrig(odetails); - } - if (odetails.onprogress || odetails.fetch === false) { - console.warn("Fetch mode does not support onprogress in the background."); - } - const { - onload, - onloadend, - onerror, - onabort, - ontimeout, - ...details - } = odetails; - const handleRedirects = (initialDetails) => { - const request = GM_xmlhttpRequestOrig({ - ...initialDetails, - redirect: "manual", - onload: function (response) { - if (response.status >= 300 && response.status < 400) { - const m = response.responseHeaders.match(/Location:\s*(\S+)/i); - const redirectUrl = m && m[1]; - if (redirectUrl) { - const absoluteUrl = new URL(redirectUrl, initialDetails.url).href; - handleRedirects({...initialDetails, url: absoluteUrl}); - return; - } - } - if (onload) onload.call(this, response); - if (onloadend) onloadend.call(this, response); - }, - onerror: function (response) { - if (onerror) onerror.call(this, response); - if (onloadend) onloadend.call(this, response); - }, - onabort: function (response) { - if (onabort) onabort.call(this, response); - if (onloadend) onloadend.call(this, response); - }, - ontimeout: function (response) { - if (ontimeout) ontimeout.call(this, response); - if (onloadend) onloadend.call(this, response); - } - }); - return request; - }; - return handleRedirects(details); + function GM_xmlhttpRequestWrapper(odetails) { + if (odetails.redirect !== void 0) { + return GM_xmlhttpRequestOrig(odetails); + } + if (odetails.onprogress || odetails.fetch === false) { + console.warn("Fetch mode does not support onprogress in the background."); + } + const { + onload, + onloadend, + onerror, + onabort, + ontimeout, + ...details + } = odetails; + const handleRedirects = (initialDetails) => { + const request = GM_xmlhttpRequestOrig({ + ...initialDetails, + redirect: "manual", + onload: function (response) { + if (response.status >= 300 && response.status < 400) { + const m = response.responseHeaders.match(/Location:\s*(\S+)/i); + const redirectUrl = m && m[1]; + if (redirectUrl) { + const absoluteUrl = new URL(redirectUrl, initialDetails.url).href; + handleRedirects({...initialDetails, url: absoluteUrl}); + return; + } } + if (onload) onload.call(this, response); + if (onloadend) onloadend.call(this, response); + }, + onerror: function (response) { + if (onerror) onerror.call(this, response); + if (onloadend) onloadend.call(this, response); + }, + onabort: function (response) { + if (onabort) onabort.call(this, response); + if (onloadend) onloadend.call(this, response); + }, + ontimeout: function (response) { + if (ontimeout) ontimeout.call(this, response); + if (onloadend) onloadend.call(this, response); + } + }); + return request; + }; + return handleRedirects(details); + } - function GM_xmlHttpRequestWrapper(odetails) { - let abort; - const p = new Promise((resolve, reject) => { - const {onload, ontimeout, onerror, ...send} = odetails; - send.onerror = function (r) { - if (onerror) { - resolve(r); - onerror.call(this, r); - } else { - reject(r); - } - }; - send.ontimeout = function (r) { - if (ontimeout) { - resolve(r); - ontimeout.call(this, r); - } else { - reject(r); - } - }; - send.onload = function (r) { - resolve(r); - if (onload) onload.call(this, r); - }; - const a = GM_xmlhttpRequestWrapper(send).abort; - if (abort === true) { - a(); - } else { - abort = a; - } - }); - p.abort = () => { - if (typeof abort === "function") { - abort(); - } else { - abort = true; - } - }; - return p; - } - - GM_xmlhttpRequest = GM_xmlhttpRequestWrapper; - scope.GM_xmlhttpRequestOrig = GM_xmlhttpRequestOrig; - const gopd = Object.getOwnPropertyDescriptor(GM2, "xmlHttpRequest"); - if (gopd && gopd.configurable === false) { - return { - __proto__: GM2, - xmlHttpRequest: GM_xmlHttpRequestWrapper, - xmlHttpRequestOrig: GM_xmlHttpRequestOrig - }; - } else { - GM2.xmlHttpRequest = GM_xmlHttpRequestWrapper; - GM2.xmlHttpRequestOrig = GM_xmlHttpRequestOrig; - } - })(globalThis, HAS_GM ? GM : {}); - if (HAS_GM && NEW_GM) GM = NEW_GM; - var _StorageManager_instances, setItem_fn, saveFilterItem_fn; - _StorageManager_instances = /* @__PURE__ */ new WeakSet(); - setItem_fn = async function (key, data) { - key === this.favorite_actresses_key && window.clean_cacheFavoriteActressList(); - key === this.blacklist_car_list_key && window.clean_cacheBlacklistCarList(); - key === this.setting_key && window.clean_cacheSettingObj(); - key === this.car_list_key && window.clean_cacheCarList(); - await this.forage.setItem(key, data); + function GM_xmlHttpRequestWrapper(odetails) { + let abort; + const p = new Promise((resolve, reject) => { + const {onload, ontimeout, onerror, ...send} = odetails; + send.onerror = function (r) { + if (onerror) { + resolve(r); + onerror.call(this, r); + } else { + reject(r); + } }; - saveFilterItem_fn = async function (items, storageKey, itemName) { - let itemList; - if (Array.isArray(items)) itemList = [...items]; - else { - itemList = await this.forage.getItem(storageKey) || []; - if (itemList.includes(items)) { - const errorMsg = `${items} ${itemName}已存在`; - show.error(errorMsg); - throw new Error(errorMsg); - } - itemList.push(items); - } - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, storageKey, itemList); - return itemList; + send.ontimeout = function (r) { + if (ontimeout) { + resolve(r); + ontimeout.call(this, r); + } else { + reject(r); + } }; - let StorageManager = class _StorageManager { - constructor() { - obj = this, (member = _StorageManager_instances).has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); - var obj, member, value; - __publicField2(this, "car_list_key", "car_list"); - __publicField2(this, "filter_keyword_title_key", "filter_keyword_title"); - __publicField2(this, "filter_keyword_review_key", "filter_keyword_review"); - __publicField2(this, "setting_key", "setting"); - __publicField2(this, "blacklist_key", "blacklist"); - __publicField2(this, "blacklist_car_list_key", "blacklist_car_list"); - __publicField2(this, "favorite_actresses_key", "favorite_actresses"); - __publicField2(this, "highlighted_tags_key", "highlighted_tags"); - __publicField2(this, "forage", localforage.createInstance({ - driver: localforage.INDEXEDDB, - name: "JAV-JHS", - version: 1, - storeName: "appData" - })); - __publicField2(this, "cacheCarList", null); - __publicField2(this, "cacheBlacklistCarList", null); - __publicField2(this, "cacheFavoriteActressList", null); - __publicField2(this, "cacheSettingObj", null); - if (_StorageManager.instance) throw new Error("StorageManager已被实例化过了!"); - _StorageManager.instance = this; - } - - async getCarList() { - if (this.cacheCarList) return utils.copyObj(this.cacheCarList); - this.cacheCarList = await this.forage.getItem(this.car_list_key) || []; - return utils.copyObj(this.cacheCarList); - } - - async getCar(carNum2) { - return (await this.getCarList()).find(((item) => item.carNum === carNum2)); - } - - _handleSingleCar(carParam, carList) { - let {carNum: carNum2, url, names, actionType, publishTime, starId} = carParam; - if (!carNum2) { - show.error("番号为空!"); - throw new Error("番号为空!"); - } - if (!url) { - show.error("url为空!"); - throw new Error("url为空!"); - } - url.includes("http") || (url = window.location.origin + url); - names && (names = names.trim()); - let carData = carList.find(((item) => item.carNum === carNum2)); - if (carData) { - names && (carData.names = names); - url && (carData.url = url); - publishTime && (carData.publishTime = publishTime); - carData.updateDate = utils.getNowStr(); - } else { - let nowStr = utils.getNowStr(); - carData = { - carNum: carNum2, - url, - names, - status: "", - createDate: nowStr, - updateDate: nowStr, - publishTime - }; - starId && (carData.starId = starId); - carList.push(carData); - } - switch (actionType) { - case Status_FILTER: - if (carData.status === Status_FILTER) { - const msg2 = `${carNum2} 已在屏蔽列表中`; - show.error(msg2); - throw new Error(msg2); - } - carData.status = Status_FILTER; - break; - case Status_FAVORITE: - if (carData.status === Status_FAVORITE) { - const msg2 = `${carNum2} 已在收藏列表中`; - show.error(msg2); - throw new Error(msg2); - } - carData.status = Status_FAVORITE; - break; - case Status_HAS_DOWN: - carData.status = Status_HAS_DOWN; - break; - case Status_HAS_WATCH: - carData.status = Status_HAS_WATCH; - break; - default: - const msg = "actionType错误, 请联系作者更正: " + actionType; - show.error(msg); - throw new Error(msg); - } - } - - async saveCar(carData) { - const carList = await this.forage.getItem(this.car_list_key) || []; - this._handleSingleCar(carData, carList); - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); - await this.removeNewVideoList([carData.carNum]); - } - - async updateCarInfo(carParam) { - let {carNum: carNum2, url, names, actionType, publishTime, remark} = carParam; - if (!carNum2) { - show.error("番号为空!"); - throw new Error("番号为空!"); - } - if (!url) { - show.error("url为空!"); - throw new Error("url为空!"); - } - names && (names = names.trim()); - const carList = await this.forage.getItem(this.car_list_key) || []; - let carData = carList.find(((item) => item.carNum === carNum2)); - if (!carData) { - const msg = "数据不存在: " + carNum2; - show.error(msg); - throw new Error(msg); - } - carData.names = names; - carData.url = url; - carData.remark = remark; - carData.updateDate = utils.getNowStr(); - switch (actionType) { - case Status_FILTER: - carData.status = Status_FILTER; - break; - case Status_FAVORITE: - carData.status = Status_FAVORITE; - break; - case Status_HAS_DOWN: - carData.status = Status_HAS_DOWN; - break; - case Status_HAS_WATCH: - carData.status = Status_HAS_WATCH; - break; - default: - const msg = "actionType错误, 请联系作者更正: " + actionType; - show.error(msg); - throw new Error(msg); - } - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); - } - - async saveCarList(carRecords) { - if (!carRecords || !Array.isArray(carRecords) || 0 === carRecords.length) { - show.error("记录列表为空!"); - throw new Error("记录列表为空!"); - } - const carList = await this.forage.getItem(this.car_list_key) || []; - for (const record of carRecords) try { - this._handleSingleCar(record, carList); - } catch (error) { - throw error; - } - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); - } - - async removeNewVideoList(carNumList) { - const favoriteActressesList = await this.getFavoriteActressList(); - let hasAnyListBeenModified = false; - const updatedActressList = favoriteActressesList.map(((actress) => { - if (!actress.newVideoList || !Array.isArray(actress.newVideoList)) return actress; - const newFilteredVideoList = actress.newVideoList.filter(((carNumString) => { - const isRemoved = carNumList.includes(carNumString); - if (isRemoved) { - clog.log("移除关联女优新作品", actress.name, carNumString); - hasAnyListBeenModified = true; - } - return !isRemoved; - })); - return { - ...actress, - newVideoList: newFilteredVideoList - }; - })); - hasAnyListBeenModified && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedActressList); - } - - async removeCar(carNum2) { - const carList = await this.getCarList(), initialLength = carList.length, - updatedList = carList.filter(((car) => car.carNum !== carNum2)); - if (updatedList.length === initialLength) { - show.error(`${carNum2} 不存在`); - return false; - } - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, updatedList); - return true; - } - - async batchRemoveCars(carNumList) { - if (!carNumList || 0 === carNumList.length) throw new Error("未传入参数"); - const carList = await this.getCarList(), initialLength = carList.length, - carNumsSet = new Set(carNumList), - updatedList = carList.filter(((car) => !carNumsSet.has(car.carNum))), - removedCount = initialLength - updatedList.length; - if (0 === removedCount) return removedCount; - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, updatedList); - return removedCount; - } - - async getBlacklist() { - return await this.forage.getItem(this.blacklist_key) || []; - } - - async addBlacklistItem(item) { - let {starId, name: name2, allName, role, movieType, url} = item; - if (!starId) throw new Error("缺失starId"); - if (!name2) throw new Error("缺失name"); - if (!role) throw new Error("缺失role"); - const blacklist = await this.getBlacklist(), - existData = blacklist.find(((item2) => item2.starId === starId)); - if (existData) { - existData.url = url; - existData.role = role; - existData.movieType = movieType; - clog.log("更新黑名单演员信息", existData); - } else { - const info = { - starId, - name: name2, - allName: allName || [name2], - createTime: utils.getNowStr(), - role, - movieType, - url - }; - blacklist.push(info); - clog.log("增加黑名单演员信息", info); - } - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, blacklist); - } - - async updateBlacklistItem(item) { - if (!item || !item.starId) throw new Error("参数不全"); - const filterActorActressInfoList = await this.getBlacklist(), - waitUpdateObj = filterActorActressInfoList.find(((i) => i.starId === item.starId)); - if (!waitUpdateObj) throw new Error(`未找到黑名单演员信息:${item.name} ${item.starId}`); - item.checkTime && (waitUpdateObj.checkTime = item.checkTime); - item.lastPublishTime && (waitUpdateObj.lastPublishTime = item.lastPublishTime); - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, filterActorActressInfoList); - } - - async deleteBlacklistItem(starId) { - const blacklist = await this.getBlacklist(), - updatedList = blacklist.filter(((item) => item.starId !== starId)); - blacklist.length !== updatedList.length && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, updatedList); - } - - async getBlacklistCarList() { - if (this.cacheBlacklistCarList && this.cacheBlacklistCarList.length > 0) return utils.deepFreeze(this.cacheBlacklistCarList); - this.cacheBlacklistCarList = await this.forage.getItem(this.blacklist_car_list_key) || []; - setTimeout((() => { - utils.deepFreeze(this.cacheBlacklistCarList); - }), 0); - return this.cacheBlacklistCarList; - } - - async batchSaveBlacklistCarList(carDataList) { - const carList = await this.getCarList(); - let blacklistCarList = await this.getBlacklistCarList(), hasChanged = false, - copyBlacklistCarList = null, carNumList = []; - for (const carData of carDataList) { - let existBlacklistCarData = blacklistCarList.find(((item) => item.carNum === carData.carNum)); - if (existBlacklistCarData) { - console.log("已在鉴定记录中", existBlacklistCarData); - continue; - } - let existCarData = carList.find(((item) => item.carNum === carData.carNum)); - if (existCarData) console.log("已在鉴定记录中", existCarData); - else { - copyBlacklistCarList || (copyBlacklistCarList = utils.copyObj(blacklistCarList)); - this._handleSingleCar(carData, copyBlacklistCarList); - clog.log(`屏蔽演员番号: ${carData.names} ${carData.carNum}`); - hasChanged = true; - carNumList.push(carData.carNum); - } - } - if (hasChanged) { - if (!copyBlacklistCarList) throw new Error("程序异常, 黑名单番号数据对象为空!"); - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, copyBlacklistCarList); - await this.removeNewVideoList(carNumList); - } - } - - async removeBlacklistCarList(starId) { - const filterActorActressCarList = await this.getBlacklistCarList(), - newList = filterActorActressCarList.filter(((car) => car.starId !== starId)); - newList.length !== filterActorActressCarList.length && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, newList); - } - - async batchRemoveBlacklistCars(carNumList) { - if (!carNumList || 0 === carNumList.length) throw new Error("未传入参数"); - const blacklistCarList = await this.getBlacklistCarList(), initialLength = blacklistCarList.length, - carNumsSet = new Set(carNumList), - updatedList = blacklistCarList.filter(((car) => !carNumsSet.has(car.carNum))), - removedCount = initialLength - updatedList.length; - if (0 === removedCount) return removedCount; - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, updatedList); - return removedCount; - } - - async getFavoriteActressList() { - if (this.cacheFavoriteActressList) return utils.copyObj(this.cacheFavoriteActressList); - this.cacheFavoriteActressList = await this.forage.getItem(this.favorite_actresses_key) || []; - return utils.copyObj(this.cacheFavoriteActressList); - } - - async addFavoriteActressList(actressList) { - const favoriteActressesInfoList = await this.getFavoriteActressList(); - let resultCount = 0; - for (const actress of actressList) { - let { - starId, - name: name2, - allName, - avatar, - lastCheckTime, - lastPublishTime, - actressType - } = actress; - if (!starId) throw new Error("缺失starId"); - if (!name2) throw new Error("缺失name"); - allName || (allName = [name2]); - const uncensoredText = "(無碼)"; - if (!actressType) { - actressType = name2.includes(uncensoredText) || allName.some(((element) => element.includes(uncensoredText))) ? "uncensored" : "censored"; - } - name2 = name2.replace(uncensoredText, ""); - allName = allName.map(((n) => n.replace(uncensoredText, ""))); - let favoriteActresses = favoriteActressesInfoList.find(((item) => item.starId === starId)); - if (favoriteActresses) { - if ((!favoriteActresses.avatar || !favoriteActresses.avatar.includes("https")) && avatar) { - clog.log(avatar); - favoriteActresses.avatar = avatar; - clog.log(`补全女优头像: ${name2}`); - resultCount++; - } - if (!favoriteActresses.actressType && actressType) { - favoriteActresses.actressType = actressType; - clog.log(`补全女优类别: ${name2} ${actressType}`); - resultCount++; - } - if (favoriteActresses.name.includes(uncensoredText)) { - favoriteActresses.name = name2; - favoriteActresses.allName = allName; - clog.log(`更正女优名字: ${name2} ${allName}`); - resultCount++; - } - continue; - } - const nowStr = utils.getNowStr(); - favoriteActressesInfoList.push({ - starId, - name: name2, - allName, - avatar, - lastCheckTime, - lastPublishTime, - createDate: nowStr, - updateDate: nowStr, - actressType - }); - clog.log(`同步JavDB已收藏的演员: ${name2}`); - resultCount++; - } - resultCount > 0 ? await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, favoriteActressesInfoList) : clog.log("信息已记录, 无需要进行同步收藏的演员"); - return resultCount; - } - - async removeFavoriteActress(starId) { - const favoriteActressesInfoList = await this.getFavoriteActressList(), - initialLength = favoriteActressesInfoList.length, - updatedList = favoriteActressesInfoList.filter(((car) => car.starId !== starId)); - if (updatedList.length === initialLength) { - clog.error(`移除演员失败, ${starId} 不存在`); - return false; - } - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedList); - return true; - } - - async updateFavoriteActress(actress) { - const favoriteActressesInfoList = await this.getFavoriteActressList(), { - starId, - name: name2, - allName, - avatar, - lastCheckTime, - newVideoList, - lastPublishTime, - actressType, - remark - } = actress; - if (!starId) throw new Error("缺失starId"); - let favoriteActresses = favoriteActressesInfoList.find(((item) => item.starId === starId)); - if (!favoriteActresses) { - clog.error("未找到演员信息", starId, name2); - return false; - } - name2 && (favoriteActresses.name = name2); - allName && (favoriteActresses.allName = allName); - avatar && (favoriteActresses.avatar = avatar); - null != actressType && (favoriteActresses.actressType = actressType); - lastCheckTime && (favoriteActresses.lastCheckTime = lastCheckTime); - newVideoList && (favoriteActresses.newVideoList = newVideoList); - lastPublishTime && (favoriteActresses.lastPublishTime = lastPublishTime); - remark && (favoriteActresses.remark = remark); - favoriteActresses.updateDate = utils.getNowStr(); - await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, favoriteActressesInfoList); - } - - async getHighlightedTags() { - return await this.forage.getItem(this.highlighted_tags_key) || []; - } - - async setHighlightedTags(highlightedTags) { - return await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.highlighted_tags_key, highlightedTags); - } - - async saveTitleFilterKeyword(keywords) { - await __privateMethod(this, _StorageManager_instances, saveFilterItem_fn).call(this, keywords, this.filter_keyword_title_key, "标题关键词"); - if (Array.isArray(keywords)) return null; - const favoriteActressesList = await this.getFavoriteActressList(); - let hasAnyListBeenModified = false; - const updatedActressList = favoriteActressesList.map(((actress) => { - if (!actress.newVideoList || !Array.isArray(actress.newVideoList)) return actress; - const newFilteredVideoList = actress.newVideoList.filter(((carNumString) => { - const isRemoved = carNumString.startsWith(keywords); - if (isRemoved) { - clog.log("移除关联女优新作品", actress.name, carNumString); - hasAnyListBeenModified = true; - } - return !isRemoved; - })); - return { - ...actress, - newVideoList: newFilteredVideoList - }; - })); - hasAnyListBeenModified && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedActressList); - } - - async getTitleFilterKeyword() { - return await this.forage.getItem(this.filter_keyword_title_key) || []; - } - - async getReviewFilterKeywordList() { - return await this.forage.getItem(this.filter_keyword_review_key) || []; - } - - async saveReviewFilterKeyword(keywords) { - return __privateMethod(this, _StorageManager_instances, saveFilterItem_fn).call(this, keywords, this.filter_keyword_review_key, "评论关键词"); - } - - async getSetting(attribute = null, defaultVal) { - this.cacheSettingObj || (this.cacheSettingObj = await this.forage.getItem(this.setting_key) || {}); - let settingObj = utils.copyObj(this.cacheSettingObj); - if (null === attribute) return settingObj; - const value = settingObj[attribute]; - return value ? "true" === value || "false" === value ? "true" === value.toLowerCase() : "string" != typeof value || "" === value.trim() || isNaN(Number(value)) ? value : Number(value) : defaultVal; - } - - async saveSetting(settingObj) { - settingObj ? await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.setting_key, settingObj) : show.error("设置对象为空"); - } - - async saveSettingItem(key, value) { - if (!key) { - show.error("key 不能为空"); - return; - } - let settingObj = await this.getSetting(); - settingObj[key] = value; - await this.saveSetting(settingObj); - } - - async importData(jsonData) { - await this.forage.clear(); - const importPromises = []; - for (const key in jsonData) { - const value = jsonData[key], - setPromise = __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, key, value); - importPromises.push(setPromise); - } - await Promise.all(importPromises); - } - - async exportData() { - const dataMap = {}; - await this.forage.iterate(((value, key) => { - dataMap[key] = value; - })); - if (0 === Object.keys(dataMap).length) throw new Error("没有可导出的数据"); - return dataMap; - } + send.onload = function (r) { + resolve(r); + if (onload) onload.call(this, r); }; - const apiUrl = "https://jdforrepam.com/api"; - - function buildSignature() { - const curr = Math.floor(Date.now() / 1e3), stored_sign = localStorage.getItem("jhs_jdsignature"); - if (stored_sign) { - const parts = stored_sign.split("."); - if (3 === parts.length) { - if (curr - parseInt(parts[0]) <= 300) return stored_sign; - } - } - const sign = `${curr}.lpw6vgqzsp.${md5(`${curr}71cf27bb3c0bcdf207b64abecddc970098c7421ee7203b9cdae54478478a199e7d5a6e1a57691123c1a931c057842fb73ba3b3c83bcd69c17ccf174081e3d8aa`)}`; - localStorage.setItem("jhs_jdsignature", sign); - return sign; + const a = GM_xmlhttpRequestWrapper(send).abort; + if (abort === true) { + a(); + } else { + abort = a; } + }); + p.abort = () => { + if (typeof abort === "function") { + abort(); + } else { + abort = true; + } + }; + return p; + } - const javDbApi = { - getReviews: async (movieId, pageNum = 1, pageSize = 20) => { - let url = `${apiUrl}/v1/movies/${movieId}/reviews`, headers = { - jdSignature: await buildSignature() - }; - return (await gmHttp.get(url, { - page: pageNum, - sort_by: "hotly", - limit: pageSize - }, headers)).data.reviews; - }, - searchMovie: async (keyword) => { - let url = `${apiUrl}/v2/search`, headers = { - "user-agent": "Dart/3.5 (dart:io)", - "accept-language": "zh-TW", - host: "jdforrepam.com", - jdsignature: await buildSignature() - }, params = { - q: keyword, - page: 1, - type: "movie", - limit: 1, - movie_type: "all", - from_recent: "false", - movie_filter_by: "all", - movie_sort_by: "relevance" - }; - return (await gmHttp.get(url, params, headers)).data.movies; - }, - getMovieDetail: async (movieId) => { - let url = `${apiUrl}/v4/movies/${movieId}`, headers = { - jdSignature: await buildSignature() - }; - const res = await gmHttp.get(url, null, headers); - if (!res.data) { - show.error("获取视频详情失败: " + res.message); - throw new Error(res.message); - } - const movie = res.data.movie, preview_images = movie.preview_images, imgList = []; - preview_images.forEach(((item) => { - imgList.push(item.large_url.replace("https://tp.spfcas.com/rhe951l4q", "https://c0.jdbstatic.com")); - })); - return { - movieId: movie.id, - actors: movie.actors, - duration: movie.duration, - title: movie.origin_title, - carNum: movie.number, - score: movie.score, - releaseDate: movie.release_date, - watchedCount: movie.watched_count, - imgList - }; - }, - related: async (movieId, page = 1, limit = 20) => { - let url = `${apiUrl}/v1/lists/related?movie_id=${movieId}&page=${page}&limit=${limit}`, headers = { - jdSignature: await buildSignature() - }; - const res = await gmHttp.get(url, null, headers), dataList = []; - res.data.lists.forEach(((item) => { - dataList.push({ - relatedId: item.id, - name: item.name, - movieCount: item.movies_count, - collectionCount: item.collections_count, - viewCount: item.views_count, - createTime: utils.formatDate(item.created_at) - }); - })); - return dataList; - }, - getMagnets: async (movieId) => { - let url = `${apiUrl}/v1/movies/${movieId}/magnets`, headers = { - jdSignature: await buildSignature() - }; - return (await gmHttp.get(url, null, headers)).data.magnets; - }, - playback: async (period = "daily", filter_by = "high_score") => { - let url = `${apiUrl}/v1/rankings/playback?period=${period}&filter_by=${filter_by}`, headers = { - jdSignature: await buildSignature() - }; - return (await gmHttp.get(url, null, headers)).data.movies; - }, - login: async (username, password) => { - let url = `${apiUrl}/v1/sessions?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&device_uuid=04b9534d-5118-53de-9f87-2ddded77111e&device_name=iPhone&device_model=iPhone&platform=ios&system_version=17.4&app_version=official&app_version_number=1.9.29&app_channel=official`, - headers = { - "user-agent": "Dart/3.5 (dart:io)", - "accept-language": "zh-TW", - "content-type": "multipart/form-data; boundary=--dio-boundary-2210433284", - jdsignature: await buildSignature() - }; - return await gmHttp.post(url, null, headers); - }, - top250: async (type = "all", type_value = "", page = 1, limit = 40) => { - let url = `${apiUrl}/v1/movies/top?start_rank=1&type=${type}&type_value=${type_value}&ignore_watched=false&page=${page}&limit=${limit}`, - headers = { - "user-agent": "Dart/3.5 (dart:io)", - "accept-language": "zh-TW", - host: "jdforrepam.com", - authorization: "Bearer " + localStorage.getItem("jhs_appAuthorization"), - jdsignature: await buildSignature() - }; - return await gmHttp.get(url, null, headers); - }, - buildSignature, - markDataListHtml: (movies) => { - let moviesHtml = ""; - movies.forEach(((movie) => { - moviesHtml += ` + GM_xmlhttpRequest = GM_xmlhttpRequestWrapper; + scope.GM_xmlhttpRequestOrig = GM_xmlhttpRequestOrig; + const gopd = Object.getOwnPropertyDescriptor(GM2, "xmlHttpRequest"); + if (gopd && gopd.configurable === false) { + return { + __proto__: GM2, + xmlHttpRequest: GM_xmlHttpRequestWrapper, + xmlHttpRequestOrig: GM_xmlHttpRequestOrig + }; + } else { + GM2.xmlHttpRequest = GM_xmlHttpRequestWrapper; + GM2.xmlHttpRequestOrig = GM_xmlHttpRequestOrig; + } + })(globalThis, HAS_GM ? GM : {}); + if (HAS_GM && NEW_GM) GM = NEW_GM; + var _StorageManager_instances, setItem_fn, saveFilterItem_fn; + _StorageManager_instances = /* @__PURE__ */ new WeakSet(); + setItem_fn = async function (key, data) { + key === this.favorite_actresses_key && window.clean_cacheFavoriteActressList(); + key === this.blacklist_car_list_key && window.clean_cacheBlacklistCarList(); + key === this.setting_key && window.clean_cacheSettingObj(); + key === this.car_list_key && window.clean_cacheCarList(); + await this.forage.setItem(key, data); + }; + saveFilterItem_fn = async function (items, storageKey, itemName) { + let itemList; + if (Array.isArray(items)) itemList = [...items]; + else { + itemList = await this.forage.getItem(storageKey) || []; + if (itemList.includes(items)) { + const errorMsg = `${items} ${itemName}已存在`; + show.error(errorMsg); + throw new Error(errorMsg); + } + itemList.push(items); + } + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, storageKey, itemList); + return itemList; + }; + let StorageManager = class _StorageManager { + constructor() { + obj = this, (member = _StorageManager_instances).has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); + var obj, member, value; + __publicField2(this, "car_list_key", "car_list"); + __publicField2(this, "filter_keyword_title_key", "filter_keyword_title"); + __publicField2(this, "filter_keyword_review_key", "filter_keyword_review"); + __publicField2(this, "setting_key", "setting"); + __publicField2(this, "blacklist_key", "blacklist"); + __publicField2(this, "blacklist_car_list_key", "blacklist_car_list"); + __publicField2(this, "favorite_actresses_key", "favorite_actresses"); + __publicField2(this, "highlighted_tags_key", "highlighted_tags"); + __publicField2(this, "forage", localforage.createInstance({ + driver: localforage.INDEXEDDB, + name: "JAV-JHS", + version: 1, + storeName: "appData" + })); + __publicField2(this, "cacheCarList", null); + __publicField2(this, "cacheBlacklistCarList", null); + __publicField2(this, "cacheFavoriteActressList", null); + __publicField2(this, "cacheSettingObj", null); + if (_StorageManager.instance) throw new Error("StorageManager已被实例化过了!"); + _StorageManager.instance = this; + } + + async getCarList() { + if (this.cacheCarList) return utils.copyObj(this.cacheCarList); + this.cacheCarList = await this.forage.getItem(this.car_list_key) || []; + return utils.copyObj(this.cacheCarList); + } + + async getCar(carNum2) { + return (await this.getCarList()).find(((item) => item.carNum === carNum2)); + } + + _handleSingleCar(carParam, carList) { + let {carNum: carNum2, url, names, actionType, publishTime, starId} = carParam; + if (!carNum2) { + show.error("番号为空!"); + throw new Error("番号为空!"); + } + if (!url) { + show.error("url为空!"); + throw new Error("url为空!"); + } + url.includes("http") || (url = window.location.origin + url); + names && (names = names.trim()); + let carData = carList.find(((item) => item.carNum === carNum2)); + if (carData) { + names && (carData.names = names); + url && (carData.url = url); + publishTime && (carData.publishTime = publishTime); + carData.updateDate = utils.getNowStr(); + } else { + let nowStr = utils.getNowStr(); + carData = { + carNum: carNum2, + url, + names, + status: "", + createDate: nowStr, + updateDate: nowStr, + publishTime + }; + starId && (carData.starId = starId); + carList.push(carData); + } + switch (actionType) { + case Status_FILTER: + if (carData.status === Status_FILTER) { + const msg2 = `${carNum2} 已在屏蔽列表中`; + show.error(msg2); + throw new Error(msg2); + } + carData.status = Status_FILTER; + break; + case Status_FAVORITE: + if (carData.status === Status_FAVORITE) { + const msg2 = `${carNum2} 已在收藏列表中`; + show.error(msg2); + throw new Error(msg2); + } + carData.status = Status_FAVORITE; + break; + case Status_HAS_DOWN: + carData.status = Status_HAS_DOWN; + break; + case Status_HAS_WATCH: + carData.status = Status_HAS_WATCH; + break; + default: + const msg = "actionType错误, 请联系作者更正: " + actionType; + show.error(msg); + throw new Error(msg); + } + } + + async saveCar(carData) { + const carList = await this.forage.getItem(this.car_list_key) || []; + this._handleSingleCar(carData, carList); + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); + await this.removeNewVideoList([carData.carNum]); + } + + async updateCarInfo(carParam) { + let {carNum: carNum2, url, names, actionType, publishTime, remark} = carParam; + if (!carNum2) { + show.error("番号为空!"); + throw new Error("番号为空!"); + } + if (!url) { + show.error("url为空!"); + throw new Error("url为空!"); + } + names && (names = names.trim()); + const carList = await this.forage.getItem(this.car_list_key) || []; + let carData = carList.find(((item) => item.carNum === carNum2)); + if (!carData) { + const msg = "数据不存在: " + carNum2; + show.error(msg); + throw new Error(msg); + } + carData.names = names; + carData.url = url; + carData.remark = remark; + carData.updateDate = utils.getNowStr(); + switch (actionType) { + case Status_FILTER: + carData.status = Status_FILTER; + break; + case Status_FAVORITE: + carData.status = Status_FAVORITE; + break; + case Status_HAS_DOWN: + carData.status = Status_HAS_DOWN; + break; + case Status_HAS_WATCH: + carData.status = Status_HAS_WATCH; + break; + default: + const msg = "actionType错误, 请联系作者更正: " + actionType; + show.error(msg); + throw new Error(msg); + } + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); + } + + async saveCarList(carRecords) { + if (!carRecords || !Array.isArray(carRecords) || 0 === carRecords.length) { + show.error("记录列表为空!"); + throw new Error("记录列表为空!"); + } + const carList = await this.forage.getItem(this.car_list_key) || []; + for (const record of carRecords) try { + this._handleSingleCar(record, carList); + } catch (error) { + throw error; + } + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, carList); + } + + async removeNewVideoList(carNumList) { + const favoriteActressesList = await this.getFavoriteActressList(); + let hasAnyListBeenModified = false; + const updatedActressList = favoriteActressesList.map(((actress) => { + if (!actress.newVideoList || !Array.isArray(actress.newVideoList)) return actress; + const newFilteredVideoList = actress.newVideoList.filter(((carNumString) => { + const isRemoved = carNumList.includes(carNumString); + if (isRemoved) { + clog.log("移除关联女优新作品", actress.name, carNumString); + hasAnyListBeenModified = true; + } + return !isRemoved; + })); + return { + ...actress, + newVideoList: newFilteredVideoList + }; + })); + hasAnyListBeenModified && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedActressList); + } + + async removeCar(carNum2) { + const carList = await this.getCarList(), initialLength = carList.length, + updatedList = carList.filter(((car) => car.carNum !== carNum2)); + if (updatedList.length === initialLength) { + show.error(`${carNum2} 不存在`); + return false; + } + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, updatedList); + return true; + } + + async batchRemoveCars(carNumList) { + if (!carNumList || 0 === carNumList.length) throw new Error("未传入参数"); + const carList = await this.getCarList(), initialLength = carList.length, carNumsSet = new Set(carNumList), + updatedList = carList.filter(((car) => !carNumsSet.has(car.carNum))), + removedCount = initialLength - updatedList.length; + if (0 === removedCount) return removedCount; + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.car_list_key, updatedList); + return removedCount; + } + + async getBlacklist() { + return await this.forage.getItem(this.blacklist_key) || []; + } + + async addBlacklistItem(item) { + let {starId, name: name2, allName, role, movieType, url} = item; + if (!starId) throw new Error("缺失starId"); + if (!name2) throw new Error("缺失name"); + if (!role) throw new Error("缺失role"); + const blacklist = await this.getBlacklist(), existData = blacklist.find(((item2) => item2.starId === starId)); + if (existData) { + existData.url = url; + existData.role = role; + existData.movieType = movieType; + clog.log("更新黑名单演员信息", existData); + } else { + const info = { + starId, + name: name2, + allName: allName || [name2], + createTime: utils.getNowStr(), + role, + movieType, + url + }; + blacklist.push(info); + clog.log("增加黑名单演员信息", info); + } + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, blacklist); + } + + async updateBlacklistItem(item) { + if (!item || !item.starId) throw new Error("参数不全"); + const filterActorActressInfoList = await this.getBlacklist(), + waitUpdateObj = filterActorActressInfoList.find(((i) => i.starId === item.starId)); + if (!waitUpdateObj) throw new Error(`未找到黑名单演员信息:${item.name} ${item.starId}`); + item.checkTime && (waitUpdateObj.checkTime = item.checkTime); + item.lastPublishTime && (waitUpdateObj.lastPublishTime = item.lastPublishTime); + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, filterActorActressInfoList); + } + + async deleteBlacklistItem(starId) { + const blacklist = await this.getBlacklist(), + updatedList = blacklist.filter(((item) => item.starId !== starId)); + blacklist.length !== updatedList.length && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_key, updatedList); + } + + async getBlacklistCarList() { + if (this.cacheBlacklistCarList && this.cacheBlacklistCarList.length > 0) return utils.deepFreeze(this.cacheBlacklistCarList); + this.cacheBlacklistCarList = await this.forage.getItem(this.blacklist_car_list_key) || []; + setTimeout((() => { + utils.deepFreeze(this.cacheBlacklistCarList); + }), 0); + return this.cacheBlacklistCarList; + } + + async batchSaveBlacklistCarList(carDataList) { + const carList = await this.getCarList(); + let blacklistCarList = await this.getBlacklistCarList(), hasChanged = false, copyBlacklistCarList = null, + carNumList = []; + for (const carData of carDataList) { + let existBlacklistCarData = blacklistCarList.find(((item) => item.carNum === carData.carNum)); + if (existBlacklistCarData) { + console.log("已在鉴定记录中", existBlacklistCarData); + continue; + } + let existCarData = carList.find(((item) => item.carNum === carData.carNum)); + if (existCarData) console.log("已在鉴定记录中", existCarData); + else { + copyBlacklistCarList || (copyBlacklistCarList = utils.copyObj(blacklistCarList)); + this._handleSingleCar(carData, copyBlacklistCarList); + clog.log(`屏蔽演员番号: ${carData.names} ${carData.carNum}`); + hasChanged = true; + carNumList.push(carData.carNum); + } + } + if (hasChanged) { + if (!copyBlacklistCarList) throw new Error("程序异常, 黑名单番号数据对象为空!"); + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, copyBlacklistCarList); + await this.removeNewVideoList(carNumList); + } + } + + async removeBlacklistCarList(starId) { + const filterActorActressCarList = await this.getBlacklistCarList(), + newList = filterActorActressCarList.filter(((car) => car.starId !== starId)); + newList.length !== filterActorActressCarList.length && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, newList); + } + + async batchRemoveBlacklistCars(carNumList) { + if (!carNumList || 0 === carNumList.length) throw new Error("未传入参数"); + const blacklistCarList = await this.getBlacklistCarList(), initialLength = blacklistCarList.length, + carNumsSet = new Set(carNumList), + updatedList = blacklistCarList.filter(((car) => !carNumsSet.has(car.carNum))), + removedCount = initialLength - updatedList.length; + if (0 === removedCount) return removedCount; + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.blacklist_car_list_key, updatedList); + return removedCount; + } + + async getFavoriteActressList() { + if (this.cacheFavoriteActressList) return utils.copyObj(this.cacheFavoriteActressList); + this.cacheFavoriteActressList = await this.forage.getItem(this.favorite_actresses_key) || []; + return utils.copyObj(this.cacheFavoriteActressList); + } + + async addFavoriteActressList(actressList) { + const favoriteActressesInfoList = await this.getFavoriteActressList(); + let resultCount = 0; + for (const actress of actressList) { + let {starId, name: name2, allName, avatar, lastCheckTime, lastPublishTime, actressType} = actress; + if (!starId) throw new Error("缺失starId"); + if (!name2) throw new Error("缺失name"); + allName || (allName = [name2]); + const uncensoredText = "(無碼)"; + if (!actressType) { + actressType = name2.includes(uncensoredText) || allName.some(((element) => element.includes(uncensoredText))) ? "uncensored" : "censored"; + } + name2 = name2.replace(uncensoredText, ""); + allName = allName.map(((n) => n.replace(uncensoredText, ""))); + let favoriteActresses = favoriteActressesInfoList.find(((item) => item.starId === starId)); + if (favoriteActresses) { + if ((!favoriteActresses.avatar || !favoriteActresses.avatar.includes("https")) && avatar) { + clog.log(avatar); + favoriteActresses.avatar = avatar; + clog.log(`补全女优头像: ${name2}`); + resultCount++; + } + if (!favoriteActresses.actressType && actressType) { + favoriteActresses.actressType = actressType; + clog.log(`补全女优类别: ${name2} ${actressType}`); + resultCount++; + } + if (favoriteActresses.name.includes(uncensoredText)) { + favoriteActresses.name = name2; + favoriteActresses.allName = allName; + clog.log(`更正女优名字: ${name2} ${allName}`); + resultCount++; + } + continue; + } + const nowStr = utils.getNowStr(); + favoriteActressesInfoList.push({ + starId, + name: name2, + allName, + avatar, + lastCheckTime, + lastPublishTime, + createDate: nowStr, + updateDate: nowStr, + actressType + }); + clog.log(`同步JavDB已收藏的演员: ${name2}`); + resultCount++; + } + resultCount > 0 ? await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, favoriteActressesInfoList) : clog.log("信息已记录, 无需要进行同步收藏的演员"); + return resultCount; + } + + async removeFavoriteActress(starId) { + const favoriteActressesInfoList = await this.getFavoriteActressList(), + initialLength = favoriteActressesInfoList.length, + updatedList = favoriteActressesInfoList.filter(((car) => car.starId !== starId)); + if (updatedList.length === initialLength) { + clog.error(`移除演员失败, ${starId} 不存在`); + return false; + } + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedList); + return true; + } + + async updateFavoriteActress(actress) { + const favoriteActressesInfoList = await this.getFavoriteActressList(), { + starId, + name: name2, + allName, + avatar, + lastCheckTime, + newVideoList, + lastPublishTime, + actressType, + remark + } = actress; + if (!starId) throw new Error("缺失starId"); + let favoriteActresses = favoriteActressesInfoList.find(((item) => item.starId === starId)); + if (!favoriteActresses) { + clog.error("未找到演员信息", starId, name2); + return false; + } + name2 && (favoriteActresses.name = name2); + allName && (favoriteActresses.allName = allName); + avatar && (favoriteActresses.avatar = avatar); + null != actressType && (favoriteActresses.actressType = actressType); + lastCheckTime && (favoriteActresses.lastCheckTime = lastCheckTime); + newVideoList && (favoriteActresses.newVideoList = newVideoList); + lastPublishTime && (favoriteActresses.lastPublishTime = lastPublishTime); + remark && (favoriteActresses.remark = remark); + favoriteActresses.updateDate = utils.getNowStr(); + await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, favoriteActressesInfoList); + } + + async getHighlightedTags() { + return await this.forage.getItem(this.highlighted_tags_key) || []; + } + + async setHighlightedTags(highlightedTags) { + return await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.highlighted_tags_key, highlightedTags); + } + + async saveTitleFilterKeyword(keywords) { + await __privateMethod(this, _StorageManager_instances, saveFilterItem_fn).call(this, keywords, this.filter_keyword_title_key, "标题关键词"); + if (Array.isArray(keywords)) return null; + const favoriteActressesList = await this.getFavoriteActressList(); + let hasAnyListBeenModified = false; + const updatedActressList = favoriteActressesList.map(((actress) => { + if (!actress.newVideoList || !Array.isArray(actress.newVideoList)) return actress; + const newFilteredVideoList = actress.newVideoList.filter(((carNumString) => { + const isRemoved = carNumString.startsWith(keywords); + if (isRemoved) { + clog.log("移除关联女优新作品", actress.name, carNumString); + hasAnyListBeenModified = true; + } + return !isRemoved; + })); + return { + ...actress, + newVideoList: newFilteredVideoList + }; + })); + hasAnyListBeenModified && await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.favorite_actresses_key, updatedActressList); + } + + async getTitleFilterKeyword() { + return await this.forage.getItem(this.filter_keyword_title_key) || []; + } + + async getReviewFilterKeywordList() { + return await this.forage.getItem(this.filter_keyword_review_key) || []; + } + + async saveReviewFilterKeyword(keywords) { + return __privateMethod(this, _StorageManager_instances, saveFilterItem_fn).call(this, keywords, this.filter_keyword_review_key, "评论关键词"); + } + + async getSetting(attribute = null, defaultVal) { + this.cacheSettingObj || (this.cacheSettingObj = await this.forage.getItem(this.setting_key) || {}); + let settingObj = utils.copyObj(this.cacheSettingObj); + if (null === attribute) return settingObj; + const value = settingObj[attribute]; + return value ? "true" === value || "false" === value ? "true" === value.toLowerCase() : "string" != typeof value || "" === value.trim() || isNaN(Number(value)) ? value : Number(value) : defaultVal; + } + + async saveSetting(settingObj) { + settingObj ? await __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, this.setting_key, settingObj) : show.error("设置对象为空"); + } + + async saveSettingItem(key, value) { + if (!key) { + show.error("key 不能为空"); + return; + } + let settingObj = await this.getSetting(); + settingObj[key] = value; + await this.saveSetting(settingObj); + } + + async importData(jsonData) { + await this.forage.clear(); + const importPromises = []; + for (const key in jsonData) { + const value = jsonData[key], + setPromise = __privateMethod(this, _StorageManager_instances, setItem_fn).call(this, key, value); + importPromises.push(setPromise); + } + await Promise.all(importPromises); + } + + async exportData() { + const dataMap = {}; + await this.forage.iterate(((value, key) => { + dataMap[key] = value; + })); + if (0 === Object.keys(dataMap).length) throw new Error("没有可导出的数据"); + return dataMap; + } + }; + const apiUrl = "https://jdforrepam.com/api"; + + function buildSignature() { + const curr = Math.floor(Date.now() / 1e3), stored_sign = localStorage.getItem("jhs_jdsignature"); + if (stored_sign) { + const parts = stored_sign.split("."); + if (3 === parts.length) { + if (curr - parseInt(parts[0]) <= 300) return stored_sign; + } + } + const sign = `${curr}.lpw6vgqzsp.${md5(`${curr}71cf27bb3c0bcdf207b64abecddc970098c7421ee7203b9cdae54478478a199e7d5a6e1a57691123c1a931c057842fb73ba3b3c83bcd69c17ccf174081e3d8aa`)}`; + localStorage.setItem("jhs_jdsignature", sign); + return sign; + } + + const javDbApi = { + getReviews: async (movieId, pageNum = 1, pageSize = 20) => { + let url = `${apiUrl}/v1/movies/${movieId}/reviews`, headers = { + jdSignature: await buildSignature() + }; + return (await gmHttp.get(url, { + page: pageNum, + sort_by: "hotly", + limit: pageSize + }, headers)).data.reviews; + }, + searchMovie: async (keyword) => { + let url = `${apiUrl}/v2/search`, headers = { + "user-agent": "Dart/3.5 (dart:io)", + "accept-language": "zh-TW", + host: "jdforrepam.com", + jdsignature: await buildSignature() + }, params = { + q: keyword, + page: 1, + type: "movie", + limit: 1, + movie_type: "all", + from_recent: "false", + movie_filter_by: "all", + movie_sort_by: "relevance" + }; + return (await gmHttp.get(url, params, headers)).data.movies; + }, + getMovieDetail: async (movieId) => { + let url = `${apiUrl}/v4/movies/${movieId}`, headers = { + jdSignature: await buildSignature() + }; + const res = await gmHttp.get(url, null, headers); + if (!res.data) { + show.error("获取视频详情失败: " + res.message); + throw new Error(res.message); + } + const movie = res.data.movie, preview_images = movie.preview_images, imgList = []; + preview_images.forEach(((item) => { + imgList.push(item.large_url.replace("https://tp.spfcas.com/rhe951l4q", "https://c0.jdbstatic.com")); + })); + return { + movieId: movie.id, + actors: movie.actors, + duration: movie.duration, + title: movie.origin_title, + carNum: movie.number, + score: movie.score, + releaseDate: movie.release_date, + watchedCount: movie.watched_count, + imgList + }; + }, + related: async (movieId, page = 1, limit = 20) => { + let url = `${apiUrl}/v1/lists/related?movie_id=${movieId}&page=${page}&limit=${limit}`, headers = { + jdSignature: await buildSignature() + }; + const res = await gmHttp.get(url, null, headers), dataList = []; + res.data.lists.forEach(((item) => { + dataList.push({ + relatedId: item.id, + name: item.name, + movieCount: item.movies_count, + collectionCount: item.collections_count, + viewCount: item.views_count, + createTime: utils.formatDate(item.created_at) + }); + })); + return dataList; + }, + getMagnets: async (movieId) => { + let url = `${apiUrl}/v1/movies/${movieId}/magnets`, headers = { + jdSignature: await buildSignature() + }; + return (await gmHttp.get(url, null, headers)).data.magnets; + }, + playback: async (period = "daily", filter_by = "high_score") => { + let url = `${apiUrl}/v1/rankings/playback?period=${period}&filter_by=${filter_by}`, headers = { + jdSignature: await buildSignature() + }; + return (await gmHttp.get(url, null, headers)).data.movies; + }, + login: async (username, password) => { + let url = `${apiUrl}/v1/sessions?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&device_uuid=04b9534d-5118-53de-9f87-2ddded77111e&device_name=iPhone&device_model=iPhone&platform=ios&system_version=17.4&app_version=official&app_version_number=1.9.29&app_channel=official`, + headers = { + "user-agent": "Dart/3.5 (dart:io)", + "accept-language": "zh-TW", + "content-type": "multipart/form-data; boundary=--dio-boundary-2210433284", + jdsignature: await buildSignature() + }; + return await gmHttp.post(url, null, headers); + }, + top250: async (type = "all", type_value = "", page = 1, limit = 40) => { + let url = `${apiUrl}/v1/movies/top?start_rank=1&type=${type}&type_value=${type_value}&ignore_watched=false&page=${page}&limit=${limit}`, + headers = { + "user-agent": "Dart/3.5 (dart:io)", + "accept-language": "zh-TW", + host: "jdforrepam.com", + authorization: "Bearer " + localStorage.getItem("jhs_appAuthorization"), + jdsignature: await buildSignature() + }; + return await gmHttp.get(url, null, headers); + }, + buildSignature, + markDataListHtml: (movies) => { + let moviesHtml = ""; + movies.forEach(((movie) => { + moviesHtml += `
`; - })); - return moviesHtml; - } - }; - var _GM_openInTab = /* @__PURE__ */ (() => typeof GM_openInTab != "undefined" ? GM_openInTab : void 0)(); - var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)(); + })); + return moviesHtml; + } + }; + var _GM_openInTab = /* @__PURE__ */ (() => typeof GM_openInTab != "undefined" ? GM_openInTab : void 0)(); + var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)(); - class Utils { - constructor() { - __publicField2(this, "intervalContainer", {}); - __publicField2(this, "mimeTypes", { - txt: "text/plain", - html: "text/html", - css: "text/css", - csv: "text/csv", - json: "application/json", - xml: "application/xml", - jpg: "image/jpeg", - jpeg: "image/jpeg", - png: "image/png", - gif: "image/gif", - webp: "image/webp", - svg: "image/svg+xml", - pdf: "application/pdf", - doc: "application/msword", - docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - xls: "application/vnd.ms-excel", - xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - ppt: "application/vnd.ms-powerpoint", - pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", - zip: "application/zip", - rar: "application/x-rar-compressed", - "7z": "application/x-7z-compressed", - mp3: "audio/mpeg", - wav: "audio/wav", - mp4: "video/mp4", - webm: "video/webm", - ogg: "audio/ogg" - }); - __publicField2(this, "timers", /* @__PURE__ */ new Map()); - __publicField2(this, "insertStyle", ((css) => { - if (css) { - -1 === css.indexOf(""); - $("head").append(css); - } - })); - __publicField2(this, "layerIndexStack", []); - Utils.instance || (Utils.instance = this); - return Utils.instance; - } - - importResource(url) { - let tag; - if (url.indexOf("css") >= 0) { - tag = document.createElement("link"); - tag.setAttribute("rel", "stylesheet"); - tag.href = url; - } else { - tag = document.createElement("script"); - tag.setAttribute("type", "text/javascript"); - tag.src = url; - } - document.documentElement.appendChild(tag); - } - - openPage(url, title, shadeClose, event) { - if (!url) throw new Error("未传入url"); - shadeClose = shadeClose ?? true; - if (event && (event.ctrlKey || event.metaKey)) { - _GM_openInTab(url.includes("http") ? url : window.location.origin + url, { - insert: 0 - }); - return; - } - let finalUrl = url; - url.includes("/actors/") || url.includes("/star/") || (finalUrl = url.includes("?") ? `${url}&hideNav=1` : `${url}?hideNav=1`); - layer.open({ - type: 2, - title, - content: finalUrl, - scrollbar: false, - shadeClose, - area: this.getResponsiveArea(["85%", "90%"]), - isOutAnim: false, - anim: -1, - success: (layero, index) => { - this.setupEscClose(index); - } - }); - } - - _handleGlobalEscKey(e) { - if ("Escape" !== e.key && 27 !== e.keyCode) return; - if (0 === this.layerIndexStack.length) return; - const topLayerIndex = this.layerIndexStack[this.layerIndexStack.length - 1], - $layer = $(`#layui-layer${topLayerIndex}`); - let viewerExists = false; - if ($layer.find(".viewer-container").length > 0) viewerExists = true; - else { - const iframe = $layer.find(`#layui-layer-iframe${topLayerIndex}`)[0]; - if (iframe && iframe.contentDocument) try { - $(iframe.contentDocument).find(".viewer-container").length > 0 && (viewerExists = true); - } catch (error) { - clog.warn("无法检查跨域 iframe 内的 .viewer-container"); - } - } - if (!viewerExists) { - this.layerIndexStack.pop(); - typeof layer !== "undefined" && layer.close(topLayerIndex); - } - } - - setupEscClose(layerIndex) { - var _a2; - if (!this._boundHandler) { - this._boundHandler = this._handleGlobalEscKey.bind(this); - $(document).off("keydown.globalLayerEsc"); - $(document).on("keydown.globalLayerEsc", this._boundHandler); - } - -1 === this.layerIndexStack.indexOf(layerIndex) && this.layerIndexStack.push(layerIndex); - const $iframe = $(`#layui-layer-iframe${layerIndex}`), - eventNamespace = `keydown.layerEsc${layerIndex}`; - try { - const iframeDocument = null == (_a2 = $iframe[0]) ? void 0 : _a2.contentDocument; - if (iframeDocument) { - if ("yes" === $iframe.attr("data-esc-bound")) return; - $(iframeDocument).off(eventNamespace); - $(iframeDocument).on(eventNamespace, this._boundHandler); - $iframe.attr("data-esc-bound", "yes"); - } - } catch (e) { - clog.error("iframe监听失败 (跨域或未加载完毕):", e); - } - } - - closePage() { - storageManager.getSetting("needClosePage", "yes").then(((needClosePage) => { - if ("yes" !== needClosePage) return; - parent.document.documentElement.style.overflow = "auto"; - [".layui-layer-shade", ".layui-layer-move", ".layui-layer"].forEach((function (selector) { - const elements = parent.document.querySelectorAll(selector); - if (elements.length > 0) { - const elementToRemove = elements.length > 1 ? elements[elements.length - 1] : elements[0]; - elementToRemove.parentNode.removeChild(elementToRemove); - } - })); - window.close(); - })); - } - - loopDetector(condition, after, detectInterval = 20, timeout = 1e4, runWhenTimeout = true) { - const uuid = Math.random(), start = (/* @__PURE__ */ new Date()).getTime(), - stopAndRun = (shouldRun) => { - clearInterval(this.intervalContainer[uuid]); - shouldRun && after && after(); - delete this.intervalContainer[uuid]; - }; - this.intervalContainer[uuid] = setInterval((() => { - const timeElapsed = (/* @__PURE__ */ new Date()).getTime() - start; - condition() ? stopAndRun(true) : timeElapsed >= timeout && stopAndRun(runWhenTimeout); - }), detectInterval); - } - - rightClick(container, targetSelector, callback) { - let containerElement; - "string" == typeof container ? containerElement = document.querySelector(container) : container instanceof HTMLElement && (containerElement = container); - if (!containerElement) { - console.warn("rightClick(), 容器无效或未提供,将使用 document.body 进行全局委托。"); - containerElement = document.body; - } - "string" == typeof targetSelector && "" !== targetSelector.trim() ? containerElement.addEventListener("contextmenu", ((event) => { - const targetElement = event.target.closest(targetSelector); - targetElement && callback(event, targetElement); - })) : console.error("rightClick(), 必须提供有效的 targetSelector。"); - } - - q(event, msg, fun, cancelFun) { - let x, y; - if (event) { - x = event.clientX - 130; - y = event.clientY - 120; - } else { - x = window.innerWidth / 2 - 120; - y = window.innerHeight / 2 - 120; - } - let confirmIndex = layer.confirm(msg, { - offset: [y, x], - title: "提示", - btn: ["确定", "取消"], - shade: 0, - zIndex: 999999991 - }, (function () { - fun && fun(); - layer.close(confirmIndex); - }), (function () { - cancelFun && cancelFun(); - })); - } - - alert(event, msg, yesFun) { - let offset; - event && (offset = [event.clientX - 200, event.clientY - 120]); - let confirmIndex = layer.alert(msg, { - offset, - shade: 0, - zIndex: 999999991 - }, (function () { - yesFun && yesFun(); - layer.close(confirmIndex); - })); - } - - getNowStr(dateSplitStr = "-", timeSplitStr = ":", dateString = null) { - let now; - now = dateString ? new Date(dateString) : /* @__PURE__ */ new Date(); - const year = now.getFullYear(), month = String(now.getMonth() + 1).padStart(2, "0"), - day = String(now.getDate()).padStart(2, "0"), hours = String(now.getHours()).padStart(2, "0"), - minutes = String(now.getMinutes()).padStart(2, "0"), - seconds = String(now.getSeconds()).padStart(2, "0"); - return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; - } - - formatDate(date, dateSplitStr = "-", timeSplitStr = ":") { - let targetDate; - if (date instanceof Date) targetDate = date; - else { - if ("string" != typeof date) throw new Error("Invalid date input: must be Date object or date string"); - targetDate = new Date(date); - if (isNaN(targetDate.getTime())) throw new Error("Invalid date string"); - } - const year = targetDate.getFullYear(), month = String(targetDate.getMonth() + 1).padStart(2, "0"), - day = String(targetDate.getDate()).padStart(2, "0"), - hours = String(targetDate.getHours()).padStart(2, "0"), - minutes = String(targetDate.getMinutes()).padStart(2, "0"), - seconds = String(targetDate.getSeconds()).padStart(2, "0"); - return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; - } - - getHourDifference(date1, date2) { - const timestamp1 = date1.getTime(), timestamp2 = date2.getTime(), - differenceInHours = Math.abs(timestamp2 - timestamp1) / 36e5; - return Math.floor(differenceInHours); - } - - download(data, fileName) { - show.info("开始请求下载..."); - const fileExtension = fileName.split(".").pop().toLowerCase(); - let blob, mimeType = this.mimeTypes[fileExtension] || "application/octet-stream"; - if (data instanceof Blob) blob = data; - else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) blob = new Blob([data], { - type: mimeType - }); - else if ("string" == typeof data && data.startsWith("data:")) { - const byteString = atob(data.split(",")[1]), arrayBuffer = new ArrayBuffer(byteString.length), - uintArray = new Uint8Array(arrayBuffer); - for (let i = 0; i < byteString.length; i++) uintArray[i] = byteString.charCodeAt(i); - blob = new Blob([uintArray], { - type: mimeType - }); - } else blob = new Blob([data], { - type: mimeType - }); - const url = URL.createObjectURL(blob), a = document.createElement("a"); - a.href = url; - a.download = fileName; - document.body.appendChild(a); - a.click(); - setTimeout((() => { - document.body.removeChild(a); - URL.revokeObjectURL(url); - }), 100); - } - - smoothScrollToTop(duration = 500) { - return new Promise(((resolve) => { - const start = performance.now(), startPosition = window.pageYOffset; - window.requestAnimationFrame((function scrollStep(timestamp) { - const elapsed = timestamp - start, progress = Math.min(elapsed / duration, 1), - easeInOutCubic = progress < 0.5 ? 4 * progress * progress * progress : 1 - Math.pow(-2 * progress + 2, 3) / 2; - window.scrollTo(0, startPosition * (1 - easeInOutCubic)); - progress < 1 ? window.requestAnimationFrame(scrollStep) : resolve(); - })); - })); - } - - simpleId() { - return crypto.randomUUID().replace("-", ""); - } - - isUrl(urlString) { - try { - new URL(urlString); - return true; - } catch (_) { - return false; - } - } - - setHrefParam(key, val) { - const newUrl = new URL(window.location.href); - newUrl.searchParams.set(key, val); - window.history.pushState({}, "", newUrl.toString()); - } - - getUrlParam(url, key) { - const searchString = url.split("?")[1]; - if (!searchString) return null; - const regex = new RegExp(`(?:^|&)${key}=([^&]*)`), match = searchString.match(regex); - let value = ""; - match && match[1] && (value = decodeURIComponent(match[1].replace(/\+/g, " "))); - return value ? "true" === value || "false" === value ? "true" === value.toLowerCase() : "string" != typeof value || "" === value.trim() || isNaN(Number(value)) ? value : Number(value) : value; - } - - reBuildSignature() { - return javDbApi.buildSignature(); - } - - getResponsiveArea(defaultArea) { - const screenWidth = window.innerWidth; - return screenWidth >= 1200 ? defaultArea || this.getDefaultArea() : screenWidth >= 768 ? ["70%", "90%"] : ["95%", "95%"]; - } - - getDefaultArea() { - return ["85%", "90%"]; - } - - isMobile() { - const userAgent = navigator.userAgent.toLowerCase(); - return ["iphone", "ipod", "ipad", "android", "blackberry", "windows phone", "nokia", "webos", "opera mini", "mobile", "mobi", "tablet"].some(((keyword) => userAgent.includes(keyword))); - } - - copyToClipboard(type, text) { - navigator.clipboard.writeText(text).then((() => show.info(`${type}已复制到剪切板, ${text}`))).catch(((err) => console.error("复制失败: ", err))); - } - - htmlTo$dom(html) { - const parser = new DOMParser(); - return $(parser.parseFromString(html, "text/html")); - } - - addCookie(cookieStr, options = {}) { - const {maxAge = 604800, path = "/", domain = "", secure = false, sameSite = "Lax"} = options; - cookieStr.split(";").forEach(((cookie) => { - const trimmed = cookie.trim(); - if (trimmed) { - const parts = trimmed.split("="); - if (parts.length >= 2 && parts[0].trim()) { - let cookieParts = [`${parts[0].trim()}=${parts.slice(1).join("=")}`]; - maxAge > 0 && cookieParts.push(`max-age=${maxAge}`); - cookieParts.push(`path=${path}`); - domain && cookieParts.push(`domain=${domain}`); - secure && cookieParts.push("Secure"); - sameSite && cookieParts.push(`SameSite=${sameSite}`); - console.log("document.cookie = '" + cookieParts.join("; ") + "'"); - document.cookie = cookieParts.join("; "); - } - } - })); - } - - isHidden(el) { - const element = el.jquery ? el[0] : el; - return !element || (element.offsetWidth <= 0 && element.offsetHeight <= 0 || "none" === window.getComputedStyle(element).display); - } - - time(label = "default", unit = "s", precision = 2) { - if (this.timers.has(label)) { - const timer = this.timers.get(label), elapsedTime = performance.now() - timer.startTime; - let formattedTime, unitLabel; - if ("s" === timer.unit) { - formattedTime = (elapsedTime / 1e3).toFixed(timer.precision); - unitLabel = "秒"; - } else { - formattedTime = elapsedTime.toFixed(timer.precision); - unitLabel = "毫秒"; - } - this.timers.delete(label); - return `${label}: ${formattedTime}${unitLabel}`; - } - this.timers.set(label, { - startTime: performance.now(), - unit, - precision - }); - } - - sleep(ms = 1e3) { - return new Promise(((resolve) => setTimeout(resolve, ms))); - } - - genericSort(arr, sortRules, emptyLast = true) { - if (!Array.isArray(arr) || 0 === arr.length) return []; - if (!Array.isArray(sortRules) || 0 === sortRules.length) return [...arr]; - const sortedArr = [...arr], safeDateConvert = (value) => { - if (value instanceof Date) return value; - if ("string" == typeof value) { - const date = new Date(value); - if (!isNaN(date.getTime())) return date; - } - return value; - }; - return sortedArr.sort(((a, b) => { - for (const rule of sortRules) { - const {key, order = "asc"} = rule; - let valA = a, valB = b; - if (null != key) if ("function" == typeof key) { - valA = key(a); - valB = key(b); - } else { - valA = a && "object" == typeof a ? a[key] : void 0; - valB = b && "object" == typeof b ? b[key] : void 0; - } - const dateA = safeDateConvert(valA), dateB = safeDateConvert(valB); - let comparison = 0; - const aIsNull = null == valA, bIsNull = null == valB; - if (aIsNull && bIsNull) return 0; - if (aIsNull) return emptyLast ? 1 : -1; - if (bIsNull) return emptyLast ? 1 : -1; - comparison = dateA instanceof Date && dateB instanceof Date ? dateA.getTime() - dateB.getTime() : "number" == typeof valA && "number" == typeof valB ? valA - valB : "string" == typeof valA && "string" == typeof valB ? valA.localeCompare(valB) : String(valA).localeCompare(String(valB)); - "desc" === order && (comparison *= -1); - if (0 !== comparison) return comparison; - } - return 0; - })); - } - - async retry(fun, tryCount = 3) { - let runCount = 0; - for (; runCount < tryCount;) try { - const result = await fun(); - runCount > 0 && clog.debug(`[重试] 成功,共发起 ${runCount + 1} 次。`); - return result; - } catch (e) { - let errorString = String(e); - errorString.startsWith("Error: ") && (errorString = errorString.replace("Error: ", "")); - if (errorString.includes("Just a moment") || errorString.includes("重定向") || errorString.toLowerCase().includes("404 page not found") || errorString.toLowerCase().includes("404 not found")) throw e; - runCount++; - if (runCount === tryCount) { - clog.debug(`[重试] 达到最大重试次数 (${tryCount}),最终失败:`, e); - throw e; - } - clog.debug(`[重试] 准备第 ${runCount + 1} 次重试, 错误信息: ${errorString}`); - } - } - - copyObj(data) { - return JSON.parse(JSON.stringify(data)); - } - - deepFreeze(obj) { - if (null === obj || "object" != typeof obj || Object.isFrozen(obj)) return obj; - const propNames = Object.getOwnPropertyNames(obj); - for (const name2 of propNames) { - const value = obj[name2]; - value && "object" == typeof value && this.deepFreeze(value); - } - return Object.freeze(obj); - } + class Utils { + constructor() { + __publicField2(this, "intervalContainer", {}); + __publicField2(this, "mimeTypes", { + txt: "text/plain", + html: "text/html", + css: "text/css", + csv: "text/csv", + json: "application/json", + xml: "application/xml", + jpg: "image/jpeg", + jpeg: "image/jpeg", + png: "image/png", + gif: "image/gif", + webp: "image/webp", + svg: "image/svg+xml", + pdf: "application/pdf", + doc: "application/msword", + docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + xls: "application/vnd.ms-excel", + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ppt: "application/vnd.ms-powerpoint", + pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation", + zip: "application/zip", + rar: "application/x-rar-compressed", + "7z": "application/x-7z-compressed", + mp3: "audio/mpeg", + wav: "audio/wav", + mp4: "video/mp4", + webm: "video/webm", + ogg: "audio/ogg" + }); + __publicField2(this, "timers", /* @__PURE__ */ new Map()); + __publicField2(this, "insertStyle", ((css) => { + if (css) { + -1 === css.indexOf(""); + $("head").append(css); } + })); + __publicField2(this, "layerIndexStack", []); + Utils.instance || (Utils.instance = this); + return Utils.instance; + } - class AsyncQueue { - constructor() { - this.queue = Promise.resolve(); - } + importResource(url) { + let tag; + if (url.indexOf("css") >= 0) { + tag = document.createElement("link"); + tag.setAttribute("rel", "stylesheet"); + tag.href = url; + } else { + tag = document.createElement("script"); + tag.setAttribute("type", "text/javascript"); + tag.src = url; + } + document.documentElement.appendChild(tag); + } - addTask(fun) { - this.queue = this.queue.then((() => fun())).catch(((e) => { - console.error("执行异步队列任务失败:", e); - })); - } - - async waitAllFinished() { - return this.queue; - } + openPage(url, title, shadeClose, event) { + if (!url) throw new Error("未传入url"); + shadeClose = shadeClose ?? true; + if (event && (event.ctrlKey || event.metaKey)) { + _GM_openInTab(url.includes("http") ? url : window.location.origin + url, { + insert: 0 + }); + return; + } + let finalUrl = url; + url.includes("/actors/") || url.includes("/star/") || (finalUrl = url.includes("?") ? `${url}&hideNav=1` : `${url}?hideNav=1`); + layer.open({ + type: 2, + title, + content: finalUrl, + scrollbar: false, + shadeClose, + area: this.getResponsiveArea(["85%", "90%"]), + isOutAnim: false, + anim: -1, + success: (layero, index) => { + this.setupEscClose(index); } + }); + } - class GmHttp { - async get(url, params = {}, headers = {}, noRedirect) { - return this.gmRequest("GET", url, null, params, headers, noRedirect); - } + _handleGlobalEscKey(e) { + if ("Escape" !== e.key && 27 !== e.keyCode) return; + if (0 === this.layerIndexStack.length) return; + const topLayerIndex = this.layerIndexStack[this.layerIndexStack.length - 1], + $layer = $(`#layui-layer${topLayerIndex}`); + let viewerExists = false; + if ($layer.find(".viewer-container").length > 0) viewerExists = true; + else { + const iframe = $layer.find(`#layui-layer-iframe${topLayerIndex}`)[0]; + if (iframe && iframe.contentDocument) try { + $(iframe.contentDocument).find(".viewer-container").length > 0 && (viewerExists = true); + } catch (error) { + clog.warn("无法检查跨域 iframe 内的 .viewer-container"); + } + } + if (!viewerExists) { + this.layerIndexStack.pop(); + typeof layer !== "undefined" && layer.close(topLayerIndex); + } + } - post(url, data = {}, headers = {}) { - headers = { - "Content-Type": "application/json", - ...headers - }; - let jsonData = JSON.stringify(data); - return this.gmRequest("POST", url, jsonData, null, headers); - } + setupEscClose(layerIndex) { + var _a2; + if (!this._boundHandler) { + this._boundHandler = this._handleGlobalEscKey.bind(this); + $(document).off("keydown.globalLayerEsc"); + $(document).on("keydown.globalLayerEsc", this._boundHandler); + } + -1 === this.layerIndexStack.indexOf(layerIndex) && this.layerIndexStack.push(layerIndex); + const $iframe = $(`#layui-layer-iframe${layerIndex}`), eventNamespace = `keydown.layerEsc${layerIndex}`; + try { + const iframeDocument = null == (_a2 = $iframe[0]) ? void 0 : _a2.contentDocument; + if (iframeDocument) { + if ("yes" === $iframe.attr("data-esc-bound")) return; + $(iframeDocument).off(eventNamespace); + $(iframeDocument).on(eventNamespace, this._boundHandler); + $iframe.attr("data-esc-bound", "yes"); + } + } catch (e) { + clog.error("iframe监听失败 (跨域或未加载完毕):", e); + } + } - postForm(url, data = {}, headers = {}) { - headers || (headers = {}); - headers["Content-Type"] || (headers["Content-Type"] = "application/x-www-form-urlencoded"); - let body = ""; - data && Object.keys(data).length > 0 && (body = Object.entries(data).map((([key, value]) => `${key}=${value}`)).join("&")); - return this.gmRequest("POST", url, body, null, headers); - } + closePage() { + storageManager.getSetting("needClosePage", "yes").then(((needClosePage) => { + if ("yes" !== needClosePage) return; + parent.document.documentElement.style.overflow = "auto"; + [".layui-layer-shade", ".layui-layer-move", ".layui-layer"].forEach((function (selector) { + const elements = parent.document.querySelectorAll(selector); + if (elements.length > 0) { + const elementToRemove = elements.length > 1 ? elements[elements.length - 1] : elements[0]; + elementToRemove.parentNode.removeChild(elementToRemove); + } + })); + window.close(); + })); + } - postFileFormData(url, data = {}, headers = {}) { - headers || (headers = {}); - const boundary = `----WebKitFormBoundary${Math.random().toString(36).substring(2)}`; - headers["Content-Type"] = `multipart/form-data; boundary=${boundary}`; - let body = ""; - data && Object.keys(data).length > 0 && (body = Object.entries(data).map((([key, value]) => `--${boundary}\r + loopDetector(condition, after, detectInterval = 20, timeout = 1e4, runWhenTimeout = true) { + const uuid = Math.random(), start = (/* @__PURE__ */ new Date()).getTime(), stopAndRun = (shouldRun) => { + clearInterval(this.intervalContainer[uuid]); + shouldRun && after && after(); + delete this.intervalContainer[uuid]; + }; + this.intervalContainer[uuid] = setInterval((() => { + const timeElapsed = (/* @__PURE__ */ new Date()).getTime() - start; + condition() ? stopAndRun(true) : timeElapsed >= timeout && stopAndRun(runWhenTimeout); + }), detectInterval); + } + + rightClick(container, targetSelector, callback) { + let containerElement; + "string" == typeof container ? containerElement = document.querySelector(container) : container instanceof HTMLElement && (containerElement = container); + if (!containerElement) { + console.warn("rightClick(), 容器无效或未提供,将使用 document.body 进行全局委托。"); + containerElement = document.body; + } + "string" == typeof targetSelector && "" !== targetSelector.trim() ? containerElement.addEventListener("contextmenu", ((event) => { + const targetElement = event.target.closest(targetSelector); + targetElement && callback(event, targetElement); + })) : console.error("rightClick(), 必须提供有效的 targetSelector。"); + } + + q(event, msg, fun, cancelFun) { + let x, y; + if (event) { + x = event.clientX - 130; + y = event.clientY - 120; + } else { + x = window.innerWidth / 2 - 120; + y = window.innerHeight / 2 - 120; + } + let confirmIndex = layer.confirm(msg, { + offset: [y, x], + title: "提示", + btn: ["确定", "取消"], + shade: 0, + zIndex: 999999991 + }, (function () { + fun && fun(); + layer.close(confirmIndex); + }), (function () { + cancelFun && cancelFun(); + })); + } + + alert(event, msg, yesFun) { + let offset; + event && (offset = [event.clientX - 200, event.clientY - 120]); + let confirmIndex = layer.alert(msg, { + offset, + shade: 0, + zIndex: 999999991 + }, (function () { + yesFun && yesFun(); + layer.close(confirmIndex); + })); + } + + getNowStr(dateSplitStr = "-", timeSplitStr = ":", dateString = null) { + let now; + now = dateString ? new Date(dateString) : /* @__PURE__ */ new Date(); + const year = now.getFullYear(), month = String(now.getMonth() + 1).padStart(2, "0"), + day = String(now.getDate()).padStart(2, "0"), hours = String(now.getHours()).padStart(2, "0"), + minutes = String(now.getMinutes()).padStart(2, "0"), seconds = String(now.getSeconds()).padStart(2, "0"); + return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; + } + + formatDate(date, dateSplitStr = "-", timeSplitStr = ":") { + let targetDate; + if (date instanceof Date) targetDate = date; + else { + if ("string" != typeof date) throw new Error("Invalid date input: must be Date object or date string"); + targetDate = new Date(date); + if (isNaN(targetDate.getTime())) throw new Error("Invalid date string"); + } + const year = targetDate.getFullYear(), month = String(targetDate.getMonth() + 1).padStart(2, "0"), + day = String(targetDate.getDate()).padStart(2, "0"), + hours = String(targetDate.getHours()).padStart(2, "0"), + minutes = String(targetDate.getMinutes()).padStart(2, "0"), + seconds = String(targetDate.getSeconds()).padStart(2, "0"); + return `${[year, month, day].join(dateSplitStr)} ${[hours, minutes, seconds].join(timeSplitStr)}`; + } + + getHourDifference(date1, date2) { + const timestamp1 = date1.getTime(), timestamp2 = date2.getTime(), + differenceInHours = Math.abs(timestamp2 - timestamp1) / 36e5; + return Math.floor(differenceInHours); + } + + download(data, fileName) { + show.info("开始请求下载..."); + const fileExtension = fileName.split(".").pop().toLowerCase(); + let blob, mimeType = this.mimeTypes[fileExtension] || "application/octet-stream"; + if (data instanceof Blob) blob = data; + else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) blob = new Blob([data], { + type: mimeType + }); + else if ("string" == typeof data && data.startsWith("data:")) { + const byteString = atob(data.split(",")[1]), arrayBuffer = new ArrayBuffer(byteString.length), + uintArray = new Uint8Array(arrayBuffer); + for (let i = 0; i < byteString.length; i++) uintArray[i] = byteString.charCodeAt(i); + blob = new Blob([uintArray], { + type: mimeType + }); + } else blob = new Blob([data], { + type: mimeType + }); + const url = URL.createObjectURL(blob), a = document.createElement("a"); + a.href = url; + a.download = fileName; + document.body.appendChild(a); + a.click(); + setTimeout((() => { + document.body.removeChild(a); + URL.revokeObjectURL(url); + }), 100); + } + + smoothScrollToTop(duration = 500) { + return new Promise(((resolve) => { + const start = performance.now(), startPosition = window.pageYOffset; + window.requestAnimationFrame((function scrollStep(timestamp) { + const elapsed = timestamp - start, progress = Math.min(elapsed / duration, 1), + easeInOutCubic = progress < 0.5 ? 4 * progress * progress * progress : 1 - Math.pow(-2 * progress + 2, 3) / 2; + window.scrollTo(0, startPosition * (1 - easeInOutCubic)); + progress < 1 ? window.requestAnimationFrame(scrollStep) : resolve(); + })); + })); + } + + simpleId() { + return crypto.randomUUID().replace("-", ""); + } + + isUrl(urlString) { + try { + new URL(urlString); + return true; + } catch (_) { + return false; + } + } + + setHrefParam(key, val) { + const newUrl = new URL(window.location.href); + newUrl.searchParams.set(key, val); + window.history.pushState({}, "", newUrl.toString()); + } + + getUrlParam(url, key) { + const searchString = url.split("?")[1]; + if (!searchString) return null; + const regex = new RegExp(`(?:^|&)${key}=([^&]*)`), match = searchString.match(regex); + let value = ""; + match && match[1] && (value = decodeURIComponent(match[1].replace(/\+/g, " "))); + return value ? "true" === value || "false" === value ? "true" === value.toLowerCase() : "string" != typeof value || "" === value.trim() || isNaN(Number(value)) ? value : Number(value) : value; + } + + reBuildSignature() { + return javDbApi.buildSignature(); + } + + getResponsiveArea(defaultArea) { + const screenWidth = window.innerWidth; + return screenWidth >= 1200 ? defaultArea || this.getDefaultArea() : screenWidth >= 768 ? ["70%", "90%"] : ["95%", "95%"]; + } + + getDefaultArea() { + return ["85%", "90%"]; + } + + isMobile() { + const userAgent = navigator.userAgent.toLowerCase(); + return ["iphone", "ipod", "ipad", "android", "blackberry", "windows phone", "nokia", "webos", "opera mini", "mobile", "mobi", "tablet"].some(((keyword) => userAgent.includes(keyword))); + } + + copyToClipboard(type, text) { + navigator.clipboard.writeText(text).then((() => show.info(`${type}已复制到剪切板, ${text}`))).catch(((err) => console.error("复制失败: ", err))); + } + + htmlTo$dom(html) { + const parser = new DOMParser(); + return $(parser.parseFromString(html, "text/html")); + } + + addCookie(cookieStr, options = {}) { + const {maxAge = 604800, path = "/", domain = "", secure = false, sameSite = "Lax"} = options; + cookieStr.split(";").forEach(((cookie) => { + const trimmed = cookie.trim(); + if (trimmed) { + const parts = trimmed.split("="); + if (parts.length >= 2 && parts[0].trim()) { + let cookieParts = [`${parts[0].trim()}=${parts.slice(1).join("=")}`]; + maxAge > 0 && cookieParts.push(`max-age=${maxAge}`); + cookieParts.push(`path=${path}`); + domain && cookieParts.push(`domain=${domain}`); + secure && cookieParts.push("Secure"); + sameSite && cookieParts.push(`SameSite=${sameSite}`); + console.log("document.cookie = '" + cookieParts.join("; ") + "'"); + document.cookie = cookieParts.join("; "); + } + } + })); + } + + isHidden(el) { + const element = el.jquery ? el[0] : el; + return !element || (element.offsetWidth <= 0 && element.offsetHeight <= 0 || "none" === window.getComputedStyle(element).display); + } + + time(label = "default", unit = "s", precision = 2) { + if (this.timers.has(label)) { + const timer = this.timers.get(label), elapsedTime = performance.now() - timer.startTime; + let formattedTime, unitLabel; + if ("s" === timer.unit) { + formattedTime = (elapsedTime / 1e3).toFixed(timer.precision); + unitLabel = "秒"; + } else { + formattedTime = elapsedTime.toFixed(timer.precision); + unitLabel = "毫秒"; + } + this.timers.delete(label); + return `${label}: ${formattedTime}${unitLabel}`; + } + this.timers.set(label, { + startTime: performance.now(), + unit, + precision + }); + } + + sleep(ms = 1e3) { + return new Promise(((resolve) => setTimeout(resolve, ms))); + } + + genericSort(arr, sortRules, emptyLast = true) { + if (!Array.isArray(arr) || 0 === arr.length) return []; + if (!Array.isArray(sortRules) || 0 === sortRules.length) return [...arr]; + const sortedArr = [...arr], safeDateConvert = (value) => { + if (value instanceof Date) return value; + if ("string" == typeof value) { + const date = new Date(value); + if (!isNaN(date.getTime())) return date; + } + return value; + }; + return sortedArr.sort(((a, b) => { + for (const rule of sortRules) { + const {key, order = "asc"} = rule; + let valA = a, valB = b; + if (null != key) if ("function" == typeof key) { + valA = key(a); + valB = key(b); + } else { + valA = a && "object" == typeof a ? a[key] : void 0; + valB = b && "object" == typeof b ? b[key] : void 0; + } + const dateA = safeDateConvert(valA), dateB = safeDateConvert(valB); + let comparison = 0; + const aIsNull = null == valA, bIsNull = null == valB; + if (aIsNull && bIsNull) return 0; + if (aIsNull) return emptyLast ? 1 : -1; + if (bIsNull) return emptyLast ? 1 : -1; + comparison = dateA instanceof Date && dateB instanceof Date ? dateA.getTime() - dateB.getTime() : "number" == typeof valA && "number" == typeof valB ? valA - valB : "string" == typeof valA && "string" == typeof valB ? valA.localeCompare(valB) : String(valA).localeCompare(String(valB)); + "desc" === order && (comparison *= -1); + if (0 !== comparison) return comparison; + } + return 0; + })); + } + + async retry(fun, tryCount = 3) { + let runCount = 0; + for (; runCount < tryCount;) try { + const result = await fun(); + runCount > 0 && clog.debug(`[重试] 成功,共发起 ${runCount + 1} 次。`); + return result; + } catch (e) { + let errorString = String(e); + errorString.startsWith("Error: ") && (errorString = errorString.replace("Error: ", "")); + if (errorString.includes("Just a moment") || errorString.includes("重定向") || errorString.toLowerCase().includes("404 page not found") || errorString.toLowerCase().includes("404 not found")) throw e; + runCount++; + if (runCount === tryCount) { + clog.debug(`[重试] 达到最大重试次数 (${tryCount}),最终失败:`, e); + throw e; + } + clog.debug(`[重试] 准备第 ${runCount + 1} 次重试, 错误信息: ${errorString}`); + } + } + + copyObj(data) { + return JSON.parse(JSON.stringify(data)); + } + + deepFreeze(obj) { + if (null === obj || "object" != typeof obj || Object.isFrozen(obj)) return obj; + const propNames = Object.getOwnPropertyNames(obj); + for (const name2 of propNames) { + const value = obj[name2]; + value && "object" == typeof value && this.deepFreeze(value); + } + return Object.freeze(obj); + } + } + + class AsyncQueue { + constructor() { + this.queue = Promise.resolve(); + } + + addTask(fun) { + this.queue = this.queue.then((() => fun())).catch(((e) => { + console.error("执行异步队列任务失败:", e); + })); + } + + async waitAllFinished() { + return this.queue; + } + } + + class GmHttp { + async get(url, params = {}, headers = {}, noRedirect) { + return this.gmRequest("GET", url, null, params, headers, noRedirect); + } + + post(url, data = {}, headers = {}) { + headers = { + "Content-Type": "application/json", + ...headers + }; + let jsonData = JSON.stringify(data); + return this.gmRequest("POST", url, jsonData, null, headers); + } + + postForm(url, data = {}, headers = {}) { + headers || (headers = {}); + headers["Content-Type"] || (headers["Content-Type"] = "application/x-www-form-urlencoded"); + let body = ""; + data && Object.keys(data).length > 0 && (body = Object.entries(data).map((([key, value]) => `${key}=${value}`)).join("&")); + return this.gmRequest("POST", url, body, null, headers); + } + + postFileFormData(url, data = {}, headers = {}) { + headers || (headers = {}); + const boundary = `----WebKitFormBoundary${Math.random().toString(36).substring(2)}`; + headers["Content-Type"] = `multipart/form-data; boundary=${boundary}`; + let body = ""; + data && Object.keys(data).length > 0 && (body = Object.entries(data).map((([key, value]) => `--${boundary}\r Content-Disposition: form-data; name="${key}"\r \r ${value}\r `)).join("")); - body += `--${boundary}--`; - return this.gmRequest("POST", url, body, null, headers); - } + body += `--${boundary}--`; + return this.gmRequest("POST", url, body, null, headers); + } - async downloadFileInChunks(url, headers = {}) { - const httpTimeout = await storageManager.getSetting("httpTimeout", 5e3), - httpRetryCount = await storageManager.getSetting("httpRetryCount", 3); - clog.log("正在获取文件大小..."); - let fileSize, mimeType; - try { - const sizeResponse = await utils.retry((() => new Promise(((resolve, reject) => { - _GM_xmlhttpRequest({ - method: "GET", - url, - headers: { - ...headers, - Range: "bytes=0-0" - }, - timeout: httpTimeout, - onload: resolve, - onerror: (e) => reject(new Error("网络错误:无法获取文件大小")), - ontimeout: () => reject(new Error("超时:获取文件大小")) - }); - }))), httpRetryCount); - if (206 !== sizeResponse.status && 200 !== sizeResponse.status) throw new Error(`请求文件大小失败,状态码: ${sizeResponse.status}`); - { - const rangeHeader = sizeResponse.responseHeaders.match(/content-range:\s*bytes\s*\d+-\d+\/(\d+)/i), - typeHeader = sizeResponse.responseHeaders.match(/content-type:\s*([^\s;]+)/i); - if (rangeHeader && rangeHeader[1]) fileSize = parseInt(rangeHeader[1], 10); - else { - if (!sizeResponse.responseHeaders.match(/content-length:\s*(\d+)/i) || 200 !== sizeResponse.status) throw new Error("无法从响应头中获取文件总大小,服务器可能不支持 Range 请求。"); - { - const lengthHeader = sizeResponse.responseHeaders.match(/content-length:\s*(\d+)/i); - fileSize = parseInt(lengthHeader[1], 10); - clog.warn("服务器返回 200 状态码,可能不支持 Range 请求。将尝试完整下载。"); - } - } - typeHeader && typeHeader[1] && (mimeType = typeHeader[1]); - clog.log(`文件总大小:${(fileSize / 1024 / 1024).toFixed(2)} MB, MIME 类型: ${mimeType || "未知"}`); - } - } catch (e) { - clog.error("获取文件大小失败:", e.message); - throw e; - } - if (!fileSize || fileSize <= 0) throw new Error("获取到的文件大小无效或服务器拒绝提供大小信息。"); - const numChunks = Math.ceil(fileSize / 1048576), chunkPromises = [], - downloadedChunks = new Array(numChunks); - clog.log(`文件将被分为 ${numChunks} 块进行下载 (每块约 ${1.toFixed(2)} MB)`); - for (let i = 0; i < numChunks; i++) { - const start = 1048576 * i, - rangeHeader = `bytes=${start}-${Math.min(start + 1048576 - 1, fileSize - 1)}`, - chunkPromise = await utils.retry((() => new Promise(((resolve, reject) => { - const currentHeaders = { - ...headers, - Range: rangeHeader, - Accept: "application/octet-stream" - }; - _GM_xmlhttpRequest({ - method: "GET", - url, - headers: currentHeaders, - timeout: httpTimeout, - responseType: "arraybuffer", - onload: (response) => { - if (206 === response.status || 200 === response.status) if (response.response instanceof ArrayBuffer) { - downloadedChunks[i] = response.response; - clog.log(`成功下载第 ${i + 1}/${numChunks} 块 (${rangeHeader})`); - resolve(); - } else reject(new Error(`第 ${i + 1} 块响应不是 ArrayBuffer。`)); - else reject(new Error(`第 ${i + 1} 块请求失败,状态码: ${response.status}`)); - }, - onerror: (error) => reject(new Error(`第 ${i + 1} 块网络错误: ${error.error}`)), - ontimeout: () => reject(new Error(`第 ${i + 1} 块超时。`)) - }); - }))), httpRetryCount); - chunkPromises.push(chunkPromise); - } - try { - await Promise.all(chunkPromises); - clog.log("所有分块下载完成,开始合并..."); - } catch (e) { - clog.error("分块下载过程中发生错误:", e.message); - throw e; - } - const finalBlob = new Blob(downloadedChunks); - finalBlob.size !== fileSize && clog.warn(`警告:合并后的 Blob 大小 (${finalBlob.size}) 与预期文件大小 (${fileSize}) 不匹配!`); - return await finalBlob.text(); - } - - async gmRequest(method, url, data = {}, params = {}, headers = {}, noRedirect = false) { - if (params && Object.keys(params).length) { - const queryString = new URLSearchParams(params).toString(); - url += (url.includes("?") ? "&" : "?") + queryString; - } - const httpTimeout = await storageManager.getSetting("httpTimeout", 5e3), - httpRetryCount = await storageManager.getSetting("httpRetryCount", 3); - data || (data = void 0); - return await utils.retry((() => new Promise(((resolve, reject) => { - _GM_xmlhttpRequest({ - method, - url, - headers, - timeout: httpTimeout, - data, - onload: (response) => { - try { - noRedirect && response.finalUrl !== url && reject("请求被重定向了,URL是:" + response.finalUrl); - if (response.status >= 200 && response.status < 300) if (response.responseText) try { - resolve(JSON.parse(response.responseText)); - } catch (e) { - resolve(response.responseText); - } - else resolve(response.responseText || response); - else { - clog.error("请求失败,状态码:", response.status, url); - if (response.responseText) try { - const errorData = JSON.parse(response.responseText); - reject(errorData); - } catch { - reject(new Error(response.responseText || `请求发生错误 ${response.status}`)); - } - else reject(new Error(`请求发生错误 ${response.status}`)); - } - } catch (e) { - reject(e); - } - }, - onerror: (error) => { - clog.error("网络错误:", url); - reject(new Error(error.error || "网络错误")); - }, - ontimeout: () => { - reject(new Error("请求超时: " + url)); - } - }); - }))), httpRetryCount); + async downloadFileInChunks(url, headers = {}) { + const httpTimeout = await storageManager.getSetting("httpTimeout", 5e3), + httpRetryCount = await storageManager.getSetting("httpRetryCount", 3); + clog.log("正在获取文件大小..."); + let fileSize, mimeType; + try { + const sizeResponse = await utils.retry((() => new Promise(((resolve, reject) => { + _GM_xmlhttpRequest({ + method: "GET", + url, + headers: { + ...headers, + Range: "bytes=0-0" + }, + timeout: httpTimeout, + onload: resolve, + onerror: (e) => reject(new Error("网络错误:无法获取文件大小")), + ontimeout: () => reject(new Error("超时:获取文件大小")) + }); + }))), httpRetryCount); + if (206 !== sizeResponse.status && 200 !== sizeResponse.status) throw new Error(`请求文件大小失败,状态码: ${sizeResponse.status}`); + { + const rangeHeader = sizeResponse.responseHeaders.match(/content-range:\s*bytes\s*\d+-\d+\/(\d+)/i), + typeHeader = sizeResponse.responseHeaders.match(/content-type:\s*([^\s;]+)/i); + if (rangeHeader && rangeHeader[1]) fileSize = parseInt(rangeHeader[1], 10); + else { + if (!sizeResponse.responseHeaders.match(/content-length:\s*(\d+)/i) || 200 !== sizeResponse.status) throw new Error("无法从响应头中获取文件总大小,服务器可能不支持 Range 请求。"); + { + const lengthHeader = sizeResponse.responseHeaders.match(/content-length:\s*(\d+)/i); + fileSize = parseInt(lengthHeader[1], 10); + clog.warn("服务器返回 200 状态码,可能不支持 Range 请求。将尝试完整下载。"); } + } + typeHeader && typeHeader[1] && (mimeType = typeHeader[1]); + clog.log(`文件总大小:${(fileSize / 1024 / 1024).toFixed(2)} MB, MIME 类型: ${mimeType || "未知"}`); } + } catch (e) { + clog.error("获取文件大小失败:", e.message); + throw e; + } + if (!fileSize || fileSize <= 0) throw new Error("获取到的文件大小无效或服务器拒绝提供大小信息。"); + const numChunks = Math.ceil(fileSize / 1048576), chunkPromises = [], downloadedChunks = new Array(numChunks); + clog.log(`文件将被分为 ${numChunks} 块进行下载 (每块约 ${1.toFixed(2)} MB)`); + for (let i = 0; i < numChunks; i++) { + const start = 1048576 * i, rangeHeader = `bytes=${start}-${Math.min(start + 1048576 - 1, fileSize - 1)}`, + chunkPromise = await utils.retry((() => new Promise(((resolve, reject) => { + const currentHeaders = { + ...headers, + Range: rangeHeader, + Accept: "application/octet-stream" + }; + _GM_xmlhttpRequest({ + method: "GET", + url, + headers: currentHeaders, + timeout: httpTimeout, + responseType: "arraybuffer", + onload: (response) => { + if (206 === response.status || 200 === response.status) if (response.response instanceof ArrayBuffer) { + downloadedChunks[i] = response.response; + clog.log(`成功下载第 ${i + 1}/${numChunks} 块 (${rangeHeader})`); + resolve(); + } else reject(new Error(`第 ${i + 1} 块响应不是 ArrayBuffer。`)); + else reject(new Error(`第 ${i + 1} 块请求失败,状态码: ${response.status}`)); + }, + onerror: (error) => reject(new Error(`第 ${i + 1} 块网络错误: ${error.error}`)), + ontimeout: () => reject(new Error(`第 ${i + 1} 块超时。`)) + }); + }))), httpRetryCount); + chunkPromises.push(chunkPromise); + } + try { + await Promise.all(chunkPromises); + clog.log("所有分块下载完成,开始合并..."); + } catch (e) { + clog.error("分块下载过程中发生错误:", e.message); + throw e; + } + const finalBlob = new Blob(downloadedChunks); + finalBlob.size !== fileSize && clog.warn(`警告:合并后的 Blob 大小 (${finalBlob.size}) 与预期文件大小 (${fileSize}) 不匹配!`); + return await finalBlob.text(); + } - class PluginManager { - constructor() { - this.plugins = /* @__PURE__ */ new Map(); + async gmRequest(method, url, data = {}, params = {}, headers = {}, noRedirect = false) { + if (params && Object.keys(params).length) { + const queryString = new URLSearchParams(params).toString(); + url += (url.includes("?") ? "&" : "?") + queryString; + } + const httpTimeout = await storageManager.getSetting("httpTimeout", 5e3), + httpRetryCount = await storageManager.getSetting("httpRetryCount", 3); + data || (data = void 0); + return await utils.retry((() => new Promise(((resolve, reject) => { + _GM_xmlhttpRequest({ + method, + url, + headers, + timeout: httpTimeout, + data, + onload: (response) => { + try { + noRedirect && response.finalUrl !== url && reject("请求被重定向了,URL是:" + response.finalUrl); + if (response.status >= 200 && response.status < 300) if (response.responseText) try { + resolve(JSON.parse(response.responseText)); + } catch (e) { + resolve(response.responseText); + } + else resolve(response.responseText || response); + else { + clog.error("请求失败,状态码:", response.status, url); + if (response.responseText) try { + const errorData = JSON.parse(response.responseText); + reject(errorData); + } catch { + reject(new Error(response.responseText || `请求发生错误 ${response.status}`)); + } + else reject(new Error(`请求发生错误 ${response.status}`)); + } + } catch (e) { + reject(e); } + }, + onerror: (error) => { + clog.error("网络错误:", url); + reject(new Error(error.error || "网络错误")); + }, + ontimeout: () => { + reject(new Error("请求超时: " + url)); + } + }); + }))), httpRetryCount); + } + } - register(pluginClass) { - if ("function" != typeof pluginClass) throw new Error("插件必须是一个类"); - const instance = new pluginClass(); - instance.pluginManager = this; - const lowerName = instance.getName(); - if (this.plugins.has(lowerName)) throw new Error(`插件"${name}"已注册`); - this.plugins.set(lowerName, instance); - } + class PluginManager { + constructor() { + this.plugins = /* @__PURE__ */ new Map(); + } - getBean(name2) { - return this.plugins.get(name2); - } + register(pluginClass) { + if ("function" != typeof pluginClass) throw new Error("插件必须是一个类"); + const instance = new pluginClass(); + instance.pluginManager = this; + const lowerName = instance.getName(); + if (this.plugins.has(lowerName)) throw new Error(`插件"${name}"已注册`); + this.plugins.set(lowerName, instance); + } - async processCss() { - const failedCssLoads = (await Promise.allSettled(Array.from(this.plugins).map((async ([name2, instance]) => { - try { - if ("function" == typeof instance.initCss) { - const css = await instance.initCss(); - css && utils.insertStyle(css); - return { - name: name2, - status: "fulfilled" - }; - } - return { - name: name2, - status: "skipped" - }; - } catch (e) { - console.error(`插件 ${name2} 加载 CSS 失败`, e); - return { - name: name2, - status: "rejected", - error: e - }; - } - })))).filter(((r) => "rejected" === r.status)); - failedCssLoads.length && console.error("以下插件的 CSS 加载失败:", failedCssLoads.map(((p) => p.value.name))); - } + getBean(name2) { + return this.plugins.get(name2); + } - async processPlugins() { - const failedPlugins = (await Promise.allSettled(Array.from(this.plugins).map((async ([name2, instance]) => { - try { - if ("function" == typeof instance.handle) { - await instance.handle(); - return { - name: name2, - status: "fulfilled" - }; - } - } catch (e) { - clog.error(`插件 ${name2} 执行失败`, e); - return { - name: name2, - status: "rejected", - error: e - }; - } - })))).filter(((r) => "rejected" === r.status)); - failedPlugins.length && console.error("以下插件执行失败:", failedPlugins.map(((p) => p.value.name))); - } + async processCss() { + const failedCssLoads = (await Promise.allSettled(Array.from(this.plugins).map((async ([name2, instance]) => { + try { + if ("function" == typeof instance.initCss) { + const css = await instance.initCss(); + css && utils.insertStyle(css); + return { + name: name2, + status: "fulfilled" + }; + } + return { + name: name2, + status: "skipped" + }; + } catch (e) { + console.error(`插件 ${name2} 加载 CSS 失败`, e); + return { + name: name2, + status: "rejected", + error: e + }; } + })))).filter(((r) => "rejected" === r.status)); + failedCssLoads.length && console.error("以下插件的 CSS 加载失败:", failedCssLoads.map(((p) => p.value.name))); + } - class BasePlugin { - constructor() { - __publicField2(this, "pluginManager", null); - __publicField2(this, "settingSvg", ''); - __publicField2(this, "editSvg", ''); - __publicField2(this, "deleteSvg", ''); - __publicField2(this, "checkSvg", ''); - __publicField2(this, "actressSvg", ''); - __publicField2(this, "newSvg", ''); - __publicField2(this, "refreshSvg", ''); - __publicField2(this, "blacklistSvg", ''); - __publicField2(this, "removeSvg", ''); - __publicField2(this, "copySvg", ''); - __publicField2(this, "titleSvg", ''); - __publicField2(this, "carNumSvg", ''); - __publicField2(this, "downSvg", ''); - __publicField2(this, "handleSvg", ''); - __publicField2(this, "siteSvg", ''); - __publicField2(this, "videoSvg", ''); - __publicField2(this, "screenSvg", ''); - __publicField2(this, "recoveryVideoSvg", ''); - __publicField2(this, "markDeleteSvg", ''); - } - - getName() { - throw new Error(`${this.constructor.name} 未显示getName()`); - } - - getBean(name2) { - return this.pluginManager.getBean(name2); - } - - async initCss() { - return ""; - } - - async handle() { - } - - getPageInfo() { - let carNum2, url, actress, actors, publishTime, currentHref2 = window.location.href; - if (isJavDb) { - carNum2 = $('a[title="複製番號"]').attr("data-clipboard-text"); - url = currentHref2.split("?")[0].split("#")[0]; - actress = $(".female").prev().map(((i, el) => $(el).text())).get().join(" "); - actors = $(".male").prev().map(((i, el) => $(el).text())).get().join(" "); - publishTime = $('strong:contains("日期:")').parent(".panel-block").find(".value").text().trim(); - } - if (isJavBus) { - url = currentHref2.split("?")[0]; - carNum2 = url.split("/").filter(Boolean).pop().replace(/_\d{4}-\d{2}-\d{2}$/, ""); - actress = $('span[onmouseover*="star_"] a').map(((i, el) => $(el).text())).get().join(" "); - actors = ""; - publishTime = $('span.header:contains("發行日期:")').parent("p").text().trim().replace("發行日期:", "").trim(); - } - return { - carNum: carNum2, - url, - actress, - actors, - publishTime - }; - } - - getActressId() { - const match = currentHref.match(/\/actors\/([^/?]+)/); - return match && match.length > 1 ? match[1] : null; - } - - getActressPageInfo() { - let currentHref2 = window.location.href; - if (!currentHref2.includes("/actors/") && !currentHref2.includes("/star/")) throw new Error("接口调用错误, 非演员详情页"); - let nameList = [], $actor = isJavDb ? $(".actor-section-name") : $(".avatar-box .photo-info .pb10"); - $actor.length && $actor.text().trim().split(",").forEach(((name2) => { - nameList.push(name2.trim()); - })); - let $sectionMeta = $(".section-meta:not(:contains('影片'))"); - $sectionMeta.length && $sectionMeta.text().trim().split(",").forEach(((name2) => { - nameList.push(name2.trim()); - })); - let role = $(".section-meta:contains('男優')").length > 0 ? "actor" : "actress", - movieType = "censored"; - nameList.some(((n) => n.includes("無碼"))) && (movieType = "uncensored"); - currentHref2.includes("uncensored") && (movieType = "uncensored"); - let blacklistUrl = null, starId = null; - const urlObj = new URL(currentHref2); - if (isJavDb) { - starId = urlObj.pathname.split("/").filter(((segment) => "" !== segment.trim())).pop(); - const params = urlObj.searchParams; - params.delete("sort_type"); - params.delete("page"); - blacklistUrl = urlObj.toString(); - } else if (isJavBus) { - const splitStr = "/star/", parts = currentHref2.split(splitStr); - if (parts.length < 2) throw new Error("提取演员url失败"); - const host = parts[0]; - starId = parts[1].split("/")[0]; - blacklistUrl = host + splitStr + starId; - } - return { - starId, - name: nameList[0], - allName: nameList, - role, - movieType, - blacklistUrl - }; - } - - getSelector(type) { - const key = type || (isJavDb ? "javdb" : isJavBus ? "javbus" : null), selectors = { - javdb: { - boxSelector: ".movie-list", - itemSelector: ".movie-list .item", - coverImgSelector: ".cover img", - requestDomItemSelector: ".movie-list .item", - nextPageSelector: ".pagination-next" - }, - javbus: { - boxSelector: ".masonry", - itemSelector: ".masonry .item", - coverImgSelector: ".masonry .movie-box .photo-frame img", - requestDomItemSelector: "#waterfall .item", - nextPageSelector: "#next" - } - }; - if (!key || !selectors[key]) throw new Error("类型错误: 无法确定选择器类型 (JavDb 或 JavBus)"); - return selectors[key]; - } - - parseMovieId(href) { - return href.split("/").pop().split(/[?#]/)[0]; - } - - getBoxCarInfo($box2) { - var _a2, _b, _c; - const $aLink = $box2.find("a"), url = $aLink.attr("href"); - let carNum2 = null, title = null, publishTime = null; - const $videoTitleEle = $box2.find(".video-title"); - if ($videoTitleEle.length > 0) { - const $strongEle = $videoTitleEle.find("strong"); - $strongEle.length > 0 && (carNum2 = $strongEle.text().trim()); - title = null == (_a2 = $aLink.attr("title")) ? void 0 : _a2.trim(); - if (!title) { - const fullTitleText = $videoTitleEle.text().trim(); - title = carNum2 && fullTitleText.includes(carNum2) ? fullTitleText.replace(carNum2, "").trim() : fullTitleText; - } - publishTime = $box2.find(".meta").text().trim(); - } - if (!carNum2) { - const $imgEle = $box2.find("img"); - $imgEle.length > 0 && (title = (null == (_b = $imgEle.attr("title")) ? void 0 : _b.trim()) || (null == (_c = $imgEle.attr("data-title")) ? void 0 : _c.trim())); - const dateElements = $box2.find("date").map(((i, el) => $(el).text().trim())).get(), - isDate = (s) => /^\d{4}-\d{1,2}-\d{1,2}$/.test(s); - publishTime = dateElements.find(isDate) || null; - carNum2 = dateElements.find(((i) => !isDate(i))) || null; - } - if (!carNum2) { - const msg = "提取番号信息失败: carNum 为空"; - console.error("Error in getBoxCarInfo:", msg, "Box Element:", $box2.get(0)); - show.error(msg); - throw new Error(msg); - } - return { - carNum: carNum2, - url: url || "", - aHref: url || "", - title: title || "", - publishTime: publishTime || "" - }; - } - - getBoxCarInfoList($boxList = null) { - $boxList || ($boxList = $(this.getSelector().itemSelector)); - if (0 === $boxList.length) { - clog.error("获取当前列表页所有item的番号信息失败!"); - return []; - } - const results = []; - $boxList.each(((index, element) => { - const $box2 = $(element); - try { - const carInfo = this.getBoxCarInfo($box2); - results.push(carInfo); - } catch (error) { - clog.error("[getBoxCarInfoList] 提取单个 boxCar 信息失败:", error.message, "元素索引:", index); - } - })); - return results; - } - - checkDuplicateCarNumbers(currentList, newList) { - if (!isJavDb) return false; - if (!currentList || 0 === currentList.length || !newList || 0 === newList.length) return false; - const currentCarNums = new Set(currentList.map(((item) => item.carNum)).filter(((n) => n))); - if (0 === currentCarNums.size) return false; - let consecutiveDuplicates = 0; - for (let i = 0; i < newList.length; i++) { - const newCarNum = newList[i] ? newList[i].carNum : null; - if (newCarNum && currentCarNums.has(newCarNum)) { - consecutiveDuplicates++; - if (consecutiveDuplicates >= 2) { - clog.warn("警告: 检测到连续番号信息重复, 该类别可能已被限制页码。"); - return true; - } - } else consecutiveDuplicates = 0; - } - return false; - } + async processPlugins() { + const failedPlugins = (await Promise.allSettled(Array.from(this.plugins).map((async ([name2, instance]) => { + try { + if ("function" == typeof instance.handle) { + await instance.handle(); + return { + name: name2, + status: "fulfilled" + }; + } + } catch (e) { + clog.error(`插件 ${name2} 执行失败`, e); + return { + name: name2, + status: "rejected", + error: e + }; } + })))).filter(((r) => "rejected" === r.status)); + failedPlugins.length && console.error("以下插件执行失败:", failedPlugins.map(((p) => p.value.name))); + } + } - const DMM_GRAPHQL_URL = "https://api.video.dmm.co.jp/graphql"; - const dmmGraphQLKeyword = (code) => { - const match = String(code || "").trim().toUpperCase().match(/^([A-Z0-9]{2,10})-(\d{1,6})$/); - if (!match) return ""; - return `${match[1].toLowerCase()}${match[2].padStart(5, "0")}`; - }; - const dmmGraphQLRequest = (query) => { - return new Promise((resolve, reject) => { - _GM_xmlhttpRequest({ - method: "POST", - url: DMM_GRAPHQL_URL, - data: JSON.stringify({query}), - timeout: 12e3, - headers: { - Accept: "application/json", - "Content-Type": "application/json", - Referer: "https://video.dmm.co.jp/", - "Fanza-Device": "BROWSER", - "Cache-Control": "no-cache" - }, - onload: (response) => { - if (response.status < 200 || response.status >= 400) { - reject(new Error(`DMM GraphQL HTTP ${response.status || 0}`)); - return; - } - try { - const json = JSON.parse(response.responseText || "{}"); - if (Array.isArray(json.errors) && json.errors.length) { - reject(new Error(json.errors[0].message || "DMM GraphQL error")); - return; - } - resolve(json.data || {}); - } catch (e) { - reject(new Error(`DMM GraphQL JSON parse error: ${e.message}`)); - } - }, - onerror: () => reject(new Error("DMM GraphQL network error")), - ontimeout: () => reject(new Error("DMM GraphQL timeout")) - }); + class BasePlugin { + constructor() { + __publicField2(this, "pluginManager", null); + __publicField2(this, "settingSvg", ''); + __publicField2(this, "editSvg", ''); + __publicField2(this, "deleteSvg", ''); + __publicField2(this, "checkSvg", ''); + __publicField2(this, "actressSvg", ''); + __publicField2(this, "newSvg", ''); + __publicField2(this, "refreshSvg", ''); + __publicField2(this, "blacklistSvg", ''); + __publicField2(this, "removeSvg", ''); + __publicField2(this, "copySvg", ''); + __publicField2(this, "titleSvg", ''); + __publicField2(this, "carNumSvg", ''); + __publicField2(this, "downSvg", ''); + __publicField2(this, "handleSvg", ''); + __publicField2(this, "siteSvg", ''); + __publicField2(this, "videoSvg", ''); + __publicField2(this, "screenSvg", ''); + __publicField2(this, "recoveryVideoSvg", ''); + __publicField2(this, "markDeleteSvg", ''); + } + + getName() { + throw new Error(`${this.constructor.name} 未显示getName()`); + } + + getBean(name2) { + return this.pluginManager.getBean(name2); + } + + async initCss() { + return ""; + } + + async handle() { + } + + getPageInfo() { + let carNum2, url, actress, actors, publishTime, currentHref2 = window.location.href; + if (isJavDb) { + carNum2 = $('a[title="複製番號"]').attr("data-clipboard-text"); + url = currentHref2.split("?")[0].split("#")[0]; + actress = $(".female").prev().map(((i, el) => $(el).text())).get().join(" "); + actors = $(".male").prev().map(((i, el) => $(el).text())).get().join(" "); + publishTime = $('strong:contains("日期:")').parent(".panel-block").find(".value").text().trim(); + } + if (isJavBus) { + url = currentHref2.split("?")[0]; + carNum2 = url.split("/").filter(Boolean).pop().replace(/_\d{4}-\d{2}-\d{2}$/, ""); + actress = $('span[onmouseover*="star_"] a').map(((i, el) => $(el).text())).get().join(" "); + actors = ""; + publishTime = $('span.header:contains("發行日期:")').parent("p").text().trim().replace("發行日期:", "").trim(); + } + return { + carNum: carNum2, + url, + actress, + actors, + publishTime + }; + } + + getActressId() { + const match = currentHref.match(/\/actors\/([^/?]+)/); + return match && match.length > 1 ? match[1] : null; + } + + getActressPageInfo() { + let currentHref2 = window.location.href; + if (!currentHref2.includes("/actors/") && !currentHref2.includes("/star/")) throw new Error("接口调用错误, 非演员详情页"); + let nameList = [], $actor = isJavDb ? $(".actor-section-name") : $(".avatar-box .photo-info .pb10"); + $actor.length && $actor.text().trim().split(",").forEach(((name2) => { + nameList.push(name2.trim()); + })); + let $sectionMeta = $(".section-meta:not(:contains('影片'))"); + $sectionMeta.length && $sectionMeta.text().trim().split(",").forEach(((name2) => { + nameList.push(name2.trim()); + })); + let role = $(".section-meta:contains('男優')").length > 0 ? "actor" : "actress", movieType = "censored"; + nameList.some(((n) => n.includes("無碼"))) && (movieType = "uncensored"); + currentHref2.includes("uncensored") && (movieType = "uncensored"); + let blacklistUrl = null, starId = null; + const urlObj = new URL(currentHref2); + if (isJavDb) { + starId = urlObj.pathname.split("/").filter(((segment) => "" !== segment.trim())).pop(); + const params = urlObj.searchParams; + params.delete("sort_type"); + params.delete("page"); + blacklistUrl = urlObj.toString(); + } else if (isJavBus) { + const splitStr = "/star/", parts = currentHref2.split(splitStr); + if (parts.length < 2) throw new Error("提取演员url失败"); + const host = parts[0]; + starId = parts[1].split("/")[0]; + blacklistUrl = host + splitStr + starId; + } + return { + starId, + name: nameList[0], + allName: nameList, + role, + movieType, + blacklistUrl + }; + } + + getSelector(type) { + const key = type || (isJavDb ? "javdb" : isJavBus ? "javbus" : null), selectors = { + javdb: { + boxSelector: ".movie-list", + itemSelector: ".movie-list .item", + coverImgSelector: ".cover img", + requestDomItemSelector: ".movie-list .item", + nextPageSelector: ".pagination-next" + }, + javbus: { + boxSelector: ".masonry", + itemSelector: ".masonry .item", + coverImgSelector: ".masonry .movie-box .photo-frame img", + requestDomItemSelector: "#waterfall .item", + nextPageSelector: "#next" + } + }; + if (!key || !selectors[key]) throw new Error("类型错误: 无法确定选择器类型 (JavDb 或 JavBus)"); + return selectors[key]; + } + + parseMovieId(href) { + return href.split("/").pop().split(/[?#]/)[0]; + } + + getBoxCarInfo($box2) { + var _a2, _b, _c; + const $aLink = $box2.find("a"), url = $aLink.attr("href"); + let carNum2 = null, title = null, publishTime = null; + const $videoTitleEle = $box2.find(".video-title"); + if ($videoTitleEle.length > 0) { + const $strongEle = $videoTitleEle.find("strong"); + $strongEle.length > 0 && (carNum2 = $strongEle.text().trim()); + title = null == (_a2 = $aLink.attr("title")) ? void 0 : _a2.trim(); + if (!title) { + const fullTitleText = $videoTitleEle.text().trim(); + title = carNum2 && fullTitleText.includes(carNum2) ? fullTitleText.replace(carNum2, "").trim() : fullTitleText; + } + publishTime = $box2.find(".meta").text().trim(); + } + if (!carNum2) { + const $imgEle = $box2.find("img"); + $imgEle.length > 0 && (title = (null == (_b = $imgEle.attr("title")) ? void 0 : _b.trim()) || (null == (_c = $imgEle.attr("data-title")) ? void 0 : _c.trim())); + const dateElements = $box2.find("date").map(((i, el) => $(el).text().trim())).get(), + isDate = (s) => /^\d{4}-\d{1,2}-\d{1,2}$/.test(s); + publishTime = dateElements.find(isDate) || null; + carNum2 = dateElements.find(((i) => !isDate(i))) || null; + } + if (!carNum2) { + const msg = "提取番号信息失败: carNum 为空"; + console.error("Error in getBoxCarInfo:", msg, "Box Element:", $box2.get(0)); + show.error(msg); + throw new Error(msg); + } + return { + carNum: carNum2, + url: url || "", + aHref: url || "", + title: title || "", + publishTime: publishTime || "" + }; + } + + getBoxCarInfoList($boxList = null) { + $boxList || ($boxList = $(this.getSelector().itemSelector)); + if (0 === $boxList.length) { + clog.error("获取当前列表页所有item的番号信息失败!"); + return []; + } + const results = []; + $boxList.each(((index, element) => { + const $box2 = $(element); + try { + const carInfo = this.getBoxCarInfo($box2); + results.push(carInfo); + } catch (error) { + clog.error("[getBoxCarInfoList] 提取单个 boxCar 信息失败:", error.message, "元素索引:", index); + } + })); + return results; + } + + checkDuplicateCarNumbers(currentList, newList) { + if (!isJavDb) return false; + if (!currentList || 0 === currentList.length || !newList || 0 === newList.length) return false; + const currentCarNums = new Set(currentList.map(((item) => item.carNum)).filter(((n) => n))); + if (0 === currentCarNums.size) return false; + let consecutiveDuplicates = 0; + for (let i = 0; i < newList.length; i++) { + const newCarNum = newList[i] ? newList[i].carNum : null; + if (newCarNum && currentCarNums.has(newCarNum)) { + consecutiveDuplicates++; + if (consecutiveDuplicates >= 2) { + clog.warn("警告: 检测到连续番号信息重复, 该类别可能已被限制页码。"); + return true; + } + } else consecutiveDuplicates = 0; + } + return false; + } + } + + const DMM_GRAPHQL_URL = "https://api.video.dmm.co.jp/graphql"; + const dmmGraphQLKeyword = (code) => { + const match = String(code || "").trim().toUpperCase().match(/^([A-Z0-9]{2,10})-(\d{1,6})$/); + if (!match) return ""; + return `${match[1].toLowerCase()}${match[2].padStart(5, "0")}`; + }; + const dmmGraphQLRequest = (query) => { + return new Promise((resolve, reject) => { + _GM_xmlhttpRequest({ + method: "POST", + url: DMM_GRAPHQL_URL, + data: JSON.stringify({query}), + timeout: 12e3, + headers: { + Accept: "application/json", + "Content-Type": "application/json", + Referer: "https://video.dmm.co.jp/", + "Fanza-Device": "BROWSER", + "Cache-Control": "no-cache" + }, + onload: (response) => { + if (response.status < 200 || response.status >= 400) { + reject(new Error(`DMM GraphQL HTTP ${response.status || 0}`)); + return; + } + try { + const json = JSON.parse(response.responseText || "{}"); + if (Array.isArray(json.errors) && json.errors.length) { + reject(new Error(json.errors[0].message || "DMM GraphQL error")); + return; + } + resolve(json.data || {}); + } catch (e) { + reject(new Error(`DMM GraphQL JSON parse error: ${e.message}`)); + } + }, + onerror: () => reject(new Error("DMM GraphQL network error")), + ontimeout: () => reject(new Error("DMM GraphQL timeout")) + }); + }); + }; + const searchDmmContentIdsByGraphQL = async (code) => { + const keyword = dmmGraphQLKeyword(code); + if (!keyword) return []; + const carNumNoHyphen = String(code || "").replace(/-/g, "").toLowerCase(); + const results = []; + const searchKeywords = [.../* @__PURE__ */ new Set([keyword, `${keyword}#`])]; + for (const searchKeyword of searchKeywords) { + const query = `{ legacySearchPPV(limit: 10, offset: 0, sort: SALES_RANK_SCORE, floor: AV, queryWord: ${JSON.stringify(searchKeyword)}) { result { contents { contentId serviceCode floorCode } } } }`; + const data = await dmmGraphQLRequest(query); + const contents = Array.isArray(data && data.legacySearchPPV && data.legacySearchPPV.result && data.legacySearchPPV.result.contents) ? data.legacySearchPPV.result.contents : []; + for (const item of contents) { + const contentId = String(item.contentId || ""); + if (contentId.replace(/[^a-z0-9]/gi, "").toLowerCase().includes(carNumNoHyphen)) { + results.push({ + serviceCode: item.serviceCode || "digital", + floorCode: item.floorCode || "AV", + contentId + }); + } + } + if (results.length > 0) break; + } + return results; + }; + const getDmmGraphQLVideoUrls = async (code) => { + const contentItems = await searchDmmContentIdsByGraphQL(code); + if (!contentItems.length) return null; + const results = await Promise.allSettled( + contentItems.map((item) => extractTrailerLinks(item)) + ); + for (const result of results) { + if (result.status === "fulfilled" && result.value) { + return result.value; + } + } + return null; + }; + const extractTrailerLinks = (item) => { + const {contentId, serviceCode, floorCode} = item; + return new Promise((resolve, reject) => { + const trailerPageUrl = `https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${contentId}/mtype=AhRVShI_/service=${serviceCode}/floor=${floorCode}/mode=/`; + _GM_xmlhttpRequest({ + method: "GET", + url: trailerPageUrl, + timeout: 15e3, + headers: { + "accept-language": "ja-JP,ja;q=0.9", + Cookie: "age_check_done=1" + }, + onload: (response) => { + const htmlContent = response.responseText || ""; + if (htmlContent.includes("このサービスはお住まいの地域からは")) { + reject(new Error("节点不可用,请将DMM域名分流到日本ip")); + return; + } + const match = htmlContent.match(/const\s+args\s+=\s+(.*);/); + if (!match) { + reject(new Error("未在脚本中找到 const args = ... 变量")); + return; + } + let bitrates; + try { + bitrates = JSON.parse(match[1]).bitrates; + } catch (e) { + reject(new Error(`解析播放器脚本 JSON 失败: ${e.message}`)); + return; + } + if (!Array.isArray(bitrates)) { + reject(new Error("解析画质链接失败: bitrates 字段不是一个数组或不存在")); + return; + } + const qualityKeys = [ + "4ks", + "4k", + "hhbs", + "hhb", + "hmb", + "mhb", + "mmb", + "dmb_w", + "dmb_s", + "dm_s", + "sm_s", + "mhb_w" + ]; + const qualityNameRegex = new RegExp(`(${qualityKeys.join("|")})\\.mp4$`); + const finalQualityMap = {}; + for (const bitrate of bitrates) { + const url = bitrate && bitrate.src; + if (!url || typeof url !== "string" || !url.endsWith(".mp4")) continue; + const qualityMatch = url.match(qualityNameRegex); + let qualityKey = ""; + if (qualityMatch && qualityMatch[1]) qualityKey = qualityMatch[1]; + if (qualityKey && !finalQualityMap[qualityKey]) { + finalQualityMap[qualityKey] = url; + } + } + if (Object.keys(finalQualityMap).length === 0) { + reject(new Error("未找到匹配要求的预览画质视频")); + return; + } + resolve(finalQualityMap); + }, + onerror: () => reject(new Error("DMM 播放页请求网络错误")), + ontimeout: () => reject(new Error("DMM 播放页请求超时")) + }); + }); + }; + const selectDefaultQuality = (dmmVideoQualityList, intendedDefault) => { + if (!dmmVideoQualityList || 0 === dmmVideoQualityList.length) return null; + const availableSet = new Set(dmmVideoQualityList); + if (availableSet.has(intendedDefault)) return intendedDefault; + const priorityOrder = qualityOptions.map(((option) => option.quality)).reverse(); + for (const quality of priorityOrder) if (availableSet.has(quality)) return quality; + return dmmVideoQualityList[0]; + }, CACHE_KEY = "jhs_dmm_video"; + + class DmmVideoFetcher { + constructor(carNum2, showErrorMessages = true) { + this.carNum = carNum2; + this.showErrorMessages = showErrorMessages; + } + + _checkCache() { + const cachedData = localStorage.getItem(CACHE_KEY) ? JSON.parse(localStorage.getItem(CACHE_KEY)) : {}; + if (cachedData[this.carNum]) { + clog.debug("缓存中存在预览视频信息", cachedData[this.carNum]); + return cachedData[this.carNum]; + } + return null; + } + + _updateCache(videoMap) { + const cachedData = localStorage.getItem(CACHE_KEY) ? JSON.parse(localStorage.getItem(CACHE_KEY)) : {}; + cachedData[this.carNum] = videoMap; + clog.debug("成功解析出预览视频并已缓存:", videoMap); + localStorage.setItem(CACHE_KEY, JSON.stringify(cachedData)); + } + + async _searchContentIds() { + const carNum2 = this.carNum, carNumNoHyphen = carNum2.replace(/-/g, ""), keywordAttempts = [{ + keyword: carNum2.replace("-", "00"), + name: "00-替换关键词" + }, { + keyword: carNum2, + name: "原始番号关键词" + }, { + keyword: carNumNoHyphen, + name: "无连字符关键词" + }], carNumLower = carNum2.toLowerCase(); + for (const attempt of keywordAttempts) { + const {keyword, name: name2} = attempt, currentTempCarNumLower = keyword.toLowerCase(), + apiUrl2 = `https://api.dmm.com/affiliate/v3/ItemList?${new URLSearchParams({ + api_id: "UrwskPfkqQ0DuVry2gYL", + affiliate_id: "10278-996", + output: "json", + site: "FANZA", + sort: "match", + keyword + }).toString()}`; + let response; + try { + response = await gmHttp.get(apiUrl2); + } catch (e) { + clog.error(`API 请求失败,跳过 ${name2}:`, e); + continue; + } + if (!response || !response.result || !response.result.result_count) { + clog.debug(`使用 ${name2} (${keyword}) 进行 API 搜索 返回无结果,尝试下一个关键词。`); + continue; + } + const newItems = []; + for (const item of response.result.items) { + if (newItems.length >= 2) break; + const contentId = item.content_id || "", makerProduct = item.maker_product || ""; + if (contentId.includes(currentTempCarNumLower.replace("-", "")) || carNumLower === makerProduct.toLowerCase() || contentId.includes(carNumNoHyphen.toLowerCase())) { + newItems.push({ + serviceCode: item.service_code, + floorCode: item.floor_code, + contentId, + pageUrl: item.URL }); + clog.debug(`[${name2}] cid|makerProduct 匹配成功:`, contentId, makerProduct); + } + } + if (newItems.length > 0) { + clog.debug(`--- 成功通过 ${name2} 找到 Content IDs ---`); + const $btn2 = $("#fanzaBtn"); + let url = `https://www.dmm.co.jp/search/=/searchstr=${keyword}`, type = "single"; + if (newItems.length > 1) { + $btn2.attr("href", url); + $btn2.append('多结果'); + $btn2.css("backgroundColor", "#7bc73b"); + type = "multiple"; + } else { + url = newItems[0].pageUrl; + $btn2.attr("href", url); + $btn2.css("backgroundColor", "#7bc73b"); + } + const dmmCacheKey = "jhs_other_site_dmm", + dmmCacheData = localStorage.getItem(dmmCacheKey) ? JSON.parse(localStorage.getItem(dmmCacheKey)) : {}; + dmmCacheData[this.carNum] = { + type, + url + }; + localStorage.setItem(dmmCacheKey, JSON.stringify(dmmCacheData)); + return newItems; + } + clog.debug(`[${name2}] API 返回结果数 ${response.result.result_count},但无精确匹配的 Content ID。`); + } + clog.warn("所有关键词尝试均未找到匹配的Content ID, 解析Dmm视频失败"); + const $btn = $("#fanzaBtn"); + $btn.attr("href", `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}`); + $btn.attr("title", "未查询到, 点击前往搜索页"); + $btn.css("backgroundColor", "#de3333"); + return null; + } + + async _extractTrailerLinks({contentId, serviceCode, floorCode}) { + const trailerPageUrl = `https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${contentId}/mtype=AhRVShI_/service=${serviceCode}/floor=${floorCode}/mode=/`, + htmlContent = await gmHttp.get(trailerPageUrl, null, { + "accept-language": "ja-JP,ja;q=0.9", + Cookie: "age_check_done=1" + }); + if ("string" != typeof htmlContent) { + clog.error(htmlContent); + throw new Error("解析播放页内容失败, 非文本内容"); + } + if (htmlContent.includes("このサービスはお住まいの地域からは")) throw new Error("节点不可用,请将DMM域名分流到日本ip"); + const match = htmlContent.match(/const\s+args\s+=\s+(.*);/); + if (!match) throw new Error("未在脚本中找到 const args = ... 变量"); + let bitrates; + try { + ({bitrates} = JSON.parse(match[1])); + } catch (e) { + throw new Error(`解析播放器脚本 JSON 失败: ${e.message}`); + } + const finalQualityMap = {}, qualityKeys = qualityOptions.map(((o) => o.quality)).join("|"), + qualityNameRegex = new RegExp(`(${qualityKeys})\\.mp4$`); + if (!Array.isArray(bitrates)) { + clog.error("解析画质链接失败: bitrates 字段不是一个数组或不存在"); + throw new Error("解析画质链接失败: bitrates 字段不是一个数组或不存在"); + } + clog.debug("原始数据返回:", bitrates); + for (const item of bitrates) { + const url = null == item ? void 0 : item.src; + if (!url || "string" != typeof url || !url.endsWith(".mp4")) continue; + const qualityMatch = url.match(qualityNameRegex); + let qualityKey = ""; + qualityMatch && qualityMatch[1] && (qualityKey = qualityMatch[1]); + qualityKey && !finalQualityMap[qualityKey] && (finalQualityMap[qualityKey] = url); + } + if (0 === Object.keys(finalQualityMap).length) throw new Error("未找到匹配要求的预览画质视频"); + return finalQualityMap; + } + + async _searchViaGraphQL() { + clog.debug("尝试通过 GraphQL API 搜索视频..."); + const videoMap = await getDmmGraphQLVideoUrls(this.carNum); + if (videoMap && Object.keys(videoMap).length > 0) { + this._updateCache(videoMap); + clog.debug("GraphQL 成功解析出预览视频:", videoMap); + const dmmCacheKey = "jhs_other_site_dmm"; + const dmmCacheData = localStorage.getItem(dmmCacheKey) ? JSON.parse(localStorage.getItem(dmmCacheKey)) : {}; + dmmCacheData[this.carNum] = { + type: "graphql", + url: `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}` }; - const searchDmmContentIdsByGraphQL = async (code) => { - const keyword = dmmGraphQLKeyword(code); - if (!keyword) return []; - const carNumNoHyphen = String(code || "").replace(/-/g, "").toLowerCase(); - const results = []; - const searchKeywords = [.../* @__PURE__ */ new Set([keyword, `${keyword}#`])]; - for (const searchKeyword of searchKeywords) { - const query = `{ legacySearchPPV(limit: 10, offset: 0, sort: SALES_RANK_SCORE, floor: AV, queryWord: ${JSON.stringify(searchKeyword)}) { result { contents { contentId serviceCode floorCode } } } }`; - const data = await dmmGraphQLRequest(query); - const contents = Array.isArray(data && data.legacySearchPPV && data.legacySearchPPV.result && data.legacySearchPPV.result.contents) ? data.legacySearchPPV.result.contents : []; - for (const item of contents) { - const contentId = String(item.contentId || ""); - if (contentId.replace(/[^a-z0-9]/gi, "").toLowerCase().includes(carNumNoHyphen)) { - results.push({ - serviceCode: item.serviceCode || "digital", - floorCode: item.floorCode || "AV", - contentId - }); - } - } - if (results.length > 0) break; + localStorage.setItem(dmmCacheKey, JSON.stringify(dmmCacheData)); + return videoMap; + } + return null; + } + + async fetchVideo() { + const cachedResult = this._checkCache(); + if (cachedResult) return cachedResult; + let contentItems; + try { + const testCarNum = this.carNum.toLowerCase(); + if (testCarNum.startsWith("heyzo") || /^(n\d+|\d+(-\d+)*)$/.test(testCarNum) || /^n\d+$/.test(testCarNum)) throw new Error("无码番号类型, 取消dmm解析"); + if (this.carNum.includes("VR-")) throw new Error("VR类型, 取消dmm解析"); + contentItems = await this._searchContentIds(); + } catch (e) { + clog.error("DMM API 搜索失败:", e); + } + if (!contentItems || 0 === contentItems.length) { + clog.warn("Affiliate API 未找到视频,尝试 GraphQL API..."); + const graphQLResult = await this._searchViaGraphQL(); + if (graphQLResult) return graphQLResult; + const $btn = $("#fanzaBtn"); + $btn.attr("href", `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}`); + $btn.attr("title", "未查询到, 点击前往搜索页"); + $btn.css("backgroundColor", "#de3333"); + return null; + } + try { + const finalVideoMap = await Promise.any(contentItems.map(((item) => this._extractTrailerLinks(item)))); + this._updateCache(finalVideoMap); + return finalVideoMap; + } catch (error) { + const errors = error.errors || [error]; + clog.error(`Affiliate 解析失败: ${errors[0] && errors[0].message || errors[0]}`, errors); + clog.warn("尝试 GraphQL API 作为 fallback..."); + const graphQLResult = await this._searchViaGraphQL(); + if (graphQLResult) return graphQLResult; + if (errors.some(((err) => err.message.includes("节点不可用")))) this.showErrorMessages && show.error("节点不可用,请将DMM域名分流到日本ip"); + else { + const displayError = errors[0].message || errors[0]; + this.showErrorMessages && show.error(`解析失败: ${displayError}`); + } + const $btn = $("#fanzaBtn"); + $btn.attr("href", `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}`); + $btn.attr("title", "未查询到, 点击前往搜索页"); + $btn.css("backgroundColor", "#de3333"); + return null; + } + } + } + + const getDmmVideo = async (carNum2, showErrorMessages = true) => new DmmVideoFetcher(carNum2, showErrorMessages).fetchVideo(); + + class AutoPagePlugin extends BasePlugin { + constructor() { + super(...arguments); + __publicField2(this, "preloadDistance", 500); + __publicField2(this, "currentPage", this.getInitialPageNumber()); + __publicField2(this, "pageItems", []); + } + + getName() { + return "AutoPagePlugin"; + } + + async initCss() { + return "\n \n "; + } + + async handle() { + this.waterfall().then(); + } + + getInitialPageNumber() { + if (isJavBus$1) { + const match = currentHref$1.match(/\/(page|star\/[^/]+)\/(\d+)/); + return match ? parseInt(match[2], 10) : 1; + } + if (isJavDb$1) { + const match = currentHref$1.match(/[?&]page=(\d+)/); + return match ? parseInt(match[1], 10) : 1; + } + return 1; + } + + async waterfall() { + if (await this.shouldDisablePaging()) return; + const selector = this.getSelector(); + this.container = document.querySelector(selector.boxSelector); + if (!this.container) { + console.error("没有找到容器节点,停止瀑布流!"); + return; + } + this.loader = document.createElement("div"); + this.loader.className = "jhs-scroll"; + this.container.parentNode.insertBefore(this.loader, this.container.nextSibling); + this.pageItems.push({ + page: this.currentPage, + top: 0, + url: window.location.href + }); + this.loader.addEventListener("click", (() => { + this.loader.classList.contains("waterfall-error") && this.loadNextPage().then(); + })); + window.addEventListener("scroll", (() => { + this.checkLoad(); + this.checkScrollPosition(); + })); + const nextLink = document.querySelector(selector.nextPageSelector); + this.nextUrl = null == nextLink ? void 0 : nextLink.href; + this.hasMore = !!this.nextUrl; + setTimeout((() => { + this.checkLoad(); + }), 1e3); + this.hasMore || this.setState("waterfall-no-more", "已经到底了"); + } + + async loadNextPage() { + var _a2; + if (await storageManager.getSetting("autoPage", YES$1) === NO) { + this.setState("waterfall-loading", ""); + return; + } + if (this.isLoading || !this.nextUrl) return; + this.isLoading = true; + this.setState("waterfall-loading", "加载中..."); + const selector = this.getSelector(); + try { + const pageNum = utils.getUrlParam(this.nextUrl, "page"); + let maxPage = 60; + currentHref$1.includes("c11") && (maxPage = 30); + if (isJavDb$1 && pageNum > maxPage || currentHref$1.includes("month")) { + const beyond60Plugin = this.getBean("Beyond60Plugin"); + if (beyond60Plugin) { + const {html: html2, nextUrl, hasMore} = await beyond60Plugin.handleBeyond60(this.nextUrl); + if (html2) { + const pageTop2 = this.container.scrollHeight; + this.pageItems.push({ + page: this.currentPage + 1, + top: pageTop2, + url: this.nextUrl + }); + $(".movie-list").append(html2); } - return results; + this.hasMore = hasMore; + this.nextUrl = nextUrl; + const $ul = beyond60Plugin.createPagination(pageNum, hasMore); + $(".pagination").html($ul); + this.setState("waterfall-loading", ""); + this.hasMore || this.setState("waterfall-no-more", "已经到底了"); + return; + } + } + const html = await gmHttp.get(this.nextUrl); + clog.log("请求下一页内容:", this.nextUrl); + const $dom = utils.htmlTo$dom(html); + isJavBus$1 && $dom.find(".avatar-box").length > 0 && $dom.find(".avatar-box").parent().remove(); + let itemList = $dom.find(this.getSelector().requestDomItemSelector); + const currentBoxCarInfoList = this.getBoxCarInfoList(), + nextPageBoxCarInfoList = this.getBoxCarInfoList(itemList); + if (this.checkDuplicateCarNumbers(currentBoxCarInfoList, nextPageBoxCarInfoList)) { + this.nextUrl = null; + this.hasMore = false; + this.setState("waterfall-error", "翻页内容出现重复数据, 可能首页已更新了新视频 或 页码受JavDB限制, 停止瀑布流"); + return; + } + const pageTop = this.container.scrollHeight; + this.pageItems.push({ + page: this.currentPage + 1, + top: pageTop, + url: this.nextUrl + }); + const listPagePlugin = this.getBean("ListPagePlugin"); + let coverImgNodeList = $dom.find(this.getSelector().coverImgSelector); + listPagePlugin.replaceHdImg(coverImgNodeList); + $(this.getSelector().boxSelector).append(itemList); + this.nextUrl = null == (_a2 = $dom.find(selector.nextPageSelector)) ? void 0 : _a2.attr("href"); + this.hasMore = !!this.nextUrl; + let pagination = $dom.find(".pagination"); + $(".pagination").replaceWith(pagination); + this.setState("waterfall-loading", ""); + this.hasMore || this.setState("waterfall-no-more", "已经到底了"); + } catch (e) { + clog.error("加载失败:", e); + this.setState("waterfall-error", "加载失败,点击重试"); + } finally { + this.isLoading = false; + } + } + + checkScrollPosition() { + const scrollPosition = window.scrollY; + for (let i = this.pageItems.length - 1; i >= 0; i--) { + const page = this.pageItems[i]; + if (scrollPosition >= page.top) { + if (this.currentPage !== page.page) { + this.currentPage = page.page; + this.updatePageUrl(page.url); + } + break; + } + } + } + + checkLoad() { + if (!this.loader) return; + this.loader.getBoundingClientRect().top < window.innerHeight + this.preloadDistance && this.loadNextPage().then(); + } + + async shouldDisablePaging() { + if (!window.isListPage) return true; + await storageManager.getSetting("autoPage", YES$1); + return ["search?q", "handlePlayback=1", "handleTop=1", "/want_watch_videos", "/watched_videos", "/advanced_search?type=100"].some(((path) => currentHref$1.includes(path))); + } + + updatePageUrl_old(href) { + window.history.pushState({}, "", href); + if (isJavBus$1) { + const match = href.match(/\/(page|star\/.*?)\/(\d+)/), pageNumber = match ? parseInt(match[2], 10) : null; + document.title = document.title.replace(/第\d+頁/, "第" + pageNumber + "頁"); + } + } + + updatePageUrl(url) { + window.history.replaceState({}, "", url); + isJavBus$1 && (document.title = document.title.replace(/第\d+頁/, `第${this.currentPage}頁`)); + } + + setState(state, text) { + this.loader.className = `jhs-scroll ${state}`; + this.loader.textContent = text; + } + } + + class AliyunApi { + constructor(refresh_token) { + this.baseApiUrl = "https://api.aliyundrive.com"; + this.refresh_token = refresh_token; + this.authorization = null; + this.default_drive_id = null; + this.backupFolderId = null; + } + + async getDefaultDriveId() { + if (this.default_drive_id) return this.default_drive_id; + this.userInfo = await this.getUserInfo(); + this.default_drive_id = this.userInfo.default_drive_id; + return this.default_drive_id; + } + + async getHeaders() { + if (this.authorization) return { + authorization: this.authorization + }; + this.authorization = await this.getAuthorization(); + return { + authorization: this.authorization + }; + } + + async getAuthorization() { + let url = this.baseApiUrl + "/v2/account/token", data = { + refresh_token: this.refresh_token, + grant_type: "refresh_token" + }; + try { + return "Bearer " + (await gmHttp.post(url, data)).access_token; + } catch (e) { + throw e.message.includes("is not valid") ? new Error("refresh_token无效, 请重新填写并保存") : e; + } + } + + async getUserInfo() { + const headers = await this.getHeaders(); + let url = this.baseApiUrl + "/v2/user/get"; + return await gmHttp.post(url, {}, headers); + } + + async deleteFile(file_id, drive_id = null) { + if (!file_id) throw new Error("未传入file_id"); + drive_id || (drive_id = await this.getDefaultDriveId()); + let data = { + file_id, + drive_id + }, url = this.baseApiUrl + "/v2/recyclebin/trash"; + const headers = await this.getHeaders(); + await gmHttp.post(url, data, headers); + return {}; + } + + async createFolder(name2, drive_id = null, parent_folder_id = "root") { + drive_id || (drive_id = await this.getDefaultDriveId()); + let url = this.baseApiUrl + "/adrive/v2/file/createWithFolders", data = { + name: name2, + type: "folder", + parent_file_id: parent_folder_id, + check_name_mode: "auto_rename", + content_hash_name: "sha1", + drive_id + }; + const headers = await this.getHeaders(); + return await gmHttp.post(url, data, headers); + } + + async getFileList(parent_folder_id = "root", drive_id = null) { + drive_id || (drive_id = await this.getDefaultDriveId()); + let url = this.baseApiUrl + "/adrive/v3/file/list"; + const data = { + drive_id, + parent_file_id: parent_folder_id, + limit: 200, + all: false, + url_expire_sec: 14400, + image_thumbnail_process: "image/resize,w_256/format,avif", + image_url_process: "image/resize,w_1920/format,avif", + video_thumbnail_process: "video/snapshot,t_120000,f_jpg,m_lfit,w_256,ar_auto,m_fast", + fields: "*", + order_by: "updated_at", + order_direction: "DESC" + }, headers = await this.getHeaders(); + return (await gmHttp.post(url, data, headers)).items; + } + + async uploadFile(folder_id, fileName, uploadContent, drive_id = null) { + show.info("请求存储空间中..."); + let createFileUrl = this.baseApiUrl + "/adrive/v2/file/createWithFolders"; + drive_id || (drive_id = await this.getDefaultDriveId()); + let data = { + drive_id, + part_info_list: [{ + part_number: 1 + }], + parent_file_id: folder_id, + name: fileName, + type: "file", + check_name_mode: "auto_rename" + }; + const headers = await this.getHeaders(), createFileResult = await gmHttp.post(createFileUrl, data, headers), + upload_id = createFileResult.upload_id, upload_file_id = createFileResult.file_id, + upload_url = createFileResult.part_info_list[0].upload_url; + show.info("开始上传文件..."); + await this._doUpload(upload_url, uploadContent); + await gmHttp.post("https://api.aliyundrive.com/v2/file/complete", data = { + drive_id, + file_id: upload_file_id, + upload_id + }, headers); + } + + _doUpload(upload_url, uploadContent) { + return new Promise(((resolve, reject) => { + $.ajax({ + type: "PUT", + url: upload_url, + data: uploadContent, + contentType: " ", + processData: false, + success: (res, status, xhr) => { + 200 === xhr.status ? resolve({}) : reject(xhr); + }, + error: (xhr) => { + clog.error("上传失败", xhr.responseText); + reject(xhr); + } + }); + })); + } + + async getDownloadUrl(file_id, drive_id = null) { + drive_id || (drive_id = await this.getDefaultDriveId()); + let url = this.baseApiUrl + "/v2/file/get_download_url"; + const headers = await this.getHeaders(); + let data = { + file_id, + drive_id + }; + return (await gmHttp.post(url, data, headers)).url; + } + + async _createBackupFolder(folderName) { + const fileList = await this.getFileList(); + let folderObj = null; + for (let i = 0; i < fileList.length; i++) { + let file = fileList[i]; + if (file.name === folderName) { + folderObj = file; + break; + } + } + if (!folderObj) { + show.info("不存在备份目录, 进行创建"); + folderObj = await this.createFolder(folderName); + } + this.backupFolderId = folderObj.file_id; + } + + async backup(folderName, fileName, uploadContent) { + if (this.backupFolderId) await this.uploadFile(this.backupFolderId, fileName, uploadContent); + else { + await this._createBackupFolder(folderName); + await this.uploadFile(this.backupFolderId, fileName, uploadContent); + } + } + + async getBackupList(folderName) { + let dataList; + if (this.backupFolderId) dataList = await this.getFileList(this.backupFolderId); + else { + await this._createBackupFolder(folderName); + dataList = await this.getFileList(this.backupFolderId); + } + const fileList = []; + dataList.forEach(((data) => { + fileList.push({ + name: data.name, + fileId: data.file_id, + createTime: data.created_at, + size: data.size + }); + })); + return fileList; + } + } + + class WebDavApi { + constructor(davUrl, username, password) { + this.davUrl = davUrl.endsWith("/") ? davUrl : davUrl + "/"; + this.username = username; + this.password = password; + this.folderName = null; + } + + _getAuthHeaders() { + return { + Authorization: `Basic ${btoa(`${this.username}:${this.password}`)}`, + Depth: "1" + }; + } + + _sendRequest(method, path, headers = {}, data) { + return new Promise(((resolve, reject) => { + const url = this.davUrl + path, allHeaders = { + ...this._getAuthHeaders(), + ...headers }; - const getDmmGraphQLVideoUrls = async (code) => { - const contentItems = await searchDmmContentIdsByGraphQL(code); - if (!contentItems.length) return null; - const results = await Promise.allSettled( - contentItems.map((item) => extractTrailerLinks(item)) - ); - for (const result of results) { - if (result.status === "fulfilled" && result.value) { - return result.value; - } + _GM_xmlhttpRequest({ + method, + url, + headers: allHeaders, + data, + onload: (response) => { + if (response.status >= 200 && response.status < 300) resolve(response); + else { + console.error(response); + reject(new Error(`请求失败 ${response.status}: ${response.statusText}`)); } - return null; - }; - const extractTrailerLinks = (item) => { - const {contentId, serviceCode, floorCode} = item; - return new Promise((resolve, reject) => { - const trailerPageUrl = `https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${contentId}/mtype=AhRVShI_/service=${serviceCode}/floor=${floorCode}/mode=/`; - _GM_xmlhttpRequest({ - method: "GET", - url: trailerPageUrl, - timeout: 15e3, - headers: { - "accept-language": "ja-JP,ja;q=0.9", - Cookie: "age_check_done=1" - }, - onload: (response) => { - const htmlContent = response.responseText || ""; - if (htmlContent.includes("このサービスはお住まいの地域からは")) { - reject(new Error("节点不可用,请将DMM域名分流到日本ip")); - return; - } - const match = htmlContent.match(/const\s+args\s+=\s+(.*);/); - if (!match) { - reject(new Error("未在脚本中找到 const args = ... 变量")); - return; - } - let bitrates; - try { - bitrates = JSON.parse(match[1]).bitrates; - } catch (e) { - reject(new Error(`解析播放器脚本 JSON 失败: ${e.message}`)); - return; - } - if (!Array.isArray(bitrates)) { - reject(new Error("解析画质链接失败: bitrates 字段不是一个数组或不存在")); - return; - } - const qualityKeys = [ - "4ks", - "4k", - "hhbs", - "hhb", - "hmb", - "mhb", - "mmb", - "dmb_w", - "dmb_s", - "dm_s", - "sm_s", - "mhb_w" - ]; - const qualityNameRegex = new RegExp(`(${qualityKeys.join("|")})\\.mp4$`); - const finalQualityMap = {}; - for (const bitrate of bitrates) { - const url = bitrate && bitrate.src; - if (!url || typeof url !== "string" || !url.endsWith(".mp4")) continue; - const qualityMatch = url.match(qualityNameRegex); - let qualityKey = ""; - if (qualityMatch && qualityMatch[1]) qualityKey = qualityMatch[1]; - if (qualityKey && !finalQualityMap[qualityKey]) { - finalQualityMap[qualityKey] = url; - } - } - if (Object.keys(finalQualityMap).length === 0) { - reject(new Error("未找到匹配要求的预览画质视频")); - return; - } - resolve(finalQualityMap); - }, - onerror: () => reject(new Error("DMM 播放页请求网络错误")), - ontimeout: () => reject(new Error("DMM 播放页请求超时")) - }); - }); - }; - const selectDefaultQuality = (dmmVideoQualityList, intendedDefault) => { - if (!dmmVideoQualityList || 0 === dmmVideoQualityList.length) return null; - const availableSet = new Set(dmmVideoQualityList); - if (availableSet.has(intendedDefault)) return intendedDefault; - const priorityOrder = qualityOptions.map(((option) => option.quality)).reverse(); - for (const quality of priorityOrder) if (availableSet.has(quality)) return quality; - return dmmVideoQualityList[0]; - }, CACHE_KEY = "jhs_dmm_video"; + }, + onerror: (response) => { + console.error("请求WebDav发生错误:", response); + reject(new Error("请求WebDav失败, 请检查服务是否启动, 凭证是否正确")); + } + }); + })); + } - class DmmVideoFetcher { - constructor(carNum2, showErrorMessages = true) { - this.carNum = carNum2; - this.showErrorMessages = showErrorMessages; - } + async backup(folderName, fileName, uploadContent) { + await this._sendRequest("MKCOL", folderName); + const path = folderName + "/" + fileName; + await this._sendRequest("PUT", path, { + "Content-Type": "text/plain" + }, uploadContent); + } - _checkCache() { - const cachedData = localStorage.getItem(CACHE_KEY) ? JSON.parse(localStorage.getItem(CACHE_KEY)) : {}; - if (cachedData[this.carNum]) { - clog.debug("缓存中存在预览视频信息", cachedData[this.carNum]); - return cachedData[this.carNum]; - } - return null; - } + async getFileList(folderName) { + var _a2, _b, _c; + const xmlResponse = (await this._sendRequest("PROPFIND", folderName, { + "Content-Type": "application/xml" + }, '\n \n \n \n \n \n \n \n \n \n ')).responseText, + items = new DOMParser().parseFromString(xmlResponse, "text/xml").getElementsByTagNameNS("DAV:", "response"), + fileList = []; + for (let i = 0; i < items.length; i++) { + if (0 === i) continue; + let item = items[i]; + console.log(item); + const name2 = item.getElementsByTagNameNS("DAV:", "displayname")[0].textContent, + size = (null == (_a2 = item.getElementsByTagNameNS("DAV:", "getcontentlength")[0]) ? void 0 : _a2.textContent) || "0", + createTime = (null == (_b = item.getElementsByTagNameNS("DAV:", "creationdate")[0]) ? void 0 : _b.textContent) || (null == (_c = item.getElementsByTagNameNS("DAV:", "getlastmodified")[0]) ? void 0 : _c.textContent) || ""; + "0" !== size && fileList.push({ + fileId: name2, + name: name2, + size: Number(size), + createTime + }); + } + fileList.reverse(); + return fileList; + } - _updateCache(videoMap) { - const cachedData = localStorage.getItem(CACHE_KEY) ? JSON.parse(localStorage.getItem(CACHE_KEY)) : {}; - cachedData[this.carNum] = videoMap; - clog.debug("成功解析出预览视频并已缓存:", videoMap); - localStorage.setItem(CACHE_KEY, JSON.stringify(cachedData)); - } + async deleteFile(fileId) { + let path = this.folderName + "/" + encodeURI(fileId); + await this._sendRequest("DELETE", path, { + "Cache-Control": "no-cache" + }); + } - async _searchContentIds() { - const carNum2 = this.carNum, carNumNoHyphen = carNum2.replace(/-/g, ""), keywordAttempts = [{ - keyword: carNum2.replace("-", "00"), - name: "00-替换关键词" - }, { - keyword: carNum2, - name: "原始番号关键词" - }, { - keyword: carNumNoHyphen, - name: "无连字符关键词" - }], carNumLower = carNum2.toLowerCase(); - for (const attempt of keywordAttempts) { - const {keyword, name: name2} = attempt, currentTempCarNumLower = keyword.toLowerCase(), - apiUrl2 = `https://api.dmm.com/affiliate/v3/ItemList?${new URLSearchParams({ - api_id: "UrwskPfkqQ0DuVry2gYL", - affiliate_id: "10278-996", - output: "json", - site: "FANZA", - sort: "match", - keyword - }).toString()}`; - let response; - try { - response = await gmHttp.get(apiUrl2); - } catch (e) { - clog.error(`API 请求失败,跳过 ${name2}:`, e); - continue; - } - if (!response || !response.result || !response.result.result_count) { - clog.debug(`使用 ${name2} (${keyword}) 进行 API 搜索 返回无结果,尝试下一个关键词。`); - continue; - } - const newItems = []; - for (const item of response.result.items) { - if (newItems.length >= 2) break; - const contentId = item.content_id || "", makerProduct = item.maker_product || ""; - if (contentId.includes(currentTempCarNumLower.replace("-", "")) || carNumLower === makerProduct.toLowerCase() || contentId.includes(carNumNoHyphen.toLowerCase())) { - newItems.push({ - serviceCode: item.service_code, - floorCode: item.floor_code, - contentId, - pageUrl: item.URL - }); - clog.debug(`[${name2}] cid|makerProduct 匹配成功:`, contentId, makerProduct); - } - } - if (newItems.length > 0) { - clog.debug(`--- 成功通过 ${name2} 找到 Content IDs ---`); - const $btn2 = $("#fanzaBtn"); - let url = `https://www.dmm.co.jp/search/=/searchstr=${keyword}`, type = "single"; - if (newItems.length > 1) { - $btn2.attr("href", url); - $btn2.append('多结果'); - $btn2.css("backgroundColor", "#7bc73b"); - type = "multiple"; - } else { - url = newItems[0].pageUrl; - $btn2.attr("href", url); - $btn2.css("backgroundColor", "#7bc73b"); - } - const dmmCacheKey = "jhs_other_site_dmm", - dmmCacheData = localStorage.getItem(dmmCacheKey) ? JSON.parse(localStorage.getItem(dmmCacheKey)) : {}; - dmmCacheData[this.carNum] = { - type, - url - }; - localStorage.setItem(dmmCacheKey, JSON.stringify(dmmCacheData)); - return newItems; - } - clog.debug(`[${name2}] API 返回结果数 ${response.result.result_count},但无精确匹配的 Content ID。`); - } - clog.warn("所有关键词尝试均未找到匹配的Content ID, 解析Dmm视频失败"); - const $btn = $("#fanzaBtn"); - $btn.attr("href", `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}`); - $btn.attr("title", "未查询到, 点击前往搜索页"); - $btn.css("backgroundColor", "#de3333"); - return null; - } + async getBackupList(folderName) { + this.folderName = folderName; + await this._sendRequest("MKCOL", folderName); + return this.getFileList(folderName); + } - async _extractTrailerLinks({contentId, serviceCode, floorCode}) { - const trailerPageUrl = `https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${contentId}/mtype=AhRVShI_/service=${serviceCode}/floor=${floorCode}/mode=/`, - htmlContent = await gmHttp.get(trailerPageUrl, null, { - "accept-language": "ja-JP,ja;q=0.9", - Cookie: "age_check_done=1" - }); - if ("string" != typeof htmlContent) { - clog.error(htmlContent); - throw new Error("解析播放页内容失败, 非文本内容"); - } - if (htmlContent.includes("このサービスはお住まいの地域からは")) throw new Error("节点不可用,请将DMM域名分流到日本ip"); - const match = htmlContent.match(/const\s+args\s+=\s+(.*);/); - if (!match) throw new Error("未在脚本中找到 const args = ... 变量"); - let bitrates; - try { - ({bitrates} = JSON.parse(match[1])); - } catch (e) { - throw new Error(`解析播放器脚本 JSON 失败: ${e.message}`); - } - const finalQualityMap = {}, qualityKeys = qualityOptions.map(((o) => o.quality)).join("|"), - qualityNameRegex = new RegExp(`(${qualityKeys})\\.mp4$`); - if (!Array.isArray(bitrates)) { - clog.error("解析画质链接失败: bitrates 字段不是一个数组或不存在"); - throw new Error("解析画质链接失败: bitrates 字段不是一个数组或不存在"); - } - clog.debug("原始数据返回:", bitrates); - for (const item of bitrates) { - const url = null == item ? void 0 : item.src; - if (!url || "string" != typeof url || !url.endsWith(".mp4")) continue; - const qualityMatch = url.match(qualityNameRegex); - let qualityKey = ""; - qualityMatch && qualityMatch[1] && (qualityKey = qualityMatch[1]); - qualityKey && !finalQualityMap[qualityKey] && (finalQualityMap[qualityKey] = url); - } - if (0 === Object.keys(finalQualityMap).length) throw new Error("未找到匹配要求的预览画质视频"); - return finalQualityMap; - } + async getFileContent(filePath) { + let path = this.folderName + "/" + filePath; + return (await this._sendRequest("GET", path, { + Accept: "application/octet-stream" + })).responseText; + } + } - async _searchViaGraphQL() { - clog.debug("尝试通过 GraphQL API 搜索视频..."); - const videoMap = await getDmmGraphQLVideoUrls(this.carNum); - if (videoMap && Object.keys(videoMap).length > 0) { - this._updateCache(videoMap); - clog.debug("GraphQL 成功解析出预览视频:", videoMap); - const dmmCacheKey = "jhs_other_site_dmm"; - const dmmCacheData = localStorage.getItem(dmmCacheKey) ? JSON.parse(localStorage.getItem(dmmCacheKey)) : {}; - dmmCacheData[this.carNum] = { - type: "graphql", - url: `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}` - }; - localStorage.setItem(dmmCacheKey, JSON.stringify(dmmCacheData)); - return videoMap; - } - return null; - } + const SALT = "x7k9p3"; - async fetchVideo() { - const cachedResult = this._checkCache(); - if (cachedResult) return cachedResult; - let contentItems; - try { - const testCarNum = this.carNum.toLowerCase(); - if (testCarNum.startsWith("heyzo") || /^(n\d+|\d+(-\d+)*)$/.test(testCarNum) || /^n\d+$/.test(testCarNum)) throw new Error("无码番号类型, 取消dmm解析"); - if (this.carNum.includes("VR-")) throw new Error("VR类型, 取消dmm解析"); - contentItems = await this._searchContentIds(); - } catch (e) { - clog.error("DMM API 搜索失败:", e); - } - if (!contentItems || 0 === contentItems.length) { - clog.warn("Affiliate API 未找到视频,尝试 GraphQL API..."); - const graphQLResult = await this._searchViaGraphQL(); - if (graphQLResult) return graphQLResult; - const $btn = $("#fanzaBtn"); - $btn.attr("href", `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}`); - $btn.attr("title", "未查询到, 点击前往搜索页"); - $btn.css("backgroundColor", "#de3333"); - return null; - } - try { - const finalVideoMap = await Promise.any(contentItems.map(((item) => this._extractTrailerLinks(item)))); - this._updateCache(finalVideoMap); - return finalVideoMap; - } catch (error) { - const errors = error.errors || [error]; - clog.error(`Affiliate 解析失败: ${errors[0] && errors[0].message || errors[0]}`, errors); - clog.warn("尝试 GraphQL API 作为 fallback..."); - const graphQLResult = await this._searchViaGraphQL(); - if (graphQLResult) return graphQLResult; - if (errors.some(((err) => err.message.includes("节点不可用")))) this.showErrorMessages && show.error("节点不可用,请将DMM域名分流到日本ip"); - else { - const displayError = errors[0].message || errors[0]; - this.showErrorMessages && show.error(`解析失败: ${displayError}`); - } - const $btn = $("#fanzaBtn"); - $btn.attr("href", `https://www.dmm.co.jp/search/=/searchstr=${this.carNum}`); - $btn.attr("title", "未查询到, 点击前往搜索页"); - $btn.css("backgroundColor", "#de3333"); - return null; - } - } - } + function simpleEncrypt(str) { + return (SALT + str + SALT).split("").map(((char) => { + const code = char.codePointAt(0); + return String.fromCodePoint(code + 5); + })).join(""); + } - const getDmmVideo = async (carNum2, showErrorMessages = true) => new DmmVideoFetcher(carNum2, showErrorMessages).fetchVideo(); + class SettingPlugin extends BasePlugin { + constructor() { + super(...arguments); + __publicField2(this, "folderName", "JHS-数据备份"); + __publicField2(this, "cacheItems", [{ + key: "jhs_dmm_video", + text: "🎥 预览视频缓存", + title: "预览视频缓存" + }, { + key: "jhs_other_site", + text: "🌍 第三方站点缓存", + title: "第三方站点资源检测结果, 如missav,123Av等" + }, { + key: "jhs_screenShot", + text: "🖼️ 缩略图缓存", + title: "缩略图缓存" + }, { + key: "jhs_translate", + text: "🆎 标题翻译", + title: "标题翻译" + }, { + key: "jhs_actress_info", + text: "👩 演员信息", + title: "演员的年龄三围等数据信息" + }, { + key: "jhs_score_info", + text: "⭐ Top250|热播 评分数据", + title: "Top250及热播的评分数据" + }]); + } - class AutoPagePlugin extends BasePlugin { - constructor() { - super(...arguments); - __publicField2(this, "preloadDistance", 500); - __publicField2(this, "currentPage", this.getInitialPageNumber()); - __publicField2(this, "pageItems", []); - } + getName() { + return "SettingPlugin"; + } - getName() { - return "AutoPagePlugin"; - } - - async initCss() { - return "\n \n "; - } - - async handle() { - this.waterfall().then(); - } - - getInitialPageNumber() { - if (isJavBus$1) { - const match = currentHref$1.match(/\/(page|star\/[^/]+)\/(\d+)/); - return match ? parseInt(match[2], 10) : 1; - } - if (isJavDb$1) { - const match = currentHref$1.match(/[?&]page=(\d+)/); - return match ? parseInt(match[1], 10) : 1; - } - return 1; - } - - async waterfall() { - if (await this.shouldDisablePaging()) return; - const selector = this.getSelector(); - this.container = document.querySelector(selector.boxSelector); - if (!this.container) { - console.error("没有找到容器节点,停止瀑布流!"); - return; - } - this.loader = document.createElement("div"); - this.loader.className = "jhs-scroll"; - this.container.parentNode.insertBefore(this.loader, this.container.nextSibling); - this.pageItems.push({ - page: this.currentPage, - top: 0, - url: window.location.href - }); - this.loader.addEventListener("click", (() => { - this.loader.classList.contains("waterfall-error") && this.loadNextPage().then(); - })); - window.addEventListener("scroll", (() => { - this.checkLoad(); - this.checkScrollPosition(); - })); - const nextLink = document.querySelector(selector.nextPageSelector); - this.nextUrl = null == nextLink ? void 0 : nextLink.href; - this.hasMore = !!this.nextUrl; - setTimeout((() => { - this.checkLoad(); - }), 1e3); - this.hasMore || this.setState("waterfall-no-more", "已经到底了"); - } - - async loadNextPage() { - var _a2; - if (await storageManager.getSetting("autoPage", YES$1) === NO) { - this.setState("waterfall-loading", ""); - return; - } - if (this.isLoading || !this.nextUrl) return; - this.isLoading = true; - this.setState("waterfall-loading", "加载中..."); - const selector = this.getSelector(); - try { - const pageNum = utils.getUrlParam(this.nextUrl, "page"); - let maxPage = 60; - currentHref$1.includes("c11") && (maxPage = 30); - if (isJavDb$1 && pageNum > maxPage || currentHref$1.includes("month")) { - const beyond60Plugin = this.getBean("Beyond60Plugin"); - if (beyond60Plugin) { - const { - html: html2, - nextUrl, - hasMore - } = await beyond60Plugin.handleBeyond60(this.nextUrl); - if (html2) { - const pageTop2 = this.container.scrollHeight; - this.pageItems.push({ - page: this.currentPage + 1, - top: pageTop2, - url: this.nextUrl - }); - $(".movie-list").append(html2); - } - this.hasMore = hasMore; - this.nextUrl = nextUrl; - const $ul = beyond60Plugin.createPagination(pageNum, hasMore); - $(".pagination").html($ul); - this.setState("waterfall-loading", ""); - this.hasMore || this.setState("waterfall-no-more", "已经到底了"); - return; - } - } - const html = await gmHttp.get(this.nextUrl); - clog.log("请求下一页内容:", this.nextUrl); - const $dom = utils.htmlTo$dom(html); - isJavBus$1 && $dom.find(".avatar-box").length > 0 && $dom.find(".avatar-box").parent().remove(); - let itemList = $dom.find(this.getSelector().requestDomItemSelector); - const currentBoxCarInfoList = this.getBoxCarInfoList(), - nextPageBoxCarInfoList = this.getBoxCarInfoList(itemList); - if (this.checkDuplicateCarNumbers(currentBoxCarInfoList, nextPageBoxCarInfoList)) { - this.nextUrl = null; - this.hasMore = false; - this.setState("waterfall-error", "翻页内容出现重复数据, 可能首页已更新了新视频 或 页码受JavDB限制, 停止瀑布流"); - return; - } - const pageTop = this.container.scrollHeight; - this.pageItems.push({ - page: this.currentPage + 1, - top: pageTop, - url: this.nextUrl - }); - const listPagePlugin = this.getBean("ListPagePlugin"); - let coverImgNodeList = $dom.find(this.getSelector().coverImgSelector); - listPagePlugin.replaceHdImg(coverImgNodeList); - $(this.getSelector().boxSelector).append(itemList); - this.nextUrl = null == (_a2 = $dom.find(selector.nextPageSelector)) ? void 0 : _a2.attr("href"); - this.hasMore = !!this.nextUrl; - let pagination = $dom.find(".pagination"); - $(".pagination").replaceWith(pagination); - this.setState("waterfall-loading", ""); - this.hasMore || this.setState("waterfall-no-more", "已经到底了"); - } catch (e) { - clog.error("加载失败:", e); - this.setState("waterfall-error", "加载失败,点击重试"); - } finally { - this.isLoading = false; - } - } - - checkScrollPosition() { - const scrollPosition = window.scrollY; - for (let i = this.pageItems.length - 1; i >= 0; i--) { - const page = this.pageItems[i]; - if (scrollPosition >= page.top) { - if (this.currentPage !== page.page) { - this.currentPage = page.page; - this.updatePageUrl(page.url); - } - break; - } - } - } - - checkLoad() { - if (!this.loader) return; - this.loader.getBoundingClientRect().top < window.innerHeight + this.preloadDistance && this.loadNextPage().then(); - } - - async shouldDisablePaging() { - if (!window.isListPage) return true; - await storageManager.getSetting("autoPage", YES$1); - return ["search?q", "handlePlayback=1", "handleTop=1", "/want_watch_videos", "/watched_videos", "/advanced_search?type=100"].some(((path) => currentHref$1.includes(path))); - } - - updatePageUrl_old(href) { - window.history.pushState({}, "", href); - if (isJavBus$1) { - const match = href.match(/\/(page|star\/.*?)\/(\d+)/), - pageNumber = match ? parseInt(match[2], 10) : null; - document.title = document.title.replace(/第\d+頁/, "第" + pageNumber + "頁"); - } - } - - updatePageUrl(url) { - window.history.replaceState({}, "", url); - isJavBus$1 && (document.title = document.title.replace(/第\d+頁/, `第${this.currentPage}頁`)); - } - - setState(state, text) { - this.loader.className = `jhs-scroll ${state}`; - this.loader.textContent = text; - } - } - - class AliyunApi { - constructor(refresh_token) { - this.baseApiUrl = "https://api.aliyundrive.com"; - this.refresh_token = refresh_token; - this.authorization = null; - this.default_drive_id = null; - this.backupFolderId = null; - } - - async getDefaultDriveId() { - if (this.default_drive_id) return this.default_drive_id; - this.userInfo = await this.getUserInfo(); - this.default_drive_id = this.userInfo.default_drive_id; - return this.default_drive_id; - } - - async getHeaders() { - if (this.authorization) return { - authorization: this.authorization - }; - this.authorization = await this.getAuthorization(); - return { - authorization: this.authorization - }; - } - - async getAuthorization() { - let url = this.baseApiUrl + "/v2/account/token", data = { - refresh_token: this.refresh_token, - grant_type: "refresh_token" - }; - try { - return "Bearer " + (await gmHttp.post(url, data)).access_token; - } catch (e) { - throw e.message.includes("is not valid") ? new Error("refresh_token无效, 请重新填写并保存") : e; - } - } - - async getUserInfo() { - const headers = await this.getHeaders(); - let url = this.baseApiUrl + "/v2/user/get"; - return await gmHttp.post(url, {}, headers); - } - - async deleteFile(file_id, drive_id = null) { - if (!file_id) throw new Error("未传入file_id"); - drive_id || (drive_id = await this.getDefaultDriveId()); - let data = { - file_id, - drive_id - }, url = this.baseApiUrl + "/v2/recyclebin/trash"; - const headers = await this.getHeaders(); - await gmHttp.post(url, data, headers); - return {}; - } - - async createFolder(name2, drive_id = null, parent_folder_id = "root") { - drive_id || (drive_id = await this.getDefaultDriveId()); - let url = this.baseApiUrl + "/adrive/v2/file/createWithFolders", data = { - name: name2, - type: "folder", - parent_file_id: parent_folder_id, - check_name_mode: "auto_rename", - content_hash_name: "sha1", - drive_id - }; - const headers = await this.getHeaders(); - return await gmHttp.post(url, data, headers); - } - - async getFileList(parent_folder_id = "root", drive_id = null) { - drive_id || (drive_id = await this.getDefaultDriveId()); - let url = this.baseApiUrl + "/adrive/v3/file/list"; - const data = { - drive_id, - parent_file_id: parent_folder_id, - limit: 200, - all: false, - url_expire_sec: 14400, - image_thumbnail_process: "image/resize,w_256/format,avif", - image_url_process: "image/resize,w_1920/format,avif", - video_thumbnail_process: "video/snapshot,t_120000,f_jpg,m_lfit,w_256,ar_auto,m_fast", - fields: "*", - order_by: "updated_at", - order_direction: "DESC" - }, headers = await this.getHeaders(); - return (await gmHttp.post(url, data, headers)).items; - } - - async uploadFile(folder_id, fileName, uploadContent, drive_id = null) { - show.info("请求存储空间中..."); - let createFileUrl = this.baseApiUrl + "/adrive/v2/file/createWithFolders"; - drive_id || (drive_id = await this.getDefaultDriveId()); - let data = { - drive_id, - part_info_list: [{ - part_number: 1 - }], - parent_file_id: folder_id, - name: fileName, - type: "file", - check_name_mode: "auto_rename" - }; - const headers = await this.getHeaders(), - createFileResult = await gmHttp.post(createFileUrl, data, headers), - upload_id = createFileResult.upload_id, upload_file_id = createFileResult.file_id, - upload_url = createFileResult.part_info_list[0].upload_url; - show.info("开始上传文件..."); - await this._doUpload(upload_url, uploadContent); - await gmHttp.post("https://api.aliyundrive.com/v2/file/complete", data = { - drive_id, - file_id: upload_file_id, - upload_id - }, headers); - } - - _doUpload(upload_url, uploadContent) { - return new Promise(((resolve, reject) => { - $.ajax({ - type: "PUT", - url: upload_url, - data: uploadContent, - contentType: " ", - processData: false, - success: (res, status, xhr) => { - 200 === xhr.status ? resolve({}) : reject(xhr); - }, - error: (xhr) => { - clog.error("上传失败", xhr.responseText); - reject(xhr); - } - }); - })); - } - - async getDownloadUrl(file_id, drive_id = null) { - drive_id || (drive_id = await this.getDefaultDriveId()); - let url = this.baseApiUrl + "/v2/file/get_download_url"; - const headers = await this.getHeaders(); - let data = { - file_id, - drive_id - }; - return (await gmHttp.post(url, data, headers)).url; - } - - async _createBackupFolder(folderName) { - const fileList = await this.getFileList(); - let folderObj = null; - for (let i = 0; i < fileList.length; i++) { - let file = fileList[i]; - if (file.name === folderName) { - folderObj = file; - break; - } - } - if (!folderObj) { - show.info("不存在备份目录, 进行创建"); - folderObj = await this.createFolder(folderName); - } - this.backupFolderId = folderObj.file_id; - } - - async backup(folderName, fileName, uploadContent) { - if (this.backupFolderId) await this.uploadFile(this.backupFolderId, fileName, uploadContent); - else { - await this._createBackupFolder(folderName); - await this.uploadFile(this.backupFolderId, fileName, uploadContent); - } - } - - async getBackupList(folderName) { - let dataList; - if (this.backupFolderId) dataList = await this.getFileList(this.backupFolderId); - else { - await this._createBackupFolder(folderName); - dataList = await this.getFileList(this.backupFolderId); - } - const fileList = []; - dataList.forEach(((data) => { - fileList.push({ - name: data.name, - fileId: data.file_id, - createTime: data.created_at, - size: data.size - }); - })); - return fileList; - } - } - - class WebDavApi { - constructor(davUrl, username, password) { - this.davUrl = davUrl.endsWith("/") ? davUrl : davUrl + "/"; - this.username = username; - this.password = password; - this.folderName = null; - } - - _getAuthHeaders() { - return { - Authorization: `Basic ${btoa(`${this.username}:${this.password}`)}`, - Depth: "1" - }; - } - - _sendRequest(method, path, headers = {}, data) { - return new Promise(((resolve, reject) => { - const url = this.davUrl + path, allHeaders = { - ...this._getAuthHeaders(), - ...headers - }; - _GM_xmlhttpRequest({ - method, - url, - headers: allHeaders, - data, - onload: (response) => { - if (response.status >= 200 && response.status < 300) resolve(response); - else { - console.error(response); - reject(new Error(`请求失败 ${response.status}: ${response.statusText}`)); - } - }, - onerror: (response) => { - console.error("请求WebDav发生错误:", response); - reject(new Error("请求WebDav失败, 请检查服务是否启动, 凭证是否正确")); - } - }); - })); - } - - async backup(folderName, fileName, uploadContent) { - await this._sendRequest("MKCOL", folderName); - const path = folderName + "/" + fileName; - await this._sendRequest("PUT", path, { - "Content-Type": "text/plain" - }, uploadContent); - } - - async getFileList(folderName) { - var _a2, _b, _c; - const xmlResponse = (await this._sendRequest("PROPFIND", folderName, { - "Content-Type": "application/xml" - }, '\n \n \n \n \n \n \n \n \n \n ')).responseText, - items = new DOMParser().parseFromString(xmlResponse, "text/xml").getElementsByTagNameNS("DAV:", "response"), - fileList = []; - for (let i = 0; i < items.length; i++) { - if (0 === i) continue; - let item = items[i]; - console.log(item); - const name2 = item.getElementsByTagNameNS("DAV:", "displayname")[0].textContent, - size = (null == (_a2 = item.getElementsByTagNameNS("DAV:", "getcontentlength")[0]) ? void 0 : _a2.textContent) || "0", - createTime = (null == (_b = item.getElementsByTagNameNS("DAV:", "creationdate")[0]) ? void 0 : _b.textContent) || (null == (_c = item.getElementsByTagNameNS("DAV:", "getlastmodified")[0]) ? void 0 : _c.textContent) || ""; - "0" !== size && fileList.push({ - fileId: name2, - name: name2, - size: Number(size), - createTime - }); - } - fileList.reverse(); - return fileList; - } - - async deleteFile(fileId) { - let path = this.folderName + "/" + encodeURI(fileId); - await this._sendRequest("DELETE", path, { - "Cache-Control": "no-cache" - }); - } - - async getBackupList(folderName) { - this.folderName = folderName; - await this._sendRequest("MKCOL", folderName); - return this.getFileList(folderName); - } - - async getFileContent(filePath) { - let path = this.folderName + "/" + filePath; - return (await this._sendRequest("GET", path, { - Accept: "application/octet-stream" - })).responseText; - } - } - - const SALT = "x7k9p3"; - - function simpleEncrypt(str) { - return (SALT + str + SALT).split("").map(((char) => { - const code = char.codePointAt(0); - return String.fromCodePoint(code + 5); - })).join(""); - } - - class SettingPlugin extends BasePlugin { - constructor() { - super(...arguments); - __publicField2(this, "folderName", "JHS-数据备份"); - __publicField2(this, "cacheItems", [{ - key: "jhs_dmm_video", - text: "🎥 预览视频缓存", - title: "预览视频缓存" - }, { - key: "jhs_other_site", - text: "🌍 第三方站点缓存", - title: "第三方站点资源检测结果, 如missav,123Av等" - }, { - key: "jhs_screenShot", - text: "🖼️ 缩略图缓存", - title: "缩略图缓存" - }, { - key: "jhs_translate", - text: "🆎 标题翻译", - title: "标题翻译" - }, { - key: "jhs_actress_info", - text: "👩 演员信息", - title: "演员的年龄三围等数据信息" - }, { - key: "jhs_score_info", - text: "⭐ Top250|热播 评分数据", - title: "Top250及热播的评分数据" - }]); - } - - getName() { - return "SettingPlugin"; - } - - async initCss() { - const settingObj = await storageManager.getSetting(); - let containerWidth = (null == settingObj ? void 0 : settingObj.containerWidth) ?? "100", - containerColumns = utils.isMobile() && window.innerWidth < 1e3 ? 1 : (null == settingObj ? void 0 : settingObj.containerColumns) ?? 5; - this.applyImageMode().then(); - let containerWidthCss = ` + async initCss() { + const settingObj = await storageManager.getSetting(); + let containerWidth = (null == settingObj ? void 0 : settingObj.containerWidth) ?? "100", + containerColumns = utils.isMobile() && window.innerWidth < 1e3 ? 1 : (null == settingObj ? void 0 : settingObj.containerColumns) ?? 5; + this.applyImageMode().then(); + let containerWidthCss = ` section .container{ max-width: 1000px !important; min-width: ${containerWidth}%; @@ -3897,7 +3874,7 @@ ${value}\r grid-template-columns: repeat(${containerColumns}, minmax(0, 1fr)); } `; - isJavBus$1 && (containerWidthCss = ` + isJavBus$1 && (containerWidthCss = ` .container-fluid .row{ max-width: 1000px !important; min-width: ${containerWidth}%; @@ -3914,7 +3891,7 @@ ${value}\r grid-template-columns: repeat(${containerColumns}, minmax(0, 1fr)); } `); - return ` + return ` `; - } + } - async handle() { - await storageManager.getSetting("enableClog", YES$1) === YES$1 && clog.show(); - if (isJavDb$1) { - let handleResize2 = function () { - if ($(".navbar-search").is(":hidden")) { - $(".mini-setting-box").hide(); - $(".setting-box").show(); - } else { - $(".mini-setting-box").show(); - $(".setting-box").hide(); - } - }; - $("#navbar-menu-user .navbar-end").prepend(''); - utils.loopDetector((() => $("#miniHistoryBtn").length > 0), (() => { - $(".miniHistoryBtnBox").before('\n \n '); - handleResize2(); - })); - $(window).resize(handleResize2); - } - if (isJavBus$1) { - utils.loopDetector((() => $("#waitCheckBtn").length), (() => { - $("#waitCheckBtn").parent().append('\n
\n
\n \n 设置\n \n
\n
\n
\n '); - }), 1, 1e4, false); - window.isDetailPage && $("h3").before('\n
\n
\n
\n \n 设置\n \n
\n
\n
\n
\n '); - } - $(".main-nav, .container-fluid").on("click", "#setting-btn, #mini-setting-btn", (() => { - clog.lowZIndex(); - this.openSettingDialog(); - })); - $(".main-nav, .container-fluid").on("mouseenter", ".setting-box", (async () => { - $(".simple-setting").html(await this.simpleSetting()).show(); - this.initSimpleSettingForm().then(); - clog.lowZIndex(); - })).on("mouseleave", ".setting-box", (() => { - $(".simple-setting").html("").hide(); - })); - $(".main-nav, .container-fluid").on("mouseenter", ".mini-setting-box", (async () => { - $(".mini-simple-setting").html(await this.simpleSetting()).show(); - this.initSimpleSettingForm().then(); - clog.lowZIndex(); - })).on("mouseleave", ".mini-setting-box", (() => { - $(".mini-simple-setting").html("").hide(); - })); - } + async handle() { + await storageManager.getSetting("enableClog", YES$1) === YES$1 && clog.show(); + if (isJavDb$1) { + let handleResize2 = function () { + if ($(".navbar-search").is(":hidden")) { + $(".mini-setting-box").hide(); + $(".setting-box").show(); + } else { + $(".mini-setting-box").show(); + $(".setting-box").hide(); + } + }; + $("#navbar-menu-user .navbar-end").prepend(''); + utils.loopDetector((() => $("#miniHistoryBtn").length > 0), (() => { + $(".miniHistoryBtnBox").before('\n \n '); + handleResize2(); + })); + $(window).resize(handleResize2); + } + if (isJavBus$1) { + utils.loopDetector((() => $("#waitCheckBtn").length), (() => { + $("#waitCheckBtn").parent().append('\n
\n
\n \n 设置\n \n
\n
\n
\n '); + }), 1, 1e4, false); + window.isDetailPage && $("h3").before('\n
\n
\n
\n \n 设置\n \n
\n
\n
\n
\n '); + } + $(".main-nav, .container-fluid").on("click", "#setting-btn, #mini-setting-btn", (() => { + clog.lowZIndex(); + this.openSettingDialog(); + })); + $(".main-nav, .container-fluid").on("mouseenter", ".setting-box", (async () => { + $(".simple-setting").html(await this.simpleSetting()).show(); + this.initSimpleSettingForm().then(); + clog.lowZIndex(); + })).on("mouseleave", ".setting-box", (() => { + $(".simple-setting").html("").hide(); + })); + $(".main-nav, .container-fluid").on("mouseenter", ".mini-setting-box", (async () => { + $(".mini-simple-setting").html(await this.simpleSetting()).show(); + this.initSimpleSettingForm().then(); + clog.lowZIndex(); + })).on("mouseleave", ".mini-setting-box", (() => { + $(".mini-simple-setting").html("").hide(); + })); + } - async openSettingDialog(defaultActivePanel = "backup-panel", fun) { - const buttonsHTML = this.cacheItems.map(((item) => ` + async openSettingDialog(defaultActivePanel = "backup-panel", fun) { + const buttonsHTML = this.cacheItems.map(((item) => `
${item.text}
@@ -4203,12 +4180,12 @@ ${value}\r
`)).join(""); - let videoQualityHtml = ""; - qualityOptions.forEach(((option) => { - option.canSelect && (videoQualityHtml += ``); - })); - const coverButtonPlugin = this.getBean("CoverButtonPlugin"); - let settingHtml = ` + let videoQualityHtml = ""; + qualityOptions.forEach(((option) => { + option.canSelect && (videoQualityHtml += ``); + })); + const coverButtonPlugin = this.getBean("CoverButtonPlugin"); + let settingHtml = `
💾 数据备份
@@ -4845,35 +4822,35 @@ ${value}\r
`; - layer.open({ - type: 1, - title: "设置", - content: settingHtml, - area: utils.getResponsiveArea(["55%", "90%"]), - scrollbar: false, - success: (layero, index) => { - $(layero).find(".layui-layer-content").css("position", "relative"); - this.loadForm(); - this.bindClick(); - utils.setupEscClose(index); - fun && fun(); - }, - end: () => { - this.getBean("CoverButtonPlugin").enableSvgBtn(); - } - }); - } + layer.open({ + type: 1, + title: "设置", + content: settingHtml, + area: utils.getResponsiveArea(["55%", "90%"]), + scrollbar: false, + success: (layero, index) => { + $(layero).find(".layui-layer-content").css("position", "relative"); + this.loadForm(); + this.bindClick(); + utils.setupEscClose(index); + fun && fun(); + }, + end: () => { + this.getBean("CoverButtonPlugin").enableSvgBtn(); + } + }); + } - async simpleSetting() { - let settingObj = await storageManager.getSetting(); - const showFilterItemHotKey = settingObj.showFilterItemHotKey, - showFilterActorItemHotKey = settingObj.showFilterActorItemHotKey, - showFilterKeywordItemHotKey = settingObj.showFilterKeywordItemHotKey, - showFavoriteItemHotKey = settingObj.showFavoriteItemHotKey, - showHasDownItemHotKey = settingObj.showHasDownItemHotKey, - showHasWatchItemHotKey = settingObj.showHasWatchItemHotKey, - showAllItemHotKey = settingObj.showAllItemHotKey; - return ` + async simpleSetting() { + let settingObj = await storageManager.getSetting(); + const showFilterItemHotKey = settingObj.showFilterItemHotKey, + showFilterActorItemHotKey = settingObj.showFilterActorItemHotKey, + showFilterKeywordItemHotKey = settingObj.showFilterKeywordItemHotKey, + showFavoriteItemHotKey = settingObj.showFavoriteItemHotKey, + showHasDownItemHotKey = settingObj.showHasDownItemHotKey, + showHasWatchItemHotKey = settingObj.showHasWatchItemHotKey, + showAllItemHotKey = settingObj.showAllItemHotKey; + return `
@@ -4943,7 +4920,7 @@ ${value}\r
- ❓ 启用不规则重命名: + ❓ 不规则重命名 (详情页生效,有延迟):
@@ -5029,302 +5006,300 @@ ${value}\r
`; - } + } - async loadForm() { - let settingObj = await storageManager.getSetting(); - $("#videoQuality").val(settingObj.videoQuality); - $("#reviewCount").val(settingObj.reviewCount || 20); - $("#tagPosition").val(settingObj.tagPosition || "rightTop"); - $("#movieShowType").val(settingObj.movieShowType || "hide"); - $("#waitCheckCount").val(settingObj.waitCheckCount || 5); - $("#showWaitCheckBtn").prop("checked", !settingObj.showWaitCheckBtn || settingObj.showWaitCheckBtn === YES$1); - $("#showWaitDownBtn").prop("checked", !settingObj.showWaitDownBtn || settingObj.showWaitDownBtn === YES$1); - $("#randomOpenWaitDown").prop("checked", !!settingObj.randomOpenWaitDown && settingObj.randomOpenWaitDown === YES$1); - $("#checkConcurrencyCount").val(settingObj.checkConcurrencyCount || 2); - $("#checkRequestSleep").val(settingObj.checkRequestSleep || 100); - $("#enableCheckBlacklist").val(settingObj.enableCheckBlacklist || YES$1); - $("#checkBlacklist_intervalTime").val(settingObj.checkBlacklist_intervalTime || 12); - $("#checkBlacklist_ruleTime").val(settingObj.checkBlacklist_ruleTime || 8760); - $("#enableCheckFavoriteActress").val(settingObj.enableCheckFavoriteActress || YES$1); - $("#checkFavoriteActress_IntervalTime").val(settingObj.checkFavoriteActress_IntervalTime || 24); - $("#enableCheckNewVideo").val(settingObj.enableCheckNewVideo || YES$1); - $("#checkNewVideo_intervalTime").val(settingObj.checkNewVideo_intervalTime || 12); - $("#checkNewVideo_ruleTime").val(settingObj.checkNewVideo_ruleTime || 8760); - const highlightedTagNumber = settingObj.highlightedTagNumber || 1, - highlightedTagColor = settingObj.highlightedTagColor || "#ce2222"; - $("#highlightedTagNumber").val(settingObj.highlightedTagNumber || 1); - $("#highlightedTagColor").val(settingObj.highlightedTagColor || "#ce2222"); - $("#highlightedTagLabel").css("border", `${highlightedTagNumber}px solid ${highlightedTagColor}`); - $("#enableClog").val(settingObj.enableClog || YES$1); - $("#clogMsgCount").val(settingObj.clogMsgCount || 2e3); - $("#refresh_token").val(settingObj.refresh_token || ""); - $("#httpTimeout").val(settingObj.httpTimeout || 5e3); - $("#httpRetryCount").val(settingObj.httpRetryCount || 3); - $("#webDavUrl").val(settingObj.webDavUrl || ""); - $("#webDavUsername").val(settingObj.webDavUsername || ""); - $("#webDavPassword").val(settingObj.webDavPassword || ""); - $("#enableTitleSelectFilter").prop("checked", !settingObj.enableTitleSelectFilter || settingObj.enableTitleSelectFilter === YES$1); - $("#enableFavoriteActresses").prop("checked", !settingObj.enableFavoriteActresses || settingObj.enableFavoriteActresses === YES$1); - $("#enableSaveActressCarInfo").prop("checked", !!settingObj.enableSaveActressCarInfo && settingObj.enableSaveActressCarInfo === YES$1); - $("#enableScreenSvg").prop("checked", !settingObj.enableScreenSvg || settingObj.enableScreenSvg === YES$1); - $("#enableVideoSvg").prop("checked", !settingObj.enableVideoSvg || settingObj.enableVideoSvg === YES$1); - $("#enableHandleSvg").prop("checked", !settingObj.enableHandleSvg || settingObj.enableHandleSvg === YES$1); - $("#enableSiteSvg").prop("checked", !settingObj.enableSiteSvg || settingObj.enableSiteSvg === YES$1); - $("#enableCopySvg").prop("checked", !settingObj.enableCopySvg || settingObj.enableCopySvg === YES$1); - const otherSitePlugin = this.getBean("OtherSitePlugin"), - missAvUrl = await otherSitePlugin.getMissAvUrl(), - jableUrl = await otherSitePlugin.getjableUrl(), - javTrailersUrl = await otherSitePlugin.getJavTrailersUrl(), - av123Url = await otherSitePlugin.getAv123Url(), javDbUrl = await otherSitePlugin.getJavDbUrl(), - javBusUrl = await otherSitePlugin.getJavBusUrl(), - supJavUrl = await otherSitePlugin.getSupJavUrl(); - $("#missAvUrl").val(missAvUrl); - $("#jableUrl").val(jableUrl); - $("#javTrailersUrl").val(javTrailersUrl); - $("#av123Url").val(av123Url); - $("#javDbUrl").val(javDbUrl); - $("#javBusUrl").val(javBusUrl); - $("#supJavUrl").val(supJavUrl); - let reviewKeywordList = await storageManager.getReviewFilterKeywordList(), - filterKeywordList = await storageManager.getTitleFilterKeyword(); - reviewKeywordList && reviewKeywordList.forEach(((reviewKeyword) => { - this.addLabelTag("#reviewKeywordContainer", reviewKeyword); - })); - filterKeywordList && filterKeywordList.forEach(((reviewKeyword) => { - this.addLabelTag("#filterKeywordContainer", reviewKeyword); - })); - ["#reviewKeywordContainer", "#filterKeywordContainer"].forEach(((containerId) => { - $(`${containerId} .add-tag-btn`).on("click", ((event) => this.addKeyword(event, containerId))); - $(`${containerId} .keyword-input`).on("keypress", ((event) => { - "Enter" === event.key && this.addKeyword(event, containerId); - })); - })); - $("#hotkey-panel [id]").map(((i, el) => el.id)).get().forEach(((containerId) => { - const $element = $(`#${containerId}`), - defaultValue = void 0 !== settingObj[containerId] ? settingObj[containerId] : $element.attr("data-default-hotkey") || ""; - $element.val(defaultValue).on("input", ((event) => { - let value = $(event.target).val(); - if (/[\u4e00-\u9fa5]/.test(value) || /^Shift[a-zA-Z0-9]+$/.test(value)) { - $(event.target).val(""); - show.error("非法输入:不能输入中文或输入法转换错误"); - } - })).on("keydown", ((event) => this.handleHotkeyInput(event, $element))); - })); - $("#enableImageHotKey").prop("checked", !!settingObj.enableImageHotKey && settingObj.enableImageHotKey === YES$1); - } + async loadForm() { + let settingObj = await storageManager.getSetting(); + $("#videoQuality").val(settingObj.videoQuality); + $("#reviewCount").val(settingObj.reviewCount || 20); + $("#tagPosition").val(settingObj.tagPosition || "rightTop"); + $("#movieShowType").val(settingObj.movieShowType || "hide"); + $("#waitCheckCount").val(settingObj.waitCheckCount || 5); + $("#showWaitCheckBtn").prop("checked", !settingObj.showWaitCheckBtn || settingObj.showWaitCheckBtn === YES$1); + $("#showWaitDownBtn").prop("checked", !settingObj.showWaitDownBtn || settingObj.showWaitDownBtn === YES$1); + $("#randomOpenWaitDown").prop("checked", !!settingObj.randomOpenWaitDown && settingObj.randomOpenWaitDown === YES$1); + $("#checkConcurrencyCount").val(settingObj.checkConcurrencyCount || 2); + $("#checkRequestSleep").val(settingObj.checkRequestSleep || 100); + $("#enableCheckBlacklist").val(settingObj.enableCheckBlacklist || YES$1); + $("#checkBlacklist_intervalTime").val(settingObj.checkBlacklist_intervalTime || 12); + $("#checkBlacklist_ruleTime").val(settingObj.checkBlacklist_ruleTime || 8760); + $("#enableCheckFavoriteActress").val(settingObj.enableCheckFavoriteActress || YES$1); + $("#checkFavoriteActress_IntervalTime").val(settingObj.checkFavoriteActress_IntervalTime || 24); + $("#enableCheckNewVideo").val(settingObj.enableCheckNewVideo || YES$1); + $("#checkNewVideo_intervalTime").val(settingObj.checkNewVideo_intervalTime || 12); + $("#checkNewVideo_ruleTime").val(settingObj.checkNewVideo_ruleTime || 8760); + const highlightedTagNumber = settingObj.highlightedTagNumber || 1, + highlightedTagColor = settingObj.highlightedTagColor || "#ce2222"; + $("#highlightedTagNumber").val(settingObj.highlightedTagNumber || 1); + $("#highlightedTagColor").val(settingObj.highlightedTagColor || "#ce2222"); + $("#highlightedTagLabel").css("border", `${highlightedTagNumber}px solid ${highlightedTagColor}`); + $("#enableClog").val(settingObj.enableClog || YES$1); + $("#clogMsgCount").val(settingObj.clogMsgCount || 2e3); + $("#refresh_token").val(settingObj.refresh_token || ""); + $("#httpTimeout").val(settingObj.httpTimeout || 5e3); + $("#httpRetryCount").val(settingObj.httpRetryCount || 3); + $("#webDavUrl").val(settingObj.webDavUrl || ""); + $("#webDavUsername").val(settingObj.webDavUsername || ""); + $("#webDavPassword").val(settingObj.webDavPassword || ""); + $("#enableTitleSelectFilter").prop("checked", !settingObj.enableTitleSelectFilter || settingObj.enableTitleSelectFilter === YES$1); + $("#enableFavoriteActresses").prop("checked", !settingObj.enableFavoriteActresses || settingObj.enableFavoriteActresses === YES$1); + $("#enableSaveActressCarInfo").prop("checked", !!settingObj.enableSaveActressCarInfo && settingObj.enableSaveActressCarInfo === YES$1); + $("#enableScreenSvg").prop("checked", !settingObj.enableScreenSvg || settingObj.enableScreenSvg === YES$1); + $("#enableVideoSvg").prop("checked", !settingObj.enableVideoSvg || settingObj.enableVideoSvg === YES$1); + $("#enableHandleSvg").prop("checked", !settingObj.enableHandleSvg || settingObj.enableHandleSvg === YES$1); + $("#enableSiteSvg").prop("checked", !settingObj.enableSiteSvg || settingObj.enableSiteSvg === YES$1); + $("#enableCopySvg").prop("checked", !settingObj.enableCopySvg || settingObj.enableCopySvg === YES$1); + const otherSitePlugin = this.getBean("OtherSitePlugin"), missAvUrl = await otherSitePlugin.getMissAvUrl(), + jableUrl = await otherSitePlugin.getjableUrl(), + javTrailersUrl = await otherSitePlugin.getJavTrailersUrl(), + av123Url = await otherSitePlugin.getAv123Url(), javDbUrl = await otherSitePlugin.getJavDbUrl(), + javBusUrl = await otherSitePlugin.getJavBusUrl(), supJavUrl = await otherSitePlugin.getSupJavUrl(); + $("#missAvUrl").val(missAvUrl); + $("#jableUrl").val(jableUrl); + $("#javTrailersUrl").val(javTrailersUrl); + $("#av123Url").val(av123Url); + $("#javDbUrl").val(javDbUrl); + $("#javBusUrl").val(javBusUrl); + $("#supJavUrl").val(supJavUrl); + let reviewKeywordList = await storageManager.getReviewFilterKeywordList(), + filterKeywordList = await storageManager.getTitleFilterKeyword(); + reviewKeywordList && reviewKeywordList.forEach(((reviewKeyword) => { + this.addLabelTag("#reviewKeywordContainer", reviewKeyword); + })); + filterKeywordList && filterKeywordList.forEach(((reviewKeyword) => { + this.addLabelTag("#filterKeywordContainer", reviewKeyword); + })); + ["#reviewKeywordContainer", "#filterKeywordContainer"].forEach(((containerId) => { + $(`${containerId} .add-tag-btn`).on("click", ((event) => this.addKeyword(event, containerId))); + $(`${containerId} .keyword-input`).on("keypress", ((event) => { + "Enter" === event.key && this.addKeyword(event, containerId); + })); + })); + $("#hotkey-panel [id]").map(((i, el) => el.id)).get().forEach(((containerId) => { + const $element = $(`#${containerId}`), + defaultValue = void 0 !== settingObj[containerId] ? settingObj[containerId] : $element.attr("data-default-hotkey") || ""; + $element.val(defaultValue).on("input", ((event) => { + let value = $(event.target).val(); + if (/[\u4e00-\u9fa5]/.test(value) || /^Shift[a-zA-Z0-9]+$/.test(value)) { + $(event.target).val(""); + show.error("非法输入:不能输入中文或输入法转换错误"); + } + })).on("keydown", ((event) => this.handleHotkeyInput(event, $element))); + })); + $("#enableImageHotKey").prop("checked", !!settingObj.enableImageHotKey && settingObj.enableImageHotKey === YES$1); + } - handleHotkeyInput(event, $input) { - event.preventDefault(); - const hotkey = this.parseHotkey(event); - "" !== hotkey ? this.isDuplicateHotkey(hotkey, $input.attr("id")) ? show.error("该快捷键已被其他功能使用!") : $input.val(hotkey) : $input.val(""); - } + handleHotkeyInput(event, $input) { + event.preventDefault(); + const hotkey = this.parseHotkey(event); + "" !== hotkey ? this.isDuplicateHotkey(hotkey, $input.attr("id")) ? show.error("该快捷键已被其他功能使用!") : $input.val(hotkey) : $input.val(""); + } - parseHotkey(event) { - if ("Backspace" === event.key || "Process" === event.key) return ""; - const keys = []; - event.ctrlKey && keys.push("Ctrl"); - event.shiftKey && keys.push("Shift"); - event.altKey && keys.push("Alt"); - event.metaKey && keys.push("Cmd"); - const key = { - " ": "Space", - Control: "Ctrl", - Meta: "Cmd", - ArrowUp: "Up", - ArrowDown: "Down", - ArrowLeft: "Left", - ArrowRight: "Right" - }[event.key] || (event.key.length > 1 ? event.key.replace("Arrow", "") : event.key); - ["Control", "Shift", "Alt", "Meta"].includes(event.key) || keys.push(key); - return keys.length > 0 ? keys.join("+") : ""; - } + parseHotkey(event) { + if ("Backspace" === event.key || "Process" === event.key) return ""; + const keys = []; + event.ctrlKey && keys.push("Ctrl"); + event.shiftKey && keys.push("Shift"); + event.altKey && keys.push("Alt"); + event.metaKey && keys.push("Cmd"); + const key = { + " ": "Space", + Control: "Ctrl", + Meta: "Cmd", + ArrowUp: "Up", + ArrowDown: "Down", + ArrowLeft: "Left", + ArrowRight: "Right" + }[event.key] || (event.key.length > 1 ? event.key.replace("Arrow", "") : event.key); + ["Control", "Shift", "Alt", "Meta"].includes(event.key) || keys.push(key); + return keys.length > 0 ? keys.join("+") : ""; + } - isDuplicateHotkey(hotkey, currentInputId) { - let isDuplicate = false; - $("#hotkey-panel [id]").each(((i, el) => { - if (el.id !== currentInputId && hotkey && hotkey === $(el).val()) { - isDuplicate = true; - return false; - } - })); - return isDuplicate; - } + isDuplicateHotkey(hotkey, currentInputId) { + let isDuplicate = false; + $("#hotkey-panel [id]").each(((i, el) => { + if (el.id !== currentInputId && hotkey && hotkey === $(el).val()) { + isDuplicate = true; + return false; + } + })); + return isDuplicate; + } - async initSimpleSettingForm() { - let settingObj = await storageManager.getSetting(); - $("#containerColumns").val(settingObj.containerColumns || 5); - $("#showContainerColumns").text(settingObj.containerColumns || 5); - $("#containerWidth").val((settingObj.containerWidth || 100) - 70); - $("#showContainerWidth").text((settingObj.containerWidth || 100) + "%"); - $("#dialogOpenDetail").prop("checked", !settingObj.dialogOpenDetail || settingObj.dialogOpenDetail === YES$1); - $("#needClosePage").prop("checked", !settingObj.needClosePage || settingObj.needClosePage === YES$1); - $("#autoPage").prop("checked", !settingObj.autoPage || settingObj.autoPage === YES$1); - $("#translateTitle").prop("checked", !settingObj.translateTitle || settingObj.translateTitle === YES$1); - $("#enableLoadActressInfo").prop("checked", !settingObj.enableLoadActressInfo || settingObj.enableLoadActressInfo === YES$1); - $("#enableLoadOtherSite").prop("checked", !settingObj.enableLoadOtherSite || settingObj.enableLoadOtherSite === YES$1); - $("#containerColumns").on("input", (async (event) => { - let columns = $("#containerColumns").val(); - $("#showContainerColumns").text(columns); - if (isJavDb$1) { - document.querySelector(".movie-list").style.gridTemplateColumns = `repeat(${columns}, minmax(0, 1fr))`; - } - if (isJavBus$1) { - document.querySelector(".masonry").style.gridTemplateColumns = `repeat(${columns}, minmax(0, 1fr))`; - } - await storageManager.saveSettingItem("containerColumns", columns); - this.applyImageMode(); - })); - $("#containerWidth").on("input", (async (event) => { - let containerWidth = parseInt($(event.target).val()); - const value = containerWidth + 70 + "%"; - $("#showContainerWidth").text(value); - if (isJavDb$1) { - document.querySelector("section .container").style.minWidth = value; - } - if (isJavBus$1) { - document.querySelector(".container-fluid .row").style.minWidth = value; - } - storageManager.saveSettingItem("containerWidth", containerWidth + 70); - })); - $("#dialogOpenDetail").on("change", ((event) => { - let dialogOpenDetail = $("#dialogOpenDetail").is(":checked") ? YES$1 : NO; - storageManager.saveSettingItem("dialogOpenDetail", dialogOpenDetail); - })); - $("#showFilterItem").prop("checked", !!settingObj.showFilterItem && settingObj.showFilterItem === YES$1); - $("#showFilterActorItem").prop("checked", !!settingObj.showFilterActorItem && settingObj.showFilterActorItem === YES$1); - $("#showFilterKeywordItem").prop("checked", !!settingObj.showFilterKeywordItem && settingObj.showFilterKeywordItem === YES$1); - $("#showFavoriteItem").prop("checked", !settingObj.showFavoriteItem || settingObj.showFavoriteItem === YES$1); - $("#showHasDownItem").prop("checked", !settingObj.showHasDownItem || settingObj.showHasDownItem === YES$1); - $("#showHasWatchItem").prop("checked", !settingObj.showHasWatchItem || settingObj.showHasWatchItem === YES$1); - $("#showFilterItem").on("change", (async (event) => { - let showFilterItem = $("#showFilterItem").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("showFilterItem", showFilterItem); - window.refresh(); - })); - $("#showFilterActorItem").on("change", (async (event) => { - let showFilterActorItem = $("#showFilterActorItem").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("showFilterActorItem", showFilterActorItem); - window.refresh(); - })); - $("#showFilterKeywordItem").on("change", (async (event) => { - let showFilterKeywordItem = $("#showFilterKeywordItem").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("showFilterKeywordItem", showFilterKeywordItem); - window.refresh(); - })); - $("#showFavoriteItem").on("change", (async (event) => { - let showFavoriteItem = $("#showFavoriteItem").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("showFavoriteItem", showFavoriteItem); - window.refresh(); - })); - $("#showHasDownItem").on("change", (async (event) => { - let showHasDownItem = $("#showHasDownItem").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("showHasDownItem", showHasDownItem); - window.refresh(); - })); - $("#showHasWatchItem").on("change", (async (event) => { - let showHasWatchItem = $("#showHasWatchItem").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("showHasWatchItem", showHasWatchItem); - window.refresh(); - })); - const $otherCheckboxes = $("#showFilterItem, #showFilterActorItem, #showFilterKeywordItem, #showFavoriteItem, #showHasDownItem, #showHasWatchItem"), - updateOtherCheckboxesState = () => { - const isShowAllChecked = $("#showAllItem").is(":checked"); - $otherCheckboxes.prop("disabled", isShowAllChecked); - isShowAllChecked ? $otherCheckboxes.attr("data-tip", "请先关闭显示所有才可点击") : $otherCheckboxes.removeAttr("data-tip"); - }; - $("#showAllItem").prop("checked", !!settingObj.showAllItem && settingObj.showAllItem === YES$1); - $("#showAllItem").on("change", (async (event) => { - let showAllItem = $("#showAllItem").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("showAllItem", showAllItem); - updateOtherCheckboxesState(); - window.refresh(); - })); - updateOtherCheckboxesState(); - $("#needClosePage").on("change", (async (event) => { - await storageManager.saveSettingItem("needClosePage", $("#needClosePage").is(":checked") ? YES$1 : NO); - window.refresh(); - })); - $("#autoPage").on("change", (async (event) => { - const autoPage = $("#autoPage").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("autoPage", autoPage); - autoPage === YES$1 ? ($("#sort-toggle-btn").hide(), $("#one-time-sort-btn").show()) : ($("#sort-toggle-btn").show(), $("#one-time-sort-btn").hide()); - })); - $("#translateTitle").on("change", (async (event) => { - const translateTitle = $("#translateTitle").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("translateTitle", translateTitle); - if (translateTitle === YES$1) { - await this.getBean("ListPagePlugin").doFilter(); - window.isDetailPage && await this.getBean("TranslatePlugin").translate(); - } else { - await this.getBean("ListPagePlugin").revertTranslation(); - $(".translated-title").remove(); - } - })); - $("#hoverBigImg").prop("checked", !!settingObj.hoverBigImg && settingObj.hoverBigImg === YES$1); - $("#hoverBigImg").on("change", (async (event) => { - const hoverBigImg = $("#hoverBigImg").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("hoverBigImg", hoverBigImg); - hoverBigImg === YES$1 ? window.imageHoverPreviewObj = new ImageHoverPreview({ - selector: this.getSelector().coverImgSelector - }) : window.imageHoverPreviewObj && window.imageHoverPreviewObj.destroy(); - })); - $("#enableLoadActressInfo").on("change", (async (event) => { - const enableLoadActressInfo = $("#enableLoadActressInfo").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("enableLoadActressInfo", enableLoadActressInfo); - enableLoadActressInfo === YES$1 ? this.getBean("ActressInfoPlugin").loadActressInfo() : $(".actress-info").remove(); - })); - $("#enableLoadOtherSite").on("change", (async (event) => { - const enableLoadOtherSite = $("#enableLoadOtherSite").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("enableLoadOtherSite", enableLoadOtherSite); - enableLoadOtherSite === YES$1 ? this.getBean("OtherSitePlugin").loadOtherSite().then() : $("#otherSiteBox").remove(); - })); - $("#enableLoadScreenShot").prop("checked", !settingObj.enableLoadScreenShot || settingObj.enableLoadScreenShot === YES$1); - $("#enableLoadScreenShot").on("change", (async (event) => { - const enableLoadScreenShot = $("#enableLoadScreenShot").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("enableLoadScreenShot", enableLoadScreenShot); - enableLoadScreenShot === YES$1 ? this.getBean("ScreenShotPlugin").loadScreenShot().then() : $(".screen-container").remove(); - })); - $("#enableLoadPreviewVideo").prop("checked", !settingObj.enableLoadPreviewVideo || settingObj.enableLoadPreviewVideo === YES$1); - $("#enableLoadPreviewVideo").on("change", (async (event) => { - const enableLoadPreviewVideo = $("#enableLoadPreviewVideo").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("enableLoadPreviewVideo", enableLoadPreviewVideo); - })); - $("#enable115AutoRename").prop("checked", !!settingObj.enable115AutoRename && settingObj.enable115AutoRename === YES$1); - $("#autoRenameScope").val(settingObj.autoRenameScope || "vr_only"); - $("#autoRenameScopeRow").toggle(!!settingObj.enable115AutoRename && settingObj.enable115AutoRename === YES$1); - $("#enable115AutoRename").on("change", (async (event) => { - const enable115AutoRename = $("#enable115AutoRename").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("enable115AutoRename", enable115AutoRename); - $("#autoRenameScopeRow").toggle(enable115AutoRename === YES$1); - })); - $("#autoRenameScope").on("change", (async (event) => { - await storageManager.saveSettingItem("autoRenameScope", $("#autoRenameScope").val()); - })); - $("#enable115Match").prop("checked", !!settingObj.enable115Match && settingObj.enable115Match === YES$1); - $("#enable115Match").on("change", (async (event) => { - const enable115Match = $("#enable115Match").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("enable115Match", enable115Match); - let movieList = $(this.getSelector().itemSelector).toArray(); - await this.getBean("WangPan115MatchPlugin").matchMovieList(movieList); - })); - $("#enableVerticalModel").prop("checked", !!settingObj.enableVerticalModel && settingObj.enableVerticalModel === YES$1); - $("#enableVerticalModel").on("change", (async (event) => { - const enableVerticalModel = $("#enableVerticalModel").is(":checked") ? YES$1 : NO; - await storageManager.saveSettingItem("enableVerticalModel", enableVerticalModel); - this.applyImageMode(); - })); - $("#moreBtn").on("click", (() => { - $(".simple-setting").html("").hide(); - this.openSettingDialog("base-panel"); - })); - $("#helpBtn").on("click", (() => { - layer.open({ - type: 1, - title: "", - shadeClose: true, - scrollbar: false, - content: ` + async initSimpleSettingForm() { + let settingObj = await storageManager.getSetting(); + $("#containerColumns").val(settingObj.containerColumns || 5); + $("#showContainerColumns").text(settingObj.containerColumns || 5); + $("#containerWidth").val((settingObj.containerWidth || 100) - 70); + $("#showContainerWidth").text((settingObj.containerWidth || 100) + "%"); + $("#dialogOpenDetail").prop("checked", !settingObj.dialogOpenDetail || settingObj.dialogOpenDetail === YES$1); + $("#needClosePage").prop("checked", !settingObj.needClosePage || settingObj.needClosePage === YES$1); + $("#autoPage").prop("checked", !settingObj.autoPage || settingObj.autoPage === YES$1); + $("#translateTitle").prop("checked", !settingObj.translateTitle || settingObj.translateTitle === YES$1); + $("#enableLoadActressInfo").prop("checked", !settingObj.enableLoadActressInfo || settingObj.enableLoadActressInfo === YES$1); + $("#enableLoadOtherSite").prop("checked", !settingObj.enableLoadOtherSite || settingObj.enableLoadOtherSite === YES$1); + $("#containerColumns").on("input", (async (event) => { + let columns = $("#containerColumns").val(); + $("#showContainerColumns").text(columns); + if (isJavDb$1) { + document.querySelector(".movie-list").style.gridTemplateColumns = `repeat(${columns}, minmax(0, 1fr))`; + } + if (isJavBus$1) { + document.querySelector(".masonry").style.gridTemplateColumns = `repeat(${columns}, minmax(0, 1fr))`; + } + await storageManager.saveSettingItem("containerColumns", columns); + this.applyImageMode(); + })); + $("#containerWidth").on("input", (async (event) => { + let containerWidth = parseInt($(event.target).val()); + const value = containerWidth + 70 + "%"; + $("#showContainerWidth").text(value); + if (isJavDb$1) { + document.querySelector("section .container").style.minWidth = value; + } + if (isJavBus$1) { + document.querySelector(".container-fluid .row").style.minWidth = value; + } + storageManager.saveSettingItem("containerWidth", containerWidth + 70); + })); + $("#dialogOpenDetail").on("change", ((event) => { + let dialogOpenDetail = $("#dialogOpenDetail").is(":checked") ? YES$1 : NO; + storageManager.saveSettingItem("dialogOpenDetail", dialogOpenDetail); + })); + $("#showFilterItem").prop("checked", !!settingObj.showFilterItem && settingObj.showFilterItem === YES$1); + $("#showFilterActorItem").prop("checked", !!settingObj.showFilterActorItem && settingObj.showFilterActorItem === YES$1); + $("#showFilterKeywordItem").prop("checked", !!settingObj.showFilterKeywordItem && settingObj.showFilterKeywordItem === YES$1); + $("#showFavoriteItem").prop("checked", !settingObj.showFavoriteItem || settingObj.showFavoriteItem === YES$1); + $("#showHasDownItem").prop("checked", !settingObj.showHasDownItem || settingObj.showHasDownItem === YES$1); + $("#showHasWatchItem").prop("checked", !settingObj.showHasWatchItem || settingObj.showHasWatchItem === YES$1); + $("#showFilterItem").on("change", (async (event) => { + let showFilterItem = $("#showFilterItem").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("showFilterItem", showFilterItem); + window.refresh(); + })); + $("#showFilterActorItem").on("change", (async (event) => { + let showFilterActorItem = $("#showFilterActorItem").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("showFilterActorItem", showFilterActorItem); + window.refresh(); + })); + $("#showFilterKeywordItem").on("change", (async (event) => { + let showFilterKeywordItem = $("#showFilterKeywordItem").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("showFilterKeywordItem", showFilterKeywordItem); + window.refresh(); + })); + $("#showFavoriteItem").on("change", (async (event) => { + let showFavoriteItem = $("#showFavoriteItem").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("showFavoriteItem", showFavoriteItem); + window.refresh(); + })); + $("#showHasDownItem").on("change", (async (event) => { + let showHasDownItem = $("#showHasDownItem").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("showHasDownItem", showHasDownItem); + window.refresh(); + })); + $("#showHasWatchItem").on("change", (async (event) => { + let showHasWatchItem = $("#showHasWatchItem").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("showHasWatchItem", showHasWatchItem); + window.refresh(); + })); + const $otherCheckboxes = $("#showFilterItem, #showFilterActorItem, #showFilterKeywordItem, #showFavoriteItem, #showHasDownItem, #showHasWatchItem"), + updateOtherCheckboxesState = () => { + const isShowAllChecked = $("#showAllItem").is(":checked"); + $otherCheckboxes.prop("disabled", isShowAllChecked); + isShowAllChecked ? $otherCheckboxes.attr("data-tip", "请先关闭显示所有才可点击") : $otherCheckboxes.removeAttr("data-tip"); + }; + $("#showAllItem").prop("checked", !!settingObj.showAllItem && settingObj.showAllItem === YES$1); + $("#showAllItem").on("change", (async (event) => { + let showAllItem = $("#showAllItem").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("showAllItem", showAllItem); + updateOtherCheckboxesState(); + window.refresh(); + })); + updateOtherCheckboxesState(); + $("#needClosePage").on("change", (async (event) => { + await storageManager.saveSettingItem("needClosePage", $("#needClosePage").is(":checked") ? YES$1 : NO); + window.refresh(); + })); + $("#autoPage").on("change", (async (event) => { + const autoPage = $("#autoPage").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("autoPage", autoPage); + autoPage === YES$1 ? ($("#sort-toggle-btn").hide(), $("#one-time-sort-btn").show()) : ($("#sort-toggle-btn").show(), $("#one-time-sort-btn").hide()); + })); + $("#translateTitle").on("change", (async (event) => { + const translateTitle = $("#translateTitle").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("translateTitle", translateTitle); + if (translateTitle === YES$1) { + await this.getBean("ListPagePlugin").doFilter(); + window.isDetailPage && await this.getBean("TranslatePlugin").translate(); + } else { + await this.getBean("ListPagePlugin").revertTranslation(); + $(".translated-title").remove(); + } + })); + $("#hoverBigImg").prop("checked", !!settingObj.hoverBigImg && settingObj.hoverBigImg === YES$1); + $("#hoverBigImg").on("change", (async (event) => { + const hoverBigImg = $("#hoverBigImg").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("hoverBigImg", hoverBigImg); + hoverBigImg === YES$1 ? window.imageHoverPreviewObj = new ImageHoverPreview({ + selector: this.getSelector().coverImgSelector + }) : window.imageHoverPreviewObj && window.imageHoverPreviewObj.destroy(); + })); + $("#enableLoadActressInfo").on("change", (async (event) => { + const enableLoadActressInfo = $("#enableLoadActressInfo").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("enableLoadActressInfo", enableLoadActressInfo); + enableLoadActressInfo === YES$1 ? this.getBean("ActressInfoPlugin").loadActressInfo() : $(".actress-info").remove(); + })); + $("#enableLoadOtherSite").on("change", (async (event) => { + const enableLoadOtherSite = $("#enableLoadOtherSite").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("enableLoadOtherSite", enableLoadOtherSite); + enableLoadOtherSite === YES$1 ? this.getBean("OtherSitePlugin").loadOtherSite().then() : $("#otherSiteBox").remove(); + })); + $("#enableLoadScreenShot").prop("checked", !settingObj.enableLoadScreenShot || settingObj.enableLoadScreenShot === YES$1); + $("#enableLoadScreenShot").on("change", (async (event) => { + const enableLoadScreenShot = $("#enableLoadScreenShot").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("enableLoadScreenShot", enableLoadScreenShot); + enableLoadScreenShot === YES$1 ? this.getBean("ScreenShotPlugin").loadScreenShot().then() : $(".screen-container").remove(); + })); + $("#enableLoadPreviewVideo").prop("checked", !settingObj.enableLoadPreviewVideo || settingObj.enableLoadPreviewVideo === YES$1); + $("#enableLoadPreviewVideo").on("change", (async (event) => { + const enableLoadPreviewVideo = $("#enableLoadPreviewVideo").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("enableLoadPreviewVideo", enableLoadPreviewVideo); + })); + $("#enable115AutoRename").prop("checked", !!settingObj.enable115AutoRename && settingObj.enable115AutoRename === YES$1); + $("#autoRenameScope").val(settingObj.autoRenameScope || "vr_only"); + $("#autoRenameScopeRow").toggle(!!settingObj.enable115AutoRename && settingObj.enable115AutoRename === YES$1); + $("#enable115AutoRename").on("change", (async (event) => { + const enable115AutoRename = $("#enable115AutoRename").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("enable115AutoRename", enable115AutoRename); + $("#autoRenameScopeRow").toggle(enable115AutoRename === YES$1); + })); + $("#autoRenameScope").on("change", (async (event) => { + await storageManager.saveSettingItem("autoRenameScope", $("#autoRenameScope").val()); + })); + $("#enable115Match").prop("checked", !!settingObj.enable115Match && settingObj.enable115Match === YES$1); + $("#enable115Match").on("change", (async (event) => { + const enable115Match = $("#enable115Match").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("enable115Match", enable115Match); + let movieList = $(this.getSelector().itemSelector).toArray(); + await this.getBean("WangPan115MatchPlugin").matchMovieList(movieList); + })); + $("#enableVerticalModel").prop("checked", !!settingObj.enableVerticalModel && settingObj.enableVerticalModel === YES$1); + $("#enableVerticalModel").on("change", (async (event) => { + const enableVerticalModel = $("#enableVerticalModel").is(":checked") ? YES$1 : NO; + await storageManager.saveSettingItem("enableVerticalModel", enableVerticalModel); + this.applyImageMode(); + })); + $("#moreBtn").on("click", (() => { + $(".simple-setting").html("").hide(); + this.openSettingDialog("base-panel"); + })); + $("#helpBtn").on("click", (() => { + layer.open({ + type: 1, + title: "", + shadeClose: true, + scrollbar: false, + content: ` \n "; - } + async loadConfig() { + const settingObj = await storageManager.getSetting(); + this.taskConfig = { + checkConcurrencyCount: settingObj.checkConcurrencyCount ? Number(settingObj.checkConcurrencyCount) : 2, + checkRequestSleep: settingObj.checkRequestSleep ? Number(settingObj.checkRequestSleep) : 100, + enableCheckBlacklist: settingObj.enableCheckBlacklist || YES$1, + checkBlacklist_intervalTime: settingObj.checkBlacklist_intervalTime ? Number(settingObj.checkBlacklist_intervalTime) : 12, + checkBlacklist_ruleTime: settingObj.checkBlacklist_ruleTime ? Number(settingObj.checkBlacklist_ruleTime) : 8760, + enableCheckFavoriteActress: settingObj.enableCheckFavoriteActress || YES$1, + checkFavoriteActress_IntervalTime: settingObj.checkFavoriteActress_IntervalTime ? Number(settingObj.checkFavoriteActress_IntervalTime) : 24, + enableCheckNewVideo: settingObj.enableCheckNewVideo || YES$1, + checkNewVideo_intervalTime: settingObj.checkNewVideo_intervalTime ? Number(settingObj.checkNewVideo_intervalTime) : 12, + checkNewVideo_ruleTime: settingObj.checkNewVideo_ruleTime ? Number(settingObj.checkNewVideo_ruleTime) : 8760 + }; + } - async showNewVideoCount() { - const totalNewVideoCount = (await storageManager.getFavoriteActressList()).reduce(((accumulator, actress) => { - var _a2; - return accumulator + ((null == (_a2 = actress.newVideoList) ? void 0 : _a2.length) ?? 0); - }), 0); - $("#newVideoCount").text(`${totalNewVideoCount}`); - } + async checkBlacklist(isManual) { + let blacklist = await storageManager.getBlacklist(); + if (0 === blacklist.length) return; + blacklist = blacklist.sort(((a, b) => a.createTime < b.createTime ? 1 : a.createTime > b.createTime ? -1 : 0)); + const checkConcurrencyCount = this.taskConfig.checkConcurrencyCount, + checkRequestSleep = this.taskConfig.checkRequestSleep, + checkBlacklist_intervalTime = this.taskConfig.checkBlacklist_intervalTime, + checkBlacklist_ruleTime = this.taskConfig.checkBlacklist_ruleTime, + lastCheckBlacklistTimeStr = localStorage.getItem(this.lastCheckBlacklistTimeKey); + if (!isManual && lastCheckBlacklistTimeStr && this.isUnnecessaryCheck(lastCheckBlacklistTimeStr, checkBlacklist_intervalTime)) { + clog.debug(`检测黑名单, 上次检测时间: ${lastCheckBlacklistTimeStr} 检测间隔时间: ${checkBlacklist_intervalTime}小时 未到时间`); + return; + } + const taskParamList = [], msgList = []; + for (const blacklistItem of blacklist) { + let name2 = blacklistItem.name, checkTime = blacklistItem.checkTime, + lastPublishTime = blacklistItem.lastPublishTime, url = blacklistItem.url; + if (new URL(window.location.href).hostname === new URL(url).hostname) { + if (isManual || !checkTime || !this.isUnnecessaryCheck(checkTime, checkBlacklist_intervalTime)) if (!lastPublishTime || 0 === checkBlacklist_ruleTime || this.isUnnecessaryCheck(lastPublishTime, checkBlacklist_ruleTime)) taskParamList.push(blacklistItem); + else { + let msg = `检测黑名单: ${name2} ${lastPublishTime} 停更超过${checkBlacklist_ruleTime / 24 / 365}年,跳过检测`; + msgList.push(msg); + $("#checkBlacklistMsg").text(msg); + } + } else clog.log("黑名单地址非同域名,跳过", url); + } + if (0 === taskParamList.length) return; + msgList.forEach(((msg) => { + clog.log(msg); + })); + clog.log(`检测屏蔽黑名单, 总任务数: ${taskParamList.length}, 并发限制:${checkConcurrencyCount}, 请求间隔时间:${checkRequestSleep}ms`); + const blacklistPlugin = this.getBean("BlacklistPlugin"); + await this.limitConcurrency(taskParamList, checkConcurrencyCount, checkRequestSleep, (async (task) => { + let {starId, name: name2, url} = task; + try { + clog.log("正在检屏黑名单演员:", name2, url); + $("#checkBlacklistMsg").text(`正在检屏黑名单演员: ${name2} ${url}`); + const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html); + this.storageQueue.addTask((async () => { + let {lastPublishTime} = await blacklistPlugin.parseAndSaveFilterInfo($dom, name2, starId); + await storageManager.updateBlacklistItem({ + starId, + name: name2, + checkTime: utils.getNowStr(), + lastPublishTime + }); + })); + } catch (e) { + $("#checkBlacklistMsg").text(`检测屏蔽演员信息, 发生错误: ${url}`); + clog.error("检测屏蔽演员信息, 发生错误:", url, e); + show.error("检测屏蔽演员信息, 发生错误:" + e, "bottom", "right"); + } + })); + await this.storageQueue.waitAllFinished(); + const updateLastCheckBlacklistTimeStr = utils.getNowStr(); + localStorage.setItem(this.lastCheckBlacklistTimeKey, updateLastCheckBlacklistTimeStr); + clog.log('-------- END 检测屏蔽黑名单 END --------'); + $("#checkBlacklistMsg").text("检测屏蔽黑名单, 结束"); + this.getBean("BlacklistPlugin").resetBtnTip().then(); + } - async resetBtnTip() { - const taskPlugin = this.getBean("TaskPlugin"), settingObj = await storageManager.getSetting(), - lastCheckTimeStr = localStorage.getItem(taskPlugin.lastCheckFavoriteActressTimeKey) || "无", - checkFavoriteActress_IntervalTime = settingObj.checkFavoriteActress_IntervalTime, - lastCheckNewVideoTimeStr = localStorage.getItem(taskPlugin.lastCheckNewVideoTimeKey) || "无", - checkNewVideo_intervalTime = settingObj.checkNewVideo_intervalTime; - $("#checkFavoriteActress").attr("data-tip", `上次自动同步时间: ${lastCheckTimeStr}; 检测间隔时间: ${checkFavoriteActress_IntervalTime}小时`); - $("#checkNewVideo").attr("data-tip", `上次检测时间: ${lastCheckNewVideoTimeStr}; 检测间隔时间: ${checkNewVideo_intervalTime}小时`); - } + async checkFavoriteActress() { + const checkUrl = `${this.javDbUrl}/users/collection_actors`, actorInfoList = []; + await this.scrapeActorInfo(checkUrl, actorInfoList); + clog.log("所有演员信息已收集, 总计数量:", actorInfoList.length); + $("#checkNewVideoMsg").text("同步完成"); + if (actorInfoList.length > 0) { + await storageManager.addFavoriteActressList(actorInfoList); + localStorage.setItem(this.lastCheckFavoriteActressTimeKey, utils.getNowStr()); + this.getBean("NewVideoPlugin").resetBtnTip().then(); + } + } - async openDialog() { - const taskPlugin = this.getBean("TaskPlugin"), settingObj = await storageManager.getSetting(), - lastCheckTimeStr = localStorage.getItem(taskPlugin.lastCheckFavoriteActressTimeKey) || "无", - checkFavoriteActress_IntervalTime = settingObj.checkFavoriteActress_IntervalTime, - lastCheckNewVideoTimeStr = localStorage.getItem(taskPlugin.lastCheckNewVideoTimeKey) || "无", - checkNewVideo_intervalTime = settingObj.checkNewVideo_intervalTime; - let html = ` + async scrapeActorInfo(currentUrl, actorInfoList) { + clog.log(`正在抓取页面: ${currentUrl}`); + $("#checkNewVideoMsg").text(`正在解析已收藏的演员: ${currentUrl}`); + try { + const html = await gmHttp.get(currentUrl), $dom = utils.htmlTo$dom(html); + $dom.find("#actors .actor-box a").each(((i, element) => { + const $a = $(element), title = $a.attr("title"), href = $a.attr("href"); + if (title && href) { + const allName = title.split(",").map(((name3) => name3.trim())).filter(((name3) => name3.length > 0)), + name2 = allName[0] || "", + segments = new URL(href, this.javDbUrl).pathname.split("/").filter(((s) => s.length > 0)); + let starId = ""; + segments.length > 0 && (starId = segments[segments.length - 1]); + let actressType = "censored"; + const avatar = $a.find("img").attr("src"), $infoSpan = $a.find(".info"); + $infoSpan.length && $infoSpan.text().trim().includes("無碼") && (actressType = "uncensored"); + actorInfoList.push({ + starId, + name: name2, + allName, + avatar, + actressType, + lastCheckTime: null, + lastUpdateTime: null + }); + } + })); + const nextRelativeUrl = $dom.find(".pagination-next").attr("href"); + if (nextRelativeUrl) { + const nextAbsoluteUrl = new URL(nextRelativeUrl, this.javDbUrl).href; + await this.scrapeActorInfo(nextAbsoluteUrl, actorInfoList); + } + } catch (error) { + clog.error(`抓取 ${currentUrl} 时发生错误:`, error); + } + } + + async checkNewVideo(isManual) { + const dataActressInfoList = await storageManager.getFavoriteActressList(), + actressInfoList = utils.genericSort(dataActressInfoList, [{ + key: (item) => { + var _a2; + return (null == (_a2 = item.newVideoList) ? void 0 : _a2.length) ?? 0; + }, + order: "desc" + }, { + key: "lastPublishTime", + order: "desc" + }]), checkConcurrencyCount = this.taskConfig.checkConcurrencyCount, + checkRequestSleep = this.taskConfig.checkRequestSleep, + checkNewVideo_intervalTime = this.taskConfig.checkNewVideo_intervalTime, + checkNewVideo_ruleTime = this.taskConfig.checkNewVideo_ruleTime, + lastCheckNewVideoTimeStr = localStorage.getItem(this.lastCheckNewVideoTimeKey); + if (!isManual && lastCheckNewVideoTimeStr && this.isUnnecessaryCheck(lastCheckNewVideoTimeStr, checkNewVideo_intervalTime)) { + clog.debug(`检测新作品, 上次检测时间: ${lastCheckNewVideoTimeStr} 检测间隔时间: ${checkNewVideo_intervalTime}小时 未到时间`); + return; + } + const taskParamList = [], msgList = []; + for (const actress of actressInfoList) { + const {lastCheckTime, lastPublishTime, name: name2} = actress; + !isManual && lastCheckTime && this.isUnnecessaryCheck(lastCheckTime, checkNewVideo_intervalTime) || (!lastPublishTime || 0 === checkNewVideo_ruleTime || this.isUnnecessaryCheck(lastPublishTime, checkNewVideo_ruleTime) ? taskParamList.push(actress) : msgList.push(`检测新作品: ${name2} ${lastPublishTime} 停更超过${checkNewVideo_ruleTime / 24 / 365}年,跳过检测`)); + } + if (0 === taskParamList.length) return; + msgList.forEach(((msg) => { + clog.log(msg); + })); + clog.log(`检测最新作品, 总任务数: ${taskParamList.length}, 并发限制:${checkConcurrencyCount}, 请求间隔时间:${checkRequestSleep}ms`); + const filterKeywordList = await storageManager.getTitleFilterKeyword(), + filterActorActressCarList = await storageManager.getBlacklistCarList(), + filterActorActressCarNumList = new Set(filterActorActressCarList.map(((car) => car.carNum))); + await this.limitConcurrency(taskParamList, checkConcurrencyCount, checkRequestSleep, (async (task) => { + const {lastCheckTime, name: name2, starId} = task; + let url = `${this.javDbUrl}/actors/${starId}?t=d`; + try { + clog.log("正在检测最新作品, 演员:", name2, url); + $("#checkNewVideoMsg").text(`正在检测最新作品, 演员: ${name2}`); + const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html); + this.storageQueue.addTask((async () => { + await this.parsePage($dom, starId, name2, filterKeywordList, filterActorActressCarNumList); + })); + } catch (e) { + clog.error("检测屏蔽演员信息, 发生错误:", url, e); + console.error("检测屏蔽演员信息, 发生错误:", url, e); + show.error("检测屏蔽演员信息, 发生错误:" + e, "bottom", "right"); + } + })); + await this.storageQueue.waitAllFinished(); + localStorage.setItem(this.lastCheckNewVideoTimeKey, utils.getNowStr()); + clog.log('检测最新作品---结束'); + $("#checkNewVideoMsg").text("检测完毕"); + const newVideoPlugin = this.getBean("NewVideoPlugin"); + newVideoPlugin.loadData(); + newVideoPlugin.resetBtnTip().then(); + } + + async parsePage($dom, starId, name2, filterKeywordList, filterActorActressCarNumList) { + let movieList, nextPageLink, tempIsJavBus = false, selectorType = "javdb"; + if ($dom.text().includes("javbus")) { + tempIsJavBus = true; + selectorType = "javbus"; + } + tempIsJavBus && $dom.find(".avatar-box").length > 0 && $dom.find(".avatar-box").parent().remove(); + movieList = $dom.find(this.getSelector(selectorType).requestDomItemSelector); + nextPageLink = $dom.find(this.getSelector(selectorType).nextPageSelector).attr("href"); + if (nextPageLink && 0 === movieList.length) { + clog.error("新作品检测-解析列表失败"); + show.error("新作品检测-解析列表失败"); + throw new Error("新作品检测-解析列表失败"); + } + let carNumList = [], lastPublishTime = null; + for (const element of movieList) { + const $item = $(element), {carNum: carNum2, url, title, publishTime} = this.getBoxCarInfo($item); + if (!carNum2) continue; + if (!filterKeywordList.find(((kw) => title.includes(kw) || carNum2.startsWith(kw))) && !filterActorActressCarNumList.has(carNum2)) { + lastPublishTime || (lastPublishTime = publishTime); + carNumList.push(carNum2); + } + } + const carList = await storageManager.getCarList(), + storageCarNumList = new Set(carList.map(((car) => car.carNum))), + nonExistingCarNumList = carNumList.filter(((carNum2) => !storageCarNumList.has(carNum2))); + nonExistingCarNumList.length > 0 && clog.log(`检测出新作品, ${name2}, 共${nonExistingCarNumList.length}部`); + await storageManager.updateFavoriteActress({ + starId, + lastCheckTime: utils.getNowStr(), + newVideoList: nonExistingCarNumList, + lastPublishTime + }); + } + + async checkOneNewVideo(actress) { + const filterKeywordList = await storageManager.getTitleFilterKeyword(), + filterActorActressCarList = await storageManager.getBlacklistCarList(), + filterActorActressCarNumList = new Set(filterActorActressCarList.map(((car) => car.carNum))), { + lastCheckTime, + name: name2, + starId + } = actress; + let url = `${this.javDbUrl}/actors/${starId}?t=d`; + const $checkNewVideoMsg = $("#checkNewVideoMsg"); + try { + clog.log("正在检测最新作品, 演员:", name2, url); + $checkNewVideoMsg.text(`正在检测最新作品, 演员: ${name2}`); + const html = await gmHttp.get(url), $dom = utils.htmlTo$dom(html); + await this.parsePage($dom, starId, name2, filterKeywordList, filterActorActressCarNumList); + clog.log('检测最新作品---结束'); + $checkNewVideoMsg.text("检测完毕"); + this.getBean("NewVideoPlugin").loadData(); + } catch (e) { + clog.error("检测屏蔽演员信息, 发生错误:", url, e); + show.error("检测屏蔽演员信息, 发生错误:" + e, "bottom", "right"); + $checkNewVideoMsg.text(`检测屏蔽演员信息, 发生错误: ${url}`); + } + } + } + + const CDN_SOURCES = [{ + name: "jsDelivr (全球CDN)", + json: "https://cdn.jsdelivr.net/gh/gfriends/gfriends/Filetree.json", + base: "https://cdn.jsdelivr.net/gh/gfriends/gfriends/Content/" + }, { + name: "GitHub Raw (备用)", + json: "https://raw.githubusercontent.com/gfriends/gfriends/master/Filetree.json", + base: "https://raw.githubusercontent.com/gfriends/gfriends/master/Content/" + }]; + let currentCdnIndex$1 = parseInt(localStorage.getItem("jhs_img_cdn_index") || "0", 10); + (currentCdnIndex$1 >= CDN_SOURCES.length || currentCdnIndex$1 < 0) && (currentCdnIndex$1 = 0); + window.G_FRIENDS_JSON_URL = CDN_SOURCES[currentCdnIndex$1].json; + window.window.CDN_BASE_URL = CDN_SOURCES[currentCdnIndex$1].base; + const STORE_NAME = "filetreeStore", dbHelper = { + db: null, + async open() { + return this.db ? this.db : new Promise(((resolve, reject) => { + const request = indexedDB.open("GfriendsAvatarDB", 1); + request.onupgradeneeded = (event) => { + this.db = event.target.result; + this.db.objectStoreNames.contains(STORE_NAME) || this.db.createObjectStore(STORE_NAME); + }; + request.onsuccess = (event) => { + this.db = event.target.result; + resolve(this.db); + }; + request.onerror = (event) => { + console.error("IndexedDB open error:", event.target.errorCode); + reject(new Error("Failed to open IndexedDB")); + }; + })); + }, + async get(key) { + await this.open(); + return new Promise(((resolve) => { + const request = this.db.transaction([STORE_NAME], "readonly").objectStore(STORE_NAME).get(key); + request.onsuccess = () => resolve(request.result); + request.onerror = () => resolve(null); + })); + }, + async set(key, value) { + await this.open(); + return new Promise(((resolve, reject) => { + const request = this.db.transaction([STORE_NAME], "readwrite").objectStore(STORE_NAME).put(value, key); + request.onsuccess = () => resolve(); + request.onerror = (event) => { + console.error("IndexedDB set error:", event.target.errorCode); + reject(new Error("Failed to write to IndexedDB")); + }; + })); + } + }; + window.window.G_FRIENDS_DATA_CACHE = null; + window.window.G_FRIENDS_AVATAR_MAP = null; + + class NewVideoPlugin extends BasePlugin { + constructor() { + super(...arguments); + __publicField2(this, "currentPage", 1); + __publicField2(this, "pageSize", 30); + } + + getName() { + return "NewVideoPlugin"; + } + + async initCss() { + return "\n \n "; + } + + async showNewVideoCount() { + const totalNewVideoCount = (await storageManager.getFavoriteActressList()).reduce(((accumulator, actress) => { + var _a2; + return accumulator + ((null == (_a2 = actress.newVideoList) ? void 0 : _a2.length) ?? 0); + }), 0); + $("#newVideoCount").text(`${totalNewVideoCount}`); + } + + async resetBtnTip() { + const taskPlugin = this.getBean("TaskPlugin"), settingObj = await storageManager.getSetting(), + lastCheckTimeStr = localStorage.getItem(taskPlugin.lastCheckFavoriteActressTimeKey) || "无", + checkFavoriteActress_IntervalTime = settingObj.checkFavoriteActress_IntervalTime, + lastCheckNewVideoTimeStr = localStorage.getItem(taskPlugin.lastCheckNewVideoTimeKey) || "无", + checkNewVideo_intervalTime = settingObj.checkNewVideo_intervalTime; + $("#checkFavoriteActress").attr("data-tip", `上次自动同步时间: ${lastCheckTimeStr}; 检测间隔时间: ${checkFavoriteActress_IntervalTime}小时`); + $("#checkNewVideo").attr("data-tip", `上次检测时间: ${lastCheckNewVideoTimeStr}; 检测间隔时间: ${checkNewVideo_intervalTime}小时`); + } + + async openDialog() { + const taskPlugin = this.getBean("TaskPlugin"), settingObj = await storageManager.getSetting(), + lastCheckTimeStr = localStorage.getItem(taskPlugin.lastCheckFavoriteActressTimeKey) || "无", + checkFavoriteActress_IntervalTime = settingObj.checkFavoriteActress_IntervalTime, + lastCheckNewVideoTimeStr = localStorage.getItem(taskPlugin.lastCheckNewVideoTimeKey) || "无", + checkNewVideo_intervalTime = settingObj.checkNewVideo_intervalTime; + let html = `
@@ -6493,123 +6461,122 @@ ${value}\r
`; - layer.open({ - type: 1, - title: '新作品检测 ❓', - content: html, - scrollbar: false, - area: utils.getResponsiveArea(["80%", "90%"]), - anim: -1, - success: async (layero, index) => { - this.loadData(); - this.bindClick(); - utils.setupEscClose(index); - } - }); - } + layer.open({ + type: 1, + title: '新作品检测 ❓', + content: html, + scrollbar: false, + area: utils.getResponsiveArea(["80%", "90%"]), + anim: -1, + success: async (layero, index) => { + this.loadData(); + this.bindClick(); + utils.setupEscClose(index); + } + }); + } - bindClick() { - const taskPlugin = this.getBean("TaskPlugin"); - $("#reLoad").on("click", ((event) => { - this.loadData(); - $("#checkNewVideoMsg").text(""); - })); - $("#toSetting").on("click", ((event) => { - this.getBean("SettingPlugin").openSettingDialog("task-panel", (() => { - $("#setting-checkFavoriteActress").css({ - border: "1px solid #f40" - }); - $("#setting-checkNewVideo").css({ - border: "1px solid #f40" - }); - })); - })); - $("#checkFavoriteActress").on("click", ((event) => { - utils.q({ - clientX: event.clientX, - clientY: event.clientY + 20 - }, "是否手动同步演员?", (() => { - navigator.locks.request(taskPlugin.singleTaskKey, { - ifAvailable: true - }, (async (lock) => { - if (!lock) { - show.error("当前有定时任务在后台执行中, 无法发起手动任务"); - return; - } - if ($('a[href*="/users/profile"]').length > 0) { - await taskPlugin.checkFavoriteActress(); - this.loadData(); - } else show.error("未登录JavDb, 同步失败"); - })).catch(((error) => { - console.error("锁任务出现错误:", error); - clog.error("锁任务出现错误:", error); - })); - })); - })); - $("#checkNewVideo").on("click", ((event) => { - utils.q({ - clientX: event.clientX, - clientY: event.clientY + 20 - }, "是否手动检测最新作品?", (() => { - navigator.locks.request(taskPlugin.singleTaskKey, { - ifAvailable: true - }, (async (lock) => { - lock ? await taskPlugin.checkNewVideo(true) : show.error("当前有定时任务在后台执行中, 无法发起手动任务"); - })).catch(((error) => { - console.error("锁任务出现错误:", error); - clog.error("锁任务出现错误:", error); - })); - })); - })); - $("#paramActressType").on("change", ((event) => { - this.loadData(); - })); + bindClick() { + const taskPlugin = this.getBean("TaskPlugin"); + $("#reLoad").on("click", ((event) => { + this.loadData(); + $("#checkNewVideoMsg").text(""); + })); + $("#toSetting").on("click", ((event) => { + this.getBean("SettingPlugin").openSettingDialog("task-panel", (() => { + $("#setting-checkFavoriteActress").css({ + border: "1px solid #f40" + }); + $("#setting-checkNewVideo").css({ + border: "1px solid #f40" + }); + })); + })); + $("#checkFavoriteActress").on("click", ((event) => { + utils.q({ + clientX: event.clientX, + clientY: event.clientY + 20 + }, "是否手动同步演员?", (() => { + navigator.locks.request(taskPlugin.singleTaskKey, { + ifAvailable: true + }, (async (lock) => { + if (!lock) { + show.error("当前有定时任务在后台执行中, 无法发起手动任务"); + return; } + if ($('a[href*="/users/profile"]').length > 0) { + await taskPlugin.checkFavoriteActress(); + this.loadData(); + } else show.error("未登录JavDb, 同步失败"); + })).catch(((error) => { + console.error("锁任务出现错误:", error); + clog.error("锁任务出现错误:", error); + })); + })); + })); + $("#checkNewVideo").on("click", ((event) => { + utils.q({ + clientX: event.clientX, + clientY: event.clientY + 20 + }, "是否手动检测最新作品?", (() => { + navigator.locks.request(taskPlugin.singleTaskKey, { + ifAvailable: true + }, (async (lock) => { + lock ? await taskPlugin.checkNewVideo(true) : show.error("当前有定时任务在后台执行中, 无法发起手动任务"); + })).catch(((error) => { + console.error("锁任务出现错误:", error); + clog.error("锁任务出现错误:", error); + })); + })); + })); + $("#paramActressType").on("change", ((event) => { + this.loadData(); + })); + } - loadData() { - this.currentPage = 1; - this.renderActressCards().then(); + loadData() { + this.currentPage = 1; + this.renderActressCards().then(); + } + + async renderActressCards() { + const $actressCardContainer = $("#actress-card-container"); + if (!$actressCardContainer.length) return; + let favoriteActressesList = await storageManager.getFavoriteActressList(); + const paramActressType = $("#paramActressType").val(); + "all" !== paramActressType && (favoriteActressesList = favoriteActressesList.filter(((actress) => actress.actressType === paramActressType))); + const fullActressList = utils.genericSort(favoriteActressesList, [{ + key: (item) => { + var _a2; + return (null == (_a2 = item.newVideoList) ? void 0 : _a2.length) ?? 0; + }, + order: "desc" + }, { + key: "lastPublishTime", + order: "desc" + }]), totalCount = fullActressList.length, totalPages = Math.ceil(totalCount / this.pageSize), + startIndex = (this.currentPage - 1) * this.pageSize, endIndex = startIndex + this.pageSize, + pagedData = fullActressList.slice(startIndex, endIndex), + javDbUrl = await this.getBean("OtherSitePlugin").getJavDbUrl(), taskPlugin = this.getBean("TaskPlugin"), + checkNewVideo_ruleTime = await storageManager.getSetting("checkNewVideo_ruleTime") || 8760, + cardsHtml = pagedData.map(((data) => { + var _a2, _b, _c; + const allNamesStr = Array.isArray(data.allName) ? data.allName.join(",") : ""; + Array.isArray(data.newVideoList) && data.newVideoList.join(","); + const detailLink = `${javDbUrl}/actors/${data.starId}?t=d`; + let isUnCheck = false; + data.lastPublishTime && (isUnCheck = !taskPlugin.isUnnecessaryCheck(data.lastPublishTime, checkNewVideo_ruleTime)); + let actressTypeText = "未知", actressTypeBgc = "#9E9E9E"; + if ("uncensored" === data.actressType) { + actressTypeText = "无码"; + actressTypeBgc = "#4CAF50"; + } else if ("censored" === data.actressType) { + actressTypeText = "有码"; + actressTypeBgc = "#FF9800"; } - - async renderActressCards() { - const $actressCardContainer = $("#actress-card-container"); - if (!$actressCardContainer.length) return; - let favoriteActressesList = await storageManager.getFavoriteActressList(); - const paramActressType = $("#paramActressType").val(); - "all" !== paramActressType && (favoriteActressesList = favoriteActressesList.filter(((actress) => actress.actressType === paramActressType))); - const fullActressList = utils.genericSort(favoriteActressesList, [{ - key: (item) => { - var _a2; - return (null == (_a2 = item.newVideoList) ? void 0 : _a2.length) ?? 0; - }, - order: "desc" - }, { - key: "lastPublishTime", - order: "desc" - }]), totalCount = fullActressList.length, totalPages = Math.ceil(totalCount / this.pageSize), - startIndex = (this.currentPage - 1) * this.pageSize, endIndex = startIndex + this.pageSize, - pagedData = fullActressList.slice(startIndex, endIndex), - javDbUrl = await this.getBean("OtherSitePlugin").getJavDbUrl(), - taskPlugin = this.getBean("TaskPlugin"), - checkNewVideo_ruleTime = await storageManager.getSetting("checkNewVideo_ruleTime") || 8760, - cardsHtml = pagedData.map(((data) => { - var _a2, _b, _c; - const allNamesStr = Array.isArray(data.allName) ? data.allName.join(",") : ""; - Array.isArray(data.newVideoList) && data.newVideoList.join(","); - const detailLink = `${javDbUrl}/actors/${data.starId}?t=d`; - let isUnCheck = false; - data.lastPublishTime && (isUnCheck = !taskPlugin.isUnnecessaryCheck(data.lastPublishTime, checkNewVideo_ruleTime)); - let actressTypeText = "未知", actressTypeBgc = "#9E9E9E"; - if ("uncensored" === data.actressType) { - actressTypeText = "无码"; - actressTypeBgc = "#4CAF50"; - } else if ("censored" === data.actressType) { - actressTypeText = "有码"; - actressTypeBgc = "#FF9800"; - } - let cardUnnecessaryBtnCss = ""; - isUnCheck && (cardUnnecessaryBtnCss = "background: linear-gradient(145deg, #e0e0e0 0%, #cabdbd 100%);box-shadow: none"); - return ` + let cardUnnecessaryBtnCss = ""; + isUnCheck && (cardUnnecessaryBtnCss = "background: linear-gradient(145deg, #e0e0e0 0%, #cabdbd 100%);box-shadow: none"); + return `
`; - })).join(""); - $actressCardContainer.html(cardsHtml); - $(".btn-delete-actress").off("click").on("click", ((e) => { - e.preventDefault(); - const starId = $(e.currentTarget).attr("data-starId"), - actress = fullActressList.find(((item) => item.starId === starId)); - utils.q(e, `是否取消收藏 ${actress.name}?`, (async () => { - let deleteActressUrl = `${await this.getBean("OtherSitePlugin").getJavDbUrl()}/actors/${starId}/uncollect`; - const csrfToken = document.querySelector("meta[name=csrf-token]").content, - res = await gmHttp.post(deleteActressUrl, null, { - "x-csrf-token": csrfToken - }); - if (res.includes("removeClass")) { - await storageManager.removeFavoriteActress(starId); - this.loadData(); - } else { - show.error("移除失败"); - clog.error("移除失败,返回值:", res); - } - })); - })); - $(".btn-edit-actress").off("click").on("click", ((e) => { - e.preventDefault(); - const starId = $(e.currentTarget).attr("data-starId"), - actress = fullActressList.find(((item) => item.starId === starId)); - actress ? this.editActress(actress) : show.error(`未找到 starId 为 ${starId} 的女优记录。`); - })); - $(".btn-check-actress").off("click").on("click", ((e) => { - e.preventDefault(); - navigator.locks.request(taskPlugin.singleTaskKey, { - ifAvailable: true - }, (async (lock) => { - if (!lock) { - show.error("当前有定时任务在后台执行中, 无法发起手动任务"); - return; - } - const starId = $(e.currentTarget).attr("data-starId"), - actress = fullActressList.find(((item) => item.starId === starId)); - await taskPlugin.checkOneNewVideo(actress); - })).catch(((error) => { - console.error("锁任务出现错误:", error); - clog.error("锁任务出现错误:", error); - })); - })); - this.renderPagination(totalCount, totalPages); - show.ok("加载完成"); - } + })).join(""); + $actressCardContainer.html(cardsHtml); + $(".btn-delete-actress").off("click").on("click", ((e) => { + e.preventDefault(); + const starId = $(e.currentTarget).attr("data-starId"), + actress = fullActressList.find(((item) => item.starId === starId)); + utils.q(e, `是否取消收藏 ${actress.name}?`, (async () => { + let deleteActressUrl = `${await this.getBean("OtherSitePlugin").getJavDbUrl()}/actors/${starId}/uncollect`; + const csrfToken = document.querySelector("meta[name=csrf-token]").content, + res = await gmHttp.post(deleteActressUrl, null, { + "x-csrf-token": csrfToken + }); + if (res.includes("removeClass")) { + await storageManager.removeFavoriteActress(starId); + this.loadData(); + } else { + show.error("移除失败"); + clog.error("移除失败,返回值:", res); + } + })); + })); + $(".btn-edit-actress").off("click").on("click", ((e) => { + e.preventDefault(); + const starId = $(e.currentTarget).attr("data-starId"), + actress = fullActressList.find(((item) => item.starId === starId)); + actress ? this.editActress(actress) : show.error(`未找到 starId 为 ${starId} 的女优记录。`); + })); + $(".btn-check-actress").off("click").on("click", ((e) => { + e.preventDefault(); + navigator.locks.request(taskPlugin.singleTaskKey, { + ifAvailable: true + }, (async (lock) => { + if (!lock) { + show.error("当前有定时任务在后台执行中, 无法发起手动任务"); + return; + } + const starId = $(e.currentTarget).attr("data-starId"), + actress = fullActressList.find(((item) => item.starId === starId)); + await taskPlugin.checkOneNewVideo(actress); + })).catch(((error) => { + console.error("锁任务出现错误:", error); + clog.error("锁任务出现错误:", error); + })); + })); + this.renderPagination(totalCount, totalPages); + show.ok("加载完成"); + } - async editActress(actress) { - const initialName = actress.name, initialAvatar = actress.avatar, - initialRemark = actress.remark || "", - initialAllName = Array.isArray(actress.allName) ? actress.allName.join(",") : "", - initialNewVideoList = Array.isArray(actress.newVideoList) ? actress.newVideoList.join(",") : "", - starId = actress.starId, - textareaStyle = "width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; min-height: 60px; overflow-y: hidden;", - initActressType = actress.actressType || "", editFormHtml = ` + async editActress(actress) { + const initialName = actress.name, initialAvatar = actress.avatar, initialRemark = actress.remark || "", + initialAllName = Array.isArray(actress.allName) ? actress.allName.join(",") : "", + initialNewVideoList = Array.isArray(actress.newVideoList) ? actress.newVideoList.join(",") : "", + starId = actress.starId, + textareaStyle = "width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; min-height: 60px; overflow-y: hidden;", + initActressType = actress.actressType || "", editFormHtml = `
Avatar Preview
`; - layer.open({ - type: 1, - title: `编辑女优: ${initialName} (${starId})`, - area: ["500px", "750px"], - content: editFormHtml, - btn: ["保存", "取消"], - success: (layero, index) => { - const autoResizeTextarea = ($textarea) => { - $textarea.css("height", "auto"); - $textarea.css("height", $textarea[0].scrollHeight + 15 + "px"); - }; - $("#edit-actress-avatar").on("input", (function () { - const newUrl = $(this).val(); - $("#edit-avatar-preview").attr("src", newUrl); - })); - const $allNameTextarea = $("#edit-actress-allname"); - $allNameTextarea.on("input", (function () { - autoResizeTextarea($(this)); - })); - autoResizeTextarea($allNameTextarea); - const $videoListTextarea = $("#edit-actress-newvideolist"); - $videoListTextarea.on("input", (function () { - autoResizeTextarea($(this)); - })); - autoResizeTextarea($videoListTextarea); - $("#search-avatar-btn").on("click", (async () => { - await this.searchAvatar(); - })); - $("#select-cdn-btn").on("click", (async () => { - await (async function () { - const initialIndex = currentCdnIndex, - radioOptions = CDN_SOURCES.map(((source, index2) => ` + layer.open({ + type: 1, + title: `编辑女优: ${initialName} (${starId})`, + area: ["500px", "750px"], + content: editFormHtml, + btn: ["保存", "取消"], + success: (layero, index) => { + const autoResizeTextarea = ($textarea) => { + $textarea.css("height", "auto"); + $textarea.css("height", $textarea[0].scrollHeight + 15 + "px"); + }; + $("#edit-actress-avatar").on("input", (function () { + const newUrl = $(this).val(); + $("#edit-avatar-preview").attr("src", newUrl); + })); + const $allNameTextarea = $("#edit-actress-allname"); + $allNameTextarea.on("input", (function () { + autoResizeTextarea($(this)); + })); + autoResizeTextarea($allNameTextarea); + const $videoListTextarea = $("#edit-actress-newvideolist"); + $videoListTextarea.on("input", (function () { + autoResizeTextarea($(this)); + })); + autoResizeTextarea($videoListTextarea); + $("#search-avatar-btn").on("click", (async () => { + await this.searchAvatar(); + })); + $("#select-cdn-btn").on("click", (async () => { + await (async function () { + const initialIndex = currentCdnIndex, radioOptions = CDN_SOURCES.map(((source, index2) => `
@@ -6796,122 +6761,120 @@ ${value}\r

切换源会清除本地缓存的数据,并在下次搜索时重新加载。

`; - layer.open({ - type: 1, - title: "选择 CDN 源", - area: ["400px", "auto"], - content: cdnSelectHtml, - btn: ["确定", "取消"], - success: (layero2, index2) => { - utils.setupEscClose(index2); - }, - yes: async (index2) => { - const newIndexStr = $('input[name="cdn-source"]:checked').val(), - newIndex = parseInt(newIndexStr, 10); - if (newIndex !== currentCdnIndex) { - currentCdnIndex = newIndex; - localStorage.setItem("jhs_img_cdn_index", newIndex.toString()); - window.G_FRIENDS_JSON_URL = CDN_SOURCES[newIndex].json; - window.CDN_BASE_URL = CDN_SOURCES[newIndex].base; - window.G_FRIENDS_DATA_CACHE = null; - window.G_FRIENDS_AVATAR_MAP = null; - try { - await dbHelper.set("filetree_data", null); - } catch (e) { - clog.error("清除 IndexedDB 缓存失败:", e); - } - show.ok(`CDN 源已切换为: ${CDN_SOURCES[newIndex].name}`); - layer.close(index2); - } else layer.close(index2); - } - }); - })(); - })); - utils.setupEscClose(index); - }, - yes: async (index) => { - const newAvatar = $("#edit-actress-avatar").val().trim(), - newName = $("#edit-actress-name").val().trim(), - newAllNameStr = $("#edit-actress-allname").val().trim(), - newVideoListStr = $("#edit-actress-newvideolist").val().trim(), - newRemark = $("#edit-remark").val().trim(), newActressType = $("#actressType").val(); - if (!newName) { - show.error("主名称不能为空"); - return false; - } - const newAllName = newAllNameStr.split(/[\uff0c,]/).map(((n) => n.trim())).filter(((n) => n.length > 0)), - newVideoList = newVideoListStr.split(/[\uff0c,]/).map(((n) => n.trim())).filter(((n) => n.length > 0)); - actress.avatar = newAvatar; - actress.name = newName; - actress.allName = newAllName; - actress.newVideoList = newVideoList; - actress.actressType = newActressType; - actress.remark = newRemark; - if (await storageManager.updateFavoriteActress(actress)) show.error("修改失败"); - else { - show.ok(`女优 ${newName} 信息已更新`); - await this.renderActressCards(); - layer.close(index); - } + layer.open({ + type: 1, + title: "选择 CDN 源", + area: ["400px", "auto"], + content: cdnSelectHtml, + btn: ["确定", "取消"], + success: (layero2, index2) => { + utils.setupEscClose(index2); + }, + yes: async (index2) => { + const newIndexStr = $('input[name="cdn-source"]:checked').val(), + newIndex = parseInt(newIndexStr, 10); + if (newIndex !== currentCdnIndex) { + currentCdnIndex = newIndex; + localStorage.setItem("jhs_img_cdn_index", newIndex.toString()); + window.G_FRIENDS_JSON_URL = CDN_SOURCES[newIndex].json; + window.CDN_BASE_URL = CDN_SOURCES[newIndex].base; + window.G_FRIENDS_DATA_CACHE = null; + window.G_FRIENDS_AVATAR_MAP = null; + try { + await dbHelper.set("filetree_data", null); + } catch (e) { + clog.error("清除 IndexedDB 缓存失败:", e); } - }); - } + show.ok(`CDN 源已切换为: ${CDN_SOURCES[newIndex].name}`); + layer.close(index2); + } else layer.close(index2); + } + }); + })(); + })); + utils.setupEscClose(index); + }, + yes: async (index) => { + const newAvatar = $("#edit-actress-avatar").val().trim(), newName = $("#edit-actress-name").val().trim(), + newAllNameStr = $("#edit-actress-allname").val().trim(), + newVideoListStr = $("#edit-actress-newvideolist").val().trim(), + newRemark = $("#edit-remark").val().trim(), newActressType = $("#actressType").val(); + if (!newName) { + show.error("主名称不能为空"); + return false; + } + const newAllName = newAllNameStr.split(/[\uff0c,]/).map(((n) => n.trim())).filter(((n) => n.length > 0)), + newVideoList = newVideoListStr.split(/[\uff0c,]/).map(((n) => n.trim())).filter(((n) => n.length > 0)); + actress.avatar = newAvatar; + actress.name = newName; + actress.allName = newAllName; + actress.newVideoList = newVideoList; + actress.actressType = newActressType; + actress.remark = newRemark; + if (await storageManager.updateFavoriteActress(actress)) show.error("修改失败"); + else { + show.ok(`女优 ${newName} 信息已更新`); + await this.renderActressCards(); + layer.close(index); + } + } + }); + } - renderPagination(totalCount, totalPages) { - const currentPage = this.currentPage; - let paginationHtml = ""; - const $actressPagination = $("#actress-pagination"); - if (0 === totalPages) { - paginationHtml = '共 0 条记录'; - $actressPagination.html(paginationHtml); - return; - } - currentPage > 1 && totalPages > 5 && (paginationHtml += ''); - currentPage > 1 && (paginationHtml += ``); - let startPage = Math.max(1, currentPage - Math.floor(2.5)), - endPage = Math.min(totalPages, startPage + 5 - 1); - endPage - startPage < 4 && (startPage = Math.max(1, endPage - 5 + 1)); - for (let i = startPage; i <= endPage; i++) { - paginationHtml += ``; - } - currentPage < totalPages && (paginationHtml += ``); - currentPage < totalPages && totalPages > 5 && (paginationHtml += ``); - paginationHtml += `共 ${totalCount} 条记录 (第 ${currentPage}/${totalPages} 页)`; - $actressPagination.html(paginationHtml); - $(".pagination-btn").off("click").on("click", ((e) => { - if ($(e.currentTarget).is("[disabled]")) return; - const newPage = parseInt($(e.currentTarget).data("page")); - if (newPage >= 1 && newPage <= totalPages && newPage !== this.currentPage) { - this.currentPage = newPage; - this.renderActressCards(); - } - })); - } + renderPagination(totalCount, totalPages) { + const currentPage = this.currentPage; + let paginationHtml = ""; + const $actressPagination = $("#actress-pagination"); + if (0 === totalPages) { + paginationHtml = '共 0 条记录'; + $actressPagination.html(paginationHtml); + return; + } + currentPage > 1 && totalPages > 5 && (paginationHtml += ''); + currentPage > 1 && (paginationHtml += ``); + let startPage = Math.max(1, currentPage - Math.floor(2.5)), endPage = Math.min(totalPages, startPage + 5 - 1); + endPage - startPage < 4 && (startPage = Math.max(1, endPage - 5 + 1)); + for (let i = startPage; i <= endPage; i++) { + paginationHtml += ``; + } + currentPage < totalPages && (paginationHtml += ``); + currentPage < totalPages && totalPages > 5 && (paginationHtml += ``); + paginationHtml += `共 ${totalCount} 条记录 (第 ${currentPage}/${totalPages} 页)`; + $actressPagination.html(paginationHtml); + $(".pagination-btn").off("click").on("click", ((e) => { + if ($(e.currentTarget).is("[disabled]")) return; + const newPage = parseInt($(e.currentTarget).data("page")); + if (newPage >= 1 && newPage <= totalPages && newPage !== this.currentPage) { + this.currentPage = newPage; + this.renderActressCards(); + } + })); + } - async searchAvatar() { - const $mainNameInput = $("#edit-actress-name"), $aliasInput = $("#edit-actress-allname"), - currentName = $mainNameInput.val().trim(), - searchNames = $aliasInput.val().trim().split(/[\uff0c,]/).map(((n) => n.trim())).filter(((n) => n.length > 0)); - currentName && searchNames.unshift(currentName); - if (0 === searchNames.length) { - show.error("请先填写女优主名称或别名进行搜索。"); - return; - } - const loadObj = loading("正在搜索头像..."); - let imageLinks = []; - try { - imageLinks = await searchActorAvatars(searchNames); - } catch (e) { - show.error(`头像数据加载或搜索失败: ${e.message || e}`); - return; - } finally { - loadObj.close(); - } - if (0 === imageLinks.length) { - show.error(`未找到与 '${searchNames.join("、")}' 相关的头像。请检查名称。`); - return; - } - const imageItems = imageLinks.map(((url, index) => ` + async searchAvatar() { + const $mainNameInput = $("#edit-actress-name"), $aliasInput = $("#edit-actress-allname"), + currentName = $mainNameInput.val().trim(), + searchNames = $aliasInput.val().trim().split(/[\uff0c,]/).map(((n) => n.trim())).filter(((n) => n.length > 0)); + currentName && searchNames.unshift(currentName); + if (0 === searchNames.length) { + show.error("请先填写女优主名称或别名进行搜索。"); + return; + } + const loadObj = loading("正在搜索头像..."); + let imageLinks = []; + try { + imageLinks = await searchActorAvatars(searchNames); + } catch (e) { + show.error(`头像数据加载或搜索失败: ${e.message || e}`); + return; + } finally { + loadObj.close(); + } + if (0 === imageLinks.length) { + show.error(`未找到与 '${searchNames.join("、")}' 相关的头像。请检查名称。`); + return; + } + const imageItems = imageLinks.map(((url, index) => `
...
@@ -6972,419 +6935,417 @@ ${value}\r
`; - let errorCount = 0; - layer.open({ - type: 1, - title: `选择女优头像 (${imageLinks.length} 张)`, - area: utils.getResponsiveArea(["900px", "85%"]), - content: imageListHtml, - btn: ["关闭"], - success: (selectionLayero, selectionIndex) => { - const $container = $(selectionLayero), - $images = $container.find(".gfriends-selectable-img"), - $prompt = $container.find("#gfriends-prompt"); - $images.each((function () { - const $img = $(this), wrapperId = $img.data("wrapper-id"), - $wrapper = $container.find(`#${wrapperId}`), - $sizeTag = $container.find(`.gfriends-size-tag[data-size-for="${wrapperId}"]`); - $img.on("load", (function () { - const width = this.naturalWidth, height = this.naturalHeight; - $sizeTag.text(`${width} x ${height}`); - })); - $img.on("error", (function () { - $wrapper.remove(); - errorCount++; - const validCount = imageLinks.length - errorCount; - $prompt.text(`点击图片即可选择(已移除 ${errorCount} 张错误图片,剩余 ${validCount} 张)`); - if (0 === validCount) { - show.error("所有搜索到的头像链接均已失效,无法选择。"); - layer.close(selectionIndex); - } - })); - this.complete && (this.naturalWidth > 0 ? $img.trigger("load") : $img.trigger("error")); - })); - $images.on("click", (function () { - const $clickedImg = $(this), selectedUrl = $clickedImg.data("url"); - $("#edit-actress-avatar").val(selectedUrl); - $("#edit-avatar-preview").attr("src", selectedUrl); - $images.removeClass("is-selected"); - $clickedImg.addClass("is-selected"); - setTimeout((() => { - layer.close(selectionIndex); - }), 150); - })); - utils.setupEscClose(selectionIndex); - } - }); - } + let errorCount = 0; + layer.open({ + type: 1, + title: `选择女优头像 (${imageLinks.length} 张)`, + area: utils.getResponsiveArea(["900px", "85%"]), + content: imageListHtml, + btn: ["关闭"], + success: (selectionLayero, selectionIndex) => { + const $container = $(selectionLayero), $images = $container.find(".gfriends-selectable-img"), + $prompt = $container.find("#gfriends-prompt"); + $images.each((function () { + const $img = $(this), wrapperId = $img.data("wrapper-id"), $wrapper = $container.find(`#${wrapperId}`), + $sizeTag = $container.find(`.gfriends-size-tag[data-size-for="${wrapperId}"]`); + $img.on("load", (function () { + const width = this.naturalWidth, height = this.naturalHeight; + $sizeTag.text(`${width} x ${height}`); + })); + $img.on("error", (function () { + $wrapper.remove(); + errorCount++; + const validCount = imageLinks.length - errorCount; + $prompt.text(`点击图片即可选择(已移除 ${errorCount} 张错误图片,剩余 ${validCount} 张)`); + if (0 === validCount) { + show.error("所有搜索到的头像链接均已失效,无法选择。"); + layer.close(selectionIndex); + } + })); + this.complete && (this.naturalWidth > 0 ? $img.trigger("load") : $img.trigger("error")); + })); + $images.on("click", (function () { + const $clickedImg = $(this), selectedUrl = $clickedImg.data("url"); + $("#edit-actress-avatar").val(selectedUrl); + $("#edit-avatar-preview").attr("src", selectedUrl); + $images.removeClass("is-selected"); + $clickedImg.addClass("is-selected"); + setTimeout((() => { + layer.close(selectionIndex); + }), 150); + })); + utils.setupEscClose(selectionIndex); } + }); + } + } - class HistoryPlugin extends BasePlugin { - constructor() { - super(...arguments); - __publicField2(this, "tableObj", null); + class HistoryPlugin extends BasePlugin { + constructor() { + super(...arguments); + __publicField2(this, "tableObj", null); + } + + getName() { + return "HistoryPlugin"; + } + + async initCss() { + return "\n \n "; - } + class Drive115 extends Req { + static files(cid = "0", params = {}) { + return this.request({ + url: "https://webapi.115.com/files", + params: {cid, ...params} + }); + } - handle() { - let fc2Url = "/advanced_search?type=3&score_min=0&d=1"; - $('.navbar-item:contains("FC2")').attr("href", fc2Url); - $('.tabs a:contains("FC2")').attr("href", fc2Url); - if (currentHref$1.includes("advanced_search?type=3")) { - $("h2.section-title").contents().first().replaceWith("Fc2PPV"); - $(".section .container > .box").remove(); - } - if (currentHref$1.includes("collection_codes?movieId")) { - $("section").html(""); - const urlParams = new URLSearchParams(window.location.search); - let movieId = urlParams.get("movieId"), carNum2 = urlParams.get("carNum"), - url = urlParams.get("url"); - movieId && carNum2 && url && this.openFc2Dialog(movieId, carNum2, url); - } - } + static filesSearch(search_value, params = {}) { + return this.request({ + url: "https://webapi.115.com/files/search", + params: {search_value, ...params} + }); + } - openFc2Dialog(movieId, carNum2, href) { - let tempCarNum = carNum2.replace("FC2-", ""); - if (href.includes("123av")) { - this.getBean("Fc2By123AvPlugin").open123AvFc2Dialog(carNum2, href); - return; - } - layer.open({ - type: 1, - title: carNum2, - content: '\n
\n ', - area: utils.getResponsiveArea(["70%", "90%"]), - skin: "movie-detail-layer", - scrollbar: false, - success: (layero, index) => { - this.loadData(movieId, carNum2); - $("#favoriteBtn").on("click", (async (event) => { - const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_FAVORITE$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - })); - $("#filterBtn").on("click", ((event) => { - utils.q(event, `是否屏蔽${carNum2}?`, (async () => { - const actress = $("#data-actress").text(), - publishTime = $("#data-releaseDate").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_FILTER$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - window.location.href.includes("collection_codes?movieId") && utils.closePage(); - })); - })); - $("#hasDownBtn").on("click", (async (event) => { - const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_HAS_DOWN$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - })); - $("#hasWatchBtn").on("click", (async (event) => { - const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_HAS_WATCH$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - })); - $("#subtitleSearchBtn").on("click", (() => { - window.JavPackSubtitle.openSearchModal({details: {code: carNum2}}); - })); - window.JavPackSubtitle.preload115Matches(carNum2); - $("#magnetSearchBtn").on("click", (() => { - let magnetHub = this.getBean("MagnetHubPlugin").createMagnetHub(carNum2); - layer.open({ - type: 1, - title: "磁力搜索", - content: '
', - area: utils.getResponsiveArea(["60%", "80%"]), - scrollbar: false, - success: () => { - $("#magnetHubBox").append(magnetHub); - } - }); - })); - this.getBean("OtherSitePlugin").loadOtherSite(tempCarNum, carNum2).then(); - utils.setupEscClose(index); - }, - end() { - window.location.href.includes("collection_codes?movieId") && utils.closePage(); - } - }); - } + static lixianTaskLists(page = 1) { + return this.request({ + url: "https://115.com/web/lixian/", + params: {ct: "lixian", ac: "task_lists", page} + }); + } - loadData(movieId, carNum2) { - let tempCarNum = carNum2.replace("FC2-", ""); - this.handleMovieDetail(movieId); - this.handleLongImg(tempCarNum); - this.handleMagnets(movieId); - this.getBean("ReviewPlugin").showReview(movieId, $("#reviews-content")).then(); - this.getBean("RelatedPlugin").showRelated($("#related-content"), movieId).then(); - } + static labelList() { + return this.request({ + url: "https://webapi.115.com/label/list", + params: {keyword: "", limit: 11150} + }); + } - handleMovieDetail(movieId) { - javDbApi.getMovieDetail(movieId).then(((res) => { - const actors = res.actors || [], imgList = res.imgList || []; - let actorsHtml = ""; - if (actors.length > 0) { - let actress = ""; - for (let i = 0; i < actors.length; i++) { - let actor = actors[i]; - actorsHtml += `${actor.name}`; - 0 === actor.gender && (actress += actor.name + " "); - } - $("#data-actress").text(actress); - } else actorsHtml = '暂无演员信息'; - let imagesHtml = ""; - imagesHtml = Array.isArray(imgList) && imgList.length > 0 ? imgList.map(((img, index) => ` + /** + * @connect 115vod.com + */ + static filesVideo(pickcode) { + return this.request({ + url: "https://115vod.com/webapi/files/video", + params: {pickcode, local: 1} + }); + } + + static post(details) { + return this.request({method: "POST", ...details}); + } + + static filesAdd(cname, pid) { + return this.post({ + url: "https://webapi.115.com/files/add", + data: {cname, pid} + }); + } + + static lixianAddTaskUrl(url, wp_path_id) { + return this.post({ + url: "https://115.com/web/lixian/", + params: {ct: "lixian", ac: "add_task_url"}, + data: {url, wp_path_id} + }); + } + + /** + * Bulk delete offline tasks and source files + * @param {string[]} hash Array of info_hashes + */ + static lixianTaskDel(hash) { + return this.post({ + url: "https://115.com/web/lixian/", + params: {ct: "lixian", ac: "task_del"}, + data: {hash} + }); + } + + /** + * Bulk delete files + * @param {string[]} fid Array of file IDs + * @param {string} pid Parent folder ID + */ + static rbDelete(fid, pid = "") { + return this.post({ + url: "https://webapi.115.com/rb/delete", + data: {fid, pid, ignore_warn: 1} + }); + } + + /** + * Batch move files + * @param {string[]} fid Array of file IDs + * @param {string} pid Destination folder ID + */ + static filesMove(fid, pid) { + return this.post({ + url: "https://webapi.115.com/files/move", + data: {fid, pid, move_proid: ""} + }); + } + + /** + * Bulk label files + * @param {string} file_ids fid1,fid2,fid3... + * @param {string} file_label label_id1,label_id2,label_id3... + */ + static filesBatchLabel(file_ids, file_label, action = "add") { + return this.post({ + url: "https://webapi.115.com/files/batch_label", + data: {file_ids, file_label, action} + }); + } + + /** + * Bulk rename files + * @param {object} files_new_name { [fid]: rename } + */ + static filesBatchRename(files_new_name) { + return this.post({ + url: "https://webapi.115.com/files/batch_rename", + data: {files_new_name} + }); + } + + static sampleInitUpload({filename, filesize, cid}) { + return this.post({ + url: "https://uplb.115.com/3.0/sampleinitupload.php", + data: {filename, filesize, target: `U_1_${cid}`} + }); + } + + /** + * @connect aliyuncs.com + */ + static upload({ + host: url, + filename: name2, + object: key, + policy, + accessid: OSSAccessKeyId, + callback, + signature, + file + }) { + return this.post({ + url, + data: { + name: name2, + key, + policy, + OSSAccessKeyId, + success_action_status: "200", + callback, + signature, + file + } + }); + } + + static filesEdit(fid, fid_cover) { + return this.post({ + url: "https://webapi.115.com/files/edit", + data: {fid, fid_cover} + }); + } + } + + __publicField(Drive115, "DEFAULT_GET_RESPONSE_TYPE", "json"); + + class Req115 extends Drive115 { + static async filesAll(cid, params = {}) { + const res = await this.files(cid, params); + const {count, page_size, data} = res; + return count > page_size && data.length ? this.files(cid, {...params, limit: count}) : res; + } + + static filesAllVideos(cid, params = {}) { + return this.filesAll(cid, {...params, type: 4}); + } + + static filesAllSRTs(cid, params = {}) { + return this.filesAll(cid, {...params, suffix: "srt"}); + } + + static async filesSearchAll(search_value, params = {}) { + const res = await this.filesSearch(search_value, params); + const {count, page_size, data} = res; + return count > page_size && data.length ? this.filesSearch(search_value, {...params, limit: count}) : res; + } + + static filesSearchAllVideos(search_value, params = {}) { + return this.filesSearchAll(search_value, {...params, type: 4}); + } + + static filesSearchAllFolders(search_value, params = {}) { + return this.filesSearchAll(search_value, {...params, fc: 1}); + } + + static async handleDir(routes) { + var _a; + if (routes.length === 1 && /^\d{5,}$/.test(routes[0])) return routes[0]; + let cid; + const routesStr = routes.join("/"); + const cachedCid = localStorage.getItem(routesStr); + if (cachedCid) { + const res = await this.files(cachedCid); + if ((_a = res == null ? void 0 : res.path) == null ? void 0 : _a.length) { + const path = res.path.slice(1).map((p) => p.name); + if (path.join("/") === routesStr) cid = cachedCid; + } + } + if (!cid) { + cid = "0"; + for (const route of routes) { + const {data} = await this.filesSearchAllFolders(route, {cid}); + let folder = data.find((folder2) => folder2.n === route); + if (!folder) folder = await this.filesAdd(route, cid); + cid = folder == null ? void 0 : folder.cid; + if (!cid) break; + } + } + const month = (/* @__PURE__ */ new Date()).getMonth().toString(); + if (localStorage.getItem("115_CD") !== month) { + localStorage.clear(); + localStorage.setItem("115_CD", month); + } + if (cid) localStorage.setItem(routesStr, cid); + return cid; + } + + static async handleVerify(info_hash, {regex, codes}, {max, filter}) { + const sleep = () => { + return new Promise((r) => { + setTimeout(r, 1e3); + }); + }; + let file_id = ""; + let videos = []; + for (let index = 0; index < max; index++) { + if (index) await sleep(); + const {tasks} = await this.lixianTaskLists(); + const task = tasks.find((task2) => task2.info_hash === info_hash); + if (!task || task.status === -1) break; + file_id = task.file_id; + if (file_id) break; + } + if (!file_id) return {file_id, videos}; + for (let index = 0; index < max; index++) { + if (index) await sleep(); + const {data} = await this.filesAllVideos(file_id); + videos = data.filter((item) => regex.test(item.n)); + if (videos.length) break; + } + if (!videos.length) { + const {tasks} = await this.lixianTaskLists(); + const task = tasks.find((task2) => task2.info_hash === info_hash); + if (task.status === 2) { + const {data} = await this.filesAllVideos(file_id); + codes = codes.map((code) => code.toUpperCase()); + videos = data.filter((item) => { + const name2 = item.n.toUpperCase(); + return codes.some((code) => name2.includes(code)); + }); + } + } + return {videos: videos.filter(filter), file_id}; + } + + static async handleClean(keepFiles, cid) { + const needMove = keepFiles.filter((file) => file.cid !== cid).map((file) => file.fid); + if (needMove.length) await this.filesMove(needMove, cid); + const {data} = await this.filesAll(cid); + const needRemove = data.filter((item) => !keepFiles.some((file) => file.fid === item.fid)).map((item) => item.fid ?? item.cid); + if (needRemove.length) return this.rbDelete(needRemove, cid); + } + + static async handleTags(files, tags) { + var _a; + const {data} = await this.labelList(); + if (!((_a = data == null ? void 0 : data.list) == null ? void 0 : _a.length)) return; + const {list} = data; + const labels = []; + tags.forEach((tag) => { + const item = list.find((item2) => item2.name === tag); + if (item) labels.push(item.id); + }); + if (labels.length) return this.filesBatchLabel(files.map((it) => it.fid).toString(), labels.toString()); + } + + static handleRename(files, cid, {rename, renameTxt, zh, crack}) { + rename = rename.replaceAll("$zh", zh ? renameTxt.zh : ""); + rename = rename.replaceAll("$crack", crack ? renameTxt.crack : ""); + rename = rename.split("$sep").filter(Boolean).join(renameTxt.sep); + rename = rename.trim(); + const renameObj = {[cid]: rename}; + if (files.length === 1) { + const {fid, ico} = files[0]; + renameObj[fid] = `${rename}.${ico}`; + return this.filesBatchRename(renameObj); + } + const icoMap = files.reduce((acc, {ico, ...item}) => { + acc[ico] ?? (acc[ico] = []); + acc[ico].push(item); + return acc; + }, {}); + const noTxt = renameTxt.no; + for (const [ico, items] of Object.entries(icoMap)) { + if (items.length === 1) { + renameObj[items[0].fid] = `${rename}.${ico}`; + continue; + } + items.toSorted((a, b) => a.n.localeCompare(b.n)).forEach(({fid}, idx) => { + const no = noTxt.replaceAll(`\${no}`, `${idx + 1}`.padStart(2, "0")); + renameObj[fid] = `${rename}${no}.${ico}`; + }); + } + return this.filesBatchRename(renameObj); + } + + static async handleCover(url, cid, filename) { + const file = await this.request({url, timeout: 6e4, responseType: "blob"}); + if (!file) return; + const res = await this.sampleInitUpload({cid, filename, filesize: file.size}); + if (res == null ? void 0 : res.host) return this.upload({...res, filename, file}); + } + + static async handleOffline({ + dir, + regex, + codes, + verifyOptions, + code, + rename, + renameTxt, + tags, + clean, + cover + }, magnets) { + const res = {status: "error", msg: `获取目录失败: ${dir.join("/")}`}; + const cid = await this.handleDir(dir); + if (!cid) return res; + for (let index = 0, {length} = magnets; index < length; index++) { + const {url, zh, crack} = magnets[index]; + const {state, error_msg, errcode, info_hash} = await this.lixianAddTaskUrl(url, cid); + if (!state) { + res.msg = error_msg; + res.status = "error"; + res.currIdx = index; + if (errcode === 10008) continue; + if (errcode === 911) res.status = "warn"; + break; + } + const {videos, file_id} = await this.handleVerify(info_hash, {regex, codes}, verifyOptions); + if (!videos.length) { + if (verifyOptions.clean) this.lixianTaskDel([info_hash]); + if (file_id && clean) this.rbDelete([file_id], cid); + res.msg = `${code} 离线验证失败`; + res.status = "error"; + continue; + } + const {data: srts = []} = await this.filesAllSRTs(file_id); + const files = [...videos, ...srts]; + if (clean) await this.handleClean(files, file_id); + if (tags.length) this.handleTags(videos, tags); + if (rename) this.handleRename(files, file_id, {rename, renameTxt, zh: zh || srts.length, crack}); + if (cover) { + try { + const {data} = await this.handleCover(cover, file_id, `${code}.cover.jpg`); + if (data == null ? void 0 : data.file_id) this.filesEdit(file_id, data.file_id); + } catch (err) { + console.warn("[Req115.handleCover]", err == null ? void 0 : err.message); + } + } + res.msg = `${code} 离线任务成功`; + res.status = "success"; + break; + } + return res; + } + + static async queueMutation(name2, fn) { + return fn(); + } + } + + window.Req115 = Req115; + + class Fc2Plugin extends BasePlugin { + getName() { + return "Fc2Plugin"; + } + + async initCss() { + return "\n \n "; + } + + handle() { + let fc2Url = "/advanced_search?type=3&score_min=0&d=1"; + $('.navbar-item:contains("FC2")').attr("href", fc2Url); + $('.tabs a:contains("FC2")').attr("href", fc2Url); + if (currentHref$1.includes("advanced_search?type=3")) { + $("h2.section-title").contents().first().replaceWith("Fc2PPV"); + $(".section .container > .box").remove(); + } + if (currentHref$1.includes("collection_codes?movieId")) { + $("section").html(""); + const urlParams = new URLSearchParams(window.location.search); + let movieId = urlParams.get("movieId"), carNum2 = urlParams.get("carNum"), url = urlParams.get("url"); + movieId && carNum2 && url && this.openFc2Dialog(movieId, carNum2, url); + } + } + + openFc2Dialog(movieId, carNum2, href) { + let tempCarNum = carNum2.replace("FC2-", ""); + if (href.includes("123av")) { + this.getBean("Fc2By123AvPlugin").open123AvFc2Dialog(carNum2, href); + return; + } + layer.open({ + type: 1, + title: carNum2, + content: '\n
\n \n \n
\n
加载中...
\n
\n \n
第三方资源:
\n \n \n
\n \n
\n
\n
\n \n \n \n
\n ', + area: utils.getResponsiveArea(["70%", "90%"]), + skin: "movie-detail-layer", + scrollbar: false, + success: (layero, index) => { + this.loadData(movieId, carNum2); + $("#favoriteBtn").on("click", (async (event) => { + const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_FAVORITE$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + })); + $("#filterBtn").on("click", ((event) => { + utils.q(event, `是否屏蔽${carNum2}?`, (async () => { + const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_FILTER$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + window.location.href.includes("collection_codes?movieId") && utils.closePage(); + })); + })); + $("#hasDownBtn").on("click", (async (event) => { + const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_HAS_DOWN$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + })); + $("#hasWatchBtn").on("click", (async (event) => { + const actress = $("#data-actress").text(), publishTime = $("#data-releaseDate").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_HAS_WATCH$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + })); + $("#subtitleSearchBtn").on("click", (() => { + window.JavPackSubtitle.openSearchModal({details: {code: carNum2}}); + })); + window.JavPackSubtitle.preload115Matches(carNum2); + $("#magnetSearchBtn").on("click", (() => { + let magnetHub = this.getBean("MagnetHubPlugin").createMagnetHub(carNum2); + layer.open({ + type: 1, + title: "磁力搜索", + content: '
', + area: utils.getResponsiveArea(["60%", "80%"]), + scrollbar: false, + success: () => { + $("#magnetHubBox").append(magnetHub); + } + }); + })); + this.getBean("OtherSitePlugin").loadOtherSite(tempCarNum, carNum2).then(); + utils.setupEscClose(index); + }, + end() { + window.location.href.includes("collection_codes?movieId") && utils.closePage(); + } + }); + } + + loadData(movieId, carNum2) { + let tempCarNum = carNum2.replace("FC2-", ""); + this.handleMovieDetail(movieId); + this.handleLongImg(tempCarNum); + this.handleMagnets(movieId); + this.getBean("ReviewPlugin").showReview(movieId, $("#reviews-content")).then(); + this.getBean("RelatedPlugin").showRelated($("#related-content"), movieId).then(); + } + + handleMovieDetail(movieId) { + javDbApi.getMovieDetail(movieId).then(((res) => { + const actors = res.actors || [], imgList = res.imgList || []; + let actorsHtml = ""; + if (actors.length > 0) { + let actress = ""; + for (let i = 0; i < actors.length; i++) { + let actor = actors[i]; + actorsHtml += `${actor.name}`; + 0 === actor.gender && (actress += actor.name + " "); + } + $("#data-actress").text(actress); + } else actorsHtml = '暂无演员信息'; + let imagesHtml = ""; + imagesHtml = Array.isArray(imgList) && imgList.length > 0 ? imgList.map(((img, index) => ` `)).join("") : '
暂无剧照
'; - $(".movie-info-container").html(` + $(".movie-info-container").html(`

${res.title || "无标题"}

番号: ${res.carNum || "未知"} @@ -9200,31 +9134,31 @@ ${value}\r
`); - this.getBean("TranslatePlugin").translate(res.carNum, false).then(); - })).catch(((err) => { - console.error(err); - $(".movie-info-container").html(` + this.getBean("TranslatePlugin").translate(res.carNum, false).then(); + })).catch(((err) => { + console.error(err); + $(".movie-info-container").html(`
加载失败: ${err.message}
`); - })); - } + })); + } - handleLongImg(carNum2) { - utils.loopDetector((() => $(".movie-gallery .image-list").length > 0), (async () => { - $(".movie-gallery .image-list").prepend('
正在加载缩略图
'); - const screenShotPlugin = this.getBean("ScreenShotPlugin"), - imgUrl = await screenShotPlugin.getScreenshot(carNum2); - imgUrl && await screenShotPlugin.addImg("缩略图", imgUrl, carNum2); - })); - } + handleLongImg(carNum2) { + utils.loopDetector((() => $(".movie-gallery .image-list").length > 0), (async () => { + $(".movie-gallery .image-list").prepend('
正在加载缩略图
'); + const screenShotPlugin = this.getBean("ScreenShotPlugin"), + imgUrl = await screenShotPlugin.getScreenshot(carNum2); + imgUrl && await screenShotPlugin.addImg("缩略图", imgUrl, carNum2); + })); + } - handleMagnets(movieId) { - javDbApi.getMagnets(movieId).then(((magnetList) => { - let magnetsHtml = ""; - if (magnetList.length > 0) for (let i = 0; i < magnetList.length; i++) { - let magnet = magnetList[i], oddClass = ""; - i % 2 == 0 && (oddClass = "odd"); - magnetsHtml += ` + handleMagnets(movieId) { + javDbApi.getMagnets(movieId).then(((magnetList) => { + let magnetsHtml = ""; + if (magnetList.length > 0) for (let i = 0; i < magnetList.length; i++) { + let magnet = magnetList[i], oddClass = ""; + i % 2 == 0 && (oddClass = "odd"); + magnetsHtml += `
`; - } - else magnetsHtml = '暂无磁力信息'; - $("#magnets-content").html(magnetsHtml); - $(".buttons button[data-clipboard-text*='magnet:']").each(((i, el) => { - $(el).parent().append($("'); - $tag.append(button); - button.fadeIn(0); - }), (function () { - $(this).find(".highlight-btn").fadeOut(0, (function () { - $(this).remove(); - })); - })); - $(document).on("click", ".highlight-btn", (async function (e) { - e.stopPropagation(); - e.preventDefault(); - const $tag = $(this).closest("a.tag"), clonedTag = $tag.clone(); - clonedTag.find(".highlight-btn").remove(); - const tagText = clonedTag.text().trim().replace(/\s*\(\d+\)$/, ""); - let highlightedTags = await storageManager.getHighlightedTags(); - if (highlightedTags.includes(tagText)) { - highlightedTags = highlightedTags.filter(((item) => item !== tagText)); - $tag.removeClass("highlighted"); - } else { - highlightedTags.push(tagText); - $tag.addClass("highlighted"); - } - await storageManager.setHighlightedTags(highlightedTags); - })); - } + highlightTag() { + (async () => { + const tags = await storageManager.getHighlightedTags(); + tags && tags.forEach(((text) => { + $(`#tags a.tag:contains(${text})`).addClass("highlighted"); + $(`.tags a.tag:contains(${text})`).addClass("highlighted"); + })); + })().then(); + $("#tags a.tag, .tags a.tag").hover((function () { + const $tag = $(this), button = $(''); + $tag.append(button); + button.fadeIn(0); + }), (function () { + $(this).find(".highlight-btn").fadeOut(0, (function () { + $(this).remove(); + })); + })); + $(document).on("click", ".highlight-btn", (async function (e) { + e.stopPropagation(); + e.preventDefault(); + const $tag = $(this).closest("a.tag"), clonedTag = $tag.clone(); + clonedTag.find(".highlight-btn").remove(); + const tagText = clonedTag.text().trim().replace(/\s*\(\d+\)$/, ""); + let highlightedTags = await storageManager.getHighlightedTags(); + if (highlightedTags.includes(tagText)) { + highlightedTags = highlightedTags.filter(((item) => item !== tagText)); + $tag.removeClass("highlighted"); + } else { + highlightedTags.push(tagText); + $tag.addClass("highlighted"); + } + await storageManager.setHighlightedTags(highlightedTags); + })); + } - async createFoldBtn() { - const foldCategoryHotKey = await storageManager.getSetting("foldCategoryHotKey"); - let $subTags = $("#tags"), checkTagStr = $("#tags dl div.tag.is-info").map((function () { - return $(this).text().replaceAll("\n", "").replaceAll(" ", ""); - })).get().join(" "); - if (!checkTagStr) return; - $(".tabs").append(` + async createFoldBtn() { + const foldCategoryHotKey = await storageManager.getSetting("foldCategoryHotKey"); + let $subTags = $("#tags"), checkTagStr = $("#tags dl div.tag.is-info").map((function () { + return $(this).text().replaceAll("\n", "").replaceAll(" ", ""); + })).get().join(" "); + if (!checkTagStr) return; + $(".tabs").append(` `); - let $section = $("h2.section-title"); - if ($section.length > 0) { - $section.append('\n \n '); - $subTags = $("section > div > div.box"); - } - if (!$subTags) return; - let $foldCategoryBtn = $("#foldCategoryBtn"), - isFolded = localStorage.getItem("jhs_foldCategory") === YES$1, [newText, newIcon] = isFolded ? ["展开", "icon-angle-double-down"] : ["折叠", "icon-angle-double-up"]; - $foldCategoryBtn.find("span").text(newText).end().find("i").attr("class", newIcon); - window.location.href.includes("noFold=1") || $subTags[isFolded ? "hide" : "show"](); - $foldCategoryBtn.on("click", (async (event) => { - event.preventDefault(); - isFolded = !isFolded; - localStorage.setItem("jhs_foldCategory", isFolded ? YES$1 : NO); - const [newText2, newIcon2] = isFolded ? ["展开", "icon-angle-double-down"] : ["折叠", "icon-angle-double-up"]; - $foldCategoryBtn.find("span").text(newText2).end().find("i").attr("class", newIcon2); - $subTags[isFolded ? "hide" : "show"](); - })); - } + let $section = $("h2.section-title"); + if ($section.length > 0) { + $section.append('\n
\n \n \n \n \n
\n '); + $subTags = $("section > div > div.box"); + } + if (!$subTags) return; + let $foldCategoryBtn = $("#foldCategoryBtn"), + isFolded = localStorage.getItem("jhs_foldCategory") === YES$1, [newText, newIcon] = isFolded ? ["展开", "icon-angle-double-down"] : ["折叠", "icon-angle-double-up"]; + $foldCategoryBtn.find("span").text(newText).end().find("i").attr("class", newIcon); + window.location.href.includes("noFold=1") || $subTags[isFolded ? "hide" : "show"](); + $foldCategoryBtn.on("click", (async (event) => { + event.preventDefault(); + isFolded = !isFolded; + localStorage.setItem("jhs_foldCategory", isFolded ? YES$1 : NO); + const [newText2, newIcon2] = isFolded ? ["展开", "icon-angle-double-down"] : ["折叠", "icon-angle-double-up"]; + $foldCategoryBtn.find("span").text(newText2).end().find("i").attr("class", newIcon2); + $subTags[isFolded ? "hide" : "show"](); + })); + } + } + + class ActressInfoPlugin extends BasePlugin { + constructor() { + super(...arguments); + __publicField2(this, "apiUrl", "https://ja.wikipedia.org/wiki/"); + } + + getName() { + return "ActressInfoPlugin"; + } + + async handle() { + "yes" === await storageManager.getSetting("enableLoadActressInfo", "yes") && this.loadActressInfo(); + } + + loadActressInfo() { + this.handleDetailPage().then(); + this.handleStarPage().then(); + } + + async initCss() { + return "\n \n "; + } + + async handleDetailPage() { + if ($(".actress-info").length > 0) return; + let nameList = $(".female").prev().map(((i, el) => $(el).text().trim())).get(); + if (!nameList.length) return; + const cacheKey = "jhs_actress_info", + cacheData = localStorage.getItem(cacheKey) ? JSON.parse(localStorage.getItem(cacheKey)) : {}; + let result = null, infoHtml = ""; + for (let i = 0; i < nameList.length; i++) { + let name2 = nameList[i]; + result = cacheData[name2]; + if (!result) try { + result = await this.searchInfo(name2); + result && (cacheData[name2] = result); + } catch (e) { + console.error("该名称查询失败,尝试其它名称"); } - - class ActressInfoPlugin extends BasePlugin { - constructor() { - super(...arguments); - __publicField2(this, "apiUrl", "https://ja.wikipedia.org/wiki/"); - } - - getName() { - return "ActressInfoPlugin"; - } - - async handle() { - "yes" === await storageManager.getSetting("enableLoadActressInfo", "yes") && this.loadActressInfo(); - } - - loadActressInfo() { - this.handleDetailPage().then(); - this.handleStarPage().then(); - } - - async initCss() { - return "\n \n "; - } - - async handleDetailPage() { - if ($(".actress-info").length > 0) return; - let nameList = $(".female").prev().map(((i, el) => $(el).text().trim())).get(); - if (!nameList.length) return; - const cacheKey = "jhs_actress_info", - cacheData = localStorage.getItem(cacheKey) ? JSON.parse(localStorage.getItem(cacheKey)) : {}; - let result = null, infoHtml = ""; - for (let i = 0; i < nameList.length; i++) { - let name2 = nameList[i]; - result = cacheData[name2]; - if (!result) try { - result = await this.searchInfo(name2); - result && (cacheData[name2] = result); - } catch (e) { - console.error("该名称查询失败,尝试其它名称"); - } - let contentHtml = ""; - contentHtml = result ? ` + let contentHtml = ""; + contentHtml = result ? ` ` : ` `; - infoHtml += contentHtml; - } - $('strong:contains("演員")').parent().after(infoHtml); - localStorage.setItem(cacheKey, JSON.stringify(cacheData)); - } + infoHtml += contentHtml; + } + $('strong:contains("演員")').parent().after(infoHtml); + localStorage.setItem(cacheKey, JSON.stringify(cacheData)); + } - async handleStarPage() { - if ($(".actress-info").length > 0) return; - let nameList = [], $actor = $(".actor-section-name"); - $actor.length && $actor.text().trim().split(",").forEach(((name2) => { - nameList.push(name2.trim()); - })); - let $sectionMeta = $(".section-meta:not(:contains('影片'))"); - $sectionMeta.length && $sectionMeta.text().trim().split(",").forEach(((name2) => { - nameList.push(name2.trim()); - })); - if (!nameList.length) return; - const cacheKey = "jhs_actress_info", - cacheData = localStorage.getItem(cacheKey) ? JSON.parse(localStorage.getItem(cacheKey)) : {}; - let result = null; - for (let i = 0; i < nameList.length; i++) { - let name2 = nameList[i]; - result = cacheData[name2]; - if (result) break; - try { - result = await this.searchInfo(name2); - } catch (e) { - console.error("该名称查询失败,尝试其它名称"); - } - if (result) break; - } - result && nameList.forEach(((name2) => { - cacheData[name2] = result; - })); - let contentHtml = '
无此相关演员信息
'; - result && (contentHtml = ` + async handleStarPage() { + if ($(".actress-info").length > 0) return; + let nameList = [], $actor = $(".actor-section-name"); + $actor.length && $actor.text().trim().split(",").forEach(((name2) => { + nameList.push(name2.trim()); + })); + let $sectionMeta = $(".section-meta:not(:contains('影片'))"); + $sectionMeta.length && $sectionMeta.text().trim().split(",").forEach(((name2) => { + nameList.push(name2.trim()); + })); + if (!nameList.length) return; + const cacheKey = "jhs_actress_info", + cacheData = localStorage.getItem(cacheKey) ? JSON.parse(localStorage.getItem(cacheKey)) : {}; + let result = null; + for (let i = 0; i < nameList.length; i++) { + let name2 = nameList[i]; + result = cacheData[name2]; + if (result) break; + try { + result = await this.searchInfo(name2); + } catch (e) { + console.error("该名称查询失败,尝试其它名称"); + } + if (result) break; + } + result && nameList.forEach(((name2) => { + cacheData[name2] = result; + })); + let contentHtml = '
无此相关演员信息
'; + result && (contentHtml = `
@@ -9740,106 +9672,106 @@ ${value}\r
`); - $actor.parent().append(contentHtml); - localStorage.setItem(cacheKey, JSON.stringify(cacheData)); - } + $actor.parent().append(contentHtml); + localStorage.setItem(cacheKey, JSON.stringify(cacheData)); + } - async searchInfo(name2) { - "三上悠亞" === name2 && (name2 = "三上悠亜"); - let url = this.apiUrl + name2; - const html = await gmHttp.get(url), parser = new DOMParser(), - $dom = $(parser.parseFromString(html, "text/html")); - let birthday = $dom.find('a[title="誕生日"]').parent().parent().find("td").text().trim(), - age = $dom.find("th:contains('現年齢')").parent().find("td").text().trim() ? parseInt($dom.find("th:contains('現年齢')").parent().find("td").text().trim()) + "岁" : "", - height = $dom.find('tr:has(a[title="身長"]) td').text().trim().split(" ")[0] + "cm", - weight = $dom.find('tr:has(a[title="体重"]) td').text().trim().split("/")[1].trim(); - "― kg" === weight && (weight = ""); - return { - birthday, - age, - height, - weight, - threeSizeText: $dom.find('a[title="スリーサイズ"]').closest("tr").find("td").text().replace("cm", "").trim(), - braSize: $dom.find('th:contains("ブラサイズ")').next("td").contents().first().text().trim(), - url - }; - } + async searchInfo(name2) { + "三上悠亞" === name2 && (name2 = "三上悠亜"); + let url = this.apiUrl + name2; + const html = await gmHttp.get(url), parser = new DOMParser(), + $dom = $(parser.parseFromString(html, "text/html")); + let birthday = $dom.find('a[title="誕生日"]').parent().parent().find("td").text().trim(), + age = $dom.find("th:contains('現年齢')").parent().find("td").text().trim() ? parseInt($dom.find("th:contains('現年齢')").parent().find("td").text().trim()) + "岁" : "", + height = $dom.find('tr:has(a[title="身長"]) td').text().trim().split(" ")[0] + "cm", + weight = $dom.find('tr:has(a[title="体重"]) td').text().trim().split("/")[1].trim(); + "― kg" === weight && (weight = ""); + return { + birthday, + age, + height, + weight, + threeSizeText: $dom.find('a[title="スリーサイズ"]').closest("tr").find("td").text().replace("cm", "").trim(), + braSize: $dom.find('th:contains("ブラサイズ")').next("td").contents().first().text().trim(), + url + }; + } + } + + class AliyunPanPlugin extends BasePlugin { + getName() { + return "AliyunPanPlugin"; + } + + handle() { + $("body").append('获取refresh_token'); + $("#refresh-token-btn").on("click", ((event) => { + let tokenStr = localStorage.getItem("token"); + if (!tokenStr) { + alert("请先登录!"); + return; } + let refresh_token = JSON.parse(tokenStr).refresh_token; + navigator.clipboard.writeText(refresh_token).then((() => { + alert("已复制到剪切板 如失败, 请手动复制: " + refresh_token); + })).catch(((err) => { + console.error("Failed to copy refresh token: ", err); + })); + })); + } + } - class AliyunPanPlugin extends BasePlugin { - getName() { - return "AliyunPanPlugin"; - } + class HitShowPlugin extends BasePlugin { + constructor() { + super(); + __publicField2(this, "$contentBox", $(".section .container")); + } - handle() { - $("body").append('获取refresh_token'); - $("#refresh-token-btn").on("click", ((event) => { - let tokenStr = localStorage.getItem("token"); - if (!tokenStr) { - alert("请先登录!"); - return; - } - let refresh_token = JSON.parse(tokenStr).refresh_token; - navigator.clipboard.writeText(refresh_token).then((() => { - alert("已复制到剪切板 如失败, 请手动复制: " + refresh_token); - })).catch(((err) => { - console.error("Failed to copy refresh token: ", err); - })); - })); - } - } + getName() { + return "HitShowPlugin"; + } - class HitShowPlugin extends BasePlugin { - constructor() { - super(); - __publicField2(this, "$contentBox", $(".section .container")); - } + handle() { + $('a[href*="rankings/playback"]').on("click", ((event) => { + event.preventDefault(); + event.stopPropagation(); + window.location.href = "/advanced_search?handlePlayback=1&period=daily"; + })); + this.handlePlayback().then(); + } - getName() { - return "HitShowPlugin"; - } + hookPage() { + let $h2 = $("h2.section-title"); + $h2.contents().first().replaceWith("热播"); + $h2.css("marginBottom", "0"); + $(".empty-message").remove(); + $(".section .container .box").remove(); + $("#sort-toggle-btn").remove(); + this.$contentBox.append('
'); + this.$contentBox.append('
'); + } - handle() { - $('a[href*="rankings/playback"]').on("click", ((event) => { - event.preventDefault(); - event.stopPropagation(); - window.location.href = "/advanced_search?handlePlayback=1&period=daily"; - })); - this.handlePlayback().then(); - } + async handlePlayback() { + if (!window.location.href.includes("handlePlayback=1")) return; + let period = new URLSearchParams(window.location.search).get("period"); + this.toolBar(period); + this.hookPage(); + let $movieBox = $(".movie-list"); + $movieBox.html(""); + let loadObj = loading(); + try { + const movies = await javDbApi.playback(period); + let moviesHtml = javDbApi.markDataListHtml(movies); + $movieBox.html(moviesHtml); + } catch (e) { + clog.error("发生错误:", e); + } finally { + loadObj.close(); + } + } - hookPage() { - let $h2 = $("h2.section-title"); - $h2.contents().first().replaceWith("热播"); - $h2.css("marginBottom", "0"); - $(".empty-message").remove(); - $(".section .container .box").remove(); - $("#sort-toggle-btn").remove(); - this.$contentBox.append('
'); - this.$contentBox.append('
'); - } - - async handlePlayback() { - if (!window.location.href.includes("handlePlayback=1")) return; - let period = new URLSearchParams(window.location.search).get("period"); - this.toolBar(period); - this.hookPage(); - let $movieBox = $(".movie-list"); - $movieBox.html(""); - let loadObj = loading(); - try { - const movies = await javDbApi.playback(period); - let moviesHtml = javDbApi.markDataListHtml(movies); - $movieBox.html(moviesHtml); - } catch (e) { - clog.error("发生错误:", e); - } finally { - loadObj.close(); - } - } - - toolBar(period) { - let conditionHtml = ` + toolBar(period) { + let conditionHtml = `
日榜 @@ -9848,105 +9780,104 @@ ${value}\r
`; - this.$contentBox.append(conditionHtml); - } + this.$contentBox.append(conditionHtml); + } - getStarRating(score) { - let stars = ""; - const fullStars = Math.floor(score); - for (let i = 0; i < fullStars; i++) stars += ''; - for (let i = 0; i < 5 - fullStars; i++) stars += ''; - return stars; - } + getStarRating(score) { + let stars = ""; + const fullStars = Math.floor(score); + for (let i = 0; i < fullStars; i++) stars += ''; + for (let i = 0; i < 5 - fullStars; i++) stars += ''; + return stars; + } - loadScore(movies) { - if (0 === movies.length) return; - (async () => { - for (const movie of movies) try { - const movieId = movie.id; - if (!$(`#score_${movieId}`).length) return; - if ($(`#${movieId}`).is(":hidden")) continue; - const cacheData = localStorage.getItem("jhs_score_info") ? JSON.parse(localStorage.getItem("jhs_score_info")) : {}, - cached = cacheData[movieId]; - if (cached) { - this.appendScoreHtml(movieId, cached); - continue; - } - for (; !document.hasFocus();) await new Promise(((r) => setTimeout(r, 500))); - const res = await javDbApi.getMovieDetail(movieId); - let score = res.score, watchedCount = res.watchedCount, html = ` + loadScore(movies) { + if (0 === movies.length) return; + (async () => { + for (const movie of movies) try { + const movieId = movie.id; + if (!$(`#score_${movieId}`).length) return; + if ($(`#${movieId}`).is(":hidden")) continue; + const cacheData = localStorage.getItem("jhs_score_info") ? JSON.parse(localStorage.getItem("jhs_score_info")) : {}, + cached = cacheData[movieId]; + if (cached) { + this.appendScoreHtml(movieId, cached); + continue; + } + for (; !document.hasFocus();) await new Promise(((r) => setTimeout(r, 500))); + const res = await javDbApi.getMovieDetail(movieId); + let score = res.score, watchedCount = res.watchedCount, html = ` ${this.getStarRating(score)}   ${score}分,由${watchedCount}人評價 `; - this.appendScoreHtml(movieId, html); - cacheData[movieId] = html; - localStorage.setItem("jhs_score_info", JSON.stringify(cacheData)); - await new Promise(((r) => setTimeout(r, 500))); - } catch (err) { - clog.error(`🚨 解析评分数据失败 | 编号: ${movie.number} + this.appendScoreHtml(movieId, html); + cacheData[movieId] = html; + localStorage.setItem("jhs_score_info", JSON.stringify(cacheData)); + await new Promise(((r) => setTimeout(r, 500))); + } catch (err) { + clog.error(`🚨 解析评分数据失败 | 编号: ${movie.number} `, `错误详情: ${err.message} `, err.stack ? `调用栈: ${err.stack}` : ""); - } - })(); - } - - appendScoreHtml(movieId, scoreHtml) { - let $scoreBox = $(`#score_${movieId}`); - $scoreBox.length && "" === $scoreBox.html().trim() && $scoreBox.slideUp(0, (function () { - $(this).html(scoreHtml).slideDown(500); - })); - } } + })(); + } - class TOP250Plugin extends BasePlugin { - constructor() { - super(); - __publicField2(this, "has_cnsub", ""); - __publicField2(this, "$contentBox", $(".section .container")); - __publicField2(this, "movies", []); - } + appendScoreHtml(movieId, scoreHtml) { + let $scoreBox = $(`#score_${movieId}`); + $scoreBox.length && "" === $scoreBox.html().trim() && $scoreBox.slideUp(0, (function () { + $(this).html(scoreHtml).slideDown(500); + })); + } + } - getName() { - return "TOP250Plugin"; - } + class TOP250Plugin extends BasePlugin { + constructor() { + super(); + __publicField2(this, "has_cnsub", ""); + __publicField2(this, "$contentBox", $(".section .container")); + __publicField2(this, "movies", []); + } - handle() { - $('.main-tabs ul li:contains("猜你喜歡")').html('Top250'); - $('a[href*="rankings/top"]').on("click", ((event) => { - event.preventDefault(); - event.stopPropagation(); - const $target = $(event.target), - href = ($target.is("a") ? $target : $target.closest("a")).attr("href"); - let queryString = href.includes("?") ? href.split("?")[1] : href; - const urlParams = new URLSearchParams(queryString); - this.checkLogin(event, urlParams); - })); - this.handleTop().then(); - } + getName() { + return "TOP250Plugin"; + } - hookPage() { - $("h2.section-title").contents().first().replaceWith("Top250"); - $(".empty-message").remove(); - $(".section .container .box").remove(); - $("#sort-toggle-btn").remove(); - this.$contentBox.append('
'); - this.$contentBox.append('
'); - this.renderPagination(); - } + handle() { + $('.main-tabs ul li:contains("猜你喜歡")').html('Top250'); + $('a[href*="rankings/top"]').on("click", ((event) => { + event.preventDefault(); + event.stopPropagation(); + const $target = $(event.target), href = ($target.is("a") ? $target : $target.closest("a")).attr("href"); + let queryString = href.includes("?") ? href.split("?")[1] : href; + const urlParams = new URLSearchParams(queryString); + this.checkLogin(event, urlParams); + })); + this.handleTop().then(); + } - renderPagination() { - const urlParams = new URLSearchParams(window.location.search); - let currentPage = parseInt(urlParams.get("page")) || 1; - this.$contentBox.append(((page) => { - const isNextDisabled = page >= 5; - let paginationListHTML = ""; - for (let i = 1; i <= 5; i++) { - paginationListHTML += `
  • ${i}
  • `; - } - return ` + hookPage() { + $("h2.section-title").contents().first().replaceWith("Top250"); + $(".empty-message").remove(); + $(".section .container .box").remove(); + $("#sort-toggle-btn").remove(); + this.$contentBox.append('
    '); + this.$contentBox.append('
    '); + this.renderPagination(); + } + + renderPagination() { + const urlParams = new URLSearchParams(window.location.search); + let currentPage = parseInt(urlParams.get("page")) || 1; + this.$contentBox.append(((page) => { + const isNextDisabled = page >= 5; + let paginationListHTML = ""; + for (let i = 1; i <= 5; i++) { + paginationListHTML += `
  • ${i}
  • `; + } + return ` `; - })(currentPage)); - this.$contentBox.on("click", ".pagination-link, .pagination-previous, .pagination-next", ((event) => { - event.preventDefault(); - const newPage = parseInt($(event.currentTarget).data("page")); - !isNaN(newPage) && newPage > 0 && ((newPage2) => { - urlParams.set("page", newPage2); - window.history.pushState({}, "", "?" + urlParams.toString()); - window.location.reload(); - })(newPage); - })); - } + })(currentPage)); + this.$contentBox.on("click", ".pagination-link, .pagination-previous, .pagination-next", ((event) => { + event.preventDefault(); + const newPage = parseInt($(event.currentTarget).data("page")); + !isNaN(newPage) && newPage > 0 && ((newPage2) => { + urlParams.set("page", newPage2); + window.history.pushState({}, "", "?" + urlParams.toString()); + window.location.reload(); + })(newPage); + })); + } - async handleTop() { - if (!window.location.href.includes("handleTop=1")) return; - const urlParams = new URLSearchParams(window.location.search); - let type = urlParams.get("handleType") || "all", type_value = urlParams.get("type_value") || ""; - this.has_cnsub = urlParams.get("has_cnsub") || ""; - let page = urlParams.get("page") || 1; - this.toolBar(type, type_value, page); - this.hookPage(); - let $movieBox = $(".movie-list"); - $movieBox.html(""); - let loadObj = loading(); - try { - const res = await javDbApi.top250(type, type_value, page, 50); - let successFlag = res.success, message = res.message, action = res.action; - if (1 === successFlag) { - let dataList = res.data.movies; - if (0 === dataList.length) { - show.error("无数据"); - loadObj.close(); - return; - } - this.movies = dataList; - const filter_movies = dataList.filter(((item) => "1" === this.has_cnsub ? item.has_cnsub : "0" !== this.has_cnsub || !item.has_cnsub)); - let moviesHtml = javDbApi.markDataListHtml(filter_movies); - $movieBox.html(moviesHtml); - } else { - clog.error(res); - $movieBox.html(`

    ${message}

    `); - show.error(message); - if ("JWTVerificationError" === action) { - await localStorage.removeItem("jhs_appAuthorization"); - await this.checkLogin(null, new URLSearchParams(window.location.search)); - } - } - } catch (e) { - clog.error("发生错误:", e); - } finally { - loadObj.close(); - } - } + async handleTop() { + if (!window.location.href.includes("handleTop=1")) return; + const urlParams = new URLSearchParams(window.location.search); + let type = urlParams.get("handleType") || "all", type_value = urlParams.get("type_value") || ""; + this.has_cnsub = urlParams.get("has_cnsub") || ""; + let page = urlParams.get("page") || 1; + this.toolBar(type, type_value, page); + this.hookPage(); + let $movieBox = $(".movie-list"); + $movieBox.html(""); + let loadObj = loading(); + try { + const res = await javDbApi.top250(type, type_value, page, 50); + let successFlag = res.success, message = res.message, action = res.action; + if (1 === successFlag) { + let dataList = res.data.movies; + if (0 === dataList.length) { + show.error("无数据"); + loadObj.close(); + return; + } + this.movies = dataList; + const filter_movies = dataList.filter(((item) => "1" === this.has_cnsub ? item.has_cnsub : "0" !== this.has_cnsub || !item.has_cnsub)); + let moviesHtml = javDbApi.markDataListHtml(filter_movies); + $movieBox.html(moviesHtml); + } else { + clog.error(res); + $movieBox.html(`

    ${message}

    `); + show.error(message); + if ("JWTVerificationError" === action) { + await localStorage.removeItem("jhs_appAuthorization"); + await this.checkLogin(null, new URLSearchParams(window.location.search)); + } + } + } catch (e) { + clog.error("发生错误:", e); + } finally { + loadObj.close(); + } + } - toolBar(type, type_value, currentPage) { - "5" === currentPage.toString() && $(".pagination-next").remove(); - $(".pagination-ellipsis").closest("li").remove(); - $(".pagination-list li a").each((function () { - parseInt($(this).text()) > 5 && $(this).closest("li").remove(); - })); - let yearHtml = ""; - for (let year = (/* @__PURE__ */ new Date()).getFullYear(); year >= 2008; year--) yearHtml += ` + toolBar(type, type_value, currentPage) { + "5" === currentPage.toString() && $(".pagination-next").remove(); + $(".pagination-ellipsis").closest("li").remove(); + $(".pagination-list li a").each((function () { + parseInt($(this).text()) > 5 && $(this).closest("li").remove(); + })); + let yearHtml = ""; + for (let year = (/* @__PURE__ */ new Date()).getFullYear(); year >= 2008; year--) yearHtml += ` ${year} `; - let conditionHtml = ` + let conditionHtml = `
    全部 @@ -10042,51 +9973,51 @@ ${err.stack}` : "");
    `; - this.$contentBox.append(conditionHtml); - $("a[data-cnsub-value]").on("click", ((event) => { - const cnsubValue = $(event.currentTarget).data("cnsub-value"); - this.has_cnsub = cnsubValue.toString(); - $("a[data-cnsub-value]").removeClass("is-info"); - $(event.currentTarget).addClass("is-info"); - $(".toolbar a.button").not("[data-cnsub-value]").each(((index, element) => { - const $link = $(element), url = new URL($link.attr("href"), window.location.origin); - url.searchParams.set("has_cnsub", cnsubValue); - $link.attr("href", url.toString()); - })); - const filter_movies = this.movies.filter(((item) => "1" === this.has_cnsub ? item.has_cnsub : "0" !== this.has_cnsub || !item.has_cnsub)); - let moviesHtml = javDbApi.markDataListHtml(filter_movies); - $(".movie-list").html(moviesHtml); - })); - } + this.$contentBox.append(conditionHtml); + $("a[data-cnsub-value]").on("click", ((event) => { + const cnsubValue = $(event.currentTarget).data("cnsub-value"); + this.has_cnsub = cnsubValue.toString(); + $("a[data-cnsub-value]").removeClass("is-info"); + $(event.currentTarget).addClass("is-info"); + $(".toolbar a.button").not("[data-cnsub-value]").each(((index, element) => { + const $link = $(element), url = new URL($link.attr("href"), window.location.origin); + url.searchParams.set("has_cnsub", cnsubValue); + $link.attr("href", url.toString()); + })); + const filter_movies = this.movies.filter(((item) => "1" === this.has_cnsub ? item.has_cnsub : "0" !== this.has_cnsub || !item.has_cnsub)); + let moviesHtml = javDbApi.markDataListHtml(filter_movies); + $(".movie-list").html(moviesHtml); + })); + } - async checkLogin(event, urlParams) { - if (!localStorage.getItem("jhs_appAuthorization")) { - show.error("该类别依赖移动端接口,请先完成登录"); - this.openLoginDialog(); - return; - } - let type = "all", type_value = "", t = urlParams.get("t") || ""; - if (/^y\d+$/.test(t)) { - type = "year"; - type_value = t.substring(1); - } else if ("" !== t) { - type = "video_type"; - type_value = t; - } - let url = `/advanced_search?handleTop=1&handleType=${type}&type_value=${type_value}`; - event && (event.ctrlKey || event.metaKey) ? _GM_openInTab(window.location.origin + url, { - insert: 0 - }) : window.location.href = url; - } + async checkLogin(event, urlParams) { + if (!localStorage.getItem("jhs_appAuthorization")) { + show.error("该类别依赖移动端接口,请先完成登录"); + this.openLoginDialog(); + return; + } + let type = "all", type_value = "", t = urlParams.get("t") || ""; + if (/^y\d+$/.test(t)) { + type = "year"; + type_value = t.substring(1); + } else if ("" !== t) { + type = "video_type"; + type_value = t; + } + let url = `/advanced_search?handleTop=1&handleType=${type}&type_value=${type_value}`; + event && (event.ctrlKey || event.metaKey) ? _GM_openInTab(window.location.origin + url, { + insert: 0 + }) : window.location.href = url; + } - openLoginDialog() { - layer.open({ - type: 1, - title: "JavDB", - closeBtn: 1, - area: ["360px", "auto"], - shadeClose: false, - content: ` + openLoginDialog() { + layer.open({ + type: 1, + title: "JavDB", + closeBtn: 1, + area: ["360px", "auto"], + shadeClose: false, + content: `
    `, - success: (layero, index) => { - $("#loginBtn").click((function () { - const username = $("#username").val(), password = $("#password").val(); - if (!username || !password) { - show.error("请输入用户名和密码"); - return; - } - let loadObj = loading(); - javDbApi.login(username, password).then((async (res) => { - let success = res.success; - if (0 === success) show.error(res.message); - else { - if (1 !== success) { - clog.error("登录失败", res); - throw new Error(res.message); - } - { - let token = res.data.token; - await localStorage.setItem("jhs_appAuthorization", token); - show.ok("登录成功"); - layer.close(index); - window.location.href = "/advanced_search?handleTop=1&period=daily"; - } - } - })).catch(((err) => { - clog.error("登录异常:", err); - show.error(err.message); - })).finally((() => { - loadObj.close(); - })); - })); - } - }); + success: (layero, index) => { + $("#loginBtn").click((function () { + const username = $("#username").val(), password = $("#password").val(); + if (!username || !password) { + show.error("请输入用户名和密码"); + return; } + let loadObj = loading(); + javDbApi.login(username, password).then((async (res) => { + let success = res.success; + if (0 === success) show.error(res.message); + else { + if (1 !== success) { + clog.error("登录失败", res); + throw new Error(res.message); + } + { + let token = res.data.token; + await localStorage.setItem("jhs_appAuthorization", token); + show.ok("登录成功"); + layer.close(index); + window.location.href = "/advanced_search?handleTop=1&period=daily"; + } + } + })).catch(((err) => { + clog.error("登录异常:", err); + show.error(err.message); + })).finally((() => { + loadObj.close(); + })); + })); } + }); + } + } - class NavBarPlugin extends BasePlugin { - getName() { - return "NavBarPlugin"; - } + class NavBarPlugin extends BasePlugin { + getName() { + return "NavBarPlugin"; + } - async initCss() { - return "\n .highlight-red {\n /* 核心要求:高亮红色文本 */\n color: red !important; \n \n /* 建议:增加字体加粗,效果更明显 */\n font-weight: bold;\n \n /* 建议:增加背景色,效果更突出 */\n /* background-color: yellow; */ \n}\n "; - } + async initCss() { + return "\n .highlight-red {\n /* 核心要求:高亮红色文本 */\n color: red !important; \n \n /* 建议:增加字体加粗,效果更明显 */\n font-weight: bold;\n \n /* 建议:增加背景色,效果更突出 */\n /* background-color: yellow; */ \n}\n "; + } - handle() { - this.margeNav(); - this.hookSearch(); - this.hookOldSearch(); - this.toggleOtherNavItem(); - $(window).resize(this.toggleOtherNavItem); - if (window.location.href.includes("/search")) { - const urlParams = new URLSearchParams(window.location.search); - let q = urlParams.get("q"), f = urlParams.get("f"); - $("#search-keyword").val(q); - f && $("#search-type").val(f); - q && this.highlightKeyword(q); - } - } + handle() { + this.margeNav(); + this.hookSearch(); + this.hookOldSearch(); + this.toggleOtherNavItem(); + $(window).resize(this.toggleOtherNavItem); + if (window.location.href.includes("/search")) { + const urlParams = new URLSearchParams(window.location.search); + let q = urlParams.get("q"), f = urlParams.get("f"); + $("#search-keyword").val(q); + f && $("#search-type").val(f); + q && this.highlightKeyword(q); + } + } - highlightKeyword(keyword) { - const trimedKeyword = keyword.trim(); - if (!trimedKeyword) return; - const lowerCaseKeyword = trimedKeyword.toLowerCase(); - $(".video-title strong, .actor-box strong").each((function () { - const $strongElement = $(this); - $strongElement.text().toLowerCase().includes(lowerCaseKeyword) && $strongElement.addClass("highlight-red"); - })); - } + highlightKeyword(keyword) { + const trimedKeyword = keyword.trim(); + if (!trimedKeyword) return; + const lowerCaseKeyword = trimedKeyword.toLowerCase(); + $(".video-title strong, .actor-box strong").each((function () { + const $strongElement = $(this); + $strongElement.text().toLowerCase().includes(lowerCaseKeyword) && $strongElement.addClass("highlight-red"); + })); + } - hookSearch() { - $("#navbar-menu-hero").after('\n \n '); - $("#search-keyword").on("paste", ((event) => { - const items = event.originalEvent.clipboardData.items; - for (let i = 0; i < items.length; i++) if (-1 !== items[i].type.indexOf("image")) { - const blob = items[i].getAsFile(); - $("#search-keyword").blur(); - const imageRecognitionPlugin = this.getBean("ImageRecognitionPlugin"); - imageRecognitionPlugin.open((() => { - imageRecognitionPlugin.handleImageFile(blob); - imageRecognitionPlugin.resetSearchUI(); - })); - return; - } - setTimeout((() => { - $("#search-btn").click(); - }), 0); - })).on("keypress", ((event) => { - "Enter" === event.key && setTimeout((() => { - $("#search-btn").click(); - }), 0); - })); - $("#search-btn").on("click", ((event) => { - let keyword = $("#search-keyword").val(), - searchCurrentType = $("#search-type option:selected").val(); - "" !== keyword && (window.location.href.includes("/search") ? window.location.href = "/search?q=" + keyword + "&f=" + searchCurrentType : window.open("/search?q=" + keyword + "&f=" + searchCurrentType)); - })); - $("#search-img-btn").on("click", (() => { - this.getBean("ImageRecognitionPlugin").open(); - })); - } - - hookOldSearch() { - const searchImage = document.querySelector(".search-image"); - if (!searchImage) return; - const clonedImage = searchImage.cloneNode(true); - searchImage.parentNode.replaceChild(clonedImage, searchImage); - $("#button-search-image").attr("data-tooltip", "以图识图"); - $(".search-image").on("click", ((event) => { - this.getBean("ImageRecognitionPlugin").open(); - })); - } - - margeNav() { - $('a[href*="/feedbacks/new"]').remove(); - $('a[href*="theporndude.com"]').remove(); - $('a.navbar-link[href="/makers"]').parent().after('\n \n '); - } - - toggleOtherNavItem() { - let $searchBox = $("#search-box"), $oldSearchBox = $("#search-bar-container"); - if ($(window).width() < 1600 && $(window).width() > 1023) { - $searchBox.hide(); - $oldSearchBox.show(); - } - if ($(window).width() > 1600) { - $searchBox.show(); - $oldSearchBox.hide(); - } - } + hookSearch() { + $("#navbar-menu-hero").after('\n \n '); + $("#search-keyword").on("paste", ((event) => { + const items = event.originalEvent.clipboardData.items; + for (let i = 0; i < items.length; i++) if (-1 !== items[i].type.indexOf("image")) { + const blob = items[i].getAsFile(); + $("#search-keyword").blur(); + const imageRecognitionPlugin = this.getBean("ImageRecognitionPlugin"); + imageRecognitionPlugin.open((() => { + imageRecognitionPlugin.handleImageFile(blob); + imageRecognitionPlugin.resetSearchUI(); + })); + return; } + setTimeout((() => { + $("#search-btn").click(); + }), 0); + })).on("keypress", ((event) => { + "Enter" === event.key && setTimeout((() => { + $("#search-btn").click(); + }), 0); + })); + $("#search-btn").on("click", ((event) => { + let keyword = $("#search-keyword").val(), searchCurrentType = $("#search-type option:selected").val(); + "" !== keyword && (window.location.href.includes("/search") ? window.location.href = "/search?q=" + keyword + "&f=" + searchCurrentType : window.open("/search?q=" + keyword + "&f=" + searchCurrentType)); + })); + $("#search-img-btn").on("click", (() => { + this.getBean("ImageRecognitionPlugin").open(); + })); + } - class BusDetailPagePlugin extends BasePlugin { - getName() { - return "BusDetailPagePlugin"; - } + hookOldSearch() { + const searchImage = document.querySelector(".search-image"); + if (!searchImage) return; + const clonedImage = searchImage.cloneNode(true); + searchImage.parentNode.replaceChild(clonedImage, searchImage); + $("#button-search-image").attr("data-tooltip", "以图识图"); + $(".search-image").on("click", ((event) => { + this.getBean("ImageRecognitionPlugin").open(); + })); + } - async initCss() { - if (!window.isDetailPage) return ""; - $("h4:contains('推薦')").hide(); - } + margeNav() { + $('a[href*="/feedbacks/new"]').remove(); + $('a[href*="theporndude.com"]').remove(); + $('a.navbar-link[href="/makers"]').parent().after('\n \n '); + } - async handle() { - if (window.location.href.includes("/star/")) { - const $avatarBox = $(".avatar-box"); - if ($avatarBox.length > 0) { - let parent2 = $avatarBox.parent(); - parent2.css("position", "initial"); - parent2.insertBefore(parent2.parent()); - } - } - $(".genre a").each((function () { - const href2 = $(this).attr("href"); - href2 && (href2.startsWith("http://") || href2.startsWith("https://") || href2.startsWith("/")) && $(this).attr("target", "_blank"); - })); - this.addCopyCarNumBtn(); - } + toggleOtherNavItem() { + let $searchBox = $("#search-box"), $oldSearchBox = $("#search-bar-container"); + if ($(window).width() < 1600 && $(window).width() > 1023) { + $searchBox.hide(); + $oldSearchBox.show(); + } + if ($(window).width() > 1600) { + $searchBox.show(); + $oldSearchBox.hide(); + } + } + } - addCopyCarNumBtn() { - let headerSpan = null; - const headerSpans = document.querySelectorAll("span.header"); - for (const span of headerSpans) if ("識別碼:" === span.textContent.trim()) { - headerSpan = span; - break; - } - if (headerSpan) { - const targetSpan = headerSpan.nextElementSibling; - if (targetSpan && "SPAN" === targetSpan.tagName) { - const identifierText = targetSpan.textContent.trim(), - copyButton = document.createElement("button"); - copyButton.textContent = "复制"; - copyButton.style.marginLeft = "10px"; - copyButton.style.padding = "0 10px"; - copyButton.style.cursor = "pointer"; - copyButton.style.border = "1px solid #ccc"; - copyButton.style.borderRadius = "5px"; - copyButton.style.backgroundColor = "#f0f0f0"; - copyButton.style.fontSize = "12px"; - copyButton.addEventListener("click", (function (event) { - event.preventDefault(); - const copyAction = (text) => { - this.textContent = "已复制"; - setTimeout((() => { - this.textContent = "复制"; - }), 1500); - }; - navigator.clipboard && navigator.clipboard.writeText && navigator.clipboard.writeText(identifierText).then((() => copyAction())).catch(((err) => { - console.error("无法通过标准API复制:", err); - alert("复制失败,请手动复制: " + identifierText); - })); - })); - targetSpan.parentNode.insertBefore(copyButton, targetSpan.nextSibling); - } - } - } + class BusDetailPagePlugin extends BasePlugin { + getName() { + return "BusDetailPagePlugin"; + } + + async initCss() { + if (!window.isDetailPage) return ""; + $("h4:contains('推薦')").hide(); + } + + async handle() { + if (window.location.href.includes("/star/")) { + const $avatarBox = $(".avatar-box"); + if ($avatarBox.length > 0) { + let parent2 = $avatarBox.parent(); + parent2.css("position", "initial"); + parent2.insertBefore(parent2.parent()); } + } + $(".genre a").each((function () { + const href2 = $(this).attr("href"); + href2 && (href2.startsWith("http://") || href2.startsWith("https://") || href2.startsWith("/")) && $(this).attr("target", "_blank"); + })); + this.addCopyCarNumBtn(); + } - class BusPreviewVideoPlugin extends BasePlugin { - getName() { - return "BusPreviewVideoPlugin"; - } + addCopyCarNumBtn() { + let headerSpan = null; + const headerSpans = document.querySelectorAll("span.header"); + for (const span of headerSpans) if ("識別碼:" === span.textContent.trim()) { + headerSpan = span; + break; + } + if (headerSpan) { + const targetSpan = headerSpan.nextElementSibling; + if (targetSpan && "SPAN" === targetSpan.tagName) { + const identifierText = targetSpan.textContent.trim(), copyButton = document.createElement("button"); + copyButton.textContent = "复制"; + copyButton.style.marginLeft = "10px"; + copyButton.style.padding = "0 10px"; + copyButton.style.cursor = "pointer"; + copyButton.style.border = "1px solid #ccc"; + copyButton.style.borderRadius = "5px"; + copyButton.style.backgroundColor = "#f0f0f0"; + copyButton.style.fontSize = "12px"; + copyButton.addEventListener("click", (function (event) { + event.preventDefault(); + const copyAction = (text) => { + this.textContent = "已复制"; + setTimeout((() => { + this.textContent = "复制"; + }), 1500); + }; + navigator.clipboard && navigator.clipboard.writeText && navigator.clipboard.writeText(identifierText).then((() => copyAction())).catch(((err) => { + console.error("无法通过标准API复制:", err); + alert("复制失败,请手动复制: " + identifierText); + })); + })); + targetSpan.parentNode.insertBefore(copyButton, targetSpan.nextSibling); + } + } + } + } - async initCss() { - return "\n /* 弹窗/Modal 样式 */\n .bus-preview-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.95); \n /* 关键修改:更新 z-index */\n z-index: 12345699; \n display: flex;\n justify-content: center;\n align-items: center;\n opacity: 0; \n visibility: hidden; \n transition: opacity 0.2s ease;\n }\n .bus-preview-modal.is-open {\n opacity: 1;\n visibility: visible;\n }\n /* 垂直排列视频和按钮,并居中 */\n .bus-preview-modal-content {\n position: relative;\n max-width: 95%; \n max-height: 95%;\n display: flex; \n flex-direction: column; \n align-items: center; \n gap: 15px; \n }\n \n /* 移除 .bus-preview-close-btn 的样式 */\n\n /* 视频播放器容器 */\n .video-player-wrapper {\n /* 关键修改:更新 width 和 max-height */\n width: 80vw; \n max-height: 85vh; \n aspect-ratio: 16 / 9; \n position: relative; \n background-color: black; \n max-width: 100%; \n }\n /* 视频元素 */\n .video-player-wrapper #preview-video {\n position: absolute; \n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: block;\n }\n\n /* 画质控制盒 (底部按钮) */\n .video-control-box {\n display: flex;\n flex-direction: row; \n justify-content: center; \n flex-wrap: wrap; \n gap: 10px;\n padding: 10px 0; \n }\n\n /* 按钮样式 (保留) */\n .video-control-btn {\n min-width:80px;\n padding: 6px 12px;\n background: rgba(255,255,255,0.2);\n color: white;\n border: 1px solid rgba(255,255,255,0.5);\n border-radius: 4px;\n cursor: pointer;\n text-align: center;\n font-size: 14px;\n transition: background-color 0.2s, border-color 0.2s;\n }\n .video-control-btn:hover {\n background: rgba(255,255,255,0.4);\n }\n .video-control-btn.active {\n background-color: #1890ff; \n color: white;\n font-weight: bold;\n border: 1px solid #096dd9;\n }\n "; - } + class BusPreviewVideoPlugin extends BasePlugin { + getName() { + return "BusPreviewVideoPlugin"; + } - initModal() { - if (0 === $("#bus-preview-modal").length) { - $("body").append('\n
    \n
    \n
    \n
    \n '); - const $modal = $("#bus-preview-modal"); - $modal.on("click", ((e) => { - "bus-preview-modal" === e.target.id && this.closeVideoModal(); - })); - $(document).on("keydown", ((e) => { - "Escape" === e.key && $modal.hasClass("is-open") && this.closeVideoModal(); - })); - } - } + async initCss() { + return "\n /* 弹窗/Modal 样式 */\n .bus-preview-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.95); \n /* 关键修改:更新 z-index */\n z-index: 12345699; \n display: flex;\n justify-content: center;\n align-items: center;\n opacity: 0; \n visibility: hidden; \n transition: opacity 0.2s ease;\n }\n .bus-preview-modal.is-open {\n opacity: 1;\n visibility: visible;\n }\n /* 垂直排列视频和按钮,并居中 */\n .bus-preview-modal-content {\n position: relative;\n max-width: 95%; \n max-height: 95%;\n display: flex; \n flex-direction: column; \n align-items: center; \n gap: 15px; \n }\n \n /* 移除 .bus-preview-close-btn 的样式 */\n\n /* 视频播放器容器 */\n .video-player-wrapper {\n /* 关键修改:更新 width 和 max-height */\n width: 80vw; \n max-height: 85vh; \n aspect-ratio: 16 / 9; \n position: relative; \n background-color: black; \n max-width: 100%; \n }\n /* 视频元素 */\n .video-player-wrapper #preview-video {\n position: absolute; \n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: block;\n }\n\n /* 画质控制盒 (底部按钮) */\n .video-control-box {\n display: flex;\n flex-direction: row; \n justify-content: center; \n flex-wrap: wrap; \n gap: 10px;\n padding: 10px 0; \n }\n\n /* 按钮样式 (保留) */\n .video-control-btn {\n min-width:80px;\n padding: 6px 12px;\n background: rgba(255,255,255,0.2);\n color: white;\n border: 1px solid rgba(255,255,255,0.5);\n border-radius: 4px;\n cursor: pointer;\n text-align: center;\n font-size: 14px;\n transition: background-color 0.2s, border-color 0.2s;\n }\n .video-control-btn:hover {\n background: rgba(255,255,255,0.4);\n }\n .video-control-btn.active {\n background-color: #1890ff; \n color: white;\n font-weight: bold;\n border: 1px solid #096dd9;\n }\n "; + } - closeVideoModal() { - const $previewVideo = $("#preview-video"); - if ($previewVideo.length > 0) { - const videoEl = $previewVideo[0]; - videoEl.pause(); - } - $("#bus-preview-modal").removeClass("is-open"); - } + initModal() { + if (0 === $("#bus-preview-modal").length) { + $("body").append('\n
    \n
    \n
    \n
    \n '); + const $modal = $("#bus-preview-modal"); + $modal.on("click", ((e) => { + "bus-preview-modal" === e.target.id && this.closeVideoModal(); + })); + $(document).on("keydown", ((e) => { + "Escape" === e.key && $modal.hasClass("is-open") && this.closeVideoModal(); + })); + } + } - async handle() { - if (!window.isDetailPage) return; - this.initModal(); - const firstImageSrc = $("#sample-waterfall .sample-box .photo-frame img:first").attr("src"), - videoPreview = $(` + closeVideoModal() { + const $previewVideo = $("#preview-video"); + if ($previewVideo.length > 0) { + const videoEl = $previewVideo[0]; + videoEl.pause(); + } + $("#bus-preview-modal").removeClass("is-open"); + } + + async handle() { + if (!window.isDetailPage) return; + this.initModal(); + const firstImageSrc = $("#sample-waterfall .sample-box .photo-frame img:first").attr("src"), + videoPreview = $(`
    @@ -10360,51 +10289,51 @@ ${err.stack}` : "");
    `); - $("#sample-waterfall").prepend(videoPreview); - "yes" === await storageManager.getSetting("enableLoadPreviewVideo", "yes") && getDmmVideo(this.getPageInfo().carNum, false).then(); - let isHandlingVideo = false, $preview = $(".preview-video-container"); - $preview.on("click", (async (event) => { - event.preventDefault(); - event.stopPropagation(); - if (isHandlingVideo) show.info("正在加载中, 勿重复点击"); - else { - isHandlingVideo = true; - try { - await this.handleVideo(); - } finally { - isHandlingVideo = false; - } - } - })); - window.location.href.includes("autoPlay=1") && $preview.trigger("click"); - } + $("#sample-waterfall").prepend(videoPreview); + "yes" === await storageManager.getSetting("enableLoadPreviewVideo", "yes") && getDmmVideo(this.getPageInfo().carNum, false).then(); + let isHandlingVideo = false, $preview = $(".preview-video-container"); + $preview.on("click", (async (event) => { + event.preventDefault(); + event.stopPropagation(); + if (isHandlingVideo) show.info("正在加载中, 勿重复点击"); + else { + isHandlingVideo = true; + try { + await this.handleVideo(); + } finally { + isHandlingVideo = false; + } + } + })); + window.location.href.includes("autoPlay=1") && $preview.trigger("click"); + } - async handleVideo() { - const $modal = $("#bus-preview-modal"), $modalContent = $modal.find(".bus-preview-modal-content"); - let $previewVideo = $("#preview-video"); - if ($previewVideo.length > 0) { - $modal.addClass("is-open"); - const videoEl = $previewVideo[0]; - videoEl.play().catch(((e) => console.warn("尝试播放失败 (可能被浏览器阻止):", e))); - return; - } - let carNum2 = this.getPageInfo().carNum; - const dmmVideoMap = await getDmmVideo(carNum2); - if (dmmVideoMap && 0 !== Object.keys(dmmVideoMap).length) { - await this.createVideoPlayerAndControls(dmmVideoMap, $modalContent); - $previewVideo = $("#preview-video"); - if ($previewVideo.length > 0) { - $modal.addClass("is-open"); - $previewVideo[0].play().catch(((e) => console.warn("尝试播放失败 (可能被浏览器阻止):", e))); - } else show.error("视频播放器创建失败。"); - } else show.error("未找到可用的视频源。"); - } + async handleVideo() { + const $modal = $("#bus-preview-modal"), $modalContent = $modal.find(".bus-preview-modal-content"); + let $previewVideo = $("#preview-video"); + if ($previewVideo.length > 0) { + $modal.addClass("is-open"); + const videoEl = $previewVideo[0]; + videoEl.play().catch(((e) => console.warn("尝试播放失败 (可能被浏览器阻止):", e))); + return; + } + let carNum2 = this.getPageInfo().carNum; + const dmmVideoMap = await getDmmVideo(carNum2); + if (dmmVideoMap && 0 !== Object.keys(dmmVideoMap).length) { + await this.createVideoPlayerAndControls(dmmVideoMap, $modalContent); + $previewVideo = $("#preview-video"); + if ($previewVideo.length > 0) { + $modal.addClass("is-open"); + $previewVideo[0].play().catch(((e) => console.warn("尝试播放失败 (可能被浏览器阻止):", e))); + } else show.error("视频播放器创建失败。"); + } else show.error("未找到可用的视频源。"); + } - async createVideoPlayerAndControls(dmmVideoMap, $container) { - let defaultVideoQuality = await storageManager.getSetting("videoQuality"); - defaultVideoQuality = selectDefaultQuality(Object.keys(dmmVideoMap), defaultVideoQuality); - let defaultVideoUrl = dmmVideoMap[defaultVideoQuality]; - $container.html(` + async createVideoPlayerAndControls(dmmVideoMap, $container) { + let defaultVideoQuality = await storageManager.getSetting("videoQuality"); + defaultVideoQuality = selectDefaultQuality(Object.keys(dmmVideoMap), defaultVideoQuality); + let defaultVideoUrl = dmmVideoMap[defaultVideoQuality]; + $container.html(`
    `); - if (isJavBus$1) { - if ($box2.find(".avatar-box").length > 0) return; - $box2.find(".photo-info").append(` + if (isJavBus$1) { + if ($box2.find(".avatar-box").length > 0) return; + $box2.find(".photo-info").append(`
    @@ -14606,218 +14518,213 @@ ${err.stack}` : "");
    `); - } - } - })); - this.enableSvgBtn(); - } + } + } + })); + this.enableSvgBtn(); + } - async enableSvgBtn() { - const settingObj = await storageManager.getSetting(), { - enableScreenSvg = YES$1, - enableVideoSvg = YES$1, - enableHandleSvg = YES$1, - enableSiteSvg = YES$1, - enableCopySvg = YES$1 - } = settingObj; - [{ - selector: ".screenSvg", - enabled: enableScreenSvg - }, { - selector: ".videoSvg", - enabled: enableVideoSvg - }, { - selector: ".handleSvg", - enabled: enableHandleSvg - }, { - selector: ".siteSvg", - enabled: enableSiteSvg - }, { - selector: ".copySvg", - enabled: enableCopySvg - }].forEach((({selector, enabled}) => { - $(selector).toggle(enabled === YES$1); - })); - } + async enableSvgBtn() { + const settingObj = await storageManager.getSetting(), { + enableScreenSvg = YES$1, + enableVideoSvg = YES$1, + enableHandleSvg = YES$1, + enableSiteSvg = YES$1, + enableCopySvg = YES$1 + } = settingObj; + [{ + selector: ".screenSvg", + enabled: enableScreenSvg + }, { + selector: ".videoSvg", + enabled: enableVideoSvg + }, { + selector: ".handleSvg", + enabled: enableHandleSvg + }, { + selector: ".siteSvg", + enabled: enableSiteSvg + }, { + selector: ".copySvg", + enabled: enableCopySvg + }].forEach((({selector, enabled}) => { + $(selector).toggle(enabled === YES$1); + })); + } - async bindClick() { - this.getSelector(); - const listPagePlugin = this.getBean("ListPagePlugin"); - $(document).on("click", ".more-tools-container", ((event) => { - event.preventDefault(); - var $currentTools = $(event.target).closest(".more-tools-container").find(".more-tools"); - $(".more-tools").not($currentTools).stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide(); - $currentTools.is(":visible") ? $currentTools.stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide() : $currentTools.stop(true, true).removeClass("elastic-out").addClass("elastic-in").show(); - })); - $(document).on("click", (function (event) { - $(event.target).closest(".more-tools-container").length || $(".more-tools").stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide(); - })); - $(document).on("click", ".videoSvg", ((event) => { - event.preventDefault(); - $('.videoSvg[title!="播放视频"]').each(((index, element) => { - const $otherSvgElement = $(element); - let $otherBox = $otherSvgElement.closest(".item"), - $otherImg = $otherBox.find("img"), {carNum: carNum2} = this.getBoxCarInfo($otherBox); - this.showImg($otherSvgElement, $otherImg, carNum2); - $otherSvgElement.html(this.videoSvg).attr("title", "播放视频"); - })); - const $currentBox = $(event.target).closest(".item"), - $svgElement = $currentBox.find(".videoSvg"); - if ("播放视频" === $svgElement.attr("title")) { - $svgElement.html(this.recoveryVideoSvg).attr("title", "切回封面"); - const {carNum: carNum2} = this.getBoxCarInfo($currentBox); - let $img = $currentBox.find("img"); - if (!$img.length) { - show.error("没有找到图片"); - return; - } - this.showVideo($svgElement, $img, carNum2).then(); - } - })); - $(document).on("click", ".screenSvg", (async (event) => { - event.preventDefault(); - let loadObj = loading(); - try { - const $box2 = $(event.currentTarget).closest(".item"); - let {carNum: carNum2} = this.getBoxCarInfo($box2); - carNum2 = carNum2.replace("FC2-", ""); - const imgUrl = await this.getBean("ScreenShotPlugin").getScreenshot(carNum2); - loadObj.close(); - showPreviewOverlay(imgUrl, carNum2); - } catch (error) { - console.error("图片预览出错:", error); - show.error("图片预览出错:" + error); - } finally { - loadObj.close(); - } - })); - $(document).on("click", ".filterBtn, .favoriteBtn, .hasDownBtn, .hasWatchBtn", ((event) => { - event.preventDefault(); - event.stopPropagation(); - const $btn = $(event.target).closest(".menu-btn"), $box2 = $btn.closest(".item"), { - carNum: carNum2, - url, - publishTime - } = this.getBoxCarInfo($box2), handleAction = async (status) => { - let actress = await listPagePlugin.parseActressName(url); - await storageManager.saveCar({ - carNum: carNum2, - url, - names: actress, - actionType: status, - publishTime - }); - window.refresh(); - show.ok("操作成功"); - }; - $btn.hasClass("filterBtn") ? utils.q(event, `是否屏蔽${carNum2}?`, (() => handleAction(Status_FILTER$1))) : $btn.hasClass("favoriteBtn") ? handleAction(Status_FAVORITE$1).then() : $btn.hasClass("hasDownBtn") ? handleAction(Status_HAS_DOWN$1).then() : $btn.hasClass("hasWatchBtn") && handleAction(Status_HAS_WATCH$1).then(); - $(".more-tools").stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide(); - })); - const otherSitePlugin = this.getBean("OtherSitePlugin"), - missAvUrl = await otherSitePlugin.getMissAvUrl(), - jableUrl = await otherSitePlugin.getjableUrl(), av123Url = await otherSitePlugin.getAv123Url(); - $(document).on("click", ".site-jable, .site-miss-av, .site-123-av", ((event) => { - event.preventDefault(); - event.stopPropagation(); - const $currentTarget = $(event.currentTarget), - $box2 = $currentTarget.closest(".item"), {carNum: carNum2} = this.getBoxCarInfo($box2); - let url = null; + async bindClick() { + this.getSelector(); + const listPagePlugin = this.getBean("ListPagePlugin"); + $(document).on("click", ".more-tools-container", ((event) => { + event.preventDefault(); + var $currentTools = $(event.target).closest(".more-tools-container").find(".more-tools"); + $(".more-tools").not($currentTools).stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide(); + $currentTools.is(":visible") ? $currentTools.stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide() : $currentTools.stop(true, true).removeClass("elastic-out").addClass("elastic-in").show(); + })); + $(document).on("click", (function (event) { + $(event.target).closest(".more-tools-container").length || $(".more-tools").stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide(); + })); + $(document).on("click", ".videoSvg", ((event) => { + event.preventDefault(); + $('.videoSvg[title!="播放视频"]').each(((index, element) => { + const $otherSvgElement = $(element); + let $otherBox = $otherSvgElement.closest(".item"), + $otherImg = $otherBox.find("img"), {carNum: carNum2} = this.getBoxCarInfo($otherBox); + this.showImg($otherSvgElement, $otherImg, carNum2); + $otherSvgElement.html(this.videoSvg).attr("title", "播放视频"); + })); + const $currentBox = $(event.target).closest(".item"), $svgElement = $currentBox.find(".videoSvg"); + if ("播放视频" === $svgElement.attr("title")) { + $svgElement.html(this.recoveryVideoSvg).attr("title", "切回封面"); + const {carNum: carNum2} = this.getBoxCarInfo($currentBox); + let $img = $currentBox.find("img"); + if (!$img.length) { + show.error("没有找到图片"); + return; + } + this.showVideo($svgElement, $img, carNum2).then(); + } + })); + $(document).on("click", ".screenSvg", (async (event) => { + event.preventDefault(); + let loadObj = loading(); + try { + const $box2 = $(event.currentTarget).closest(".item"); + let {carNum: carNum2} = this.getBoxCarInfo($box2); + carNum2 = carNum2.replace("FC2-", ""); + const imgUrl = await this.getBean("ScreenShotPlugin").getScreenshot(carNum2); + loadObj.close(); + showPreviewOverlay(imgUrl, carNum2); + } catch (error) { + console.error("图片预览出错:", error); + show.error("图片预览出错:" + error); + } finally { + loadObj.close(); + } + })); + $(document).on("click", ".filterBtn, .favoriteBtn, .hasDownBtn, .hasWatchBtn", ((event) => { + event.preventDefault(); + event.stopPropagation(); + const $btn = $(event.target).closest(".menu-btn"), $box2 = $btn.closest(".item"), { + carNum: carNum2, + url, + publishTime + } = this.getBoxCarInfo($box2), handleAction = async (status) => { + let actress = await listPagePlugin.parseActressName(url); + await storageManager.saveCar({ + carNum: carNum2, + url, + names: actress, + actionType: status, + publishTime + }); + window.refresh(); + show.ok("操作成功"); + }; + $btn.hasClass("filterBtn") ? utils.q(event, `是否屏蔽${carNum2}?`, (() => handleAction(Status_FILTER$1))) : $btn.hasClass("favoriteBtn") ? handleAction(Status_FAVORITE$1).then() : $btn.hasClass("hasDownBtn") ? handleAction(Status_HAS_DOWN$1).then() : $btn.hasClass("hasWatchBtn") && handleAction(Status_HAS_WATCH$1).then(); + $(".more-tools").stop(true, true).removeClass("elastic-in").addClass("elastic-out").hide(); + })); + const otherSitePlugin = this.getBean("OtherSitePlugin"), missAvUrl = await otherSitePlugin.getMissAvUrl(), + jableUrl = await otherSitePlugin.getjableUrl(), av123Url = await otherSitePlugin.getAv123Url(); + $(document).on("click", ".site-jable, .site-miss-av, .site-123-av", ((event) => { + event.preventDefault(); + event.stopPropagation(); + const $currentTarget = $(event.currentTarget), + $box2 = $currentTarget.closest(".item"), {carNum: carNum2} = this.getBoxCarInfo($box2); + let url = null; $currentTarget.hasClass("site-jable") ? url = `${jableUrl}/search/${carNum2}/` : $currentTarget.hasClass("site-miss-av") ? url = `${missAvUrl}/search/${carNum2}` : $currentTarget.hasClass("site-123-av") && (url = `${av123Url}/ja/search?keyword=${carNum2}`); - event && (event.ctrlKey || event.metaKey) ? _GM_openInTab(url, { - insert: 0 - }) : window.open(url); - })); - $(document).on("click", ".titleSvg, .carNumSvg, .downSvg", ((event) => { - event.preventDefault(); - event.stopPropagation(); - const $box2 = $(event.currentTarget).closest(".item"), { - carNum: carNum2, - title - } = this.getBoxCarInfo($box2), - $img = $box2.find(isJavBus$1 ? ".photo-frame img" : ".cover img"); - $(event.currentTarget).hasClass("titleSvg") ? utils.copyToClipboard("标题", title) : $(event.currentTarget).hasClass("carNumSvg") ? utils.copyToClipboard("番号", carNum2) : $(event.currentTarget).hasClass("downSvg") && fetch($img.attr("src")).then(((response) => response.blob())).then(((blob) => { - utils.download(blob, carNum2 + " " + title + ".jpg"); - })); - })); - $(document).on("click", ".markDeleteSvg", (async (event) => { - event.preventDefault(); - event.stopPropagation(); - const $btn = $(event.currentTarget); - const $box2 = $btn.closest(".item"); - const {carNum: carNum2, title, publishTime, url} = this.getBoxCarInfo($box2); - const score = $box2.find(".score").text().trim() || "无评分"; - let markedList = await storageManager.forage.getItem("markedDeleteList") || []; - const existingIndex = markedList.findIndex((item) => item.carNum === carNum2); - if (existingIndex > -1) { - markedList.splice(existingIndex, 1); - $btn.removeClass("marked"); - $btn.attr("title", "标记删除"); - show.ok(`已取消标记: ${title}`); - } else { - markedList.push({ - carNum: carNum2, - title, - publishTime, - score, - url, - markedTime: (/* @__PURE__ */ new Date()).toISOString() - }); - $btn.addClass("marked"); - $btn.attr("title", "取消标记删除"); - show.ok(`已标记删除: ${title}`); - } - await storageManager.forage.setItem("markedDeleteList", markedList); - })); - $(document).on("click", ".delete115Svg", (async (event) => { - event.preventDefault(); - event.stopPropagation(); - const $btn = $(event.currentTarget); - const matchData = $btn.attr("data-match"); - if (!matchData) { - show.error("未找到115匹配数据"); - return; - } - const matchList = JSON.parse(matchData); - const $box2 = $btn.closest(".item"); - const {carNum: carNum2} = this.getBoxCarInfo($box2); - this.getBean("WangPan115MatchPlugin").showDeleteDialog(carNum2, matchList, (async (newMatchList) => { - this.getBean("WangPan115MatchPlugin").updateMatchStatus($box2, carNum2, newMatchList); - })); - })); - } + event && (event.ctrlKey || event.metaKey) ? _GM_openInTab(url, { + insert: 0 + }) : window.open(url); + })); + $(document).on("click", ".titleSvg, .carNumSvg, .downSvg", ((event) => { + event.preventDefault(); + event.stopPropagation(); + const $box2 = $(event.currentTarget).closest(".item"), {carNum: carNum2, title} = this.getBoxCarInfo($box2), + $img = $box2.find(isJavBus$1 ? ".photo-frame img" : ".cover img"); + $(event.currentTarget).hasClass("titleSvg") ? utils.copyToClipboard("标题", title) : $(event.currentTarget).hasClass("carNumSvg") ? utils.copyToClipboard("番号", carNum2) : $(event.currentTarget).hasClass("downSvg") && fetch($img.attr("src")).then(((response) => response.blob())).then(((blob) => { + utils.download(blob, carNum2 + " " + title + ".jpg"); + })); + })); + $(document).on("click", ".markDeleteSvg", (async (event) => { + event.preventDefault(); + event.stopPropagation(); + const $btn = $(event.currentTarget); + const $box2 = $btn.closest(".item"); + const {carNum: carNum2, title, publishTime, url} = this.getBoxCarInfo($box2); + const score = $box2.find(".score").text().trim() || "无评分"; + let markedList = await storageManager.forage.getItem("markedDeleteList") || []; + const existingIndex = markedList.findIndex((item) => item.carNum === carNum2); + if (existingIndex > -1) { + markedList.splice(existingIndex, 1); + $btn.removeClass("marked"); + $btn.attr("title", "标记删除"); + show.ok(`已取消标记: ${title}`); + } else { + markedList.push({ + carNum: carNum2, + title, + publishTime, + score, + url, + markedTime: (/* @__PURE__ */ new Date()).toISOString() + }); + $btn.addClass("marked"); + $btn.attr("title", "取消标记删除"); + show.ok(`已标记删除: ${title}`); + } + await storageManager.forage.setItem("markedDeleteList", markedList); + })); + $(document).on("click", ".delete115Svg", (async (event) => { + event.preventDefault(); + event.stopPropagation(); + const $btn = $(event.currentTarget); + const matchData = $btn.attr("data-match"); + if (!matchData) { + show.error("未找到115匹配数据"); + return; + } + const matchList = JSON.parse(matchData); + const $box2 = $btn.closest(".item"); + const {carNum: carNum2} = this.getBoxCarInfo($box2); + this.getBean("WangPan115MatchPlugin").showDeleteDialog(carNum2, matchList, (async (newMatchList) => { + this.getBean("WangPan115MatchPlugin").updateMatchStatus($box2, carNum2, newMatchList); + })); + })); + } - showImg($svgElement, $img, carNum2) { - $svgElement.html(this.videoSvg).attr("title", "播放视频"); - let $video = $(`#${`${carNum2}_preview_video`}`); - if ($video.length > 0) { - $video[0].pause(); - $video.parent().hide(); - } - $img.show(); - $img.removeClass("loading"); - $img.next(".loading-spinner").remove(); - } + showImg($svgElement, $img, carNum2) { + $svgElement.html(this.videoSvg).attr("title", "播放视频"); + let $video = $(`#${`${carNum2}_preview_video`}`); + if ($video.length > 0) { + $video[0].pause(); + $video.parent().hide(); + } + $img.show(); + $img.removeClass("loading"); + $img.next(".loading-spinner").remove(); + } - async showVideo($svgElement, $img, carNum2) { - const id = `${carNum2}_preview_video`; - let $video = $(`#${id}`); - if ($video.length > 0) { - $video.parent().show(); - $video[0].play(); - $img.hide(); - return; - } - $img.addClass("loading"); - $img.after('
    '); - const poster = $img.attr("src"), dmmVideoMap = await getDmmVideo(carNum2); - if (!dmmVideoMap) { - show.error("未解析到视频"); - this.showImg($svgElement, $img, carNum2); - return; - } - let defaultVideoQuality = await storageManager.getSetting("videoQuality"); - defaultVideoQuality = selectDefaultQuality(Object.keys(dmmVideoMap), defaultVideoQuality); - let videoUrl = dmmVideoMap[defaultVideoQuality], videoHtml = ` + async showVideo($svgElement, $img, carNum2) { + const id = `${carNum2}_preview_video`; + let $video = $(`#${id}`); + if ($video.length > 0) { + $video.parent().show(); + $video[0].play(); + $img.hide(); + return; + } + $img.addClass("loading"); + $img.after('
    '); + const poster = $img.attr("src"), dmmVideoMap = await getDmmVideo(carNum2); + if (!dmmVideoMap) { + show.error("未解析到视频"); + this.showImg($svgElement, $img, carNum2); + return; + } + let defaultVideoQuality = await storageManager.getSetting("videoQuality"); + defaultVideoQuality = selectDefaultQuality(Object.keys(dmmVideoMap), defaultVideoQuality); + let videoUrl = dmmVideoMap[defaultVideoQuality], videoHtml = `
    `; - isJavBus$1 && (videoHtml = ` + isJavBus$1 && (videoHtml = `
    `); - $img.parent().append(videoHtml); - $img.hide(); - $img.removeClass("loading"); - $img.next(".loading-spinner").remove(); - $video = $(`#${id}`); - let videoElement = $video[0]; - videoElement.load(); - videoElement.muted = false; - videoElement.play(); - $video.trigger("focus"); - } + $img.parent().append(videoHtml); + $img.hide(); + $img.removeClass("loading"); + $img.next(".loading-spinner").remove(); + $video = $(`#${id}`); + let videoElement = $video[0]; + videoElement.load(); + videoElement.muted = false; + videoElement.play(); + $video.trigger("focus"); + } + } + + class Fc2By123AvPlugin extends BasePlugin { + constructor() { + super(...arguments); + __publicField2(this, "$contentBox", $(".section .container")); + __publicField2(this, "urlParams", new URLSearchParams(window.location.search)); + __publicField2(this, "sortVal", this.urlParams.get("sort") || "release_date"); + __publicField2(this, "currentPage", this.urlParams.get("page") ? parseInt(this.urlParams.get("page")) : 1); + __publicField2(this, "maxPage", null); + __publicField2(this, "keyword", this.urlParams.get("keyword") || null); + } + + getName() { + return "Fc2By123AvPlugin"; + } + + async getBaseUrl() { + const otherSitePlugin = this.getBean("OtherSitePlugin"); + return await otherSitePlugin.getAv123Url() + "/ja"; + } + + handle() { + $("#navbar-menu-hero > div > div:nth-child(1) > div > a:nth-child(4)").after('123Av-Fc2'); + $('.tabs li:contains("FC2")').after('
  • 123Av-Fc2
  • '); + if (currentHref$1.includes("/advanced_search?type=100")) { + this.hookPage(); + this.handleQuery().then(); + } + } + + hookPage() { + let $h2 = $("h2.section-title"); + $h2.contents().first().replaceWith("123Av"); + $h2.css("marginBottom", "0"); + $h2.append('\n
    \n \n 搜索\n 重置\n
    \n '); + $("#search-123av-keyword").val(this.keyword); + $("#search-123av-btn").on("click", (async () => { + let keyword = $("#search-123av-keyword").val().trim(); + if (keyword) { + this.keyword = keyword; + utils.setHrefParam("keyword", keyword); + await this.handleQuery(); } + })); + $("#clear-123av-btn").on("click", (async () => { + $("#search-123av-keyword").val(""); + this.keyword = ""; + utils.setHrefParam("keyword", ""); + $(".page-box").show(); + $(".tool-box").show(); + await this.handleQuery(); + })); + $(".empty-message").remove(); + $("#foldCategoryBtn").remove(); + $(".section .container .box").remove(); + $("#sort-toggle-btn").remove(); + this.$contentBox.append('
    '); + this.$contentBox.append('
    '); + this.$contentBox.append('
    '); + $(".tool-box").append('\n \n '); + $(`#conditionBox a[data-sort="${this.sortVal}"]`).addClass("is-info"); + utils.setHrefParam("sort", this.sortVal); + utils.setHrefParam("page", this.currentPage); + $("#conditionBox").on("click", "a.button", ((e) => { + let $target = $(e.target); + this.sortVal = $target.data("sort"); + utils.setHrefParam("sort", this.sortVal); + $target.siblings().removeClass("is-info"); + $target.addClass("is-info"); + this.handleQuery(); + })); + $(".page-box").append('\n \n '); + $(document).on("click", ".pagination-link", ((e) => { + e.preventDefault(); + this.currentPage = parseInt($(e.target).data("page")); + utils.setHrefParam("page", this.currentPage); + this.renderPagination(); + this.handleQuery(); + })); + $(".pagination-previous").on("click", ((e) => { + e.preventDefault(); + if (this.currentPage > 1) { + this.currentPage--; + utils.setHrefParam("page", this.currentPage); + this.renderPagination(); + this.handleQuery(); + } + })); + $(".pagination-next").on("click", ((e) => { + e.preventDefault(); + if (this.currentPage < this.maxPage) { + this.currentPage++; + utils.setHrefParam("page", this.currentPage); + this.renderPagination(); + this.handleQuery(); + } + })); + } - class Fc2By123AvPlugin extends BasePlugin { - constructor() { - super(...arguments); - __publicField2(this, "$contentBox", $(".section .container")); - __publicField2(this, "urlParams", new URLSearchParams(window.location.search)); - __publicField2(this, "sortVal", this.urlParams.get("sort") || "release_date"); - __publicField2(this, "currentPage", this.urlParams.get("page") ? parseInt(this.urlParams.get("page")) : 1); - __publicField2(this, "maxPage", null); - __publicField2(this, "keyword", this.urlParams.get("keyword") || null); - } + renderPagination() { + const $paginationList = $(".pagination-list"); + $paginationList.empty(); + let startPage = Math.max(1, this.currentPage - 2), endPage = Math.min(this.maxPage, this.currentPage + 2); + this.currentPage <= 3 ? endPage = Math.min(6, this.maxPage) : this.currentPage >= this.maxPage - 2 && (startPage = Math.max(this.maxPage - 5, 1)); + if (startPage > 1) { + $paginationList.append('
  • 1
  • '); + startPage > 2 && $paginationList.append('
  • …
  • '); + } + for (let i = startPage; i <= endPage; i++) { + const activeClass = i === this.currentPage ? " is-current" : ""; + $paginationList.append(`
  • ${i}
  • `); + } + if (endPage < this.maxPage) { + endPage < this.maxPage - 1 && $paginationList.append('
  • …
  • '); + $paginationList.append(`
  • ${this.maxPage}
  • `); + } + } - getName() { - return "Fc2By123AvPlugin"; - } + async handleQuery() { + let loadObj = loading(); + try { + let pagesToFetch = []; + pagesToFetch = 1 === this.currentPage ? [1, 2] : [2 * this.currentPage - 1, 2 * this.currentPage]; + if (this.keyword) { + pagesToFetch = [1]; + $(".page-box").hide(); + $(".tool-box").hide(); + } + const baseUrl = await this.getBaseUrl(), fetchPromises = pagesToFetch.map(((page) => { + let url = `${baseUrl}/tags/fc2?sort=${this.sortVal}&page=${page}`; + this.keyword && (url = `${baseUrl}/search?keyword=${this.keyword}`); + return gmHttp.get(url); + })), htmlResults = await Promise.all(fetchPromises); + let dataList = []; + for (const html of htmlResults) { + let $dom = $(html); + $dom.find(".box-item").each(((index, element) => { + const $item = $(element), imgSrc = $item.find("img").attr("data-src"); + let carNum2 = $item.find("img").attr("title"); + const detailLink = $item.find(".detail a"), link = detailLink.attr("href"), + href = baseUrl + (link.startsWith("/") ? link : "/" + link), + title = detailLink.text().trim().replace(carNum2 + " - ", ""); + carNum2 = carNum2.replace("FC2-PPV", "FC2"); + dataList.push({ + imgSrc, + carNum: carNum2, + href, + title + }); + })); + if (!this.maxPage) { + let rawMaxPage, lastPageItem = $dom.find(".page-item:not(.disabled)").last(); + if (lastPageItem.find("a.page-link").length) { + let href = lastPageItem.find("a.page-link").attr("href"); + rawMaxPage = parseInt(href.split("page=")[1]); + } else rawMaxPage = parseInt(lastPageItem.find("span.page-link").text()); + this.maxPage = Math.ceil(rawMaxPage / 2); + this.renderPagination(); + } + } + if (0 === dataList.length) { + console.log(dataList); + show.error("无结果"); + let errorUrl = `${baseUrl}/dm4/tags/fc2?sort=${this.sortVal}`; + this.keyword && (errorUrl = `${baseUrl}/search?keyword=${this.keyword}`); + console.error("获取数据失败!", errorUrl); + } + let movieHtml = this.markDataListHtml(dataList); + $(".movie-list").html(movieHtml); + await utils.smoothScrollToTop(); + } catch (e) { + console.error(e); + } finally { + loadObj.close(); + } + } - async getBaseUrl() { - const otherSitePlugin = this.getBean("OtherSitePlugin"); - return await otherSitePlugin.getAv123Url() + "/ja"; - } - - handle() { - $("#navbar-menu-hero > div > div:nth-child(1) > div > a:nth-child(4)").after('123Av-Fc2'); - $('.tabs li:contains("FC2")').after('
  • 123Av-Fc2
  • '); - if (currentHref$1.includes("/advanced_search?type=100")) { - this.hookPage(); - this.handleQuery().then(); - } - } - - hookPage() { - let $h2 = $("h2.section-title"); - $h2.contents().first().replaceWith("123Av"); - $h2.css("marginBottom", "0"); - $h2.append('\n
    \n \n 搜索\n 重置\n
    \n '); - $("#search-123av-keyword").val(this.keyword); - $("#search-123av-btn").on("click", (async () => { - let keyword = $("#search-123av-keyword").val().trim(); - if (keyword) { - this.keyword = keyword; - utils.setHrefParam("keyword", keyword); - await this.handleQuery(); - } - })); - $("#clear-123av-btn").on("click", (async () => { - $("#search-123av-keyword").val(""); - this.keyword = ""; - utils.setHrefParam("keyword", ""); - $(".page-box").show(); - $(".tool-box").show(); - await this.handleQuery(); - })); - $(".empty-message").remove(); - $("#foldCategoryBtn").remove(); - $(".section .container .box").remove(); - $("#sort-toggle-btn").remove(); - this.$contentBox.append('
    '); - this.$contentBox.append('
    '); - this.$contentBox.append('
    '); - $(".tool-box").append('\n \n '); - $(`#conditionBox a[data-sort="${this.sortVal}"]`).addClass("is-info"); - utils.setHrefParam("sort", this.sortVal); - utils.setHrefParam("page", this.currentPage); - $("#conditionBox").on("click", "a.button", ((e) => { - let $target = $(e.target); - this.sortVal = $target.data("sort"); - utils.setHrefParam("sort", this.sortVal); - $target.siblings().removeClass("is-info"); - $target.addClass("is-info"); - this.handleQuery(); - })); - $(".page-box").append('\n \n '); - $(document).on("click", ".pagination-link", ((e) => { - e.preventDefault(); - this.currentPage = parseInt($(e.target).data("page")); - utils.setHrefParam("page", this.currentPage); - this.renderPagination(); - this.handleQuery(); - })); - $(".pagination-previous").on("click", ((e) => { - e.preventDefault(); - if (this.currentPage > 1) { - this.currentPage--; - utils.setHrefParam("page", this.currentPage); - this.renderPagination(); - this.handleQuery(); - } - })); - $(".pagination-next").on("click", ((e) => { - e.preventDefault(); - if (this.currentPage < this.maxPage) { - this.currentPage++; - utils.setHrefParam("page", this.currentPage); - this.renderPagination(); - this.handleQuery(); - } - })); - } - - renderPagination() { - const $paginationList = $(".pagination-list"); - $paginationList.empty(); - let startPage = Math.max(1, this.currentPage - 2), - endPage = Math.min(this.maxPage, this.currentPage + 2); - this.currentPage <= 3 ? endPage = Math.min(6, this.maxPage) : this.currentPage >= this.maxPage - 2 && (startPage = Math.max(this.maxPage - 5, 1)); - if (startPage > 1) { - $paginationList.append('
  • 1
  • '); - startPage > 2 && $paginationList.append('
  • …
  • '); - } - for (let i = startPage; i <= endPage; i++) { - const activeClass = i === this.currentPage ? " is-current" : ""; - $paginationList.append(`
  • ${i}
  • `); - } - if (endPage < this.maxPage) { - endPage < this.maxPage - 1 && $paginationList.append('
  • …
  • '); - $paginationList.append(`
  • ${this.maxPage}
  • `); - } - } - - async handleQuery() { - let loadObj = loading(); - try { - let pagesToFetch = []; - pagesToFetch = 1 === this.currentPage ? [1, 2] : [2 * this.currentPage - 1, 2 * this.currentPage]; - if (this.keyword) { - pagesToFetch = [1]; - $(".page-box").hide(); - $(".tool-box").hide(); - } - const baseUrl = await this.getBaseUrl(), fetchPromises = pagesToFetch.map(((page) => { - let url = `${baseUrl}/tags/fc2?sort=${this.sortVal}&page=${page}`; - this.keyword && (url = `${baseUrl}/search?keyword=${this.keyword}`); - return gmHttp.get(url); - })), htmlResults = await Promise.all(fetchPromises); - let dataList = []; - for (const html of htmlResults) { - let $dom = $(html); - $dom.find(".box-item").each(((index, element) => { - const $item = $(element), imgSrc = $item.find("img").attr("data-src"); - let carNum2 = $item.find("img").attr("title"); - const detailLink = $item.find(".detail a"), link = detailLink.attr("href"), - href = baseUrl + (link.startsWith("/") ? link : "/" + link), - title = detailLink.text().trim().replace(carNum2 + " - ", ""); - carNum2 = carNum2.replace("FC2-PPV", "FC2"); - dataList.push({ - imgSrc, - carNum: carNum2, - href, - title - }); - })); - if (!this.maxPage) { - let rawMaxPage, lastPageItem = $dom.find(".page-item:not(.disabled)").last(); - if (lastPageItem.find("a.page-link").length) { - let href = lastPageItem.find("a.page-link").attr("href"); - rawMaxPage = parseInt(href.split("page=")[1]); - } else rawMaxPage = parseInt(lastPageItem.find("span.page-link").text()); - this.maxPage = Math.ceil(rawMaxPage / 2); - this.renderPagination(); - } - } - if (0 === dataList.length) { - console.log(dataList); - show.error("无结果"); - let errorUrl = `${baseUrl}/dm4/tags/fc2?sort=${this.sortVal}`; - this.keyword && (errorUrl = `${baseUrl}/search?keyword=${this.keyword}`); - console.error("获取数据失败!", errorUrl); - } - let movieHtml = this.markDataListHtml(dataList); - $(".movie-list").html(movieHtml); - await utils.smoothScrollToTop(); - } catch (e) { - console.error(e); - } finally { - loadObj.close(); - } - } - - async open123AvFc2Dialog(carNum2, href) { - let otherHtml = ""; - await storageManager.getSetting("enableLoadOtherSite", YES$1) === YES$1 && (otherHtml = '
    第三方站点:
    '); - let pageHtml = ` + async open123AvFc2Dialog(carNum2, href) { + let otherHtml = ""; + await storageManager.getSetting("enableLoadOtherSite", YES$1) === YES$1 && (otherHtml = '
    第三方站点:
    '); + let pageHtml = `
    `; - layer.open({ - type: 1, - title: carNum2, - content: pageHtml, - area: utils.getDefaultArea(), - skin: "movie-detail-layer", - scrollbar: false, - success: (layero, index) => { - utils.setupEscClose(index); - this.loadData(carNum2, href); - let keyword = carNum2.replace("FC2-", ""); - $("#magnets-content").append(this.getBean("MagnetHubPlugin").createMagnetHub(keyword)); - $("#favoriteBtn").on("click", (async (event) => { - const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_FAVORITE$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - })); - $("#filterBtn").on("click", ((event) => { - utils.q(event, `是否屏蔽${carNum2}?`, (async () => { - const actress = $("#data-actress").text(), - publishTime = $("#data-publishTime").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_FILTER$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - window.location.href.includes("collection_codes?movieId") && utils.closePage(); - })); - })); - $("#hasDownBtn").on("click", (async (event) => { - const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_HAS_DOWN$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - })); - $("#hasWatchBtn").on("click", (async (event) => { - const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text(); - await storageManager.saveCar({ - carNum: carNum2, - url: href, - names: actress, - actionType: Status_HAS_WATCH$1, - publishTime - }); - window.refresh(); - layer.closeAll(); - })); - $("#subtitleSearchBtn").on("click", (() => { - window.JavPackSubtitle.openSearchModal({details: {code: carNum2}}); - })); - window.JavPackSubtitle.preload115Matches(carNum2); - let tempCarNum = carNum2.replace("FC2-", ""); - this.getBean("OtherSitePlugin").loadOtherSite(tempCarNum, carNum2).then(); - } - }); - } + layer.open({ + type: 1, + title: carNum2, + content: pageHtml, + area: utils.getDefaultArea(), + skin: "movie-detail-layer", + scrollbar: false, + success: (layero, index) => { + utils.setupEscClose(index); + this.loadData(carNum2, href); + let keyword = carNum2.replace("FC2-", ""); + $("#magnets-content").append(this.getBean("MagnetHubPlugin").createMagnetHub(keyword)); + $("#favoriteBtn").on("click", (async (event) => { + const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_FAVORITE$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + })); + $("#filterBtn").on("click", ((event) => { + utils.q(event, `是否屏蔽${carNum2}?`, (async () => { + const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_FILTER$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + window.location.href.includes("collection_codes?movieId") && utils.closePage(); + })); + })); + $("#hasDownBtn").on("click", (async (event) => { + const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_HAS_DOWN$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + })); + $("#hasWatchBtn").on("click", (async (event) => { + const actress = $("#data-actress").text(), publishTime = $("#data-publishTime").text(); + await storageManager.saveCar({ + carNum: carNum2, + url: href, + names: actress, + actionType: Status_HAS_WATCH$1, + publishTime + }); + window.refresh(); + layer.closeAll(); + })); + $("#subtitleSearchBtn").on("click", (() => { + window.JavPackSubtitle.openSearchModal({details: {code: carNum2}}); + })); + window.JavPackSubtitle.preload115Matches(carNum2); + let tempCarNum = carNum2.replace("FC2-", ""); + this.getBean("OtherSitePlugin").loadOtherSite(tempCarNum, carNum2).then(); + } + }); + } - async loadData(carNum2, href) { - let loadObj = loading(); - try { - const {id, publishDate, title, moviePoster} = await this.get123AvVideoInfo(href); - $(".movie-info-container").html(` + async loadData(carNum2, href) { + let loadObj = loading(); + try { + const {id, publishDate, title, moviePoster} = await this.get123AvVideoInfo(href); + $(".movie-info-container").html(`

    ${title || "无标题"}

    番号: ${carNum2 || "未知"} @@ -15183,117 +15088,116 @@ ${err.stack}` : ""); `); - this.getImgList(carNum2).then(); - this.getActressInfo(carNum2).then(); - this.getBean("TranslatePlugin").translate(carNum2, false).then(); - } catch (e) { - console.error(e); - } finally { - loadObj.close(); - } - } + this.getImgList(carNum2).then(); + this.getActressInfo(carNum2).then(); + this.getBean("TranslatePlugin").translate(carNum2, false).then(); + } catch (e) { + console.error(e); + } finally { + loadObj.close(); + } + } - handleLongImg(carNum2) { - utils.loopDetector((() => $(".movie-gallery .image-list").length > 0), (async () => { - $(".movie-gallery .image-list").prepend('
    正在加载缩略图
    '); - const imgUrl = await this.getBean("ScreenShotPlugin").getScreenshot(carNum2); - if (imgUrl) { - $(".screen-container").html(``); - $(".screen-container").on("click", ((event) => { - event.stopPropagation(); - event.preventDefault(); - showPreviewOverlay(imgUrl, carNum2); - })); - } - })); - } + handleLongImg(carNum2) { + utils.loopDetector((() => $(".movie-gallery .image-list").length > 0), (async () => { + $(".movie-gallery .image-list").prepend('
    正在加载缩略图
    '); + const imgUrl = await this.getBean("ScreenShotPlugin").getScreenshot(carNum2); + if (imgUrl) { + $(".screen-container").html(``); + $(".screen-container").on("click", ((event) => { + event.stopPropagation(); + event.preventDefault(); + showPreviewOverlay(imgUrl, carNum2); + })); + } + })); + } - async get123AvVideoInfo(href) { - const html = await gmHttp.get(href), match = html.match(/v-scope="Movie\({id:\s*(\d+),/), - id = match ? match[1] : null, $dom = utils.htmlTo$dom(html); - return { - id, - publishDate: $dom.find('span:contains("リリース日:")').next("span").text(), - title: $dom.find("h1").text().trim(), - moviePoster: $dom.find("#player").attr("data-poster") - }; - } + async get123AvVideoInfo(href) { + const html = await gmHttp.get(href), match = html.match(/v-scope="Movie\({id:\s*(\d+),/), + id = match ? match[1] : null, $dom = utils.htmlTo$dom(html); + return { + id, + publishDate: $dom.find('span:contains("リリース日:")').next("span").text(), + title: $dom.find("h1").text().trim(), + moviePoster: $dom.find("#player").attr("data-poster") + }; + } - async getActressInfo(fc2Num) { - let url = `https://fc2ppvdb.com/articles/${fc2Num.replace("FC2-", "")}`; - const html = await gmHttp.get(url), $dom = $(html), - actressNodeList = $dom.find("div").filter((function () { - return 0 === $(this).text().trim().indexOf("女優:"); - })); - if (0 === actressNodeList.length || actressNodeList.length > 1) { - show.error("解析女优信息失败"); - return; - } - const $actress = $(actressNodeList[0]).find("a"); - let actorsHtml = "主演: "; - if ($actress.length > 0) { - let actress = ""; - $actress.each(((index, ele) => { - let $actor = $(ele), name2 = $actor.text(), actressHref = $actor.attr("href"); - actorsHtml += `${name2}`; - actress += name2 + " "; - })); - $("#data-actress").text(actress); - } else actorsHtml += "暂无演员信息"; - $(".actor-list").html(actorsHtml); - const sellerNodeList = $dom.find("div").filter((function () { - return 0 === $(this).text().trim().indexOf("販売者:"); - })); - if (sellerNodeList.length > 0) { - const $sellerA = $(sellerNodeList[0]).find("a"); - if ($sellerA.length > 0) { - const $seller = $($sellerA[0]); - let name2 = $seller.text(), sellerHref = $seller.attr("href"); - $(".movie-seller").html(`販売者: ${name2}`); - } - } - } + async getActressInfo(fc2Num) { + let url = `https://fc2ppvdb.com/articles/${fc2Num.replace("FC2-", "")}`; + const html = await gmHttp.get(url), $dom = $(html), actressNodeList = $dom.find("div").filter((function () { + return 0 === $(this).text().trim().indexOf("女優:"); + })); + if (0 === actressNodeList.length || actressNodeList.length > 1) { + show.error("解析女优信息失败"); + return; + } + const $actress = $(actressNodeList[0]).find("a"); + let actorsHtml = "主演: "; + if ($actress.length > 0) { + let actress = ""; + $actress.each(((index, ele) => { + let $actor = $(ele), name2 = $actor.text(), actressHref = $actor.attr("href"); + actorsHtml += `${name2}`; + actress += name2 + " "; + })); + $("#data-actress").text(actress); + } else actorsHtml += "暂无演员信息"; + $(".actor-list").html(actorsHtml); + const sellerNodeList = $dom.find("div").filter((function () { + return 0 === $(this).text().trim().indexOf("販売者:"); + })); + if (sellerNodeList.length > 0) { + const $sellerA = $(sellerNodeList[0]).find("a"); + if ($sellerA.length > 0) { + const $seller = $($sellerA[0]); + let name2 = $seller.text(), sellerHref = $seller.attr("href"); + $(".movie-seller").html(`販売者: ${name2}`); + } + } + } - async getImgList(fc2Num) { - let tempCarNum = fc2Num.replace("FC2-", ""), - url = `https://adult.contents.fc2.com/article/${fc2Num.replace("FC2-", "")}/`; - const html = await gmHttp.get(url, null, { - referer: url - }); - let imgList = $(html).find(".items_article_SampleImagesArea img").map((function () { - return $(this).attr("src"); - })).get(), imagesHtml = ""; - Array.isArray(imgList) && imgList.length > 0 ? imagesHtml = imgList.map(((img, index) => ` + async getImgList(fc2Num) { + let tempCarNum = fc2Num.replace("FC2-", ""), + url = `https://adult.contents.fc2.com/article/${fc2Num.replace("FC2-", "")}/`; + const html = await gmHttp.get(url, null, { + referer: url + }); + let imgList = $(html).find(".items_article_SampleImagesArea img").map((function () { + return $(this).attr("src"); + })).get(), imagesHtml = ""; + Array.isArray(imgList) && imgList.length > 0 ? imagesHtml = imgList.map(((img, index) => ` `)).join("") : $(".movie-gallery").html("

    剧照: 暂无剧照

    "); - $(".image-list").html(imagesHtml); - this.handleLongImg(tempCarNum); - } + $(".image-list").html(imagesHtml); + this.handleLongImg(tempCarNum); + } - async getMovie(id, moviePoster) { - let url = `${await this.getBaseUrl()}/ajax/v/${id}/videos`, loadObj = loading(); - try { - let movieList = (await gmHttp.get(url)).result.watch; - if (movieList.length > 0) { - movieList.forEach(((movieItem) => { - movieItem.url = movieItem.url + "?poster=" + moviePoster; - })); - return movieList; - } - return null; - } catch (e) { - console.error(e); - } finally { - loadObj.close(); - } - } + async getMovie(id, moviePoster) { + let url = `${await this.getBaseUrl()}/ajax/v/${id}/videos`, loadObj = loading(); + try { + let movieList = (await gmHttp.get(url)).result.watch; + if (movieList.length > 0) { + movieList.forEach(((movieItem) => { + movieItem.url = movieItem.url + "?poster=" + moviePoster; + })); + return movieList; + } + return null; + } catch (e) { + console.error(e); + } finally { + loadObj.close(); + } + } - markDataListHtml(movies) { - let moviesHtml = ""; - movies.forEach(((movie) => { - moviesHtml += ` + markDataListHtml(movies) { + let moviesHtml = ""; + movies.forEach(((movie) => { + moviesHtml += `
    `; - })); - return moviesHtml; - } + })); + return moviesHtml; + } + } + + class DetailPageButtonPlugin extends BasePlugin { + getName() { + return "DetailPageButtonPlugin"; + } + + constructor() { + super(); + this.answerCount = 1; + } + + async handle() { + let settingObj = await storageManager.getSetting(); + this.filterHotKey = settingObj.filterHotKey; + this.favoriteHotKey = settingObj.favoriteHotKey; + this.hasDownHotKey = settingObj.hasDownHotKey; + this.hasWatchHotKey = settingObj.hasWatchHotKey; + this.speedVideoHotKey = settingObj.speedVideoHotKey; + this.bindHotkey().then(); + this.hideVideoControls(); + window.isDetailPage && this.createMenuBtn(); + } + + async createMenuBtn() { + const pageInfo = this.getPageInfo(), carNum2 = pageInfo.carNum, + buttonsHtml = '\n \n '; + isJavDb$1 && $(".tabs").after(buttonsHtml); + isJavBus$1 && $("#mag-submit-show").before(buttonsHtml); + $("#favoriteBtn").on("click", (() => this.favoriteOne())); + $("#filterBtn").on("click", ((event) => this.filterOne(event))); + $("#hasDownBtn").on("click", (async () => this.hasDownOne())); + $("#hasWatchBtn").on("click", (async () => this.hasWatchOne())); + $("#magnetSearchBtn").on("click", (() => { + let magnetHub = this.getBean("MagnetHubPlugin").createMagnetHub(pageInfo.carNum); + layer.open({ + type: 1, + title: "磁力搜索 " + pageInfo.carNum, + content: '
    ', + area: utils.getResponsiveArea(["60%", "80%"]), + scrollbar: false, + success: () => { + $("#magnetHubBox").append(magnetHub); + } + }); + })); + const highlightMagnetPlugin = this.getBean("HighlightMagnetPlugin"), + enableMagnetsFilter = await storageManager.getSetting("enableMagnetsFilter", NO); + if (enableMagnetsFilter === YES$1) { + const savedSettings = await storageManager.getSetting("magnetSortAndFilter", "{}"); + let settings; + try { + settings = JSON.parse(savedSettings); + } catch (e) { + settings = {}; } + const sortEnabled = settings.sortEnabled || {}; + const defaultFullSortOrder = isJavBus$1 ? ["date", "size"] : ["date", "size", "files"]; + const fullSortOrder = settings.sortOrder && settings.sortOrder.length === defaultFullSortOrder.length ? settings.sortOrder : defaultFullSortOrder; + const effectiveSortOrder = fullSortOrder.filter((key) => sortEnabled[key]); + const applySettings = { + filterHD: settings.filterHD || false, + filter4K: settings.filter4K || false, + filterSubtitle: settings.filterSubtitle || false, + filterUncensored: settings.filterUncensored || false, + sortOrder: effectiveSortOrder + }; + const rowReadyCondition = isJavBus$1 ? (() => $("#magnet-table tr").length > 1) : (() => $("#magnets-content .item[data-rank]").length > 0); + utils.loopDetector(rowReadyCondition, () => { + highlightMagnetPlugin.applySortAndFilter(applySettings); + }); + $("#magnets-span").text("取消磁力过滤"); + } else { + $("#magnets-span").text("排序与过滤"); + } + $("#enable-magnets-filter").on("click", ((event) => { + const $span = $("#magnets-span"); + if ("取消磁力过滤" === $span.text()) { + highlightMagnetPlugin.showAll(); + $span.text("排序与过滤"); + storageManager.saveSettingItem("enableMagnetsFilter", NO); + } else { + this.openMagnetSortFilterPanel(highlightMagnetPlugin); + } + })); + $("#subtitleSearchBtn").on("click", (() => { + window.JavPackSubtitle.openSearchModal({details: {code: carNum2}}); + })); + window.JavPackSubtitle.preload115Matches(carNum2); + this.showStatus(carNum2).then(); + } - class DetailPageButtonPlugin extends BasePlugin { - getName() { - return "DetailPageButtonPlugin"; - } - - constructor() { - super(); - this.answerCount = 1; - } - - async handle() { - let settingObj = await storageManager.getSetting(); - this.filterHotKey = settingObj.filterHotKey; - this.favoriteHotKey = settingObj.favoriteHotKey; - this.hasDownHotKey = settingObj.hasDownHotKey; - this.hasWatchHotKey = settingObj.hasWatchHotKey; - this.speedVideoHotKey = settingObj.speedVideoHotKey; - this.bindHotkey().then(); - this.hideVideoControls(); - window.isDetailPage && this.createMenuBtn(); - } - - async createMenuBtn() { - const pageInfo = this.getPageInfo(), carNum2 = pageInfo.carNum, - buttonsHtml = '\n \n '; - isJavDb$1 && $(".tabs").after(buttonsHtml); - isJavBus$1 && $("#mag-submit-show").before(buttonsHtml); - $("#favoriteBtn").on("click", (() => this.favoriteOne())); - $("#filterBtn").on("click", ((event) => this.filterOne(event))); - $("#hasDownBtn").on("click", (async () => this.hasDownOne())); - $("#hasWatchBtn").on("click", (async () => this.hasWatchOne())); - $("#magnetSearchBtn").on("click", (() => { - let magnetHub = this.getBean("MagnetHubPlugin").createMagnetHub(pageInfo.carNum); - layer.open({ - type: 1, - title: "磁力搜索 " + pageInfo.carNum, - content: '
    ', - area: utils.getResponsiveArea(["60%", "80%"]), - scrollbar: false, - success: () => { - $("#magnetHubBox").append(magnetHub); - } - }); - })); - const highlightMagnetPlugin = this.getBean("HighlightMagnetPlugin"), - enableMagnetsFilter = await storageManager.getSetting("enableMagnetsFilter", NO); - if (enableMagnetsFilter === YES$1) { - const savedSettings = await storageManager.getSetting("magnetSortAndFilter", "{}"); - let settings; - try { - settings = JSON.parse(savedSettings); - } catch (e) { - settings = {}; - } - const sortEnabled = settings.sortEnabled || {}; - const defaultFullSortOrder = isJavBus$1 ? ["date", "size"] : ["date", "size", "files"]; - const fullSortOrder = settings.sortOrder && settings.sortOrder.length === defaultFullSortOrder.length ? settings.sortOrder : defaultFullSortOrder; - const effectiveSortOrder = fullSortOrder.filter((key) => sortEnabled[key]); - const applySettings = { - filterHD: settings.filterHD || false, - filter4K: settings.filter4K || false, - filterSubtitle: settings.filterSubtitle || false, - filterUncensored: settings.filterUncensored || false, - sortOrder: effectiveSortOrder - }; - const rowReadyCondition = isJavBus$1 ? (() => $("#magnet-table tr").length > 1) : (() => $("#magnets-content .item[data-rank]").length > 0); - utils.loopDetector(rowReadyCondition, () => { - highlightMagnetPlugin.applySortAndFilter(applySettings); - }); - $("#magnets-span").text("取消磁力过滤"); - } else { - $("#magnets-span").text("排序与过滤"); - } - $("#enable-magnets-filter").on("click", ((event) => { - const $span = $("#magnets-span"); - if ("取消磁力过滤" === $span.text()) { - highlightMagnetPlugin.showAll(); - $span.text("排序与过滤"); - storageManager.saveSettingItem("enableMagnetsFilter", NO); - } else { - this.openMagnetSortFilterPanel(highlightMagnetPlugin); - } - })); - $("#subtitleSearchBtn").on("click", (() => { - window.JavPackSubtitle.openSearchModal({details: {code: carNum2}}); - })); - window.JavPackSubtitle.preload115Matches(carNum2); - this.showStatus(carNum2).then(); - } - - async openMagnetSortFilterPanel(highlightMagnetPlugin) { - const existingPanel = document.getElementById("magnet-sort-filter-panel"); - if (existingPanel) { - existingPanel.remove(); - return; - } - const savedSettings = await storageManager.getSetting("magnetSortAndFilter", "{}"); - let settings; - try { - settings = JSON.parse(savedSettings); - } catch (e) { - settings = {}; - } - const sortEnabled = settings.sortEnabled || (isJavBus$1 ? {date: false, size: false} : { - date: false, - size: false, - files: false - }); - const defaultSortOrder = isJavBus$1 ? ["date", "size"] : ["date", "size", "files"]; - const sortOrder = settings.sortOrder && settings.sortOrder.length === defaultSortOrder.length ? settings.sortOrder : defaultSortOrder; - const filterHD = settings.filterHD || false; - const filter4K = settings.filter4K || false; - const filterSubtitle = settings.filterSubtitle || false; - const filterUncensored = settings.filterUncensored || false; - const SORT_LABELS = isJavBus$1 ? {date: "发布日期", size: "文件大小"} : { - date: "发布日期", - size: "文件大小", - files: "文件数量" - }; - const SORT_HINTS = isJavBus$1 ? {date: "从新到旧", size: "从大到小"} : { - date: "从新到旧", - size: "从大到小", - files: "从少到多" - }; - const FILTER_ITEMS = [ - {key: "HD", label: "高清", checked: filterHD}, - {key: "4K", label: "4K", checked: filter4K}, - {key: "Subtitle", label: "字幕", checked: filterSubtitle}, - {key: "Uncensored", label: "无码", checked: filterUncensored} - ]; - const currentSortOrder = [...sortOrder]; - const currentSortEnabled = {...sortEnabled}; - const currentFilters = { - HD: filterHD, - "4K": filter4K, - Subtitle: filterSubtitle, - Uncensored: filterUncensored - }; - const buildSortItemsHTML = () => { - return currentSortOrder.map((key) => { - const checked = currentSortEnabled[key] ? "checked" : ""; - return `
    + async openMagnetSortFilterPanel(highlightMagnetPlugin) { + const existingPanel = document.getElementById("magnet-sort-filter-panel"); + if (existingPanel) { + existingPanel.remove(); + return; + } + const savedSettings = await storageManager.getSetting("magnetSortAndFilter", "{}"); + let settings; + try { + settings = JSON.parse(savedSettings); + } catch (e) { + settings = {}; + } + const sortEnabled = settings.sortEnabled || (isJavBus$1 ? {date: false, size: false} : { + date: false, + size: false, + files: false + }); + const defaultSortOrder = isJavBus$1 ? ["date", "size"] : ["date", "size", "files"]; + const sortOrder = settings.sortOrder && settings.sortOrder.length === defaultSortOrder.length ? settings.sortOrder : defaultSortOrder; + const filterHD = settings.filterHD || false; + const filter4K = settings.filter4K || false; + const filterSubtitle = settings.filterSubtitle || false; + const filterUncensored = settings.filterUncensored || false; + const SORT_LABELS = isJavBus$1 ? {date: "发布日期", size: "文件大小"} : { + date: "发布日期", + size: "文件大小", + files: "文件数量" + }; + const SORT_HINTS = isJavBus$1 ? {date: "从新到旧", size: "从大到小"} : { + date: "从新到旧", + size: "从大到小", + files: "从少到多" + }; + const FILTER_ITEMS = [ + {key: "HD", label: "高清", checked: filterHD}, + {key: "4K", label: "4K", checked: filter4K}, + {key: "Subtitle", label: "字幕", checked: filterSubtitle}, + {key: "Uncensored", label: "无码", checked: filterUncensored} + ]; + const currentSortOrder = [...sortOrder]; + const currentSortEnabled = {...sortEnabled}; + const currentFilters = { + HD: filterHD, + "4K": filter4K, + Subtitle: filterSubtitle, + Uncensored: filterUncensored + }; + const buildSortItemsHTML = () => { + return currentSortOrder.map((key) => { + const checked = currentSortEnabled[key] ? "checked" : ""; + return `
    ⋮⋮
    `; - }).join(""); - }; - const buildFilterItemsHTML = () => { - return FILTER_ITEMS.map((item) => { - const checked = currentFilters[item.key] ? "checked" : ""; - return `