diff --git a/CHANGELOG.md b/CHANGELOG.md index e1b65fc7..b743fec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/lang/zh-CN/ ## [Unreleased] +## [6.5.2](../../compare/v6.5.1...v6.5.2) - 2026-10-16 + +### 新增 + +- 列表“更多筛选”新增“全部未下载”,排除屏蔽项和已下载作品,保留未下载的待鉴定、收藏和已看内容。 +- 设置中的“默认显示选项卡”支持全部筛选,包括“屏蔽项”和“全部未下载”等智能筛选,下次进入列表页生效;保留原有默认设置,选项与列表共用同一份筛选定义。 + +### 修复 + +- 启用“浏览后自动移除新作品标记”后,已浏览卡片渐隐移除,后续作品按原有筛选、排序和分页规则补位;保留其他卡片及封面节点、浏览位置和选择项,避免整体刷新回到顶部。 +- 新作品手动移除和状态标记移除共用局部更新逻辑;处理连续移除、动画期间翻页或切换筛选和关闭重开弹窗,避免已移除卡片重新出现、页码越界或旧回调覆盖新界面。 +- 最后一页移空时回到上一页,全部移空时显示原有空状态;减少动态效果时直接完成补位。 + ## [6.5.1](../../compare/v6.5.0...v6.5.1) - 2026-09-25 ### 修复 diff --git a/JHS.user.js b/JHS.user.js index 02a58a59..ae6ae9c9 100644 --- a/JHS.user.js +++ b/JHS.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name JHS // @namespace https://sleazyfork.org/zh-CN/scripts/578503-jhs-ya -// @version 6.5.1 +// @version 6.5.2 // @author JHS Contributors // @description JAV Helper Suite:为 JavDB / JavBus 提供浏览、收藏、筛选、资源检索、数据备份与统计增强。 // @license MIT @@ -70,14 +70,14 @@ // @updateURL https://raw.githubusercontent.com/Teamper/JHS/main/JHS.user.js // ==/UserScript== -(()=>{var Po=Object.defineProperty;var Ud=(o,e,t)=>e in o?Po(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var d=(o,e)=>Po(o,"name",{value:e,configurable:!0});var ct=(o,e,t)=>Ud(o,typeof e!="symbol"?e+"":e,t);var Dr=class Dr{constructor(e,t={}){if(!e)throw new TypeError("LifecycleScope id is required");this.id=e,this.controller=new AbortController,this.cleanups=new Set,this.requestConsumers=new Set,this.observerCleanups=new Map,this.listenerCount=0,this.observerCount=0,this.disposed=!1,this.generation=0,this.onChange=t.onChange??null}get signal(){return this.controller.signal}listen(e,t,s,a){return this.assertActive(),e.addEventListener(t,s,a),this.listenerCount+=1,this.addCleanup(()=>{e.removeEventListener(t,s,a),this.listenerCount-=1})}ownObserver(e){this.assertActive();let t=this.observerCleanups.get(e);if(t)return t;this.observerCount+=1;let s=this.addCleanup(()=>{e.disconnect(),this.observerCount-=1,this.observerCleanups.delete(e)});return this.observerCleanups.set(e,s),s}releaseObserver(e){this.observerCleanups.get(e)?.()}observe(e,t,s){this.assertActive();let a=new MutationObserver(t);return a.observe(e,s),this.ownObserver(a),a}ownTimeout(e){return this.addCleanup(()=>clearTimeout(e))}ownRequestConsumer(e){return this.assertActive(),this.requestConsumers.add(e),this.emitChange(),this.addCleanup(()=>{this.requestConsumers.delete(e)&&e.release()})}addCleanup(e){this.assertActive();let t=!0,s=d(()=>{t&&(t=!1,this.cleanups.delete(s),e(),this.emitChange())},"wrapped");return this.cleanups.add(s),this.emitChange(),s}nextGeneration(){return this.assertActive(),this.generation+=1,this.generation}canCommit(e){return!this.disposed&&e===this.generation}dispose(){if(!this.disposed){this.disposed=!0,this.controller.abort();for(let e of[...this.cleanups].reverse())e();this.emitChange()}}assertActive(){if(this.disposed)throw new DOMException(`LifecycleScope ${this.id} is disposed`,"AbortError")}snapshot(){return Object.freeze({id:this.id,disposed:this.disposed,listeners:this.listenerCount,observers:this.observerCount,requestConsumers:this.requestConsumers.size,generation:this.generation})}emitChange(){this.onChange?.(this.snapshot())}};d(Dr,"LifecycleScope");var te=Dr;var gs=new WeakSet;function kt(o={},e={}){if(gs.has(o)||gs.has(o.success))return o;let{ui:t,...s}=o,a=["scroll","table","media"].includes(t?.body)?t.body:"scroll";t?.size&&e.getDialogArea&&(s.area=e.getDialogArea(t.size));let r,i=s.success,n=s.end;return s.success=function(l,c){let h=l?.nodeType===1?l:l?.[0]||globalThis.document?.getElementById(`layui-layer${c}`);if(h?.classList){h.classList.add("jhs-dialog","jhs-ui"),h.dataset.jhsDialogBody=a,r=new te(`dialog-shell-${c}`);let u=h.querySelector(".layui-layer-close");u&&(u.setAttribute("role","button"),u.setAttribute("tabindex","0"),u.setAttribute("aria-label","关闭弹窗"),r.listen(u,"keydown",g=>{let m=g.key;(m==="Enter"||m===" ")&&(g.preventDefault(),u.click())}));let p=d(()=>{if(t?.size&&e.getDialogArea){let[m,f]=e.getDialogArea(t.size);Object.assign(h.style,{width:m,height:f});let v=h.querySelector(".layui-layer-content"),b=h.querySelector("iframe");if(b&&v){let w=h.querySelector(".layui-layer-title")?.getBoundingClientRect().height||0;v.style.height=`${Math.max(0,parseFloat(f)-w)}px`,b.style.height=v.style.height}}h.style.maxWidth=`${Math.max(0,window.innerWidth-16)}px`,h.style.maxHeight=`${Math.max(0,window.innerHeight-16)}px`;let g=h.getBoundingClientRect();(t?.size||g.right>window.innerWidth-8||g.left<8)&&(h.style.left=`${h.offsetLeft+Math.max(8,(window.innerWidth-g.width)/2)-g.left}px`),(t?.size||g.bottom>window.innerHeight-8||g.top<8)&&(h.style.top=`${h.offsetTop+Math.max(8,(window.innerHeight-g.height)/2)-g.top}px`)},"resize");r.listen(window,"resize",p),p()}try{return i?.call(this,l,c)}catch(u){throw r?.dispose(),u}},s.end=function(...l){return r?.dispose(),n?.apply(this,l)},gs.add(s),gs.add(s.success),s}d(kt,"prepareDialogOptions");var zd=/^(?:[a-z0-9-]+\.)?javdb(?:[a-z0-9-]*)\.com$/i,Fd=["javbus","javsee","seejav"];function Nr(o=window.location){return o instanceof URL?o:typeof o=="string"?new URL(o):new URL(o.href||`${o.protocol}//${o.hostname}${o.pathname||"/"}${o.search||""}`)}d(Nr,"normalizeLocation");function Ct(o=window.location){let t=Nr(o).hostname.toLowerCase().replace(/\.$/,""),s=zd.test(t),a=Fd.some((c=>t.includes(c))),r=t==="123pan.com"||t.endsWith(".123pan.com"),i=t==="javtrailers.com"||t.endsWith(".javtrailers.com"),n=t==="subtitlecat.com"||t.endsWith(".subtitlecat.com");return{site:s?"javdb":a?"javbus":r?"123pan":i?"javtrailers":n?"subtitlecat":"unknown",hostname:t,isJavDB:s,isJavBus:a,is123Pan:r,isJavTrailers:i,isSubtitleCat:n}}d(Ct,"detectSite");function je(o=window.location){let e=Nr(o),t=e.pathname,s=e.searchParams;return t==="/rankings/movies"?{kind:"movie-ranking",period:s.get("p")||"daily",category:s.get("t")||"censored"}:t==="/rankings/playback"?{kind:"playback-ranking",period:s.get("p")||"daily",filter:s.get("t")||"high_score"}:t==="/rankings/top"?{kind:"top250-ranking",selection:s.get("t")||"all",page:Math.max(1,Number(s.get("page"))||1)}:t==="/rankings/actors"?{kind:"actor-ranking"}:t==="/rankings/fanza_award"?{kind:"award-ranking"}:t==="/tags/fc2"?{kind:s.get("jhs_source")==="123av"?"external-fc2-catalog":"fc2-catalog"}:t==="/search_advanced"?{kind:"advanced-search"}:{kind:"other"}}d(je,"classifyJavDbPage");function Io(o){let e=Nr(o);if(e.pathname!=="/advanced_search")return null;let t=e.searchParams,s=new URL(e.href);if(t.get("handlePlayback")==="1"){s.pathname="/rankings/playback",s.search="";let a=t.get("period")||"daily";s.searchParams.set("p",["daily","weekly","monthly"].includes(a)?a:"daily"),s.searchParams.set("t","high_score")}else if(t.get("handleTop")==="1"){s.pathname="/rankings/top",s.search="";let a=t.get("handleType"),r=t.get("type_value")||"";a==="year"&&/^\d{4}$/.test(r)&&s.searchParams.set("t",`y${r}`),a==="video_type"&&/^[0-3]$/.test(r)&&s.searchParams.set("t",r);let i=Math.max(1,Number.parseInt(t.get("page")||"1",10)||1),n=Math.floor((i-1)*50/40)+1;n>1&&s.searchParams.set("page",String(n)),["0","1"].includes(t.get("has_cnsub")||"")&&s.searchParams.set("jhs_subtitle",t.get("has_cnsub")==="1"?"with":"without")}else if(t.get("type")==="100"&&t.get("released_start")==="2099-09"){s.pathname="/tags/fc2",s.search="",s.searchParams.set("c10","1"),s.searchParams.set("jhs_source","123av");for(let a of["keyword","page"])t.has(a)&&s.searchParams.set(a,t.get(a)||"")}else s.pathname="/search_advanced";return s.href}d(Io,"resolveLegacyJavDbUrl");var Vd=Object.defineProperty,Lr=d(o=>{throw TypeError(o)},"a"),P=d((o,e,t)=>((s,a,r)=>a in s?Vd(s,a,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[a]=r)(o,typeof e!="symbol"?e+"":e,t),"i"),Mr=d((o,e,t)=>(((s,a,r)=>{a.has(s)||Lr("Cannot "+r)})(o,e,"access private method"),t),"s"),X="",Br={site:"unknown",hostname:"",isJavDB:!1,isJavBus:!1,is123Pan:!1,isJavTrailers:!1,isSubtitleCat:!1},M=!1,B=!1,ms=!1,ce="filter",ue="favorite",pe="hasDown",me="hasWatch",Le="屏蔽",tt="已屏蔽";var Me="收藏",st="已收藏";var fe="已下载";var ve="已观看";var ne="no",R="yes",Be="javdb",Se="javbus",Oe="actor",at="actress",We="censored",Ke="uncensored",rt=[{id:"video-mhb",quality:"dmb_w",text:"旧视频源-中画质宽版 (404p)",canSelect:!1},{id:"video-mhb",quality:"sm_s",text:"旧视频源-低画质 (240p)",canSelect:!1},{id:"video-mhb",quality:"dm_s",text:"旧视频源-中画质 (360p)",canSelect:!1},{id:"video-mhb",quality:"dmb_s",text:"旧视频源-中画质 (480p)",canSelect:!1},{id:"video-mhb",quality:"mhb_w",text:"旧视频源-高画质宽版 (404p)",canSelect:!1},{id:"video-mmb",quality:"mmb",text:"中画质 (432p)",canSelect:!0},{id:"video-mhb",quality:"mhb",text:"高画质 (576p)",canSelect:!0},{id:"video-hmb",quality:"hmb",text:"HD (720p)",canSelect:!0},{id:"video-hhb",quality:"hhb",text:"FullHD (1080p)",canSelect:!0},{id:"video-hhbs",quality:"hhbs",text:"FullHD (1080p60fps)",canSelect:!0},{id:"video-4k",quality:"4k",text:"4K (2160p)",canSelect:!0},{id:"video-4ks",quality:"4ks",text:"4K (2160p60fps)",canSelect:!0}];function Ro(o=window.location){let e=Ct(o);return X=o.href,Br=e,M=e.isJavDB,B=e.isJavBus,ms=X.includes("/search?q")||X.includes("/search/")||X.includes("/users/"),e}d(Ro,"initializeRuntimeConstants");function C(o){let e=document.createElement("span");return e.textContent=o,e.innerHTML.replaceAll('"',""").replaceAll("'","'")}d(C,"escapeHtml");var fs=3;function T(o){if(typeof o!="string")return null;let e=o.trim();return!e||["undefined","null"].includes(e.toLowerCase())?null:(e=e.normalize("NFKC").replace(/[‐‑‒–—―﹘﹣-]/g,"-").replace(/[\s_]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toUpperCase(),e?qd(e):null)}d(T,"normalizeCarNum");var Hd=new Set(["ABC","ABP","ADN","ATID","BF","CAWD","DLDSS","DVAJ","FSDSS","HEYZO","HMN","IPX","IPZZ","JUQ","JUL","JUX","MEYD","MIAA","MIDE","MIDV","MIMK","MIRD","NIMA","PRED","RBD","SDDE","SONE","SSIS","SSNI","STARS","URE","VEC","WAAA","WANZ","XVSR"]);function qd(o){let e=String(o||"").match(/^([A-Z]{2,8})(\d{2,7})$/);return e&&Hd.has(e[1])?`${e[1]}-${e[2]}`:o}d(qd,"tryCanonicalizeSimpleCarNum");function Eo(...o){for(let e of o){let t=T(e);if(t)return t}return null}d(Eo,"firstValidCarNum");function Do(o){if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError("getPageInfo() contract broken: expected object");return o}d(Do,"assertPageInfoContract");function No(){return window.location.href.includes("hideNav=1")?` +(()=>{var Ro=Object.defineProperty;var zd=(o,e,t)=>e in o?Ro(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var d=(o,e)=>Ro(o,"name",{value:e,configurable:!0});var dt=(o,e,t)=>zd(o,typeof e!="symbol"?e+"":e,t);var Nr=class Nr{constructor(e,t={}){if(!e)throw new TypeError("LifecycleScope id is required");this.id=e,this.controller=new AbortController,this.cleanups=new Set,this.requestConsumers=new Set,this.observerCleanups=new Map,this.listenerCount=0,this.observerCount=0,this.disposed=!1,this.generation=0,this.onChange=t.onChange??null}get signal(){return this.controller.signal}listen(e,t,s,a){return this.assertActive(),e.addEventListener(t,s,a),this.listenerCount+=1,this.addCleanup(()=>{e.removeEventListener(t,s,a),this.listenerCount-=1})}ownObserver(e){this.assertActive();let t=this.observerCleanups.get(e);if(t)return t;this.observerCount+=1;let s=this.addCleanup(()=>{e.disconnect(),this.observerCount-=1,this.observerCleanups.delete(e)});return this.observerCleanups.set(e,s),s}releaseObserver(e){this.observerCleanups.get(e)?.()}observe(e,t,s){this.assertActive();let a=new MutationObserver(t);return a.observe(e,s),this.ownObserver(a),a}ownTimeout(e){return this.addCleanup(()=>clearTimeout(e))}ownRequestConsumer(e){return this.assertActive(),this.requestConsumers.add(e),this.emitChange(),this.addCleanup(()=>{this.requestConsumers.delete(e)&&e.release()})}addCleanup(e){this.assertActive();let t=!0,s=d(()=>{t&&(t=!1,this.cleanups.delete(s),e(),this.emitChange())},"wrapped");return this.cleanups.add(s),this.emitChange(),s}nextGeneration(){return this.assertActive(),this.generation+=1,this.generation}canCommit(e){return!this.disposed&&e===this.generation}dispose(){if(!this.disposed){this.disposed=!0,this.controller.abort();for(let e of[...this.cleanups].reverse())e();this.emitChange()}}assertActive(){if(this.disposed)throw new DOMException(`LifecycleScope ${this.id} is disposed`,"AbortError")}snapshot(){return Object.freeze({id:this.id,disposed:this.disposed,listeners:this.listenerCount,observers:this.observerCount,requestConsumers:this.requestConsumers.size,generation:this.generation})}emitChange(){this.onChange?.(this.snapshot())}};d(Nr,"LifecycleScope");var te=Nr;var gs=new WeakSet;function kt(o={},e={}){if(gs.has(o)||gs.has(o.success))return o;let{ui:t,...s}=o,a=["scroll","table","media"].includes(t?.body)?t.body:"scroll";t?.size&&e.getDialogArea&&(s.area=e.getDialogArea(t.size));let r,i=s.success,n=s.end;return s.success=function(l,c){let h=l?.nodeType===1?l:l?.[0]||globalThis.document?.getElementById(`layui-layer${c}`);if(h?.classList){h.classList.add("jhs-dialog","jhs-ui"),h.dataset.jhsDialogBody=a,r=new te(`dialog-shell-${c}`);let u=h.querySelector(".layui-layer-close");u&&(u.setAttribute("role","button"),u.setAttribute("tabindex","0"),u.setAttribute("aria-label","关闭弹窗"),r.listen(u,"keydown",g=>{let m=g.key;(m==="Enter"||m===" ")&&(g.preventDefault(),u.click())}));let p=d(()=>{if(t?.size&&e.getDialogArea){let[m,f]=e.getDialogArea(t.size);Object.assign(h.style,{width:m,height:f});let v=h.querySelector(".layui-layer-content"),b=h.querySelector("iframe");if(b&&v){let w=h.querySelector(".layui-layer-title")?.getBoundingClientRect().height||0;v.style.height=`${Math.max(0,parseFloat(f)-w)}px`,b.style.height=v.style.height}}h.style.maxWidth=`${Math.max(0,window.innerWidth-16)}px`,h.style.maxHeight=`${Math.max(0,window.innerHeight-16)}px`;let g=h.getBoundingClientRect();(t?.size||g.right>window.innerWidth-8||g.left<8)&&(h.style.left=`${h.offsetLeft+Math.max(8,(window.innerWidth-g.width)/2)-g.left}px`),(t?.size||g.bottom>window.innerHeight-8||g.top<8)&&(h.style.top=`${h.offsetTop+Math.max(8,(window.innerHeight-g.height)/2)-g.top}px`)},"resize");r.listen(window,"resize",p),p()}try{return i?.call(this,l,c)}catch(u){throw r?.dispose(),u}},s.end=function(...l){return r?.dispose(),n?.apply(this,l)},gs.add(s),gs.add(s.success),s}d(kt,"prepareDialogOptions");var Fd=/^(?:[a-z0-9-]+\.)?javdb(?:[a-z0-9-]*)\.com$/i,Vd=["javbus","javsee","seejav"];function Lr(o=window.location){return o instanceof URL?o:typeof o=="string"?new URL(o):new URL(o.href||`${o.protocol}//${o.hostname}${o.pathname||"/"}${o.search||""}`)}d(Lr,"normalizeLocation");function Ct(o=window.location){let t=Lr(o).hostname.toLowerCase().replace(/\.$/,""),s=Fd.test(t),a=Vd.some((c=>t.includes(c))),r=t==="123pan.com"||t.endsWith(".123pan.com"),i=t==="javtrailers.com"||t.endsWith(".javtrailers.com"),n=t==="subtitlecat.com"||t.endsWith(".subtitlecat.com");return{site:s?"javdb":a?"javbus":r?"123pan":i?"javtrailers":n?"subtitlecat":"unknown",hostname:t,isJavDB:s,isJavBus:a,is123Pan:r,isJavTrailers:i,isSubtitleCat:n}}d(Ct,"detectSite");function je(o=window.location){let e=Lr(o),t=e.pathname,s=e.searchParams;return t==="/rankings/movies"?{kind:"movie-ranking",period:s.get("p")||"daily",category:s.get("t")||"censored"}:t==="/rankings/playback"?{kind:"playback-ranking",period:s.get("p")||"daily",filter:s.get("t")||"high_score"}:t==="/rankings/top"?{kind:"top250-ranking",selection:s.get("t")||"all",page:Math.max(1,Number(s.get("page"))||1)}:t==="/rankings/actors"?{kind:"actor-ranking"}:t==="/rankings/fanza_award"?{kind:"award-ranking"}:t==="/tags/fc2"?{kind:s.get("jhs_source")==="123av"?"external-fc2-catalog":"fc2-catalog"}:t==="/search_advanced"?{kind:"advanced-search"}:{kind:"other"}}d(je,"classifyJavDbPage");function Io(o){let e=Lr(o);if(e.pathname!=="/advanced_search")return null;let t=e.searchParams,s=new URL(e.href);if(t.get("handlePlayback")==="1"){s.pathname="/rankings/playback",s.search="";let a=t.get("period")||"daily";s.searchParams.set("p",["daily","weekly","monthly"].includes(a)?a:"daily"),s.searchParams.set("t","high_score")}else if(t.get("handleTop")==="1"){s.pathname="/rankings/top",s.search="";let a=t.get("handleType"),r=t.get("type_value")||"";a==="year"&&/^\d{4}$/.test(r)&&s.searchParams.set("t",`y${r}`),a==="video_type"&&/^[0-3]$/.test(r)&&s.searchParams.set("t",r);let i=Math.max(1,Number.parseInt(t.get("page")||"1",10)||1),n=Math.floor((i-1)*50/40)+1;n>1&&s.searchParams.set("page",String(n)),["0","1"].includes(t.get("has_cnsub")||"")&&s.searchParams.set("jhs_subtitle",t.get("has_cnsub")==="1"?"with":"without")}else if(t.get("type")==="100"&&t.get("released_start")==="2099-09"){s.pathname="/tags/fc2",s.search="",s.searchParams.set("c10","1"),s.searchParams.set("jhs_source","123av");for(let a of["keyword","page"])t.has(a)&&s.searchParams.set(a,t.get(a)||"")}else s.pathname="/search_advanced";return s.href}d(Io,"resolveLegacyJavDbUrl");var qd=Object.defineProperty,Mr=d(o=>{throw TypeError(o)},"a"),P=d((o,e,t)=>((s,a,r)=>a in s?qd(s,a,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[a]=r)(o,typeof e!="symbol"?e+"":e,t),"i"),Br=d((o,e,t)=>(((s,a,r)=>{a.has(s)||Mr("Cannot "+r)})(o,e,"access private method"),t),"s"),X="",Or={site:"unknown",hostname:"",isJavDB:!1,isJavBus:!1,is123Pan:!1,isJavTrailers:!1,isSubtitleCat:!1},M=!1,B=!1,ms=!1,ce="filter",ue="favorite",pe="hasDown",me="hasWatch",Le="屏蔽",tt="已屏蔽";var Me="收藏",st="已收藏";var fe="已下载";var ve="已观看";var ne="no",E="yes",Be="javdb",Se="javbus",Oe="actor",at="actress",Je="censored",Ke="uncensored",rt=[{id:"video-mhb",quality:"dmb_w",text:"旧视频源-中画质宽版 (404p)",canSelect:!1},{id:"video-mhb",quality:"sm_s",text:"旧视频源-低画质 (240p)",canSelect:!1},{id:"video-mhb",quality:"dm_s",text:"旧视频源-中画质 (360p)",canSelect:!1},{id:"video-mhb",quality:"dmb_s",text:"旧视频源-中画质 (480p)",canSelect:!1},{id:"video-mhb",quality:"mhb_w",text:"旧视频源-高画质宽版 (404p)",canSelect:!1},{id:"video-mmb",quality:"mmb",text:"中画质 (432p)",canSelect:!0},{id:"video-mhb",quality:"mhb",text:"高画质 (576p)",canSelect:!0},{id:"video-hmb",quality:"hmb",text:"HD (720p)",canSelect:!0},{id:"video-hhb",quality:"hhb",text:"FullHD (1080p)",canSelect:!0},{id:"video-hhbs",quality:"hhbs",text:"FullHD (1080p60fps)",canSelect:!0},{id:"video-4k",quality:"4k",text:"4K (2160p)",canSelect:!0},{id:"video-4ks",quality:"4ks",text:"4K (2160p60fps)",canSelect:!0}];function Eo(o=window.location){let e=Ct(o);return X=o.href,Or=e,M=e.isJavDB,B=e.isJavBus,ms=X.includes("/search?q")||X.includes("/search/")||X.includes("/users/"),e}d(Eo,"initializeRuntimeConstants");function T(o){let e=document.createElement("span");return e.textContent=o,e.innerHTML.replaceAll('"',""").replaceAll("'","'")}d(T,"escapeHtml");var fs=3;function C(o){if(typeof o!="string")return null;let e=o.trim();return!e||["undefined","null"].includes(e.toLowerCase())?null:(e=e.normalize("NFKC").replace(/[‐‑‒–—―﹘﹣-]/g,"-").replace(/[\s_]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toUpperCase(),e?Wd(e):null)}d(C,"normalizeCarNum");var Hd=new Set(["ABC","ABP","ADN","ATID","BF","CAWD","DLDSS","DVAJ","FSDSS","HEYZO","HMN","IPX","IPZZ","JUQ","JUL","JUX","MEYD","MIAA","MIDE","MIDV","MIMK","MIRD","NIMA","PRED","RBD","SDDE","SONE","SSIS","SSNI","STARS","URE","VEC","WAAA","WANZ","XVSR"]);function Wd(o){let e=String(o||"").match(/^([A-Z]{2,8})(\d{2,7})$/);return e&&Hd.has(e[1])?`${e[1]}-${e[2]}`:o}d(Wd,"tryCanonicalizeSimpleCarNum");function Do(...o){for(let e of o){let t=C(e);if(t)return t}return null}d(Do,"firstValidCarNum");function No(o){if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError("getPageInfo() contract broken: expected object");return o}d(No,"assertPageInfoContract");function Lo(){return window.location.href.includes("hideNav=1")?` .navbar-default { display: none !important; } body { padding-top:0px!important; } - `:""}d(No,"getJavBusHiddenNavCss");function Lo(){return window.location.href.includes("hideNav=1")?` + `:""}d(Lo,"getJavBusHiddenNavCss");function Mo(){return window.location.href.includes("hideNav=1")?` .main-nav,#search-bar-container { display: none !important; } @@ -85,7 +85,7 @@ html { padding-top:0px!important; } - `:""}d(Lo,"getJavDbHiddenNavCss");function Mo(o){if(o)if(o.includes(" -`}d(Bo,"buildThemeCss");function Ht(o="light"){let e="light";o==="dark"?e="dark":o==="auto"&&(e=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"),document.documentElement.setAttribute("data-jhs-theme",e)}d(Ht,"applyThemeMode");function Oo(o){let e=window.matchMedia("(prefers-color-scheme: dark)");o.listen(e,"change",()=>{let t=globalThis.settingsService?.snapshot?.().themeMode??storageManager.getSettingSync("themeMode","light");t==="auto"&&Ht(t)})}d(Oo,"initializeThemeRuntime");function Uo(){return` +`}d(Oo,"buildThemeCss");function Ht(o="light"){let e="light";o==="dark"?e="dark":o==="auto"&&(e=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"),document.documentElement.setAttribute("data-jhs-theme",e)}d(Ht,"applyThemeMode");function Uo(o){let e=window.matchMedia("(prefers-color-scheme: dark)");o.listen(e,"change",()=>{let t=globalThis.settingsService?.snapshot?.().themeMode??storageManager.getSettingSync("themeMode","light");t==="auto"&&Ht(t)})}d(Uo,"initializeThemeRuntime");function zo(){return` `}d(Uo,"buildUiPrimitivesCss");function Ue(o,{type:e="empty",title:t="",description:s="",actionLabel:a="",onAction:r=null}={}){let i=o?.jquery?o:$(o),n=$('
').addClass(`jhs-state--${e}`).attr("role",e==="error"?"alert":"status"),l=$('
');return t&&l.append($('

').text(t)),s&&l.append($('

').text(s)),a&&typeof r=="function"&&l.append($('').text(a).on("click",r)),n.append(l),i.empty().append(n),n}d(Ue,"renderStateView");function zo(o){if(!o||typeof o.observe!="function")throw new TypeError("UI accessibility requires an app LifecycleScope");let e="button.jhs-btn, a.jhs-btn[role='button'], .card-btn, .jhs-icon-btn, [class*='jhs-'] button, [class*='jhs-'] a[role='button']",t=d(i=>{let n=i.nodeType===Node.ELEMENT_NODE&&i.matches?.(e)?[i]:[],l=i.querySelectorAll?[...i.querySelectorAll(e)]:[];[...n,...l].forEach((c=>{if(c.hasAttribute("aria-label")||c.hasAttribute("aria-labelledby")||c.textContent.trim())return;let h=c.getAttribute("title")||c.getAttribute("data-tip");h&&c.setAttribute("aria-label",h)}))},"enhance");t(document);let s=new Set,a=!1,r=d(()=>{a=!1;let i=[...s],n=i.filter((l=>!i.some((c=>c!==l&&c.contains?.(l)))));s.clear(),n.forEach(t)},"flush");return o.observe(document.documentElement,(i=>{i.forEach((n=>n.addedNodes.forEach((l=>{l.nodeType===Node.ELEMENT_NODE&&s.add(l)})))),s.size&&!a&&(a=!0,queueMicrotask(r))}),{childList:!0,subtree:!0})}d(zo,"initializeUiAccessibility");var ie=class ie{static _ensureGlobalClickHandler(){ie._globalClickBound||(ie._globalClickBound=!0,$(document).on("click.jhsSelect",(e=>{$(e.target).closest(".jhs-select-control").length||ie.closeAll()})))}constructor(e){if(this.source=$(e),!this.source.length)return;let t=ie.instances.get(this.source[0]);if(t)return t;let s=this.source.hasClass("jhs-is-hidden")||this.source[0].style.display==="none";this.control=$('
'),this.trigger=$(''),this.menu=$(''),this.source.wrap(this.control),this.control=this.source.parent(),this.control.append(this.trigger,this.menu),this.source.addClass("jhs-select-source-native").attr({"aria-hidden":"true",tabindex:"-1"}),s&&this.control.addClass("jhs-is-hidden"),ie.instances.set(this.source[0],this),this.render(),this.bind(),this.refresh()}static enhance(e=document){let t=$(e),s=t.is("select.jhs-select-source")?t:t.find("select.jhs-select-source");return s.each(((a,r)=>new ie(r))),s}static get(e){let t=$(e)[0];return t?ie.instances.get(t)||new ie(t):null}static setValue(e,t,s=!1){let a=ie.get(e);a&&(a.source.val(t),s?a.emitChange():a.refresh())}static refresh(e){ie.get(e)?.refresh()}static refreshAll(e=document){ie.enhance(e),$(e).find("select.jhs-select-source").each(((t,s)=>ie.refresh(s)))}static setVisible(e,t){ie.get(e)?.control.toggleClass("jhs-is-hidden",!t)}static closeAll(e=null){$(".jhs-select-control.is-open").each(((t,s)=>{let a=$(s).children("select.jhs-select-source")[0],r=a&&ie.instances.get(a);r&&r!==e&&r.close()}))}render(){this.menu.empty();let e=d((t,s)=>{let a=$('');a.attr({"data-value":t.value,"aria-checked":t.selected?"true":"false"}).prop("disabled",t.disabled).text(t.text),s.append(a)},"appendOption");this.source.children().each(((t,s)=>{if(s.tagName==="OPTGROUP"){let a=$('
').attr("aria-label",s.label),r=$('
').text(s.label);a.append(r),$(s).children("option").each(((i,n)=>e(n,a))),this.menu.append(a)}else s.tagName==="OPTION"&&e(s,this.menu)}))}bind(){this.trigger.on("click",(e=>{e.preventDefault(),e.stopPropagation(),this.source.prop("disabled")||(this.control.hasClass("is-open")?this.close():this.open())})).on("keydown",(e=>{["ArrowDown","ArrowUp","Home","End"].includes(e.key)&&(e.preventDefault(),this.open(e.key==="ArrowUp"||e.key==="End"?"last":e.key==="Home"?"first":"selected"))})),this.menu.on("click",".jhs-select-option",(e=>{e.preventDefault(),this.choose($(e.currentTarget))})).on("keydown",".jhs-select-option",(e=>{let t=this.options(),s=t.index(e.currentTarget);if(e.key==="Escape")return e.preventDefault(),e.stopPropagation(),this.close(!0);if(e.key==="Tab")return void this.close(!0);if(["Enter"," "].includes(e.key))return e.preventDefault(),this.choose($(e.currentTarget));if(!["ArrowDown","ArrowUp","Home","End"].includes(e.key))return;e.preventDefault();let a=e.key==="Home"?0:e.key==="End"?t.length-1:e.key==="ArrowDown"?(s+1)%t.length:(s-1+t.length)%t.length;t.eq(a).trigger("focus")})),this.source.on("change.jhsSelect",(()=>this.refresh())),ie._ensureGlobalClickHandler()}options(){return this.menu.find(".jhs-select-option:not(:disabled)")}open(e="selected"){ie.closeAll(this),this.control.addClass("is-open"),this.menu.addClass("is-open"),this.trigger.attr("aria-expanded","true");let t=this.options(),s=t.filter('[aria-checked="true"]');(e==="last"?t.last():e==="first"?t.first():s.length?s.first():t.first()).trigger("focus")}close(e=!1){this.control.removeClass("is-open"),this.menu.removeClass("is-open"),this.trigger.attr("aria-expanded","false"),e&&this.trigger.trigger("focus")}choose(e){e.prop("disabled")||(this.source.val(e.attr("data-value")),this.emitChange(),this.close(!0))}emitChange(){this.source[0]?.dispatchEvent(new Event("change",{bubbles:!0}))}refresh(){let e=this.source.find("option:selected").first(),t=this.source.val();this.trigger.find(".jhs-select-value").text(e.text()),this.trigger.prop("disabled",this.source.prop("disabled")),this.menu.find(".jhs-select-option").attr("aria-checked","false").filter(((s,a)=>$(a).attr("data-value")===String(t??""))).attr("aria-checked","true")}};d(ie,"JhsSelect"),ct(ie,"instances",new WeakMap),ct(ie,"_globalClickBound",!1);var K=ie;function Jd(){return` +`}d(zo,"buildUiPrimitivesCss");function Ue(o,{type:e="empty",title:t="",description:s="",actionLabel:a="",onAction:r=null}={}){let i=o?.jquery?o:$(o),n=$('
').addClass(`jhs-state--${e}`).attr("role",e==="error"?"alert":"status"),l=$('
');return t&&l.append($('

').text(t)),s&&l.append($('

').text(s)),a&&typeof r=="function"&&l.append($('').text(a).on("click",r)),n.append(l),i.empty().append(n),n}d(Ue,"renderStateView");function Fo(o){if(!o||typeof o.observe!="function")throw new TypeError("UI accessibility requires an app LifecycleScope");let e="button.jhs-btn, a.jhs-btn[role='button'], .card-btn, .jhs-icon-btn, [class*='jhs-'] button, [class*='jhs-'] a[role='button']",t=d(i=>{let n=i.nodeType===Node.ELEMENT_NODE&&i.matches?.(e)?[i]:[],l=i.querySelectorAll?[...i.querySelectorAll(e)]:[];[...n,...l].forEach((c=>{if(c.hasAttribute("aria-label")||c.hasAttribute("aria-labelledby")||c.textContent.trim())return;let h=c.getAttribute("title")||c.getAttribute("data-tip");h&&c.setAttribute("aria-label",h)}))},"enhance");t(document);let s=new Set,a=!1,r=d(()=>{a=!1;let i=[...s],n=i.filter((l=>!i.some((c=>c!==l&&c.contains?.(l)))));s.clear(),n.forEach(t)},"flush");return o.observe(document.documentElement,(i=>{i.forEach((n=>n.addedNodes.forEach((l=>{l.nodeType===Node.ELEMENT_NODE&&s.add(l)})))),s.size&&!a&&(a=!0,queueMicrotask(r))}),{childList:!0,subtree:!0})}d(Fo,"initializeUiAccessibility");var ie=class ie{static _ensureGlobalClickHandler(){ie._globalClickBound||(ie._globalClickBound=!0,$(document).on("click.jhsSelect",(e=>{$(e.target).closest(".jhs-select-control").length||ie.closeAll()})))}constructor(e){if(this.source=$(e),!this.source.length)return;let t=ie.instances.get(this.source[0]);if(t)return t;let s=this.source.hasClass("jhs-is-hidden")||this.source[0].style.display==="none";this.control=$('
'),this.trigger=$(''),this.menu=$(''),this.source.wrap(this.control),this.control=this.source.parent(),this.control.append(this.trigger,this.menu),this.source.addClass("jhs-select-source-native").attr({"aria-hidden":"true",tabindex:"-1"}),s&&this.control.addClass("jhs-is-hidden"),ie.instances.set(this.source[0],this),this.render(),this.bind(),this.refresh()}static enhance(e=document){let t=$(e),s=t.is("select.jhs-select-source")?t:t.find("select.jhs-select-source");return s.each(((a,r)=>new ie(r))),s}static get(e){let t=$(e)[0];return t?ie.instances.get(t)||new ie(t):null}static setValue(e,t,s=!1){let a=ie.get(e);a&&(a.source.val(t),s?a.emitChange():a.refresh())}static refresh(e){ie.get(e)?.refresh()}static refreshAll(e=document){ie.enhance(e),$(e).find("select.jhs-select-source").each(((t,s)=>ie.refresh(s)))}static setVisible(e,t){ie.get(e)?.control.toggleClass("jhs-is-hidden",!t)}static closeAll(e=null){$(".jhs-select-control.is-open").each(((t,s)=>{let a=$(s).children("select.jhs-select-source")[0],r=a&&ie.instances.get(a);r&&r!==e&&r.close()}))}render(){this.menu.empty();let e=d((t,s)=>{let a=$('');a.attr({"data-value":t.value,"aria-checked":t.selected?"true":"false"}).prop("disabled",t.disabled).text(t.text),s.append(a)},"appendOption");this.source.children().each(((t,s)=>{if(s.tagName==="OPTGROUP"){let a=$('
').attr("aria-label",s.label),r=$('
').text(s.label);a.append(r),$(s).children("option").each(((i,n)=>e(n,a))),this.menu.append(a)}else s.tagName==="OPTION"&&e(s,this.menu)}))}bind(){this.trigger.on("click",(e=>{e.preventDefault(),e.stopPropagation(),this.source.prop("disabled")||(this.control.hasClass("is-open")?this.close():this.open())})).on("keydown",(e=>{["ArrowDown","ArrowUp","Home","End"].includes(e.key)&&(e.preventDefault(),this.open(e.key==="ArrowUp"||e.key==="End"?"last":e.key==="Home"?"first":"selected"))})),this.menu.on("click",".jhs-select-option",(e=>{e.preventDefault(),this.choose($(e.currentTarget))})).on("keydown",".jhs-select-option",(e=>{let t=this.options(),s=t.index(e.currentTarget);if(e.key==="Escape")return e.preventDefault(),e.stopPropagation(),this.close(!0);if(e.key==="Tab")return void this.close(!0);if(["Enter"," "].includes(e.key))return e.preventDefault(),this.choose($(e.currentTarget));if(!["ArrowDown","ArrowUp","Home","End"].includes(e.key))return;e.preventDefault();let a=e.key==="Home"?0:e.key==="End"?t.length-1:e.key==="ArrowDown"?(s+1)%t.length:(s-1+t.length)%t.length;t.eq(a).trigger("focus")})),this.source.on("change.jhsSelect",(()=>this.refresh())),ie._ensureGlobalClickHandler()}options(){return this.menu.find(".jhs-select-option:not(:disabled)")}open(e="selected"){ie.closeAll(this),this.control.addClass("is-open"),this.menu.addClass("is-open"),this.trigger.attr("aria-expanded","true");let t=this.options(),s=t.filter('[aria-checked="true"]');(e==="last"?t.last():e==="first"?t.first():s.length?s.first():t.first()).trigger("focus")}close(e=!1){this.control.removeClass("is-open"),this.menu.removeClass("is-open"),this.trigger.attr("aria-expanded","false"),e&&this.trigger.trigger("focus")}choose(e){e.prop("disabled")||(this.source.val(e.attr("data-value")),this.emitChange(),this.close(!0))}emitChange(){this.source[0]?.dispatchEvent(new Event("change",{bubbles:!0}))}refresh(){let e=this.source.find("option:selected").first(),t=this.source.val();this.trigger.find(".jhs-select-value").text(e.text()),this.trigger.prop("disabled",this.source.prop("disabled")),this.menu.find(".jhs-select-option").attr("aria-checked","false").filter(((s,a)=>$(a).attr("data-value")===String(t??""))).attr("aria-checked","true")}};d(ie,"JhsSelect"),dt(ie,"instances",new WeakMap),dt(ie,"_globalClickBound",!1);var K=ie;function Jd(){return` `}d(Jd,"buildJavBusCss");function Wd(){return` +`}d(Jd,"buildJavBusCss");function Kd(){return` `}d(Wd,"buildJavDbCss");var Kd=` +`}d(Kd,"buildJavDbCss");var Gd=` `,Fo=!1;function Vo(o,e=""){if(Fo)return;let t=d((s,a)=>o?.register?o.register(s,a.replace(/^\s*`,Vo=!1;function qo(o,e=""){if(Vo)return;let t=d((s,a)=>o?.register?o.register(s,a.replace(/^\s* - `),document.head.insertAdjacentHTML("beforeend",""),window.loading=function(){let i=document.createElement("div");i.className="loading-container",i.setAttribute("role","status"),i.setAttribute("aria-live","polite"),i.setAttribute("aria-label","处理中"),i.setAttribute("aria-busy","true");let n=document.createElement("div");return n.className="loading-animation",i.appendChild(n),document.body.appendChild(i),{close:d(()=>{i&&i.parentNode&&i.parentNode.removeChild(i)},"close")}},(function(){let i=d((n,l,c,h,u)=>{let p;typeof c=="object"?(p=c,p.gravity||(p.gravity="top"),p.position||(p.position="center")):(p=typeof h=="object"?h:u||{},p.gravity=c||"top",p.position=typeof h=="string"?h:"center"),p.gravity&&p.gravity!=="center"||(p.offset={y:"calc(50vh - 150px)"});let g="var(--jhs-status-fav)",m="var(--jhs-status-fav-tint)",f="var(--jhs-status-down)",v="var(--jhs-status-down-tint)",b="var(--jhs-status-filter)",w="var(--jhs-status-filter-tint)",S={borderRadius:"12px",padding:"12px 16px",boxShadow:"0 4px 6px rgba(0,0,0,0.1)",minWidth:"150px",textAlign:"center",zIndex:W.debug},j={text:n,duration:2500,close:!1,gravity:"top",position:"center",style:{info:{...S,background:`${g}`,color:"var(--jhs-status-fav-on)"},success:{...S,background:`${f}`,color:"var(--jhs-status-down-on)"},error:{...S,background:`${b}`,color:"var(--jhs-status-filter-on)"}}[l],stopOnFocus:!0,oldestFirst:!1,...p};j.duration===-1&&(j.close=!0);let x=Toastify(j);return x.showToast(),x.closeShow=()=>{x.toastElement.remove()},x},"e");window.show={ok:d((n,l="center",c,h)=>i(n,"success",l,c,h),"ok"),error:d((n,l="center",c,h)=>i(n,"error",l,c,h),"error"),info:d((n,l="center",c,h)=>i(n,"info",l,c,h),"info")}})(),(function(){let i=null;document.head.insertAdjacentHTML("beforeend",`"),window.loading=function(){let i=document.createElement("div");i.className="loading-container",i.setAttribute("role","status"),i.setAttribute("aria-live","polite"),i.setAttribute("aria-label","处理中"),i.setAttribute("aria-busy","true");let n=document.createElement("div");return n.className="loading-animation",i.appendChild(n),document.body.appendChild(i),{close:d(()=>{i&&i.parentNode&&i.parentNode.removeChild(i)},"close")}},(function(){let i=d((n,l,c,h,u)=>{let p;typeof c=="object"?(p=c,p.gravity||(p.gravity="top"),p.position||(p.position="center")):(p=typeof h=="object"?h:u||{},p.gravity=c||"top",p.position=typeof h=="string"?h:"center"),p.gravity&&p.gravity!=="center"||(p.offset={y:"calc(50vh - 150px)"});let g="var(--jhs-status-fav)",m="var(--jhs-status-fav-tint)",f="var(--jhs-status-down)",v="var(--jhs-status-down-tint)",b="var(--jhs-status-filter)",w="var(--jhs-status-filter-tint)",S={borderRadius:"12px",padding:"12px 16px",boxShadow:"0 4px 6px rgba(0,0,0,0.1)",minWidth:"150px",textAlign:"center",zIndex:J.debug},j={text:n,duration:2500,close:!1,gravity:"top",position:"center",style:{info:{...S,background:`${g}`,color:"var(--jhs-status-fav-on)"},success:{...S,background:`${f}`,color:"var(--jhs-status-down-on)"},error:{...S,background:`${b}`,color:"var(--jhs-status-filter-on)"}}[l],stopOnFocus:!0,oldestFirst:!1,...p};j.duration===-1&&(j.close=!0);let k=Toastify(j);return k.showToast(),k.closeShow=()=>{k.toastElement.remove()},k},"e");window.show={ok:d((n,l="center",c,h)=>i(n,"success",l,c,h),"ok"),error:d((n,l="center",c,h)=>i(n,"error",l,c,h),"error"),info:d((n,l="center",c,h)=>i(n,"info",l,c,h),"info")}})(),(function(){let i=null;document.head.insertAdjacentHTML("beforeend",` - `),window.showImageViewer=function(n,l="",c={}){let h=null,u=!1;if(typeof n=="string"||n instanceof String){let z=document.createElement("div"),Z=document.createElement("img");z.className="temporary-container jhs-layout-c8be1ccb",Z.src=String(n),Z.alt=String(l),z.appendChild(Z),document.body.appendChild(z),h=$(z),u=!0}else h=$(n);let p=h.is("img")?h[0]:h.find("img")[0],g=p?.closest(".jhs-fc2-workspace"),m=g?.querySelector('[data-jhs-slot="gallery"]'),f=m?.contains(p)?$(m):c.galleryRoot?$(c.galleryRoot):null,v=f?.length?f:h,b=v.find("img").addBack("img").toArray(),w=Math.max(0,b.indexOf(p)),S=b.length>1;if(!p||!v.length||!p.isConnected||o.disposed)return void(u&&h.remove());i?.close(!1);let j=p.closest(".layui-layer"),x=p.closest("button,a,[tabindex]")||document.activeElement,k=g&&j?.querySelector(".layui-layer-content"),_=new te("ui:image-viewer"),E=document.documentElement.style.overflow,L=document.body.style.overflow,N,A,O,U,H=g?.inert,Q=k?.classList.contains("jhs-image-viewer-owner"),se={close(z=!0){if(!_.disposed){_.dispose(),A?.();try{N?.destroy()}finally{O?.remove(),k&&(k.classList.toggle("jhs-image-viewer-owner",Q),g.inert=H),u&&h.remove(),i===se&&(i=null,document.documentElement.style.overflow=document.querySelector(".layui-layer-shade")?"hidden":j?"":E,document.body.style.overflow=L,z&&x?.isConnected&&x.focus?.({preventScroll:!0}))}}}};i=se,A=o.addCleanup(()=>se.close(!1));let ge=[...document.querySelectorAll(".layui-layer")].reduce((z,Z)=>{let re=window.getComputedStyle(Z),xt=Number(re.zIndex);return re.display!=="none"&&Number.isFinite(xt)?Math.max(z,xt+1):z},W.viewer);if(k){O=document.createElement("div"),O.className="jhs-image-viewer-host",O.style.zIndex=String(ge);let z=document.createElement("div");z.hidden=!0,b.forEach(Z=>{let re=document.createElement("img");re.src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1' height='1'/%3E",re.setAttribute("data-jhs-viewer-source",Z.currentSrc||Z.src),re.alt=Z.alt,z.appendChild(re)}),O.appendChild(z),k.classList.add("jhs-image-viewer-owner"),k.appendChild(O),g.inert=!0,v=$(z)}let De=d(z=>z<0?N?.prev(!!g):N?.next(!!g),"navigate"),Ne={zIndex:ge,...g?{className:`jhs-fc2-image-viewer jhs-ui${k?" viewer-in":""}`,inline:!!k,zIndexInline:ge,minWidth:0,minHeight:0,button:!1,transition:!1,initialCoverage:.9,ready:d(()=>{if(_.disposed||!N?.viewer)return;let z=N.viewer,Z=document.createElement("div");Z.className="jhs-image-viewer-toolbar",z.setAttribute("role","dialog"),z.setAttribute("aria-label","图片预览");let re=d((ye,Ld,Md,Bd,Od=z)=>{let lt=document.createElement("button");return lt.type="button",lt.className=`jhs-btn jhs-btn--secondary ${Md}`,lt.setAttribute("aria-label",ye),lt.textContent=Ld,_.listen(lt,"click",Ao=>{Ao.preventDefault(),Ao.stopPropagation(),Bd()}),Od.appendChild(lt),lt},"button"),xt=re("关闭图片","×","jhs-image-viewer-close",()=>se.close());S&&(re("上一张","‹","jhs-image-viewer-nav jhs-image-viewer-prev",()=>De(-1)),re("下一张","›","jhs-image-viewer-nav jhs-image-viewer-next",()=>De(1))),re("放大图片","放大","",()=>N.zoom(.1),Z),re("缩小图片","缩小","",()=>N.zoom(-.1),Z),re("适应窗口","适应","",()=>N.reset(),Z),U=document.createElement("span"),U.className="jhs-image-viewer-count",U.setAttribute("aria-live","polite"),Z.appendChild(U),N.footer.appendChild(Z);let ps=-1/0;if(_.listen(z,"wheel",ye=>{!S||ye.ctrlKey||!ye.deltaY||(ye.preventDefault(),ye.stopPropagation(),!(ye.timeStamp-ps<180)&&(ps=ye.timeStamp,De(Math.sign(ye.deltaY))))},{passive:!1}),k&&typeof ResizeObserver<"u"){let ye=new ResizeObserver(()=>{N?.ready&&!_.disposed&&N.resize()});ye.observe(O),_.ownObserver(ye)}xt.focus({preventScroll:!0})},"bindFc2Controls")}:{},...k?{url:"data-jhs-viewer-source"}:{},navbar:!1,initialViewIndex:w,zoomOnWheel:!1,zoomRatio:.1,toggleOnDblclick:!1,toolbar:g?!1:{prev:S?1:0,zoomIn:1,zoomOut:1,reset:1,next:S?1:0,rotateLeft:0,rotateRight:0,flipHorizontal:0,flipVertical:0},title:!1,keyboard:!1,viewed(){if(_.disposed)return;if(g){N.resize(),U&&(U.textContent=`${N.index+1} / ${b.length}`);return}N.zoomTo(1.4);let z=(N.viewerData.width-N.imageData.width)/2,Z=(N.viewerData.height-N.imageData.height)/2;N.moveTo(z,Z)},shown(){_.disposed||(document.documentElement.style.overflow="hidden",document.body.style.overflow="hidden")},hidden(){se.close()}};try{_.listen(document,"keydown",z=>{if(S&&z.key==="ArrowLeft")return z.preventDefault(),z.stopPropagation(),void De(-1);if(S&&z.key==="ArrowRight")return z.preventDefault(),z.stopPropagation(),void De(1);if(g&&z.key==="Tab"&&N?.viewer){let Z=[...N.viewer.querySelectorAll("button")],re=Z.indexOf(document.activeElement);z.preventDefault(),Z[(re+(z.shiftKey?-1:1)+Z.length)%Z.length]?.focus();return}(z.key==="Escape"||!g&&z.key===" ")&&(z.preventDefault(),z.stopPropagation(),se.close())},!0),_.observe(document.body,()=>{(!p.isConnected||j&&!j.isConnected)&&se.close(!1)},{childList:!0,subtree:!0}),N=new Viewer(v[0],Ne),N.show()}catch(z){throw se.close(!1),z}}})(),window.ImageHoverPreview=class{constructor(i={}){this.scope=new te(`ui:image-hover:${Date.now()}`),this.config={selector:".hover-preview",dataAttribute:"data-full",maxWidth:1e3,maxHeight:1e3,offsetX:20,offsetY:20,zIndex:W.hoverPreview,owner:null,resolveOwner:null,zIndexStrategy:"fixed",transition:.2,hideDelay:100,loadedUrlLimit:128,autoAdjustPosition:!0,...i},this.config.loadedUrlLimit=Math.max(1,Number(this.config.loadedUrlLimit)||128),this.preview=null,this.currentTarget=null,this.timer=null,this.imgElement=null,this.pendingImage=null,this.placement=null,this.pointer=null,this.animationFrame=null,this.loadGeneration=0,this.destroyed=!1,this.currentUrl=null,this.pendingUrl=null,this.loadedUrls=new Map,this.eventsBound=!1,this.overlayObserver=null,this.onMouseEnter=n=>this.handleMouseEnter(n),this.onMouseLeave=n=>this.handleMouseLeave(n),this.onMouseMove=n=>this.handleMouseMove(n),this.onDocumentOver=n=>this.handleDocumentOver(n),this.onDocumentOut=n=>this.handleDocumentOut(n),this.onDocumentMove=n=>this.handleDocumentMove(n),this.onDocumentScroll=()=>this.handleDocumentScroll(),this.suppressUntilMouseMove=!1,this.init()}init(){utils.isMobileMode()||(this.injectStyles(),this.createPreviewElement(),this.bindEvents())}injectStyles(){if(document.getElementById("jhs-image-hover-preview-style"))return;let i=document.createElement("style");i.id="jhs-image-hover-preview-style",i.textContent=` + `),window.showImageViewer=function(n,l="",c={}){let h=null,u=!1;if(typeof n=="string"||n instanceof String){let z=document.createElement("div"),Z=document.createElement("img");z.className="temporary-container jhs-layout-c8be1ccb",Z.src=String(n),Z.alt=String(l),z.appendChild(Z),document.body.appendChild(z),h=$(z),u=!0}else h=$(n);let p=h.is("img")?h[0]:h.find("img")[0],g=p?.closest(".jhs-fc2-workspace"),m=g?.querySelector('[data-jhs-slot="gallery"]'),f=m?.contains(p)?$(m):c.galleryRoot?$(c.galleryRoot):null,v=f?.length?f:h,b=v.find("img").addBack("img").toArray(),w=Math.max(0,b.indexOf(p)),S=b.length>1;if(!p||!v.length||!p.isConnected||o.disposed)return void(u&&h.remove());i?.close(!1);let j=p.closest(".layui-layer"),k=p.closest("button,a,[tabindex]")||document.activeElement,x=g&&j?.querySelector(".layui-layer-content"),_=new te("ui:image-viewer"),R=document.documentElement.style.overflow,L=document.body.style.overflow,N,A,O,U,q=g?.inert,Q=x?.classList.contains("jhs-image-viewer-owner"),se={close(z=!0){if(!_.disposed){_.dispose(),A?.();try{N?.destroy()}finally{O?.remove(),x&&(x.classList.toggle("jhs-image-viewer-owner",Q),g.inert=q),u&&h.remove(),i===se&&(i=null,document.documentElement.style.overflow=document.querySelector(".layui-layer-shade")?"hidden":j?"":R,document.body.style.overflow=L,z&&k?.isConnected&&k.focus?.({preventScroll:!0}))}}}};i=se,A=o.addCleanup(()=>se.close(!1));let ge=[...document.querySelectorAll(".layui-layer")].reduce((z,Z)=>{let re=window.getComputedStyle(Z),xt=Number(re.zIndex);return re.display!=="none"&&Number.isFinite(xt)?Math.max(z,xt+1):z},J.viewer);if(x){O=document.createElement("div"),O.className="jhs-image-viewer-host",O.style.zIndex=String(ge);let z=document.createElement("div");z.hidden=!0,b.forEach(Z=>{let re=document.createElement("img");re.src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1' height='1'/%3E",re.setAttribute("data-jhs-viewer-source",Z.currentSrc||Z.src),re.alt=Z.alt,z.appendChild(re)}),O.appendChild(z),x.classList.add("jhs-image-viewer-owner"),x.appendChild(O),g.inert=!0,v=$(z)}let De=d(z=>z<0?N?.prev(!!g):N?.next(!!g),"navigate"),Ne={zIndex:ge,...g?{className:`jhs-fc2-image-viewer jhs-ui${x?" viewer-in":""}`,inline:!!x,zIndexInline:ge,minWidth:0,minHeight:0,button:!1,transition:!1,initialCoverage:.9,ready:d(()=>{if(_.disposed||!N?.viewer)return;let z=N.viewer,Z=document.createElement("div");Z.className="jhs-image-viewer-toolbar",z.setAttribute("role","dialog"),z.setAttribute("aria-label","图片预览");let re=d((ye,Md,Bd,Od,Ud=z)=>{let ct=document.createElement("button");return ct.type="button",ct.className=`jhs-btn jhs-btn--secondary ${Bd}`,ct.setAttribute("aria-label",ye),ct.textContent=Md,_.listen(ct,"click",Po=>{Po.preventDefault(),Po.stopPropagation(),Od()}),Ud.appendChild(ct),ct},"button"),xt=re("关闭图片","×","jhs-image-viewer-close",()=>se.close());S&&(re("上一张","‹","jhs-image-viewer-nav jhs-image-viewer-prev",()=>De(-1)),re("下一张","›","jhs-image-viewer-nav jhs-image-viewer-next",()=>De(1))),re("放大图片","放大","",()=>N.zoom(.1),Z),re("缩小图片","缩小","",()=>N.zoom(-.1),Z),re("适应窗口","适应","",()=>N.reset(),Z),U=document.createElement("span"),U.className="jhs-image-viewer-count",U.setAttribute("aria-live","polite"),Z.appendChild(U),N.footer.appendChild(Z);let ps=-1/0;if(_.listen(z,"wheel",ye=>{!S||ye.ctrlKey||!ye.deltaY||(ye.preventDefault(),ye.stopPropagation(),!(ye.timeStamp-ps<180)&&(ps=ye.timeStamp,De(Math.sign(ye.deltaY))))},{passive:!1}),x&&typeof ResizeObserver<"u"){let ye=new ResizeObserver(()=>{N?.ready&&!_.disposed&&N.resize()});ye.observe(O),_.ownObserver(ye)}xt.focus({preventScroll:!0})},"bindFc2Controls")}:{},...x?{url:"data-jhs-viewer-source"}:{},navbar:!1,initialViewIndex:w,zoomOnWheel:!1,zoomRatio:.1,toggleOnDblclick:!1,toolbar:g?!1:{prev:S?1:0,zoomIn:1,zoomOut:1,reset:1,next:S?1:0,rotateLeft:0,rotateRight:0,flipHorizontal:0,flipVertical:0},title:!1,keyboard:!1,viewed(){if(_.disposed)return;if(g){N.resize(),U&&(U.textContent=`${N.index+1} / ${b.length}`);return}N.zoomTo(1.4);let z=(N.viewerData.width-N.imageData.width)/2,Z=(N.viewerData.height-N.imageData.height)/2;N.moveTo(z,Z)},shown(){_.disposed||(document.documentElement.style.overflow="hidden",document.body.style.overflow="hidden")},hidden(){se.close()}};try{_.listen(document,"keydown",z=>{if(S&&z.key==="ArrowLeft")return z.preventDefault(),z.stopPropagation(),void De(-1);if(S&&z.key==="ArrowRight")return z.preventDefault(),z.stopPropagation(),void De(1);if(g&&z.key==="Tab"&&N?.viewer){let Z=[...N.viewer.querySelectorAll("button")],re=Z.indexOf(document.activeElement);z.preventDefault(),Z[(re+(z.shiftKey?-1:1)+Z.length)%Z.length]?.focus();return}(z.key==="Escape"||!g&&z.key===" ")&&(z.preventDefault(),z.stopPropagation(),se.close())},!0),_.observe(document.body,()=>{(!p.isConnected||j&&!j.isConnected)&&se.close(!1)},{childList:!0,subtree:!0}),N=new Viewer(v[0],Ne),N.show()}catch(z){throw se.close(!1),z}}})(),window.ImageHoverPreview=class{constructor(i={}){this.scope=new te(`ui:image-hover:${Date.now()}`),this.config={selector:".hover-preview",dataAttribute:"data-full",maxWidth:1e3,maxHeight:1e3,offsetX:20,offsetY:20,zIndex:J.hoverPreview,owner:null,resolveOwner:null,zIndexStrategy:"fixed",transition:.2,hideDelay:100,loadedUrlLimit:128,autoAdjustPosition:!0,...i},this.config.loadedUrlLimit=Math.max(1,Number(this.config.loadedUrlLimit)||128),this.preview=null,this.currentTarget=null,this.timer=null,this.imgElement=null,this.pendingImage=null,this.placement=null,this.pointer=null,this.animationFrame=null,this.loadGeneration=0,this.destroyed=!1,this.currentUrl=null,this.pendingUrl=null,this.loadedUrls=new Map,this.eventsBound=!1,this.overlayObserver=null,this.onMouseEnter=n=>this.handleMouseEnter(n),this.onMouseLeave=n=>this.handleMouseLeave(n),this.onMouseMove=n=>this.handleMouseMove(n),this.onDocumentOver=n=>this.handleDocumentOver(n),this.onDocumentOut=n=>this.handleDocumentOut(n),this.onDocumentMove=n=>this.handleDocumentMove(n),this.onDocumentScroll=()=>this.handleDocumentScroll(),this.suppressUntilMouseMove=!1,this.init()}init(){utils.isMobileMode()||(this.injectStyles(),this.createPreviewElement(),this.bindEvents())}injectStyles(){if(document.getElementById("jhs-image-hover-preview-style"))return;let i=document.createElement("style");i.id="jhs-image-hover-preview-style",i.textContent=` .image-hover-preview { position: fixed; display: block; @@ -1747,7 +1747,7 @@ transform: translate(-50%, -50%); } .image-hover-preview__error { padding: var(--jhs-space-3); color: var(--jhs-danger); } - `,document.head.appendChild(i)}createPreviewElement(){this.preview=document.createElement("div"),this.preview.className="image-hover-preview",this.preview.style.zIndex=String(this.resolvePreviewZIndex()),this.preview.style.setProperty("--jhs-hover-transition",`${this.config.transition}s`),document.body.appendChild(this.preview)}resolveOwnerElement(){let i=typeof this.config.resolveOwner=="function"?this.config.resolveOwner():this.config.owner;return i?.jquery?i[0]:i}resolvePreviewZIndex(){let i=Number(this.config.zIndex)||W.hoverPreview;if(this.config.zIndexStrategy!=="owner"&&!this.resolveOwnerElement())return i;let n=this.resolveOwnerElement();for(;n;){let l=typeof getComputedStyle=="function"?getComputedStyle(n).zIndex:"",c=Number(n.style?.zIndex||l);if(Number.isFinite(c)&&c>0){i=c+1;break}n=n.parentElement}return i}refreshOwnerZIndex(){if(this.preview&&(this.config.zIndexStrategy==="owner"||this.resolveOwnerElement())){let i=String(this.resolvePreviewZIndex());this.preview.style.zIndex!==i&&(this.preview.style.zIndex=i)}}isOwnerUncovered(){let i=this.resolveOwnerElement();if(!i)return this.config.zIndexStrategy!=="owner";if(!i.isConnected||!this.currentTarget?.isConnected||!i.contains(this.currentTarget))return!1;let n=i.closest(".layui-layer"),l=Number(n&&window.getComputedStyle(n).zIndex)||0;return![...document.querySelectorAll(".layui-layer, .viewer-container, .fancybox-container, .loading-container")].some(c=>{if(c===n||c.contains(i))return!1;let h=window.getComputedStyle(c);return!c.getClientRects().length||h.display==="none"||h.visibility==="hidden"?!1:!c.matches(".layui-layer")||Number(h.zIndex)>=l})}watchOwnerOverlays(){!this.resolveOwnerElement()||this.overlayObserver||(this.overlayObserver=this.scope.observe(document.body,()=>{this.isOwnerUncovered()?this.refreshOwnerZIndex():this.hidePreview()},{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class","style","hidden"]}))}bindEvents(){this.eventsBound||this.destroyed||(this.scope.listen(document,"mouseover",this.onDocumentOver),this.scope.listen(document,"mouseout",this.onDocumentOut),this.scope.listen(document,"mousemove",this.onDocumentMove),this.scope.listen(document,"scroll",this.onDocumentScroll,{capture:!0,passive:!0}),this.scope.listen(document,"wheel",this.onDocumentScroll,{passive:!0}),this.eventsBound=!0)}handleDocumentScroll(){this.destroyed||!this.currentTarget||(this.suppressUntilMouseMove=!0,clearTimeout(this.timer),this.timer=null,this.hidePreview())}findTarget(i){let n=i.target;return n?.closest?n.closest(this.config.selector):null}handleDocumentOver(i){if(this.suppressUntilMouseMove)return;let n=this.findTarget(i);n&&(!i.relatedTarget||!n.contains(i.relatedTarget))&&this.handleMouseEnter(i,n)}handleDocumentOut(i){let n=this.findTarget(i);n&&(!i.relatedTarget||!n.contains(i.relatedTarget))&&this.handleMouseLeave()}handleDocumentMove(i){this.suppressUntilMouseMove=!1,this.currentTarget&&(i.target===this.currentTarget||this.currentTarget.contains(i.target))&&this.handleMouseMove(i)}handleMouseEnter(i,n=i.currentTarget){if(this.destroyed||!this.preview)return;if(this.refreshOwnerZIndex(),clearTimeout(this.timer),this.timer=null,this.currentTarget=n,!this.isOwnerUncovered())return this.hidePreview();this.watchOwnerOverlays(),this.pointer={x:i.clientX,y:i.clientY},this.placement=null;let l=this.currentTarget.getAttribute(this.config.dataAttribute)||this.currentTarget.src;if(!l)return;if(l===this.currentUrl&&this.imgElement)return this.showCurrentPreview();if(l===this.pendingUrl)return void this.preview.classList.add("active");let c=this.loadedUrls.get(l);if(c)return++this.loadGeneration,this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingImage=null,this.pendingUrl=null,this.loadedUrls.delete(l),this.loadedUrls.set(l,c),void this.commitPreview(l,c);let h=++this.loadGeneration;this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingUrl=l,this.currentUrl?this.showCurrentPreview():(this.preview.replaceChildren(),this.preview.classList.add("loading","active"));let u=new Image;this.pendingImage=u,u.onload=()=>{if(this.destroyed||h!==this.loadGeneration||!this.preview)return;let{width:p,height:g}=this.calculateImageSize(u),m={width:p,height:g};for(this.loadedUrls.set(l,m);this.loadedUrls.size>this.config.loadedUrlLimit;)this.loadedUrls.delete(this.loadedUrls.keys().next().value);this.pendingImage=null,this.pendingUrl=null,this.commitPreview(l,m)},u.onerror=()=>{if(this.destroyed||h!==this.loadGeneration||!this.preview)return;if(this.pendingImage=null,this.pendingUrl=null,this.currentUrl)return void this.preview.classList.add("active");let p=document.createElement("div");p.className="image-hover-preview__error",p.textContent="图片加载失败",this.preview.replaceChildren(p),this.preview.classList.remove("loading"),this.preview.classList.add("active")},u.src=l}commitPreview(i,n){if(!this.preview)return;let l=document.createElement("img");l.src=i,l.alt="预览图",this.preview.replaceChildren(l),this.imgElement=l,this.currentUrl=i,this.preview.style.width=`${n.width}px`,this.preview.style.height=`${n.height}px`,this.preview.classList.remove("loading"),this.showCurrentPreview()}showCurrentPreview(){if(!this.preview||!this.pointer||!this.imgElement)return;if(!this.isOwnerUncovered())return this.hidePreview();let i=this.preview.offsetWidth,n=this.preview.offsetHeight;this.placement=this.choosePlacement(this.pointer.x,this.pointer.y,i,n),this.preview.classList.add("active"),this.schedulePosition()}calculateImageSize(i){let l=Math.max(1,window.innerWidth-2*(8+this.config.offsetX)),c=Math.max(1,window.innerHeight-2*(8+this.config.offsetY)),h=Math.min(this.config.maxWidth,l),u=Math.min(this.config.maxHeight,c),p=Math.min(1,h/i.naturalWidth,u/i.naturalHeight);return{width:Math.max(1,Math.round(i.naturalWidth*p)),height:Math.max(1,Math.round(i.naturalHeight*p))}}choosePlacement(i,n,l,c){if(!this.config.autoAdjustPosition)return{horizontal:"right",vertical:"bottom"};let h=window.innerWidth-i-this.config.offsetX,u=i-this.config.offsetX,p=window.innerHeight-n-this.config.offsetY,g=n-this.config.offsetY;return{horizontal:h>=l||h>=u?"right":"left",vertical:p>=c||p>=g?"bottom":"top"}}handleMouseMove(i){!this.currentTarget||!this.preview?.classList.contains("active")||(this.pointer={x:i.clientX,y:i.clientY},this.schedulePosition())}schedulePosition(){this.animationFrame||!this.pointer||!this.placement||(this.animationFrame=requestAnimationFrame((()=>{this.animationFrame=null,this.applyPosition()})))}applyPosition(){if(!this.preview||!this.pointer||!this.placement)return;let i=8,n=this.preview.offsetWidth,l=this.preview.offsetHeight,c=this.placement.horizontal==="right"?this.pointer.x+this.config.offsetX:this.pointer.x-n-this.config.offsetX,h=this.placement.vertical==="bottom"?this.pointer.y+this.config.offsetY:this.pointer.y-l-this.config.offsetY;c=Math.min(Math.max(i,c),Math.max(i,window.innerWidth-n-i)),h=Math.min(Math.max(i,h),Math.max(i,window.innerHeight-l-i)),this.preview.style.left=`${c}px`,this.preview.style.top=`${h}px`}handleMouseLeave(){this.preview&&(clearTimeout(this.timer),this.timer=setTimeout((()=>this.hidePreview()),this.config.hideDelay))}hidePreview(){this.preview&&(clearTimeout(this.timer),this.overlayObserver&&(this.scope.releaseObserver(this.overlayObserver),this.overlayObserver=null),++this.loadGeneration,this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingImage=null,this.pendingUrl=null,this.preview.classList.remove("active","loading"),this.currentTarget=null,this.pointer=null,this.placement=null,this.timer=null)}destroy(){this.destroyed||(this.destroyed=!0,++this.loadGeneration,clearTimeout(this.timer),this.animationFrame&&cancelAnimationFrame(this.animationFrame),this.animationFrame=null,this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingImage=null,this.eventsBound&&(this.scope.dispose(),this.eventsBound=!1),this.overlayObserver=null,this.loadedUrls.clear(),this.preview?.remove(),this.preview=null,this.currentTarget=null)}},(function(){document.head.insertAdjacentHTML("beforeend",` + `,document.head.appendChild(i)}createPreviewElement(){this.preview=document.createElement("div"),this.preview.className="image-hover-preview",this.preview.style.zIndex=String(this.resolvePreviewZIndex()),this.preview.style.setProperty("--jhs-hover-transition",`${this.config.transition}s`),document.body.appendChild(this.preview)}resolveOwnerElement(){let i=typeof this.config.resolveOwner=="function"?this.config.resolveOwner():this.config.owner;return i?.jquery?i[0]:i}resolvePreviewZIndex(){let i=Number(this.config.zIndex)||J.hoverPreview;if(this.config.zIndexStrategy!=="owner"&&!this.resolveOwnerElement())return i;let n=this.resolveOwnerElement();for(;n;){let l=typeof getComputedStyle=="function"?getComputedStyle(n).zIndex:"",c=Number(n.style?.zIndex||l);if(Number.isFinite(c)&&c>0){i=c+1;break}n=n.parentElement}return i}refreshOwnerZIndex(){if(this.preview&&(this.config.zIndexStrategy==="owner"||this.resolveOwnerElement())){let i=String(this.resolvePreviewZIndex());this.preview.style.zIndex!==i&&(this.preview.style.zIndex=i)}}isOwnerUncovered(){let i=this.resolveOwnerElement();if(!i)return this.config.zIndexStrategy!=="owner";if(!i.isConnected||!this.currentTarget?.isConnected||!i.contains(this.currentTarget))return!1;let n=i.closest(".layui-layer"),l=Number(n&&window.getComputedStyle(n).zIndex)||0;return![...document.querySelectorAll(".layui-layer, .viewer-container, .fancybox-container, .loading-container")].some(c=>{if(c===n||c.contains(i))return!1;let h=window.getComputedStyle(c);return!c.getClientRects().length||h.display==="none"||h.visibility==="hidden"?!1:!c.matches(".layui-layer")||Number(h.zIndex)>=l})}watchOwnerOverlays(){!this.resolveOwnerElement()||this.overlayObserver||(this.overlayObserver=this.scope.observe(document.body,()=>{this.isOwnerUncovered()?this.refreshOwnerZIndex():this.hidePreview()},{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class","style","hidden"]}))}bindEvents(){this.eventsBound||this.destroyed||(this.scope.listen(document,"mouseover",this.onDocumentOver),this.scope.listen(document,"mouseout",this.onDocumentOut),this.scope.listen(document,"mousemove",this.onDocumentMove),this.scope.listen(document,"scroll",this.onDocumentScroll,{capture:!0,passive:!0}),this.scope.listen(document,"wheel",this.onDocumentScroll,{passive:!0}),this.eventsBound=!0)}handleDocumentScroll(){this.destroyed||!this.currentTarget||(this.suppressUntilMouseMove=!0,clearTimeout(this.timer),this.timer=null,this.hidePreview())}findTarget(i){let n=i.target;return n?.closest?n.closest(this.config.selector):null}handleDocumentOver(i){if(this.suppressUntilMouseMove)return;let n=this.findTarget(i);n&&(!i.relatedTarget||!n.contains(i.relatedTarget))&&this.handleMouseEnter(i,n)}handleDocumentOut(i){let n=this.findTarget(i);n&&(!i.relatedTarget||!n.contains(i.relatedTarget))&&this.handleMouseLeave()}handleDocumentMove(i){this.suppressUntilMouseMove=!1,this.currentTarget&&(i.target===this.currentTarget||this.currentTarget.contains(i.target))&&this.handleMouseMove(i)}handleMouseEnter(i,n=i.currentTarget){if(this.destroyed||!this.preview)return;if(this.refreshOwnerZIndex(),clearTimeout(this.timer),this.timer=null,this.currentTarget=n,!this.isOwnerUncovered())return this.hidePreview();this.watchOwnerOverlays(),this.pointer={x:i.clientX,y:i.clientY},this.placement=null;let l=this.currentTarget.getAttribute(this.config.dataAttribute)||this.currentTarget.src;if(!l)return;if(l===this.currentUrl&&this.imgElement)return this.showCurrentPreview();if(l===this.pendingUrl)return void this.preview.classList.add("active");let c=this.loadedUrls.get(l);if(c)return++this.loadGeneration,this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingImage=null,this.pendingUrl=null,this.loadedUrls.delete(l),this.loadedUrls.set(l,c),void this.commitPreview(l,c);let h=++this.loadGeneration;this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingUrl=l,this.currentUrl?this.showCurrentPreview():(this.preview.replaceChildren(),this.preview.classList.add("loading","active"));let u=new Image;this.pendingImage=u,u.onload=()=>{if(this.destroyed||h!==this.loadGeneration||!this.preview)return;let{width:p,height:g}=this.calculateImageSize(u),m={width:p,height:g};for(this.loadedUrls.set(l,m);this.loadedUrls.size>this.config.loadedUrlLimit;)this.loadedUrls.delete(this.loadedUrls.keys().next().value);this.pendingImage=null,this.pendingUrl=null,this.commitPreview(l,m)},u.onerror=()=>{if(this.destroyed||h!==this.loadGeneration||!this.preview)return;if(this.pendingImage=null,this.pendingUrl=null,this.currentUrl)return void this.preview.classList.add("active");let p=document.createElement("div");p.className="image-hover-preview__error",p.textContent="图片加载失败",this.preview.replaceChildren(p),this.preview.classList.remove("loading"),this.preview.classList.add("active")},u.src=l}commitPreview(i,n){if(!this.preview)return;let l=document.createElement("img");l.src=i,l.alt="预览图",this.preview.replaceChildren(l),this.imgElement=l,this.currentUrl=i,this.preview.style.width=`${n.width}px`,this.preview.style.height=`${n.height}px`,this.preview.classList.remove("loading"),this.showCurrentPreview()}showCurrentPreview(){if(!this.preview||!this.pointer||!this.imgElement)return;if(!this.isOwnerUncovered())return this.hidePreview();let i=this.preview.offsetWidth,n=this.preview.offsetHeight;this.placement=this.choosePlacement(this.pointer.x,this.pointer.y,i,n),this.preview.classList.add("active"),this.schedulePosition()}calculateImageSize(i){let l=Math.max(1,window.innerWidth-2*(8+this.config.offsetX)),c=Math.max(1,window.innerHeight-2*(8+this.config.offsetY)),h=Math.min(this.config.maxWidth,l),u=Math.min(this.config.maxHeight,c),p=Math.min(1,h/i.naturalWidth,u/i.naturalHeight);return{width:Math.max(1,Math.round(i.naturalWidth*p)),height:Math.max(1,Math.round(i.naturalHeight*p))}}choosePlacement(i,n,l,c){if(!this.config.autoAdjustPosition)return{horizontal:"right",vertical:"bottom"};let h=window.innerWidth-i-this.config.offsetX,u=i-this.config.offsetX,p=window.innerHeight-n-this.config.offsetY,g=n-this.config.offsetY;return{horizontal:h>=l||h>=u?"right":"left",vertical:p>=c||p>=g?"bottom":"top"}}handleMouseMove(i){!this.currentTarget||!this.preview?.classList.contains("active")||(this.pointer={x:i.clientX,y:i.clientY},this.schedulePosition())}schedulePosition(){this.animationFrame||!this.pointer||!this.placement||(this.animationFrame=requestAnimationFrame((()=>{this.animationFrame=null,this.applyPosition()})))}applyPosition(){if(!this.preview||!this.pointer||!this.placement)return;let i=8,n=this.preview.offsetWidth,l=this.preview.offsetHeight,c=this.placement.horizontal==="right"?this.pointer.x+this.config.offsetX:this.pointer.x-n-this.config.offsetX,h=this.placement.vertical==="bottom"?this.pointer.y+this.config.offsetY:this.pointer.y-l-this.config.offsetY;c=Math.min(Math.max(i,c),Math.max(i,window.innerWidth-n-i)),h=Math.min(Math.max(i,h),Math.max(i,window.innerHeight-l-i)),this.preview.style.left=`${c}px`,this.preview.style.top=`${h}px`}handleMouseLeave(){this.preview&&(clearTimeout(this.timer),this.timer=setTimeout((()=>this.hidePreview()),this.config.hideDelay))}hidePreview(){this.preview&&(clearTimeout(this.timer),this.overlayObserver&&(this.scope.releaseObserver(this.overlayObserver),this.overlayObserver=null),++this.loadGeneration,this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingImage=null,this.pendingUrl=null,this.preview.classList.remove("active","loading"),this.currentTarget=null,this.pointer=null,this.placement=null,this.timer=null)}destroy(){this.destroyed||(this.destroyed=!0,++this.loadGeneration,clearTimeout(this.timer),this.animationFrame&&cancelAnimationFrame(this.animationFrame),this.animationFrame=null,this.pendingImage&&(this.pendingImage.onload=null,this.pendingImage.onerror=null),this.pendingImage=null,this.eventsBound&&(this.scope.dispose(),this.eventsBound=!1),this.overlayObserver=null,this.loadedUrls.clear(),this.preview?.remove(),this.preview=null,this.currentTarget=null)}},(function(){document.head.insertAdjacentHTML("beforeend",` `);let i={base:{label:"信息",background:"var(--jhs-status-fav-tint)",borderLeftColor:"var(--jhs-accent)"},warn:{label:"警告",background:"var(--jhs-status-watch-tint)",borderLeftColor:"var(--jhs-status-watch)"},error:{label:"错误",background:"var(--jhs-status-filter-tint)",borderLeftColor:"var(--jhs-status-filter)"},debug:{label:"调试",background:"var(--jhs-surface-2)",borderLeftColor:"var(--jhs-border-strong)"}},n={base:["base","warn","error"],warn:["warn"],error:["error"],debug:["base","warn","error","debug"]},l=t,c="jhs_clog_maximize",h="jhs_clog_expand",u="jhs_clog_filter",g=class g{constructor(){let f=localStorage.getItem(u);this.currentFilter=f&&i[f]?f:"base",this.logs=[],this.isInitialized=!1,this.userScrolledUp=!1}tryInitialize(){return document.readyState!=="loading"&&(this.isInitialized||(this.init(),this.isInitialized=!0),!0)}init(){this.createContainer(),this.bindEvents(),this.checkInitialMaximizeState(),this.checkInitialCollapseState()}createContainer(){this.container=document.createElement("div"),this.container.className="console-logger-container jhs-ui",this.container.style.display="none",this.toggleBtn=document.createElement("button"),this.toggleBtn.type="button",this.toggleBtn.setAttribute("aria-label","展开或收起运行日志"),this.toggleBtn.className="console-logger-toggle collapsed",this.container.appendChild(this.toggleBtn),window.matchMedia?.("(max-width: 767px)").matches&&(this.toggleBtn.hidden=!0,this.toggleBtn.style.display="none"),this.window=document.createElement("div"),this.window.className="console-logger-window collapsed";let f=document.createElement("div");f.className="console-logger-header";let v=document.createElement("div");v.className="console-logger-title",v.textContent="JHS Console";let b=document.createElement("div");b.className="console-logger-controls",this.maximizeBtn=document.createElement("button"),this.maximizeBtn.textContent="",this.maximizeBtn.classList.add("console-logger-maximize-toggle"),b.appendChild(this.maximizeBtn);let w=document.createElement("button");w.textContent="清空",w.addEventListener("click",(()=>this.clear())),b.appendChild(w),f.appendChild(v),f.appendChild(b),this.filtersContainer=document.createElement("div"),this.filtersContainer.className="console-logger-filters",this.filterButtonGroup=document.createElement("div"),this.filterButtonGroup.className="console-logger-filter-group",this.filtersContainer.appendChild(this.filterButtonGroup),this.scrollToBottomBtn=document.createElement("button"),this.scrollToBottomBtn.className="console-logger-scroll-to-bottom",this.scrollToBottomBtn.textContent="到底部",this.filtersContainer.appendChild(this.scrollToBottomBtn),this.content=document.createElement("div"),this.content.className="console-logger-content jhs-scrollbar",this.window.appendChild(f),this.window.appendChild(this.filtersContainer),this.window.appendChild(this.content),this.container.appendChild(this.window),document.body.appendChild(this.container),Object.keys(i).forEach((S=>{let j=document.createElement("button");j.type="button",j.className="jhs-btn console-logger-filter",S===this.currentFilter&&j.classList.add("active"),j.textContent=i[S].label,j.dataset.type=S,j.addEventListener("click",(()=>this.setFilter(S))),this.filterButtonGroup.appendChild(j)}))}bindEvents(){this.toggleBtn.addEventListener("click",(()=>{this.toggleExpandCollapsed()})),this.maximizeBtn.addEventListener("click",(()=>this.toggleMaximize())),this.scrollToBottomBtn.addEventListener("click",(()=>{this.content.scrollTop=this.content.scrollHeight,this.userScrolledUp=!1})),this.content.addEventListener("scroll",(()=>{let f=this.content.scrollHeight-this.content.clientHeight<=this.content.scrollTop+5;this.userScrolledUp=!f})),this.content.addEventListener("wheel",(f=>{let v=this.content.scrollTop===0,b=this.content.scrollHeight-this.content.clientHeight<=this.content.scrollTop+1;(v&&f.deltaY<0||b&&f.deltaY>0)&&(f.preventDefault(),f.stopPropagation())}),{passive:!1})}toggleExpandCollapsed(){let f=this.window.classList.toggle("collapsed");this.toggleBtn.classList.toggle("collapsed"),f?localStorage.setItem(h,"no"):(localStorage.setItem(h,"yes"),this.reRenderAllLogs())}checkInitialCollapseState(){let f=localStorage.getItem(h);f&&f!=="no"?(this.window.classList.toggle("collapsed"),this.toggleBtn.classList.toggle("collapsed"),setTimeout((()=>{this.content.scrollTop=this.content.scrollHeight}),0)):(this.window.classList.add("collapsed"),this.toggleBtn.classList.add("collapsed"))}checkInitialMaximizeState(){localStorage.getItem(c)==="maximized"&&(this.window.classList.add("maximized"),this.maximizeBtn.classList.add("active"))}toggleMaximize(){let f=this.window.classList.toggle("maximized");this.maximizeBtn.classList.toggle("active",f),f?localStorage.setItem(c,"maximized"):localStorage.setItem(c,"minimized"),this.window.classList.contains("collapsed")||(this.content.scrollTop=this.content.scrollHeight)}addLog(f,v="base",...b){return this._appendLog(!1,f,v,...b)}addHtmlLog(f,v="base",...b){return this._appendLog(!0,f,v,...b)}_appendLog(f,v,b="base",...w){let S=this.tryInitialize(),j,x=[];i[b]?(j=b,x=w):(j="base",x=[b,...w]),j=i[j]?j:"base";let k=[v,...x],_="msg",E=[];k.forEach((A=>{if(Object.prototype.toString.call(A)==="[object Error]")E.push(String(A));else if(typeof A=="object"&&A!==null)try{E.push("
"+JSON.stringify(A,null,2)),_="json"}catch{E.push(String(A)),_="msg"}else E.push(String(A))}));let L=E.join(" ");f&&(L=L.replace(/(?:(?:https?|ftp):\/\/|www\.|(?:\/\/))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/gi,(A=>{let O=A.startsWith("http")||A.startsWith("ftp"),U=A.startsWith("//"),H=A.startsWith("www."),Q=A;return U?Q=`http:${A}`:!O&&H&&(Q=`http://${A}`),`${C(A)}`})));let N={message:L,messageType:_,type:j,html:f,timestamp:new Date,id:Date.now()+Math.random()};if(this.logs.push(N),this.logs.length>l){this.logs.shift();let A=this.content.querySelector(".console-logger-entry");A&&A.remove()}S&&this.renderLog(N)}log(...f){let[v,...b]=f;setTimeout((()=>{this.addLog(v,"base",...b)}),0)}html(...f){let[v,...b]=f;setTimeout((()=>{this.addHtmlLog(v,"base",...b)}),0)}htmlDebug(...f){let[v,...b]=f;setTimeout((()=>{this.addHtmlLog(v,"debug",...b)}),0)}error(...f){let[v,...b]=f;console.error(...f),setTimeout((()=>{this.addLog(v,"error",...b)}),0)}warn(...f){let[v,...b]=f;setTimeout((()=>{this.addLog(v,"warn",...b)}),0)}debug(...f){let[v,...b]=f;setTimeout((()=>{this.addLog(v,"debug",...b)}),0)}renderLog(f){if(this.container.style.display==="none"||this.window.classList.contains("collapsed")||!(n[this.currentFilter]||[]).includes(f.type))return;let v=this._createLogElement(f);this.content.appendChild(v),this.window.classList.contains("collapsed")||this.userScrolledUp||(this.content.scrollTop=this.content.scrollHeight)}reRenderAllLogs(){this.container.style.display!=="none"&&(this.window.classList.contains("collapsed")||setTimeout((()=>{if(this.content.innerHTML="",this.logs.length===0)return;let f=n[this.currentFilter]||[],v=document.createDocumentFragment();this.logs.forEach((b=>{if(f.includes(b.type)){let w=this._createLogElement(b);v.appendChild(w)}})),this.content.appendChild(v),this.content.scrollTop=this.content.scrollHeight}),0))}_createLogElement(f){let v=document.createElement("div");v.className="console-logger-entry",v.dataset.type=f.type,v.dataset.id=f.id;let b=i[f.type]||i.base;v.style.borderLeft="3px solid "+b.borderLeftColor,v.style.background=b.background;let w=(f.timestamp instanceof Date?f.timestamp:new Date(f.timestamp)).toTimeString().split(" ")[0],S=document.createElement("span");S.className="console-logger-timestamp",S.textContent=`[${w}]`;let j=document.createElement("span");if(j.className="console-logger-message",j.dataset.type=f.messageType,f.html)j.innerHTML=f.message;else{let x=f.message.replace(//gi,` -`),k=/(?:(?:https?|ftp):\/\/|www\.|(?:\/\/))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/gi,_=0,E;for(;E=k.exec(x);){E.index>_&&j.appendChild(document.createTextNode(x.slice(_,E.index)));let L=E[0],N=L;L.startsWith("//")?N=`http:${L}`:L.startsWith("www.")&&(N=`http://${L}`);let A=document.createElement("a");A.href=N,A.target="_blank",A.textContent=L,j.appendChild(A),_=E.index+E[0].length}_{v.dataset.type===f?v.classList.add("active"):v.classList.remove("active")})),this.reRenderAllLogs())}clear(){this.logs=[],this.content.innerHTML=""}openDialog(){if(!this.tryInitialize()||!this.window||typeof layer>"u")return;let f=document.createElement("div"),v=this.window.parentNode,b=this.window.getAttribute("style");f.className="jhs-ui jhs-logger-dialog",f.style.height="100%",this.window.classList.remove("collapsed","maximized"),Object.assign(this.window.style,{width:"100%",height:"100%",border:"0",borderRadius:"0",boxShadow:"none"}),this.reRenderAllLogs(),layer.open({type:1,title:"JHS 运行日志",content:f.outerHTML,area:utils.getDialogArea("md"),anim:-1,success:d(w=>{$(w).find(".jhs-logger-dialog")[0]?.appendChild(this.window),this.content.scrollTop=this.content.scrollHeight},"success"),end:d(()=>{v?.appendChild(this.window),b==null?this.window.removeAttribute("style"):this.window.setAttribute("style",b),this.window.classList.add("collapsed"),this.toggleBtn.classList.add("collapsed")},"end")})}show(){(this.isInitialized&&this.container||this.tryInitialize()&&this.container)&&(this.container.style.display="",this.reRenderAllLogs())}hide(){this.isInitialized&&this.container&&(this.container.style.display="none")}lowZIndex(){this.isInitialized&&this.container&&(this.container.style.zIndex=String(W.debugLow))}highZIndex(){this.isInitialized&&this.container&&(this.container.style.zIndex=String(W.debug))}};d(g,"o");let p=g;try{unsafeWindow.parent!==unsafeWindow&&unsafeWindow.parent.clog&&typeof unsafeWindow.parent.clog.log=="function"?s=unsafeWindow.parent.clog:s=new p}catch(m){console.error("创建日志控制台出现异常",m),s=new p}(function(){let m=d(()=>window.clog||console,"resolveClog");o.listen(window,"error",(function(f){let v=f.filename,b=f.message;typeof v=="string"&&(v.includes("javdb")||v.includes("javbus"))||m().error(`[全局 Error 异常捕获] ${b} 来源: ${v??"未知"}`)})),o.listen(window,"unhandledrejection",(function(f){let v=m(),b=f.reason,w=b?.message??"";if(["NotAllowedError","AbortError","NotSupportedError"].includes(b?.name)||w.includes("play()")||w.includes("The element has no supported sources"))return v.warn("[全局媒体播放异常] 当前媒体源无法播放",b),void f.preventDefault();if(w.includes("1005")&&w.includes("fc2ppvdb"))return;let S=`[全局 Promise 异常捕获] ${b.message||b}`;v.error(S,b),f.preventDefault()}))})(),o.listen(document,"mousedown",(m=>{let f=window.clog;if(!f.isInitialized||!f.container)return;let v=m.target,b=[".console-logger-container",".layui-layer-shade",".loading-container"].join(",");v.closest(b)?f.highZIndex():f.lowZIndex()}))})(),(function(){function i(l,c,h){let u=(function(E){let L=document.createElement("div");L.classList.add("js-tooltip");let N=document.createElement("div");return N.innerHTML=C(E),L.appendChild(N),document.body.appendChild(L),L})(c);u.style.display="block";let p=l.getBoundingClientRect(),g=u.getBoundingClientRect();u.style.display="none";let m=window.innerWidth,f=window.innerHeight,v,b,w=h,S=d(E=>E>=8&&E+g.height<=f-8,"h"),j=d(E=>E>=8&&E+g.width<=m-8,"g"),x=p.left+p.width/2-g.width/2,k=p.top+p.height/2-g.height/2;switch(h){case"top":b=p.top-g.height-0,b<8&&S(p.bottom+0)&&(b=p.bottom+0,w="bottom");break;case"bottom":b=p.bottom+0,b+g.height>f-8&&S(p.top-g.height-0)&&(b=p.top-g.height-0,w="top");break;case"left":v=p.left-g.width-0,v<8&&j(p.right+0)&&(v=p.right+0,w="right");break;case"right":v=p.right+0,v+g.width>m-8&&j(p.left-g.width-0)&&(v=p.left-g.width-0,w="left")}w==="top"||w==="bottom"?(v=x,v<8?v=8:v+g.width>m-8&&(v=m-g.width-8)):(w==="left"||w==="right")&&(b=k,b<8?b=8:b+g.height>f-8&&(b=f-g.height-8)),u.style.left=`${v}px`,u.style.top=`${b}px`,u.classList.add("is-active"),l.tooltipElement=u}d(i,"e"),document.head.insertAdjacentHTML("beforeend",` + `);let i={base:{label:"信息",background:"var(--jhs-status-fav-tint)",borderLeftColor:"var(--jhs-accent)"},warn:{label:"警告",background:"var(--jhs-status-watch-tint)",borderLeftColor:"var(--jhs-status-watch)"},error:{label:"错误",background:"var(--jhs-status-filter-tint)",borderLeftColor:"var(--jhs-status-filter)"},debug:{label:"调试",background:"var(--jhs-surface-2)",borderLeftColor:"var(--jhs-border-strong)"}},n={base:["base","warn","error"],warn:["warn"],error:["error"],debug:["base","warn","error","debug"]},l=t,c="jhs_clog_maximize",h="jhs_clog_expand",u="jhs_clog_filter",g=class g{constructor(){let f=localStorage.getItem(u);this.currentFilter=f&&i[f]?f:"base",this.logs=[],this.isInitialized=!1,this.userScrolledUp=!1}tryInitialize(){return document.readyState!=="loading"&&(this.isInitialized||(this.init(),this.isInitialized=!0),!0)}init(){this.createContainer(),this.bindEvents(),this.checkInitialMaximizeState(),this.checkInitialCollapseState()}createContainer(){this.container=document.createElement("div"),this.container.className="console-logger-container jhs-ui",this.container.style.display="none",this.toggleBtn=document.createElement("button"),this.toggleBtn.type="button",this.toggleBtn.setAttribute("aria-label","展开或收起运行日志"),this.toggleBtn.className="console-logger-toggle collapsed",this.container.appendChild(this.toggleBtn),window.matchMedia?.("(max-width: 767px)").matches&&(this.toggleBtn.hidden=!0,this.toggleBtn.style.display="none"),this.window=document.createElement("div"),this.window.className="console-logger-window collapsed";let f=document.createElement("div");f.className="console-logger-header";let v=document.createElement("div");v.className="console-logger-title",v.textContent="JHS Console";let b=document.createElement("div");b.className="console-logger-controls",this.maximizeBtn=document.createElement("button"),this.maximizeBtn.textContent="",this.maximizeBtn.classList.add("console-logger-maximize-toggle"),b.appendChild(this.maximizeBtn);let w=document.createElement("button");w.textContent="清空",w.addEventListener("click",(()=>this.clear())),b.appendChild(w),f.appendChild(v),f.appendChild(b),this.filtersContainer=document.createElement("div"),this.filtersContainer.className="console-logger-filters",this.filterButtonGroup=document.createElement("div"),this.filterButtonGroup.className="console-logger-filter-group",this.filtersContainer.appendChild(this.filterButtonGroup),this.scrollToBottomBtn=document.createElement("button"),this.scrollToBottomBtn.className="console-logger-scroll-to-bottom",this.scrollToBottomBtn.textContent="到底部",this.filtersContainer.appendChild(this.scrollToBottomBtn),this.content=document.createElement("div"),this.content.className="console-logger-content jhs-scrollbar",this.window.appendChild(f),this.window.appendChild(this.filtersContainer),this.window.appendChild(this.content),this.container.appendChild(this.window),document.body.appendChild(this.container),Object.keys(i).forEach((S=>{let j=document.createElement("button");j.type="button",j.className="jhs-btn console-logger-filter",S===this.currentFilter&&j.classList.add("active"),j.textContent=i[S].label,j.dataset.type=S,j.addEventListener("click",(()=>this.setFilter(S))),this.filterButtonGroup.appendChild(j)}))}bindEvents(){this.toggleBtn.addEventListener("click",(()=>{this.toggleExpandCollapsed()})),this.maximizeBtn.addEventListener("click",(()=>this.toggleMaximize())),this.scrollToBottomBtn.addEventListener("click",(()=>{this.content.scrollTop=this.content.scrollHeight,this.userScrolledUp=!1})),this.content.addEventListener("scroll",(()=>{let f=this.content.scrollHeight-this.content.clientHeight<=this.content.scrollTop+5;this.userScrolledUp=!f})),this.content.addEventListener("wheel",(f=>{let v=this.content.scrollTop===0,b=this.content.scrollHeight-this.content.clientHeight<=this.content.scrollTop+1;(v&&f.deltaY<0||b&&f.deltaY>0)&&(f.preventDefault(),f.stopPropagation())}),{passive:!1})}toggleExpandCollapsed(){let f=this.window.classList.toggle("collapsed");this.toggleBtn.classList.toggle("collapsed"),f?localStorage.setItem(h,"no"):(localStorage.setItem(h,"yes"),this.reRenderAllLogs())}checkInitialCollapseState(){let f=localStorage.getItem(h);f&&f!=="no"?(this.window.classList.toggle("collapsed"),this.toggleBtn.classList.toggle("collapsed"),setTimeout((()=>{this.content.scrollTop=this.content.scrollHeight}),0)):(this.window.classList.add("collapsed"),this.toggleBtn.classList.add("collapsed"))}checkInitialMaximizeState(){localStorage.getItem(c)==="maximized"&&(this.window.classList.add("maximized"),this.maximizeBtn.classList.add("active"))}toggleMaximize(){let f=this.window.classList.toggle("maximized");this.maximizeBtn.classList.toggle("active",f),f?localStorage.setItem(c,"maximized"):localStorage.setItem(c,"minimized"),this.window.classList.contains("collapsed")||(this.content.scrollTop=this.content.scrollHeight)}addLog(f,v="base",...b){return this._appendLog(!1,f,v,...b)}addHtmlLog(f,v="base",...b){return this._appendLog(!0,f,v,...b)}_appendLog(f,v,b="base",...w){let S=this.tryInitialize(),j,k=[];i[b]?(j=b,k=w):(j="base",k=[b,...w]),j=i[j]?j:"base";let x=[v,...k],_="msg",R=[];x.forEach((A=>{if(Object.prototype.toString.call(A)==="[object Error]")R.push(String(A));else if(typeof A=="object"&&A!==null)try{R.push("
"+JSON.stringify(A,null,2)),_="json"}catch{R.push(String(A)),_="msg"}else R.push(String(A))}));let L=R.join(" ");f&&(L=L.replace(/(?:(?:https?|ftp):\/\/|www\.|(?:\/\/))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/gi,(A=>{let O=A.startsWith("http")||A.startsWith("ftp"),U=A.startsWith("//"),q=A.startsWith("www."),Q=A;return U?Q=`http:${A}`:!O&&q&&(Q=`http://${A}`),`${T(A)}`})));let N={message:L,messageType:_,type:j,html:f,timestamp:new Date,id:Date.now()+Math.random()};if(this.logs.push(N),this.logs.length>l){this.logs.shift();let A=this.content.querySelector(".console-logger-entry");A&&A.remove()}S&&this.renderLog(N)}log(...f){let[v,...b]=f;setTimeout((()=>{this.addLog(v,"base",...b)}),0)}html(...f){let[v,...b]=f;setTimeout((()=>{this.addHtmlLog(v,"base",...b)}),0)}htmlDebug(...f){let[v,...b]=f;setTimeout((()=>{this.addHtmlLog(v,"debug",...b)}),0)}error(...f){let[v,...b]=f;console.error(...f),setTimeout((()=>{this.addLog(v,"error",...b)}),0)}warn(...f){let[v,...b]=f;setTimeout((()=>{this.addLog(v,"warn",...b)}),0)}debug(...f){let[v,...b]=f;setTimeout((()=>{this.addLog(v,"debug",...b)}),0)}renderLog(f){if(this.container.style.display==="none"||this.window.classList.contains("collapsed")||!(n[this.currentFilter]||[]).includes(f.type))return;let v=this._createLogElement(f);this.content.appendChild(v),this.window.classList.contains("collapsed")||this.userScrolledUp||(this.content.scrollTop=this.content.scrollHeight)}reRenderAllLogs(){this.container.style.display!=="none"&&(this.window.classList.contains("collapsed")||setTimeout((()=>{if(this.content.innerHTML="",this.logs.length===0)return;let f=n[this.currentFilter]||[],v=document.createDocumentFragment();this.logs.forEach((b=>{if(f.includes(b.type)){let w=this._createLogElement(b);v.appendChild(w)}})),this.content.appendChild(v),this.content.scrollTop=this.content.scrollHeight}),0))}_createLogElement(f){let v=document.createElement("div");v.className="console-logger-entry",v.dataset.type=f.type,v.dataset.id=f.id;let b=i[f.type]||i.base;v.style.borderLeft="3px solid "+b.borderLeftColor,v.style.background=b.background;let w=(f.timestamp instanceof Date?f.timestamp:new Date(f.timestamp)).toTimeString().split(" ")[0],S=document.createElement("span");S.className="console-logger-timestamp",S.textContent=`[${w}]`;let j=document.createElement("span");if(j.className="console-logger-message",j.dataset.type=f.messageType,f.html)j.innerHTML=f.message;else{let k=f.message.replace(//gi,` +`),x=/(?:(?:https?|ftp):\/\/|www\.|(?:\/\/))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/gi,_=0,R;for(;R=x.exec(k);){R.index>_&&j.appendChild(document.createTextNode(k.slice(_,R.index)));let L=R[0],N=L;L.startsWith("//")?N=`http:${L}`:L.startsWith("www.")&&(N=`http://${L}`);let A=document.createElement("a");A.href=N,A.target="_blank",A.textContent=L,j.appendChild(A),_=R.index+R[0].length}_{v.dataset.type===f?v.classList.add("active"):v.classList.remove("active")})),this.reRenderAllLogs())}clear(){this.logs=[],this.content.innerHTML=""}openDialog(){if(!this.tryInitialize()||!this.window||typeof layer>"u")return;let f=document.createElement("div"),v=this.window.parentNode,b=this.window.getAttribute("style");f.className="jhs-ui jhs-logger-dialog",f.style.height="100%",this.window.classList.remove("collapsed","maximized"),Object.assign(this.window.style,{width:"100%",height:"100%",border:"0",borderRadius:"0",boxShadow:"none"}),this.reRenderAllLogs(),layer.open({type:1,title:"JHS 运行日志",content:f.outerHTML,area:utils.getDialogArea("md"),anim:-1,success:d(w=>{$(w).find(".jhs-logger-dialog")[0]?.appendChild(this.window),this.content.scrollTop=this.content.scrollHeight},"success"),end:d(()=>{v?.appendChild(this.window),b==null?this.window.removeAttribute("style"):this.window.setAttribute("style",b),this.window.classList.add("collapsed"),this.toggleBtn.classList.add("collapsed")},"end")})}show(){(this.isInitialized&&this.container||this.tryInitialize()&&this.container)&&(this.container.style.display="",this.reRenderAllLogs())}hide(){this.isInitialized&&this.container&&(this.container.style.display="none")}lowZIndex(){this.isInitialized&&this.container&&(this.container.style.zIndex=String(J.debugLow))}highZIndex(){this.isInitialized&&this.container&&(this.container.style.zIndex=String(J.debug))}};d(g,"o");let p=g;try{unsafeWindow.parent!==unsafeWindow&&unsafeWindow.parent.clog&&typeof unsafeWindow.parent.clog.log=="function"?s=unsafeWindow.parent.clog:s=new p}catch(m){console.error("创建日志控制台出现异常",m),s=new p}(function(){let m=d(()=>window.clog||console,"resolveClog");o.listen(window,"error",(function(f){let v=f.filename,b=f.message;typeof v=="string"&&(v.includes("javdb")||v.includes("javbus"))||m().error(`[全局 Error 异常捕获] ${b} 来源: ${v??"未知"}`)})),o.listen(window,"unhandledrejection",(function(f){let v=m(),b=f.reason,w=b?.message??"";if(["NotAllowedError","AbortError","NotSupportedError"].includes(b?.name)||w.includes("play()")||w.includes("The element has no supported sources"))return v.warn("[全局媒体播放异常] 当前媒体源无法播放",b),void f.preventDefault();if(w.includes("1005")&&w.includes("fc2ppvdb"))return;let S=`[全局 Promise 异常捕获] ${b.message||b}`;v.error(S,b),f.preventDefault()}))})(),o.listen(document,"mousedown",(m=>{let f=window.clog;if(!f.isInitialized||!f.container)return;let v=m.target,b=[".console-logger-container",".layui-layer-shade",".loading-container"].join(",");v.closest(b)?f.highZIndex():f.lowZIndex()}))})(),(function(){function i(l,c,h){let u=(function(R){let L=document.createElement("div");L.classList.add("js-tooltip");let N=document.createElement("div");return N.innerHTML=T(R),L.appendChild(N),document.body.appendChild(L),L})(c);u.style.display="block";let p=l.getBoundingClientRect(),g=u.getBoundingClientRect();u.style.display="none";let m=window.innerWidth,f=window.innerHeight,v,b,w=h,S=d(R=>R>=8&&R+g.height<=f-8,"h"),j=d(R=>R>=8&&R+g.width<=m-8,"g"),k=p.left+p.width/2-g.width/2,x=p.top+p.height/2-g.height/2;switch(h){case"top":b=p.top-g.height-0,b<8&&S(p.bottom+0)&&(b=p.bottom+0,w="bottom");break;case"bottom":b=p.bottom+0,b+g.height>f-8&&S(p.top-g.height-0)&&(b=p.top-g.height-0,w="top");break;case"left":v=p.left-g.width-0,v<8&&j(p.right+0)&&(v=p.right+0,w="right");break;case"right":v=p.right+0,v+g.width>m-8&&j(p.left-g.width-0)&&(v=p.left-g.width-0,w="left")}w==="top"||w==="bottom"?(v=k,v<8?v=8:v+g.width>m-8&&(v=m-g.width-8)):(w==="left"||w==="right")&&(b=x,b<8?b=8:b+g.height>f-8&&(b=f-g.height-8)),u.style.left=`${v}px`,u.style.top=`${b}px`,u.classList.add("is-active"),l.tooltipElement=u}d(i,"e"),document.head.insertAdjacentHTML("beforeend",` - `);let n="[data-tip-top], [data-tip-bottom], [data-tip-left], [data-tip-right], [data-tip]";o.listen(document,"mouseover",(l=>{let c=l.target.closest(n);if(c&&!c.tooltipElement){let h,u="top";if(c.hasAttribute("data-tip-bottom")?(h=c.getAttribute("data-tip-bottom"),u="bottom"):c.hasAttribute("data-tip-left")?(h=c.getAttribute("data-tip-left"),u="left"):c.hasAttribute("data-tip-right")?(h=c.getAttribute("data-tip-right"),u="right"):c.hasAttribute("data-tip-top")?(h=c.getAttribute("data-tip-top"),u="top"):c.hasAttribute("data-tip")&&(h=c.getAttribute("data-tip"),u="top"),!h)return;c.hoverTimeout=setTimeout((()=>{c.matches(":hover")&&!c.tooltipElement&&i(c,h,u)}),50)}})),o.listen(document,"mouseout",(l=>{let c=l.target.closest(n);var h;c&&(c.hoverTimeout&&(clearTimeout(c.hoverTimeout),c.hoverTimeout=null),c.contains(l.relatedTarget)||c.tooltipElement&&((h=c.tooltipElement)&&h.parentNode&&h.remove(),c.tooltipElement=null))}))})();let a=window.loading,r=window.show;return ht=Object.freeze({loading:a,show:r,clog:s}),window.loading=ht.loading,window.show=ht.show,window.clog=ht.clog,ht}d(ol,"initializeLoggerRuntime");function ll(o=window){let e={$:o.jQuery,Tabulator:o.Tabulator,layer:o.layer,md5:o.md5,Toastify:o.Toastify,localforage:o.localforage,Viewer:o.Viewer},t=Object.entries(e).filter(([,s])=>s==null).map(([s])=>s);if(t.length)throw new Error(`Missing userscript vendor runtime: ${t.join(", ")}`);return Object.freeze(e)}d(ll,"getVendorRuntime");var uh=new Set(["star","genre","maker","actress","series","tag","search","director","studio","label"]),ei=class ei{constructor(e=document,t=window.location){this.site="javbus",this.document=e,this.location=t}resolveFirstPageUrl(e){try{let t=new URL(e),s=t.pathname.split("/").filter(Boolean),a=s[s.length-1],r=s[s.length-2];if(s.length>=2&&/^\d+$/.test(a)&&(r==="page"||s.length>=3&&uh.has(s[s.length-3]))){let n=r==="page"?s.slice(0,-2):s.slice(0,-1);t.pathname=n.length?"/"+n.join("/"):"/"}return t.href}catch{return e}}detectRoute(){return this.locateNativeMagnets()?"detail":this.locateListRoot()?"list":"other"}readMovieRef(){let e=this.document.querySelector(".info p span, [data-car-number]")?.textContent?.trim()??null;return e?Object.freeze({carNum:e,url:this.location.href,site:"javbus"}):null}locateListRoot(){return this.document.querySelector(".masonry")}locateListItems(){return[...this.locateListRoot()?.querySelectorAll(":scope > .item, :scope > .movie-box")??[]]}getListContainer(){return this.locateListRoot()?.parentElement??null}getListLayoutContainer(){return this.document.querySelector(".container-fluid .row")}createOwnedListRoot(e=[]){let t=this.document.createElement("div");return t.classList.add("masonry",...e),t}locateDetailRoot(){return this.locateNativeMagnets()?.closest(".container")??this.document.querySelector(".container .row.movie")?.parentElement??null}locateDetailSlots(){let e=this.locateDetailRoot();return Object.freeze({summary:e?.querySelector('[data-jhs-slot="summary-actions"]')??e?.querySelector(".row.movie")??null,resources:this.locateNativeMagnets(),reviews:e?.querySelector('[data-jhs-slot="reviews"]')??this.document.querySelector("#reviews"),related:e?.querySelector('[data-jhs-slot="related"]')})}locateNativeGallery(){return this.document.querySelector("#sample-waterfall, .sample-box")}locateNativeMagnets(){return this.document.querySelector("#magnet-table")}getDetailResourceBoundary(){let e=this.locateNativeMagnets(),t=this.locateDetailRoot();return!t||!e?null:Object.freeze({site:"javbus",hostRoot:t,controller:e,observeRoot:e.parentElement,resourceRoot:e,resourceRegion:[...t.children].find(s=>s===e||s.contains(e))||e,rows:d(()=>[...e.querySelectorAll("tr")].filter(s=>s.querySelector('td a[href^="magnet:"],td a[href^="ed2k:"]')),"rows"),sortSelect:null,getResource:d(s=>s.querySelector('td a[href^="magnet:"],td a[href^="ed2k:"]')?.getAttribute("href")||"","getResource"),getTitleTarget:d(s=>s.querySelector("td:first-child a:first-child"),"getTitleTarget"),hasSubtitleTag:d(s=>[...s.querySelectorAll("td:first-child a")].slice(1).some(a=>a.textContent?.includes("字幕")),"hasSubtitleTag"),getActionTarget(s){let a=[...s.querySelectorAll(".buttons,.actions,.btn-group")].filter(n=>n.closest("td")).at(-1);return a||s.querySelector('td a[href^="magnet:"],td a[href^="ed2k:"]')?.closest("td")||null},actionTargetRequiresWrapper:d(s=>![...s.querySelectorAll(".buttons,.actions,.btn-group")].some(a=>a.closest("td")),"actionTargetRequiresWrapper")})}};d(ei,"JavBusHostAdapter");var _s=ei;var ph=new Set(["ABC","ABP","ADN","ATID","BF","CAWD","DLDSS","DVAJ","FSDSS","HEYZO","HMN","IPX","IPZZ","JUQ","JUL","JUX","MEYD","MIAA","MIDE","MIDV","MIMK","MIRD","NIMA","PRED","RBD","SDDE","SONE","SSIS","SSNI","STARS","URE","VEC","WAAA","WANZ","XVSR"]);function ee(o){if(typeof o!="string")return null;let e=o.trim();if(!e||["undefined","null"].includes(e.toLowerCase()))return null;e=e.normalize("NFKC").replace(/[‐‑‒–—―﹘﹣-]/g,"-").replace(/[\s_]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toUpperCase();let t=e.match(/^([A-Z]{2,8})(\d{2,7})$/);return t&&ph.has(t[1])?`${t[1]}-${t[2]}`:e||null}d(ee,"normalizeMovieCarNum");function cl(o,e="https://javdb.com"){try{return new URL(String(o||""),e).pathname.match(/^\/v\/([^/]+)\/?$/)?.[1]||null}catch{return null}}d(cl,"extractJavDbMovieId");var ti=class ti{constructor(e=document,t=window.location){this.site="javdb",this.document=e,this.location=t}resolveFirstPageUrl(e){try{let t=new URL(e);return t.searchParams.delete("page"),t.href}catch{return e}}detectRoute(){return this.location.pathname.startsWith("/v/")||this.location.pathname.startsWith("/movies/")?"detail":this.location.pathname==="/users/collection_codes"?"owned-detail":["actor-ranking","award-ranking"].includes(this.getPageContext().kind)?"other":this.locateListRoot()?"list":"other"}getPageContext(){return je(this.location)}getTop250FilterContainer(){return this.document.querySelector("section .container")??this.getListContainer()}locateTop250SubtitleCards(){return this.locateListItems()}mountTop250SubtitleControls(e){let t=this.locateListRoot();t?.parentElement?.insertBefore(e,t)}mountExternalFc2Catalog(e){let t=this.getListContainer();if(!t)throw new Error("JavDB 列表容器不可用");t.querySelector(":scope > .box")?.remove(),t.querySelector(":scope > .tool-box")?.remove(),this.mountOwnedListRoot(t,e)}syncTop250SubtitleLinks(e){let t=this.getTop250FilterContainer();if(t)for(let s of t.querySelectorAll('a[href^="/rankings/top"],select[data-url^="/rankings/top"]')){let a=s.matches("select")?"data-url":"href",r=s.getAttribute(a);if(!r)continue;let i=new URL(r,this.location.origin);e==="all"?i.searchParams.delete("jhs_subtitle"):i.searchParams.set("jhs_subtitle",e),s.setAttribute(a,`${i.pathname}${i.search}`)}}readMovieRef(){let e=this.document.querySelector(".panel-block.first-block .value, [data-car-number]")?.textContent?.trim()??null;return e?Object.freeze({carNum:e,url:this.location.href,site:"javdb"}):null}locateListRoot(){return this.document.querySelector(".movie-list")}locateListItems(){return[...this.locateListRoot()?.querySelectorAll(":scope > .item")??[]]}getListContainer(){return this.locateListRoot()?.parentElement??null}getListLayoutContainer(){return this.document.querySelector("section .container")}createOwnedListRoot(e=[]){let t=this.document.createElement("div");return t.classList.add("movie-list","h","cols-4","vcols-8",...e),t}mountOwnedListRoot(e,t){for(let s of[...e.children])s.matches(".movie-list, nav.pagination")&&s.remove();e.append(t)}locateDetailRoot(){return this.document.querySelector(".video-detail")??this.document.querySelector(".movie-panel-info")?.closest(".container")??this.document.querySelector("main")}locateDetailSlots(){let e=this.locateDetailRoot();return Object.freeze({summary:e?.querySelector('[data-jhs-slot="summary-actions"]')??this.document.querySelector(".movie-panel-info"),resources:this.document.querySelector("#magnets-content"),reviews:e?.querySelector('[data-jhs-slot="reviews"]')??this.document.querySelector("#reviews"),related:e?.querySelector('[data-jhs-slot="related"]')})}locateNativeGallery(){return this.document.querySelector(".tile-images, .preview-images")}locateNativeMagnets(){return this.document.querySelector("#magnets-content")}getDetailResourceBoundary(){let e=this.locateNativeMagnets(),t=e?.closest('[data-controller="magnet-sort"]'),s=this.locateDetailRoot();if(!s||!t||!e)return null;let a=[...s.children].find(r=>r===t||r.contains(t))||t;return Object.freeze({site:"javdb",hostRoot:s,controller:t,observeRoot:t,resourceRoot:e,resourceRegion:a,rows:d(()=>[...e.children].filter(r=>r.matches(".item")),"rows"),sortSelect:t.querySelector('select[data-action*="magnet-sort#sort"]'),prepareLayout(){e.setAttribute("data-jhs-magnets","true"),a.setAttribute("data-jhs-host-region","resources");let r=e.closest(".message.video-panel, .video-panel")||t;r.setAttribute("data-jhs-resource-surface","true");let i=e.closest(".message-body");i&&r.contains(i)&&i.setAttribute("data-jhs-resource-body","true");for(let n of e.children){if(!n.matches(".item"))continue;let l=n.querySelector(":scope > .magnet-name"),c=n.querySelector(":scope > .date"),h=n.querySelector(":scope > .buttons");!l||!h||(n.setAttribute("data-jhs-magnet-row","true"),l.setAttribute("data-jhs-magnet-part","info"),c?.setAttribute("data-jhs-magnet-part","date"),h.setAttribute("data-jhs-magnet-part","actions"))}},getResource(r){return r.querySelector('.copy-to-clipboard[data-clipboard-text^="magnet:"]')?.getAttribute("data-clipboard-text")||r.querySelector('.magnet-name a[href^="magnet:"]')?.getAttribute("href")||""},getActionTarget:d(r=>r.querySelector(":scope > .buttons"),"getActionTarget"),actionTargetRequiresWrapper:d(()=>!1,"actionTargetRequiresWrapper"),getTitleTarget:d(r=>r.querySelector(".name"),"getTitleTarget"),hasSubtitleTag:d(()=>!1,"hasSubtitleTag")})}parseActorMovies(e,t){if(typeof e!="string")throw new TypeError("JavDB actor page must be HTML text");let s=new DOMParser().parseFromString(e,"text/html"),a=s.querySelector("title")?.textContent??s.body?.textContent??"";if(/Just a moment|cf-chl-|Cloudflare/i.test(a))throw new TypeError("JavDB actor page is a challenge page");let r=[...s.querySelectorAll(".movie-list .item")];return Object.freeze(r.flatMap(i=>{let n=i.querySelector(".video-title"),l=n?.querySelector("strong")?.textContent?.trim()??"",c=ee(l);if(!c)return[];let h=i.querySelector("img")?.getAttribute("src")??"",u=i.querySelector("a[href]")?.getAttribute("href")??"",p=i.querySelector(".score .value, .score")?.textContent?.trim()??"",g=i.querySelector(".score .count, .meta .count")?.textContent?.trim()??"";return[Object.freeze({carNum:c,title:(n?.textContent??"").replace(l,"").trim(),coverUrl:h?new URL(h,t).href.replace("thumbs","covers"):null,url:u?new URL(u,t).href:null,publishTime:i.querySelector(".meta")?.textContent?.trim()||null,score:Number.parseFloat(p)||0,voteCount:Number.parseInt(g.replace(/[^\d]/g,""))||0})]}))}parseActorCollection(e,t){if(typeof e!="string")throw new TypeError("JavDB actor collection must be HTML text");let s=new DOMParser().parseFromString(e,"text/html"),a=s.querySelector("title")?.textContent??s.body?.textContent??"";if(/Just a moment|cf-chl-|Cloudflare/i.test(a))return Object.freeze({state:"challenge",isEmpty:!1,actors:Object.freeze([]),nextUrl:null});let r=s.querySelector("#actors");if(!r)return Object.freeze({state:"invalid",isEmpty:!1,actors:Object.freeze([]),nextUrl:null});try{let i=[...r.querySelectorAll(".actor-box")],n=i.map(h=>{let u=h.querySelector("a[title][href]"),p=u?.getAttribute("title")??"",g=u?.getAttribute("href")??"",m=u?.querySelector("img")?.getAttribute("src")??"",f=p.split(",").map(w=>w.trim()).filter(Boolean),v=new URL(g,t),b=v.pathname.split("/").filter(Boolean).pop()??"";if(!b||!f.length)throw new TypeError("演员卡身份字段无效");return Object.freeze({starId:b,name:f[0],allName:Object.freeze(f),avatar:m?new URL(m,t).href:null,actressType:u?.querySelector(".info")?.textContent?.trim().includes("無碼")?"uncensored":"censored",lastCheckTime:null,lastUpdateTime:null})}),l=s.querySelector(".pagination-next")?.getAttribute("href"),c=l?new URL(l,t).href:null;return Object.freeze({state:"valid",isEmpty:i.length===0,actors:Object.freeze(n),nextUrl:c})}catch{return Object.freeze({state:"invalid",isEmpty:!1,actors:Object.freeze([]),nextUrl:null})}}};d(ti,"JavDbHostAdapter");var $s=ti;var gh=new Set(["system","feature"]),mh=new Set(["eager","idle","on-command","on-demand"]),fh=new Set(["builtin-public","custom-public","user-local"]),vh=new Set(["bronze","silver"]);function ut(o,e){if(typeof o!="string"||o.trim()==="")throw new TypeError(`${e} must be a non-empty string`)}d(ut,"requireNonEmptyString");function dl(o,e){if(!Array.isArray(o))throw new TypeError(`${e} must be an array`)}d(dl,"requireArray");function Pt(o,e){dl(o,e);let t=o;for(let s of t)ut(s,`${e} item`);if(new Set(t).size!==t.length)throw new TypeError(`${e} cannot contain duplicates`)}d(Pt,"requireUniqueStrings");function si(o,e){dl(o,e);let t=o;if(t.some(s=>typeof s!="symbol"))throw new TypeError(`${e} must contain dependency tokens`);if(new Set(t).size!==t.length)throw new TypeError(`${e} cannot contain duplicate tokens`)}d(si,"requireUniqueTokens");function Re(o){if(ut(o.id,"Feature id"),!gh.has(String(o.kind)))throw new TypeError("Feature kind must be system or feature");if(!mh.has(String(o.startup)))throw new TypeError("Feature startup mode is invalid");for(let e of["sites","routes","contributes","providesCommands"])Pt(o[e],e);if(si(o.requires,"requires"),typeof o.activate!="function")throw new TypeError("Feature activate must be a function");if(typeof o.disableable!="boolean")throw new TypeError("Feature disableable must be explicit");if(o.kind==="system"&&o.disableable!==!1)throw new TypeError("System features cannot be disableable");return Object.freeze({...o})}d(Re,"defineFeature");function hl(o){if(ut(o.id,"Contribution id"),ut(o.featureId,"Contribution featureId"),ut(o.legacyPluginId,"Contribution legacyPluginId"),Pt(o.sites,"sites"),Pt(o.routes,"routes"),Pt(o.surfaces,"surfaces"),si(o.requires,"requires"),typeof o.plugin!="function")throw new TypeError("Contribution plugin must be a class");if(!o.order||typeof o.order!="object")throw new TypeError("Contribution order must be explicit");return Object.freeze({...o,sites:Object.freeze([...o.sites]),routes:Object.freeze([...o.routes]),surfaces:Object.freeze([...o.surfaces]),order:Object.freeze({...o.order})})}d(hl,"defineContribution");function J(o){if(ut(o.id,"Integration id"),!fh.has(String(o.trustClass)))throw new TypeError("Integration trustClass is invalid");if(!vh.has(String(o.quality)))throw new TypeError("Integration quality is invalid");Pt(o.hosts,"hosts"),Pt(o.capabilities,"capabilities"),si(o.requires,"requires");let e=o.hosts,t=o.capabilities;if(e.length===0||t.length===0)throw new TypeError("Integration hosts and capabilities cannot be empty");for(let s of e){let a=String(s);if(a!==a.toLowerCase()||new URL(`https://${a}`).hostname!==a)throw new TypeError(`Integration host is invalid: ${a}`)}if(o.cachePolicy===void 0)throw new TypeError("Integration cachePolicy must be explicit");if(o.cachePolicy!=="none"){if(!o.cachePolicy||typeof o.cachePolicy!="object"||Array.isArray(o.cachePolicy))throw new TypeError("Integration cachePolicy must be none or a capability map");let s=o.cachePolicy,a=t.filter(i=>!Object.hasOwn(s,String(i))),r=Object.keys(s).filter(i=>!t.includes(i));if(a.length||r.length)throw new TypeError(`Integration cachePolicy mismatch (missing: ${a.join(", ")||"none"}; extra: ${r.join(", ")||"none"})`);for(let[i,n]of Object.entries(s))ut(n,`cachePolicy.${i}`)}if(typeof o.createClient!="function"||typeof o.createAdapter!="function")throw new TypeError("Integration client and adapter factories are required");if(o.createHostAdapter!==null&&typeof o.createHostAdapter!="function")throw new TypeError("Integration createHostAdapter must be a function or explicit null");return Object.freeze({...o})}d(J,"defineIntegration");function G(o,e){return Symbol.for(`jhs.${o}.${e}`)}d(G,"createToken");var Y=Object.freeze({navigation:G("port","navigation"),http:G("port","http"),storage:G("port","storage"),dialog:G("port","dialog"),style:G("port","style"),host:G("port","host"),javdbHost:G("port","javdb-host"),javbusHost:G("port","javbus-host")}),y=Object.freeze({diagnostics:G("service","diagnostics"),urlPolicy:G("service","url-policy"),navigation:G("service","navigation"),http:G("service","http"),storage:G("service","storage"),webdav:G("service","webdav"),credential:G("service","credential"),dialog:G("service","dialog"),settings:G("service","settings"),movie:G("service","movie"),actressInfo:G("service","actress-info"),imageSearch:G("service","image-search"),review:G("service","review"),related:G("service","related"),magnet:G("service","magnet"),screenshot:G("service","screenshot"),translation:G("service","translation"),subtitle:G("service","subtitle"),account:G("service","account"),offline:G("service","offline"),cache:G("service","cache"),state:G("service","state"),profile:G("service","profile")}),Qe=Object.freeze({command:G("registry","command"),feature:G("registry","feature"),provider:G("registry","provider"),settings:G("registry","settings"),integration:G("registry","integration")}),ke=Object.freeze({externalDetail:"external-detail-v1"});var ai=class ai{constructor(e){this.hostAdapter=e,this.root=null,this.slots=Object.freeze({}),this.mounted=new Map,this.created=new Set}mount(){return this.root=this.hostAdapter.locateDetailRoot(),this.root&&this.ensureOwnedSlots(),this.slots=Object.freeze({...this.hostAdapter.locateDetailSlots()}),this}ensureOwnedSlots(){if(!this.root)return;let e=this.root.ownerDocument,t=this.root.querySelector(':scope > [data-jhs-slot="summary-actions"]');t||(t=e.createElement("div"),t.className="jhs-detail-owned-slot jhs-detail-owned-slot--summary-actions",t.setAttribute("data-jhs-slot","summary-actions"),this.root.append(t),this.created.add(t));let s=this.root.querySelector(':scope > [data-jhs-slot-group="post-resource"]');s||(s=e.createElement("div"),s.className="jhs-detail-post-resource",s.setAttribute("data-jhs-slot-group","post-resource"),this.root.append(s),this.created.add(s));for(let a of["reviews","related"]){if(s.querySelector(`[data-jhs-slot="${a}"]`))continue;let r=e.createElement("section");r.className=`jhs-detail-owned-slot jhs-detail-owned-slot--${a}`,r.setAttribute("data-jhs-slot",a),s.append(r),this.created.add(r)}}mountPanel(e,t){let s=this.slots[e];return s?(s.append(t),this.mounted.set(e,t),!0):!1}dispose(){for(let e of this.mounted.values())e.remove();for(let e of this.created)e.remove();this.mounted.clear(),this.created.clear(),this.root=null,this.slots=Object.freeze({})}};d(ai,"HostedDetailSurface");var Ts=ai;var ri=class ri{constructor(e){this.hostAdapter=e.hostAdapter,this.scope=e.scope,this.enabledContributions=new Set(e.enabledContributions),this.surface=new Ts(this.hostAdapter),this.movieRef=null}start(){return this.scope.assertActive(),this.surface.mount(),this.movieRef=this.hostAdapter.readMovieRef(),Object.freeze({movieRef:this.movieRef,contributions:[...this.enabledContributions]})}dispose(){this.surface.dispose(),this.scope.dispose()}};d(ri,"DetailController");var As=ri;var ul=Re({id:"detail",kind:"feature",disableable:!0,sites:["javdb","javbus"],routes:["detail","owned-detail"],startup:"eager",requires:[Y.host,y.movie,y.review,y.related,y.magnet,y.screenshot],contributes:["detail.javdb-native","detail.javbus-native","detail.workspace","detail.fc2-owned","detail.fc2-navigation","detail.fc2-lookup","detail.cover-state-actions","detail.page-state-actions","detail.javdb-preview","detail.javbus-images","detail.javbus-preview","detail.reviews","detail.related","detail.native-magnets","detail.external-magnets","detail.screenshot","detail.external-sites"],providesCommands:[],activate:d((o,e)=>{if(e.route==="owned-detail")return{dispose:d(()=>{},"dispose")};let t=new As({hostAdapter:o[Y.host],scope:e.scope,enabledContributions:e.enabledContributions});return t.start(),{dispose:d(()=>t.dispose(),"dispose")}},"activate")});var It=d((o,e,t)=>Re({id:o,kind:"feature",disableable:!0,sites:e,routes:[],startup:"eager",requires:[],contributes:t,providesCommands:[],activate:d(()=>({}),"activate")}),"feature"),pl=Object.freeze([It("list",["javdb","javbus"],["list.core","list.auto-page","list.fold-category","list.actions"]),It("library",["javdb","javbus"],["library.history","library.keyword-filter","library.state-actions","library.blacklist","library.favorite-actresses"]),It("discovery",["javdb","javbus"],["discovery.hit-show","discovery.top250","discovery.new-video","discovery.scheduler"]),It("external-bridge",["javdb","javbus","123pan","javtrailers","subtitlecat"],["external-bridge.translation","external-bridge.115-match","external-bridge.offline","external-bridge.123pan","external-bridge.javtrailers","external-bridge.subtitle"]),It("identity",["javdb","javbus"],["identity.javdb-navigation","identity.javbus-navigation","identity.image-search","identity.actress-info"]),It("compatibility",["javdb","javbus"],["compatibility.enhancements"])]);var pt=null;function gl(o){if(typeof o!="function")throw new TypeError("Settings UI owner must be a function");if(pt&&pt!==o)throw new Error("Settings UI owner is already registered");return pt=o,()=>{pt===o&&(pt=null)}}d(gl,"registerSettingsUiOwner");function ml(o){if(!pt)throw new Error("Settings UI owner is not ready");return pt(o)}d(ml,"openSettingsUi");var fl=Object.freeze([Re({id:"settings",kind:"system",disableable:!1,sites:[],routes:[],startup:"on-command",requires:[y.diagnostics,y.profile],contributes:["settings.core"],providesCommands:["settings.open"],activate:d(()=>({commands:{"settings.open":d(()=>ml(),"settings.open")}}),"activate")}),Re({id:"diagnostics",kind:"system",disableable:!1,sites:[],routes:[],startup:"eager",requires:[y.diagnostics],contributes:[],providesCommands:["diagnostics.export"],activate:d(o=>({commands:{"diagnostics.export":d(()=>o[y.diagnostics].exportSnapshot(),"diagnostics.export")}}),"activate")}),Re({id:"responsive-shell",kind:"system",disableable:!1,sites:[],routes:[],startup:"eager",requires:[y.profile],contributes:["responsive-shell.bottom-bar"],providesCommands:[],activate:d(o=>({profile:o[y.profile].current()}),"activate")}),Re({id:"stats",kind:"system",disableable:!1,sites:["javdb","javbus"],routes:[],startup:"idle",requires:[y.diagnostics],contributes:["stats.dashboard"],providesCommands:[],activate:d(o=>({diagnostics:o[y.diagnostics]}),"activate")})]);var vl=Object.freeze([...fl,ul,...pl]);var bl=Object.freeze({AutoPagePlugin:["ListPagePlugin"],BlacklistPlugin:["TaskPlugin","SettingPlugin","ListPagePlugin"],BusNavBarPlugin:["SearchByImagePlugin"],CompatibilityEnhancementsPlugin:["ListPagePlugin"],CoverButtonPlugin:["ListPagePlugin","ScreenShotPlugin"],DetailPageButtonPlugin:["DetailWorkspacePlugin","MagnetHubPlugin","HighlightMagnetPlugin"],Fc2NavigationPlugin:["Fc2Plugin"],Fc2Plugin:["DetailPageButtonPlugin","MagnetHubPlugin","FilterTitleKeywordPlugin","OtherSitePlugin","Fc2By123AvPlugin","ScreenShotPlugin"],Fc2By123AvPlugin:["ListPagePlugin"],HistoryPlugin:["UnifiedOfflinePlugin","ListPagePlugin","Fc2Plugin"],ListPageButtonPlugin:["NewVideoPlugin","BlacklistPlugin","ListPagePlugin"],ListPagePlugin:["HistoryPlugin","ListPageButtonPlugin","CoverButtonPlugin","AutoPagePlugin","BusImgPlugin","Fc2Plugin"],MobileBottomBarPlugin:["ListPagePlugin","DetailPageButtonPlugin","ListPageButtonPlugin","NewVideoPlugin","BlacklistPlugin","SettingPlugin","HighlightMagnetPlugin","MagnetHubPlugin","HistoryPlugin"],NavBarPlugin:["SearchByImagePlugin"],NewVideoPlugin:["TaskPlugin","SettingPlugin"],PreviewVideoPlugin:["DetailPageButtonPlugin"],SettingPlugin:["CoverButtonPlugin","TaskPlugin","OtherSitePlugin","ListPagePlugin","TranslatePlugin","ActressInfoPlugin","ScreenShotPlugin","NewVideoPlugin","BlacklistPlugin","BusImgPlugin"],StatsPlugin:["NewVideoPlugin","ListPagePlugin"],TaskPlugin:["BlacklistPlugin"],TranslatePlugin:["ListPagePlugin"],UnifiedOfflinePlugin:["OneTwoThreeOfflinePlugin"]});var ii=class ii extends I{constructor(){super(...arguments),this._generation=0}getName(){return"ActressInfoPlugin"}async handle(){let e=this.getRuntimeService("settings"),t=await this.getRuntimeService("scope")(),s=d(a=>{a.detail?.names?.includes("enableLoadActressInfo")&&(e.snapshot().enableLoadActressInfo==="no"?this.unmount():this.mount().catch((i=>clog.error("演员信息重新挂载失败",i))))},"onSettingsChanged");e.addEventListener("settings.changed",s),t.addCleanup((()=>e.removeEventListener("settings.changed",s))),await this.mount()}async mount(){if(this.getRuntimeService("settings").snapshot().enableLoadActressInfo==="no")return;this._generation++;let e=window.location.pathname;e.startsWith("/v/")||e.startsWith("/movies/")?await this.handleDetailPage():e.startsWith("/actors/")&&await this.handleStarPage()}unmount(){this._generation++,$(".actress-info").remove()}isStillActive(e){return e===this._generation&&this.getRuntimeService("settings").snapshot().enableLoadActressInfo!=="no"}async initCss(){return``}async handleDetailPage(){if($(".actress-info").length>0)return;let e=this._generation,t=$(".female"),s=t.prev().map(((n,l)=>$(l).text().trim())).get();if(!s.length)return;let a=[];for(let n of s){let l=null;try{l=await this.searchInfo(n)}catch(h){clog.error("演员资料查询失败",n,h)}if(!this.isStillActive(e))return;let c=$('
');if(l){c.append($("").text(`${n}:`));let h=$("").attr({href:l.url,target:"_blank",rel:"noopener noreferrer"}).addClass("jhs-layout-9813a0dd");h.append($("").addClass("info-tag").text(`${l.birthday} ${l.age}`.trim()),$("").addClass("info-tag").text(`${l.height} ${l.weight}`.trim()),$("").addClass("info-tag").text(`${l.threeSizeText} ${l.braSize}`.trim())),c.append(h)}else{let h=this.getRuntimeService("actressInfo").profileUrl(n);c.append($("").attr({href:h,target:"_blank",rel:"noopener noreferrer"}).append($("").text(`${n}:`)))}a.push(c)}if(!this.isStillActive(e))return;let r=$("strong").filter(((n,l)=>/^(?:演員|演员)\s*:?$/.test($(l).text().trim()))).first().parent(),i=t.first().closest(".panel-block");r.length?r.after(...a):i.after(...a)}async handleStarPage(){if($(".actress-info").length>0)return;let e=this._generation,t=[],s=$(".actor-section-name");s.length&&s.text().trim().split(",").forEach((l=>t.push(l.trim())));let a=$(".section-meta:not(:contains('影片'))");if(a.length&&a.text().trim().split(",").forEach((l=>t.push(l.trim()))),!t.length)return;let r=null;for(let l of t){try{r=await this.searchInfo(l)}catch(c){clog.error("演员资料查询失败",l,c)}if(!this.isStillActive(e))return;if(r)break}let i=$('
');if(!r)i.text("无此相关演员信息");else{let l=$('
'),c=$('
');l.append($("").addClass("jhs-layout-dd5a75f6").text(`出生日期: ${r.birthday}`),$("").addClass("jhs-layout-d4a09a0d").text(`年龄: ${r.age}`),$("").addClass("jhs-layout-d4a09a0d").text(`身高: ${r.height}`)),c.append($("").addClass("jhs-layout-dd5a75f6").text(`体重: ${r.weight}`),$("").addClass("jhs-layout-d4a09a0d").text(`三围: ${r.threeSizeText}`),$("").addClass("jhs-layout-d4a09a0d").text(`罩杯: ${r.braSize}`)),i.append(l,c)}if(!this.isStillActive(e))return;let n=r?$("").addClass("actress-info").attr({href:r.url,target:"_blank",rel:"noopener noreferrer"}).append(i):i.addClass("actress-info");s.parent().append(n)}async searchInfo(e){let t=await this.getRuntimeService("scope")();return this.getRuntimeService("actressInfo").lookup(e,{scope:t})}};d(ii,"ActressInfoPlugin");var Ps=ii;var ni=class ni extends I{constructor(){super(...arguments),P(this,"isUploading",!1)}getName(){return"SearchByImagePlugin"}async initCss(){return` + `}async handleDetailPage(){if($(".actress-info").length>0)return;let e=this._generation,t=$(".female"),s=t.prev().map(((n,l)=>$(l).text().trim())).get();if(!s.length)return;let a=[];for(let n of s){let l=null;try{l=await this.searchInfo(n)}catch(h){clog.error("演员资料查询失败",n,h)}if(!this.isStillActive(e))return;let c=$('
');if(l){c.append($("").text(`${n}:`));let h=$("").attr({href:l.url,target:"_blank",rel:"noopener noreferrer"}).addClass("jhs-layout-9813a0dd");h.append($("").addClass("info-tag").text(`${l.birthday} ${l.age}`.trim()),$("").addClass("info-tag").text(`${l.height} ${l.weight}`.trim()),$("").addClass("info-tag").text(`${l.threeSizeText} ${l.braSize}`.trim())),c.append(h)}else{let h=this.getRuntimeService("actressInfo").profileUrl(n);c.append($("").attr({href:h,target:"_blank",rel:"noopener noreferrer"}).append($("").text(`${n}:`)))}a.push(c)}if(!this.isStillActive(e))return;let r=$("strong").filter(((n,l)=>/^(?:演員|演员)\s*:?$/.test($(l).text().trim()))).first().parent(),i=t.first().closest(".panel-block");r.length?r.after(...a):i.after(...a)}async handleStarPage(){if($(".actress-info").length>0)return;let e=this._generation,t=[],s=$(".actor-section-name");s.length&&s.text().trim().split(",").forEach((l=>t.push(l.trim())));let a=$(".section-meta:not(:contains('影片'))");if(a.length&&a.text().trim().split(",").forEach((l=>t.push(l.trim()))),!t.length)return;let r=null;for(let l of t){try{r=await this.searchInfo(l)}catch(c){clog.error("演员资料查询失败",l,c)}if(!this.isStillActive(e))return;if(r)break}let i=$('
');if(!r)i.text("无此相关演员信息");else{let l=$('
'),c=$('
');l.append($("").addClass("jhs-layout-dd5a75f6").text(`出生日期: ${r.birthday}`),$("").addClass("jhs-layout-d4a09a0d").text(`年龄: ${r.age}`),$("").addClass("jhs-layout-d4a09a0d").text(`身高: ${r.height}`)),c.append($("").addClass("jhs-layout-dd5a75f6").text(`体重: ${r.weight}`),$("").addClass("jhs-layout-d4a09a0d").text(`三围: ${r.threeSizeText}`),$("").addClass("jhs-layout-d4a09a0d").text(`罩杯: ${r.braSize}`)),i.append(l,c)}if(!this.isStillActive(e))return;let n=r?$("").addClass("actress-info").attr({href:r.url,target:"_blank",rel:"noopener noreferrer"}).append(i):i.addClass("actress-info");s.parent().append(n)}async searchInfo(e){let t=await this.getRuntimeService("scope")();return this.getRuntimeService("actressInfo").lookup(e,{scope:t})}};d(ni,"ActressInfoPlugin");var Ps=ni;var oi=class oi extends I{constructor(){super(...arguments),P(this,"isUploading",!1)}getName(){return"SearchByImagePlugin"}async initCss(){return` - `}d(zl,"buildSettingCss");async function xh(o=null,e){if($("#verticalImgStyle").remove(),(e===void 0?await storageManager.getSetting("enableVerticalModel",ne):e)===R){let s="100% 50% !important";window.location.pathname==="/tags/fc2"&&new URLSearchParams(window.location.search).get("jhs_source")==="123av"&&(s="50% 50% !important");let a=` + `}d(Fl,"buildSettingCss");async function kh(o=null,e){if($("#verticalImgStyle").remove(),(e===void 0?await storageManager.getSetting("enableVerticalModel",ne):e)===E){let s="100% 50% !important";window.location.pathname==="/tags/fc2"&&new URLSearchParams(window.location.search).get("jhs_source")==="123av"&&(s="50% 50% !important");let a=` .cover { aspect-ratio: 3 / 4.26; overflow: hidden !important; @@ -2569,7 +2569,7 @@ object-fit: contain !important; object-position: top; } - `).appendTo("head")}d(xh,"applyImageMode");async function fi(o={},{busImgPlugin:e=null,hostAdapter:t=null}={}){let s=o.enableVerticalModel===void 0?ne:o.enableVerticalModel;await xh(e,s);let a=globalThis.utils?.isMobileMode?.()??!1,r=a?1:Number(o.containerColumns??5)||5,i=a?100:Number(o.containerWidth??100)||100;if(B&&e?.logImageHeightsByRow&&await e.logImageHeightsByRow({vertical:s,columns:r}),t){let n=t.locateListRoot?.();n&&(n.style.gridTemplateColumns=`repeat(${r}, minmax(0, 1fr))`);let l=t.getListLayoutContainer?.();l&&(l.style.minWidth=`${i}%`)}}d(fi,"applyLayoutFromSettings");var vi=new WeakMap;function wi(o){let e=vi.get(o);return e||(e=new bi(o),vi.set(o,e)),e}d(wi,"getSettingBindingHub");function Fl({root:o,selector:e,key:t,getValue:s,setValue:a,fallback:r=void 0,label:i=t,settings:n,onChange:l=null}){let c=wi(n),h=o.find(e);if(!h.length)return null;let u={setValue(p,g){p===t&&a(g)},dispose(){h.off(".jhsSettingBinding"),c._dropBinding(u)}};return c.bindings.add(u),h.off(".jhsSettingBinding").on("change.jhsSettingBinding",()=>{let p=s();l?.(t,p),c.userChanged(t,p,r,i)}),u.setValue(t,c.desiredValue(t,n.snapshot()[t]??r)),{sync(p){Object.prototype.hasOwnProperty.call(p,t)&&a(p[t])},flush:d(p=>c.flush(p),"flush"),dispose:d(()=>u.dispose(),"dispose")}}d(Fl,"bindSettingControl");function Ve({settings:o,key:e,fallback:t=void 0,apply:s,onError:a=d(()=>{},"onError")}){let r=0;return async i=>{let n=++r;s(i);try{await o.set(e,i)}catch(l){n===r&&(s(o.snapshot()[e]??t),a(l))}}}d(Ve,"createLatestSettingWriter");var yi=class yi{constructor(e){this.settings=e,this.bindings=new Set,this.pending=new Map,this.revision=0,this._onSettingsChanged=this._onSettingsChanged.bind(this),this.settings.addEventListener("settings.changed",this._onSettingsChanged)}_onSettingsChanged(e){let t=e.detail||{},s=t.snapshot??this.settings.snapshot(),a=Array.isArray(t.names)?t.names:Object.keys(s);for(let r of a){let i=this.pending.get(r);this.syncAll(r,i?i.value:s[r])}}syncAll(e,t){for(let s of this.bindings)s.setValue(e,t)}desiredValue(e,t){let s=this.pending.get(e);return s?s.value:t}userChanged(e,t,s,a){this.syncAll(e,t);let i={token:++this.revision,value:t,promise:Promise.resolve()},n=this.settings.set(e,t).then(()=>{this.pending.get(e)===i&&(this.pending.delete(e),this._maybeDispose())},l=>{if(this.pending.get(e)===i){this.pending.delete(e),i.error=l;let c=this.settings.snapshot()[e]??s;this.syncAll(e,c),this._maybeDispose(),typeof globalThis.show?.error=="function"?globalThis.show.error(`${a||e}保存失败,已恢复原设置`):typeof globalThis.clog?.error=="function"&&globalThis.clog.error(`${a||e}保存失败,已恢复原设置`,l)}});return i.promise=n,this.pending.set(e,i),n}async flush({throwOnFailure:e=!1}={}){let t=[...this.pending.values()];if(await Promise.all(t.map(s=>s.promise)),await this.settings.waitForIdle(),e){let s=t.filter(a=>a.error).map(a=>a.error);if(s.length>0){let a=new Error("部分实时设置保存失败");throw a.cause=s[0],a.liveSettingFailures=s,a}}}_dropBinding(e){this.bindings.delete(e),this._maybeDispose()}_maybeDispose(){this.bindings.size===0&&this.pending.size===0&&(this.settings.removeEventListener("settings.changed",this._onSettingsChanged),vi.delete(this.settings))}};d(yi,"SettingBindingHub");var bi=yi;function ji(o,e){return be(e,!1)}d(ji,"normalizeBooleanValue");function Vl(o,e={}){let t=globalThis.$,s=e.value??o.defaultValue,a=e.onChange??null,r;if(o.type==="boolean")return r=t('').prop("checked",ji(o.key,s)),r.on("change",()=>{a?.(r.is(":checked")?"yes":"no")}),{root:r,getValue:d(()=>r.is(":checked")?"yes":"no","getValue"),setValue:d(i=>r.prop("checked",ji(o.key,i)),"setValue")};if(o.type==="select"){let i=Array.isArray(o.options)?o.options:[];return r=t(''),i.forEach(n=>{let l=n&&typeof n=="object"?n:{value:n,label:String(n)};r.append(t("").attr("value",l.value).text(l.label??String(l.value)))}),r.val(String(s??"")),r.on("change",()=>a?.(r.val())),{root:r,getValue:d(()=>r.val(),"getValue"),setValue:d(n=>r.val(String(n??"")),"setValue")}}return o.type==="number"?(r=t('').val(s==null?"":String(s)),r.on("change",()=>a?.(Number(r.val())||0)),{root:r,getValue:d(()=>Number(r.val())||0,"getValue"),setValue:d(i=>r.val(i==null?"":String(i)),"setValue")}):(r=t('').val(s==null?"":String(s)),r.on("change",()=>a?.(r.val())),{root:r,getValue:d(()=>r.val(),"getValue"),setValue:d(i=>r.val(i==null?"":String(i)),"setValue")})}d(Vl,"renderSettingControl");function Bs(o,e={}){let t=globalThis.$,s=Vl(o,{value:e.value,onChange:e.onChange}),a=t('').append(t('').text(o.label)).append(t('').text(o.description||"")),r=t('').append(s.root);return{row:t('').attr("data-jhs-setting",o.key).attr("data-jhs-setting-effect",o.effect||"live").toggleClass("jhs-setting-row--indent",o.indent===!0).append(a,r),root:s.root,getValue:s.getValue,setValue:s.setValue}}d(Bs,"renderSettingRow");function Hl(o,e={}){let t=globalThis.$,s=t('
');for(let a of o.list({surfaces:["quick"],disabledContributions:e.disabledContributions})){let{row:r}=Bs(a);s.append(r)}return s}d(Hl,"buildQuickSettingsHtml");function ts(o,e,{settings:t,onChanged:s=null}){let a=wi(t),r=new Si(o,e,{settings:t,hub:a,onChanged:s});return{sync:d(i=>r.sync(i),"sync"),flush:d(i=>a.flush(i),"flush"),dispose:d(()=>r.dispose(),"dispose"),setters:r.setters}}d(ts,"bindSettingRows");var xi=class xi{constructor(e,t,{settings:s,hub:a,onChanged:r=null}){this.root=e,this.settings=s,this.hub=a,this.onChanged=r,this.setters={},this.controls=new Map,a.bindings.add(this);for(let i of t)this._bindDescriptor(i)}_bindDescriptor(e){let t=e.key,s=this.root.find(`[data-jhs-setting="${t}"]`).first();if(!s.length)return;let a=s.find(".jhs-setting-row__control"),r=a.children().first();if(!r.length){let h=Vl(e);a.append(h.root),r=h.root}let i=e.type||(r.is("select")?"select":r.is('input[type="checkbox"]')?"boolean":r.is('input[type="number"]')?"number":"text"),n=kh(i,r),l=Ch(i,r),c=e.defaultValue;r.off(".jhsSettingBinding").on("change.jhsSettingBinding",()=>{let h=l(),u=typeof e.normalize=="function"?e.normalize(h):h;n(u),this.onChanged?.(t,u),(e.effect||"live")==="live"&&this.hub.userChanged(t,u,c,e.label||t)}),this.controls.set(t,{element:r,setValue:n}),this.setters[t]=n,this.setValue(t,this.hub.desiredValue(t,this.settings.snapshot()[t]??c))}setValue(e,t){let s=this.controls.get(e);s&&s.setValue(t)}sync(e){for(let t of this.controls.keys()){let s=Object.prototype.hasOwnProperty.call(e,t)?e[t]:this.settings.snapshot()[t];this.setValue(t,s)}}dispose(){for(let e of this.controls.values())e.element.off(".jhsSettingBinding");this.hub._dropBinding(this)}};d(xi,"RowBinding");var Si=xi;function kh(o,e){return o==="boolean"?t=>e.prop("checked",ji("",t)):o==="select"?t=>{e.val(String(t??"")),K.refresh(e)}:o==="number"?t=>e.val(t==null?"":String(t)):t=>e.val(t==null?"":String(t))}d(kh,"makeSetValue");function Ch(o,e){return o==="boolean"?()=>e.is(":checked")?"yes":"no":o==="select"?()=>e.val():o==="number"?()=>{let t=e.val();if(t==null||String(t).trim()==="")return Number.NaN;let s=Number(t);return Number.isFinite(s)?s:Number.NaN}:()=>e.val()}d(Ch,"makeGetValue");var ki=Object.freeze(["videoQuality","reviewCount","tagPosition","waitCheckCount","highlightedTagNumber","highlightedTagColor","checkConcurrencyCount","checkRequestSleep","enableCheckBlacklist","checkBlacklist_intervalTime","checkBlacklist_ruleTime","enableCheckFavoriteActress","checkFavoriteActress_IntervalTime","enableCheckNewVideo","checkNewVideo_intervalTime","checkNewVideo_ruleTime","httpTimeout","httpRetryCount","circuitBreakerThreshold","circuitBreakerCooldown","clogMsgCount","webDavUrl","webDavUsername","webDavPassword","missAvUrl","jableUrl","avgleUrl","javTrailersUrl","av123Url","javDbUrl","javBusUrl","supJavUrl","enableTitleSelectFilter","enableFavoriteActresses","enableSaveActressCarInfo","autoRemoveNewVideoMarkAfterBrowse"]),_h=Object.freeze({videoQuality:"#videoQuality",reviewCount:"#reviewCount",tagPosition:"#tagPosition",waitCheckCount:"#waitCheckCount",highlightedTagNumber:"#highlightedTagNumber",highlightedTagColor:"#highlightedTagColor",checkConcurrencyCount:"#checkConcurrencyCount",checkRequestSleep:"#checkRequestSleep",enableCheckBlacklist:"#enableCheckBlacklist",checkBlacklist_intervalTime:"#checkBlacklist_intervalTime",checkBlacklist_ruleTime:"#checkBlacklist_ruleTime",enableCheckFavoriteActress:"#enableCheckFavoriteActress",checkFavoriteActress_IntervalTime:"#checkFavoriteActress_IntervalTime",enableCheckNewVideo:"#enableCheckNewVideo",checkNewVideo_intervalTime:"#checkNewVideo_intervalTime",checkNewVideo_ruleTime:"#checkNewVideo_ruleTime",httpTimeout:"#httpTimeout",httpRetryCount:"#httpRetryCount",circuitBreakerThreshold:"#circuitBreakerThreshold",circuitBreakerCooldown:"#circuitBreakerCooldownSec",clogMsgCount:"#clogMsgCount",webDavUrl:"#webDavUrl",webDavUsername:"#webDavUsername",webDavPassword:"#webDavPassword",missAvUrl:"#missAvUrl",jableUrl:"#jableUrl",avgleUrl:"#avgleUrl",javTrailersUrl:"#javTrailersUrl",av123Url:"#av123Url",javDbUrl:"#javDbUrl",javBusUrl:"#javBusUrl",supJavUrl:"#supJavUrl",enableTitleSelectFilter:"#enableTitleSelectFilter",enableFavoriteActresses:"#enableFavoriteActresses",enableSaveActressCarInfo:"#enableSaveActressCarInfo",autoRemoveNewVideoMarkAfterBrowse:"#autoRemoveNewVideoMarkAfterBrowse"});function $h(o){let e=new Set;o.data("jhsDirtyManualKeys",e);for(let t of ki){let s=_h[t];s&&o.find(s).off(".jhsDirty").on("change.jhsDirty",()=>e.add(t))}}d($h,"bindManualDirtyTracking");function Jl(o){return o?globalThis.$(o):globalThis.$(document)}d(Jl,"formRoot");async function Wl(o,e=null){let t=Jl(e),s=o.settings.snapshot();t.find("#videoQuality").val(s.videoQuality),t.find("#reviewCount").val(s.reviewCount||20),t.find("#tagPosition").val(s.tagPosition||"rightTop"),t.find("#autoRemoveNewVideoMarkAfterBrowse").prop("checked",!!s.autoRemoveNewVideoMarkAfterBrowse&&s.autoRemoveNewVideoMarkAfterBrowse===R),t.find("#waitCheckCount").val(s.waitCheckCount||5),t.find("#checkConcurrencyCount").val(ae(s.checkConcurrencyCount,2,{min:2,max:5})),t.find("#checkRequestSleep").val(ae(s.checkRequestSleep,100,{min:0,max:3e3})),t.find("#enableCheckBlacklist").val(s.enableCheckBlacklist||R),t.find("#checkBlacklist_intervalTime").val(s.checkBlacklist_intervalTime||12),t.find("#checkBlacklist_ruleTime").val(ae(s.checkBlacklist_ruleTime,8760,{min:0})),t.find("#enableCheckFavoriteActress").val(s.enableCheckFavoriteActress||R),t.find("#checkFavoriteActress_IntervalTime").val(s.checkFavoriteActress_IntervalTime||24),t.find("#enableCheckNewVideo").val(s.enableCheckNewVideo||R),t.find("#checkNewVideo_intervalTime").val(s.checkNewVideo_intervalTime||12),t.find("#checkNewVideo_ruleTime").val(ae(s.checkNewVideo_ruleTime,8760,{min:0}));let a=s.highlightedTagNumber||1,r=s.highlightedTagColor||"#ce2222";t.find("#highlightedTagNumber").val(s.highlightedTagNumber||1),t.find("#highlightedTagColor").val(s.highlightedTagColor||"#ce2222"),t.find("#highlightedTagLabel").css("border",`${a}px solid ${r}`),t.find("#clogMsgCount").val(s.clogMsgCount||2e3),t.find("#httpTimeout").val(s.httpTimeout||5e3),t.find("#httpRetryCount").val(s.httpRetryCount||3),t.find("#webDavUrl").val(s.webDavUrl||""),t.find("#webDavUsername").val(s.webDavUsername||"");let i=o.webdav,n=i?.getProfile?await i.getProfile():{url:s.webDavUrl,username:s.webDavUsername,password:""};t.find("#webDavUrl").val(n.url||""),t.find("#webDavUsername").val(n.username||""),t.find("#webDavPassword").val(n.password||""),t.find("#enableTitleSelectFilter").prop("checked",!s.enableTitleSelectFilter||s.enableTitleSelectFilter===R),t.find("#enableFavoriteActresses").prop("checked",!s.enableFavoriteActresses||s.enableFavoriteActresses===R),t.find("#enableSaveActressCarInfo").prop("checked",!!s.enableSaveActressCarInfo&&s.enableSaveActressCarInfo===R);let l=o.movie;t.find("#missAvUrl").val(l.externalSiteOrigin("missAvBtn",s)),t.find("#jableUrl").val(l.externalSiteOrigin("jableBtn",s)),t.find("#avgleUrl").val(l.externalSiteOrigin("avgleBtn",s)),t.find("#javTrailersUrl").val(l.externalSiteOrigin("javTrailersBtn",s)),t.find("#av123Url").val(l.providerOrigin("av123")||""),t.find("#javDbUrl").val(l.externalSiteOrigin("javDbBtn",s)),t.find("#javBusUrl").val(l.externalSiteOrigin("javBusBtn",s)),t.find("#supJavUrl").val(l.externalSiteOrigin("supJavBtn",s));let c=await storageManager.getReviewFilterKeywordList(),h=await storageManager.getTitleFilterKeyword();["#reviewKeywordContainer","#filterKeywordContainer"].forEach(u=>{t.find(`${u} .tag-box`).empty(),t.find(`${u} .add-tag-btn`).off(".jhsKeywordBind"),t.find(`${u} .keyword-input`).off(".jhsKeywordBind")}),c&&c.forEach(u=>{Ci("#reviewKeywordContainer",u,t)}),h&&h.forEach(u=>{Ci("#filterKeywordContainer",u,t)}),["#reviewKeywordContainer","#filterKeywordContainer"].forEach(u=>{t.find(`${u} .add-tag-btn`).on("click.jhsKeywordBind",(p=>ql(p,u,t))),t.find(`${u} .keyword-input`).on("keypress.jhsKeywordBind",(p=>{p.key==="Enter"&&ql(p,u,t)}))}),$h(t),Ah(t),Th(t,o.busImg,o.host,o.settings)}d(Wl,"loadSettingForm");function Th(o,e,t,s){o.find("#containerColumns").off(".jhsSetting").on("input.jhsSetting",(()=>{ss(o,t,"containerColumns",o.find("#containerColumns").val())})),o.find("#containerWidth").off(".jhsSetting").on("input.jhsSetting",(a=>{ss(o,t,"containerWidth",parseInt($(a.target).val())+70)}))}d(Th,"bindLayoutRangeEvents");function ss(o,e,t,s){if(t==="containerColumns"){let n=Math.min(10,Math.max(2,Math.round(Number(s)||5)));o.find("#containerColumns").val(String(n)),o.find("#showContainerColumns").text(String(n));let l=e?.locateListRoot?.();l&&(l.style.gridTemplateColumns=`repeat(${n}, minmax(0, 1fr))`);return}let a=Math.min(100,Math.max(70,Math.round(Number(s)||100))),r=`${a}%`;o.find("#containerWidth").val(String(a-70)),o.find("#showContainerWidth").text(r);let i=e?.getListLayoutContainer?.();i&&(i.style.minWidth=r)}d(ss,"applyLayoutRangeValue");function et(o){let e=$(o);e.data("jhsQuickSettingBinding")?.dispose?.(),e.removeData("jhsQuickSettingBinding"),e.empty().hide()}d(et,"disposeQuickSettingHost");async function Os(o,e,t,s){let a=$(s);if(!a.length)throw new Error("Quick setting root is required");let r=o.settingsRegistry;if(!r)return;let i=r.list({surfaces:["quick"]}),n=ts(a,i,{settings:o.settings});a.data("jhsQuickSettingBinding",n),a.find("#moreBtn").off(".jhsQuickSetting").on("click.jhsQuickSetting",(async l=>{l.preventDefault(),l.stopPropagation(),await a.data("jhsQuickSettingBinding")?.flush?.(),et(a),await t("base-panel")}))}d(Os,"initQuickSettingForm");async function Kl(o,e=null){let t=Jl(e),s=t.data("jhsDirtyManualKeys")||null,a=null,r=null;if(!s||s.has("webDavUrl")){if(a=String(t.find("#webDavUrl").val()||"").trim(),a)try{let g=new URL(a);if(!["http:","https:"].includes(g.protocol))throw new Error("protocol");r=g.origin}catch{throw new Error("WebDAV 地址必须是有效的 HTTP/HTTPS URL")}let p=new Set(Array.isArray(o.settings.snapshot().trustedLocalOrigins)?o.settings.snapshot().trustedLocalOrigins:[]);if(r&&!p.has(r)&&!await new Promise(m=>utils.q(null,`仅授权 WebDAV 精确来源:${r},是否继续?`,()=>m(!0),()=>m(!1))))return{canceled:!0}}(!s||["webDavUrl","webDavUsername","webDavPassword"].some(p=>s.has(p)))&&o.webdav?.saveProfile&&await o.webdav.saveProfile({...!s||s.has("webDavUrl")?{url:String(t.find("#webDavUrl").val()||"").trim()}:{},...!s||s.has("webDavUsername")?{username:String(t.find("#webDavUsername").val()||"")}:{},...!s||s.has("webDavPassword")?{password:String(t.find("#webDavPassword").val()||"")}:{}});let n=await Ph(t,s);await o.settings.update(p=>{if(Object.assign(p,n),r){let g=new Set(Array.isArray(p.trustedLocalOrigins)?p.trustedLocalOrigins:[]);g.add(r),p.trustedLocalOrigins=[...g]}}),t.data("jhsDirtyManualKeys",new Set);let l=[],c=t.data("jhsDirtyReviewKeywords")===!0,h=t.data("jhsDirtyTitleKeywords")===!0;if(c)try{let p=[...new Set(t.find("#reviewKeywordContainer .keyword-label").toArray().map(g=>$(g).text().replaceAll("×","").replace(/[\r\n]+/g," ").replace(/\s{2,}/g," ").trim()).filter(Boolean))];await storageManager.saveReviewFilterKeyword(p)}catch(p){l.push(p)}if(h)try{let p=[...new Set(t.find("#filterKeywordContainer .keyword-label").toArray().map(g=>$(g).text().replaceAll("×","").replace(/[\r\n]+/g," ").replace(/\s{2,}/g," ").trim()).filter(Boolean))];await storageManager.saveTitleFilterKeyword(p)}catch(p){l.push(p)}if(l.length){let p=new Error("部分设置保存失败,请重试");throw p.partialFailure=!0,p.cause=l[0],p}t.data("jhsDirtyReviewKeywords",!1),t.data("jhsDirtyTitleKeywords",!1);let u=[["filter rules",async()=>{if(!V)throw new Error("EventBus 尚未初始化");await V.emit("filter-rules-changed",{scope:"title-keyword"})}],["new-video status",()=>o.newVideo?.resetBtnTip?.()],["blacklist status",()=>o.blacklist?.resetBtnTip?.()],["blacklist table",()=>o.blacklist?.reloadTable?.()]];for(let[p,g]of u)try{await g()}catch(m){typeof globalThis.clog?.error=="function"&&globalThis.clog.error(`设置保存后 ${p} 刷新失败(已忽略)`,m)}return{ok:!0}}d(Kl,"saveSettingForm");function Ah(o){o.data("jhsDirtyReviewKeywords",!1),o.data("jhsDirtyTitleKeywords",!1)}d(Ah,"bindKeywordDirtyTracking");async function Ph(o,e=null){let t=d((n,l,c,h)=>Math.min(h,Math.max(c,Number(n)||l)),"clamp"),s=d((n,{allowLocalHttp:l=!1}={})=>{let c=String(n||"").trim().replace(/\/$/,"");if(!c)return"";let h;try{h=new URL(c)}catch{throw new TypeError(`无效 URL:${c}`)}let u=["localhost","127.0.0.1","[::1]"].includes(h.hostname);if(h.protocol!=="https:"&&!(l&&u&&h.protocol==="http:"))throw new TypeError(`仅允许 HTTPS URL${l?"(本机地址可使用 HTTP)":""}:${c}`);return h.href.replace(/\/$/,"")},"configuredUrl"),a={videoQuality:d(()=>o.find("#videoQuality").val(),"videoQuality"),reviewCount:d(()=>o.find("#reviewCount").val(),"reviewCount"),tagPosition:d(()=>o.find("#tagPosition").val(),"tagPosition"),autoRemoveNewVideoMarkAfterBrowse:d(()=>o.find("#autoRemoveNewVideoMarkAfterBrowse").is(":checked")?R:ne,"autoRemoveNewVideoMarkAfterBrowse"),waitCheckCount:d(()=>o.find("#waitCheckCount").val(),"waitCheckCount"),highlightedTagNumber:d(()=>o.find("#highlightedTagNumber").val(),"highlightedTagNumber"),highlightedTagColor:d(()=>o.find("#highlightedTagColor").val(),"highlightedTagColor"),checkConcurrencyCount:d(()=>o.find("#checkConcurrencyCount").val(),"checkConcurrencyCount"),checkRequestSleep:d(()=>o.find("#checkRequestSleep").val(),"checkRequestSleep"),enableCheckBlacklist:d(()=>o.find("#enableCheckBlacklist").val(),"enableCheckBlacklist"),checkBlacklist_intervalTime:d(()=>o.find("#checkBlacklist_intervalTime").val(),"checkBlacklist_intervalTime"),checkBlacklist_ruleTime:d(()=>o.find("#checkBlacklist_ruleTime").val(),"checkBlacklist_ruleTime"),enableCheckFavoriteActress:d(()=>o.find("#enableCheckFavoriteActress").val(),"enableCheckFavoriteActress"),checkFavoriteActress_IntervalTime:d(()=>o.find("#checkFavoriteActress_IntervalTime").val(),"checkFavoriteActress_IntervalTime"),enableCheckNewVideo:d(()=>o.find("#enableCheckNewVideo").val(),"enableCheckNewVideo"),checkNewVideo_intervalTime:d(()=>o.find("#checkNewVideo_intervalTime").val(),"checkNewVideo_intervalTime"),checkNewVideo_ruleTime:d(()=>o.find("#checkNewVideo_ruleTime").val(),"checkNewVideo_ruleTime"),httpTimeout:d(()=>t(o.find("#httpTimeout").val(),5e3,1e3,12e4),"httpTimeout"),httpRetryCount:d(()=>t(o.find("#httpRetryCount").val(),3,1,10),"httpRetryCount"),circuitBreakerThreshold:d(()=>t(o.find("#circuitBreakerThreshold").val(),3,1,20),"circuitBreakerThreshold"),circuitBreakerCooldown:d(()=>t(Number(o.find("#circuitBreakerCooldownSec").val())*1e3,6e4,1e3,36e5),"circuitBreakerCooldown"),clogMsgCount:d(()=>o.find("#clogMsgCount").val(),"clogMsgCount"),webDavUrl:d(()=>s(o.find("#webDavUrl").val(),{allowLocalHttp:!0}),"webDavUrl"),webDavUsername:d(()=>String(o.find("#webDavUsername").val()||""),"webDavUsername"),missAvUrl:d(()=>s(o.find("#missAvUrl").val()),"missAvUrl"),jableUrl:d(()=>s(o.find("#jableUrl").val()),"jableUrl"),avgleUrl:d(()=>s(o.find("#avgleUrl").val()),"avgleUrl"),javTrailersUrl:d(()=>s(o.find("#javTrailersUrl").val()),"javTrailersUrl"),av123Url:d(()=>s(o.find("#av123Url").val()),"av123Url"),javDbUrl:d(()=>s(o.find("#javDbUrl").val()),"javDbUrl"),javBusUrl:d(()=>s(o.find("#javBusUrl").val()),"javBusUrl"),supJavUrl:d(()=>s(o.find("#supJavUrl").val()),"supJavUrl"),enableTitleSelectFilter:d(()=>o.find("#enableTitleSelectFilter").is(":checked")?R:ne,"enableTitleSelectFilter"),enableFavoriteActresses:d(()=>o.find("#enableFavoriteActresses").is(":checked")?R:ne,"enableFavoriteActresses"),enableSaveActressCarInfo:d(()=>o.find("#enableSaveActressCarInfo").is(":checked")?R:ne,"enableSaveActressCarInfo")},r=e instanceof Set?ki.filter(n=>e.has(n)).filter(n=>!["webDavUrl","webDavUsername","webDavPassword"].includes(n)):ki.filter(n=>!["webDavUrl","webDavUsername","webDavPassword"].includes(n)),i={};for(let n of r){let l=a[n];l&&(i[n]=await l())}return i}d(Ph,"collectManualSettingPatch");function Ci(o,e,t){let s=t.find(`${o} .tag-box`),a=String(e),r;/^[a-z]{2,}-/i.test(a)&&M?r=$("").addClass("keyword-label keyword-label--link").attr("data-keyword",a).attr("href",`/video_codes/${a.replace("-","")}`).attr("target","_blank"):r=$("
").addClass("keyword-label").attr("data-keyword",a),r.append(document.createTextNode(a)),r.append($("").addClass("keyword-remove").text("×"));let i=o==="#reviewKeywordContainer"?"jhsDirtyReviewKeywords":"jhsDirtyTitleKeywords";r.find(".keyword-remove").click((n=>{n.stopPropagation(),n.preventDefault();let l=$(n.currentTarget),c=l.closest(".keyword-label").attr("data-keyword").split(" ")[0];utils.q(n,`是否移除屏蔽词 ${C(c)}?`,(async()=>{l.parent().remove(),t.data(i,!0)}))})),s.append(r)}d(Ci,"addLabelTag");function ql(o,e,t){let s=t.find(`${e} .keyword-input`),a=s.val().trim();if(!a)return;t.find(`${e} .keyword-label`).toArray().some((i=>$(i).text().replaceAll("×","").trim()===a))||Ci(e,a,t),s.val(""),t.data(e==="#reviewKeywordContainer"?"jhsDirtyReviewKeywords":"jhsDirtyTitleKeywords",!0)}d(ql,"addKeyword");function Gl(){let o={SettingPlugin:["设置中心","core"],StatsPlugin:["统计中心","core"],MobileBottomBarPlugin:["工具栏与移动操作","core"],ListPagePlugin:["列表状态处理","list"],NavBarPlugin:["JavDB 导航","list"],BusNavBarPlugin:["JavBus 导航","list"],ListPageButtonPlugin:["列表操作","list"],HighlightMagnetPlugin:["磁力标记","list"],FoldCategoryPlugin:["分类折叠","list"],AutoPagePlugin:["自动翻页","list"],HitShowPlugin:["热播榜单","list"],TOP250Plugin:["TOP 250","list"],DetailPagePlugin:["JavDB 详情页","detail"],BusDetailPagePlugin:["JavBus 详情页","detail"],DetailPageButtonPlugin:["详情操作","detail"],ReviewPlugin:["评论","detail"],RelatedPlugin:["相关影片","detail"],TranslatePlugin:["标题翻译","detail"],WantAndWatchedVideosPlugin:["想看与看过","detail"],CoverButtonPlugin:["封面快捷操作","media"],PreviewVideoPlugin:["JavDB 预览视频","media"],BusPreviewVideoPlugin:["JavBus 预览视频","media"],ScreenShotPlugin:["剧照","media"],BusImgPlugin:["JavBus 图片适配","media"],ActressInfoPlugin:["演员资料","media"],SearchByImagePlugin:["以图搜图","media"],HistoryPlugin:["鉴定记录","data"],BlacklistPlugin:["黑名单","data"],FilterTitleKeywordPlugin:["关键词筛选","data"],FavoriteActressesPlugin:["演员收藏","data"],NewVideoPlugin:["新作品检测","data"],TaskPlugin:["定时任务","data"],OtherSitePlugin:["外部站点","network"],Fc2Plugin:["FC2 详情","network"],Fc2By123AvPlugin:["FC2 123AV","network"],MagnetHubPlugin:["磁力聚合","network"],JavTrailersPlugin:["预告片","network"],SubTitleCatPlugin:["字幕搜索","network"],OneTwoThreeOfflinePlugin:["123 云盘离线","network"]},e=d((t,s)=>({label:s,plugins:Object.entries(o).filter((a=>a[1][1]===t)).map((a=>a[0]))}),"group");return{categories:{core:e("core","基础核心"),list:e("list","列表页"),detail:e("detail","详情页"),media:e("media","媒体"),data:e("data","数据"),network:e("network","网络")},pluginMeta:o}}d(Gl,"getPluginCategories");function Ih(o){return o.map(e=>` + `).appendTo("head")}d(kh,"applyImageMode");async function vi(o={},{busImgPlugin:e=null,hostAdapter:t=null}={}){let s=o.enableVerticalModel===void 0?ne:o.enableVerticalModel;await kh(e,s);let a=globalThis.utils?.isMobileMode?.()??!1,r=a?1:Number(o.containerColumns??5)||5,i=a?100:Number(o.containerWidth??100)||100;if(B&&e?.logImageHeightsByRow&&await e.logImageHeightsByRow({vertical:s,columns:r}),t){let n=t.locateListRoot?.();n&&(n.style.gridTemplateColumns=`repeat(${r}, minmax(0, 1fr))`);let l=t.getListLayoutContainer?.();l&&(l.style.minWidth=`${i}%`)}}d(vi,"applyLayoutFromSettings");var bi=new WeakMap;function yi(o){let e=bi.get(o);return e||(e=new wi(o),bi.set(o,e)),e}d(yi,"getSettingBindingHub");function Vl({root:o,selector:e,key:t,getValue:s,setValue:a,fallback:r=void 0,label:i=t,settings:n,onChange:l=null}){let c=yi(n),h=o.find(e);if(!h.length)return null;let u={setValue(p,g){p===t&&a(g)},dispose(){h.off(".jhsSettingBinding"),c._dropBinding(u)}};return c.bindings.add(u),h.off(".jhsSettingBinding").on("change.jhsSettingBinding",()=>{let p=s();l?.(t,p),c.userChanged(t,p,r,i)}),u.setValue(t,c.desiredValue(t,n.snapshot()[t]??r)),{sync(p){Object.prototype.hasOwnProperty.call(p,t)&&a(p[t])},flush:d(p=>c.flush(p),"flush"),dispose:d(()=>u.dispose(),"dispose")}}d(Vl,"bindSettingControl");function Ve({settings:o,key:e,fallback:t=void 0,apply:s,onError:a=d(()=>{},"onError")}){let r=0;return async i=>{let n=++r;s(i);try{await o.set(e,i)}catch(l){n===r&&(s(o.snapshot()[e]??t),a(l))}}}d(Ve,"createLatestSettingWriter");var ji=class ji{constructor(e){this.settings=e,this.bindings=new Set,this.pending=new Map,this.revision=0,this._onSettingsChanged=this._onSettingsChanged.bind(this),this.settings.addEventListener("settings.changed",this._onSettingsChanged)}_onSettingsChanged(e){let t=e.detail||{},s=t.snapshot??this.settings.snapshot(),a=Array.isArray(t.names)?t.names:Object.keys(s);for(let r of a){let i=this.pending.get(r);this.syncAll(r,i?i.value:s[r])}}syncAll(e,t){for(let s of this.bindings)s.setValue(e,t)}desiredValue(e,t){let s=this.pending.get(e);return s?s.value:t}userChanged(e,t,s,a){this.syncAll(e,t);let i={token:++this.revision,value:t,promise:Promise.resolve()},n=this.settings.set(e,t).then(()=>{this.pending.get(e)===i&&(this.pending.delete(e),this._maybeDispose())},l=>{if(this.pending.get(e)===i){this.pending.delete(e),i.error=l;let c=this.settings.snapshot()[e]??s;this.syncAll(e,c),this._maybeDispose(),typeof globalThis.show?.error=="function"?globalThis.show.error(`${a||e}保存失败,已恢复原设置`):typeof globalThis.clog?.error=="function"&&globalThis.clog.error(`${a||e}保存失败,已恢复原设置`,l)}});return i.promise=n,this.pending.set(e,i),n}async flush({throwOnFailure:e=!1}={}){let t=[...this.pending.values()];if(await Promise.all(t.map(s=>s.promise)),await this.settings.waitForIdle(),e){let s=t.filter(a=>a.error).map(a=>a.error);if(s.length>0){let a=new Error("部分实时设置保存失败");throw a.cause=s[0],a.liveSettingFailures=s,a}}}_dropBinding(e){this.bindings.delete(e),this._maybeDispose()}_maybeDispose(){this.bindings.size===0&&this.pending.size===0&&(this.settings.removeEventListener("settings.changed",this._onSettingsChanged),bi.delete(this.settings))}};d(ji,"SettingBindingHub");var wi=ji;function Si(o,e){return be(e,!1)}d(Si,"normalizeBooleanValue");function ql(o,e={}){let t=globalThis.$,s=e.value??o.defaultValue,a=e.onChange??null,r;if(o.type==="boolean")return r=t('').prop("checked",Si(o.key,s)),r.on("change",()=>{a?.(r.is(":checked")?"yes":"no")}),{root:r,getValue:d(()=>r.is(":checked")?"yes":"no","getValue"),setValue:d(i=>r.prop("checked",Si(o.key,i)),"setValue")};if(o.type==="select"){let i=Array.isArray(o.options)?o.options:[];return r=t(''),i.forEach(n=>{let l=n&&typeof n=="object"?n:{value:n,label:String(n)};r.append(t("").attr("value",l.value).text(l.label??String(l.value)))}),r.val(String(s??"")),r.on("change",()=>a?.(r.val())),{root:r,getValue:d(()=>r.val(),"getValue"),setValue:d(n=>r.val(String(n??"")),"setValue")}}return o.type==="number"?(r=t('').val(s==null?"":String(s)),r.on("change",()=>a?.(Number(r.val())||0)),{root:r,getValue:d(()=>Number(r.val())||0,"getValue"),setValue:d(i=>r.val(i==null?"":String(i)),"setValue")}):(r=t('').val(s==null?"":String(s)),r.on("change",()=>a?.(r.val())),{root:r,getValue:d(()=>r.val(),"getValue"),setValue:d(i=>r.val(i==null?"":String(i)),"setValue")})}d(ql,"renderSettingControl");function Os(o,e={}){let t=globalThis.$,s=ql(o,{value:e.value,onChange:e.onChange}),a=t('').append(t('').text(o.label)).append(t('').text(o.description||"")),r=t('').append(s.root);return{row:t('').attr("data-jhs-setting",o.key).attr("data-jhs-setting-effect",o.effect||"live").toggleClass("jhs-setting-row--indent",o.indent===!0).append(a,r),root:s.root,getValue:s.getValue,setValue:s.setValue}}d(Os,"renderSettingRow");function Hl(o,e={}){let t=globalThis.$,s=t('
');for(let a of o.list({surfaces:["quick"],disabledContributions:e.disabledContributions})){let{row:r}=Os(a);s.append(r)}return s}d(Hl,"buildQuickSettingsHtml");function ts(o,e,{settings:t,onChanged:s=null}){let a=yi(t),r=new xi(o,e,{settings:t,hub:a,onChanged:s});return{sync:d(i=>r.sync(i),"sync"),flush:d(i=>a.flush(i),"flush"),dispose:d(()=>r.dispose(),"dispose"),setters:r.setters}}d(ts,"bindSettingRows");var ki=class ki{constructor(e,t,{settings:s,hub:a,onChanged:r=null}){this.root=e,this.settings=s,this.hub=a,this.onChanged=r,this.setters={},this.controls=new Map,a.bindings.add(this);for(let i of t)this._bindDescriptor(i)}_bindDescriptor(e){let t=e.key,s=this.root.find(`[data-jhs-setting="${t}"]`).first();if(!s.length)return;let a=s.find(".jhs-setting-row__control"),r=a.children().first();if(!r.length){let h=ql(e);a.append(h.root),r=h.root}let i=e.type||(r.is("select")?"select":r.is('input[type="checkbox"]')?"boolean":r.is('input[type="number"]')?"number":"text"),n=Ch(i,r),l=_h(i,r),c=e.defaultValue;r.off(".jhsSettingBinding").on("change.jhsSettingBinding",()=>{let h=l(),u=typeof e.normalize=="function"?e.normalize(h):h;n(u),this.onChanged?.(t,u),(e.effect||"live")==="live"&&this.hub.userChanged(t,u,c,e.label||t)}),this.controls.set(t,{element:r,setValue:n}),this.setters[t]=n,this.setValue(t,this.hub.desiredValue(t,this.settings.snapshot()[t]??c))}setValue(e,t){let s=this.controls.get(e);s&&s.setValue(t)}sync(e){for(let t of this.controls.keys()){let s=Object.prototype.hasOwnProperty.call(e,t)?e[t]:this.settings.snapshot()[t];this.setValue(t,s)}}dispose(){for(let e of this.controls.values())e.element.off(".jhsSettingBinding");this.hub._dropBinding(this)}};d(ki,"RowBinding");var xi=ki;function Ch(o,e){return o==="boolean"?t=>e.prop("checked",Si("",t)):o==="select"?t=>{e.val(String(t??"")),K.refresh(e)}:o==="number"?t=>e.val(t==null?"":String(t)):t=>e.val(t==null?"":String(t))}d(Ch,"makeSetValue");function _h(o,e){return o==="boolean"?()=>e.is(":checked")?"yes":"no":o==="select"?()=>e.val():o==="number"?()=>{let t=e.val();if(t==null||String(t).trim()==="")return Number.NaN;let s=Number(t);return Number.isFinite(s)?s:Number.NaN}:()=>e.val()}d(_h,"makeGetValue");var Ci=Object.freeze(["videoQuality","reviewCount","tagPosition","waitCheckCount","highlightedTagNumber","highlightedTagColor","checkConcurrencyCount","checkRequestSleep","enableCheckBlacklist","checkBlacklist_intervalTime","checkBlacklist_ruleTime","enableCheckFavoriteActress","checkFavoriteActress_IntervalTime","enableCheckNewVideo","checkNewVideo_intervalTime","checkNewVideo_ruleTime","httpTimeout","httpRetryCount","circuitBreakerThreshold","circuitBreakerCooldown","clogMsgCount","webDavUrl","webDavUsername","webDavPassword","missAvUrl","jableUrl","avgleUrl","javTrailersUrl","av123Url","javDbUrl","javBusUrl","supJavUrl","enableTitleSelectFilter","enableFavoriteActresses","enableSaveActressCarInfo","autoRemoveNewVideoMarkAfterBrowse"]),$h=Object.freeze({videoQuality:"#videoQuality",reviewCount:"#reviewCount",tagPosition:"#tagPosition",waitCheckCount:"#waitCheckCount",highlightedTagNumber:"#highlightedTagNumber",highlightedTagColor:"#highlightedTagColor",checkConcurrencyCount:"#checkConcurrencyCount",checkRequestSleep:"#checkRequestSleep",enableCheckBlacklist:"#enableCheckBlacklist",checkBlacklist_intervalTime:"#checkBlacklist_intervalTime",checkBlacklist_ruleTime:"#checkBlacklist_ruleTime",enableCheckFavoriteActress:"#enableCheckFavoriteActress",checkFavoriteActress_IntervalTime:"#checkFavoriteActress_IntervalTime",enableCheckNewVideo:"#enableCheckNewVideo",checkNewVideo_intervalTime:"#checkNewVideo_intervalTime",checkNewVideo_ruleTime:"#checkNewVideo_ruleTime",httpTimeout:"#httpTimeout",httpRetryCount:"#httpRetryCount",circuitBreakerThreshold:"#circuitBreakerThreshold",circuitBreakerCooldown:"#circuitBreakerCooldownSec",clogMsgCount:"#clogMsgCount",webDavUrl:"#webDavUrl",webDavUsername:"#webDavUsername",webDavPassword:"#webDavPassword",missAvUrl:"#missAvUrl",jableUrl:"#jableUrl",avgleUrl:"#avgleUrl",javTrailersUrl:"#javTrailersUrl",av123Url:"#av123Url",javDbUrl:"#javDbUrl",javBusUrl:"#javBusUrl",supJavUrl:"#supJavUrl",enableTitleSelectFilter:"#enableTitleSelectFilter",enableFavoriteActresses:"#enableFavoriteActresses",enableSaveActressCarInfo:"#enableSaveActressCarInfo",autoRemoveNewVideoMarkAfterBrowse:"#autoRemoveNewVideoMarkAfterBrowse"});function Th(o){let e=new Set;o.data("jhsDirtyManualKeys",e);for(let t of Ci){let s=$h[t];s&&o.find(s).off(".jhsDirty").on("change.jhsDirty",()=>e.add(t))}}d(Th,"bindManualDirtyTracking");function Jl(o){return o?globalThis.$(o):globalThis.$(document)}d(Jl,"formRoot");async function Kl(o,e=null){let t=Jl(e),s=o.settings.snapshot();t.find("#videoQuality").val(s.videoQuality),t.find("#reviewCount").val(s.reviewCount||20),t.find("#tagPosition").val(s.tagPosition||"rightTop"),t.find("#autoRemoveNewVideoMarkAfterBrowse").prop("checked",!!s.autoRemoveNewVideoMarkAfterBrowse&&s.autoRemoveNewVideoMarkAfterBrowse===E),t.find("#waitCheckCount").val(s.waitCheckCount||5),t.find("#checkConcurrencyCount").val(ae(s.checkConcurrencyCount,2,{min:2,max:5})),t.find("#checkRequestSleep").val(ae(s.checkRequestSleep,100,{min:0,max:3e3})),t.find("#enableCheckBlacklist").val(s.enableCheckBlacklist||E),t.find("#checkBlacklist_intervalTime").val(s.checkBlacklist_intervalTime||12),t.find("#checkBlacklist_ruleTime").val(ae(s.checkBlacklist_ruleTime,8760,{min:0})),t.find("#enableCheckFavoriteActress").val(s.enableCheckFavoriteActress||E),t.find("#checkFavoriteActress_IntervalTime").val(s.checkFavoriteActress_IntervalTime||24),t.find("#enableCheckNewVideo").val(s.enableCheckNewVideo||E),t.find("#checkNewVideo_intervalTime").val(s.checkNewVideo_intervalTime||12),t.find("#checkNewVideo_ruleTime").val(ae(s.checkNewVideo_ruleTime,8760,{min:0}));let a=s.highlightedTagNumber||1,r=s.highlightedTagColor||"#ce2222";t.find("#highlightedTagNumber").val(s.highlightedTagNumber||1),t.find("#highlightedTagColor").val(s.highlightedTagColor||"#ce2222"),t.find("#highlightedTagLabel").css("border",`${a}px solid ${r}`),t.find("#clogMsgCount").val(s.clogMsgCount||2e3),t.find("#httpTimeout").val(s.httpTimeout||5e3),t.find("#httpRetryCount").val(s.httpRetryCount||3),t.find("#webDavUrl").val(s.webDavUrl||""),t.find("#webDavUsername").val(s.webDavUsername||"");let i=o.webdav,n=i?.getProfile?await i.getProfile():{url:s.webDavUrl,username:s.webDavUsername,password:""};t.find("#webDavUrl").val(n.url||""),t.find("#webDavUsername").val(n.username||""),t.find("#webDavPassword").val(n.password||""),t.find("#enableTitleSelectFilter").prop("checked",!s.enableTitleSelectFilter||s.enableTitleSelectFilter===E),t.find("#enableFavoriteActresses").prop("checked",!s.enableFavoriteActresses||s.enableFavoriteActresses===E),t.find("#enableSaveActressCarInfo").prop("checked",!!s.enableSaveActressCarInfo&&s.enableSaveActressCarInfo===E);let l=o.movie;t.find("#missAvUrl").val(l.externalSiteOrigin("missAvBtn",s)),t.find("#jableUrl").val(l.externalSiteOrigin("jableBtn",s)),t.find("#avgleUrl").val(l.externalSiteOrigin("avgleBtn",s)),t.find("#javTrailersUrl").val(l.externalSiteOrigin("javTrailersBtn",s)),t.find("#av123Url").val(l.providerOrigin("av123")||""),t.find("#javDbUrl").val(l.externalSiteOrigin("javDbBtn",s)),t.find("#javBusUrl").val(l.externalSiteOrigin("javBusBtn",s)),t.find("#supJavUrl").val(l.externalSiteOrigin("supJavBtn",s));let c=await storageManager.getReviewFilterKeywordList(),h=await storageManager.getTitleFilterKeyword();["#reviewKeywordContainer","#filterKeywordContainer"].forEach(u=>{t.find(`${u} .tag-box`).empty(),t.find(`${u} .add-tag-btn`).off(".jhsKeywordBind"),t.find(`${u} .keyword-input`).off(".jhsKeywordBind")}),c&&c.forEach(u=>{_i("#reviewKeywordContainer",u,t)}),h&&h.forEach(u=>{_i("#filterKeywordContainer",u,t)}),["#reviewKeywordContainer","#filterKeywordContainer"].forEach(u=>{t.find(`${u} .add-tag-btn`).on("click.jhsKeywordBind",(p=>Wl(p,u,t))),t.find(`${u} .keyword-input`).on("keypress.jhsKeywordBind",(p=>{p.key==="Enter"&&Wl(p,u,t)}))}),Th(t),Ph(t),Ah(t,o.busImg,o.host,o.settings)}d(Kl,"loadSettingForm");function Ah(o,e,t,s){o.find("#containerColumns").off(".jhsSetting").on("input.jhsSetting",(()=>{ss(o,t,"containerColumns",o.find("#containerColumns").val())})),o.find("#containerWidth").off(".jhsSetting").on("input.jhsSetting",(a=>{ss(o,t,"containerWidth",parseInt($(a.target).val())+70)}))}d(Ah,"bindLayoutRangeEvents");function ss(o,e,t,s){if(t==="containerColumns"){let n=Math.min(10,Math.max(2,Math.round(Number(s)||5)));o.find("#containerColumns").val(String(n)),o.find("#showContainerColumns").text(String(n));let l=e?.locateListRoot?.();l&&(l.style.gridTemplateColumns=`repeat(${n}, minmax(0, 1fr))`);return}let a=Math.min(100,Math.max(70,Math.round(Number(s)||100))),r=`${a}%`;o.find("#containerWidth").val(String(a-70)),o.find("#showContainerWidth").text(r);let i=e?.getListLayoutContainer?.();i&&(i.style.minWidth=r)}d(ss,"applyLayoutRangeValue");function et(o){let e=$(o);e.data("jhsQuickSettingBinding")?.dispose?.(),e.removeData("jhsQuickSettingBinding"),e.empty().hide()}d(et,"disposeQuickSettingHost");async function Us(o,e,t,s){let a=$(s);if(!a.length)throw new Error("Quick setting root is required");let r=o.settingsRegistry;if(!r)return;let i=r.list({surfaces:["quick"]}),n=ts(a,i,{settings:o.settings});a.data("jhsQuickSettingBinding",n),a.find("#moreBtn").off(".jhsQuickSetting").on("click.jhsQuickSetting",(async l=>{l.preventDefault(),l.stopPropagation(),await a.data("jhsQuickSettingBinding")?.flush?.(),et(a),await t("base-panel")}))}d(Us,"initQuickSettingForm");async function Gl(o,e=null){let t=Jl(e),s=t.data("jhsDirtyManualKeys")||null,a=null,r=null;if(!s||s.has("webDavUrl")){if(a=String(t.find("#webDavUrl").val()||"").trim(),a)try{let g=new URL(a);if(!["http:","https:"].includes(g.protocol))throw new Error("protocol");r=g.origin}catch{throw new Error("WebDAV 地址必须是有效的 HTTP/HTTPS URL")}let p=new Set(Array.isArray(o.settings.snapshot().trustedLocalOrigins)?o.settings.snapshot().trustedLocalOrigins:[]);if(r&&!p.has(r)&&!await new Promise(m=>utils.q(null,`仅授权 WebDAV 精确来源:${r},是否继续?`,()=>m(!0),()=>m(!1))))return{canceled:!0}}(!s||["webDavUrl","webDavUsername","webDavPassword"].some(p=>s.has(p)))&&o.webdav?.saveProfile&&await o.webdav.saveProfile({...!s||s.has("webDavUrl")?{url:String(t.find("#webDavUrl").val()||"").trim()}:{},...!s||s.has("webDavUsername")?{username:String(t.find("#webDavUsername").val()||"")}:{},...!s||s.has("webDavPassword")?{password:String(t.find("#webDavPassword").val()||"")}:{}});let n=await Rh(t,s);await o.settings.update(p=>{if(Object.assign(p,n),r){let g=new Set(Array.isArray(p.trustedLocalOrigins)?p.trustedLocalOrigins:[]);g.add(r),p.trustedLocalOrigins=[...g]}}),t.data("jhsDirtyManualKeys",new Set);let l=[],c=t.data("jhsDirtyReviewKeywords")===!0,h=t.data("jhsDirtyTitleKeywords")===!0;if(c)try{let p=[...new Set(t.find("#reviewKeywordContainer .keyword-label").toArray().map(g=>$(g).text().replaceAll("×","").replace(/[\r\n]+/g," ").replace(/\s{2,}/g," ").trim()).filter(Boolean))];await storageManager.saveReviewFilterKeyword(p)}catch(p){l.push(p)}if(h)try{let p=[...new Set(t.find("#filterKeywordContainer .keyword-label").toArray().map(g=>$(g).text().replaceAll("×","").replace(/[\r\n]+/g," ").replace(/\s{2,}/g," ").trim()).filter(Boolean))];await storageManager.saveTitleFilterKeyword(p)}catch(p){l.push(p)}if(l.length){let p=new Error("部分设置保存失败,请重试");throw p.partialFailure=!0,p.cause=l[0],p}t.data("jhsDirtyReviewKeywords",!1),t.data("jhsDirtyTitleKeywords",!1);let u=[["filter rules",async()=>{if(!V)throw new Error("EventBus 尚未初始化");await V.emit("filter-rules-changed",{scope:"title-keyword"})}],["new-video status",()=>o.newVideo?.resetBtnTip?.()],["blacklist status",()=>o.blacklist?.resetBtnTip?.()],["blacklist table",()=>o.blacklist?.reloadTable?.()]];for(let[p,g]of u)try{await g()}catch(m){typeof globalThis.clog?.error=="function"&&globalThis.clog.error(`设置保存后 ${p} 刷新失败(已忽略)`,m)}return{ok:!0}}d(Gl,"saveSettingForm");function Ph(o){o.data("jhsDirtyReviewKeywords",!1),o.data("jhsDirtyTitleKeywords",!1)}d(Ph,"bindKeywordDirtyTracking");async function Rh(o,e=null){let t=d((n,l,c,h)=>Math.min(h,Math.max(c,Number(n)||l)),"clamp"),s=d((n,{allowLocalHttp:l=!1}={})=>{let c=String(n||"").trim().replace(/\/$/,"");if(!c)return"";let h;try{h=new URL(c)}catch{throw new TypeError(`无效 URL:${c}`)}let u=["localhost","127.0.0.1","[::1]"].includes(h.hostname);if(h.protocol!=="https:"&&!(l&&u&&h.protocol==="http:"))throw new TypeError(`仅允许 HTTPS URL${l?"(本机地址可使用 HTTP)":""}:${c}`);return h.href.replace(/\/$/,"")},"configuredUrl"),a={videoQuality:d(()=>o.find("#videoQuality").val(),"videoQuality"),reviewCount:d(()=>o.find("#reviewCount").val(),"reviewCount"),tagPosition:d(()=>o.find("#tagPosition").val(),"tagPosition"),autoRemoveNewVideoMarkAfterBrowse:d(()=>o.find("#autoRemoveNewVideoMarkAfterBrowse").is(":checked")?E:ne,"autoRemoveNewVideoMarkAfterBrowse"),waitCheckCount:d(()=>o.find("#waitCheckCount").val(),"waitCheckCount"),highlightedTagNumber:d(()=>o.find("#highlightedTagNumber").val(),"highlightedTagNumber"),highlightedTagColor:d(()=>o.find("#highlightedTagColor").val(),"highlightedTagColor"),checkConcurrencyCount:d(()=>o.find("#checkConcurrencyCount").val(),"checkConcurrencyCount"),checkRequestSleep:d(()=>o.find("#checkRequestSleep").val(),"checkRequestSleep"),enableCheckBlacklist:d(()=>o.find("#enableCheckBlacklist").val(),"enableCheckBlacklist"),checkBlacklist_intervalTime:d(()=>o.find("#checkBlacklist_intervalTime").val(),"checkBlacklist_intervalTime"),checkBlacklist_ruleTime:d(()=>o.find("#checkBlacklist_ruleTime").val(),"checkBlacklist_ruleTime"),enableCheckFavoriteActress:d(()=>o.find("#enableCheckFavoriteActress").val(),"enableCheckFavoriteActress"),checkFavoriteActress_IntervalTime:d(()=>o.find("#checkFavoriteActress_IntervalTime").val(),"checkFavoriteActress_IntervalTime"),enableCheckNewVideo:d(()=>o.find("#enableCheckNewVideo").val(),"enableCheckNewVideo"),checkNewVideo_intervalTime:d(()=>o.find("#checkNewVideo_intervalTime").val(),"checkNewVideo_intervalTime"),checkNewVideo_ruleTime:d(()=>o.find("#checkNewVideo_ruleTime").val(),"checkNewVideo_ruleTime"),httpTimeout:d(()=>t(o.find("#httpTimeout").val(),5e3,1e3,12e4),"httpTimeout"),httpRetryCount:d(()=>t(o.find("#httpRetryCount").val(),3,1,10),"httpRetryCount"),circuitBreakerThreshold:d(()=>t(o.find("#circuitBreakerThreshold").val(),3,1,20),"circuitBreakerThreshold"),circuitBreakerCooldown:d(()=>t(Number(o.find("#circuitBreakerCooldownSec").val())*1e3,6e4,1e3,36e5),"circuitBreakerCooldown"),clogMsgCount:d(()=>o.find("#clogMsgCount").val(),"clogMsgCount"),webDavUrl:d(()=>s(o.find("#webDavUrl").val(),{allowLocalHttp:!0}),"webDavUrl"),webDavUsername:d(()=>String(o.find("#webDavUsername").val()||""),"webDavUsername"),missAvUrl:d(()=>s(o.find("#missAvUrl").val()),"missAvUrl"),jableUrl:d(()=>s(o.find("#jableUrl").val()),"jableUrl"),avgleUrl:d(()=>s(o.find("#avgleUrl").val()),"avgleUrl"),javTrailersUrl:d(()=>s(o.find("#javTrailersUrl").val()),"javTrailersUrl"),av123Url:d(()=>s(o.find("#av123Url").val()),"av123Url"),javDbUrl:d(()=>s(o.find("#javDbUrl").val()),"javDbUrl"),javBusUrl:d(()=>s(o.find("#javBusUrl").val()),"javBusUrl"),supJavUrl:d(()=>s(o.find("#supJavUrl").val()),"supJavUrl"),enableTitleSelectFilter:d(()=>o.find("#enableTitleSelectFilter").is(":checked")?E:ne,"enableTitleSelectFilter"),enableFavoriteActresses:d(()=>o.find("#enableFavoriteActresses").is(":checked")?E:ne,"enableFavoriteActresses"),enableSaveActressCarInfo:d(()=>o.find("#enableSaveActressCarInfo").is(":checked")?E:ne,"enableSaveActressCarInfo")},r=e instanceof Set?Ci.filter(n=>e.has(n)).filter(n=>!["webDavUrl","webDavUsername","webDavPassword"].includes(n)):Ci.filter(n=>!["webDavUrl","webDavUsername","webDavPassword"].includes(n)),i={};for(let n of r){let l=a[n];l&&(i[n]=await l())}return i}d(Rh,"collectManualSettingPatch");function _i(o,e,t){let s=t.find(`${o} .tag-box`),a=String(e),r;/^[a-z]{2,}-/i.test(a)&&M?r=$("
").addClass("keyword-label keyword-label--link").attr("data-keyword",a).attr("href",`/video_codes/${a.replace("-","")}`).attr("target","_blank"):r=$("
").addClass("keyword-label").attr("data-keyword",a),r.append(document.createTextNode(a)),r.append($("").addClass("keyword-remove").text("×"));let i=o==="#reviewKeywordContainer"?"jhsDirtyReviewKeywords":"jhsDirtyTitleKeywords";r.find(".keyword-remove").click((n=>{n.stopPropagation(),n.preventDefault();let l=$(n.currentTarget),c=l.closest(".keyword-label").attr("data-keyword").split(" ")[0];utils.q(n,`是否移除屏蔽词 ${T(c)}?`,(async()=>{l.parent().remove(),t.data(i,!0)}))})),s.append(r)}d(_i,"addLabelTag");function Wl(o,e,t){let s=t.find(`${e} .keyword-input`),a=s.val().trim();if(!a)return;t.find(`${e} .keyword-label`).toArray().some((i=>$(i).text().replaceAll("×","").trim()===a))||_i(e,a,t),s.val(""),t.data(e==="#reviewKeywordContainer"?"jhsDirtyReviewKeywords":"jhsDirtyTitleKeywords",!0)}d(Wl,"addKeyword");function Ql(){let o={SettingPlugin:["设置中心","core"],StatsPlugin:["统计中心","core"],MobileBottomBarPlugin:["工具栏与移动操作","core"],ListPagePlugin:["列表状态处理","list"],NavBarPlugin:["JavDB 导航","list"],BusNavBarPlugin:["JavBus 导航","list"],ListPageButtonPlugin:["列表操作","list"],HighlightMagnetPlugin:["磁力标记","list"],FoldCategoryPlugin:["分类折叠","list"],AutoPagePlugin:["自动翻页","list"],HitShowPlugin:["热播榜单","list"],TOP250Plugin:["TOP 250","list"],DetailPagePlugin:["JavDB 详情页","detail"],BusDetailPagePlugin:["JavBus 详情页","detail"],DetailPageButtonPlugin:["详情操作","detail"],ReviewPlugin:["评论","detail"],RelatedPlugin:["相关影片","detail"],TranslatePlugin:["标题翻译","detail"],WantAndWatchedVideosPlugin:["想看与看过","detail"],CoverButtonPlugin:["封面快捷操作","media"],PreviewVideoPlugin:["JavDB 预览视频","media"],BusPreviewVideoPlugin:["JavBus 预览视频","media"],ScreenShotPlugin:["剧照","media"],BusImgPlugin:["JavBus 图片适配","media"],ActressInfoPlugin:["演员资料","media"],SearchByImagePlugin:["以图搜图","media"],HistoryPlugin:["鉴定记录","data"],BlacklistPlugin:["黑名单","data"],FilterTitleKeywordPlugin:["关键词筛选","data"],FavoriteActressesPlugin:["演员收藏","data"],NewVideoPlugin:["新作品检测","data"],TaskPlugin:["定时任务","data"],OtherSitePlugin:["外部站点","network"],Fc2Plugin:["FC2 详情","network"],Fc2By123AvPlugin:["FC2 123AV","network"],MagnetHubPlugin:["磁力聚合","network"],JavTrailersPlugin:["预告片","network"],SubTitleCatPlugin:["字幕搜索","network"],OneTwoThreeOfflinePlugin:["123 云盘离线","network"]},e=d((t,s)=>({label:s,plugins:Object.entries(o).filter((a=>a[1][1]===t)).map((a=>a[0]))}),"group");return{categories:{core:e("core","基础核心"),list:e("list","列表页"),detail:e("detail","详情页"),media:e("media","媒体"),data:e("data","数据"),network:e("network","网络")},pluginMeta:o}}d(Ql,"getPluginCategories");function Ih(o){return o.map(e=>`
${e.text}
@@ -2581,7 +2581,7 @@
- `).join("")}d(Ih,"buildCacheItemsHtml");function Rh(){let o="";return rt.forEach(e=>{e.canSelect&&(o+=``)}),o}d(Rh,"buildVideoQualityOptions");function Ql(o,e){let t=Ih(e),s=Rh();return` + `).join("")}d(Ih,"buildCacheItemsHtml");function Eh(){let o="";return rt.forEach(e=>{e.canSelect&&(o+=``)}),o}d(Eh,"buildVideoQualityOptions");function Yl(o,e){let t=Ih(e),s=Eh();return`
@@ -3046,7 +3041,7 @@
- `}d(Ql,"buildSettingDialogHtml");function Yl(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="health-panel"]').length&&o.append('');let e=$(".content-panel").parent();e.length&&!$("#health-panel").length&&e.append(` + `}d(Yl,"buildSettingDialogHtml");function Zl(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="health-panel"]').length&&o.append('');let e=$(".content-panel").parent();e.length&&!$("#health-panel").length&&e.append(`

数据体检

检查本地数据并在备份后修复异常。

@@ -3056,7 +3051,7 @@
点击重新体检查看结果
- `)}d(Yl,"injectHealthPanel");function Zl(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="plugin-mgmt-panel"]').length&&o.append('');let e=$(".content-panel").parent();if(!e.length||$("#plugin-mgmt-panel").length)return;e.append(`
+ `)}d(Zl,"injectHealthPanel");function Xl(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="plugin-mgmt-panel"]').length&&o.append('');let e=$(".content-panel").parent();if(!e.length||$("#plugin-mgmt-panel").length)return;e.append(`

插件管理

按功能查看插件状态、耗时和错误记录。

0总插件数
@@ -3070,7 +3065,7 @@

错误日志

无错误记录

缓存命中率

-
`)}d(Zl,"injectPluginMgmtPanel");function Xl(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="snapshot-panel"]').length&&o.append('');let e=$(".content-panel").parent();if(!e.length||$("#snapshot-panel").length)return;e.append('

恢复点

创建、下载或恢复本地数据快照。

快照保存当前全部数据状态,可用于恢复。最多保留 10 个,超出自动清理最旧的。

')}d(Xl,"injectSnapshotPanel");function ec(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="network-panel"]').length&&o.append('');let e=$(".content-panel").parent();if(!e.length||$("#network-panel").length)return;e.append(`
+
`)}d(Xl,"injectPluginMgmtPanel");function ec(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="snapshot-panel"]').length&&o.append('');let e=$(".content-panel").parent();if(!e.length||$("#snapshot-panel").length)return;e.append('

恢复点

创建、下载或恢复本地数据快照。

快照保存当前全部数据状态,可用于恢复。最多保留 10 个,超出自动清理最旧的。

')}d(ec,"injectSnapshotPanel");function tc(){let o=$(".side-menu-item").parent();o.length&&!o.find('[data-panel="network-panel"]').length&&o.append('');let e=$(".content-panel").parent();if(!e.length||$("#network-panel").length)return;e.append(`

外部请求

配置熔断规则并查看站点健康状态。

熔断器配置

连续请求失败达到阈值后,自动停止对该站点的请求,避免拖慢整体体验。

熔断阈值(次):
@@ -3078,14 +3073,14 @@

站点健康状态

各外部站点的熔断状态和请求统计。

域名使用统计

脚本实际请求过的域名及次数。

-
`)}d(ec,"injectNetworkPanel");function tc(){if($("#resource-sources-panel").length)return;$(".content-panel").last().after(`
+
`)}d(tc,"injectNetworkPanel");function sc(){if($("#resource-sources-panel").length)return;$(".content-panel").last().after(`

磁力来源

聚合多个来源搜索磁力结果,优先级数字越小越靠前。

自定义来源

磁力规则

使用可视化规则为结果添加标签或过滤低质量内容。

标签规则

过滤规则

截图来源

自动选择会按优先级依次尝试可用来源。

高级 · 导入 / 导出配置

高级功能:错误修改可能导致自定义来源不可用,保存前会校验配置。

统一离线服务

115 状态:未知

服务不可用时会在提交前显示原因。
-

番号列表导入

支持换行、空格、逗号分隔番号。必须先解析预览,再确认导入。

`),$(".jhs-mobile-sidebar,.setting-sidebar").first().append('')}d(tc,"injectResourceSourcesPanel");function Us(o=void 0,e={}){let t=o?Hl(o,e):null;return` +

番号列表导入

支持换行、空格、逗号分隔番号。必须先解析预览,再确认导入。

`),$(".jhs-mobile-sidebar,.setting-sidebar").first().append('')}d(sc,"injectResourceSourcesPanel");function zs(o=void 0,e={}){let t=o?Hl(o,e):null;return`
${t?t.prop("outerHTML"):'
'} @@ -3093,19 +3088,19 @@
-
`}d(Us,"buildQuickSettingHtml");async function Et(o){let e=o.getNetworkDiagnostics(),t=e.circuitBreakers,s=e.domainStats,a=await storageManager.getSetting("circuitBreakerThreshold",3),r=await storageManager.getSetting("circuitBreakerCooldown",6e4);$("#circuitBreakerThreshold").each(((l,c)=>{c.dataset.jhsHydrated||(c.value=String(a),c.dataset.jhsHydrated="1")})),$("#circuitBreakerCooldownSec").each(((l,c)=>{c.dataset.jhsHydrated||(c.value=String(Math.round(r/1e3)),c.dataset.jhsHydrated="1")}));let i=Object.entries(t);if(i.length){let l='';for(let[c,h]of i){let u=h.state==="open"?"熔断":h.state==="half-open"?"半开":"正常",p=h.state==="open"?`剩余${Math.ceil((Number(h.cooldownMs)-(Date.now()-Number(h.openTime)))/1e3)}秒`:"";l+=``}l+="
域名状态失败次数操作
${C(c)}${u} ${p}${Number(h.failCount)||0}
",$("#site-health-table").html(l)}else $("#site-health-table").html('

暂无熔断记录

');let n=Object.entries(s).sort(((l,c)=>c[1].count-l[1].count));if(n.length){let l='';for(let[c,h]of n){let u=h.lastUsed?new Date(h.lastUsed).toLocaleTimeString():"-";l+=``}l+="
域名请求数错误数最后使用
${C(c)}${h.count}${h.errors}${u}
",l+=`

共 ${n.length} 个域名

`,$("#domain-stats-table").html(l)}else $("#domain-stats-table").html('

暂无统计数据

');$(".reset-breaker").off("click").on("click",(l=>{let c=$(l.target).data("domain");o.resetCircuitBreaker(c),show.ok(`已重置 ${c} 的熔断状态`),Et(o)})),$("#resetAllBreakersBtn").off("click").on("click",(()=>{o.resetAllCircuitBreakers(),show.ok("已重置全部熔断状态"),Et(o)})),$("#clearDomainStatsBtn").off("click").on("click",(()=>{o.clearDomainStats(),show.ok("已清空域名统计"),Et(o)}))}d(Et,"renderNetworkPanel");async function as(){let o=await storageManager.getSnapshotList(),e={manual:"手动创建","auto-import":"导入前自动","auto-repair":"修复前自动","auto-restore":"恢复前自动"};if(o.length===0)return void $("#snapshot-list").html('
暂无快照,点击上方按钮创建
');$("#snapshot-list").find(".tabulator").length&&$("#snapshot-list").empty();let t=ze(globalThis.Tabulator,"#snapshot-list",{pagination:!1,layout:"fitColumns",placeholder:"暂无数据",data:o,columnDefaults:{headerHozAlign:"center",hozAlign:"center"},columns:[{title:"名称",field:"name",width:200,headerSort:!1},{title:"来源",field:"source",width:100,headerSort:!1,formatter:d(s=>e[s.getValue()]||s.getValue(),"formatter")},{title:"时间",field:"time",width:170,headerSort:!1},{title:"数据量",field:"itemCount",width:80,headerSort:!1},{title:"操作",minWidth:220,headerSort:!1,formatter:d((s,a,r)=>{let i=s.getData();return r((()=>{let n=s.getElement().querySelector(".snap-restore"),l=s.getElement().querySelector(".snap-download"),c=s.getElement().querySelector(".snap-delete");n&&n.addEventListener("click",(async h=>{utils.q(h,`恢复到快照「${C(i.name)}」? 当前数据会自动备份。`,(async()=>{let u=loading();try{await storageManager.restoreSnapshot(i.id),show.ok("恢复成功, 页面将刷新"),setTimeout(()=>location.reload(),1e3)}catch(p){clog.error(p),show.error("恢复失败: "+(p instanceof Error?p.message:String(p)))}finally{u.close()}}))})),l&&l.addEventListener("click",(async h=>{let u=loading();try{let p=await storageManager.getSnapshot(i.id);if(!p)throw new Error("快照不存在");utils.download(JSON.stringify(p.data),`snapshot_${String(i.name||"snapshot").replace(/[\\/:*?"<>|]/g,"_")}.json`),show.ok("下载成功")}catch(p){show.error("下载失败: "+(p instanceof Error?p.message:String(p)))}finally{u.close()}})),c&&c.addEventListener("click",(async h=>{utils.q(h,`删除快照「${C(i.name)}」?`,(async()=>{try{await storageManager.deleteSnapshot(i.id),show.ok("已删除"),as()}catch(u){clog.error(u),show.error("删除失败: "+(u instanceof Error?u.message:String(u)))}}))}))})),' '},"formatter")}]})}d(as,"renderSnapshotPanel");function sc(o,e,t=null,s){let a=o.summary,r=[];for(let[c,h]of Object.entries(o.stores)){if(h.status==="unchanged")continue;let u={store:c,status:h.status,oldCount:h.oldCount,newCount:h.newCount,added:h.added.length,removed:h.removed.length,modified:h.modified.length};r.push(u)}let i='
';if(i+='
',i+=`
${a.added}新增数据源
`,i+=`
${a.removed}缺失数据源
`,i+=`
${a.modified}有变更
`,i+=`
${a.unchanged}无变化
`,i+="
",r.length>0){i+='
';let c={added:"新增",removed:"缺失",modified:"变更",unchanged:"无变化"};for(let h of r)i+=``;i+="
数据源状态当前导入新增删除修改
${C(h.store)}${c[h.status]||h.status}${h.oldCount}${h.newCount}${h.added||"-"}${h.removed||"-"}${h.modified||"-"}
"}else i+='
数据完全一致,无需导入
';i+='
导入将覆盖当前数据,建议先创建快照备份
',i+="
";let n=r.length>0,l=s.open({type:1,title:"数据差异预览",content:i,area:utils.getResponsiveArea(["700px","auto"]),btn:n?["确认导入","取消"]:["知道了","取消"],anim:-1,yes:d(async c=>{if(!n)return void s.close(c);let h=loading();try{await storageManager.createSnapshot("导入前自动备份","auto-import"),t?(await storageManager.importData(t),show.ok("导入成功!"),setTimeout(()=>location.reload(),1e3)):e&&(await storageManager.importData(e),show.ok("导入成功!"),setTimeout(()=>location.reload(),1e3))}catch(u){clog.error(u),show.error("导入失败: "+(u instanceof Error?u.message:String(u)))}finally{h.close()}},"yes")})}d(sc,"showDiffPreview");async function _i(o,e=null){let t=o.exportSnapshot(),s=Ge(await storageManager.getSetting("disabledPlugins","[]")),a=t.legacyPlugins,r=d(S=>{let j=new Set(S);return a.filter((x=>j.has(x)||j.has(Tt(x))))},"effectiveDisabledNames"),{categories:i,pluginMeta:n}=Gl(),l=new Map((t.legacyPluginDescriptors||[]).map(S=>[S.name,S])),c=new Set(a),h="";for(let[S,j]of Object.entries(i)){let x=j.plugins.filter(k=>c.has(k));if(x.length){h+='
',h+=`

${C(j.label)}

`;for(let k of x){let _=l.get(k)?.disableable===!1,E=s.includes(Tt(k)),L=n[k]?.[0]||k;h+='
',h+=`${C(L)}`,_?h+='核心':h+=``,h+="
"}h+="
"}}$("#plugin-mgmt-list").html(h);let u=r(s),p=a.length-u.length;$("#pm-total").text(a.length),$("#pm-enabled").text(p),$("#pm-disabled").text(u.length),$(".pm-toggle").off("change").on("change",async S=>{let j=$(S.target),x=j.data("plugin"),k=j.is(":checked"),_=!k,E=Ge(await storageManager.getSetting("disabledPlugins","[]")),L=Tt(x);if(k?E=E.filter(A=>A!==x&&A!==L):E.includes(L)||E.push(L),!e)throw new Error("SettingsService is unavailable");let N=d(A=>{let O=t.legacyPlugins,U=r(A);$("#pm-total").text(O.length),$("#pm-enabled").text(O.length-U.length),$("#pm-disabled").text(U.length)},"renderState");N(E);try{await e.set("disabledPlugins",JSON.stringify(E)),show.ok(`插件 "${x}" 已${k?"启用":"禁用"},刷新后生效`)}catch(A){j.prop("checked",_);let O=Ge(await storageManager.getSetting("disabledPlugins","[]"));N(O),clog.error("插件状态保存失败,已恢复",A),show.error(`插件 "${x}" 状态保存失败,已恢复`)}});let g=t.legacyStartup,m=t.legacyTimings,f=d(S=>Number.isFinite(S)?S.toFixed(1):"0.0","formatMs"),v=g?`
就绪: ${f(g.readyMs)} ms注册: ${f(g.registrationMs)} ms样式: ${f(g.cssMs)} ms即时插件: ${f(g.immediateMs)} ms空闲任务: ${g.idleCompleted}/${g.idleCompleted+g.idlePending}

就绪耗时不包含 @require 下载及浏览器脚本解析时间。

`:"";if(m.length){let S=[...m].sort(((x,k)=>k.elapsed-x.elapsed)),j='';for(let x of S){let k=x.status==="disabled"?"is-muted":x.elapsed>500?"is-slow":x.elapsed>200?"is-warning":"",_=x.status==="disabled"?"已禁用":x.status==="error"?"错误":x.status==="pending-idle"?"等待空闲":x.status==="skipped-mobile"?"移动端跳过":"正常";j+=``}j+="
插件阶段耗时(ms)状态
${C(x.name)}${x.startupMode==="idle"?"空闲":"即时"}${x.elapsed.toFixed(1)}${_}
",$("#plugin-timing-table").html(v+j)}else $("#plugin-timing-table").html(v+'

暂无数据,刷新页面后自动采集。

');let b=t.errors.filter(S=>S.source==="legacy-plugin");if(b.length){let S='';for(let j of[...b].reverse())S+=``;S+="
时间插件阶段错误信息
${C(String(j.timestamp||"").substring(11,19))}${C(j.plugin)}${C(j.phase)}${C(j.message)}
",$("#plugin-error-log").html(S)}else $("#plugin-error-log").text("无错误记录");let w=storageManager.getCacheHitStats();$("#cache-hit-stats").html(`
命中: ${w.hits}未命中: ${w.misses}总计: ${w.total}命中率: ${w.rate}
`)}d(_i,"renderPluginMgmtPanel");async function rs(){let o=$("#health-data-display");if(o.length){o.text("体检中...");try{let e=await storageManager.inspectDataHealth(),t=e.fixable.reduce(((r,i)=>r+i.count),0),s=e.readonly.reduce(((r,i)=>r+i.count),0),a=d(r=>r.length?r.map((i=>`
  • ${C(i.message)}:${i.count}
  • `)).join(""):"
  • 无
  • ","i");o.html(` +
    `}d(zs,"buildQuickSettingHtml");async function Dt(o){let e=o.getNetworkDiagnostics(),t=e.circuitBreakers,s=e.domainStats,a=await storageManager.getSetting("circuitBreakerThreshold",3),r=await storageManager.getSetting("circuitBreakerCooldown",6e4);$("#circuitBreakerThreshold").each(((l,c)=>{c.dataset.jhsHydrated||(c.value=String(a),c.dataset.jhsHydrated="1")})),$("#circuitBreakerCooldownSec").each(((l,c)=>{c.dataset.jhsHydrated||(c.value=String(Math.round(r/1e3)),c.dataset.jhsHydrated="1")}));let i=Object.entries(t);if(i.length){let l='';for(let[c,h]of i){let u=h.state==="open"?"熔断":h.state==="half-open"?"半开":"正常",p=h.state==="open"?`剩余${Math.ceil((Number(h.cooldownMs)-(Date.now()-Number(h.openTime)))/1e3)}秒`:"";l+=``}l+="
    域名状态失败次数操作
    ${T(c)}${u} ${p}${Number(h.failCount)||0}
    ",$("#site-health-table").html(l)}else $("#site-health-table").html('

    暂无熔断记录

    ');let n=Object.entries(s).sort(((l,c)=>c[1].count-l[1].count));if(n.length){let l='';for(let[c,h]of n){let u=h.lastUsed?new Date(h.lastUsed).toLocaleTimeString():"-";l+=``}l+="
    域名请求数错误数最后使用
    ${T(c)}${h.count}${h.errors}${u}
    ",l+=`

    共 ${n.length} 个域名

    `,$("#domain-stats-table").html(l)}else $("#domain-stats-table").html('

    暂无统计数据

    ');$(".reset-breaker").off("click").on("click",(l=>{let c=$(l.target).data("domain");o.resetCircuitBreaker(c),show.ok(`已重置 ${c} 的熔断状态`),Dt(o)})),$("#resetAllBreakersBtn").off("click").on("click",(()=>{o.resetAllCircuitBreakers(),show.ok("已重置全部熔断状态"),Dt(o)})),$("#clearDomainStatsBtn").off("click").on("click",(()=>{o.clearDomainStats(),show.ok("已清空域名统计"),Dt(o)}))}d(Dt,"renderNetworkPanel");async function as(){let o=await storageManager.getSnapshotList(),e={manual:"手动创建","auto-import":"导入前自动","auto-repair":"修复前自动","auto-restore":"恢复前自动"};if(o.length===0)return void $("#snapshot-list").html('
    暂无快照,点击上方按钮创建
    ');$("#snapshot-list").find(".tabulator").length&&$("#snapshot-list").empty();let t=ze(globalThis.Tabulator,"#snapshot-list",{pagination:!1,layout:"fitColumns",placeholder:"暂无数据",data:o,columnDefaults:{headerHozAlign:"center",hozAlign:"center"},columns:[{title:"名称",field:"name",width:200,headerSort:!1},{title:"来源",field:"source",width:100,headerSort:!1,formatter:d(s=>e[s.getValue()]||s.getValue(),"formatter")},{title:"时间",field:"time",width:170,headerSort:!1},{title:"数据量",field:"itemCount",width:80,headerSort:!1},{title:"操作",minWidth:220,headerSort:!1,formatter:d((s,a,r)=>{let i=s.getData();return r((()=>{let n=s.getElement().querySelector(".snap-restore"),l=s.getElement().querySelector(".snap-download"),c=s.getElement().querySelector(".snap-delete");n&&n.addEventListener("click",(async h=>{utils.q(h,`恢复到快照「${T(i.name)}」? 当前数据会自动备份。`,(async()=>{let u=loading();try{await storageManager.restoreSnapshot(i.id),show.ok("恢复成功, 页面将刷新"),setTimeout(()=>location.reload(),1e3)}catch(p){clog.error(p),show.error("恢复失败: "+(p instanceof Error?p.message:String(p)))}finally{u.close()}}))})),l&&l.addEventListener("click",(async h=>{let u=loading();try{let p=await storageManager.getSnapshot(i.id);if(!p)throw new Error("快照不存在");utils.download(JSON.stringify(p.data),`snapshot_${String(i.name||"snapshot").replace(/[\\/:*?"<>|]/g,"_")}.json`),show.ok("下载成功")}catch(p){show.error("下载失败: "+(p instanceof Error?p.message:String(p)))}finally{u.close()}})),c&&c.addEventListener("click",(async h=>{utils.q(h,`删除快照「${T(i.name)}」?`,(async()=>{try{await storageManager.deleteSnapshot(i.id),show.ok("已删除"),as()}catch(u){clog.error(u),show.error("删除失败: "+(u instanceof Error?u.message:String(u)))}}))}))})),' '},"formatter")}]})}d(as,"renderSnapshotPanel");function ac(o,e,t=null,s){let a=o.summary,r=[];for(let[c,h]of Object.entries(o.stores)){if(h.status==="unchanged")continue;let u={store:c,status:h.status,oldCount:h.oldCount,newCount:h.newCount,added:h.added.length,removed:h.removed.length,modified:h.modified.length};r.push(u)}let i='
    ';if(i+='
    ',i+=`
    ${a.added}新增数据源
    `,i+=`
    ${a.removed}缺失数据源
    `,i+=`
    ${a.modified}有变更
    `,i+=`
    ${a.unchanged}无变化
    `,i+="
    ",r.length>0){i+='
    ';let c={added:"新增",removed:"缺失",modified:"变更",unchanged:"无变化"};for(let h of r)i+=``;i+="
    数据源状态当前导入新增删除修改
    ${T(h.store)}${c[h.status]||h.status}${h.oldCount}${h.newCount}${h.added||"-"}${h.removed||"-"}${h.modified||"-"}
    "}else i+='
    数据完全一致,无需导入
    ';i+='
    导入将覆盖当前数据,建议先创建快照备份
    ',i+="
    ";let n=r.length>0,l=s.open({type:1,title:"数据差异预览",content:i,area:utils.getResponsiveArea(["700px","auto"]),btn:n?["确认导入","取消"]:["知道了","取消"],anim:-1,yes:d(async c=>{if(!n)return void s.close(c);let h=loading();try{await storageManager.createSnapshot("导入前自动备份","auto-import"),t?(await storageManager.importData(t),show.ok("导入成功!"),setTimeout(()=>location.reload(),1e3)):e&&(await storageManager.importData(e),show.ok("导入成功!"),setTimeout(()=>location.reload(),1e3))}catch(u){clog.error(u),show.error("导入失败: "+(u instanceof Error?u.message:String(u)))}finally{h.close()}},"yes")})}d(ac,"showDiffPreview");async function $i(o,e=null){let t=o.exportSnapshot(),s=Ge(await storageManager.getSetting("disabledPlugins","[]")),a=t.legacyPlugins,r=d(S=>{let j=new Set(S);return a.filter((k=>j.has(k)||j.has(Tt(k))))},"effectiveDisabledNames"),{categories:i,pluginMeta:n}=Ql(),l=new Map((t.legacyPluginDescriptors||[]).map(S=>[S.name,S])),c=new Set(a),h="";for(let[S,j]of Object.entries(i)){let k=j.plugins.filter(x=>c.has(x));if(k.length){h+='
    ',h+=`

    ${T(j.label)}

    `;for(let x of k){let _=l.get(x)?.disableable===!1,R=s.includes(Tt(x)),L=n[x]?.[0]||x;h+='
    ',h+=`${T(L)}`,_?h+='核心':h+=``,h+="
    "}h+="
    "}}$("#plugin-mgmt-list").html(h);let u=r(s),p=a.length-u.length;$("#pm-total").text(a.length),$("#pm-enabled").text(p),$("#pm-disabled").text(u.length),$(".pm-toggle").off("change").on("change",async S=>{let j=$(S.target),k=j.data("plugin"),x=j.is(":checked"),_=!x,R=Ge(await storageManager.getSetting("disabledPlugins","[]")),L=Tt(k);if(x?R=R.filter(A=>A!==k&&A!==L):R.includes(L)||R.push(L),!e)throw new Error("SettingsService is unavailable");let N=d(A=>{let O=t.legacyPlugins,U=r(A);$("#pm-total").text(O.length),$("#pm-enabled").text(O.length-U.length),$("#pm-disabled").text(U.length)},"renderState");N(R);try{await e.set("disabledPlugins",JSON.stringify(R)),show.ok(`插件 "${k}" 已${x?"启用":"禁用"},刷新后生效`)}catch(A){j.prop("checked",_);let O=Ge(await storageManager.getSetting("disabledPlugins","[]"));N(O),clog.error("插件状态保存失败,已恢复",A),show.error(`插件 "${k}" 状态保存失败,已恢复`)}});let g=t.legacyStartup,m=t.legacyTimings,f=d(S=>Number.isFinite(S)?S.toFixed(1):"0.0","formatMs"),v=g?`
    就绪: ${f(g.readyMs)} ms注册: ${f(g.registrationMs)} ms样式: ${f(g.cssMs)} ms即时插件: ${f(g.immediateMs)} ms空闲任务: ${g.idleCompleted}/${g.idleCompleted+g.idlePending}

    就绪耗时不包含 @require 下载及浏览器脚本解析时间。

    `:"";if(m.length){let S=[...m].sort(((k,x)=>x.elapsed-k.elapsed)),j='';for(let k of S){let x=k.status==="disabled"?"is-muted":k.elapsed>500?"is-slow":k.elapsed>200?"is-warning":"",_=k.status==="disabled"?"已禁用":k.status==="error"?"错误":k.status==="pending-idle"?"等待空闲":k.status==="skipped-mobile"?"移动端跳过":"正常";j+=``}j+="
    插件阶段耗时(ms)状态
    ${T(k.name)}${k.startupMode==="idle"?"空闲":"即时"}${k.elapsed.toFixed(1)}${_}
    ",$("#plugin-timing-table").html(v+j)}else $("#plugin-timing-table").html(v+'

    暂无数据,刷新页面后自动采集。

    ');let b=t.errors.filter(S=>S.source==="legacy-plugin");if(b.length){let S='';for(let j of[...b].reverse())S+=``;S+="
    时间插件阶段错误信息
    ${T(String(j.timestamp||"").substring(11,19))}${T(j.plugin)}${T(j.phase)}${T(j.message)}
    ",$("#plugin-error-log").html(S)}else $("#plugin-error-log").text("无错误记录");let w=storageManager.getCacheHitStats();$("#cache-hit-stats").html(`
    命中: ${w.hits}未命中: ${w.misses}总计: ${w.total}命中率: ${w.rate}
    `)}d($i,"renderPluginMgmtPanel");async function rs(){let o=$("#health-data-display");if(o.length){o.text("体检中...");try{let e=await storageManager.inspectDataHealth(),t=e.fixable.reduce(((r,i)=>r+i.count),0),s=e.readonly.reduce(((r,i)=>r+i.count),0),a=d(r=>r.length?r.map((i=>`
  • ${T(i.message)}:${i.count}
  • `)).join(""):"
  • 无
  • ","i");o.html(`
    番号记录:${e.totals.carList}
    收藏演员:${e.totals.favoriteActresses}
    黑名单演员:${e.totals.blacklist}
    黑名单作品:${e.totals.blacklistCarList}
    -
    体检时间:${C(e.checkedAt)};可修复问题 ${t} 项,只读问题 ${s} 项。
    +
    体检时间:${T(e.checkedAt)};可修复问题 ${t} 项,只读问题 ${s} 项。

    可安全修复

      ${a(e.fixable)}

    仅报告

      ${a(e.readonly)}
    - `)}catch(e){clog.error(e),o.text("体检失败: "+e)}}}d(rs,"renderDataHealthPanel");async function ac(){let o=JSON.stringify(await storageManager.exportData()),e=`health-backup-${utils.getNowStr("_","_")}.json`;utils.download(o,e);let t=await storageManager.repairDataHealth();show.ok(`已修复 ${t.fixedGroups} 组数据问题,修复前备份已下载`),await rs()}d(ac,"repairDataHealthWithBackup");var $i=class $i extends I{constructor(){super(...arguments),P(this,"folderName","JHS-数据备份"),P(this,"resourceSettings",new nt),P(this,"pendingCarImport",null),P(this,"taskStatusUnsubscribe",null),P(this,"_desktopSettingNavMounted",!1),P(this,"_settingScope",null),P(this,"_settingNavResizeCleanup",null),P(this,"_desktopNavGeneration",0),P(this,"_settingsDialogGeneration",0),P(this,"_fullSettingBinding",null),P(this,"_cloudSettingBinding",null),P(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及热播的评分数据"},{key:"third_party_ttl_cache",text:"第三方TTL缓存",title:"评论、相关清单、磁力搜索、缩略图等请求缓存"},{key:"_circuitBreaker",text:"熔断状态",title:"各站点的熔断计数和状态"},{key:"_domainStats",text:"域名请求统计",title:"各域名的请求次数和错误统计"}])}getName(){return"SettingPlugin"}getFormDependencies(){return Object.freeze({otherSite:this.getOptionalDependency("OtherSitePlugin"),listPage:this.getOptionalDependency("ListPagePlugin"),translate:this.getOptionalDependency("TranslatePlugin"),actressInfo:this.getOptionalDependency("ActressInfoPlugin"),screenshot:this.getOptionalDependency("ScreenShotPlugin"),newVideo:this.getOptionalDependency("NewVideoPlugin"),blacklist:this.getOptionalDependency("BlacklistPlugin"),busImg:this.getOptionalDependency("BusImgPlugin"),host:this.getRuntimeService("host"),movie:this.getRuntimeService("movie"),settings:this.getRuntimeService("settings"),settingsRegistry:this.getRuntimeService("settingsRegistry"),webdav:this.getRuntimeService("webdav")})}async initCss(){let e=this.getRuntimeService("settings").snapshot(),t=e?.containerWidth??"100";utils.isMobileMode()&&(t="100");let s=utils.isMobileMode()?1:e?.containerColumns??5;return fi(e,{busImgPlugin:this.getOptionalDependency("BusImgPlugin"),hostAdapter:this.getRuntimeService("host")}).catch((a=>clog.error("[JHS] applyLayoutFromSettings failed:",a))),zl(t,s,B,M)}async handle(){let e=this.getRuntimeService("settings");this.resourceSettings=new nt({getSetting:d(async(i=null,n)=>i===null?e.snapshot():Object.prototype.hasOwnProperty.call(e.snapshot(),i)?e.snapshot()[i]:n,"getSetting"),saveSettingItem:d((i,n)=>e.set(i,n),"saveSettingItem"),updateSetting:d(i=>e.update(i),"updateSetting"),patch:d(i=>e.patch(i),"patch")}),await storageManager.getSetting("enableClog",R)===R&&clog.show();let t=await this.getRuntimeService("scope")();this._settingScope=t;let s=this.getRuntimeService("settings"),a=d(i=>{let n=i.detail?.names||[];n.length&&(n.includes("themeMode")&&Ht(s.snapshot().themeMode),n.includes("enableClog")&&(s.snapshot().enableClog==="yes"?clog.show():clog.hide()),n.some(l=>["mobileMode","enableVerticalModel","containerColumns","containerWidth"].includes(l))&&fi(s.snapshot(),{busImgPlugin:this.getOptionalDependency("BusImgPlugin"),hostAdapter:this.getRuntimeService("host")}).catch(l=>clog.error("布局设置应用失败",l)))},"onSettingsChanged");s.addEventListener("settings.changed",a),t.addCleanup((()=>s.removeEventListener("settings.changed",a)));let r=d(async(i="backup-panel")=>{try{return await this.openSettingDialog(i)}catch(n){throw clog.error("设置中心打开失败",n),show.error("设置中心打开失败"),n}},"openSettings");t.addCleanup(gl(r)),t.listen(document,"click",(i=>{i.target instanceof Element&&i.target.closest("#setting-btn, #mini-setting-btn")&&(i.preventDefault(),$(".simple-setting, .mini-simple-setting").each((l,c)=>et(c)),clog.lowZIndex(),r().catch((()=>{})))})),t.addCleanup((()=>this.unmountDesktopSettingNav())),this.syncDesktopSettingNav(this.getRuntimeService("profile").current()==="compact")}syncDesktopSettingNav(e){e?this.unmountDesktopSettingNav():this.mountDesktopSettingNav()}mountDesktopSettingNav(){if(this._desktopSettingNavMounted)return;let e=this._settingScope;if(!e)return;this._desktopSettingNavMounted=!0;let t=this._desktopNavGeneration;if(M){let s=d(function(){$(".navbar-search").is(":hidden")?($(".mini-setting-box").hide(),$(".setting-box").show()):($(".mini-setting-box").show(),$(".setting-box").hide())},"e");$("#navbar-menu-user .navbar-end").prepend(` - `)}),1,1e4,!1,e)),$(".main-nav, .container-fluid").off("mouseenter.jhsSettingQuick mouseleave.jhsSettingQuick").on("mouseenter.jhsSettingQuick",".setting-box",(async s=>{let a=$(s.currentTarget).find(".simple-setting");et(a),a.html(Us(this.getRuntimeService("settingsRegistry"))).show();try{await Os(this.getFormDependencies(),this.getSelector.bind(this),this.openSettingDialog.bind(this),a)}catch(r){clog.warn("桌面快捷设置初始化失败",r)}clog.lowZIndex()})).on("mouseleave.jhsSettingQuick",".setting-box",(s=>{et($(s.currentTarget).find(".simple-setting"))})).on("mouseenter.jhsSettingQuick",".mini-setting-box",(async s=>{let a=$(s.currentTarget).find(".mini-simple-setting");et(a),a.html(Us(this.getRuntimeService("settingsRegistry"))).show();try{await Os(this.getFormDependencies(),this.getSelector.bind(this),this.openSettingDialog.bind(this),a)}catch(r){clog.warn("迷你快捷设置初始化失败",r)}clog.lowZIndex()})).on("mouseleave.jhsSettingQuick",".mini-setting-box",(s=>{et($(s.currentTarget).find(".mini-simple-setting"))}))}unmountDesktopSettingNav(){this._desktopNavGeneration++,this._desktopSettingNavMounted=!1,this._settingNavResizeCleanup?.(),this._settingNavResizeCleanup=null,$(".simple-setting, .mini-simple-setting").each((e,t)=>et(t)),$(".jhs-setting-nav-item, .jhs-mini-setting-box, .jhs-setting-anchor, .jhs-setting-detail-anchor").remove(),$(".main-nav, .container-fluid").off("mouseenter.jhsSettingQuick mouseleave.jhsSettingQuick")}async openQuickSetting(){$("#jhs-quick-setting-backdrop, #jhs-quick-setting-sheet").remove();let e=document.activeElement;await this.getRuntimeService("settings").waitForIdle();let t=!1,s=d((n=!0)=>{if(t)return;t=!0,$(document).off("keydown.jhsQuickSetting");let l=$("#jhs-quick-setting-sheet .jhs-quick-setting");et(l),$("#jhs-quick-setting-backdrop, #jhs-quick-setting-sheet").remove(),n&&e?.isConnected&&typeof e.focus=="function"&&e.focus()},"closeQuickSetting"),a=$('
    '),r=$(``),i=r.find(".jhs-quick-setting");i.html(zs(this.getRuntimeService("settingsRegistry"))),$("body").append(a,r),clog.lowZIndex(),a.on("click.jhsQuickSetting",(()=>s())),r.on("click.jhsQuickSetting",".jhs-quick-setting__close",(()=>s())),$(document).off("keydown.jhsQuickSetting").on("keydown.jhsQuickSetting",(n=>{if(n.key==="Escape")return n.preventDefault(),s();if(n.key!=="Tab")return;let l=r.find('a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])').filter(((u,p)=>!p.hidden&&p.getAttribute("aria-hidden")!=="true"));if(!l.length)return void n.preventDefault();let c=l[0],h=l[l.length-1];n.shiftKey&&document.activeElement===c?(n.preventDefault(),h.focus()):!n.shiftKey&&document.activeElement===h&&(n.preventDefault(),c.focus())}));try{await Us(this.getFormDependencies(),this.getSelector.bind(this),(n=>{s(!1),this.openSettingDialog(n).catch((l=>clog.error("完整设置打开失败",l)))}),i),r.find(".jhs-quick-setting__close").trigger("focus")}catch(n){s(),clog.error("快捷设置初始化失败",n),show.error("快捷设置加载失败")}}async openSettingDialog(e="backup-panel",t){await this.getRuntimeService("settings").waitForIdle();let s=Yl(e,this.cacheItems);this.getRuntimeService("dialog").open({type:1,title:"设置",content:s,ui:{size:"lg",body:"scroll"},area:utils.getDialogArea("lg"),scrollbar:!1,success:d(async(a,r)=>{let i=++this._settingsDialogGeneration,n=$(a);this._settingsFocusCleanup?.(),this._settingsFocusCleanup=utils.trapFocus(n[0]),n.data("jhsSettingsGeneration",i),n.find(".layui-layer-content").css("position","relative"),this.renderTaskStatuses(n),Zl(),Xl(),ec(),tc(),sc();let l=this.hydrateLiveSettings(n);this._fullSettingBinding=l,this.bindClick(n),n.find(".side-menu-item.active").attr("aria-current","page"),utils.setupEscClose(r),t&&t(),this.renderTaskStatuses(n),this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=V.on("task-status-changed",(()=>this.renderTaskStatuses(n))),utils.isMobileMode()&&this.collapseAdvancedTabs(n);let c=await Promise.allSettled([this.hydrateSettingForm(a,i),this.loadResourceSettings(a,i)]),h=c[1];K.refreshAll(a),h.status==="rejected"&&(clog.error("resource-settings 加载失败",h.reason),this.getRuntimeService("diagnostics").recordError({source:"resource-settings",message:h.reason?.message||String(h.reason)}),show.error("资源设置加载失败,基本设置仍可保存"))},"success"),end:d(()=>{this._settingsDialogGeneration++,this._fullSettingBinding?.dispose?.(),this._fullSettingBinding=null,this._cloudSettingBinding?.dispose?.(),this._cloudSettingBinding=null,this._settingsFocusCleanup?.(),this._settingsFocusCleanup=null,this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=null,this.getOptionalDependency("CoverButtonPlugin")?.enableSvgBtn?.()},"end")})}hydrateLiveSettings(e){let t=$(e),s=t.find("#jhs-live-settings"),a=this.getRuntimeService("settingsRegistry"),r=this.getRuntimeService("settings"),i=this.getRuntimeService("host"),n=new Set(["needClosePage","themeMode","mobileMode","enableClog","containerColumns","containerWidth"]),l=a.list({surfaces:["full"]}).filter(p=>(p.effect||"live")==="live"&&p.section!=="cloud"&&!n.has(p.key));s.length&&l.forEach(p=>{let{row:g}=Os(p,{value:r.snapshot()[p.key]??p.defaultValue});s.append(g)});let c=s.length?ts(s,l,{settings:r}):null,h=[],u=d(p=>{let g=Vl({settings:r,root:t,...p});g&&h.push(g)},"registerStatic");return u({selector:"#needClosePageBasic",key:"needClosePage",getValue:d(()=>t.find("#needClosePageBasic").is(":checked")?"yes":"no","getValue"),setValue:d(p=>t.find("#needClosePageBasic").prop("checked",p==="yes"||p===!0),"setValue"),fallback:"yes",label:"鉴定后立即关闭"}),u({selector:"#themeMode",key:"themeMode",getValue:d(()=>t.find("#themeMode").val(),"getValue"),setValue:d(p=>t.find("#themeMode").val(String(p??"")),"setValue"),fallback:"light",label:"主题"}),u({selector:"#mobileMode",key:"mobileMode",getValue:d(()=>t.find("#mobileMode").val(),"getValue"),setValue:d(p=>t.find("#mobileMode").val(String(p??"")),"setValue"),fallback:"auto",label:"移动模式"}),u({selector:"#enableClog",key:"enableClog",getValue:d(()=>t.find("#enableClog").val(),"getValue"),setValue:d(p=>t.find("#enableClog").val(String(p??"")),"setValue"),fallback:"yes",label:"日志"}),u({selector:"#containerColumns",key:"containerColumns",getValue:d(()=>Number(t.find("#containerColumns").val())||5,"getValue"),setValue:d(p=>ss(t,i,"containerColumns",p),"setValue"),fallback:5,label:"列表列数"}),u({selector:"#containerWidth",key:"containerWidth",getValue:d(()=>Number(t.find("#containerWidth").val())+70,"getValue"),setValue:d(p=>ss(t,i,"containerWidth",p),"setValue"),fallback:100,label:"列表宽度"}),u({selector:"#defaultQuickFilterTab",key:"defaultQuickFilterTab",getValue:d(()=>_e(t.find("#defaultQuickFilterTab").val()),"getValue"),setValue:d(p=>t.find("#defaultQuickFilterTab").val(_e(p)),"setValue"),fallback:"waitCheck",label:"列表默认筛选"}),!c&&!h.length?null:{sync:d(p=>{c?.sync?.(p);for(let g of h)g.sync?.(p)},"sync"),flush:d(async p=>{await c?.flush?.(p),await Promise.all(h.map(g=>g.flush?.(p)))},"flush"),dispose:d(()=>{c?.dispose?.();for(let p of h)p.dispose()},"dispose"),setters:c?.setters??{}}}async hydrateSettingForm(e,t){let s=$(e).find("#saveBtn"),a=$(e).find("#settings-hydration-status");s.attr("data-jhs-settings-ready","false").prop("disabled",!0).attr("title","正在加载设置…"),a.empty().text("正在加载设置…");let r=$(e);try{return await Kl(this.getFormDependencies(),r),!s[0]?.isConnected||t!==this._settingsDialogGeneration||r.data("jhsSettingsGeneration")!==t?!1:(K.refreshAll(e),s.attr("data-jhs-settings-ready","true").prop("disabled",!1).removeAttr("title"),a.empty().text("设置已加载"),!0)}catch(i){if(!s[0]?.isConnected||t!==this._settingsDialogGeneration||r.data("jhsSettingsGeneration")!==t)return!1;clog.error("settings-form 加载失败",i),this.getRuntimeService("diagnostics").recordError({source:"settings-form",message:i?.message||String(i)});let n=$('').on("click",(()=>{this.hydrateSettingForm(e,t)}));return a.empty().append(document.createTextNode("表单加载失败,已禁止保存。"),n),show.error("设置表单加载失败,保存已禁用"),!1}}renderTaskStatuses(e=null){let t=e?$(e).find("#setting-task-status-list"):$("#setting-task-status-list");if(!t.length)return;let s=this.getOptionalDependency("TaskPlugin");if(!s?.getTaskStatusSnapshot)return void t.empty();let a={blacklist:"黑名单",favoriteActress:"演员同步",newVideo:"新作品"},r={idle:"正常",running:"运行中",pending:"等待下一次任务检查",due:"待运行"},i=d(n=>n?new Date(n).toLocaleString():"无","format");t.empty(),["blacklist","favoriteActress","newVideo"].forEach((n=>{let l=s.getTaskStatusSnapshot(n),c=$('
    ');c.append($('').text(`${a[n]}:${r[l.state]}`)),c.append($('').text(`上次完成 ${i(l.completedAt)};下次检查 ${l.nextAt?i(l.nextAt):"立即"}`)),t.append(c)}))}collapseAdvancedTabs(e=null){let t=[{id:"health-panel",label:"数据体检",render:d(()=>rs(this.getRuntimeService("diagnostics")),"render")},{id:"plugin-mgmt-panel",label:"插件管理",render:d(()=>$i(this.getRuntimeService("diagnostics"),this.getRuntimeService("settings")),"render")},{id:"snapshot-panel",label:"恢复点",render:as},{id:"network-panel",label:"外部请求",render:d(()=>Dt(this.getRuntimeService("diagnostics")),"render")}],s=$(".jhs-mobile-sidebar"),a=$(".content-panel").parent();if(!s.length||!a.length||(t.forEach(l=>{s.find(`[data-panel="${l.id}"]`).remove()}),s.find('[data-panel="more-tools-panel"]').length||s.append(''),$("#more-tools-panel").length))return;let r=t.map((l,c)=>``).join(""),i=t.map((l,c)=>`
    `).join(""),n=`
    ${r}
    ${i}
    - `;a.append(n),t.forEach(l=>{let c=$(`#${l.id}`);c.length&&(c.children().appendTo(`#sub-${l.id}`),c.remove(),$(`#sub-${l.id}`).attr("data-rendered","true"))}),s.on("click",'[data-panel="more-tools-panel"]',function(){$(".side-menu-item").removeClass("active").attr("aria-current","false"),$(this).addClass("active").attr("aria-current","page"),$(".content-panel").hide(),$("#more-tools-panel").show(),$("#saveBtn").show(),$("#clean-all").addClass("jhs-is-hidden")}),$("#more-tools-panel").on("click",".jhs-sub-tab",function(){let l=$(this).data("sub-panel");$("#more-tools-panel .jhs-sub-tab").removeClass("active").attr({"aria-selected":"false",tabindex:"-1"}),$(this).addClass("active").attr({"aria-selected":"true",tabindex:"0"}),$("#more-tools-panel .jhs-sub-panel").removeClass("active"),$(`#sub-${l}`).addClass("active"),$(`#sub-${l}`).attr("data-rendered")!=="true"&&$(`#sub-${l}`).attr("data-rendered","true");let c=t.find(h=>h.id===l);c&&c.render&&c.render()}).on("keydown",".jhs-sub-tab",function(l){if(!["ArrowLeft","ArrowRight","Home","End"].includes(l.key))return;l.preventDefault();let c=$("#more-tools-panel .jhs-sub-tab"),h=c.index(this),u=l.key==="Home"?0:l.key==="End"?c.length-1:l.key==="ArrowRight"?(h+1)%c.length:(h-1+c.length)%c.length;c.eq(u).trigger("click").trigger("focus")})}bindClick(e=null){let t=this,s=this.getRuntimeService("webdav"),a=this.getRuntimeService("dialog"),r=this.getRuntimeService("diagnostics"),i=this.getRuntimeService("storage"),n=this.getRuntimeService("translation"),l=d((m,f,v=null)=>sc(m,f,v,a),"previewDiff"),c=e?$(e):$(document);c.find("#saveBtn").attr("data-jhs-settings-ready","false").prop("disabled",!0).attr("title","正在加载设置…"),c.find(".side-menu-item").on("click",(function(){c.find(".side-menu-item").removeClass("active").attr("aria-current","false"),$(this).addClass("active").attr("aria-current","page"),c.find(".content-panel").hide();let m=$(this).data("panel");c.find("#"+m).show(),m==="cache-panel"?(c.find("#saveBtn").hide(),c.find("#clean-all").removeClass("jhs-is-hidden")):(c.find("#saveBtn").show(),c.find("#clean-all").addClass("jhs-is-hidden")),m==="health-panel"&&(c.find("#saveBtn").hide(),c.find("#clean-all").addClass("jhs-is-hidden"),rs()),m==="plugin-mgmt-panel"&&(c.find("#saveBtn").hide(),c.find("#clean-all").addClass("jhs-is-hidden"),_i(t.getRuntimeService("diagnostics"),t.getRuntimeService("settings"))),m==="snapshot-panel"&&(c.find("#saveBtn").hide(),c.find("#clean-all").addClass("jhs-is-hidden"),as()),m==="network-panel"&&(c.find("#saveBtn").hide(),c.find("#clean-all").addClass("jhs-is-hidden"),Et(r))})),c.find("#importBtn").on("click",(m=>Ll(l))),c.find("#exportBtn").on("click",(m=>Ul())),c.find("#preview-car-number-import").on("click",(()=>this.previewCarNumbers(c))),c.find("#confirm-car-number-import").on("click",(async m=>this.confirmCarNumbers(m,c))),c.find("#webdavBackupBtn").on("click",(m=>Ml(this.folderName,s))),c.find("#webdavBackupListBtn").on("click",(m=>Bl(this.folderName,(f,v,b)=>Ol(f,v,b,this.folderName,l,a),s))),c.find("#saveBtn").on("click",(async m=>{let f=$(m.currentTarget);if(!(f.data("jhsBusy")||f.attr("data-jhs-settings-ready")!=="true")){f.data("jhsBusy",!0).prop("disabled",!0).attr("aria-busy","true");try{if(await this._fullSettingBinding?.flush?.({throwOnFailure:!0}),(await Kl(this.getFormDependencies(),c))?.canceled)return;show.ok("保存成功")}catch(v){v?.partialFailure?show.error("部分设置保存失败,请重试"):show.error("设置保存失败"),clog.error("设置保存失败",v)}finally{f.removeData("jhsBusy").prop("disabled",f.attr("data-jhs-settings-ready")!=="true").removeAttr("aria-busy")}}})),c.find("#runHealthCheckBtn").on("click",(()=>rs())),c.find("#repairHealthBtn").on("click",(m=>{utils.q(m,"修复前会自动下载备份,是否继续?",(()=>ac()))})),c.find("#pm-clear-log").on("click",(()=>{this.getRuntimeService("diagnostics").clearErrors(),c.find("#plugin-error-log").text("无错误记录"),show.ok("错误日志已清空")})),c.find("#createSnapshotBtn").on("click",(async()=>{let m=loading();try{await storageManager.createSnapshot("手动快照","manual"),show.ok("快照创建成功"),as()}catch(f){clog.error(f),show.error("创建快照失败: "+f.message)}finally{m.close()}})),c.find(".clean-btn").on("click",(async m=>{let f=$(m.currentTarget).data("key"),v=this.cacheItems.find((b=>b.key===f));f===storageManager.third_party_cache_key?(await storageManager.clearThirdPartyCache(),await this.getRuntimeService("cache").clearNamespace("external-detail-v1")):f==="_circuitBreaker"?r.resetAllCircuitBreakers():f==="_domainStats"?r.clearDomainStats():f==="jhs_translate"?await n.clearCache():f==="jhs_actress_info"?(await this.getRuntimeService("cache").clearNamespace("actress-info"),await i.removeLocal(f)):f==="jhs_screenShot"?(await this.getRuntimeService("cache").clearNamespace("screenshot"),await i.removeLocal(f)):i.removeLocal(f),show.ok(`${v.text} 清理成功`),c.find("#cache-data-display").addClass("jhs-is-hidden"),f==="jhs_dmm_video"&&i.removeLocal("jhs_other_site_dmm")})),c.find("#clean-all").on("click",(async()=>{this.cacheItems.forEach((m=>m.key!=="jhs_translate"&&i.removeLocal(m.key))),await n.clearCache(),await this.getRuntimeService("cache").clearAll(),show.ok("全部缓存已清理"),c.find("#cache-data-display").addClass("jhs-is-hidden"),i.removeLocal("jhs_other_site_dmm"),await storageManager.clearThirdPartyCache()})),c.find(".view-btn").on("click",(async m=>{let f=$(m.currentTarget).data("key"),v;f===storageManager.third_party_cache_key?v=JSON.stringify(await storageManager.getThirdPartyCache()):f==="_circuitBreaker"?v=JSON.stringify(r.getNetworkDiagnostics().circuitBreakers):f==="_domainStats"?v=JSON.stringify(r.getNetworkDiagnostics().domainStats):f==="jhs_translate"?v=JSON.stringify(await n.inspectCache()):v=i.getLocal(f);let b=c.find("#cache-data-display"),w=b.find("pre");if(b.removeClass("jhs-is-hidden"),v)try{let S=JSON.parse(v);w.text(JSON.stringify(S,null,2))}catch{w.text(v)}else w.text("无数据")}));let h=c.find("#highlightedTagNumber"),u=c.find("#highlightedTagColor"),p=c.find("#highlightedTagLabel");function g(){let m=h.val(),f=u.val();p.css("border",`${m}px solid ${f}`)}d(g,"updatePreview"),h.on("input",g),u.on("input",g)}async loadResourceSettings(e=null,t=this._settingsDialogGeneration){let s=e?$(e):$(document),[a,r,i,n,l,c]=await Promise.all([this.resourceSettings.getMagnetSources(),this.resourceSettings.getMagnetTagRules(),this.resourceSettings.getMagnetFilterRules(),this.resourceSettings.getBuiltInSources(),this.resourceSettings.getScreenshotSettings(),this.resourceSettings.getCloudSettings()]);if(e&&(!s[0]?.isConnected||t!==this._settingsDialogGeneration))return;let h=[...Ns,...this.getRuntimeService("magnet").getBuiltInSources()];this.resourceState={custom:a,tags:r,filters:i,builtIn:h.map((u=>({...u,...n.find((p=>p.id===u.id))||{}}))),screenshot:{mode:l.mode,providers:Ls.map((u=>{let p={...u,...l.providers.find((g=>g.id===u.id))||{}};return u.implemented===!1?{...p,enabled:!1}:p}))}},this.renderResourceSettings(s),this.renderCloudSettings(s,c),s.find("#resource-sources-panel").off("change.jhsResource",'input[name="screenshotMode"]').on("change.jhsResource",'input[name="screenshotMode"]',(u=>{let p=this.resourceState.screenshot.mode;this.resourceState.screenshot.mode=u.currentTarget.value,this.resourceSettings.saveScreenshotMode(this.resourceState.screenshot.mode).catch(g=>{this.resourceState.screenshot.mode=p,s.find(`input[name="screenshotMode"][value="${p}"]`).prop("checked",!0),clog.error("截图模式保存失败",g),show.error("截图模式保存失败,已恢复原设置")})})),s.find("#add-custom-magnet-source").off("click.jhsResource").on("click.jhsResource",(()=>this.openSourceDialog(null,s))),s.find("#add-magnet-tag-rule").off("click.jhsResource").on("click.jhsResource",(()=>this.openRuleDialog("tag",null,s))),s.find("#add-magnet-filter-rule").off("click.jhsResource").on("click.jhsResource",(()=>this.openRuleDialog("filter",null,s))),s.find("#export-resource-config").off("click.jhsResource").on("click.jhsResource",(async()=>{let u=JSON.stringify(await this.resourceSettings.exportConfig(),null,2);s.find("#advanced-resource-json").val(u).prop("readonly",!0)})),s.find("#edit-resource-config").off("click.jhsResource").on("click.jhsResource",(()=>s.find("#advanced-resource-json").prop("readonly",!1).trigger("focus"))),s.find("#import-resource-config").off("click.jhsResource").on("click.jhsResource",(async()=>{try{await this.resourceSettings.importConfig(s.find("#advanced-resource-json").val()),show.ok("资源配置导入成功"),await this.loadResourceSettings(s,t),K.refreshAll()}catch(u){show.error(u.message)}})),s.find("#car-number-import,#car-number-import-status").off("input.jhsResource change.jhsResource").on("input.jhsResource change.jhsResource",(()=>{this.pendingCarImport=null,s.find("#confirm-car-number-import").prop("disabled",!0).text("确认导入")})),s.find("#check-one-one-five-login").off("click.jhsResource").on("click.jhsResource",(()=>this.checkOneOneFiveLogin(s)))}renderCloudSettings(e,t){let s=e.find("#cloud-settings-catalog");if(!s.length)return;this._cloudSettingBinding?.dispose?.();let a=this.getRuntimeService("settingsRegistry"),r=this.getRuntimeService("settings"),i=a.list({surfaces:["full"]}).filter(l=>l.section==="cloud");s.empty();let n=d(l=>l==="offlineProviderMode"?t.providerMode:l==="oneOneFiveConcurrency"?t.concurrency:l==="oneOneFiveCacheMinutes"?t.cacheMinutes:t[l],"valueFor");i.forEach(l=>{let c=Bs(l,{value:n(l.key)});c.root.attr("id",l.key),s.append(c.row)}),this._cloudSettingBinding=ts(s,i,{settings:r})}renderResourceSettings(e=$(document)){let t=d((s,a,r)=>{let i=$('
    ');i.append($('
    ').append($("
    ").append($("").text(s.name),s.experimental?'实验性':"",$("").text(`${s.type||"截图来源"} · ${s.domain||(()=>{try{return new URL(s.searchUrlTemplate).hostname}catch{return"未配置域名"}})()} · 优先级 ${s.priority}`)),$('').prop("checked",s.enabled)));let n=$('
    ').append('');return a&&n.append(''),i.append(n),i.on("change",".jhs-source-toggle",async l=>{let c=!l.currentTarget.checked;s.enabled=l.currentTarget.checked;try{r==="screenshot"?await this.resourceSettings.updateArray("screenshotProviders",h=>{let u=h.find((p=>p.id===s.id));return u?u.enabled=s.enabled:h.push({id:s.id,enabled:s.enabled}),h}):a?await this.resourceSettings.updateArray("customMagnetSources",h=>{let u=h.find((p=>p.id===s.id));return u&&(u.enabled=s.enabled),h}):await this.resourceSettings.updateArray("magnetBuiltInSources",h=>{let u=h.find((p=>p.id===s.id));return u?u.enabled=s.enabled:h.push({id:s.id,enabled:s.enabled}),h}),this.renderResourceSettings(e)}catch{s.enabled=c,$(l.currentTarget).prop("checked",c),show.error("来源设置保存失败,已恢复原设置")}}),i.on("click",".jhs-source-test",l=>this.testSource(l.currentTarget,s.baseUrl||s.searchUrlTemplate?.replace("{keyword}","test"),{custom:a,source:s})),a&&i.on("click",".jhs-source-edit",(()=>this.openSourceDialog(s,e))).on("click",".jhs-source-delete",(l=>utils.q(l,`确认删除来源「${C(s.name)}」?`,(async()=>{try{await this.resourceSettings.updateArray("customMagnetSources",c=>c.filter((h=>h.id!==s.id))),this.resourceState.custom=await this.resourceSettings.getMagnetSources(),this.renderResourceSettings(e)}catch(c){show.error(c.message)}})))),i},"card");e.find("#builtin-magnet-source-list").empty().append(this.resourceState.builtIn.map((s=>t(s,!1,"magnet")))),e.find("#custom-magnet-source-list").empty().append(this.resourceState.custom.length?this.resourceState.custom.map((s=>t(s,!0,"magnet"))):'

    暂无自定义来源

    '),e.find("#screenshot-source-list").empty().append(this.resourceState.screenshot.providers.map((s=>t(s,!1,"screenshot")))),this.resourceState.screenshot.providers.forEach(((s,a)=>{s.implemented===!1&&e.find("#screenshot-source-list .jhs-resource-card").eq(a).find(".jhs-source-toggle").prop("disabled",!0).end().find("strong").after('未实现').end().find(".jhs-source-test").remove()})),e.find(`input[name="screenshotMode"][value="${this.resourceState.screenshot.mode}"]`).prop("checked",!0),this.renderRules("tag",e),this.renderRules("filter",e)}renderRules(e,t=$(document)){let s=e==="tag"?this.resourceState.tags:this.resourceState.filters,a=t.find("#magnet-"+e+"-rule-list").empty();s.length||a.append('

    暂无规则

    '),s.forEach((r=>{let i=$('
    ').append($("").text(r.name),$("

    ").text(`${r.type==="regex"?"正则":"包含"}:${r.pattern}${e==="tag"?` · 权重 ${Number(r.weight)>=0?"+":""}${r.weight||0}`:` · ${r.action==="hide"?"隐藏":`降权 ${r.penalty||-20}`}`}`),'
    ');i.on("click",".jhs-rule-edit",(()=>this.openRuleDialog(e,r,t))).on("click",".jhs-rule-delete",(n=>utils.q(n,`确认删除规则「${C(r.name)}」?`,(async()=>{try{await this.resourceSettings.updateArray(e==="tag"?"magnetTagRules":"magnetFilterRules",l=>l.filter((c=>c.id!==r.id))),this.resourceState[e==="tag"?"tags":"filters"]=await this.resourceSettings.getArray(e==="tag"?"magnetTagRules":"magnetFilterRules"),this.renderRules(e,t)}catch(l){show.error(l.message)}})))),a.append(i)}))}openSourceDialog(e=null,t=null){let s=this.getRuntimeService("dialog"),a=["rowSelector","titleSelector","magnetSelector","sizeSelector","dateSelector","seedersSelector","leechersSelector","resultsPath","titlePath","magnetPath","hashPath","sizePath","datePath","seedersPath"],r=$('
    '),i=d(()=>{let n=r.find('[name="parserType"]').val(),l=n==="torrent-table"?a.slice(0,7):n==="json"?a.slice(7):[];r.find(".jhs-parser-fields").html(l.map((c=>``)).join("")),l.forEach((c=>r.find(`[name="${c}"]`).val(e?.[c]||"")))},"renderFields");Object.entries(e||{enabled:!0,priority:100,parserType:"magnet-links"}).forEach(([n,l])=>{let c=r.find(`[name="${n}"]`);c.attr("type")==="checkbox"?c.prop("checked",l):c.val(l)}),r.on("change",'[name="parserType"]',i),i(),r.appendTo("body").hide(),s.open({type:1,title:e?"编辑自定义磁力源":"添加自定义磁力源",content:r,ui:{size:"md",body:"scroll"},area:utils.getDialogArea("md"),btn:["保存","取消"],success:d(()=>r.show(),"success"),end:d(()=>r.remove(),"end"),yes:d(async n=>{let l=Object.fromEntries(r.find("input,select").map(((c,h)=>[h.name,h.type==="checkbox"?h.checked:h.value])).get());try{let c=_l(l,e);await this.resourceSettings.updateArray("customMagnetSources",h=>{let u=e?h.findIndex((p=>p.id===e.id)):-1;return u>=0?h.splice(u,1,c):h.push(c),h}),this.resourceState.custom=await this.resourceSettings.getMagnetSources(),s.close(n),t&&this.renderResourceSettings(t)}catch(c){show.error(c.message)}},"yes")})}openRuleDialog(e,t=null,s=null){let a=this.getRuntimeService("dialog"),r=e==="tag",i=$(`
    ${r?"":''}${r?'':''}
    `);Object.entries(t||{enabled:!0,type:"contains",weight:0,action:"hide",penalty:-20}).forEach(([n,l])=>{let c=i.find(`[name="${n}"]`);c.attr("type")==="checkbox"?c.prop("checked",l):c.val(l)}),i.appendTo("body").hide(),a.open({type:1,title:`${t?"编辑":"新建"}${r?"标签":"过滤"}规则`,content:i,ui:{size:"sm",body:"scroll"},area:utils.getDialogArea("sm"),btn:["保存","取消"],success:d(()=>i.show(),"success"),end:d(()=>i.remove(),"end"),yes:d(async n=>{let l=Object.fromEntries(i.find("input,select").map(((c,h)=>[h.name,h.type==="checkbox"?h.checked:h.value])).get());l.id=t?.id||`rule-${Date.now()}`,l.weight=Number(l.weight),l.penalty=Number(l.penalty);try{Rt(l),await this.resourceSettings.updateArray(r?"magnetTagRules":"magnetFilterRules",c=>{let h=t?c.findIndex((u=>u.id===t.id)):-1;return h>=0?c.splice(h,1,l):c.push(l),c}),this.resourceState[r?"tags":"filters"]=await this.resourceSettings.getArray(r?"magnetTagRules":"magnetFilterRules"),a.close(n),s&&this.renderRules(e,s)}catch(c){show.error(c.message)}},"yes")})}async saveCloudSettings(e=$(document)){await this.resourceSettings.saveCloudSettings({enable123Offline:e.find("#enable123Offline").is(":checked"),enable115Offline:e.find("#enable115Offline").is(":checked"),providerMode:e.find("#offlineProviderMode").val(),enable115Match:e.find("#enable115Match").is(":checked"),enable115LoginRedirect:e.find("#enable115LoginRedirect").is(":checked"),concurrency:Number(e.find("#oneOneFiveConcurrency").val()),cacheMinutes:Number(e.find("#oneOneFiveCacheMinutes").val())})}async checkOneOneFiveLogin(e=$(document)){let t=e.find("#one-one-five-state").text("检测中");try{let s=await this.getRuntimeService("scope")(),a=await this.getRuntimeService("offline").checkAccount("one115",{scope:s});t.text(a.authenticated?"已登录":"未登录")}catch{t.text("检测失败")}}async testSource(e,t,s={}){if(!t)return show.info("本站来源无需跨站测试");let a=$(e).prop("disabled",!0),r=a.siblings(".jhs-source-test-state").length?a.siblings(".jhs-source-test-state"):$('').insertAfter(a);r.text("检测中");try{let i=new URL(t),n=await this.getRuntimeService("scope")(),l=await this.getRuntimeService("http").request({providerId:`settings-source-${s.source?.id||"unknown"}`,method:"GET",url:i.href,responseType:"text",cacheScope:"none",urlPolicy:s.custom?{trustClass:"custom-public"}:{trustClass:"builtin-public",hosts:[s.source?.domain||i.hostname]}},n);r.text(l.data?"200 · 可解析":"空响应")}catch(i){r.text(i?.code==="NOT_FOUND"?"404":i?.code==="RATE_LIMITED"?"限流":i?.code==="AUTH_REQUIRED"?"需要授权":"请求失败")}finally{a.prop("disabled",!1).text("测试")}}previewCarNumbers(e=$(document)){let t=yl(e.find("#car-number-import").val()),s=e.find("#car-number-import-status").val();this.pendingCarImport=s&&t.values.length?{...t,actionType:s}:null,e.find("#car-number-import-preview").text(`识别 ${t.recognized} 条 · 有效 ${t.values.length} · 重复 ${Math.max(0,t.recognized-t.values.length-t.invalid.length)} · 无效 ${t.invalid.length}${t.invalid.length?` · 异常示例:${t.invalid.slice(0,5).join("、")}`:""}`),e.find("#confirm-car-number-import").prop("disabled",!this.pendingCarImport).text(this.pendingCarImport?`确认导入 ${t.values.length} 条`:"确认导入"),s||show.info("请选择导入状态")}async confirmCarNumbers(e,t=$(document)){if(!this.pendingCarImport)return show.info("请先解析预览");let s=this.pendingCarImport;utils.q(e,`确认导入 ${s.values.length} 条记录?`,(async()=>{let a=new Map((await storageManager.getCarList()).map((h=>[T(h.carNum),h]))),r={added:0,updated:0,failed:0},i=Ce(s.actionType),n=this.getRuntimeService("state"),l=s.values.map(h=>{let u=T(h),p=a.get(u);return u?{carNum:u,url:p?.url||jl(u),names:p?.names||"",publishTime:p?.publishTime||""}:null}).filter(Boolean),c=75;for(let h=0;hp.carNum),{[i]:!0},{type:"manual-car-number-import",records:u}),u.forEach(p=>a.has(p.carNum)?r.updated++:r.added++)}catch(p){r.failed+=u.length,clog.warn("番号批量导入块失败",p)}}this.pendingCarImport=null,t.find("#confirm-car-number-import").prop("disabled",!0),show.ok(`导入完成:新增 ${r.added},更新 ${r.updated},失败 ${r.failed}`)}))}};d($i,"SettingPlugin");var zs=$i;async function He(o,e,t){let s=new URL(e,window.location.href),a=await o.request({providerId:"host-page",method:"GET",url:s.href,responseType:"text",cacheScope:"none",urlPolicy:{trustClass:"builtin-public",hosts:[window.location.hostname],expectedOrigin:window.location.origin}},t);return String(a.data??a.responseText??"")}d(He,"requestHostPage");function rc(o){let e=globalThis.$,t=o?.jquery?o:e(o),s=[];return t.find('.tags a[href^="/actors/"]').each((a,r)=>{let i=e(r).text().trim();i&&s.push(i)}),t.find('span[onmouseover*="star_"] a').each((a,r)=>{let i=e(r).text().trim();i&&s.push(i)}),[...new Set(s)].join(" ")}d(rc,"readCardNames");function _e(o){let e=globalThis.$,t=o?.jquery?o:e(o),s=t.find("a"),a=t.attr("data-jhs-original-url")||s.attr("href"),r=t.find(".video-title"),i,n,l;if(r.length){let h=r.find("strong");h.length&&(i=h.text().trim()),n=s.attr("title")?s.attr("title").trim():i?r.text().replace(i,"").trim():r.text().trim(),l=t.find(".meta").text().trim()}if(!i){let h=t.find("img");h.length&&(n=h.attr("title")?.trim()||h.attr("data-title")?.trim()||n);let u=t.find("date").map((p,g)=>e(g).text().trim()).get();l=u.find(p=>/^\d{4}-\d{1,2}-\d{1,2}$/.test(p)),i=u.find(p=>!/^\d{4}-\d{1,2}-\d{1,2}$/.test(p))}let c=ee(i);if(!c)throw new TypeError("提取番号信息失败");return Object.freeze({carNum:c,aHref:a,url:a,title:n,publishTime:l,fc2Source:["fc2","123av"].includes(t.attr("data-jhs-fc2-source"))?t.attr("data-jhs-fc2-source"):"fc2"})}d(_e,"readListItem");function Ti(o,e,t){for(let s of o)if(e.includes(s)||t.startsWith(s))return s;return null}d(Ti,"findMatchedTitleKeyword");function is(o={}){return{titleKeywords:Array.isArray(o.titleKeywords)?o.titleKeywords:[],carMap:o.carMap instanceof Map?o.carMap:new Map,actorCarNumToNameMap:o.actorCarNumToNameMap instanceof Map?o.actorCarNumToNameMap:new Map,actressCarNumToNameMap:o.actressCarNumToNameMap instanceof Map?o.actressCarNumToNameMap:new Map,recentCarNums:o.recentCarNums instanceof Set?o.recentCarNums:new Set,settings:o.settings??{}}}d(is,"createListEvaluationContext");function ns(o,e,{filter:t="waitCheck"}={}){let s=o?.carNum,a=s?e.carMap.get(s):null,r=q(a?.stateFlags),n={keyword:!!(e.titleKeywords.length&&s?Ti(e.titleKeywords,o.title||"",s):null),actorBlacklist:s?e.actorCarNumToNameMap.has(s):!1,actressBlacklist:s?e.actressCarNumToNameMap.has(s):!1},l=s?e.recentCarNums.has(s):!1,c=ft(r,n);return{flags:r,visibilityReasons:n,recent:l,hardHidden:c,matchesCurrentFilter:oi(t,r,{visibilityReasons:n,recent:l})}}d(ns,"evaluateListItem");function ic(o){return o.replace(/\/+$/,"")}d(ic,"stripTrailingSlashes");function nc(o,e){try{let t=new URL(o),s=new URL(e);return t.origin===s.origin&&ic(t.pathname)===ic(s.pathname)&&t.search===s.search}catch{return o===e}}d(nc,"isSamePageUrl");async function Fs({startDom:o,itemSelector:e,nextPageSelector:t,fetchHtml:s,parseItem:a,evaluate:r,isCancelled:i=d(()=>!1,"isCancelled"),onProgress:n=d(()=>{},"onProgress"),pageDelayMs:l=500,maxPages:c=200,currentUrl:h=null,firstPageUrl:u=null}){let p=[],g=new Set,m=o,f=1,v=0;if(u&&h&&!nc(u,h)){if(i())return p;let b=await s(u);if(i())return p;let w=new DOMParser().parseFromString(b,"text/html");m=$(w)}for(;m&&m.length&&!i();){n({page:f,scanned:v,matched:p.length});let b=m.find(e).toArray();for(let x of b){if(i())break;let k=null;try{k=a($(x))}catch{continue}if(!k?.carNum)continue;v++;let _=r(k);_?.matchesCurrentFilter&&!g.has(k.carNum)&&(g.add(k.carNum),p.push({...k,flags:_.flags,visibilityReasons:_.visibilityReasons,hardHidden:_.hardHidden}))}let w=m.find(t).attr("href");if(!w||i()||f>=c||(l&&await new Promise(x=>setTimeout(x,l)),i()))break;let S=await s(w),j=new DOMParser().parseFromString(S,"text/html");m=$(j),f++}return p}d(Fs,"scanAllPages");var Dt=null;function Vs(){if(Dt)return null;let o={id:Symbol("batch-run"),cancelRequested:!1};return Dt=o,o}d(Vs,"tryBeginBatchRun");function Nt(o){return Dt===o}d(Nt,"isActiveBatchRun");function oc(o){return!!o?.cancelRequested||!Nt(o)}d(oc,"isBatchRunCancelled");function lc(o){Dt===o&&o&&(o.cancelRequested=!0)}d(lc,"requestCancelBatchRun");function Hs(o){Dt===o&&(Dt=null)}d(Hs,"endBatchRun");function qs(o,e){let t=o.find("title, body").text(),s=/Just a moment|cf-chl-|Cloudflare/i.test(t),a=o.find(e.boxSelector).length>0;return{state:s?"challenge":a?"valid":"invalid",items:a?o.find(e.requestDomItemSelector):null,isEmpty:a&&o.find(e.requestDomItemSelector).length===0}}d(qs,"parseDetailPage");function cc(){if(!V)throw new Error("Blacklist EventBus 未初始化");return V}d(cc,"getBlacklistEventBus");var Ai=class Ai extends I{constructor(){super(...arguments),this.blacklistSearchDebounced=null,this.taskStatusUnsubscribe=null}getName(){return"BlacklistPlugin"}async initCss(){return``}async addBlacklist(e){let t={clientX:e.clientX,clientY:e.clientY+80},s=$("#addBlacklistBtn span").text().includes("已加入"),a,r;if(X.includes("/tags")){let p=new URL(X);p.searchParams.delete("page");let g=$("#jhs-check-tag").text().trim();a={starId:"no-"+g,name:"虚拟演员-"+g,allName:["虚拟演员"],role:"虚拟演员",movieType:g,blacklistUrl:p.toString()},r=`是否将分类 ${C(g)} 加入到黑名单中?`,s&&(r=`分类 ${C(g)} 已在黑名单中, 是否从当前页开始追加屏蔽?`)}else a=this.getActressPageInfo(),r=`是否将该演员 ${C(a.name)} 加入到黑名单中?`,s&&(r=`演员 ${C(a.name)} 已在黑名单中, 是否从当前页开始追加屏蔽?`);let{starId:i,name:n,allName:l,role:c,movieType:h,blacklistUrl:u}=a;if(X.includes("page")&&!X.includes("page=1")&&(r+="
    注意: 当前页面非第一页, 屏蔽数据将从此页面开始"),B){let p=X.split("/star/")[1].split("/");p.length>1&&parseInt(p[1])>1&&(r+="
    注意: 当前页面非第一页, 屏蔽数据将从此页面开始")}utils.q(t,r,(async()=>{let p=this.getOptionalDependency("TaskPlugin");if(!p)return void show.error("后台任务功能已禁用,无法执行黑名单抓取");navigator.locks.request(p.singleTaskKey,{ifAvailable:!0},(async g=>{if(clog.debug("获取锁",g),g){this.loadObj=loading();try{await storageManager.addBlacklistItem({starId:i,name:n,allName:l,role:c,movieType:h,url:u}),await this.filterActorVideo(n,i,null,B?Se:Be);let m=show.ok(`屏蔽结束,是否跳转到最后一页: ${this.lastPageLink}`,{duration:-1,close:!0,onClick:d(()=>{m.closeShow(),window.location.href=this.lastPageLink},"onClick")})}catch(m){clog.error(m);let f=show.error("发生错误, 是否填转到解析失败的那一页? (点击并跳转)",{duration:-1,close:!0,onClick:d(()=>{f.closeShow(),window.location.href=this.nextPageLink},"onClick")})}finally{this.loadObj.close()}}else show.error("当前有定时任务在后台执行中, 无法发起此操作")})).catch((g=>{clog.error("锁任务出现错误:",g)}))}))}async resetBtnTip(){let e=this.getOptionalDependency("TaskPlugin"),t=e?this.getRuntimeService("storage").getLocal(e.lastCheckBlacklistTimeKey)||"无":"任务已禁用",s=await storageManager.getSetting("checkBlacklist_intervalTime",12);this.checkBlacklist_ruleTime=await storageManager.getSetting("checkBlacklist_ruleTime",8760),(this.blacklistRoot||$()).find("#checkBlacklistBtn").attr("data-tip",`上次整批检测: ${t}; 检测间隔时间: ${s}小时`)}async openBlacklistDialog(){let e=this.getOptionalDependency("TaskPlugin"),t=await storageManager.getSetting(),a=` + `}async addBlacklist(e){let t={clientX:e.clientX,clientY:e.clientY+80},s=$("#addBlacklistBtn span").text().includes("已加入"),a,r;if(X.includes("/tags")){let p=new URL(X);p.searchParams.delete("page");let g=$("#jhs-check-tag").text().trim();a={starId:"no-"+g,name:"虚拟演员-"+g,allName:["虚拟演员"],role:"虚拟演员",movieType:g,blacklistUrl:p.toString()},r=`是否将分类 ${T(g)} 加入到黑名单中?`,s&&(r=`分类 ${T(g)} 已在黑名单中, 是否从当前页开始追加屏蔽?`)}else a=this.getActressPageInfo(),r=`是否将该演员 ${T(a.name)} 加入到黑名单中?`,s&&(r=`演员 ${T(a.name)} 已在黑名单中, 是否从当前页开始追加屏蔽?`);let{starId:i,name:n,allName:l,role:c,movieType:h,blacklistUrl:u}=a;if(X.includes("page")&&!X.includes("page=1")&&(r+="
    注意: 当前页面非第一页, 屏蔽数据将从此页面开始"),B){let p=X.split("/star/")[1].split("/");p.length>1&&parseInt(p[1])>1&&(r+="
    注意: 当前页面非第一页, 屏蔽数据将从此页面开始")}utils.q(t,r,(async()=>{let p=this.getOptionalDependency("TaskPlugin");if(!p)return void show.error("后台任务功能已禁用,无法执行黑名单抓取");navigator.locks.request(p.singleTaskKey,{ifAvailable:!0},(async g=>{if(clog.debug("获取锁",g),g){this.loadObj=loading();try{await storageManager.addBlacklistItem({starId:i,name:n,allName:l,role:c,movieType:h,url:u}),await this.filterActorVideo(n,i,null,B?Se:Be);let m=show.ok(`屏蔽结束,是否跳转到最后一页: ${this.lastPageLink}`,{duration:-1,close:!0,onClick:d(()=>{m.closeShow(),window.location.href=this.lastPageLink},"onClick")})}catch(m){clog.error(m);let f=show.error("发生错误, 是否填转到解析失败的那一页? (点击并跳转)",{duration:-1,close:!0,onClick:d(()=>{f.closeShow(),window.location.href=this.nextPageLink},"onClick")})}finally{this.loadObj.close()}}else show.error("当前有定时任务在后台执行中, 无法发起此操作")})).catch((g=>{clog.error("锁任务出现错误:",g)}))}))}async resetBtnTip(){let e=this.getOptionalDependency("TaskPlugin"),t=e?this.getRuntimeService("storage").getLocal(e.lastCheckBlacklistTimeKey)||"无":"任务已禁用",s=await storageManager.getSetting("checkBlacklist_intervalTime",12);this.checkBlacklist_ruleTime=await storageManager.getSetting("checkBlacklist_ruleTime",8760),(this.blacklistRoot||$()).find("#checkBlacklistBtn").attr("data-tip",`上次整批检测: ${t}; 检测间隔时间: ${s}小时`)}async openBlacklistDialog(){let e=this.getOptionalDependency("TaskPlugin"),t=await storageManager.getSetting(),a=`
    @@ -3184,11 +3179,11 @@
    - `;this.getRuntimeService("dialog").open({type:1,title:"演员黑名单",ui:{body:"table"},content:a,scrollbar:!1,area:utils.getDialogArea("xl"),anim:-1,success:d(async r=>{let i=$(r).find(".layui-layer-content > div").first().addClass("jhs-blacklist-layout").removeAttr("style");this.blacklistRoot=i;let n=i.children("div").first().addClass("jhs-blacklist-toolbar").removeAttr("style");n.children("div").addClass("jhs-blacklist-toolbar__group").removeAttr("style"),n.find("select,input,a").removeAttr("style"),i.find("#table-container").removeAttr("style"),i.find("#table-container").before('
    '),K.enhance(r),e||i.find("#checkBlacklistBtn").prop("disabled",!0).attr("title","后台任务功能已禁用"),this.renderTaskStatus(),this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=cc().on("task-status-changed",(()=>this.renderTaskStatus())),await this.loadTableData();let l=$(r).find(".layui-layer-content"),c=l.find("#searchValue");this.blacklistSearchDebounced=utils.debounce((()=>{this.reloadTable()}),200),l.on("click","#cleanQueryBtn",(async()=>{c.val(""),K.setValue(this.blacklistRoot.find("#dataType"),"",!1),K.setValue(this.blacklistRoot.find("#statusType"),"",!1),K.setValue(this.blacklistRoot.find("#urlType"),"",!1),await this.reloadTable()})).on("input","#searchValue",this.blacklistSearchDebounced).on("change","#dataType,#statusType,#urlType",(async()=>{await this.reloadTable()})).on("click","#toSetting",(()=>{this.getOptionalDependency("SettingPlugin")?.openSettingDialog?.("task-panel",(()=>{$("#setting-blacklist").css({border:"1px solid var(--jhs-status-filter)"})}))})).on("click",".open-url",(h=>{h.preventDefault();let u=$(h.currentTarget),p=u.attr("data-url"),g=u.attr("data-name");utils.openPage(p,g,!0,h)})).on("click","#checkBlacklistBtn",(h=>{let u=$(h.currentTarget),p=u.find("span").last(),g=p.text();!e||u.attr("aria-busy")==="true"||(u.attr("aria-busy","true").prop("disabled",!0),p.text("检测中…"),navigator.locks.request(e.singleTaskKey,{ifAvailable:!0},(async m=>{m?await e.checkBlacklist(!0):show.error("后台任务正在运行,请稍后再试")})).catch((m=>{clog.error("锁任务出现错误:",m),e.isNetworkBlocked(m)&&show.error(m.message||"任务执行失败")})).finally((()=>{u.removeAttr("aria-busy").prop("disabled",!1),p.text(g)})))}))},"success"),end:d(async()=>{this.blacklistRoot=null,this.blacklistSearchDebounced?.cancel?.(),this.blacklistSearchDebounced=null,this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=null,this.tableObj&&(this.tableObj.destroy(),this.tableObj=null),await cc().emit("blacklist-rules-changed")},"end")})}renderTaskStatus(){let e=(this.blacklistRoot||$()).find("#blacklist-task-status");if(!e.length)return;let t=this.getOptionalDependency("TaskPlugin");if(!t)return void e.empty().text("后台任务功能已禁用");let s=t.getTaskStatusSnapshot("blacklist"),a={idle:"正常",running:"运行中",pending:"等待下一次任务检查",due:"待运行"},r=d(n=>n?new Date(n).toLocaleString():"无","format"),i=s.state;e.empty().append($('').text(`黑名单:${a[i]||a.idle}`),$('').text(`上次完成 ${r(s.completedAt)};下次检查 ${s.nextAt?r(s.nextAt):"立即"}`))}async reloadTable(){if(!this.tableObj)return;let e=await this.getTableData();this.tableObj.setData(e)}async getTableData(){let e=this.blacklistRoot||$(),t=await storageManager.getBlacklist(),s=await storageManager.getBlacklistCarList(),a=String(e.find("#searchValue").val()||"").trim().toLocaleLowerCase(),r=e.find("#statusType").val(),i=e.find("#dataType"),n=i.val(),l=e.find("#urlType").val(),c=t.length,h=0,u=0,p=t.map(f=>{f.role===Oe?h++:f.role===at&&u++;let v=!1;return v=gt(f.lastPublishTime,this.checkBlacklist_ruleTime),{...f,isUnCheck:v}}).filter(f=>{let v=Array.isArray(f.allName)?f.allName.join(" "):f.allName||"",b=`${f.name||""} ${v} ${f.starId||""}`.toLocaleLowerCase(),w=!a||b.includes(a),S=!r||r==="normal"&&!f.isUnCheck||r==="stop"&&f.isUnCheck,j=!n||f.role===n,x=f.url.includes("t=");return w&&S&&j&&(!l||l==="hasT"&&x||l==="noT"&&!x)});i.html(` + `;this.getRuntimeService("dialog").open({type:1,title:"演员黑名单",ui:{body:"table"},content:a,scrollbar:!1,area:utils.getDialogArea("xl"),anim:-1,success:d(async r=>{let i=$(r).find(".layui-layer-content > div").first().addClass("jhs-blacklist-layout").removeAttr("style");this.blacklistRoot=i;let n=i.children("div").first().addClass("jhs-blacklist-toolbar").removeAttr("style");n.children("div").addClass("jhs-blacklist-toolbar__group").removeAttr("style"),n.find("select,input,a").removeAttr("style"),i.find("#table-container").removeAttr("style"),i.find("#table-container").before('
    '),K.enhance(r),e||i.find("#checkBlacklistBtn").prop("disabled",!0).attr("title","后台任务功能已禁用"),this.renderTaskStatus(),this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=dc().on("task-status-changed",(()=>this.renderTaskStatus())),await this.loadTableData();let l=$(r).find(".layui-layer-content"),c=l.find("#searchValue");this.blacklistSearchDebounced=utils.debounce((()=>{this.reloadTable()}),200),l.on("click","#cleanQueryBtn",(async()=>{c.val(""),K.setValue(this.blacklistRoot.find("#dataType"),"",!1),K.setValue(this.blacklistRoot.find("#statusType"),"",!1),K.setValue(this.blacklistRoot.find("#urlType"),"",!1),await this.reloadTable()})).on("input","#searchValue",this.blacklistSearchDebounced).on("change","#dataType,#statusType,#urlType",(async()=>{await this.reloadTable()})).on("click","#toSetting",(()=>{this.getOptionalDependency("SettingPlugin")?.openSettingDialog?.("task-panel",(()=>{$("#setting-blacklist").css({border:"1px solid var(--jhs-status-filter)"})}))})).on("click",".open-url",(h=>{h.preventDefault();let u=$(h.currentTarget),p=u.attr("data-url"),g=u.attr("data-name");utils.openPage(p,g,!0,h)})).on("click","#checkBlacklistBtn",(h=>{let u=$(h.currentTarget),p=u.find("span").last(),g=p.text();!e||u.attr("aria-busy")==="true"||(u.attr("aria-busy","true").prop("disabled",!0),p.text("检测中…"),navigator.locks.request(e.singleTaskKey,{ifAvailable:!0},(async m=>{m?await e.checkBlacklist(!0):show.error("后台任务正在运行,请稍后再试")})).catch((m=>{clog.error("锁任务出现错误:",m),e.isNetworkBlocked(m)&&show.error(m.message||"任务执行失败")})).finally((()=>{u.removeAttr("aria-busy").prop("disabled",!1),p.text(g)})))}))},"success"),end:d(async()=>{this.blacklistRoot=null,this.blacklistSearchDebounced?.cancel?.(),this.blacklistSearchDebounced=null,this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=null,this.tableObj&&(this.tableObj.destroy(),this.tableObj=null),await dc().emit("blacklist-rules-changed")},"end")})}renderTaskStatus(){let e=(this.blacklistRoot||$()).find("#blacklist-task-status");if(!e.length)return;let t=this.getOptionalDependency("TaskPlugin");if(!t)return void e.empty().text("后台任务功能已禁用");let s=t.getTaskStatusSnapshot("blacklist"),a={idle:"正常",running:"运行中",pending:"等待下一次任务检查",due:"待运行"},r=d(n=>n?new Date(n).toLocaleString():"无","format"),i=s.state;e.empty().append($('').text(`黑名单:${a[i]||a.idle}`),$('').text(`上次完成 ${r(s.completedAt)};下次检查 ${s.nextAt?r(s.nextAt):"立即"}`))}async reloadTable(){if(!this.tableObj)return;let e=await this.getTableData();this.tableObj.setData(e)}async getTableData(){let e=this.blacklistRoot||$(),t=await storageManager.getBlacklist(),s=await storageManager.getBlacklistCarList(),a=String(e.find("#searchValue").val()||"").trim().toLocaleLowerCase(),r=e.find("#statusType").val(),i=e.find("#dataType"),n=i.val(),l=e.find("#urlType").val(),c=t.length,h=0,u=0,p=t.map(f=>{f.role===Oe?h++:f.role===at&&u++;let v=!1;return v=mt(f.lastPublishTime,this.checkBlacklist_ruleTime),{...f,isUnCheck:v}}).filter(f=>{let v=Array.isArray(f.allName)?f.allName.join(" "):f.allName||"",b=`${f.name||""} ${v} ${f.starId||""}`.toLocaleLowerCase(),w=!a||b.includes(a),S=!r||r==="normal"&&!f.isUnCheck||r==="stop"&&f.isUnCheck,j=!n||f.role===n,k=f.url.includes("t=");return w&&S&&j&&(!l||l==="hasT"&&k||l==="noT"&&!k)});i.html(` - `),K.setValue(i,n,!1);let g=new Map;for(let f of s){let v=f.starId;g.has(v)||g.set(v,[]),g.get(v).push(f)}let m=p.map(f=>{let v=f.starId,b=g.get(v)||[];return{...f,carList:b,count:b.length}});return this.currentCarCount=m.reduce(((f,v)=>f+(v.count||0)),0),m}async loadTableData(){this.checkBlacklist_ruleTime=ae(await storageManager.getSetting("checkBlacklist_ruleTime"),8760,{min:0});let e=await this.getTableData(),t=document.createElement("div");Ue(t,{type:"empty",title:"没有符合当前筛选条件的黑名单记录"});let s=(this.blacklistRoot||$()).find("#table-container").get(0);this.tableObj=ze(globalThis.Tabulator,s,{layout:"fitColumns",placeholder:t,virtualDom:!0,data:e,pagination:!0,paginationMode:"local",paginationSize:20,paginationSizeSelector:[20,50,100,1e3],paginationCounter:d((a,r,i,n,l)=>`演员: ${n}    番号总数: ${this.currentCarCount} `,"paginationCounter"),responsiveLayout:"collapse",responsiveLayoutCollapse:!0,columnDefaults:{headerHozAlign:"center",hozAlign:"center"},index:"starId",columns:[{title:"演员",field:"name",sorter:"string",minWidth:100,responsive:0,headerSort:!1,formatter:d((a,r,i)=>{let n=a.getData(),l=Ye(n.url),c=document.createElement("a");return c.className="open-url",c.textContent=String(n.name||""),c.dataset.name=String(n.name||""),l?(c.href=l,c.dataset.url=l,c.target="_blank",c.rel="noopener noreferrer"):(c.href="#",c.setAttribute("aria-disabled","true")),c},"formatter")},{title:"性别角色",field:"role",sorter:"string",width:120,responsive:5,formatter:d((a,r,i)=>{let n=a.getData().role,l=n;return n===Oe?l="男演员":n===at&&(l="女演员"),l},"formatter")},{title:"影视类别",field:"movieType",sorter:"string",width:120,responsive:5,formatter:d((a,r,i)=>{let n=a.getData().movieType,l=n;return n===We?l="有码":n===Ke&&(l="无码"),l},"formatter")},{title:"屏蔽类型",field:"url",sorter:"string",minWidth:120,responsive:4,visible:M,formatter:d((a,r,i)=>{let n=a.getData().url.includes("t=");return`${n?"按所选分类屏蔽":"未筛选分类"}`},"formatter")},{title:"番号数量",field:"count",sorter:"number",width:170,responsive:1},{title:"创建时间",field:"createTime",sorter:"string",width:170,responsive:5},{title:"最后发行时间",field:"lastPublishTime",sorter:"string",width:170,responsive:1},{title:"状态",field:"isUnCheck",sorter:"string",width:120,responsive:1,formatter:d((a,r,i)=>{let n="",l="继续检测";return a.getData().isUnCheck&&(n=`停更${this.checkBlacklist_ruleTime/24/365}年以上, 下轮任务不再进行检测`,l="停更跳过"),`${l}`},"formatter")},{title:"操作",sorter:"string",cssClass:"action-cell-dropdown",minWidth:150,responsive:0,headerSort:!1,formatter:d((a,r,i)=>{let n=a.getData();return i((()=>{var l,c;(l=a.getElement().querySelector(".delete-btn"))==null||l.addEventListener("click",(h=>{let u=n.name,p=n.starId;u?p?utils.q(h,`是否移除对 ${C(u)} 的屏蔽?`,(async()=>{await storageManager.removeBlacklistCarList(p),await storageManager.deleteBlacklistItem(p),show.info("操作成功"),await this.reloadTable()})):show.error("获取starId失败"):show.error("获取名称失败")})),(c=a.getElement().querySelector(".keyword-btn"))==null||c.addEventListener("click",(h=>{let u=n.carList.reduce(((g,m)=>{let f=m.carNum.split("-")[0]+"-";return g[f]=(g[f]||0)+1,g}),{}),p=Object.entries(u).map((([g,m])=>({prefix:g,count:m}))).sort(((g,m)=>m.count-g.count));clog.debug(p)}))})),''},"formatter")}],initialSort:[{column:"createTime",dir:"desc"}]})}async filterAllVideo(e,{filter:t=this.getOptionalDependency("ListPagePlugin")?.activeQuickFilter||"waitCheck",confirm:s=!0,root:a=null}={}){let r=Ae(t),i=Ee[r],n=r==="all"?"将处理当前搜索全部分页的所有作品(包括屏蔽项)并加入黑名单。":`将处理当前搜索全部分页中符合「${i}」筛选的作品并加入黑名单。`;if(s&&!await new Promise(u=>utils.q(null,n,()=>u(!0),()=>u(!1))))return{cancelled:!0};let l=Vs();if(!l)return show.error("已有批量任务正在执行"),{cancelled:!0,busy:!0};let c=d(()=>(this.blacklistRoot||$()).find("#checkBlacklistMsg"),"statusHost");try{$("#favoriteAllVideo, #hasDownAllVideo, #filterAllVideo").attr("aria-disabled","true").addClass("jhs-batch-busy");let h=await this.getRuntimeService("scope")(),u=this.getOptionalDependency("ListPagePlugin"),p=typeof u?.createEvaluationContext=="function"?await u.createEvaluationContext():is({}),g=d(()=>!Nt(l)||!!h?.disposed,"isCancelled"),m=await Fs({startDom:a?$(a):$(document),currentUrl:a?null:window.location.href,firstPageUrl:a?null:this.getRuntimeService("host")?.resolveFirstPageUrl?.(window.location.href)??window.location.href,itemSelector:this.getSelector().requestDomItemSelector,nextPageSelector:this.getSelector().nextPageSelector,fetchHtml:d(async b=>He(this.getRuntimeService("http"),b,h),"fetchHtml"),parseItem:d(b=>_e(b),"parseItem"),evaluate:d(b=>ns({carNum:b.carNum,title:b.title||""},p,{filter:r}),"evaluate"),isCancelled:g,onProgress:d(({page:b,scanned:w,matched:S})=>{let j=c();j.length&&j.text(`正在扫描第 ${b} 页 · 已扫描 ${w} · 匹配 ${S} 个番号`)},"onProgress")});if(g())return{cancelled:!0};let f=0;for(let b=0;bS.carNum),{blocked:!0},{type:"actor-page-block",records:w.map(S=>({carNum:S.carNum,url:S.url||"",names:e,publishTime:S.publishTime||"",fc2Source:S.fc2Source}))}),f+=w.length,clog.log("一键屏蔽进度",`已屏蔽 ${f}/${m.length} 个番号`)}let v=c();return v.length&&v.text(`处理完成 · 共屏蔽 ${f} 个番号`),{matched:m.length,updated:f}}finally{Nt(l)&&Hs(l),$("#favoriteAllVideo, #hasDownAllVideo, #filterAllVideo").removeAttr("aria-disabled").removeClass("jhs-batch-busy")}}async filterActorVideo(e,t,s,a=B?Se:Be,r=1,i=0,n=new Set){let{nextPageLink:l,recordCount:c}=await this.parseAndSaveFilterInfo(s,e,t,a);if(i+=c,(this.blacklistRoot||$()).find("#checkBlacklistMsg").text(`正在处理第 ${r} 页 · 已屏蔽 ${i} 个番号`),this.nextPageLink=l,l&&r<200&&!n.has(l)){n.add(l);let h;this.lastPageLink=l,clog.log("正在请求下一页内容:",l);let u=await this.getRuntimeService("scope")(),p=await He(this.getRuntimeService("http"),l,u);h=utils.htmlTo$dom(p),await this.filterActorVideo(e,t,h,a,r+1,i,n)}else r>=200?((this.blacklistRoot||$()).find("#checkBlacklistMsg").text(`已达到页数上限(200 页),已停止 · 已屏蔽 ${i} 个番号`),clog.warn("演员视频分页扫描已达上限,已停止")):(this.blacklistRoot||$()).find("#checkBlacklistMsg").text(`处理完成 · ${r} 页 · 新增 ${i} 个番号`)}async parseAndSaveFilterInfo(e,t,s,a){if(![Be,Se].includes(a))throw new Error(`未知黑名单来源站点: ${a}`);let r=e||$(document),i=this.getSelector(a);a===Se&&r.find(".avatar-box").length>0&&r.find(".avatar-box").parent().remove();let n=qs(r,{boxSelector:a===Se?`${i.boxSelector}, #waterfall`:i.boxSelector,requestDomItemSelector:e?i.requestDomItemSelector:i.itemSelector}),l=r.find(i.nextPageSelector).attr("href");if(n.state!=="valid")throw new Error(`黑名单作品页面无效: ${n.state}`);if(n.isEmpty&&l)throw new Error("黑名单作品空页面包含下一页");let c=[],h=[];for(let u of n.items){let p=$(u),{carNum:g,url:m,publishTime:f}=_e(p);f&&h.push(f),m&&g&&c.push({carNum:g,url:m,names:t,actionType:ce,starId:s,publishTime:f})}return await storageManager.batchSaveBlacklistCarList(c),{nextPageLink:l,lastPublishTime:Gt(h),recordCount:c.length}}};d(Ai,"BlacklistPlugin");var Js=Ai;var Pi=class Pi extends I{getName(){return"FilterTitleKeywordPlugin"}async handle(){isDetailPage&&await this.bindDetailRoot(document)}async bindDetailRoot(e,{layerIndex:t=null}={}){if(await storageManager.getSetting("enableTitleSelectFilter",R)!==R)return;let s=$(e),a=M?".title strong, .current-title":B?"h3":".current-title, .origin-title, .jhs-detail-title";s.off("contextmenu.jhsTitleFilter",a).on("contextmenu.jhsTitleFilter",a,(r=>{let i=window.getSelection()?.toString()||"";if(i){r.preventDefault();let n={clientX:r.clientX,clientY:r.clientY+80};utils.q(n,`是否屏蔽标题关键词 ${C(i)}?`,(async()=>{let l=i.replace(/\r?\n+/g," ").replace(/\s{2,}/g," ").trim().slice(0,120);l&&await storageManager.saveTitleFilterKeyword(l),await V?.emit("filter-rules-changed",{scope:"title-keyword"}),utils.closePage({root:s,layerIndex:t})}))}}))}};d(Pi,"FilterTitleKeywordPlugin");var Ws=Pi;function Ks(o,{retry:e=null,tone:t="neutral",extraClass:s=""}={}){let a=globalThis.$,r=a('
    ').text(o);return s&&r.addClass(s),t==="error"&&r.addClass("is-error"),e&&r.append(" ",a('').on("click",e)),r}d(Ks,"createPanelState");function dc(o="正在加载…"){return Ks(o)}d(dc,"createPanelLoading");function hc(o,e=null){return Ks(o,{retry:e,tone:"error"})}d(hc,"createPanelError");function Ii(o){try{let e=new URL(String(o||""));return["http:","https:"].includes(e.protocol)?e.href:null}catch{return null}}d(Ii,"normalizeUrl");function he(o,e,t=null){let s=globalThis.$,a=s(o).empty(),r=Ks(e,{retry:t,tone:t?"error":"neutral",extraClass:"jhs-fc2-state"});a.append(r)}d(he,"renderFc2State");function os(o,e,t=null){let s=globalThis.$,a=[...new Set((e||[]).map(Ii).filter(Boolean))],r=o.root.find('[data-jhs-role="gallery-grid"]').empty(),i=o.root.find('[data-jhs-role="main-preview"]').empty();o.galleryUrls=new Set(a);let n=Ii(t);if(n&&i.append(s("").attr({src:n,alt:`${o.carNum} 概览`,loading:"eager"})),!a.length)return he(r,"暂无剧照");a.forEach((c,h)=>r.append(s('').attr("aria-label",`查看剧照 ${h+1}`).append(s("").addClass("jhs-fc2-gallery__image").attr({src:c,alt:`剧照 ${h+1}`,loading:"lazy"}))));let l=o.root.find('[data-jhs-role="screenshot"]');l.find("img").each((c,h)=>{let u=h.getAttribute("src");u&&o.galleryUrls.has(u)&&l.empty()})}d(os,"renderFc2Gallery");function Gs(o,e){let t=globalThis.$,s=t(''),a=e.sourceUrls({carNum:o.carNum},["fc2ppvdb","fc2content"]);return[[o.source==="123av"?"123AV 原页面":"JavDB 原页面",Ii(o.url)],...a.map(i=>[i.providerId==="fc2ppvdb"?"FC2PPVDB":"FC2 市场",i.url])].forEach(([i,n])=>n&&s.append(t("
    ").addClass("jhs-btn jhs-btn--ghost jhs-btn--sm").attr({href:n,target:"_blank",rel:"noopener noreferrer"}).text(i))),s}d(Gs,"createFc2SourceLinks");var Ri=class Ri extends I{constructor(){super(...arguments),this.$contentBox=null,this.$listRoot=null,this.urlParams=new URLSearchParams(window.location.search),this.currentPage=Math.max(1,parseInt(this.urlParams.get("page")||"1",10)||1),this.maxPage=null,this._queryGeneration=0,this.keyword=this.urlParams.get("keyword")||null}getName(){return"Fc2By123AvPlugin"}async resolveMovieId(e){let t=await this.getRuntimeService("scope")();return(await this.getRuntimeService("movie").resolve({carNum:e},{scope:t}))?.movieId||null}async handle(){let e=document.querySelector('#navbar-menu-hero a[href^="/tags/fc2"]');if(e&&!document.querySelector("#jhs-123av-nav")){let t=document.createElement("a");t.id="jhs-123av-nav",t.className="navbar-item",t.href="/tags/fc2?c10=1&jhs_source=123av",t.textContent="123AV · FC2片库",e.after(t)}je(window.location).kind==="external-fc2-catalog"&&(this.hookPage(),await this.handleQuery())}hookPage(){let e=this.getRuntimeService("host"),t=e.locateListRoot?.(),s=e.getListContainer?.();if(!t||!s)throw new Error("JavDB 列表容器不可用");this.$contentBox=$(s),this.$listRoot=$(e.createOwnedListRoot(["jhs-123av-list","jhs-layout-d2c171b1"]));let a=this.$contentBox.find("h2.section-title").first();a.length||(a=$("

    ").addClass("section-title").prependTo(this.$contentBox)),a.text("123AV · FC2片库"),a.css("marginBottom","0"),a.append(` + `),K.setValue(i,n,!1);let g=new Map;for(let f of s){let v=f.starId;g.has(v)||g.set(v,[]),g.get(v).push(f)}let m=p.map(f=>{let v=f.starId,b=g.get(v)||[];return{...f,carList:b,count:b.length}});return this.currentCarCount=m.reduce(((f,v)=>f+(v.count||0)),0),m}async loadTableData(){this.checkBlacklist_ruleTime=ae(await storageManager.getSetting("checkBlacklist_ruleTime"),8760,{min:0});let e=await this.getTableData(),t=document.createElement("div");Ue(t,{type:"empty",title:"没有符合当前筛选条件的黑名单记录"});let s=(this.blacklistRoot||$()).find("#table-container").get(0);this.tableObj=ze(globalThis.Tabulator,s,{layout:"fitColumns",placeholder:t,virtualDom:!0,data:e,pagination:!0,paginationMode:"local",paginationSize:20,paginationSizeSelector:[20,50,100,1e3],paginationCounter:d((a,r,i,n,l)=>`演员: ${n}    番号总数: ${this.currentCarCount} `,"paginationCounter"),responsiveLayout:"collapse",responsiveLayoutCollapse:!0,columnDefaults:{headerHozAlign:"center",hozAlign:"center"},index:"starId",columns:[{title:"演员",field:"name",sorter:"string",minWidth:100,responsive:0,headerSort:!1,formatter:d((a,r,i)=>{let n=a.getData(),l=Ye(n.url),c=document.createElement("a");return c.className="open-url",c.textContent=String(n.name||""),c.dataset.name=String(n.name||""),l?(c.href=l,c.dataset.url=l,c.target="_blank",c.rel="noopener noreferrer"):(c.href="#",c.setAttribute("aria-disabled","true")),c},"formatter")},{title:"性别角色",field:"role",sorter:"string",width:120,responsive:5,formatter:d((a,r,i)=>{let n=a.getData().role,l=n;return n===Oe?l="男演员":n===at&&(l="女演员"),l},"formatter")},{title:"影视类别",field:"movieType",sorter:"string",width:120,responsive:5,formatter:d((a,r,i)=>{let n=a.getData().movieType,l=n;return n===Je?l="有码":n===Ke&&(l="无码"),l},"formatter")},{title:"屏蔽类型",field:"url",sorter:"string",minWidth:120,responsive:4,visible:M,formatter:d((a,r,i)=>{let n=a.getData().url.includes("t=");return`${n?"按所选分类屏蔽":"未筛选分类"}`},"formatter")},{title:"番号数量",field:"count",sorter:"number",width:170,responsive:1},{title:"创建时间",field:"createTime",sorter:"string",width:170,responsive:5},{title:"最后发行时间",field:"lastPublishTime",sorter:"string",width:170,responsive:1},{title:"状态",field:"isUnCheck",sorter:"string",width:120,responsive:1,formatter:d((a,r,i)=>{let n="",l="继续检测";return a.getData().isUnCheck&&(n=`停更${this.checkBlacklist_ruleTime/24/365}年以上, 下轮任务不再进行检测`,l="停更跳过"),`${l}`},"formatter")},{title:"操作",sorter:"string",cssClass:"action-cell-dropdown",minWidth:150,responsive:0,headerSort:!1,formatter:d((a,r,i)=>{let n=a.getData();return i((()=>{var l,c;(l=a.getElement().querySelector(".delete-btn"))==null||l.addEventListener("click",(h=>{let u=n.name,p=n.starId;u?p?utils.q(h,`是否移除对 ${T(u)} 的屏蔽?`,(async()=>{await storageManager.removeBlacklistCarList(p),await storageManager.deleteBlacklistItem(p),show.info("操作成功"),await this.reloadTable()})):show.error("获取starId失败"):show.error("获取名称失败")})),(c=a.getElement().querySelector(".keyword-btn"))==null||c.addEventListener("click",(h=>{let u=n.carList.reduce(((g,m)=>{let f=m.carNum.split("-")[0]+"-";return g[f]=(g[f]||0)+1,g}),{}),p=Object.entries(u).map((([g,m])=>({prefix:g,count:m}))).sort(((g,m)=>m.count-g.count));clog.debug(p)}))})),''},"formatter")}],initialSort:[{column:"createTime",dir:"desc"}]})}async filterAllVideo(e,{filter:t=this.getOptionalDependency("ListPagePlugin")?.activeQuickFilter||"waitCheck",confirm:s=!0,root:a=null}={}){let r=_e(t),i=Pe[r],n=r==="all"?"将处理当前搜索全部分页的所有作品(包括屏蔽项)并加入黑名单。":`将处理当前搜索全部分页中符合「${i}」筛选的作品并加入黑名单。`;if(s&&!await new Promise(u=>utils.q(null,n,()=>u(!0),()=>u(!1))))return{cancelled:!0};let l=qs();if(!l)return show.error("已有批量任务正在执行"),{cancelled:!0,busy:!0};let c=d(()=>(this.blacklistRoot||$()).find("#checkBlacklistMsg"),"statusHost");try{$("#favoriteAllVideo, #hasDownAllVideo, #filterAllVideo").attr("aria-disabled","true").addClass("jhs-batch-busy");let h=await this.getRuntimeService("scope")(),u=this.getOptionalDependency("ListPagePlugin"),p=typeof u?.createEvaluationContext=="function"?await u.createEvaluationContext():is({}),g=d(()=>!Lt(l)||!!h?.disposed,"isCancelled"),m=await Vs({startDom:a?$(a):$(document),currentUrl:a?null:window.location.href,firstPageUrl:a?null:this.getRuntimeService("host")?.resolveFirstPageUrl?.(window.location.href)??window.location.href,itemSelector:this.getSelector().requestDomItemSelector,nextPageSelector:this.getSelector().nextPageSelector,fetchHtml:d(async b=>qe(this.getRuntimeService("http"),b,h),"fetchHtml"),parseItem:d(b=>$e(b),"parseItem"),evaluate:d(b=>ns({carNum:b.carNum,title:b.title||""},p,{filter:r}),"evaluate"),isCancelled:g,onProgress:d(({page:b,scanned:w,matched:S})=>{let j=c();j.length&&j.text(`正在扫描第 ${b} 页 · 已扫描 ${w} · 匹配 ${S} 个番号`)},"onProgress")});if(g())return{cancelled:!0};let f=0;for(let b=0;bS.carNum),{blocked:!0},{type:"actor-page-block",records:w.map(S=>({carNum:S.carNum,url:S.url||"",names:e,publishTime:S.publishTime||"",fc2Source:S.fc2Source}))}),f+=w.length,clog.log("一键屏蔽进度",`已屏蔽 ${f}/${m.length} 个番号`)}let v=c();return v.length&&v.text(`处理完成 · 共屏蔽 ${f} 个番号`),{matched:m.length,updated:f}}finally{Lt(l)&&Hs(l),$("#favoriteAllVideo, #hasDownAllVideo, #filterAllVideo").removeAttr("aria-disabled").removeClass("jhs-batch-busy")}}async filterActorVideo(e,t,s,a=B?Se:Be,r=1,i=0,n=new Set){let{nextPageLink:l,recordCount:c}=await this.parseAndSaveFilterInfo(s,e,t,a);if(i+=c,(this.blacklistRoot||$()).find("#checkBlacklistMsg").text(`正在处理第 ${r} 页 · 已屏蔽 ${i} 个番号`),this.nextPageLink=l,l&&r<200&&!n.has(l)){n.add(l);let h;this.lastPageLink=l,clog.log("正在请求下一页内容:",l);let u=await this.getRuntimeService("scope")(),p=await qe(this.getRuntimeService("http"),l,u);h=utils.htmlTo$dom(p),await this.filterActorVideo(e,t,h,a,r+1,i,n)}else r>=200?((this.blacklistRoot||$()).find("#checkBlacklistMsg").text(`已达到页数上限(200 页),已停止 · 已屏蔽 ${i} 个番号`),clog.warn("演员视频分页扫描已达上限,已停止")):(this.blacklistRoot||$()).find("#checkBlacklistMsg").text(`处理完成 · ${r} 页 · 新增 ${i} 个番号`)}async parseAndSaveFilterInfo(e,t,s,a){if(![Be,Se].includes(a))throw new Error(`未知黑名单来源站点: ${a}`);let r=e||$(document),i=this.getSelector(a);a===Se&&r.find(".avatar-box").length>0&&r.find(".avatar-box").parent().remove();let n=Ws(r,{boxSelector:a===Se?`${i.boxSelector}, #waterfall`:i.boxSelector,requestDomItemSelector:e?i.requestDomItemSelector:i.itemSelector}),l=r.find(i.nextPageSelector).attr("href");if(n.state!=="valid")throw new Error(`黑名单作品页面无效: ${n.state}`);if(n.isEmpty&&l)throw new Error("黑名单作品空页面包含下一页");let c=[],h=[];for(let u of n.items){let p=$(u),{carNum:g,url:m,publishTime:f}=$e(p);f&&h.push(f),m&&g&&c.push({carNum:g,url:m,names:t,actionType:ce,starId:s,publishTime:f})}return await storageManager.batchSaveBlacklistCarList(c),{nextPageLink:l,lastPublishTime:Qt(h),recordCount:c.length}}};d(Pi,"BlacklistPlugin");var Js=Pi;var Ri=class Ri extends I{getName(){return"FilterTitleKeywordPlugin"}async handle(){isDetailPage&&await this.bindDetailRoot(document)}async bindDetailRoot(e,{layerIndex:t=null}={}){if(await storageManager.getSetting("enableTitleSelectFilter",E)!==E)return;let s=$(e),a=M?".title strong, .current-title":B?"h3":".current-title, .origin-title, .jhs-detail-title";s.off("contextmenu.jhsTitleFilter",a).on("contextmenu.jhsTitleFilter",a,(r=>{let i=window.getSelection()?.toString()||"";if(i){r.preventDefault();let n={clientX:r.clientX,clientY:r.clientY+80};utils.q(n,`是否屏蔽标题关键词 ${T(i)}?`,(async()=>{let l=i.replace(/\r?\n+/g," ").replace(/\s{2,}/g," ").trim().slice(0,120);l&&await storageManager.saveTitleFilterKeyword(l),await V?.emit("filter-rules-changed",{scope:"title-keyword"}),utils.closePage({root:s,layerIndex:t})}))}}))}};d(Ri,"FilterTitleKeywordPlugin");var Ks=Ri;function Gs(o,{retry:e=null,tone:t="neutral",extraClass:s=""}={}){let a=globalThis.$,r=a('
    ').text(o);return s&&r.addClass(s),t==="error"&&r.addClass("is-error"),e&&r.append(" ",a('').on("click",e)),r}d(Gs,"createPanelState");function hc(o="正在加载…"){return Gs(o)}d(hc,"createPanelLoading");function uc(o,e=null){return Gs(o,{retry:e,tone:"error"})}d(uc,"createPanelError");function Ii(o){try{let e=new URL(String(o||""));return["http:","https:"].includes(e.protocol)?e.href:null}catch{return null}}d(Ii,"normalizeUrl");function he(o,e,t=null){let s=globalThis.$,a=s(o).empty(),r=Gs(e,{retry:t,tone:t?"error":"neutral",extraClass:"jhs-fc2-state"});a.append(r)}d(he,"renderFc2State");function os(o,e,t=null){let s=globalThis.$,a=[...new Set((e||[]).map(Ii).filter(Boolean))],r=o.root.find('[data-jhs-role="gallery-grid"]').empty(),i=o.root.find('[data-jhs-role="main-preview"]').empty();o.galleryUrls=new Set(a);let n=Ii(t);if(n&&i.append(s("").attr({src:n,alt:`${o.carNum} 概览`,loading:"eager"})),!a.length)return he(r,"暂无剧照");a.forEach((c,h)=>r.append(s('').attr("aria-label",`查看剧照 ${h+1}`).append(s("").addClass("jhs-fc2-gallery__image").attr({src:c,alt:`剧照 ${h+1}`,loading:"lazy"}))));let l=o.root.find('[data-jhs-role="screenshot"]');l.find("img").each((c,h)=>{let u=h.getAttribute("src");u&&o.galleryUrls.has(u)&&l.empty()})}d(os,"renderFc2Gallery");function Qs(o,e){let t=globalThis.$,s=t(''),a=e.sourceUrls({carNum:o.carNum},["fc2ppvdb","fc2content"]);return[[o.source==="123av"?"123AV 原页面":"JavDB 原页面",Ii(o.url)],...a.map(i=>[i.providerId==="fc2ppvdb"?"FC2PPVDB":"FC2 市场",i.url])].forEach(([i,n])=>n&&s.append(t("").addClass("jhs-btn jhs-btn--ghost jhs-btn--sm").attr({href:n,target:"_blank",rel:"noopener noreferrer"}).text(i))),s}d(Qs,"createFc2SourceLinks");var Ei=class Ei extends I{constructor(){super(...arguments),this.$contentBox=null,this.$listRoot=null,this.urlParams=new URLSearchParams(window.location.search),this.currentPage=Math.max(1,parseInt(this.urlParams.get("page")||"1",10)||1),this.maxPage=null,this._queryGeneration=0,this.keyword=this.urlParams.get("keyword")||null}getName(){return"Fc2By123AvPlugin"}async resolveMovieId(e){let t=await this.getRuntimeService("scope")();return(await this.getRuntimeService("movie").resolve({carNum:e},{scope:t}))?.movieId||null}async handle(){let e=document.querySelector('#navbar-menu-hero a[href^="/tags/fc2"]');if(e&&!document.querySelector("#jhs-123av-nav")){let t=document.createElement("a");t.id="jhs-123av-nav",t.className="navbar-item",t.href="/tags/fc2?c10=1&jhs_source=123av",t.textContent="123AV · FC2片库",e.after(t)}je(window.location).kind==="external-fc2-catalog"&&(this.hookPage(),await this.handleQuery())}hookPage(){let e=this.getRuntimeService("host"),t=e.locateListRoot?.(),s=e.getListContainer?.();if(!t||!s)throw new Error("JavDB 列表容器不可用");this.$contentBox=$(s),this.$listRoot=$(e.createOwnedListRoot(["jhs-123av-list","jhs-layout-d2c171b1"]));let a=this.$contentBox.find("h2.section-title").first();a.length||(a=$("

    ").addClass("section-title").prependTo(this.$contentBox)),a.text("123AV · FC2片库"),a.css("marginBottom","0"),a.append(`
    @@ -3200,20 +3195,20 @@
      - `),$(document).on("click",".pagination-link",(r=>{r.preventDefault(),this.currentPage=parseInt($(r.target).data("page")),utils.setHrefParam("page",this.currentPage),this.renderPagination(),this.handleQuery()})),$(".pagination-previous").on("click",(r=>{r.preventDefault(),this.currentPage>1&&(this.currentPage--,utils.setHrefParam("page",this.currentPage),this.renderPagination(),this.handleQuery())})),$(".pagination-next").on("click",(r=>{r.preventDefault(),this.currentPage<(this.maxPage??0)&&(this.currentPage++,utils.setHrefParam("page",this.currentPage),this.renderPagination(),this.handleQuery())}))}renderPagination(){let e=$(".pagination-list");e.empty();let t=this.maxPage??1,s=Math.max(1,this.currentPage-2),a=Math.min(t,this.currentPage+2);this.currentPage<=3?a=Math.min(6,t):this.currentPage>=t-2&&(s=Math.max(t-5,1)),s>1&&(e.append('
    • '),s>2&&e.append('
    • …
    • '));for(let r=s;r<=a;r++){let i=r===this.currentPage?" is-current":"";e.append(`
    • `)}a…'),e.append(`
    • `))}async handleQuery(){let e=loading(),t=++this._queryGeneration;try{$(".page-box").show();let s=await this.getRuntimeService("scope")();if(t!==this._queryGeneration)return;let a=await this.getRuntimeService("movie").catalog("av123",{page:this.currentPage,keyword:this.keyword||""},{scope:s});if(t!==this._queryGeneration)return;let r=a.items;this.maxPage=Math.max(1,Number(a.maxPage)||1),this.currentPage=Math.min(Math.max(1,this.currentPage),this.maxPage),this.renderPagination(),r.length===0&&(clog.log(r),show.error("无结果"),clog.error("123AV 获取数据失败"));let i=this.markDataListHtml(r);this.$listRoot?.html(i);let n=this.getOptionalDependency("ListPagePlugin");n&&this.$listRoot&&await n.processAddedItems?.(this.$listRoot.find(".item").toArray()),await utils.smoothScrollToTop()}catch(s){clog.error(s)}finally{e.close()}}async loadDetail(e,t){let s=this.loadSummary(e,t),a=this.getImgList(e.carNum),r=this.getActressInfo(e.carNum);a.then((i=>e.isAlive()&&os(e,i,null))).catch((i=>e.isAlive()&&he(e.root.find('[data-jhs-role="gallery-grid"]'),"剧照加载失败",(()=>{this.reloadImages(e)})))),r.then((async i=>{await s.catch((()=>null)),e.isAlive()&&this.render123AvActress(e,i)})).catch((i=>clog.error("FC2 演员信息加载失败",i))),await Promise.allSettled([s,a,r])}async loadSummary(e,t){try{let s=await this.get123AvVideoInfo(e.carNum,t);return e.isAlive()?(this.render123AvSummary(e,s),s):null}catch(s){throw e.isAlive()&&he(e.root.find('[data-jhs-role="summary-content"]'),"影片信息加载失败",(()=>{this.loadSummary(e,t)})),clog.error("123AV 详情加载失败",s),s}}render123AvSummary(e,t){let s=e.root.find('[data-jhs-role="summary-content"]').empty(),a=$('

      ');a.find("strong").text(t.title||"无标题"),s.append(a,$('
      ').append($("").text(`番号:${e.carNum}`),$("").text(`发行:${t.publishDate||"未知"}`)),'
      主演:正在加载演员…
      ','
      ',Gs(e,this.getRuntimeService("movie")),$('').text(t.publishDate||""))}async get123AvVideoInfo(e,t){let s=await this.getRuntimeService("scope")(),a=await this.getRuntimeService("movie").detail({carNum:e,url:t,providerId:"av123"},{scope:s});return{title:a?.title||"",publishDate:a?.releaseDate||"",moviePoster:null}}async getActressInfo(e){let t=await this.getRuntimeService("scope")();return this.getRuntimeService("movie").people("fc2ppvdb",{carNum:e},{scope:t})}async getImgList(e){let t=await this.getRuntimeService("scope")();return(await this.getRuntimeService("movie").images("fc2content",{carNum:e},{scope:t})).map((s=>s.url))}async reloadImages(e){try{let t=await this.getImgList(e.carNum);e.isAlive()&&os(e,t,null)}catch{e.isAlive()&&he(e.root.find('[data-jhs-role="gallery-grid"]'),"剧照加载失败",(()=>{this.reloadImages(e)}))}}render123AvActress(e,t){let s=e.root.find('[data-jhs-role="actors"]').empty().append("主演:");t.actors.length?t.actors.forEach((a=>s.append($("").addClass("jhs-fc2-actor").attr({href:a.url,target:"_blank",rel:"noopener noreferrer"}).text(a.name)))):s.append($("").text("暂无演员信息")),e.root.find('[data-jhs-role="actress-data"]').remove(),e.root.find(".jhs-fc2-summary__body").append($('').text(t.actors.map((a=>a.name)).join(" "))),t.seller&&e.root.find('[data-jhs-role="seller"]').empty().append("卖家:",t.seller.url?$("").attr({href:t.seller.url,target:"_blank",rel:"noopener noreferrer"}).text(t.seller.name):document.createTextNode(t.seller.name))}markDataListHtml(e){let t="";return e.forEach((s=>{let a=Ye(s.url),r=Ye(s.imageUrl);a&&(t+=` + `),$(document).on("click",".pagination-link",(r=>{r.preventDefault(),this.currentPage=parseInt($(r.target).data("page")),utils.setHrefParam("page",this.currentPage),this.renderPagination(),this.handleQuery()})),$(".pagination-previous").on("click",(r=>{r.preventDefault(),this.currentPage>1&&(this.currentPage--,utils.setHrefParam("page",this.currentPage),this.renderPagination(),this.handleQuery())})),$(".pagination-next").on("click",(r=>{r.preventDefault(),this.currentPage<(this.maxPage??0)&&(this.currentPage++,utils.setHrefParam("page",this.currentPage),this.renderPagination(),this.handleQuery())}))}renderPagination(){let e=$(".pagination-list");e.empty();let t=this.maxPage??1,s=Math.max(1,this.currentPage-2),a=Math.min(t,this.currentPage+2);this.currentPage<=3?a=Math.min(6,t):this.currentPage>=t-2&&(s=Math.max(t-5,1)),s>1&&(e.append('
    • '),s>2&&e.append('
    • …
    • '));for(let r=s;r<=a;r++){let i=r===this.currentPage?" is-current":"";e.append(`
    • `)}a…'),e.append(`
    • `))}async handleQuery(){let e=loading(),t=++this._queryGeneration;try{$(".page-box").show();let s=await this.getRuntimeService("scope")();if(t!==this._queryGeneration)return;let a=await this.getRuntimeService("movie").catalog("av123",{page:this.currentPage,keyword:this.keyword||""},{scope:s});if(t!==this._queryGeneration)return;let r=a.items;this.maxPage=Math.max(1,Number(a.maxPage)||1),this.currentPage=Math.min(Math.max(1,this.currentPage),this.maxPage),this.renderPagination(),r.length===0&&(clog.log(r),show.error("无结果"),clog.error("123AV 获取数据失败"));let i=this.markDataListHtml(r);this.$listRoot?.html(i);let n=this.getOptionalDependency("ListPagePlugin");n&&this.$listRoot&&await n.processAddedItems?.(this.$listRoot.find(".item").toArray()),await utils.smoothScrollToTop()}catch(s){clog.error(s)}finally{e.close()}}async loadDetail(e,t){let s=this.loadSummary(e,t),a=this.getImgList(e.carNum),r=this.getActressInfo(e.carNum);a.then((i=>e.isAlive()&&os(e,i,null))).catch((i=>e.isAlive()&&he(e.root.find('[data-jhs-role="gallery-grid"]'),"剧照加载失败",(()=>{this.reloadImages(e)})))),r.then((async i=>{await s.catch((()=>null)),e.isAlive()&&this.render123AvActress(e,i)})).catch((i=>clog.error("FC2 演员信息加载失败",i))),await Promise.allSettled([s,a,r])}async loadSummary(e,t){try{let s=await this.get123AvVideoInfo(e.carNum,t);return e.isAlive()?(this.render123AvSummary(e,s),s):null}catch(s){throw e.isAlive()&&he(e.root.find('[data-jhs-role="summary-content"]'),"影片信息加载失败",(()=>{this.loadSummary(e,t)})),clog.error("123AV 详情加载失败",s),s}}render123AvSummary(e,t){let s=e.root.find('[data-jhs-role="summary-content"]').empty(),a=$('

      ');a.find("strong").text(t.title||"无标题"),s.append(a,$('
      ').append($("").text(`番号:${e.carNum}`),$("").text(`发行:${t.publishDate||"未知"}`)),'
      主演:正在加载演员…
      ','
      ',Qs(e,this.getRuntimeService("movie")),$('').text(t.publishDate||""))}async get123AvVideoInfo(e,t){let s=await this.getRuntimeService("scope")(),a=await this.getRuntimeService("movie").detail({carNum:e,url:t,providerId:"av123"},{scope:s});return{title:a?.title||"",publishDate:a?.releaseDate||"",moviePoster:null}}async getActressInfo(e){let t=await this.getRuntimeService("scope")();return this.getRuntimeService("movie").people("fc2ppvdb",{carNum:e},{scope:t})}async getImgList(e){let t=await this.getRuntimeService("scope")();return(await this.getRuntimeService("movie").images("fc2content",{carNum:e},{scope:t})).map((s=>s.url))}async reloadImages(e){try{let t=await this.getImgList(e.carNum);e.isAlive()&&os(e,t,null)}catch{e.isAlive()&&he(e.root.find('[data-jhs-role="gallery-grid"]'),"剧照加载失败",(()=>{this.reloadImages(e)}))}}render123AvActress(e,t){let s=e.root.find('[data-jhs-role="actors"]').empty().append("主演:");t.actors.length?t.actors.forEach((a=>s.append($("").addClass("jhs-fc2-actor").attr({href:a.url,target:"_blank",rel:"noopener noreferrer"}).text(a.name)))):s.append($("").text("暂无演员信息")),e.root.find('[data-jhs-role="actress-data"]').remove(),e.root.find(".jhs-fc2-summary__body").append($('').text(t.actors.map((a=>a.name)).join(" "))),t.seller&&e.root.find('[data-jhs-role="seller"]').empty().append("卖家:",t.seller.url?$("").attr({href:t.seller.url,target:"_blank",rel:"noopener noreferrer"}).text(t.seller.name):document.createTextNode(t.seller.name))}markDataListHtml(e){let t="";return e.forEach((s=>{let a=Ye(s.url),r=Ye(s.imageUrl);a&&(t+=` - `)})),t}};d(Ri,"Fc2By123AvPlugin");var Qs=Ri;var Eh=Object.freeze({blocked:{id:"filterBtn",tone:"filter",label:Le},favorite:{id:"favoriteBtn",tone:"fav",label:Me},downloaded:{id:"hasDownBtn",tone:"down",label:fe},watched:{id:"hasWatchBtn",tone:"watch",label:ve}});function Lt({actions:o=["blocked","favorite","downloaded","watched"],ids:e={}}={}){let t=globalThis.$,s=t('
      ');s.attr("data-jhs-state-count",String(o.length));for(let a of o){let r=Eh[a];if(!r)continue;let i=t('');i.attr("id",e[a]||r.id).addClass(`jhs-btn--${r.tone}`).find("span").text(r.label),s.children().append(i)}return s}d(Lt,"createStateActions");var pc={blocked:{selector:"#filterBtn",inactive:d(()=>Le,"inactive"),active:d(()=>tt,"active")},favorite:{selector:"#favoriteBtn",inactive:d(()=>Me,"inactive"),active:d(()=>st,"active")},downloaded:{selector:"#hasDownBtn",inactive:d(()=>fe,"inactive"),active:d(()=>"已标记下载","active")},watched:{selector:"#hasWatchBtn",inactive:d(()=>ve,"inactive"),active:d(()=>"已标记观看","active")}};function uc(){return Object.entries(pc)}d(uc,"stateButtonEntries");var Ei=class Ei{constructor(e){this.stateService=e}bind({root:e=document,closeRoot:t=e,layerIndex:s=null,carNum:a,getRecord:r=null,activityType:i="detail-state",selectors:n={}}){let l={root:e,closeRoot:t,layerIndex:s,carNum:T(a),getRecord:r,activityType:i,selectors:n};for(let[c,h]of uc()){let u=n[c]||h.selector;$(e).find(u).off("click.jhsDetailState").on("click.jhsDetailState",(p=>{p.preventDefault(),p.stopPropagation(),this.requestToggle(l,c,p)}))}return this.render(l),l}async requestToggle(e,t,s=null){if(!e.carNum)return void show.error("番号不可用,无法更新状态");let a=await storageManager.getCar(e.carNum),r=q(a?.stateFlags);return t==="blocked"&&!r.blocked?void utils.q(s,`是否屏蔽${e.carNum}?`,(()=>this.toggle(e,t,s))):this.toggle(e,t,s)}async toggle(e,t,s=null){if(!e.carNum)return void show.error("番号不可用,无法更新状态");let a=e.selectors[t]||pc[t].selector,r=s?.currentTarget?$(s.currentTarget):$(e.root).find(a);if(!r.prop("disabled")){r.prop("disabled",!0).attr("aria-busy","true");try{let i=typeof e.getRecord=="function"?await e.getRecord():e.getRecord||{carNum:e.carNum};await this.stateService.toggle(e.carNum,t,{type:e.activityType,record:i}),await this.render(e),await utils.closePage({layerIndex:e.layerIndex,root:e.closeRoot||e.root})}catch(i){clog.error("详情状态更新失败",i),show.error("操作失败")}finally{r[0]?.isConnected&&r.prop("disabled",!1).removeAttr("aria-busy")}}}async render({root:e=document,carNum:t,selectors:s={}}){let a=await storageManager.getCar(T(t)),r=q(a?.stateFlags);for(let[i,n]of uc()){let l=$(e).find(s[i]||n.selector),c=!!r[i];l.attr("aria-pressed",String(c)).each((h,u)=>$(u).find("span").first().text(c?n.active():n.inactive()))}return r}};d(Ei,"DetailStateController");var Mt=Ei;var mc="https://jdforrepam.com/api",gc=0,Ys="",ls=new Map;async function fc(){let o=globalThis;if(o.credentialService?.get)return o.credentialService.get("jhs_appAuthorization");let e=localStorage.getItem("jhs_appAuthorization");return e?Xe(e):""}d(fc,"readJavDbToken");function Dh(o){return o&&typeof o=="object"?o:{}}d(Dh,"asResponseRecord");function vc(){let o=Math.floor(Date.now()/1e3);return Ys&&o-gc<=20||(gc=o,Ys=`${o}.lpw6vgqzsp.${md5(`${o}71cf27bb3c0bcdf207b64abecddc970098c7421ee7203b9cdae54478478a199e7d5a6e1a57691123c1a931c057842fb73ba3b3c83bcd69c17ccf174081e3d8aa`)}`),Ys}d(vc,"O");async function bc(o){let e=String(o||"").trim(),t=await fc();if(!t)throw Object.assign(new Error("请先登录 JavDB 账号"),{code:"LOGIN_REQUIRED"});if(!e)throw new Error("JavDB 影片 ID 无效");let s="----jhs-javdb-want-watch",a=[["status","want_watch"],["score","0"],["content",""]].map((([r,i])=>`--${s}\r + `)})),t}};d(Ei,"Fc2By123AvPlugin");var Ys=Ei;var Dh=Object.freeze({blocked:{id:"filterBtn",tone:"filter",label:Le},favorite:{id:"favoriteBtn",tone:"fav",label:Me},downloaded:{id:"hasDownBtn",tone:"down",label:fe},watched:{id:"hasWatchBtn",tone:"watch",label:ve}});function Mt({actions:o=["blocked","favorite","downloaded","watched"],ids:e={}}={}){let t=globalThis.$,s=t('
      ');s.attr("data-jhs-state-count",String(o.length));for(let a of o){let r=Dh[a];if(!r)continue;let i=t('');i.attr("id",e[a]||r.id).addClass(`jhs-btn--${r.tone}`).find("span").text(r.label),s.children().append(i)}return s}d(Mt,"createStateActions");var gc={blocked:{selector:"#filterBtn",inactive:d(()=>Le,"inactive"),active:d(()=>tt,"active")},favorite:{selector:"#favoriteBtn",inactive:d(()=>Me,"inactive"),active:d(()=>st,"active")},downloaded:{selector:"#hasDownBtn",inactive:d(()=>fe,"inactive"),active:d(()=>"已标记下载","active")},watched:{selector:"#hasWatchBtn",inactive:d(()=>ve,"inactive"),active:d(()=>"已标记观看","active")}};function pc(){return Object.entries(gc)}d(pc,"stateButtonEntries");var Di=class Di{constructor(e){this.stateService=e}bind({root:e=document,closeRoot:t=e,layerIndex:s=null,carNum:a,getRecord:r=null,activityType:i="detail-state",selectors:n={}}){let l={root:e,closeRoot:t,layerIndex:s,carNum:C(a),getRecord:r,activityType:i,selectors:n};for(let[c,h]of pc()){let u=n[c]||h.selector;$(e).find(u).off("click.jhsDetailState").on("click.jhsDetailState",(p=>{p.preventDefault(),p.stopPropagation(),this.requestToggle(l,c,p)}))}return this.render(l),l}async requestToggle(e,t,s=null){if(!e.carNum)return void show.error("番号不可用,无法更新状态");let a=await storageManager.getCar(e.carNum),r=H(a?.stateFlags);return t==="blocked"&&!r.blocked?void utils.q(s,`是否屏蔽${e.carNum}?`,(()=>this.toggle(e,t,s))):this.toggle(e,t,s)}async toggle(e,t,s=null){if(!e.carNum)return void show.error("番号不可用,无法更新状态");let a=e.selectors[t]||gc[t].selector,r=s?.currentTarget?$(s.currentTarget):$(e.root).find(a);if(!r.prop("disabled")){r.prop("disabled",!0).attr("aria-busy","true");try{let i=typeof e.getRecord=="function"?await e.getRecord():e.getRecord||{carNum:e.carNum};await this.stateService.toggle(e.carNum,t,{type:e.activityType,record:i}),await this.render(e),await utils.closePage({layerIndex:e.layerIndex,root:e.closeRoot||e.root})}catch(i){clog.error("详情状态更新失败",i),show.error("操作失败")}finally{r[0]?.isConnected&&r.prop("disabled",!1).removeAttr("aria-busy")}}}async render({root:e=document,carNum:t,selectors:s={}}){let a=await storageManager.getCar(C(t)),r=H(a?.stateFlags);for(let[i,n]of pc()){let l=$(e).find(s[i]||n.selector),c=!!r[i];l.attr("aria-pressed",String(c)).each((h,u)=>$(u).find("span").first().text(c?n.active():n.inactive()))}return r}};d(Di,"DetailStateController");var Bt=Di;var fc="https://jdforrepam.com/api",mc=0,Zs="",ls=new Map;async function vc(){let o=globalThis;if(o.credentialService?.get)return o.credentialService.get("jhs_appAuthorization");let e=localStorage.getItem("jhs_appAuthorization");return e?Xe(e):""}d(vc,"readJavDbToken");function Nh(o){return o&&typeof o=="object"?o:{}}d(Nh,"asResponseRecord");function bc(){let o=Math.floor(Date.now()/1e3);return Zs&&o-mc<=20||(mc=o,Zs=`${o}.lpw6vgqzsp.${md5(`${o}71cf27bb3c0bcdf207b64abecddc970098c7421ee7203b9cdae54478478a199e7d5a6e1a57691123c1a931c057842fb73ba3b3c83bcd69c17ccf174081e3d8aa`)}`),Zs}d(bc,"O");async function wc(o){let e=String(o||"").trim(),t=await vc();if(!t)throw Object.assign(new Error("请先登录 JavDB 账号"),{code:"LOGIN_REQUIRED"});if(!e)throw new Error("JavDB 影片 ID 无效");let s="----jhs-javdb-want-watch",a=[["status","want_watch"],["score","0"],["content",""]].map((([r,i])=>`--${s}\r Content-Disposition: form-data; name="${r}"\r \r ${i}\r `)).join("")+`--${s}--\r -`;try{let r=await gmHttp.gmRequest("POST",`${mc}/v1/movies/${encodeURIComponent(e)}/reviews`,a,{},{"user-agent":"Dart/3.5 (dart:io)","accept-language":"zh-TW",authorization:`Bearer ${t}`,jdsignature:await vc(),"content-type":`multipart/form-data; boundary=${s}`});if(r?.success===0)throw r;return await storageManager.deleteCachedRequest(`movie-detail:${e}`),ls.set(e,!0),r}catch(r){let i=Dh(r);if(i.status===401||i.action==="JWTVerificationError"||/未登录|登录|unauthorized|jwt/i.test(i.message||"")){let n=globalThis;throw n.credentialService?.remove?await n.credentialService.remove("jhs_appAuthorization"):localStorage.removeItem("jhs_appAuthorization"),Object.assign(new Error("JavDB 登录已失效,请重新登录"),{code:"LOGIN_REQUIRED"})}throw r instanceof Error?r:new Error(i.message||"加入 JavDB 想看失败")}}d(bc,"markJavDbWantWatch");async function wc(o){let e=String(o||"").trim(),t=await fc();if(!t)return null;if(!e)throw new Error("JavDB 影片 ID 无效");if(ls.has(e))return ls.get(e);let s=48;for(let a=1;a<=100;a++){let r=`${mc}/v2/users/review_movies?status=want_watch&type=0&sort_by=create&order_by=desc&page=${a}&limit=${s}`,i=await gmHttp.gmRequest("GET",r,null,{},{"user-agent":"Dart/3.5 (dart:io)","accept-language":"zh-TW",authorization:`Bearer ${t}`,jdsignature:await vc()}),n=i?.data?.movies??i?.movies;if(!Array.isArray(n))throw new Error("JavDB 想看状态响应无效");if(n.some(l=>String(l.id)===e))return ls.set(e,!0),!0;if(n.length
      ',success:d((r,i)=>{$(r).find("#loginBtn").on("click",async()=>{let n=String($(r).find("#username").val()||""),l=String($(r).find("#password").val()||"");if(!n||!l)return void show.error("请输入用户名和密码");let c=loading();try{let h=await e.login("javdb",{username:n,password:l},{scope:await s()});if(!h.success)return void show.error(h.message);if(!t?.set)throw new Error("凭证服务不可用");await t.set("jhs_appAuthorization",h.token),show.ok("登录成功"),o.close(i),await a?.()}catch(h){clog.error("登录异常:",h),show.error(h instanceof Error?h.message:String(h))}finally{c.close()}})},"success"),end:d(()=>{Zs=!1},"end")})}catch(r){throw Zs=!1,r}}d(yc,"openJavDbLoginDialog");async function Xs(o){if(o.isActive&&o.isActive()===!1)return;let e=globalThis.$,t=o.root?e(o.root):e(document),s=t.find(".origin-title").first();if(s.length||(s=t.find(".current-title").first()),s.length||(s=t.find("h3").first()),!s.length)return;let a=s.text().trim();if(!a)throw new TypeError("获取标题失败, 无法进行翻译");let r=s.nextAll(".translated-title").first();r.length||(r=e('
      ').insertAfter(s)),r.removeClass("is-error").text("翻译中...");try{let i=await o.translation.translate(a,{cacheAlias:o.carNum,scope:o.scope});if(o.isActive&&!o.isActive()||!s[0]?.isConnected||!r[0]?.isConnected)return;r.text(i)}catch(i){if(o.isActive&&!o.isActive()||!s[0]?.isConnected||!r[0]?.isConnected)return;let n=i instanceof Error?i.message:String(i);globalThis.clog?.error("翻译失败:",i),r.addClass("is-error").text(`翻译失败: ${n}`)}}d(Xs,"renderTranslatedTitle");function Nh(o){try{let e=new URL(String(o||""));return e.protocol==="https:"?e.href:null}catch{return null}}d(Nh,"normalizeImageUrl");function Lh(o,e,t){let s=globalThis.$,a=Nh(e);if(!a)return null;let r=s("").attr({src:a,alt:t,loading:"lazy"}).addClass("jhs-fc2-gallery__image"),i=s('').attr("aria-label",`查看${t}大图`).append(r);return o.empty().append(i).off("click.jhsScreenshot").on("click.jhsScreenshot",".jhs-fc2-screenshot-thumbnail",n=>{n.preventDefault(),n.stopPropagation(),globalThis.showImageViewer(r[0])}),a}d(Lh,"renderImage");async function ea(o){let e=globalThis.$,t=e(o.target),s=o.isActive??(()=>!0),a=o.providerId??"javstore";if(!t.length||!o.screenshot.isEnabled(o.settings))return t.empty(),null;let{mode:r}=o.screenshot.getScreenshotSettings(o.settings),i=o.screenshot.getEnabledProviders(o.settings);if(r!=="manual"&&!i.some(u=>u.id===a))return t.empty(),null;if(!i.length)return t.empty().append(e('
      没有可用截图来源
      ')),t;let n=d(async(u=t,p=a)=>{u.empty().append(dc("正在加载缩略图…"));try{let g=await o.screenshot.resolve({carNum:o.carNum},{providerId:p,scope:o.scope,settings:o.settings});if(!s())return null;let m=Array.isArray(g)?g[0]:g;return!m?.url||o.isDuplicate?.(m.url)?(u.empty(),null):Lh(u,m.url,"缩略图")}catch(g){return s()&&(u.empty().append(hc("缩略图加载失败 ",()=>{n(u,p)})),globalThis.clog?.error("缩略图加载失败",g)),null}},"load");if(r!=="manual")return n();let l=e('
      '),c=`jhs-screenshot-result-${String(o.carNum).replace(/[^a-z0-9_-]/gi,"-")}`,h=e('
      ').attr("id",c).text("请选择截图来源");return i.forEach((u,p)=>{let g=e('').attr({"aria-controls":c,tabindex:p===0?"0":"-1"}).text(u.name);g.on("click",async()=>{l.find("[role='tab']").attr({"aria-selected":"false",tabindex:"-1"}),g.attr({"aria-selected":"true",tabindex:"0"}),await n(h,u.id)}),l.append(g)}),l.on("keydown","[role='tab']",(u=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(u.key))return;u.preventDefault();let p=l.find("[role='tab']"),g=p.index(u.currentTarget),m=u.key==="Home"?0:u.key==="End"?p.length-1:u.key==="ArrowRight"?(g+1)%p.length:(g-1+p.length)%p.length;p.eq(m).trigger("focus").trigger("click")})),t.empty().append(l,h),t}d(ea,"renderScreenshotPanel");var Di=class Di{constructor(e){this.related=e.related,this.settings=e.settings,this.scope=e.scope}async show(e,t,s={}){let a=globalThis.$,r=s.isActive??(()=>!0);if(!t)throw new TypeError("未传入movieId");if(!r()||!e?.length)return a();let i=e.children('[data-jhs-panel="related"]').filter((b,w)=>a(w).attr("data-jhs-movie-id")===String(t)).first();if(i.length)return i;let n=a('').attr("data-jhs-movie-id",String(t)),l=a('

      相关清单

      '),c=a(''),h=await this.scope(),u=new te(`related:${t}`);if(!r()||h?.disposed)return a();let p=h?.addCleanup?.(()=>u.dispose());s.ownCleanup?.(()=>{u.dispose(),p?.()});let g={movieId:t,panel:n,panelScope:u,floorIndex:1,loaded:!1,loading:!1,page:1,enabled:!1,generation:0,isActive:d(()=>!u.disposed&&r(),"isActive"),requestScope:null};l.append(c),s.ownedSection?s.ownedSection.find('[data-jhs-section-actions="related"]').first().append(c):n.append(l),n.append('',''),e.append(n);let m=(this.settings.snapshot().enableLoadRelated??"no")==="yes",f=d(b=>{if(!g.isActive())return;let w=b==="yes";if(g.enabled!==w&&(g.enabled=w,g.generation++,w||(g.requestScope?.dispose(),g.loading=!1)),this.updateToggle(c,w),n.find(".jhs-related-container, .jhs-related-footer").toggle(w),g.loading||n.find(".jhs-related-load-more").prop("disabled",!1).text("加载更多清单"),w&&!g.loaded&&!g.loading)return this.fetch(g)},"applyExpanded");this.settings.addEventListener&&u.listen(this.settings,"settings.changed",b=>{b.detail?.names?.includes("enableLoadRelated")&&f(this.settings.snapshot().enableLoadRelated??"no")});let v=Ve({settings:this.settings,key:"enableLoadRelated",fallback:"no",apply:d(b=>{f(b)},"apply"),onError:d(b=>{globalThis.clog?.error("相关清单展开设置保存失败,已恢复",b),globalThis.show?.error?.("相关清单展开设置保存失败,已恢复原设置")},"onError")});return c.on("click",b=>{b.preventDefault(),b.stopPropagation(),v(g.enabled?"no":"yes")}),u.addCleanup(()=>{g.requestScope?.dispose(),c.off("click"),n.find("button").off("click")}),await f(m?"yes":"no"),n}updateToggle(e,t){e.attr("aria-expanded",String(t)),e.find(".toggle-text").text(t?"折叠":"展开"),e.find(".toggle-icon").text(t?"▲":"▼")}async fetch(e){if(e.loading||!e.enabled||!e.isActive())return;e.loading=!0;let t=e.panel.find(".jhs-related-container"),s=e.panel.find(".jhs-related-footer");t.empty().append(globalThis.$("
      ").addClass("jhs-panel-state").text("获取清单中...")),s.empty();let a=e.generation,r=new te(`related:${e.movieId}:page:1`),i=e.panelScope.addCleanup(()=>r.dispose());e.requestScope=r;try{let n=await this.related.list({movieId:e.movieId},{page:1,limit:20,scope:r});if(!e.isActive()||r.signal.aborted||a!==e.generation||!e.enabled)return;if(e.loading=!1,e.loaded=!0,t.empty(),!n.length)return void t.append(globalThis.$("
      ").addClass("jhs-panel-state").text("无清单"));this.display(e,n,t),n.length===20?this.bindLoadMore(e,t,s):s.append(globalThis.$("
      ").addClass("jhs-panel-end").text("已加载全部清单"))}catch(n){if(a===e.generation&&(e.loading=!1),!e.isActive()||r.signal.aborted||a!==e.generation||!e.enabled)return;globalThis.clog?.error("获取清单失败:",n),this.renderRetry(t,()=>{this.fetch(e)})}finally{i(),e.requestScope===r&&(e.requestScope=null)}}renderRetry(e,t){let s=globalThis.$;e.empty().append(s('
      ').append(document.createTextNode("获取清单失败 "),s('').on("click",t)))}bindLoadMore(e,t,s){let a=globalThis.$,r=a(''),i=a('').hide();s.empty().append(r,i),r.on("click",async()=>{if(!e.enabled||!e.isActive()||e.loading)return;let n=e.page+1,l=e.generation,c=new te(`related:${e.movieId}:page:${n}`),h=e.panelScope.addCleanup(()=>c.dispose());e.loading=!0,e.requestScope=c,r.text("加载中...").prop("disabled",!0);try{let u=await this.related.list({movieId:e.movieId},{page:n,limit:20,scope:c});if(!e.isActive()||c.signal.aborted||l!==e.generation||!e.enabled)return;e.page=n,this.display(e,u,t),u.length<20?(r.remove(),i.show()):r.text("加载更多清单").prop("disabled",!1)}catch(u){if(!e.isActive()||c.signal.aborted||l!==e.generation||!e.enabled)return;globalThis.clog?.error("加载更多清单失败:",u),r.text("加载失败,请重试").prop("disabled",!1)}finally{h(),l===e.generation&&(e.loading=!1),e.requestScope===c&&(e.requestScope=null)}})}display(e,t,s){let a=globalThis.$;t.forEach(r=>{let i=a("").addClass("jhs-related-title").attr({href:`/lists/${encodeURIComponent(r.id)}`,target:"_blank",rel:"noopener noreferrer"}).text(r.name||"未命名清单"),n=a('').append(a("").addClass("jhs-related-index").text(`#${e.floorIndex++}`),i),l=a(''),c=r.createdAt?globalThis.utils.formatDate(r.createdAt):"未知";l.append(a("").text(`视频:${Number(r.movieCount)||0}`),a("").text(`收藏:${Number(r.collectionCount)||0}`),a("").text(`查看:${Number(r.viewCount)||0}`),a('').text(`创建时间:${c}`)),s.append(a('').append(n,l))})}};d(Di,"RelatedPanel");var Bt=Di;var Ni=class Ni{constructor(e){this.review=e.review,this.settings=e.settings,this.storage=e.storage,this.scope=e.scope}async show(e,t,s={}){let a=globalThis.$,r=s.isActive??(()=>!0);if(!r()||!t?.length)return a();let i=t.children('[data-jhs-panel="reviews"]').filter((b,w)=>a(w).attr("data-jhs-movie-id")===String(e)).first();if(i.length)return i;let n=a('
      ').attr("data-jhs-movie-id",String(e)),l=a('

      评论

      '),c=a(''),h=await this.scope(),u=new te(`reviews:${e}`);if(!r()||h?.disposed)return a();let p=h?.addCleanup?.(()=>u.dispose());s.ownCleanup?.(()=>{u.dispose(),p?.()});let g={movieId:e,panel:n,panelScope:u,floorIndex:1,loaded:!1,loading:!1,page:1,enabled:!1,generation:0,isActive:d(()=>!u.disposed&&r(),"isActive"),requestScope:null};l.append(c),s.ownedSection?s.ownedSection.find('[data-jhs-section-actions="reviews"]').first().append(c):n.append(l),n.append('
      ',''),t.append(n),this.bindFilter(n);let m=(this.settings.snapshot().enableLoadReview??"yes")==="yes",f=d(b=>{if(!g.isActive())return;let w=b==="yes";if(g.enabled!==w&&(g.enabled=w,g.generation++,w||(g.requestScope?.dispose(),g.loading=!1)),this.updateToggle(c,w),n.find(".jhs-review-container, .jhs-review-footer").toggle(w),n.find(".jhs-review-load-more").prop("disabled",!1).text("加载更多评论"),w&&!g.loaded&&!g.loading)return this.fetch(g)},"applyExpanded");this.settings.addEventListener&&u.listen(this.settings,"settings.changed",b=>{b.detail?.names?.includes("enableLoadReview")&&f(this.settings.snapshot().enableLoadReview??"yes")});let v=Ve({settings:this.settings,key:"enableLoadReview",fallback:"yes",apply:d(b=>{f(b)},"apply"),onError:d(b=>{globalThis.clog?.error("评论面板展开设置保存失败,已恢复",b),globalThis.show?.error?.("评论面板展开设置保存失败,已恢复原设置")},"onError")});return c.on("click",b=>{b.preventDefault(),b.stopPropagation();let S=c.find(".toggle-text").text()==="展开"?"yes":"no";v(S)}),u.addCleanup(()=>{g.requestScope?.dispose(),c.off("click"),n.off("contextmenu.jhsReviewFilter")}),await f(m?"yes":"no"),n}updateToggle(e,t){e.attr("aria-expanded",String(t)),e.find(".toggle-text").text(t?"折叠":"展开"),e.find(".toggle-icon").text(t?"▲":"▼")}async fetch(e){if(e.loading||!e.enabled||!e.isActive())return;let t=globalThis.$,s=e.panel.find(".jhs-review-container"),a=e.panel.find(".jhs-review-footer");e.loading=!0,s.empty().append(t('
      ').text("获取评论中...")),a.empty();let r=Number(this.settings.snapshot().reviewCount)||20,i=e.generation,n=new te(`reviews:${e.movieId}:page:1`),l=e.panelScope.addCleanup(()=>n.dispose());e.requestScope=n;try{let c=await this.review.list({movieId:e.movieId},{page:1,limit:r,scope:n});if(!e.isActive()||n.signal.aborted||i!==e.generation||!e.enabled)return;let h=await this.getKeywords();if(!e.isActive()||n.signal.aborted||i!==e.generation||!e.enabled)return;if(e.loading=!1,e.loaded=!0,s.empty(),!c.length)return void s.append(t('
      ').text("无评论"));await this.display(e,c,s,h),c.length===r?this.bindLoadMore(e,r,h,s,a):a.append(t('
      ').text("已加载全部评论"))}catch(c){if(i===e.generation&&(e.loading=!1),!e.isActive()||n?.signal?.aborted)return;globalThis.clog?.error("获取评论失败:",c),this.renderRetry(s,"获取评论失败",()=>{this.fetch(e)})}finally{l(),e.requestScope===n&&(e.requestScope=null)}}async getKeywords(){return Wt(this.storage)}async saveKeyword(e){await Wt(this.storage,e)}renderRetry(e,t,s){let a=globalThis.$;e.empty().append(a('
      ').append(document.createTextNode(`${t} `),a('').on("click",s)))}bindLoadMore(e,t,s,a,r){let i=globalThis.$,n=i(''),l=i('
      已加载全部评论
      ').hide();r.empty().append(n,l),n.on("click",async()=>{if(!e.enabled||!e.isActive()||e.loading)return;let c=e.page+1,h=e.generation,u=new te(`reviews:${e.movieId}:page:${c}`),p=e.panelScope.addCleanup(()=>u.dispose());e.requestScope=u,e.loading=!0,n.text("加载中...").prop("disabled",!0);try{let g=await this.review.list({movieId:e.movieId},{page:c,limit:t,scope:u});if(!e.isActive()||u.signal.aborted||h!==e.generation||!e.enabled)return;e.page=c,await this.display(e,g,a,s),g.lengthn.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|")):null;for(let n of t){let l=String(n.content||"");if(i?.test(l))continue;let c=r('
      '),h=r('
      '),u=r('
      ');h.append(r("").addClass("jhs-review-author").text(n.author||"匿名用户"));let p=r(''),g=Math.max(0,Math.min(5,Number(n.score)||0));for(let f=0;f');let m=globalThis.utils.formatDate(n.createdAt);h.append(p,r("").text(m),r("").text(`点赞:${Number(n.likes)||0}`),r("").addClass("jhs-review-floor").text(`#${e.floorIndex++}楼`)),this.appendContent(u,l),c.append(h,u),s.append(c)}}appendContent(e,t){let s=/ed2k:\/\/\|file\|[^|]+\|\d+\|[a-fA-F0-9]{32}\|\/|magnet:\?[^\s"'<>`,;\u4e00-\u9fa5,。?!()【】]+|https?:\/\/[^\s"'<>`,;\u4e00-\u9fa5,。?!()【】]+/g,a=0,r;for(;r=s.exec(t);)r.index>a&&e.append(document.createTextNode(t.slice(a,r.index))),this.appendLink(e,r[0]),a=r.index+r[0].length;a':''),c=s(''),h=a?s('').text(i).on("click",()=>globalThis.utils.copyToClipboard(i,t)):s("").addClass("jhs-review-link").attr({href:t,target:"_blank",rel:"noopener noreferrer"}).text(i),u=s('').on("click",()=>globalThis.utils.copyToClipboard(i,t));c.append(h,u),l.append(c),n&&l.append(s('').append(s('').attr("data-resource",t))),e.append(l)}bindFilter(e){e.off("contextmenu.jhsReviewFilter",".review-content").on("contextmenu.jhsReviewFilter",".review-content",async t=>{if((this.settings.snapshot().enableTitleSelectFilter??"yes")!=="yes")return;let s=String(window.getSelection()?.toString()||"");s&&(t.preventDefault(),await globalThis.utils.q(t,`是否将 '${C(s)}' 加入评论区关键词?`,async()=>{await this.saveKeyword(s),globalThis.show.ok("操作成功, 刷新页面后生效")}))})}};d(Ni,"ReviewPanel");var Ot=Ni;function Mh(o,e="other"){if(!o||typeof o!="object"||Array.isArray(o))return null;let t=o,s=T(t.carNum);return s?Object.freeze({...t,carNum:s,movieId:typeof t.movieId=="string"&&t.movieId.trim()?t.movieId.trim():t.movieId??null,surface:t.surface||e}):null}d(Mh,"normalizeWorkspaceMovieContext");function jc({carNum:o="",source:e="fc2",mode:t="dialog"}={}){let s=$('
      ').attr({"data-jhs-fc2-source":e,"data-jhs-fc2-mode":t,"data-jhs-car-num":T(o)||""});return[["summary","影片概览"],["gallery","预览与剧照"],["resources","资源"],["reviews","评论"],["related","相关清单"]].forEach((([r,i])=>{let n=$('
      ').attr("data-jhs-section",r),l=$('
      '),c=$("

      ").text(i),h=$('
      ').attr("data-jhs-section-actions",r);n.append(l.append(c,h),$('
      ').attr("data-jhs-slot",r)),s.append(n)})),s}d(jc,"createFc2DetailShell");function Sc(o,e={}){let t=$(o).is(".jhs-fc2-workspace")?$(o):$(o).find(".jhs-fc2-workspace").first(),s=!1,a=`.jhsFc2Detail${Date.now()}${Math.random().toString(36).slice(2)}`,r=new Set,i=e.mode==="dialog"?"fc2-dialog":"native-detail",n=Mh({...e,carNum:e.carNum||t.attr("data-jhs-car-num"),detailUrl:e.url,surface:i},i),l={...e,movieContext:n,root:t,workspace:t,namespace:a,observers:r,getSlot:d(c=>t.find(`[data-jhs-slot="${c}"]`).first(),"getSlot"),getSection:d(c=>t.find(`[data-jhs-section="${c}"]`).first(),"getSection"),isAlive:d(()=>!s&&t[0]?.isConnected!==!1,"isAlive"),addObserver(c){return c&&r.add(c),c},destroy(){s||(s=!0,t.off(a).find("*").off(a),r.forEach((c=>c.disconnect?.())),r.clear(),t.removeData("jhsFc2Context"))}};return t.data("jhsFc2Context",l).attr("data-jhs-surface",i),n&&t.data("jhsMovieContext",n),l}d(Sc,"createFc2DetailContext");function Bh(o){return cl(o,window.location.origin)}d(Bh,"parseExplicitJavDbMovieId");var Li=class Li extends I{constructor(){super(...arguments),this.detailStateController=null,this.translationGeneration=0}getName(){return"Fc2Plugin"}getDetailStateController(){return this.detailStateController||(this.detailStateController=new Mt(this.getRuntimeService("state")))}async resolveMovieId(e){let t=await this.getRuntimeService("scope")();return(await this.getRuntimeService("movie").resolve({carNum:e},{scope:t}))?.movieId||null}async resolveMovieIdForRecord(e,t=""){return Bh(t)||this.resolveMovieId(e)}async initCss(){return``}async handle(){if(!X.includes("collection_codes?movieId"))return;let e=new URLSearchParams(window.location.search),t=e.get("movieId"),s=e.get("carNum"),a=e.get("url"),r=e.get("source"),i=$("section").first().empty();if(!s||!a)return void i.append($('
      ').text("FC2 详情参数不完整"));let n=t&&t!=="search"?t:await this.resolveMovieIdForRecord(s,a),l=["fc2","123av"].includes(r||"")?r:await this.resolveFc2Source({url:a}),c=this.mountFc2Detail(i,{movieId:n,carNum:s,url:a,source:l,mode:"page"});$(window).off("pagehide.jhsFc2Detail").one("pagehide.jhsFc2Detail",(()=>c.destroy()))}openFc2Dialog(e,t,s,{source:a=""}={}){a=["fc2","123av"].includes(a)?a:"";let r=null;return this.getRuntimeService("dialog").open({type:1,title:t,content:'
      ',ui:{size:"workspace",body:"scroll"},area:utils.getDialogArea("workspace"),skin:"movie-detail-layer",scrollbar:!1,shadeClose:!0,success:d((i,n)=>{r=this.mountFc2Detail($(i).find(".jhs-fc2-dialog-host"),{movieId:e,carNum:t,url:s,source:a,layerIndex:n,mode:"dialog"}),utils.setupEscClose(n)},"success"),end:d(()=>r?.destroy(),"end")})}mountFc2Detail(e,t){let s=$(e);s.data("jhsFc2Context")?.destroy?.(),s.empty();let r=jc(t).appendTo(s),i=Sc(r,t);return s.data("jhsFc2Context",i),i.translationGeneration=0,i.screenshotGeneration=0,i.otherSiteGeneration=0,this.initializeWorkspace(i),this.bindFc2FeatureLifecycle(i),i}initializeWorkspace(e){let t=$('
      正在加载影片信息…
      '),s=$('');s.append(Lt()),s.append('','',''),t.find(".jhs-fc2-summary__body").append(s),e.getSlot("summary").append(t);let a=$(''),r=$('
      ');a.on(`click${e.namespace}`,".jhs-fc2-gallery-item",(f=>{let v=$(f.currentTarget).find("img")[0];v&&globalThis.showImageViewer(v,"",{galleryRoot:a[0]})})),e.getSlot("gallery").append(a,r);let i=$('
      '),n=this.createResourceGroup("站内磁力","native-magnets"),l=this.createResourceGroup("第三方站点","other-sites"),c=this.createResourceGroup("更多磁力来源","magnet-hub"),h=$(''),u=null;c.find('[data-jhs-role="magnet-hub"]').append(h,'
      '),i.append(n,l,c),e.getSlot("resources").append(i),s.on(`click${e.namespace}`,'[data-jhs-action="subtitlecat"]',(f=>{let v=this.getRuntimeService("movie").sourceUrls({carNum:e.carNum},["subtitlecat"])[0]?.url;v&&utils.openPage(v,e.carNum,!1,f)}));let p=this.getOptionalDependency("DetailPageButtonPlugin");p?s.on(`click${e.namespace}`,'[data-jhs-action="xunlei"]',(()=>p.searchXunLeiSubtitle(e.carNum))):s.find('[data-jhs-action="xunlei"]').remove();let g=this.getOptionalDependency("MagnetHubPlugin");g||c.remove(),h.on(`click${e.namespace}`,(async()=>{if(!g||!e.isAlive())return;let f=c.find('[data-jhs-role="magnet-hub-content"]');if(h.attr("aria-expanded")==="true")return c.addClass("is-collapsed"),void h.attr("aria-expanded","false").text("展开磁力搜索");u||(u=g.createMagnetHub({movieContext:e.movieContext,root:e.root}));let b=await u;e.isAlive()&&!f.children().length&&f.append(b),e.isAlive()&&(c.removeClass("is-collapsed"),h.attr("aria-expanded","true").text("收起磁力搜索"),f[0]?.scrollIntoView?.({block:"nearest"}))})),this.getDetailStateController().bind({root:e.root,layerIndex:e.layerIndex??null,carNum:e.carNum,activityType:"fc2-state",getRecord:d(()=>({carNum:e.carNum,url:e.url,fc2Source:e.source,names:e.root.find('[data-jhs-role="actress-data"]').text(),publishTime:e.root.find('[data-jhs-role="publish-time"]').text()}),"getRecord")}),e.source==="123av"?this.load123AvDetail(e):this.loadNativeDetail(e);let m=this.getOptionalDependency("FilterTitleKeywordPlugin");m&&Promise.resolve().then((()=>m.bindDetailRoot(e.root,{layerIndex:e.layerIndex??null}))).catch((f=>clog.error("FC2 关键词过滤初始化失败",f))),this.mountFc2OtherSites(e,l,this.getOptionalDependency("OtherSitePlugin")),this.loadFc2Screenshot(e)}bindFc2FeatureLifecycle(e){let t=this.getRuntimeService("settings"),s=d(a=>{let r=a.detail?.names;if(r?.length&&(r.includes("enableLoadScreenShot")&&(t.snapshot().enableLoadScreenShot==="no"?(e.screenshotGeneration=(e.screenshotGeneration||0)+1,this.unmountFc2Screenshot(e)):this.loadFc2Screenshot(e)),r.includes("translateTitle")&&((t.snapshot().translateTitle??R)===R?this.applyFc2Translation(e):(e.translationGeneration=(e.translationGeneration||0)+1,this.revertFc2Translation(e))),r.includes("enableMagnetsFilter")&&e.magnetFilterApply?.((t.snapshot().enableMagnetsFilter??R)===R),r.includes("enableLoadOtherSite"))){let i=e.getSection("resources").find('[data-jhs-role="other-sites"]').closest(".jhs-fc2-resource-group");t.snapshot().enableLoadOtherSite==="no"?(e.otherSiteGeneration=(e.otherSiteGeneration||0)+1,this.unmountFc2OtherSites(e,i)):this.mountFc2OtherSites(e,i,this.getOptionalDependency("OtherSitePlugin"))}},"handler");t.addEventListener("settings.changed",s),e.addObserver({disconnect:d(()=>t.removeEventListener("settings.changed",s),"disconnect")})}loadFc2Screenshot(e){let t=this.getRuntimeService("screenshot"),s=this.getRuntimeService("settings"),a=e.root.find('[data-jhs-role="screenshot"]');if(!t.isEnabled(s.snapshot()))return void a.empty();let r=(e.screenshotGeneration||0)+1;e.screenshotGeneration=r,Promise.resolve().then((()=>this.getRuntimeService("scope")())).then(i=>ea({target:a,carNum:e.carNum.replace("FC2-",""),screenshot:t,settings:s.snapshot(),scope:i,isActive:d(()=>e.isAlive()&&s.snapshot().enableLoadScreenShot!=="no"&&r===e.screenshotGeneration,"isActive"),isDuplicate:d(n=>!!e.galleryUrls?.has(n),"isDuplicate")})).then(i=>{if(!(!e.isAlive()||r!==e.screenshotGeneration)&&s.snapshot().enableLoadScreenShot==="no")return void a.empty()}).catch(i=>{!e.isAlive()||r!==e.screenshotGeneration||(a.empty(),clog.error("FC2 剧照初始化失败",i))})}unmountFc2Screenshot(e){e.screenshotGeneration=(e.screenshotGeneration||0)+1,e.root.find('[data-jhs-role="screenshot"]').empty()}applyFc2Translation(e){let t=this.getRuntimeService("settings");if(!e.isAlive()||(t.snapshot().translateTitle??R)!==R)return;let s=(e.translationGeneration||0)+1;e.translationGeneration=s,Promise.resolve().then((()=>this.getRuntimeService("scope")())).then(a=>Xs({root:e.root,carNum:e.carNum,translation:this.getRuntimeService("translation"),scope:a,isActive:d(()=>e.isAlive()&&(t.snapshot().translateTitle??R)===R&&s===e.translationGeneration,"isActive")})).catch((a=>clog.error("FC2 标题翻译失败",a)))}revertFc2Translation(e){e.root.find(".translated-title").remove()}mountFc2OtherSites(e,t,s){if(!s)return void t.remove();let a=this.getRuntimeService("settings"),r=(e.otherSiteGeneration||0)+1;e.otherSiteGeneration=r,t.length&&t.show(),Promise.resolve().then((()=>s.loadOtherSite(e.carNum.replace("FC2-",""),e.carNum,{root:e.root,target:t.find('[data-jhs-role="other-sites"]'),autoDetect:!1,isActive:d(()=>e.isAlive()&&a.snapshot().enableLoadOtherSite!=="no"&&r===e.otherSiteGeneration,"isActive")}))).then(i=>{!e.isAlive()||r!==e.otherSiteGeneration||(i?t.show():t.hide())}).catch(i=>{!e.isAlive()||r!==e.otherSiteGeneration||(t.show(),he(e.root.find('[data-jhs-role="other-sites"]'),"外部站点加载失败"),clog.error("FC2 外部站点加载失败",i))})}unmountFc2OtherSites(e,t){e.otherSiteGeneration=(e.otherSiteGeneration||0)+1,e.root.find("[data-jhs-other-site-box],[data-jhs-other-site-settings]").remove(),t.length&&t.hide()}createResourceGroup(e,t){return $('

      ').find("h3").text(e).end().find("div").attr("data-jhs-role",t).end()}async loadNativeDetail(e){let t=Promise.resolve(e.movieId);this.configureJavDbWantButton(e,t),await Promise.allSettled([this.fetchAndRenderNativeDetail(e),this.fetchAndRenderNativeMagnets(e),this.mountPanels(e,t)]),e.isAlive()&&this.applyFc2Translation(e)}async load123AvDetail(e){let t=this.getOptionalDependency("Fc2By123AvPlugin");if(!t)return void he(e.getSlot("summary"),"123AV 详情功能已禁用");let s=t.resolveMovieId(e.carNum);this.configureJavDbWantButton(e,s),this.mountPanels(e,s),s.then((a=>{if(e.isAlive())return this.fetchAndRenderNativeMagnets(e,a)})).catch((a=>{e.isAlive()&&he(e.root.find('[data-jhs-role="native-magnets"]'),"站内磁力关联失败",(()=>{this.load123AvMagnets(e)})),clog.error("123AV 磁力关联失败",a)})),await t.loadDetail(e,e.url),e.isAlive()&&this.applyFc2Translation(e)}async load123AvMagnets(e){let t=this.getOptionalDependency("Fc2By123AvPlugin");if(!t)throw new Error("123AV 详情功能已禁用");let s=await t.resolveMovieId(e.carNum);return this.fetchAndRenderNativeMagnets(e,s)}async configureJavDbWantButton(e,t){let s=e.root.find('[data-jhs-action="javdb-want"]');try{let a=await t;if(!e.isAlive())return;if(!a)return void s.prop("disabled",!0).text("JavDB 暂无对应作品");try{let r=await wc(a);if(!e.isAlive())return;if(r)return void s.prop("disabled",!0).attr("aria-pressed","true").text("已在 JavDB 想看")}catch(r){clog.warn("读取 JavDB 想看状态失败,保留手动操作",r)}s.prop("disabled",!1).text("JavDB 想看").off(`click${e.namespace}`).on(`click${e.namespace}`,(()=>{this.submitJavDbWant(e,a,s)}))}catch(a){e.isAlive()&&s.prop("disabled",!1).text("JavDB 关联失败,重试").off(`click${e.namespace}`).on(`click${e.namespace}`,(()=>{this.configureJavDbWantButton(e,this.resolveMovieId(e.carNum))})),clog.error("FC2 JavDB 想看关联失败",a)}}async submitJavDbWant(e,t,s){if(!(!e.isAlive()||s.data("jhsBusy")||s.attr("aria-pressed")==="true")){s.data("jhsBusy",!0).attr({"aria-busy":"true","aria-disabled":"true"}).text("正在加入想看…");try{if(await bc(t),!e.isAlive())return;s.attr({"aria-pressed":"true","aria-disabled":"false"}).text("已加入 JavDB 想看"),show.ok("已加入 JavDB 想看")}catch(a){if(!e.isAlive())return;let r=a;if(r?.code==="LOGIN_REQUIRED")return s.attr("aria-disabled","false").text("JavDB 想看"),yc({dialog:this.getRuntimeService("dialog"),account:this.getRuntimeService("account"),credential:this.getRuntimeService("credential"),getScope:this.getRuntimeService("scope"),onSuccess:d(()=>this.submitJavDbWant(e,t,s),"onSuccess")});s.attr("aria-disabled","false").text("JavDB 想看"),show.error(r?.message||"加入 JavDB 想看失败"),clog.error("加入 JavDB 想看失败",a)}finally{e.isAlive()&&s.removeData("jhsBusy").removeAttr("aria-busy")}}}async fetchAndRenderNativeDetail(e){try{let t=await this.getRuntimeService("scope")(),s=await this.getRuntimeService("movie").detail({movieId:e.movieId,carNum:e.carNum,providerId:"javdb"},{scope:t});if(!s)throw new Error("JavDB 影片详情不存在");if(!e.isAlive())return;this.renderSummary(e,s),os(e,s.imageUrls||[],s.coverUrl||null)}catch(t){e.isAlive()&&he(e.root.find('[data-jhs-role="summary-content"]'),"影片信息加载失败",(()=>{this.fetchAndRenderNativeDetail(e)})),clog.error("FC2 详情加载失败",t)}}renderSummary(e,t){let s=e.root.find('[data-jhs-role="summary-content"]').empty(),a=$('

      ');a.find("strong").text(t.title||"无标题"),s.append(a),t.originalTitle&&t.originalTitle!==t.title&&s.append($('
      ').text(t.originalTitle));let r=$('
      ');[`番号:${t.carNum||e.carNum}`,`发行:${t.releaseDate||"未知"}`,`评分:${Number.isFinite(Number(t.score))?t.score:"无"}`,`时长:${Number.isFinite(Number(t.duration))?t.duration+" 分钟":"无"}`].forEach((l=>r.append($("").text(l)))),s.append(r);let i=[],n=$('
      主演:
      ');(t.actors||[]).forEach((l=>{n.append($("").addClass("jhs-fc2-actor").attr({href:`/actors/${encodeURIComponent(l.id)}`,target:"_blank",rel:"noopener noreferrer"}).text(l.name||"未知演员")),l.gender===0&&i.push(l.name)})),t.actors?.length||n.append($("").text("暂无演员信息")),s.append(n,Gs(e,this.getRuntimeService("movie")),$('').text(i.join(" ")),$('').text(t.releaseDate||""))}async fetchAndRenderNativeMagnets(e,t=e.movieId){let s=e.root.find('[data-jhs-role="native-magnets"]');he(s,"正在加载站内磁力…");try{if(!t)return he(s,"JavDB 暂无对应作品");let a=await this.getRuntimeService("scope")(),r=await this.getRuntimeService("magnet").listNative({movieId:t,providerId:"javdb"},{scope:a});if(!e.isAlive())return;if(s.empty(),!r.length)return he(s,"暂无站内磁力");let i=[],n=this.getRuntimeService("magnet");r.forEach((l=>{let c=wl(l.hash);if(!c)return;let h=`magnet:?xt=urn:btih:${c}`,u=n.assess({title:l.title,hasHdTag:l.hasHdTag,hasSubtitleTag:l.hasSubtitleTag,date:l.createdAt,seeders:l.seeders}),p=$('
      ').attr("data-jhs-high-quality",String(u.highQuality)),g=$('
      '),m=$('
      '),f=$('
      ');i.push(u),f.append($("").addClass("jhs-badge").attr("title",`磁力质量评分 ${u.score.total}`).text(`${u.grade} ${u.score.total}`)),l.hasHdTag&&f.append('高清'),l.hasSubtitleTag&&f.append('字幕'),g.append($("").attr("href",h).text(l.title||h),$("
      ").addClass("jhs-fc2-meta").text(`${(Number(l.sizeMb||0)/1024).toFixed(2)} GB · ${Number(l.fileCount)||0} 个文件${l.createdAt?` · ${l.createdAt}`:""}`),f),m.append($('').attr("data-clipboard-text",h),$('').attr({"data-resource":h,"data-jhs-offline-owner":"fc2"})),s.append(p.append(g,m))})),await this.bindNativeMagnetFilter(e,s,i.some((l=>l.highQuality)))}catch(a){e.isAlive()&&he(s,"站内磁力加载失败",(()=>{this.fetchAndRenderNativeMagnets(e,t)})),clog.error("FC2 磁力加载失败",a)}}async bindNativeMagnetFilter(e,t,s){let a=e.getSection("resources"),r=a.find(".jhs-fc2-section__actions");r.find('[data-jhs-action="filter-native-magnets"]').remove();let n=$(''),l=d(u=>{t.find(".jhs-fc2-magnet-item").show(),u&&s&&t.find('.jhs-fc2-magnet-item[data-jhs-high-quality="false"]').hide(),n.attr("aria-pressed",String(u&&s)).text(s?u?"显示全部磁力":"过滤低质量":"暂无可过滤项").prop("disabled",!s)},"apply"),c=this.getRuntimeService("settings"),h=Ve({settings:c,key:"enableMagnetsFilter",fallback:"no",apply:d(u=>l(u===R),"apply"),onError:d(u=>{clog.error("磁力过滤设置保存失败,已恢复",u),show.error("磁力过滤设置保存失败,已恢复原设置")},"onError")});e.magnetFilterApply=l,r.append(n),l((c.snapshot().enableMagnetsFilter??R)===R),n.on(`click${e.namespace}`,(async()=>{let u=n.attr("aria-pressed")!=="true";await h(u?R:"no")}))}async mountPanels(e,t){try{let s=await t;if(!e.isAlive())return;if(!s)return this.clearOwnedPanel(e,"reviews"),this.clearOwnedPanel(e,"related"),he(e.getSlot("reviews"),"JavDB 暂无对应作品"),he(e.getSlot("related"),"JavDB 暂无对应作品");this.clearOwnedPanel(e,"reviews"),this.clearOwnedPanel(e,"related");let a=d(()=>this.getRuntimeService("scope")(),"scope"),r=new Bt({related:this.getRuntimeService("related"),settings:this.getRuntimeService("settings"),scope:a}),i=new Ot({review:this.getRuntimeService("review"),settings:this.getRuntimeService("settings"),storage:this.getRuntimeService("storage"),scope:a});await Promise.allSettled([i.show(s,e.getSlot("reviews"),{ownedSection:e.getSection("reviews"),isActive:e.isAlive,ownCleanup:d(n=>e.addObserver({disconnect:n}),"ownCleanup")}),r.show(e.getSlot("related"),s,{ownedSection:e.getSection("related"),isActive:e.isAlive,ownCleanup:d(n=>e.addObserver({disconnect:n}),"ownCleanup")})])}catch(s){if(!e.isAlive())return;this.clearOwnedPanel(e,"reviews"),this.clearOwnedPanel(e,"related");let a=d(()=>{this.mountPanels(e,this.resolveMovieId(e.carNum))},"retry");he(e.getSlot("reviews"),"评论关联失败",a),he(e.getSlot("related"),"相关清单关联失败",a),clog.error("FC2 JavDB 关联失败",s)}}clearOwnedPanel(e,t){e.getSlot(t).empty(),e.getSection(t).find(".jhs-fc2-section__actions").empty()}async resolveFc2Source(e={}){if(e.fc2Source&&["fc2","123av"].includes(e.fc2Source))return e.fc2Source;try{let t=new URL(e.url||"",window.location.origin);return this.getRuntimeService("movie").matchesProviderUrl("av123",t.href)?"123av":t.origin===window.location.origin?"fc2":""}catch{return""}}createFc2PageUrl(e,t,s,{source:a=""}={}){if(!String(e||"").trim())throw new TypeError("FC2 owned detail requires movieId");let r=new URL("/users/collection_codes",window.location.origin);return r.searchParams.set("movieId",String(e).trim()),r.searchParams.set("carNum",t),r.searchParams.set("url",s),r.searchParams.set("source",a),r.href}async openFc2Page(e,t,s,a={newTab:!0},{source:r=""}={}){r=["fc2","123av"].includes(r)?r:"";let i=String(e||"").trim();if(!i)return void utils.openPage(s,t,!0,a);utils.openPage(this.createFc2PageUrl(i,t,s,{source:r}),t,!0,a)}};d(Li,"Fc2Plugin");var ta=Li;var Mi=class Mi extends I{getName(){return"HitShowPlugin"}async handle(){let e=je(window.location);if(e.kind!=="playback-ranking")return;let t=this.getRuntimeService("host").locateListRoot?.();t&&(t.setAttribute("data-jhs-ranking","playback"),t.setAttribute("data-jhs-ranking-period",e.period),t.setAttribute("data-jhs-ranking-filter",e.filter))}};d(Mi,"HitShowPlugin");var sa=Mi;var Bi=class Bi extends I{getName(){return"JavTrailersPlugin"}constructor(){super(),this.hasBand=!1}async handle(){let e=window.location.href;if(!e.includes("handle=1"))return;if($("h1:contains('Page not found')").length){clog.log("番号无法匹配, 跳搜索");let a=e.split("?")[0].split("video/")[1].toLowerCase().replace("00","-");return void(window.location.href="/search/"+encodeURIComponent(a)+window.location.search)}let t=$(".videos-list .video-link").toArray();if(t.length){let a=e.split("?")[0].split("search/")[1].toLowerCase(),r=t.find((i=>$(i).find(".vid-title").text().toLowerCase().includes(a)));if(r)return void(window.location.href=$(r).attr("href")+window.location.search)}let s=await this.getRuntimeService("scope")();this.handlePlayJavTrailers(s),this.bindPlaybackControls(s)}bindPlaybackControls(e){let t=$("#videoPlayerContainer"),s=d(()=>this.handlePlayJavTrailers(e),"replay");t.off("click.jhsJavTrailers").on("click.jhsJavTrailers",s),e.addCleanup((()=>t.off("click.jhsJavTrailers",s))),e.listen(window,"message",(()=>{let a=document.getElementById("vjs_video_3_html5_api");a&&(a.currentTime+=5)}))}handlePlayJavTrailers(e){if(this.hasBand||e.signal.aborted)return;let t=utils.loopDetector((()=>$("#vjs_video_3_html5_api").length!==0),(()=>{e.signal.aborted||e.ownTimeout(setTimeout((()=>{if(e.signal.aborted)return;this.hasBand=!0;let a=document.getElementById("vjs_video_3_html5_api");a&&(clog.debug(a),de(a,{context:"JavTrailers 预览"}),a.currentTime=5,e.listen(a,"timeupdate",(function(){a.currentTime>=14&&a.currentTime<16&&(a.currentTime+=2)})),$("#vjs_video_3_html5_api").css({position:"fixed",width:"100vw",height:"100vh",objectFit:"cover",zIndex:String(W.debug)}),$(".vjs-control-bar").css({position:"fixed",bottom:"20px",zIndex:String(W.debug)}))}),100))}),20,1e4,!0,e),s=utils.loopDetector((()=>$("#vjs_video_3 canvas").length>0),(()=>{e.signal.aborted||$("#vjs_video_3 canvas").length!==0&&$("#vjs_video_3 canvas").css({position:"fixed",width:"100vw",height:"100vh",objectFit:"cover",top:"0",right:"0",zIndex:String(W.debug-1)})}),20,1e4,!0,e);e.addCleanup(t),e.addCleanup(s)}};d(Bi,"JavTrailersPlugin");var aa=Bi;var ra=Object.freeze({magnet:216e5,screenshot:6048e5,screenshotNegative:432e5,match115:36e5,externalDetail:864e5}),Oi=class Oi extends Error{constructor(e,t,s,a={}){super(s,{cause:a.cause}),this.name="ProviderError",this.provider=e,this.code=t,this.status=a.status||0,this.url=a.url||"",this.retryable=!!a.retryable}};d(Oi,"ProviderError");var we=Oi;function cs(o){let e=0,t=Number(o.seeders)||0,s=t>=50?35:t>=10?25:t>=1?15:3;e+=s;let a=String(o.title||"").toLowerCase(),r=String(o.resolution||"").toLowerCase(),i=/4k|2160p/.test(r)||/4k|2160p/.test(a)?25:/1080p/.test(r)||/1080p/.test(a)?20:/720p/.test(r)||/720p/.test(a)?15:5;e+=i;let n=o.hasSubtitle||/-c\b|-uc\b|chinese|中字|字幕/.test(a)?20:0;e+=n;let l=Oh(o.date),c=l<=7?15:l<=30?12:l<=90?8:3;e+=c;let h=/sample|预告|trailer/.test(a)?-15:0;return e+=h,{total:Math.max(0,Math.min(100,e)),seeders:s,resolution:i,subtitle:n,freshness:c,completeness:h}}d(cs,"calcMagnetScore");function Oh(o){try{let e=new Date(String(o||""));return Number.isNaN(e.getTime())?999:Math.max(0,Math.floor((Date.now()-e.getTime())/864e5))}catch{return 999}}d(Oh,"daysSince");function Ui(o,e=!1){let t=String(o||"").toLowerCase(),s=/(?:4k|2160p|1080p|720p)/.exec(t)?.[0]||"",a=e||/(?:-c\b|-u(?:c)?\b|chinese|中字|字幕)/.test(t);return{resolution:s,subtitle:a,recognized:!!s||a,highQuality:s==="4k"||s==="2160p"||a}}d(Ui,"getMagnetQualitySignals");function xc({title:o="",hasHdTag:e=!1,hasSubtitleTag:t=!1,date:s=null,seeders:a=0}={}){let r=Ui(o,t),i=e||r.highQuality,n=cs({title:o,date:s,seeders:a,resolution:e&&!r.resolution?"1080p":r.resolution,hasSubtitle:r.subtitle});return{...r,highQuality:i,score:n,grade:n.total>=70?"高":n.total>=40?"中":"低"}}d(xc,"assessMagnetQuality");function wt(o,e="other"){if(!o||typeof o!="object"||Array.isArray(o))return null;let t=o,s=T(t.carNum);return s?Object.freeze({...t,carNum:s,movieId:typeof t.movieId=="string"&&t.movieId.trim()?t.movieId.trim():null,surface:t.surface||e}):null}d(wt,"normalizeMovieContext");function kc(o,e="other"){let t=wt(o,e);if(!t)throw new TypeError("Movie context requires a valid carNum");return t}d(kc,"createMovieContext");function ia(o){let e=o?.nodeType?o:o?.[0]||null;for(;e;){let s=(typeof globalThis.$=="function"?globalThis.$(e):null)?.data?.("jhsMovieContext")||e.__jhsMovieContext,a=wt(s);if(a)return a;e=e.parentElement||null}return null}d(ia,"readOwnedMovieContext");function zi(o={}){let e=wt(o.explicitContext);if(e)return{context:e,source:"explicit"};let t=wt(o.ownedResolver?.()??ia(o.trigger),"other");if(t)return{context:t,source:t.surface==="fc2-dialog"?"fc2-workspace":"owned-surface"};let s=wt(o.listResolver?.(),"list-item");if(s)return{context:s,source:"list-item"};let a=wt(o.nativeResolver?.(),"native-detail");if(a)return{context:a,source:"native-detail"};let r=wt(o.legacyResolver?.(),"other");return r?(o.logger?.("movie-context source=legacy-fallback",r),{context:r,source:"legacy-fallback"}):{context:null,source:"missing"}}d(zi,"resolveMovieContext");var Fi=class Fi extends I{constructor(){super(...arguments),this.sourceRegistry=new Yt,this.searchEngines=[]}async initializeSources(){let e=new nt,t=this.getRuntimeService("magnet"),s=await e.getBuiltInSources(),a=await e.getMagnetSources(),r=t.getBuiltInSources(),i=[...Ns,...r],n=d(h=>({...i.find(u=>u.id===h)||{},...s.find(u=>u.id===h)||{}}),"configured"),l=r.map((h=>{let u=n(h.id),p=String(u.baseUrl||h.baseUrl).replace(/\/$/,"");return{...h,...u,search:d(async g=>t.searchSource(h.id,g,{baseUrl:p,scope:await this.getRuntimeService("scope")()}),"search"),targetUrl:d(g=>t.getSourceTargetUrl(h.id,g,{baseUrl:p}),"targetUrl")}}));this.sourceRegistry=new Yt([{name:"JavDB 本站",id:"native-javdb",applicable:M,enabled:M,priority:1,search:d(async(h,u=document)=>ci(u?.jquery?u[0]:u,"javdb"),"search"),targetUrl:d(()=>window.location.href,"targetUrl")},{name:"JavBus 本站",id:"native-javbus",applicable:B,enabled:B,priority:2,search:d(async(h,u=document)=>ci(u?.jquery?u[0]:u,"javbus"),"search"),targetUrl:d(()=>window.location.href,"targetUrl")},...l].map((h=>{let u=n(h.id),p=h.applicable??!0;return{...h,...u,enabled:p&&(u.enabled??h.enabled??!0),search:h.search,targetUrl:h.targetUrl}}))),a.filter(h=>h.enabled).forEach(h=>this.sourceRegistry.register({...h,id:`custom:${h.id}`,search:d(u=>this.searchCustomSource(h,u),"search"),targetUrl:d(u=>h.targetUrlTemplate.replaceAll("{keyword}",encodeURIComponent(u)),"targetUrl")}));let c=this.sourceRegistry.getEnabledSources().map((h=>({...h,targetPage:h.targetUrl("{keyword}").replace("%7Bkeyword%7D","{keyword}")})));this.searchEngines=c.length?[{id:"all",name:"全部",priority:0,targetPage:"#",targetUrl:d(()=>"#","targetUrl"),search:d(h=>this.searchAllSources(c,h),"search")},...c]:[]}getName(){return"MagnetHubPlugin"}async initCss(){return``}async handle(){if(!X.includes("collection_codes?movieId"))return;let e=new URLSearchParams(window.location.search),t=e.get("movieId"),s=e.get("carNum"),a=e.get("url"),r=e.get("source"),i=$("section").first().empty();if(!s||!a)return void i.append($('
      ').text("FC2 详情参数不完整"));let n=t&&t!=="search"?t:await this.resolveMovieIdForRecord(s,a),l=["fc2","123av"].includes(r||"")?r:await this.resolveFc2Source({url:a}),c=this.mountFc2Detail(i,{movieId:n,carNum:s,url:a,source:l,mode:"page"});$(window).off("pagehide.jhsFc2Detail").one("pagehide.jhsFc2Detail",(()=>c.destroy()))}openFc2Dialog(e,t,s,{source:a=""}={}){a=["fc2","123av"].includes(a)?a:"";let r=null;return this.getRuntimeService("dialog").open({type:1,title:t,content:'
      ',ui:{size:"workspace",body:"scroll"},area:utils.getDialogArea("workspace"),skin:"movie-detail-layer",scrollbar:!1,shadeClose:!0,success:d((i,n)=>{r=this.mountFc2Detail($(i).find(".jhs-fc2-dialog-host"),{movieId:e,carNum:t,url:s,source:a,layerIndex:n,mode:"dialog"}),utils.setupEscClose(n)},"success"),end:d(()=>r?.destroy(),"end")})}mountFc2Detail(e,t){let s=$(e);s.data("jhsFc2Context")?.destroy?.(),s.empty();let r=Sc(t).appendTo(s),i=xc(r,t);return s.data("jhsFc2Context",i),i.translationGeneration=0,i.screenshotGeneration=0,i.otherSiteGeneration=0,this.initializeWorkspace(i),this.bindFc2FeatureLifecycle(i),i}initializeWorkspace(e){let t=$('
      正在加载影片信息…
      '),s=$('');s.append(Mt()),s.append('','',''),t.find(".jhs-fc2-summary__body").append(s),e.getSlot("summary").append(t);let a=$(''),r=$('
      ');a.on(`click${e.namespace}`,".jhs-fc2-gallery-item",(f=>{let v=$(f.currentTarget).find("img")[0];v&&globalThis.showImageViewer(v,"",{galleryRoot:a[0]})})),e.getSlot("gallery").append(a,r);let i=$('
      '),n=this.createResourceGroup("站内磁力","native-magnets"),l=this.createResourceGroup("第三方站点","other-sites"),c=this.createResourceGroup("更多磁力来源","magnet-hub"),h=$(''),u=null;c.find('[data-jhs-role="magnet-hub"]').append(h,'
      '),i.append(n,l,c),e.getSlot("resources").append(i),s.on(`click${e.namespace}`,'[data-jhs-action="subtitlecat"]',(f=>{let v=this.getRuntimeService("movie").sourceUrls({carNum:e.carNum},["subtitlecat"])[0]?.url;v&&utils.openPage(v,e.carNum,!1,f)}));let p=this.getOptionalDependency("DetailPageButtonPlugin");p?s.on(`click${e.namespace}`,'[data-jhs-action="xunlei"]',(()=>p.searchXunLeiSubtitle(e.carNum))):s.find('[data-jhs-action="xunlei"]').remove();let g=this.getOptionalDependency("MagnetHubPlugin");g||c.remove(),h.on(`click${e.namespace}`,(async()=>{if(!g||!e.isAlive())return;let f=c.find('[data-jhs-role="magnet-hub-content"]');if(h.attr("aria-expanded")==="true")return c.addClass("is-collapsed"),void h.attr("aria-expanded","false").text("展开磁力搜索");u||(u=g.createMagnetHub({movieContext:e.movieContext,root:e.root}));let b=await u;e.isAlive()&&!f.children().length&&f.append(b),e.isAlive()&&(c.removeClass("is-collapsed"),h.attr("aria-expanded","true").text("收起磁力搜索"),f[0]?.scrollIntoView?.({block:"nearest"}))})),this.getDetailStateController().bind({root:e.root,layerIndex:e.layerIndex??null,carNum:e.carNum,activityType:"fc2-state",getRecord:d(()=>({carNum:e.carNum,url:e.url,fc2Source:e.source,names:e.root.find('[data-jhs-role="actress-data"]').text(),publishTime:e.root.find('[data-jhs-role="publish-time"]').text()}),"getRecord")}),e.source==="123av"?this.load123AvDetail(e):this.loadNativeDetail(e);let m=this.getOptionalDependency("FilterTitleKeywordPlugin");m&&Promise.resolve().then((()=>m.bindDetailRoot(e.root,{layerIndex:e.layerIndex??null}))).catch((f=>clog.error("FC2 关键词过滤初始化失败",f))),this.mountFc2OtherSites(e,l,this.getOptionalDependency("OtherSitePlugin")),this.loadFc2Screenshot(e)}bindFc2FeatureLifecycle(e){let t=this.getRuntimeService("settings"),s=d(a=>{let r=a.detail?.names;if(r?.length&&(r.includes("enableLoadScreenShot")&&(t.snapshot().enableLoadScreenShot==="no"?(e.screenshotGeneration=(e.screenshotGeneration||0)+1,this.unmountFc2Screenshot(e)):this.loadFc2Screenshot(e)),r.includes("translateTitle")&&((t.snapshot().translateTitle??E)===E?this.applyFc2Translation(e):(e.translationGeneration=(e.translationGeneration||0)+1,this.revertFc2Translation(e))),r.includes("enableMagnetsFilter")&&e.magnetFilterApply?.((t.snapshot().enableMagnetsFilter??E)===E),r.includes("enableLoadOtherSite"))){let i=e.getSection("resources").find('[data-jhs-role="other-sites"]').closest(".jhs-fc2-resource-group");t.snapshot().enableLoadOtherSite==="no"?(e.otherSiteGeneration=(e.otherSiteGeneration||0)+1,this.unmountFc2OtherSites(e,i)):this.mountFc2OtherSites(e,i,this.getOptionalDependency("OtherSitePlugin"))}},"handler");t.addEventListener("settings.changed",s),e.addObserver({disconnect:d(()=>t.removeEventListener("settings.changed",s),"disconnect")})}loadFc2Screenshot(e){let t=this.getRuntimeService("screenshot"),s=this.getRuntimeService("settings"),a=e.root.find('[data-jhs-role="screenshot"]');if(!t.isEnabled(s.snapshot()))return void a.empty();let r=(e.screenshotGeneration||0)+1;e.screenshotGeneration=r,Promise.resolve().then((()=>this.getRuntimeService("scope")())).then(i=>ta({target:a,carNum:e.carNum.replace("FC2-",""),screenshot:t,settings:s.snapshot(),scope:i,isActive:d(()=>e.isAlive()&&s.snapshot().enableLoadScreenShot!=="no"&&r===e.screenshotGeneration,"isActive"),isDuplicate:d(n=>!!e.galleryUrls?.has(n),"isDuplicate")})).then(i=>{if(!(!e.isAlive()||r!==e.screenshotGeneration)&&s.snapshot().enableLoadScreenShot==="no")return void a.empty()}).catch(i=>{!e.isAlive()||r!==e.screenshotGeneration||(a.empty(),clog.error("FC2 剧照初始化失败",i))})}unmountFc2Screenshot(e){e.screenshotGeneration=(e.screenshotGeneration||0)+1,e.root.find('[data-jhs-role="screenshot"]').empty()}applyFc2Translation(e){let t=this.getRuntimeService("settings");if(!e.isAlive()||(t.snapshot().translateTitle??E)!==E)return;let s=(e.translationGeneration||0)+1;e.translationGeneration=s,Promise.resolve().then((()=>this.getRuntimeService("scope")())).then(a=>ea({root:e.root,carNum:e.carNum,translation:this.getRuntimeService("translation"),scope:a,isActive:d(()=>e.isAlive()&&(t.snapshot().translateTitle??E)===E&&s===e.translationGeneration,"isActive")})).catch((a=>clog.error("FC2 标题翻译失败",a)))}revertFc2Translation(e){e.root.find(".translated-title").remove()}mountFc2OtherSites(e,t,s){if(!s)return void t.remove();let a=this.getRuntimeService("settings"),r=(e.otherSiteGeneration||0)+1;e.otherSiteGeneration=r,t.length&&t.show(),Promise.resolve().then((()=>s.loadOtherSite(e.carNum.replace("FC2-",""),e.carNum,{root:e.root,target:t.find('[data-jhs-role="other-sites"]'),autoDetect:!1,isActive:d(()=>e.isAlive()&&a.snapshot().enableLoadOtherSite!=="no"&&r===e.otherSiteGeneration,"isActive")}))).then(i=>{!e.isAlive()||r!==e.otherSiteGeneration||(i?t.show():t.hide())}).catch(i=>{!e.isAlive()||r!==e.otherSiteGeneration||(t.show(),he(e.root.find('[data-jhs-role="other-sites"]'),"外部站点加载失败"),clog.error("FC2 外部站点加载失败",i))})}unmountFc2OtherSites(e,t){e.otherSiteGeneration=(e.otherSiteGeneration||0)+1,e.root.find("[data-jhs-other-site-box],[data-jhs-other-site-settings]").remove(),t.length&&t.hide()}createResourceGroup(e,t){return $('

      ').find("h3").text(e).end().find("div").attr("data-jhs-role",t).end()}async loadNativeDetail(e){let t=Promise.resolve(e.movieId);this.configureJavDbWantButton(e,t),await Promise.allSettled([this.fetchAndRenderNativeDetail(e),this.fetchAndRenderNativeMagnets(e),this.mountPanels(e,t)]),e.isAlive()&&this.applyFc2Translation(e)}async load123AvDetail(e){let t=this.getOptionalDependency("Fc2By123AvPlugin");if(!t)return void he(e.getSlot("summary"),"123AV 详情功能已禁用");let s=t.resolveMovieId(e.carNum);this.configureJavDbWantButton(e,s),this.mountPanels(e,s),s.then((a=>{if(e.isAlive())return this.fetchAndRenderNativeMagnets(e,a)})).catch((a=>{e.isAlive()&&he(e.root.find('[data-jhs-role="native-magnets"]'),"站内磁力关联失败",(()=>{this.load123AvMagnets(e)})),clog.error("123AV 磁力关联失败",a)})),await t.loadDetail(e,e.url),e.isAlive()&&this.applyFc2Translation(e)}async load123AvMagnets(e){let t=this.getOptionalDependency("Fc2By123AvPlugin");if(!t)throw new Error("123AV 详情功能已禁用");let s=await t.resolveMovieId(e.carNum);return this.fetchAndRenderNativeMagnets(e,s)}async configureJavDbWantButton(e,t){let s=e.root.find('[data-jhs-action="javdb-want"]');try{let a=await t;if(!e.isAlive())return;if(!a)return void s.prop("disabled",!0).text("JavDB 暂无对应作品");try{let r=await yc(a);if(!e.isAlive())return;if(r)return void s.prop("disabled",!0).attr("aria-pressed","true").text("已在 JavDB 想看")}catch(r){clog.warn("读取 JavDB 想看状态失败,保留手动操作",r)}s.prop("disabled",!1).text("JavDB 想看").off(`click${e.namespace}`).on(`click${e.namespace}`,(()=>{this.submitJavDbWant(e,a,s)}))}catch(a){e.isAlive()&&s.prop("disabled",!1).text("JavDB 关联失败,重试").off(`click${e.namespace}`).on(`click${e.namespace}`,(()=>{this.configureJavDbWantButton(e,this.resolveMovieId(e.carNum))})),clog.error("FC2 JavDB 想看关联失败",a)}}async submitJavDbWant(e,t,s){if(!(!e.isAlive()||s.data("jhsBusy")||s.attr("aria-pressed")==="true")){s.data("jhsBusy",!0).attr({"aria-busy":"true","aria-disabled":"true"}).text("正在加入想看…");try{if(await wc(t),!e.isAlive())return;s.attr({"aria-pressed":"true","aria-disabled":"false"}).text("已加入 JavDB 想看"),show.ok("已加入 JavDB 想看")}catch(a){if(!e.isAlive())return;let r=a;if(r?.code==="LOGIN_REQUIRED")return s.attr("aria-disabled","false").text("JavDB 想看"),jc({dialog:this.getRuntimeService("dialog"),account:this.getRuntimeService("account"),credential:this.getRuntimeService("credential"),getScope:this.getRuntimeService("scope"),onSuccess:d(()=>this.submitJavDbWant(e,t,s),"onSuccess")});s.attr("aria-disabled","false").text("JavDB 想看"),show.error(r?.message||"加入 JavDB 想看失败"),clog.error("加入 JavDB 想看失败",a)}finally{e.isAlive()&&s.removeData("jhsBusy").removeAttr("aria-busy")}}}async fetchAndRenderNativeDetail(e){try{let t=await this.getRuntimeService("scope")(),s=await this.getRuntimeService("movie").detail({movieId:e.movieId,carNum:e.carNum,providerId:"javdb"},{scope:t});if(!s)throw new Error("JavDB 影片详情不存在");if(!e.isAlive())return;this.renderSummary(e,s),os(e,s.imageUrls||[],s.coverUrl||null)}catch(t){e.isAlive()&&he(e.root.find('[data-jhs-role="summary-content"]'),"影片信息加载失败",(()=>{this.fetchAndRenderNativeDetail(e)})),clog.error("FC2 详情加载失败",t)}}renderSummary(e,t){let s=e.root.find('[data-jhs-role="summary-content"]').empty(),a=$('

      ');a.find("strong").text(t.title||"无标题"),s.append(a),t.originalTitle&&t.originalTitle!==t.title&&s.append($('
      ').text(t.originalTitle));let r=$('
      ');[`番号:${t.carNum||e.carNum}`,`发行:${t.releaseDate||"未知"}`,`评分:${Number.isFinite(Number(t.score))?t.score:"无"}`,`时长:${Number.isFinite(Number(t.duration))?t.duration+" 分钟":"无"}`].forEach((l=>r.append($("").text(l)))),s.append(r);let i=[],n=$('
      主演:
      ');(t.actors||[]).forEach((l=>{n.append($("").addClass("jhs-fc2-actor").attr({href:`/actors/${encodeURIComponent(l.id)}`,target:"_blank",rel:"noopener noreferrer"}).text(l.name||"未知演员")),l.gender===0&&i.push(l.name)})),t.actors?.length||n.append($("").text("暂无演员信息")),s.append(n,Qs(e,this.getRuntimeService("movie")),$('').text(i.join(" ")),$('').text(t.releaseDate||""))}async fetchAndRenderNativeMagnets(e,t=e.movieId){let s=e.root.find('[data-jhs-role="native-magnets"]');he(s,"正在加载站内磁力…");try{if(!t)return he(s,"JavDB 暂无对应作品");let a=await this.getRuntimeService("scope")(),r=await this.getRuntimeService("magnet").listNative({movieId:t,providerId:"javdb"},{scope:a});if(!e.isAlive())return;if(s.empty(),!r.length)return he(s,"暂无站内磁力");let i=[],n=this.getRuntimeService("magnet");r.forEach((l=>{let c=yl(l.hash);if(!c)return;let h=`magnet:?xt=urn:btih:${c}`,u=n.assess({title:l.title,hasHdTag:l.hasHdTag,hasSubtitleTag:l.hasSubtitleTag,date:l.createdAt,seeders:l.seeders}),p=$('
      ').attr("data-jhs-high-quality",String(u.highQuality)),g=$('
      '),m=$('
      '),f=$('
      ');i.push(u),f.append($("").addClass("jhs-badge").attr("title",`磁力质量评分 ${u.score.total}`).text(`${u.grade} ${u.score.total}`)),l.hasHdTag&&f.append('高清'),l.hasSubtitleTag&&f.append('字幕'),g.append($("").attr("href",h).text(l.title||h),$("
      ").addClass("jhs-fc2-meta").text(`${(Number(l.sizeMb||0)/1024).toFixed(2)} GB · ${Number(l.fileCount)||0} 个文件${l.createdAt?` · ${l.createdAt}`:""}`),f),m.append($('').attr("data-clipboard-text",h),$('').attr({"data-resource":h,"data-jhs-offline-owner":"fc2"})),s.append(p.append(g,m))})),await this.bindNativeMagnetFilter(e,s,i.some((l=>l.highQuality)))}catch(a){e.isAlive()&&he(s,"站内磁力加载失败",(()=>{this.fetchAndRenderNativeMagnets(e,t)})),clog.error("FC2 磁力加载失败",a)}}async bindNativeMagnetFilter(e,t,s){let a=e.getSection("resources"),r=a.find(".jhs-fc2-section__actions");r.find('[data-jhs-action="filter-native-magnets"]').remove();let n=$(''),l=d(u=>{t.find(".jhs-fc2-magnet-item").show(),u&&s&&t.find('.jhs-fc2-magnet-item[data-jhs-high-quality="false"]').hide(),n.attr("aria-pressed",String(u&&s)).text(s?u?"显示全部磁力":"过滤低质量":"暂无可过滤项").prop("disabled",!s)},"apply"),c=this.getRuntimeService("settings"),h=Ve({settings:c,key:"enableMagnetsFilter",fallback:"no",apply:d(u=>l(u===E),"apply"),onError:d(u=>{clog.error("磁力过滤设置保存失败,已恢复",u),show.error("磁力过滤设置保存失败,已恢复原设置")},"onError")});e.magnetFilterApply=l,r.append(n),l((c.snapshot().enableMagnetsFilter??E)===E),n.on(`click${e.namespace}`,(async()=>{let u=n.attr("aria-pressed")!=="true";await h(u?E:"no")}))}async mountPanels(e,t){try{let s=await t;if(!e.isAlive())return;if(!s)return this.clearOwnedPanel(e,"reviews"),this.clearOwnedPanel(e,"related"),he(e.getSlot("reviews"),"JavDB 暂无对应作品"),he(e.getSlot("related"),"JavDB 暂无对应作品");this.clearOwnedPanel(e,"reviews"),this.clearOwnedPanel(e,"related");let a=d(()=>this.getRuntimeService("scope")(),"scope"),r=new Ot({related:this.getRuntimeService("related"),settings:this.getRuntimeService("settings"),scope:a}),i=new Ut({review:this.getRuntimeService("review"),settings:this.getRuntimeService("settings"),storage:this.getRuntimeService("storage"),scope:a});await Promise.allSettled([i.show(s,e.getSlot("reviews"),{ownedSection:e.getSection("reviews"),isActive:e.isAlive,ownCleanup:d(n=>e.addObserver({disconnect:n}),"ownCleanup")}),r.show(e.getSlot("related"),s,{ownedSection:e.getSection("related"),isActive:e.isAlive,ownCleanup:d(n=>e.addObserver({disconnect:n}),"ownCleanup")})])}catch(s){if(!e.isAlive())return;this.clearOwnedPanel(e,"reviews"),this.clearOwnedPanel(e,"related");let a=d(()=>{this.mountPanels(e,this.resolveMovieId(e.carNum))},"retry");he(e.getSlot("reviews"),"评论关联失败",a),he(e.getSlot("related"),"相关清单关联失败",a),clog.error("FC2 JavDB 关联失败",s)}}clearOwnedPanel(e,t){e.getSlot(t).empty(),e.getSection(t).find(".jhs-fc2-section__actions").empty()}async resolveFc2Source(e={}){if(e.fc2Source&&["fc2","123av"].includes(e.fc2Source))return e.fc2Source;try{let t=new URL(e.url||"",window.location.origin);return this.getRuntimeService("movie").matchesProviderUrl("av123",t.href)?"123av":t.origin===window.location.origin?"fc2":""}catch{return""}}createFc2PageUrl(e,t,s,{source:a=""}={}){if(!String(e||"").trim())throw new TypeError("FC2 owned detail requires movieId");let r=new URL("/users/collection_codes",window.location.origin);return r.searchParams.set("movieId",String(e).trim()),r.searchParams.set("carNum",t),r.searchParams.set("url",s),r.searchParams.set("source",a),r.href}async openFc2Page(e,t,s,a={newTab:!0},{source:r=""}={}){r=["fc2","123av"].includes(r)?r:"";let i=String(e||"").trim();if(!i)return void utils.openPage(s,t,!0,a);utils.openPage(this.createFc2PageUrl(i,t,s,{source:r}),t,!0,a)}};d(Mi,"Fc2Plugin");var sa=Mi;var Bi=class Bi extends I{getName(){return"HitShowPlugin"}async handle(){let e=je(window.location);if(e.kind!=="playback-ranking")return;let t=this.getRuntimeService("host").locateListRoot?.();t&&(t.setAttribute("data-jhs-ranking","playback"),t.setAttribute("data-jhs-ranking-period",e.period),t.setAttribute("data-jhs-ranking-filter",e.filter))}};d(Bi,"HitShowPlugin");var aa=Bi;var Oi=class Oi extends I{getName(){return"JavTrailersPlugin"}constructor(){super(),this.hasBand=!1}async handle(){let e=window.location.href;if(!e.includes("handle=1"))return;if($("h1:contains('Page not found')").length){clog.log("番号无法匹配, 跳搜索");let a=e.split("?")[0].split("video/")[1].toLowerCase().replace("00","-");return void(window.location.href="/search/"+encodeURIComponent(a)+window.location.search)}let t=$(".videos-list .video-link").toArray();if(t.length){let a=e.split("?")[0].split("search/")[1].toLowerCase(),r=t.find((i=>$(i).find(".vid-title").text().toLowerCase().includes(a)));if(r)return void(window.location.href=$(r).attr("href")+window.location.search)}let s=await this.getRuntimeService("scope")();this.handlePlayJavTrailers(s),this.bindPlaybackControls(s)}bindPlaybackControls(e){let t=$("#videoPlayerContainer"),s=d(()=>this.handlePlayJavTrailers(e),"replay");t.off("click.jhsJavTrailers").on("click.jhsJavTrailers",s),e.addCleanup((()=>t.off("click.jhsJavTrailers",s))),e.listen(window,"message",(()=>{let a=document.getElementById("vjs_video_3_html5_api");a&&(a.currentTime+=5)}))}handlePlayJavTrailers(e){if(this.hasBand||e.signal.aborted)return;let t=utils.loopDetector((()=>$("#vjs_video_3_html5_api").length!==0),(()=>{e.signal.aborted||e.ownTimeout(setTimeout((()=>{if(e.signal.aborted)return;this.hasBand=!0;let a=document.getElementById("vjs_video_3_html5_api");a&&(clog.debug(a),de(a,{context:"JavTrailers 预览"}),a.currentTime=5,e.listen(a,"timeupdate",(function(){a.currentTime>=14&&a.currentTime<16&&(a.currentTime+=2)})),$("#vjs_video_3_html5_api").css({position:"fixed",width:"100vw",height:"100vh",objectFit:"cover",zIndex:String(J.debug)}),$(".vjs-control-bar").css({position:"fixed",bottom:"20px",zIndex:String(J.debug)}))}),100))}),20,1e4,!0,e),s=utils.loopDetector((()=>$("#vjs_video_3 canvas").length>0),(()=>{e.signal.aborted||$("#vjs_video_3 canvas").length!==0&&$("#vjs_video_3 canvas").css({position:"fixed",width:"100vw",height:"100vh",objectFit:"cover",top:"0",right:"0",zIndex:String(J.debug-1)})}),20,1e4,!0,e);e.addCleanup(t),e.addCleanup(s)}};d(Oi,"JavTrailersPlugin");var ra=Oi;var ia=Object.freeze({magnet:216e5,screenshot:6048e5,screenshotNegative:432e5,match115:36e5,externalDetail:864e5}),Ui=class Ui extends Error{constructor(e,t,s,a={}){super(s,{cause:a.cause}),this.name="ProviderError",this.provider=e,this.code=t,this.status=a.status||0,this.url=a.url||"",this.retryable=!!a.retryable}};d(Ui,"ProviderError");var we=Ui;function cs(o){let e=0,t=Number(o.seeders)||0,s=t>=50?35:t>=10?25:t>=1?15:3;e+=s;let a=String(o.title||"").toLowerCase(),r=String(o.resolution||"").toLowerCase(),i=/4k|2160p/.test(r)||/4k|2160p/.test(a)?25:/1080p/.test(r)||/1080p/.test(a)?20:/720p/.test(r)||/720p/.test(a)?15:5;e+=i;let n=o.hasSubtitle||/-c\b|-uc\b|chinese|中字|字幕/.test(a)?20:0;e+=n;let l=Uh(o.date),c=l<=7?15:l<=30?12:l<=90?8:3;e+=c;let h=/sample|预告|trailer/.test(a)?-15:0;return e+=h,{total:Math.max(0,Math.min(100,e)),seeders:s,resolution:i,subtitle:n,freshness:c,completeness:h}}d(cs,"calcMagnetScore");function Uh(o){try{let e=new Date(String(o||""));return Number.isNaN(e.getTime())?999:Math.max(0,Math.floor((Date.now()-e.getTime())/864e5))}catch{return 999}}d(Uh,"daysSince");function zi(o,e=!1){let t=String(o||"").toLowerCase(),s=/(?:4k|2160p|1080p|720p)/.exec(t)?.[0]||"",a=e||/(?:-c\b|-u(?:c)?\b|chinese|中字|字幕)/.test(t);return{resolution:s,subtitle:a,recognized:!!s||a,highQuality:s==="4k"||s==="2160p"||a}}d(zi,"getMagnetQualitySignals");function kc({title:o="",hasHdTag:e=!1,hasSubtitleTag:t=!1,date:s=null,seeders:a=0}={}){let r=zi(o,t),i=e||r.highQuality,n=cs({title:o,date:s,seeders:a,resolution:e&&!r.resolution?"1080p":r.resolution,hasSubtitle:r.subtitle});return{...r,highQuality:i,score:n,grade:n.total>=70?"高":n.total>=40?"中":"低"}}d(kc,"assessMagnetQuality");function wt(o,e="other"){if(!o||typeof o!="object"||Array.isArray(o))return null;let t=o,s=C(t.carNum);return s?Object.freeze({...t,carNum:s,movieId:typeof t.movieId=="string"&&t.movieId.trim()?t.movieId.trim():null,surface:t.surface||e}):null}d(wt,"normalizeMovieContext");function Cc(o,e="other"){let t=wt(o,e);if(!t)throw new TypeError("Movie context requires a valid carNum");return t}d(Cc,"createMovieContext");function na(o){let e=o?.nodeType?o:o?.[0]||null;for(;e;){let s=(typeof globalThis.$=="function"?globalThis.$(e):null)?.data?.("jhsMovieContext")||e.__jhsMovieContext,a=wt(s);if(a)return a;e=e.parentElement||null}return null}d(na,"readOwnedMovieContext");function Fi(o={}){let e=wt(o.explicitContext);if(e)return{context:e,source:"explicit"};let t=wt(o.ownedResolver?.()??na(o.trigger),"other");if(t)return{context:t,source:t.surface==="fc2-dialog"?"fc2-workspace":"owned-surface"};let s=wt(o.listResolver?.(),"list-item");if(s)return{context:s,source:"list-item"};let a=wt(o.nativeResolver?.(),"native-detail");if(a)return{context:a,source:"native-detail"};let r=wt(o.legacyResolver?.(),"other");return r?(o.logger?.("movie-context source=legacy-fallback",r),{context:r,source:"legacy-fallback"}):{context:null,source:"missing"}}d(Fi,"resolveMovieContext");var Vi=class Vi extends I{constructor(){super(...arguments),this.sourceRegistry=new Yt,this.searchEngines=[]}async initializeSources(){let e=new ot,t=this.getRuntimeService("magnet"),s=await e.getBuiltInSources(),a=await e.getMagnetSources(),r=t.getBuiltInSources(),i=[...Ls,...r],n=d(h=>({...i.find(u=>u.id===h)||{},...s.find(u=>u.id===h)||{}}),"configured"),l=r.map((h=>{let u=n(h.id),p=String(u.baseUrl||h.baseUrl).replace(/\/$/,"");return{...h,...u,search:d(async g=>t.searchSource(h.id,g,{baseUrl:p,scope:await this.getRuntimeService("scope")()}),"search"),targetUrl:d(g=>t.getSourceTargetUrl(h.id,g,{baseUrl:p}),"targetUrl")}}));this.sourceRegistry=new Yt([{name:"JavDB 本站",id:"native-javdb",applicable:M,enabled:M,priority:1,search:d(async(h,u=document)=>di(u?.jquery?u[0]:u,"javdb"),"search"),targetUrl:d(()=>window.location.href,"targetUrl")},{name:"JavBus 本站",id:"native-javbus",applicable:B,enabled:B,priority:2,search:d(async(h,u=document)=>di(u?.jquery?u[0]:u,"javbus"),"search"),targetUrl:d(()=>window.location.href,"targetUrl")},...l].map((h=>{let u=n(h.id),p=h.applicable??!0;return{...h,...u,enabled:p&&(u.enabled??h.enabled??!0),search:h.search,targetUrl:h.targetUrl}}))),a.filter(h=>h.enabled).forEach(h=>this.sourceRegistry.register({...h,id:`custom:${h.id}`,search:d(u=>this.searchCustomSource(h,u),"search"),targetUrl:d(u=>h.targetUrlTemplate.replaceAll("{keyword}",encodeURIComponent(u)),"targetUrl")}));let c=this.sourceRegistry.getEnabledSources().map((h=>({...h,targetPage:h.targetUrl("{keyword}").replace("%7Bkeyword%7D","{keyword}")})));this.searchEngines=c.length?[{id:"all",name:"全部",priority:0,targetPage:"#",targetUrl:d(()=>"#","targetUrl"),search:d(h=>this.searchAllSources(c,h),"search")},...c]:[]}getName(){return"MagnetHubPlugin"}async initCss(){return``}async createMagnetHub(e,t={}){await this.initializeSources();let s=typeof e=="string"?null:e,a=typeof e=="string"?kc({carNum:e}):s?.movieContext;if(!a?.carNum)return $('
      ').append($('
      ').text("无法确定影片身份,未加载磁力"));let r=a.carNum.replace("FC2-",""),i=t.root??s?.root?$(t.root??s?.root):$(document),n=[...this.searchEngines],l=this.getRuntimeService("storage"),c=$('
      '),h=$('
      '),u="jhs_magnetHub_selectedEngine",p=l.getLocal(u);c.data("jhsMovieContext",a);let g=$('
      '),m=n.find((w=>w.id===p))||n[0];if(!m)return c.append($('
      ').text("暂无可用磁力来源,请前往设置启用来源"));let f=m;n.forEach((w=>g.append($('').attr("data-engine",w.id).text(w.name).toggleClass("active",w.id===f.id))));let v=$('原网页').attr("href",(f.targetPage||"#").replace("{keyword}",encodeURIComponent(r))).toggle(f.id!=="all");h.append(g),h.append(v),g.find(".magnet-tab.active").attr({"aria-selected":"true",tabindex:"0"}),c.append(h);let b=$('
      ');return c.append(b),c.on("click",".magnet-tab",(w=>{let S=$(w.target).data("engine");f=n.find((j=>j.id===S))||f,f&&(c.find('[data-jhs-role="magnet-target"]').attr("href",(f.targetPage||"#").replace("{keyword}",encodeURIComponent(r))).toggle(f.id!=="all"),l.setLocal(u,S),c.find(".magnet-tab").removeClass("active").attr({"aria-selected":"false",tabindex:"-1"}),$(w.target).addClass("active").attr({"aria-selected":"true",tabindex:"0"}),this.searchEngine(b,f,r,i))})),c.on("keydown",".magnet-tab",(w=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(w.key))return;w.preventDefault();let S=c.find(".magnet-tab"),j=S.index(w.currentTarget),x=w.key==="Home"?0:w.key==="End"?S.length-1:w.key==="ArrowRight"?(j+1)%S.length:(j-1+S.length)%S.length;S.eq(x).trigger("click").trigger("focus")})),this.searchEngine(b,f,r,i),c}async searchEngine(e,t,s,a=$(document)){e.html(`
      正在从 ${C(t.name)} 搜索 "${C(s)}"...
      `);let r=`${t.name}_${s}`;if(t.search)try{return void this.displayResults(e,await this.applyRuntimeRules(Es(await t.search(s,a))),t.name)}catch(i){return clog.error(`磁力源 ${t.name} 请求失败`,i),void e.html(`
      ${C(t.name)} 请求失败
      `)}if(t.parseHtml)try{let i=t.url.replace("{keyword}",encodeURIComponent(s)),n=await this.requestSource(t.id,i,{ttlMs:216e5}),l=t.parseHtml.call(this,n,s);return void this.displayResults(e,l,t.name)}catch(i){return void e.html(`
      解析 ${C(t.name)} 结果失败: ${C(i instanceof Error?i.message:String(i))}
      `)}t.parseJson&&await t.parseJson.call(this,e,t,s,r)}async searchCustomSources(e){let s=JSON.parse(await storageManager.getSetting("customMagnetSources","[]")).filter(r=>r.enabled).map(bt),a=await Te(s,4,(async r=>{let i=r.searchUrlTemplate.replaceAll("{keyword}",encodeURIComponent(e));try{let n=await this.requestSource(r.id,i,{ttlMs:ra.magnet,custom:!0,responseType:r.parserType==="json"?"json":"text"}),l=r.parserType==="json"&&typeof n=="string"?JSON.parse(n):n;return di(r,l,r.id)}catch(n){let l=n;return clog.error(`自定义磁力源 ${r.name} 失败`,new we(r.id,l.code||"HTTP_ERROR",l.message||String(n),{cause:n,url:i,status:l.status,retryable:l.retryable})),[]}}));return Es(a.flat())}async searchCustomSource(e,t){let s=e.searchUrlTemplate.replaceAll("{keyword}",encodeURIComponent(t)),a=await this.requestSource(e.id,s,{ttlMs:ra.magnet,custom:!0,responseType:e.parserType==="json"?"json":"text"});return di(e,e.parserType==="json"&&typeof a=="string"?JSON.parse(a):a,e.id)}async searchAllSources(e,t){let s=await Te(e,3,(async a=>{try{return await a.search(t)}catch(r){return clog.warn(`磁力源 ${a.name} 聚合失败`,r),[]}}));return Es(s.flat())}async requestSource(e,t,s={}){let a=await this.getRuntimeService("scope")();return(await this.getRuntimeService("http").request({providerId:`magnet:${e}`,method:s.method||"GET",url:t,body:s.body,headers:s.headers,responseType:s.responseType||"text",cacheScope:s.method&&s.method!=="GET"?"none":"public",ttlMs:s.ttlMs??ra.magnet,urlPolicy:s.custom?{trustClass:"custom-public"}:{trustClass:"builtin-public",hosts:s.hosts||[new URL(t).hostname]}},a)).data}async applyRuntimeRules(e){let t=new nt,[s,a]=await Promise.all([t.getMagnetTagRules(),t.getMagnetFilterRules()]);return e.map((r=>Cl(r,s,a.filter((i=>(i.target||"title")==="title")),a.filter((i=>i.target==="file"))))).filter((r=>!r.hidden))}async displayResults(e,t,s){function a(r){let i=r.text();r.addClass("copied").text("已复制"),setTimeout((()=>{r.removeClass("copied").text(i)}),2e3)}d(a,"a"),e.empty(),t.length!==0?(t.forEach((r=>{let i=this.calcMagnetScore(r);r._score={...i,total:Math.max(0,Math.min(100,i.total+(r.customTagWeight||0)+(r.filterPenalty||0)))}})),t.sort(((r,i)=>i._score.total-r._score.total)),t.forEach((r=>{let i=r._score?r._score.total:0,n=i>=80?"高":i>=60?"中":"低",l=r._score?`做种:${r._score.seeders}/35 分辨率:${r._score.resolution}/25 字幕:${r._score.subtitle}/20 新鲜度:${r._score.freshness}/15 完整性:${r._score.completeness}/5`:"",c=C(r.title),h=C(r.magnet),u=C(String(r.size||"未知")),p=C(String(r.date||"未知")),g=$(` + `}async createMagnetHub(e,t={}){await this.initializeSources();let s=typeof e=="string"?null:e,a=typeof e=="string"?Cc({carNum:e}):s?.movieContext;if(!a?.carNum)return $('
      ').append($('
      ').text("无法确定影片身份,未加载磁力"));let r=a.carNum.replace("FC2-",""),i=t.root??s?.root?$(t.root??s?.root):$(document),n=[...this.searchEngines],l=this.getRuntimeService("storage"),c=$('
      '),h=$('
      '),u="jhs_magnetHub_selectedEngine",p=l.getLocal(u);c.data("jhsMovieContext",a);let g=$('
      '),m=n.find((w=>w.id===p))||n[0];if(!m)return c.append($('
      ').text("暂无可用磁力来源,请前往设置启用来源"));let f=m;n.forEach((w=>g.append($('').attr("data-engine",w.id).text(w.name).toggleClass("active",w.id===f.id))));let v=$('原网页').attr("href",(f.targetPage||"#").replace("{keyword}",encodeURIComponent(r))).toggle(f.id!=="all");h.append(g),h.append(v),g.find(".magnet-tab.active").attr({"aria-selected":"true",tabindex:"0"}),c.append(h);let b=$('
      ');return c.append(b),c.on("click",".magnet-tab",(w=>{let S=$(w.target).data("engine");f=n.find((j=>j.id===S))||f,f&&(c.find('[data-jhs-role="magnet-target"]').attr("href",(f.targetPage||"#").replace("{keyword}",encodeURIComponent(r))).toggle(f.id!=="all"),l.setLocal(u,S),c.find(".magnet-tab").removeClass("active").attr({"aria-selected":"false",tabindex:"-1"}),$(w.target).addClass("active").attr({"aria-selected":"true",tabindex:"0"}),this.searchEngine(b,f,r,i))})),c.on("keydown",".magnet-tab",(w=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(w.key))return;w.preventDefault();let S=c.find(".magnet-tab"),j=S.index(w.currentTarget),k=w.key==="Home"?0:w.key==="End"?S.length-1:w.key==="ArrowRight"?(j+1)%S.length:(j-1+S.length)%S.length;S.eq(k).trigger("click").trigger("focus")})),this.searchEngine(b,f,r,i),c}async searchEngine(e,t,s,a=$(document)){e.html(`
      正在从 ${T(t.name)} 搜索 "${T(s)}"...
      `);let r=`${t.name}_${s}`;if(t.search)try{return void this.displayResults(e,await this.applyRuntimeRules(Ds(await t.search(s,a))),t.name)}catch(i){return clog.error(`磁力源 ${t.name} 请求失败`,i),void e.html(`
      ${T(t.name)} 请求失败
      `)}if(t.parseHtml)try{let i=t.url.replace("{keyword}",encodeURIComponent(s)),n=await this.requestSource(t.id,i,{ttlMs:216e5}),l=t.parseHtml.call(this,n,s);return void this.displayResults(e,l,t.name)}catch(i){return void e.html(`
      解析 ${T(t.name)} 结果失败: ${T(i instanceof Error?i.message:String(i))}
      `)}t.parseJson&&await t.parseJson.call(this,e,t,s,r)}async searchCustomSources(e){let s=JSON.parse(await storageManager.getSetting("customMagnetSources","[]")).filter(r=>r.enabled).map(bt),a=await Ae(s,4,(async r=>{let i=r.searchUrlTemplate.replaceAll("{keyword}",encodeURIComponent(e));try{let n=await this.requestSource(r.id,i,{ttlMs:ia.magnet,custom:!0,responseType:r.parserType==="json"?"json":"text"}),l=r.parserType==="json"&&typeof n=="string"?JSON.parse(n):n;return hi(r,l,r.id)}catch(n){let l=n;return clog.error(`自定义磁力源 ${r.name} 失败`,new we(r.id,l.code||"HTTP_ERROR",l.message||String(n),{cause:n,url:i,status:l.status,retryable:l.retryable})),[]}}));return Ds(a.flat())}async searchCustomSource(e,t){let s=e.searchUrlTemplate.replaceAll("{keyword}",encodeURIComponent(t)),a=await this.requestSource(e.id,s,{ttlMs:ia.magnet,custom:!0,responseType:e.parserType==="json"?"json":"text"});return hi(e,e.parserType==="json"&&typeof a=="string"?JSON.parse(a):a,e.id)}async searchAllSources(e,t){let s=await Ae(e,3,(async a=>{try{return await a.search(t)}catch(r){return clog.warn(`磁力源 ${a.name} 聚合失败`,r),[]}}));return Ds(s.flat())}async requestSource(e,t,s={}){let a=await this.getRuntimeService("scope")();return(await this.getRuntimeService("http").request({providerId:`magnet:${e}`,method:s.method||"GET",url:t,body:s.body,headers:s.headers,responseType:s.responseType||"text",cacheScope:s.method&&s.method!=="GET"?"none":"public",ttlMs:s.ttlMs??ia.magnet,urlPolicy:s.custom?{trustClass:"custom-public"}:{trustClass:"builtin-public",hosts:s.hosts||[new URL(t).hostname]}},a)).data}async applyRuntimeRules(e){let t=new ot,[s,a]=await Promise.all([t.getMagnetTagRules(),t.getMagnetFilterRules()]);return e.map((r=>_l(r,s,a.filter((i=>(i.target||"title")==="title")),a.filter((i=>i.target==="file"))))).filter((r=>!r.hidden))}async displayResults(e,t,s){function a(r){let i=r.text();r.addClass("copied").text("已复制"),setTimeout((()=>{r.removeClass("copied").text(i)}),2e3)}d(a,"a"),e.empty(),t.length!==0?(t.forEach((r=>{let i=this.calcMagnetScore(r);r._score={...i,total:Math.max(0,Math.min(100,i.total+(r.customTagWeight||0)+(r.filterPenalty||0)))}})),t.sort(((r,i)=>i._score.total-r._score.total)),t.forEach((r=>{let i=r._score?r._score.total:0,n=i>=80?"高":i>=60?"中":"低",l=r._score?`做种:${r._score.seeders}/35 分辨率:${r._score.resolution}/25 字幕:${r._score.subtitle}/20 新鲜度:${r._score.freshness}/15 完整性:${r._score.completeness}/5`:"",c=T(r.title),h=T(r.magnet),u=T(String(r.size||"未知")),p=T(String(r.date||"未知")),g=$(`
      ${n} ${i} @@ -3289,7 +3284,7 @@ ${i}\r
      - `);r.tags?.length&&g.find(".magnet-info").after($("
      ").addClass("magnet-tags").append(r.tags.map((f=>$("").addClass("jhs-badge").text(f)))));let m=g.find(".magnet-copy");g.find(".copy-btn").removeClass("magnet-hub-btn").addClass("jhs-btn--secondary"),m.append(``),g.appendTo(e)})),e.on("click",".copy-btn",(async r=>{let i=$(r.currentTarget),n=i.data("magnet");await utils.copyToClipboard("磁力链接",n)&&a(i)}))):e.append('
      没有找到相关结果
      ')}calcMagnetScore(e){return cs(e)}};d(Fi,"MagnetHubPlugin");var na=Fi;var Vi=class Vi extends I{constructor(){super(...arguments),this.mountGeneration=0,this._mountGenerations=new WeakMap,this.siteConfigs=[{id:"javTrailersBtn"},{id:"123AvBtn",providerId:"av123"},{id:"jableBtn"},{id:"avgleBtn"},{id:"missAvBtn"},{id:"supJavBtn"},{id:"javDbBtn",condition:d(()=>B,"condition")},{id:"javBusBtn",condition:d(e=>!!(M&&e&&!e.includes("FC2")),"condition")},{id:"fanzaBtn",providerId:"dmm",noHandle:!0,condition:d(e=>!!(e&&!e.includes("FC2")),"condition")}]}getName(){return"OtherSitePlugin"}async getSiteConfigs(){let e=await this.getSettingCache(),t=this.getRuntimeService("movie").externalSites(e);return this.siteConfigs.map(s=>({...t.find((a=>a.id===s.id))||{},...s}))}async initCss(){return` + `);r.tags?.length&&g.find(".magnet-info").after($("
      ").addClass("magnet-tags").append(r.tags.map((f=>$("").addClass("jhs-badge").text(f)))));let m=g.find(".magnet-copy");g.find(".copy-btn").removeClass("magnet-hub-btn").addClass("jhs-btn--secondary"),m.append(``),g.appendTo(e)})),e.on("click",".copy-btn",(async r=>{let i=$(r.currentTarget),n=i.data("magnet");await utils.copyToClipboard("磁力链接",n)&&a(i)}))):e.append('
      没有找到相关结果
      ')}calcMagnetScore(e){return cs(e)}};d(Vi,"MagnetHubPlugin");var oa=Vi;var qi=class qi extends I{constructor(){super(...arguments),this.mountGeneration=0,this._mountGenerations=new WeakMap,this.siteConfigs=[{id:"javTrailersBtn"},{id:"123AvBtn",providerId:"av123"},{id:"jableBtn"},{id:"avgleBtn"},{id:"missAvBtn"},{id:"supJavBtn"},{id:"javDbBtn",condition:d(()=>B,"condition")},{id:"javBusBtn",condition:d(e=>!!(M&&e&&!e.includes("FC2")),"condition")},{id:"fanzaBtn",providerId:"dmm",noHandle:!0,condition:d(e=>!!(e&&!e.includes("FC2")),"condition")}]}getName(){return"OtherSitePlugin"}async getSiteConfigs(){let e=await this.getSettingCache(),t=this.getRuntimeService("movie").externalSites(e);return this.siteConfigs.map(s=>({...t.find((a=>a.id===s.id))||{},...s}))}async initCss(){return` `}async handle(){let e=this.getRuntimeService("settings"),t=await this.getRuntimeService("scope")(),s=d(a=>{a.detail?.names?.includes("enableLoadOtherSite")&&(e.snapshot().enableLoadOtherSite==="no"?this.unmount():this.mount().catch((i=>clog.error("外部站点重新挂载失败",i))))},"onSettingsChanged");e.addEventListener("settings.changed",s),t.addCleanup((()=>e.removeEventListener("settings.changed",s))),await this.mount()}async mount(){isDetailPage&&this.getRuntimeService("settings").snapshot().enableLoadOtherSite!=="no"&&await this.loadOtherSite(null,null,{autoDetect:!1})}unmount(){this.mountGeneration++,this._mountGenerations.set(document,(this._mountGenerations.get(document)||0)+1),$("[data-jhs-other-site-box],[data-jhs-other-site-settings]").remove()}async loadOtherSite(e,t,s={}){let a=this.getRuntimeService("settings");if(a.snapshot().enableLoadOtherSite==="no")return;let r=s.root?.[0]||null,i=r?(this._mountGenerations.get(r)||0)+1:++this.mountGeneration;r&&this._mountGenerations.set(r,i);let n=d(()=>(r?i===this._mountGenerations.get(r):i===this.mountGeneration)&&(typeof s.isActive=="function"?s.isActive():!0)&&a.snapshot().enableLoadOtherSite!=="no","isActive"),l=s.root?$(s.root):$(document),c=s.target?$(s.target):$(this.getRuntimeService("host").locateDetailSlots().summary);if(!c.length||!n())return;l.find("#otherSiteBox,#settingsArea,[data-jhs-other-site-box],[data-jhs-other-site-settings]").remove(),e=T(e)||this.getPageInfo().carNum;let h=this.getEnabledSites(),u=(await this.getSiteConfigs()).map((v=>({...v,sourceCarNum:t})));if(!n())return;let p={root:l,target:c,configs:u,carNum:e,isActive:n},g=$('
      '),m=g.find(".jhs-site-list"),f=$('
      ');if(u.forEach((v=>{if(v.condition&&v.condition(v.sourceCarNum)===!1)return;let b=$('').attr("data-jhs-site-id",v.id).toggleClass("jhs-is-hidden",!h.includes(v.id));b.find("span").text(v.id.replace("Btn","")),m.append(b)})),m.append('',''),c.append(g,f),p.box=g,p.settings=f,!e)return g.find(".site-btn").removeAttr("href").attr({"aria-disabled":"true",title:"番号不可用"}),g.find('[data-jhs-role="detect-sites"]').prop("disabled",!0),this.renderSettingsArea(p),this.setupEventListeners(p),void clog.warn("跳过第三方站点解析:番号不可用");if(g.find('[data-jhs-site-id="javTrailersBtn"]').on("click",(v=>{v.preventDefault();let b=$(v.currentTarget).attr("href"),w=v.ctrlKey||v.metaKey?b:b+"?handle=1";utils.openPage(w,e,!1,v)})),await Te(u,4,(async v=>{v.condition&&v.condition(v.sourceCarNum)===!1||await this.prepareSiteLink(e,v,p)})),!!n())return this.renderSettingsArea(p),this.setupEventListeners(p),g.find('[data-jhs-role="detect-sites"]').off("click").on("click",(v=>{v.preventDefault(),this.detectOtherSites(e,p)})),s.autoDetect&&await this.detectOtherSites(e,p),g}async prepareSiteLink(e,t,s={root:$(document),configs:[],isActive:d(()=>!0,"isActive")}){let a=s.root.find(`[data-jhs-site-id="${t.id}"],#${t.id}`).first();if(!(e=T(e)))return a.removeAttr("href").attr({"aria-disabled":"true",title:"番号不可用"}),void this.setSiteState(a,"idle");if(t.providerId){let r=this.getRuntimeService("movie").searchUrl(t.providerId,{carNum:e});return void(r?(a.attr("href",r),a.attr("title","点击前往外部搜索页"),this.setSiteState(a,"idle")):(a.attr("title","外部站点地址不可用"),this.setSiteState(a,"domain-error")))}try{s.isActive?.()!==!1&&t.searchUrl&&(a.attr("href",t.searchUrl(e)),a.attr("title","点击前往外部搜索页;点击检测按钮后才自动检测"),this.setSiteState(a,"idle"))}catch{s.isActive?.()!==!1&&(a.attr("title","外部站点地址未配置或不可用"),this.setSiteState(a,"domain-error"))}}async detectOtherSites(e,t={root:$(document),configs:this.siteConfigs,isActive:d(()=>!0,"isActive")}){let s=t.root.find('[data-jhs-role="detect-sites"],#detectOtherSiteBtn').first(),a=s.text();return(e=T(e))?(s.text("检测中").prop("disabled",!0).addClass("is-checking"),await Te(t.configs,4,(async r=>{r.condition&&r.condition(r.sourceCarNum)===!1||await this.handleSite(e,r,t)})),t.isActive?.()!==!1&&s.text(a).prop("disabled",!1).removeClass("is-checking")):(s.prop("disabled",!0),void clog.warn("跳过第三方站点检测:番号不可用"))}setSiteState(e,t){e.removeClass("is-checking is-available is-unavailable is-domain-error"),t!=="idle"&&e.addClass(`is-${t}`)}async handleSite(e,t,s={root:$(document),configs:[],isActive:d(()=>!0,"isActive")}){let a=s.root.find(`[data-jhs-site-id="${t.id}"],#${t.id}`).first();if(a.removeAttr("href").find(".site-tag").remove(),this.setSiteState(a,"checking"),t.noHandle&&t.noHandle===!0){a.attr("href",this.getRuntimeService("movie").searchUrl(t.providerId,{carNum:e})||"");let r="jhs_other_site_dmm",i=this.getRuntimeService("storage").getLocal(r),n=null;try{let l=i?JSON.parse(i):{};n=l&&typeof l=="object"?l[e]:null}catch{n=null}n?(a.attr("href",n.url),n.type==="multiple"&&a.append('多结果'),this.setSiteState(a,"available")):this.setSiteState(a,"idle")}else if(t.providerId)try{let r=await this.getRuntimeService("scope")(),i=await this.getRuntimeService("movie").resolve({carNum:e,providerId:t.providerId},{scope:r});if(s.isActive?.()===!1)return;let n=this.getRuntimeService("movie").searchUrl(t.providerId,{carNum:e});a.attr("href",i?.url||n||""),this.setSiteState(a,i?.url?"available":"unavailable"),i?.url||a.attr("title","未查询到, 点击前往搜索页")}catch{s.isActive?.()!==!1&&(a.attr("title","请求失败。"),this.setSiteState(a,"unavailable"),clog.warn(`检测第三方资源失败, ${t.id.replace("Btn","")}`))}else try{if(a.attr("href"))return void this.setSiteState(a,"idle");if(utils.isHidden(a))return;let r="jhs_other_site",i=this.getRuntimeService("storage"),n=i.getLocal(r),l=n?JSON.parse(n):{},c=e+"_"+t.id.replace("Btn",""),h=l[c],u=Date.now();if(h&&h.time&&u-h.time<864e5)return a.attr("href",h.url),h.type==="multiple"&&a.append('多结果'),void this.setSiteState(a,"available");let p=await this.getRuntimeService("scope")(),g=await this.getRuntimeService("movie").searchExternalSite(t.id,e,{settings:await this.getSettingCache(),scope:p}),m=g.searchUrl;if(a.attr("href",m),s.isActive?.()===!1)return;let f=g.matches,v="",b=null;if(f.length===1){let w=f[0];a.attr("href",w),this.setSiteState(a,"available"),b={type:"single",url:w,time:u}}else f.length>1?(a.attr("href",m),v+='多结果',this.setSiteState(a,"available"),b={type:"multiple",url:m,time:u}):(a.attr("href",m),a.attr("title","未查询到, 点击前往搜索页"),this.setSiteState(a,"unavailable"));if(b){let w=i.getLocal(r),S=w?JSON.parse(w):{};S[c]=b,i.setLocal(r,JSON.stringify(S))}v&&a.append(v)}catch(r){let i=String(r),n=t.id.replace("Btn",""),l=r?.code;l==="CIRCUIT_OPEN"?(a.attr("title",i),this.setSiteState(a,"domain-error"),clog.warn(`检测第三方资源跳过, ${n} 已熔断`)):l==="CF_BLOCKED"?(a.attr("title","请求失败:Cloudflare 安全检查。"),this.setSiteState(a,"domain-error"),clog.warn(`检测第三方资源失败, ${n} 需Cloudflare安全检查`)):l==="INVALID_URL"?(a.attr("title","域名失效"),this.setSiteState(a,"domain-error"),clog.warn(`检测第三方资源失败, ${n} 域名或重定向无效`)):l==="NOT_FOUND"?(a.attr("title","未查询到, 点击前往搜索页"),this.setSiteState(a,"unavailable")):(clog.error(r),a.attr("title","请求失败。"),this.setSiteState(a,"unavailable"),clog.warn(`检测第三方资源失败, ${n}`))}}async getSettingCache(){return this.getRuntimeService("settings").snapshot()}async getMissAvUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="missAvBtn")?.baseUrl||""}async getjableUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="jableBtn")?.baseUrl||""}async getAvgleUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="avgleBtn")?.baseUrl||""}async getJavTrailersUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="javTrailersBtn")?.baseUrl||""}async getAv123Url(){return this.getRuntimeService("movie").providerOrigin("av123")||""}async getJavDbUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="javDbBtn")?.baseUrl||""}async getJavBusUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="javBusBtn")?.baseUrl||""}async getSupJavUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="supJavBtn")?.baseUrl||""}getEnabledSites(){let e=this.siteConfigs.map((t=>t.id));try{let t=this.getRuntimeService("storage").getLocal("jhs_enabled_sites");if(!t)return e;let s=JSON.parse(t);return Array.isArray(s)?s.filter((a=>e.includes(a))):e}catch(t){return clog.warn("外部站点配置损坏,已回退默认值",t),e}}saveEnabledSites(e){this.getRuntimeService("storage").setLocal("jhs_enabled_sites",JSON.stringify(e))}renderSettingsArea(e={root:$(document),configs:this.siteConfigs}){let t=this.getEnabledSites(),s=e.root.find('[data-jhs-role="site-checkboxes"],#siteCheckboxes').first().empty();e.configs.forEach((a=>{let r=$('').attr("data-site-id",a.id).prop("checked",t.includes(a.id));s.append($('').append(r,$("").text(a.id.replace("Btn",""))))}))}setupEventListeners(e={root:$(document),configs:this.siteConfigs,carNum:null}){let t=e.root.find("[data-jhs-other-site-settings],#settingsArea").first();e.root.find('[data-jhs-role="site-settings"],#settingSiteBtn').off("click.jhsOtherSite").on("click.jhsOtherSite",(()=>{t.toggleClass("jhs-is-hidden")})),t.off("change.jhsOtherSite").on("change.jhsOtherSite",'input[type="checkbox"]',(async s=>{let a=$(s.currentTarget).attr("data-site-id");try{if(s.currentTarget.checked){e.root.find(`[data-jhs-site-id="${a}"],#${a}`).removeClass("jhs-is-hidden");let r=e.carNum||this.getPageInfo().carNum,i=e.configs.find((n=>n.id===a));i&&await this.prepareSiteLink(r,i,e)}else e.root.find(`[data-jhs-site-id="${a}"],#${a}`).addClass("jhs-is-hidden");this.saveEnabledSites(t.find('input[type="checkbox"]:checked').map(((r,i)=>$(i).attr("data-site-id"))).get())}catch(r){clog.warn(`外部站点 ${a||"unknown"} 状态更新失败`,r)}}))}};d(Vi,"OtherSitePlugin");var oa=Vi;var Hi=class Hi extends I{getName(){return"RelatedPlugin"}async handle(){if(!window.isDetailPage||!M)return;let e=new URL(window.location.href).pathname.split("/").filter(Boolean).pop();e&&await this.showRelated(this.getHostedSlot("related"),e)}getHostedSlot(e){let t=this.getRuntimeService("host").locateDetailSlots()[e];return t?$(t):$()}async showRelated(e,t,s={}){return new Bt({related:this.getRuntimeService("related"),settings:this.getRuntimeService("settings"),scope:d(()=>this.getRuntimeService("scope")(),"scope")}).show(e?.length?e:this.getHostedSlot("related"),t,s)}};d(Hi,"RelatedPlugin");var la=Hi;var qi=class qi extends I{getName(){return"ReviewPlugin"}async handle(){if(window.isDetailPage){if(M){let e=this.parseMovieId(window.location.href);await this.showReview(e,this.getHostedSlot("reviews"))}if(B){let e=this.getPageInfo().carNum;if(!e)return void clog.warn("跳过 JavBus 评论解析:番号不可用");let t=await this.getRuntimeService("scope")(),s=this.getRuntimeService("settings"),a=!1,r=d(async()=>{if(!(a||t?.disposed||s.snapshot().enableLoadReview==="no")){a=!0;try{let i=await this.getRuntimeService("movie").resolve({carNum:e},{scope:t});i?.movieId&&!t?.disposed&&s.snapshot().enableLoadReview!=="no"&&await this.showReview(i.movieId,this.getHostedSlot("reviews"))}finally{a=!1}}},"mount");t?.listen?.(s,"settings.changed",i=>{i.detail?.names?.includes("enableLoadReview")&&r().catch(n=>clog.error("加载评论失败",n))}),await r()}}}getHostedSlot(e){let t=this.getRuntimeService("host").locateDetailSlots()[e];return t?$(t):$()}async showReview(e,t,s={}){return new Ot({review:this.getRuntimeService("review"),settings:this.getRuntimeService("settings"),storage:this.getRuntimeService("storage"),scope:d(()=>this.getRuntimeService("scope")(),"scope")}).show(e,t?.length?t:this.getHostedSlot("reviews"),s)}};d(qi,"ReviewPlugin");var ca=qi;function Uh(o){return[...o.querySelectorAll(".tags .tag")].some(e=>/中字磁[链鏈]/u.test(e.textContent||""))}d(Uh,"hasChineseSubtitleMagnet");var ha=class ha extends I{getName(){return"TOP250Plugin"}async initCss(){return""}async handle(){if(je(window.location).kind!=="top250-ranking")return;let e=this.getRuntimeService("host"),t=e.locateListRoot?.(),s=e.getTop250FilterContainer?.();if(!t||!s||s.querySelector(".jhs-top250-subtitle"))return;let a=document.createElement("div");a.className="jhs-top250-subtitle",a.setAttribute("role","group"),a.setAttribute("aria-label","TOP250 已加载条目筛选");for(let[i,n]of[["all","已加载条目:全部"],["with","已加载条目:含中字磁链"],["without","已加载条目:无中字磁链"]]){let l=document.createElement("button");l.type="button",l.className="jhs-btn jhs-btn--secondary",l.dataset.jhsSubtitle=i,l.textContent=n,a.append(l)}e.mountTop250SubtitleControls(a);let r=new URLSearchParams(window.location.search).get("jhs_subtitle");this.applySubtitleFilter(["with","without"].includes(r||"")?r:"all",a),a.addEventListener("click",i=>{let l=i.target?.closest("button[data-jhs-subtitle]")?.getAttribute("data-jhs-subtitle");if(!["all","with","without"].includes(l||""))return;let c=new URL(window.location.href);l==="all"?c.searchParams.delete("jhs_subtitle"):c.searchParams.set("jhs_subtitle",l),window.history.replaceState(window.history.state,"",c.href),this.applySubtitleFilter(l,a)})}applySubtitleFilter(e,t){let s=this.getRuntimeService("host");for(let a of s.locateTop250SubtitleCards()){let r=Uh(a);a.classList.toggle("jhs-top250-subtitle-hidden",e==="with"?!r:e==="without"&&r)}t.querySelectorAll("button[data-jhs-subtitle]").forEach(a=>{let r=a.getAttribute("data-jhs-subtitle")===e;a.setAttribute("aria-pressed",String(r)),a.classList.toggle("active",r)}),s.syncTop250SubtitleLinks?.(e)}};d(ha,"Top250Plugin"),ct(ha,"legacyPluginId","TOP250Plugin");var da=ha;var Ji=class Ji extends I{getName(){return"FavoriteActressesPlugin"}getStartupMode(){return"idle"}bindImmediateEvents(){this.bindEvent()}async handle(){await this.highlightActress(),this.replaceActressAvatar()}async highlightActress(){if(!isDetailPage||await storageManager.getSetting("enableFavoriteActresses",R)!==R)return;let e=await storageManager.getFavoriteActressList();if(!e||e.length===0)return;let t=new Set;e.forEach((s=>{s.starId&&t.add(String(s.starId).trim())})),t.size!==0&&$(".female").prev().each(((s,a)=>{let r=$(a),i=r.attr("href"),n=null;if(i){let c=(i.endsWith("/")?i.slice(0,-1):i).split("/"),h=c[c.length-1];h&&(n=h.trim())}let l=!1;n&&(l=t.has(n)),l&&(r.addClass("highlighted"),r.attr("title","高亮已收藏演员, 可在设置-基础配置中关闭"))}))}async removeActorFromStorage(e){await storageManager.removeFavoriteActress(e)&&(clog.log("移除演员成功"),document.dispatchEvent(new CustomEvent("actress-state-changed",{detail:{starId:String(e)}})))}bindEvent(){let e=/\/actors\/(\w+)\/(collect|uncollect)/;$(document).on("confirm:complete",'a[href*="/actors/"][href*="/uncollect"]',(async t=>{let[s]=t.detail;if(!s)return;let a=$(t.currentTarget).attr("href").match(e),r=a?a[1]:null;r&&await this.removeActorFromStorage(r)})),$("#button-collect-actor").click((async t=>{let s=$("#button-collect-actor").attr("href").match(e),a=s?s[1]:null,r=[],i=$(".actor-section-name");i.length&&i.text().trim().split(",").forEach((u=>{r.push(u.trim())}));let n=$(".section-meta:not(:contains('影片'))");if(n.length&&n.text().trim().split(",").forEach((u=>{r.push(u.trim())})),!r.length)return void clog.error("获取演员名称失败");let l=r[0];if(!a)return void clog.error("无法获取演员ID进行收藏操作。");let c=($(".avatar").first().css("background-image")||"").replace(/^url\(["']?|["']?\)$/g,""),h={starId:a,name:l,allName:r,avatar:c};await storageManager.addFavoriteActressList([h])===1?(clog.log(`收藏演员成功: ${l} (ID: ${a})`),document.dispatchEvent(new CustomEvent("actress-state-changed",{detail:{starId:String(a)}}))):clog.log(`收藏演员失败: ${l} (ID: ${a})`)})),$("#button-uncollect-actor").click((async t=>{let s=$("#button-uncollect-actor").attr("href").match(e),a=s?s[1]:null;a?await this.removeActorFromStorage(a):clog.error("无法获取演员ID进行取消收藏操作。")}))}async replaceActressAvatar(){let e=this.getActressId();if(!e)return;let t=(await storageManager.getFavoriteActressList()).find((s=>s.starId===e));if(t&&t.avatar){let s=`url('${t.avatar}')`,a=$(".avatar").first();if(a.length===0&&($(".section-columns").prepend('
      '),a=$(".avatar").first()),a.length===0)return;a.css("background-image").trim().toLowerCase()!==s.trim().toLowerCase()&&(a.css("background-image",s),a.css("background-size","cover"),a.css("background-position","top center"),a.css("background-repeat","no-repeat"))}}};d(Ji,"FavoriteActressesPlugin");var ua=Ji;var Wi=class Wi extends I{getName(){return"BusImgPlugin"}handle(){}async getVisibleImageItems(e,t){let s=[],a=document.querySelectorAll(e);for(let r of a)if(!utils.isHidden(r)){let i=r.querySelector(t);if(!(i instanceof HTMLImageElement))continue;i.style.removeProperty("height");let n=i.offsetHeight;n>0&&s.push({element:r,imgElement:i,height:n})}return s}async logImageHeightsByRow(e={}){let t=e.vertical??e.enableVerticalModel??await storageManager.getSetting("enableVerticalModel",ne),s=e.columns??e.containerColumns??await storageManager.getSetting("containerColumns",5);if(t===R)return;let a=this.getSelector().itemSelector,r=Number(s)||5,i=await this.getVisibleImageItems(a,"img");if(i.length===0)return;let n=[];for(let l=0;l{let h=l.map((m=>m.height));if(h.length<2)return;let u=Math.min(...h),p=Math.max(...h),g=0;p-u>50&&(g=u,l.forEach((m=>{if(m.height!==g){let f=`${g}px`;m.imgElement.style.setProperty("height",f,"important")}})))}))}};d(Wi,"BusImgPlugin");var pa=Wi;var Ut=d((o,e)=>{if(!o||o.length===0)return null;let t=new Set(o);if(e&&t.has(e))return e;let s=rt.map((a=>a.quality)).reverse();for(let a of s)if(t.has(a))return a;return o[0]||null},"Z"),Ki="jhs_dmm_video",zh=30*864e5,Cc=500;function Gi(o){if(!o)return{};try{let e=JSON.parse(o);return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch{return{}}}d(Gi,"parseJsonMap");function Qi(o){let e=Date.now();for(let s of Object.keys(o)){let a=o[s];(!a||a.time&&e-a.time>zh)&&delete o[s]}let t=Object.keys(o);if(t.length>Cc){t.sort(((s,a)=>(o[s].time||0)-(o[a].time||0)));for(let s of t.slice(0,t.length-Cc))delete o[s]}return o}d(Qi,"pruneDmmCache");function Pe(o){return o?.enablePreviewVideo!=="no"}d(Pe,"isPreviewEnabled");function ds(o){return o?.enableLoadPreviewVideo!=="no"}d(ds,"isDmmEnabled");function _c(o){return Pe(o)}d(_c,"canUsePreview");function zt(o){return Pe(o)&&ds(o)}d(zt,"canUseDmmPreview");function ga(o){return zt(o)}d(ga,"canUseCardPreview");var Xi=class Xi{constructor(e,t,s,a){this.carNum=e||"",this.storage=t,this.movie=s,this.scope=a,this.lastError=null}_checkCache(){let e=Qi(Gi(this.storage.getLocal(Ki)));return e[this.carNum]?(clog.debug("缓存中存在预览视频信息",e[this.carNum]),e[this.carNum]):null}_updateCache(e){let t=Qi(Gi(this.storage.getLocal(Ki)));t[this.carNum]={...e,time:Date.now()},clog.debug("成功解析出预览视频并已缓存:",e),this.storage.setLocal(Ki,JSON.stringify(t))}async _fetchRemote(){let e=await this.movie.preview("dmm",{carNum:this.carNum},{scope:this.scope}),t=$("#fanzaBtn");if(!e.sources)return clog.warn("所有关键词尝试均未找到匹配的Content ID, 解析Dmm视频失败"),t.attr("href",e.searchUrl).attr("title","未查询到, 点击前往搜索页").css("backgroundColor","var(--jhs-status-filter)"),null;t.attr("href",e.pageUrl).css("backgroundColor","var(--jhs-status-down)"),e.matchType==="multiple"&&t.append('多结果');let s="jhs_other_site_dmm",a=Qi(Gi(this.storage.getLocal(s)));return a[this.carNum]={type:e.matchType,url:e.pageUrl,time:Date.now()},this.storage.setLocal(s,JSON.stringify(a)),e.sources}async fetchVideo(){let e=T(this.carNum);if(!e)return clog.warn("跳过 DMM 解析:番号不可用"),null;this.carNum=e;let t=this._checkCache();if(t)return t;try{let s=this.carNum.toLowerCase();if(s.startsWith("heyzo")||/^(n\d+|\d+(-\d+)*)$/.test(s)||/^n\d+$/.test(s))return clog.debug("无码番号类型,取消 DMM 解析"),null;if(this.carNum.includes("VR-"))return clog.debug("VR 类型,取消 DMM 解析"),null;let a=await this._fetchRemote();return a?(this._updateCache(a),a):null}catch(s){let a=s;this.lastError=s instanceof we?s:new we("dmm",a?.code||"PARSE_ERROR",a?.message||String(s),{cause:s,retryable:a?.retryable===!0}),clog.error("DMM API 搜索失败:",this.lastError);let r=$("#fanzaBtn");return r.attr("href",this.movie.searchUrl("dmm",{carNum:this.carNum})),r.attr("title","未查询到, 点击前往搜索页"),r.css("backgroundColor","var(--jhs-status-filter)"),null}}};d(Xi,"DmmPreviewParser");var Yi=Xi;async function Zi(o,e,t,s){let a=new Yi(o,e,t,s);return{sources:await a.fetchVideo(),error:a.lastError}}d(Zi,"fetchDmmPreview");async function ma(o,e,t,s,a){return ds(a)?Zi(o,e,t,s):{sources:null,error:null}}d(ma,"fetchDmmPreviewIfEnabled");var en=class en extends I{constructor(){super(...arguments),this._busPreviewGeneration=0}getName(){return"BusPreviewVideoPlugin"}async initCss(){return` + `}async handle(){let e=this.getRuntimeService("settings"),t=await this.getRuntimeService("scope")(),s=d(a=>{a.detail?.names?.includes("enableLoadOtherSite")&&(e.snapshot().enableLoadOtherSite==="no"?this.unmount():this.mount().catch((i=>clog.error("外部站点重新挂载失败",i))))},"onSettingsChanged");e.addEventListener("settings.changed",s),t.addCleanup((()=>e.removeEventListener("settings.changed",s))),await this.mount()}async mount(){isDetailPage&&this.getRuntimeService("settings").snapshot().enableLoadOtherSite!=="no"&&await this.loadOtherSite(null,null,{autoDetect:!1})}unmount(){this.mountGeneration++,this._mountGenerations.set(document,(this._mountGenerations.get(document)||0)+1),$("[data-jhs-other-site-box],[data-jhs-other-site-settings]").remove()}async loadOtherSite(e,t,s={}){let a=this.getRuntimeService("settings");if(a.snapshot().enableLoadOtherSite==="no")return;let r=s.root?.[0]||null,i=r?(this._mountGenerations.get(r)||0)+1:++this.mountGeneration;r&&this._mountGenerations.set(r,i);let n=d(()=>(r?i===this._mountGenerations.get(r):i===this.mountGeneration)&&(typeof s.isActive=="function"?s.isActive():!0)&&a.snapshot().enableLoadOtherSite!=="no","isActive"),l=s.root?$(s.root):$(document),c=s.target?$(s.target):$(this.getRuntimeService("host").locateDetailSlots().summary);if(!c.length||!n())return;l.find("#otherSiteBox,#settingsArea,[data-jhs-other-site-box],[data-jhs-other-site-settings]").remove(),e=C(e)||this.getPageInfo().carNum;let h=this.getEnabledSites(),u=(await this.getSiteConfigs()).map((v=>({...v,sourceCarNum:t})));if(!n())return;let p={root:l,target:c,configs:u,carNum:e,isActive:n},g=$('
      '),m=g.find(".jhs-site-list"),f=$('
      ');if(u.forEach((v=>{if(v.condition&&v.condition(v.sourceCarNum)===!1)return;let b=$('').attr("data-jhs-site-id",v.id).toggleClass("jhs-is-hidden",!h.includes(v.id));b.find("span").text(v.id.replace("Btn","")),m.append(b)})),m.append('',''),c.append(g,f),p.box=g,p.settings=f,!e)return g.find(".site-btn").removeAttr("href").attr({"aria-disabled":"true",title:"番号不可用"}),g.find('[data-jhs-role="detect-sites"]').prop("disabled",!0),this.renderSettingsArea(p),this.setupEventListeners(p),void clog.warn("跳过第三方站点解析:番号不可用");if(g.find('[data-jhs-site-id="javTrailersBtn"]').on("click",(v=>{v.preventDefault();let b=$(v.currentTarget).attr("href"),w=v.ctrlKey||v.metaKey?b:b+"?handle=1";utils.openPage(w,e,!1,v)})),await Ae(u,4,(async v=>{v.condition&&v.condition(v.sourceCarNum)===!1||await this.prepareSiteLink(e,v,p)})),!!n())return this.renderSettingsArea(p),this.setupEventListeners(p),g.find('[data-jhs-role="detect-sites"]').off("click").on("click",(v=>{v.preventDefault(),this.detectOtherSites(e,p)})),s.autoDetect&&await this.detectOtherSites(e,p),g}async prepareSiteLink(e,t,s={root:$(document),configs:[],isActive:d(()=>!0,"isActive")}){let a=s.root.find(`[data-jhs-site-id="${t.id}"],#${t.id}`).first();if(!(e=C(e)))return a.removeAttr("href").attr({"aria-disabled":"true",title:"番号不可用"}),void this.setSiteState(a,"idle");if(t.providerId){let r=this.getRuntimeService("movie").searchUrl(t.providerId,{carNum:e});return void(r?(a.attr("href",r),a.attr("title","点击前往外部搜索页"),this.setSiteState(a,"idle")):(a.attr("title","外部站点地址不可用"),this.setSiteState(a,"domain-error")))}try{s.isActive?.()!==!1&&t.searchUrl&&(a.attr("href",t.searchUrl(e)),a.attr("title","点击前往外部搜索页;点击检测按钮后才自动检测"),this.setSiteState(a,"idle"))}catch{s.isActive?.()!==!1&&(a.attr("title","外部站点地址未配置或不可用"),this.setSiteState(a,"domain-error"))}}async detectOtherSites(e,t={root:$(document),configs:this.siteConfigs,isActive:d(()=>!0,"isActive")}){let s=t.root.find('[data-jhs-role="detect-sites"],#detectOtherSiteBtn').first(),a=s.text();return(e=C(e))?(s.text("检测中").prop("disabled",!0).addClass("is-checking"),await Ae(t.configs,4,(async r=>{r.condition&&r.condition(r.sourceCarNum)===!1||await this.handleSite(e,r,t)})),t.isActive?.()!==!1&&s.text(a).prop("disabled",!1).removeClass("is-checking")):(s.prop("disabled",!0),void clog.warn("跳过第三方站点检测:番号不可用"))}setSiteState(e,t){e.removeClass("is-checking is-available is-unavailable is-domain-error"),t!=="idle"&&e.addClass(`is-${t}`)}async handleSite(e,t,s={root:$(document),configs:[],isActive:d(()=>!0,"isActive")}){let a=s.root.find(`[data-jhs-site-id="${t.id}"],#${t.id}`).first();if(a.removeAttr("href").find(".site-tag").remove(),this.setSiteState(a,"checking"),t.noHandle&&t.noHandle===!0){a.attr("href",this.getRuntimeService("movie").searchUrl(t.providerId,{carNum:e})||"");let r="jhs_other_site_dmm",i=this.getRuntimeService("storage").getLocal(r),n=null;try{let l=i?JSON.parse(i):{};n=l&&typeof l=="object"?l[e]:null}catch{n=null}n?(a.attr("href",n.url),n.type==="multiple"&&a.append('多结果'),this.setSiteState(a,"available")):this.setSiteState(a,"idle")}else if(t.providerId)try{let r=await this.getRuntimeService("scope")(),i=await this.getRuntimeService("movie").resolve({carNum:e,providerId:t.providerId},{scope:r});if(s.isActive?.()===!1)return;let n=this.getRuntimeService("movie").searchUrl(t.providerId,{carNum:e});a.attr("href",i?.url||n||""),this.setSiteState(a,i?.url?"available":"unavailable"),i?.url||a.attr("title","未查询到, 点击前往搜索页")}catch{s.isActive?.()!==!1&&(a.attr("title","请求失败。"),this.setSiteState(a,"unavailable"),clog.warn(`检测第三方资源失败, ${t.id.replace("Btn","")}`))}else try{if(a.attr("href"))return void this.setSiteState(a,"idle");if(utils.isHidden(a))return;let r="jhs_other_site",i=this.getRuntimeService("storage"),n=i.getLocal(r),l=n?JSON.parse(n):{},c=e+"_"+t.id.replace("Btn",""),h=l[c],u=Date.now();if(h&&h.time&&u-h.time<864e5)return a.attr("href",h.url),h.type==="multiple"&&a.append('多结果'),void this.setSiteState(a,"available");let p=await this.getRuntimeService("scope")(),g=await this.getRuntimeService("movie").searchExternalSite(t.id,e,{settings:await this.getSettingCache(),scope:p}),m=g.searchUrl;if(a.attr("href",m),s.isActive?.()===!1)return;let f=g.matches,v="",b=null;if(f.length===1){let w=f[0];a.attr("href",w),this.setSiteState(a,"available"),b={type:"single",url:w,time:u}}else f.length>1?(a.attr("href",m),v+='多结果',this.setSiteState(a,"available"),b={type:"multiple",url:m,time:u}):(a.attr("href",m),a.attr("title","未查询到, 点击前往搜索页"),this.setSiteState(a,"unavailable"));if(b){let w=i.getLocal(r),S=w?JSON.parse(w):{};S[c]=b,i.setLocal(r,JSON.stringify(S))}v&&a.append(v)}catch(r){let i=String(r),n=t.id.replace("Btn",""),l=r?.code;l==="CIRCUIT_OPEN"?(a.attr("title",i),this.setSiteState(a,"domain-error"),clog.warn(`检测第三方资源跳过, ${n} 已熔断`)):l==="CF_BLOCKED"?(a.attr("title","请求失败:Cloudflare 安全检查。"),this.setSiteState(a,"domain-error"),clog.warn(`检测第三方资源失败, ${n} 需Cloudflare安全检查`)):l==="INVALID_URL"?(a.attr("title","域名失效"),this.setSiteState(a,"domain-error"),clog.warn(`检测第三方资源失败, ${n} 域名或重定向无效`)):l==="NOT_FOUND"?(a.attr("title","未查询到, 点击前往搜索页"),this.setSiteState(a,"unavailable")):(clog.error(r),a.attr("title","请求失败。"),this.setSiteState(a,"unavailable"),clog.warn(`检测第三方资源失败, ${n}`))}}async getSettingCache(){return this.getRuntimeService("settings").snapshot()}async getMissAvUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="missAvBtn")?.baseUrl||""}async getjableUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="jableBtn")?.baseUrl||""}async getAvgleUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="avgleBtn")?.baseUrl||""}async getJavTrailersUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="javTrailersBtn")?.baseUrl||""}async getAv123Url(){return this.getRuntimeService("movie").providerOrigin("av123")||""}async getJavDbUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="javDbBtn")?.baseUrl||""}async getJavBusUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="javBusBtn")?.baseUrl||""}async getSupJavUrl(){return(await this.getSiteConfigs()).find(e=>e.id==="supJavBtn")?.baseUrl||""}getEnabledSites(){let e=this.siteConfigs.map((t=>t.id));try{let t=this.getRuntimeService("storage").getLocal("jhs_enabled_sites");if(!t)return e;let s=JSON.parse(t);return Array.isArray(s)?s.filter((a=>e.includes(a))):e}catch(t){return clog.warn("外部站点配置损坏,已回退默认值",t),e}}saveEnabledSites(e){this.getRuntimeService("storage").setLocal("jhs_enabled_sites",JSON.stringify(e))}renderSettingsArea(e={root:$(document),configs:this.siteConfigs}){let t=this.getEnabledSites(),s=e.root.find('[data-jhs-role="site-checkboxes"],#siteCheckboxes').first().empty();e.configs.forEach((a=>{let r=$('').attr("data-site-id",a.id).prop("checked",t.includes(a.id));s.append($('').append(r,$("").text(a.id.replace("Btn",""))))}))}setupEventListeners(e={root:$(document),configs:this.siteConfigs,carNum:null}){let t=e.root.find("[data-jhs-other-site-settings],#settingsArea").first();e.root.find('[data-jhs-role="site-settings"],#settingSiteBtn').off("click.jhsOtherSite").on("click.jhsOtherSite",(()=>{t.toggleClass("jhs-is-hidden")})),t.off("change.jhsOtherSite").on("change.jhsOtherSite",'input[type="checkbox"]',(async s=>{let a=$(s.currentTarget).attr("data-site-id");try{if(s.currentTarget.checked){e.root.find(`[data-jhs-site-id="${a}"],#${a}`).removeClass("jhs-is-hidden");let r=e.carNum||this.getPageInfo().carNum,i=e.configs.find((n=>n.id===a));i&&await this.prepareSiteLink(r,i,e)}else e.root.find(`[data-jhs-site-id="${a}"],#${a}`).addClass("jhs-is-hidden");this.saveEnabledSites(t.find('input[type="checkbox"]:checked').map(((r,i)=>$(i).attr("data-site-id"))).get())}catch(r){clog.warn(`外部站点 ${a||"unknown"} 状态更新失败`,r)}}))}};d(qi,"OtherSitePlugin");var la=qi;var Hi=class Hi extends I{getName(){return"RelatedPlugin"}async handle(){if(!window.isDetailPage||!M)return;let e=new URL(window.location.href).pathname.split("/").filter(Boolean).pop();e&&await this.showRelated(this.getHostedSlot("related"),e)}getHostedSlot(e){let t=this.getRuntimeService("host").locateDetailSlots()[e];return t?$(t):$()}async showRelated(e,t,s={}){return new Ot({related:this.getRuntimeService("related"),settings:this.getRuntimeService("settings"),scope:d(()=>this.getRuntimeService("scope")(),"scope")}).show(e?.length?e:this.getHostedSlot("related"),t,s)}};d(Hi,"RelatedPlugin");var ca=Hi;var Wi=class Wi extends I{getName(){return"ReviewPlugin"}async handle(){if(window.isDetailPage){if(M){let e=this.parseMovieId(window.location.href);await this.showReview(e,this.getHostedSlot("reviews"))}if(B){let e=this.getPageInfo().carNum;if(!e)return void clog.warn("跳过 JavBus 评论解析:番号不可用");let t=await this.getRuntimeService("scope")(),s=this.getRuntimeService("settings"),a=!1,r=d(async()=>{if(!(a||t?.disposed||s.snapshot().enableLoadReview==="no")){a=!0;try{let i=await this.getRuntimeService("movie").resolve({carNum:e},{scope:t});i?.movieId&&!t?.disposed&&s.snapshot().enableLoadReview!=="no"&&await this.showReview(i.movieId,this.getHostedSlot("reviews"))}finally{a=!1}}},"mount");t?.listen?.(s,"settings.changed",i=>{i.detail?.names?.includes("enableLoadReview")&&r().catch(n=>clog.error("加载评论失败",n))}),await r()}}}getHostedSlot(e){let t=this.getRuntimeService("host").locateDetailSlots()[e];return t?$(t):$()}async showReview(e,t,s={}){return new Ut({review:this.getRuntimeService("review"),settings:this.getRuntimeService("settings"),storage:this.getRuntimeService("storage"),scope:d(()=>this.getRuntimeService("scope")(),"scope")}).show(e,t?.length?t:this.getHostedSlot("reviews"),s)}};d(Wi,"ReviewPlugin");var da=Wi;function zh(o){return[...o.querySelectorAll(".tags .tag")].some(e=>/中字磁[链鏈]/u.test(e.textContent||""))}d(zh,"hasChineseSubtitleMagnet");var ua=class ua extends I{getName(){return"TOP250Plugin"}async initCss(){return""}async handle(){if(je(window.location).kind!=="top250-ranking")return;let e=this.getRuntimeService("host"),t=e.locateListRoot?.(),s=e.getTop250FilterContainer?.();if(!t||!s||s.querySelector(".jhs-top250-subtitle"))return;let a=document.createElement("div");a.className="jhs-top250-subtitle",a.setAttribute("role","group"),a.setAttribute("aria-label","TOP250 已加载条目筛选");for(let[i,n]of[["all","已加载条目:全部"],["with","已加载条目:含中字磁链"],["without","已加载条目:无中字磁链"]]){let l=document.createElement("button");l.type="button",l.className="jhs-btn jhs-btn--secondary",l.dataset.jhsSubtitle=i,l.textContent=n,a.append(l)}e.mountTop250SubtitleControls(a);let r=new URLSearchParams(window.location.search).get("jhs_subtitle");this.applySubtitleFilter(["with","without"].includes(r||"")?r:"all",a),a.addEventListener("click",i=>{let l=i.target?.closest("button[data-jhs-subtitle]")?.getAttribute("data-jhs-subtitle");if(!["all","with","without"].includes(l||""))return;let c=new URL(window.location.href);l==="all"?c.searchParams.delete("jhs_subtitle"):c.searchParams.set("jhs_subtitle",l),window.history.replaceState(window.history.state,"",c.href),this.applySubtitleFilter(l,a)})}applySubtitleFilter(e,t){let s=this.getRuntimeService("host");for(let a of s.locateTop250SubtitleCards()){let r=zh(a);a.classList.toggle("jhs-top250-subtitle-hidden",e==="with"?!r:e==="without"&&r)}t.querySelectorAll("button[data-jhs-subtitle]").forEach(a=>{let r=a.getAttribute("data-jhs-subtitle")===e;a.setAttribute("aria-pressed",String(r)),a.classList.toggle("active",r)}),s.syncTop250SubtitleLinks?.(e)}};d(ua,"Top250Plugin"),dt(ua,"legacyPluginId","TOP250Plugin");var ha=ua;var Ji=class Ji extends I{getName(){return"FavoriteActressesPlugin"}getStartupMode(){return"idle"}bindImmediateEvents(){this.bindEvent()}async handle(){await this.highlightActress(),this.replaceActressAvatar()}async highlightActress(){if(!isDetailPage||await storageManager.getSetting("enableFavoriteActresses",E)!==E)return;let e=await storageManager.getFavoriteActressList();if(!e||e.length===0)return;let t=new Set;e.forEach((s=>{s.starId&&t.add(String(s.starId).trim())})),t.size!==0&&$(".female").prev().each(((s,a)=>{let r=$(a),i=r.attr("href"),n=null;if(i){let c=(i.endsWith("/")?i.slice(0,-1):i).split("/"),h=c[c.length-1];h&&(n=h.trim())}let l=!1;n&&(l=t.has(n)),l&&(r.addClass("highlighted"),r.attr("title","高亮已收藏演员, 可在设置-基础配置中关闭"))}))}async removeActorFromStorage(e){await storageManager.removeFavoriteActress(e)&&(clog.log("移除演员成功"),document.dispatchEvent(new CustomEvent("actress-state-changed",{detail:{starId:String(e)}})))}bindEvent(){let e=/\/actors\/(\w+)\/(collect|uncollect)/;$(document).on("confirm:complete",'a[href*="/actors/"][href*="/uncollect"]',(async t=>{let[s]=t.detail;if(!s)return;let a=$(t.currentTarget).attr("href").match(e),r=a?a[1]:null;r&&await this.removeActorFromStorage(r)})),$("#button-collect-actor").click((async t=>{let s=$("#button-collect-actor").attr("href").match(e),a=s?s[1]:null,r=[],i=$(".actor-section-name");i.length&&i.text().trim().split(",").forEach((u=>{r.push(u.trim())}));let n=$(".section-meta:not(:contains('影片'))");if(n.length&&n.text().trim().split(",").forEach((u=>{r.push(u.trim())})),!r.length)return void clog.error("获取演员名称失败");let l=r[0];if(!a)return void clog.error("无法获取演员ID进行收藏操作。");let c=($(".avatar").first().css("background-image")||"").replace(/^url\(["']?|["']?\)$/g,""),h={starId:a,name:l,allName:r,avatar:c};await storageManager.addFavoriteActressList([h])===1?(clog.log(`收藏演员成功: ${l} (ID: ${a})`),document.dispatchEvent(new CustomEvent("actress-state-changed",{detail:{starId:String(a)}}))):clog.log(`收藏演员失败: ${l} (ID: ${a})`)})),$("#button-uncollect-actor").click((async t=>{let s=$("#button-uncollect-actor").attr("href").match(e),a=s?s[1]:null;a?await this.removeActorFromStorage(a):clog.error("无法获取演员ID进行取消收藏操作。")}))}async replaceActressAvatar(){let e=this.getActressId();if(!e)return;let t=(await storageManager.getFavoriteActressList()).find((s=>s.starId===e));if(t&&t.avatar){let s=`url('${t.avatar}')`,a=$(".avatar").first();if(a.length===0&&($(".section-columns").prepend('
      '),a=$(".avatar").first()),a.length===0)return;a.css("background-image").trim().toLowerCase()!==s.trim().toLowerCase()&&(a.css("background-image",s),a.css("background-size","cover"),a.css("background-position","top center"),a.css("background-repeat","no-repeat"))}}};d(Ji,"FavoriteActressesPlugin");var pa=Ji;var Ki=class Ki extends I{getName(){return"BusImgPlugin"}handle(){}async getVisibleImageItems(e,t){let s=[],a=document.querySelectorAll(e);for(let r of a)if(!utils.isHidden(r)){let i=r.querySelector(t);if(!(i instanceof HTMLImageElement))continue;i.style.removeProperty("height");let n=i.offsetHeight;n>0&&s.push({element:r,imgElement:i,height:n})}return s}async logImageHeightsByRow(e={}){let t=e.vertical??e.enableVerticalModel??await storageManager.getSetting("enableVerticalModel",ne),s=e.columns??e.containerColumns??await storageManager.getSetting("containerColumns",5);if(t===E)return;let a=this.getSelector().itemSelector,r=Number(s)||5,i=await this.getVisibleImageItems(a,"img");if(i.length===0)return;let n=[];for(let l=0;l{let h=l.map((m=>m.height));if(h.length<2)return;let u=Math.min(...h),p=Math.max(...h),g=0;p-u>50&&(g=u,l.forEach((m=>{if(m.height!==g){let f=`${g}px`;m.imgElement.style.setProperty("height",f,"important")}})))}))}};d(Ki,"BusImgPlugin");var ga=Ki;var zt=d((o,e)=>{if(!o||o.length===0)return null;let t=new Set(o);if(e&&t.has(e))return e;let s=rt.map((a=>a.quality)).reverse();for(let a of s)if(t.has(a))return a;return o[0]||null},"Z"),Gi="jhs_dmm_video",Fh=30*864e5,_c=500;function Qi(o){if(!o)return{};try{let e=JSON.parse(o);return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch{return{}}}d(Qi,"parseJsonMap");function Yi(o){let e=Date.now();for(let s of Object.keys(o)){let a=o[s];(!a||a.time&&e-a.time>Fh)&&delete o[s]}let t=Object.keys(o);if(t.length>_c){t.sort(((s,a)=>(o[s].time||0)-(o[a].time||0)));for(let s of t.slice(0,t.length-_c))delete o[s]}return o}d(Yi,"pruneDmmCache");function Re(o){return o?.enablePreviewVideo!=="no"}d(Re,"isPreviewEnabled");function ds(o){return o?.enableLoadPreviewVideo!=="no"}d(ds,"isDmmEnabled");function $c(o){return Re(o)}d($c,"canUsePreview");function Ft(o){return Re(o)&&ds(o)}d(Ft,"canUseDmmPreview");function ma(o){return Ft(o)}d(ma,"canUseCardPreview");var en=class en{constructor(e,t,s,a){this.carNum=e||"",this.storage=t,this.movie=s,this.scope=a,this.lastError=null}_checkCache(){let e=Yi(Qi(this.storage.getLocal(Gi)));return e[this.carNum]?(clog.debug("缓存中存在预览视频信息",e[this.carNum]),e[this.carNum]):null}_updateCache(e){let t=Yi(Qi(this.storage.getLocal(Gi)));t[this.carNum]={...e,time:Date.now()},clog.debug("成功解析出预览视频并已缓存:",e),this.storage.setLocal(Gi,JSON.stringify(t))}async _fetchRemote(){let e=await this.movie.preview("dmm",{carNum:this.carNum},{scope:this.scope}),t=$("#fanzaBtn");if(!e.sources)return clog.warn("所有关键词尝试均未找到匹配的Content ID, 解析Dmm视频失败"),t.attr("href",e.searchUrl).attr("title","未查询到, 点击前往搜索页").css("backgroundColor","var(--jhs-status-filter)"),null;t.attr("href",e.pageUrl).css("backgroundColor","var(--jhs-status-down)"),e.matchType==="multiple"&&t.append('多结果');let s="jhs_other_site_dmm",a=Yi(Qi(this.storage.getLocal(s)));return a[this.carNum]={type:e.matchType,url:e.pageUrl,time:Date.now()},this.storage.setLocal(s,JSON.stringify(a)),e.sources}async fetchVideo(){let e=C(this.carNum);if(!e)return clog.warn("跳过 DMM 解析:番号不可用"),null;this.carNum=e;let t=this._checkCache();if(t)return t;try{let s=this.carNum.toLowerCase();if(s.startsWith("heyzo")||/^(n\d+|\d+(-\d+)*)$/.test(s)||/^n\d+$/.test(s))return clog.debug("无码番号类型,取消 DMM 解析"),null;if(this.carNum.includes("VR-"))return clog.debug("VR 类型,取消 DMM 解析"),null;let a=await this._fetchRemote();return a?(this._updateCache(a),a):null}catch(s){let a=s;this.lastError=s instanceof we?s:new we("dmm",a?.code||"PARSE_ERROR",a?.message||String(s),{cause:s,retryable:a?.retryable===!0}),clog.error("DMM API 搜索失败:",this.lastError);let r=$("#fanzaBtn");return r.attr("href",this.movie.searchUrl("dmm",{carNum:this.carNum})),r.attr("title","未查询到, 点击前往搜索页"),r.css("backgroundColor","var(--jhs-status-filter)"),null}}};d(en,"DmmPreviewParser");var Zi=en;async function Xi(o,e,t,s){let a=new Zi(o,e,t,s);return{sources:await a.fetchVideo(),error:a.lastError}}d(Xi,"fetchDmmPreview");async function fa(o,e,t,s,a){return ds(a)?Xi(o,e,t,s):{sources:null,error:null}}d(fa,"fetchDmmPreviewIfEnabled");var tn=class tn extends I{constructor(){super(...arguments),this._busPreviewGeneration=0}getName(){return"BusPreviewVideoPlugin"}async initCss(){return` .bus-preview-modal { position:fixed; inset:0; z-index:var(--jhs-z-modal); display:flex; align-items:center; justify-content:center; visibility:hidden; opacity:0; background:rgba(0,0,0,.95); transition:opacity var(--jhs-motion-base) var(--jhs-ease); } .bus-preview-modal.is-open { visibility:visible; opacity:1; } .bus-preview-modal-content { position:relative; display:flex; max-width:95%; max-height:95%; flex-direction:column; align-items:center; gap:var(--jhs-space-3); } @@ -3316,7 +3311,7 @@ ${i}\r
      - `);let t=$("#bus-preview-modal");t.on("click",(s=>{s.target instanceof Element&&s.target.id==="bus-preview-modal"&&this.closeVideoModal()})),e.listen(document,"keydown",(s=>{s instanceof KeyboardEvent&&s.key==="Escape"&&t.hasClass("is-open")&&this.closeVideoModal()})),e.addCleanup((()=>{t.off(),t.remove()}))}}closeVideoModal(){let e=$("#preview-video");e.length>0&&e[0].pause(),$("#bus-preview-modal").removeClass("is-open")}unmountPreview(){this._busPreviewMounted=!1,this.closeVideoModal(),$("#bus-preview-modal").remove(),$(".preview-video-container").off("click.jhsBusPreview").remove()}async handle(){if(!isDetailPage)return;let e=this.getRuntimeService("settings");if(this._busScope||(this._busScope=await this.getRuntimeService("scope")()),!this._settingsListenerBound){this._settingsListenerBound=!0;let t=d(s=>{s.detail?.names?.some(r=>r==="enablePreviewVideo"||r==="enableLoadPreviewVideo")&&this.reconfigure()},"onSettingsChanged");e.addEventListener("settings.changed",t),this._busScope.addCleanup((()=>{e.removeEventListener("settings.changed",t),this._settingsListenerBound=!1}))}this.reconfigure()}reconfigure(){this._busPreviewGeneration++;let e=this.getRuntimeService("settings").snapshot();if(!zt(e))return void this.unmountPreview();this.mountPreview()}mountPreview(){if(this._busPreviewMounted)return;this._busPreviewMounted=!0;let e=this._busScope;this.initModal(e);let t=$("#sample-waterfall .sample-box .photo-frame img:first").attr("src"),s=$(` + `);let t=$("#bus-preview-modal");t.on("click",(s=>{s.target instanceof Element&&s.target.id==="bus-preview-modal"&&this.closeVideoModal()})),e.listen(document,"keydown",(s=>{s instanceof KeyboardEvent&&s.key==="Escape"&&t.hasClass("is-open")&&this.closeVideoModal()})),e.addCleanup((()=>{t.off(),t.remove()}))}}closeVideoModal(){let e=$("#preview-video");e.length>0&&e[0].pause(),$("#bus-preview-modal").removeClass("is-open")}unmountPreview(){this._busPreviewMounted=!1,this.closeVideoModal(),$("#bus-preview-modal").remove(),$(".preview-video-container").off("click.jhsBusPreview").remove()}async handle(){if(!isDetailPage)return;let e=this.getRuntimeService("settings");if(this._busScope||(this._busScope=await this.getRuntimeService("scope")()),!this._settingsListenerBound){this._settingsListenerBound=!0;let t=d(s=>{s.detail?.names?.some(r=>r==="enablePreviewVideo"||r==="enableLoadPreviewVideo")&&this.reconfigure()},"onSettingsChanged");e.addEventListener("settings.changed",t),this._busScope.addCleanup((()=>{e.removeEventListener("settings.changed",t),this._settingsListenerBound=!1}))}this.reconfigure()}reconfigure(){this._busPreviewGeneration++;let e=this.getRuntimeService("settings").snapshot();if(!Ft(e))return void this.unmountPreview();this.mountPreview()}mountPreview(){if(this._busPreviewMounted)return;this._busPreviewMounted=!0;let e=this._busScope;this.initModal(e);let t=$("#sample-waterfall .sample-box .photo-frame img:first").attr("src"),s=$(`
      - `);$("#sample-waterfall").prepend(s);let a=!1,r=$(".preview-video-container");r.on("click",(async i=>{if(i.preventDefault(),i.stopPropagation(),a)show.info("正在加载中, 勿重复点击");else{a=!0;try{await this.handleVideo()}finally{a=!1}}})),window.location.href.includes("autoPlay=1")&&r.trigger("click")}async handleVideo(){let e=this._busPreviewGeneration,t=$("#bus-preview-modal"),s=t.find(".bus-preview-modal-content"),a=$("#preview-video");if(e!==this._busPreviewGeneration||!Pe(this.getRuntimeService("settings").snapshot()))return;if(a.length>0)return t.addClass("is-open"),void await de(a[0],{context:"JavBus 预览视频",notify:!0});let r=this.getPageInfo().carNum,i=await this.getRuntimeService("scope")(),{sources:n,error:l}=await ma(r,this.getRuntimeService("storage"),this.getRuntimeService("movie"),i,this.getRuntimeService("settings").snapshot());e!==this._busPreviewGeneration||!Pe(this.getRuntimeService("settings").snapshot())||(n&&Object.keys(n).length!==0?(await this.createVideoPlayerAndControls(n,s),a=$("#preview-video"),a.length>0?(t.addClass("is-open"),await de(a[0],{context:"JavBus 预览视频",notify:!0,message:l?.code==="REGION_BLOCKED"?l.message:"当前视频源无法播放"})):show.error("视频播放器创建失败。")):show.error(l?.code==="REGION_BLOCKED"?l.message:"未找到可用的视频源。"))}async createVideoPlayerAndControls(e,t){let s=this.getRuntimeService("settings").snapshot().videoQuality;s=Ut(Object.keys(e),s);let a=e[s],r=$('
      '),i=$(''),n=$(document.createElement("source")).attr("src",a),l=$('
      ');i.append(n),r.append(i),t.empty().append(r,l);let c=$("#preview-video"),h=c.find("source"),u=t.find(".jhs-video-quality-list");if(!c.length||!h.length)return;let p=this.getRuntimeService("settings"),g=c[0],m=p.snapshot().videoMuted;g.muted=m==null||m===!0,c.off("volumechange.jhsVideo").on("volumechange.jhsVideo",(()=>{p.set("videoMuted",g.muted).catch((v=>clog.error("保存视频静音设置失败",v)))})),rt.forEach((v=>{let b=e[v.quality];if(b){let w=s===v.quality,S=$('');w&&S.addClass("active"),S.attr({"data-quality":v.quality,"data-video-src":b,"aria-pressed":w?"true":"false"}).text(v.text),u.append(S)}}));let f=u.find(".jhs-video-quality-btn");u.off("click.jhsVideo").on("click.jhsVideo",".jhs-video-quality-btn",(async v=>{try{let b=$(v.currentTarget);if(b.hasClass("active"))return;let w=b.attr("data-video-src");h.attr("src",w);let S=g.currentTime;g.load(),g.currentTime=S,await de(g,{context:"JavBus 画质切换",notify:!0})&&(f.removeClass("active").attr("aria-pressed","false"),b.addClass("active").attr("aria-pressed","true"))}catch(b){clog.error("切换画质失败:",b)}}))}};d(en,"BusPreviewVideoPlugin");var fa=en;var tn=class tn extends I{constructor(){super(...arguments),this.previewGeneration=0}getName(){return"CoverButtonPlugin"}async initCss(){return` + `);$("#sample-waterfall").prepend(s);let a=!1,r=$(".preview-video-container");r.on("click",(async i=>{if(i.preventDefault(),i.stopPropagation(),a)show.info("正在加载中, 勿重复点击");else{a=!0;try{await this.handleVideo()}finally{a=!1}}})),window.location.href.includes("autoPlay=1")&&r.trigger("click")}async handleVideo(){let e=this._busPreviewGeneration,t=$("#bus-preview-modal"),s=t.find(".bus-preview-modal-content"),a=$("#preview-video");if(e!==this._busPreviewGeneration||!Re(this.getRuntimeService("settings").snapshot()))return;if(a.length>0)return t.addClass("is-open"),void await de(a[0],{context:"JavBus 预览视频",notify:!0});let r=this.getPageInfo().carNum,i=await this.getRuntimeService("scope")(),{sources:n,error:l}=await fa(r,this.getRuntimeService("storage"),this.getRuntimeService("movie"),i,this.getRuntimeService("settings").snapshot());e!==this._busPreviewGeneration||!Re(this.getRuntimeService("settings").snapshot())||(n&&Object.keys(n).length!==0?(await this.createVideoPlayerAndControls(n,s),a=$("#preview-video"),a.length>0?(t.addClass("is-open"),await de(a[0],{context:"JavBus 预览视频",notify:!0,message:l?.code==="REGION_BLOCKED"?l.message:"当前视频源无法播放"})):show.error("视频播放器创建失败。")):show.error(l?.code==="REGION_BLOCKED"?l.message:"未找到可用的视频源。"))}async createVideoPlayerAndControls(e,t){let s=this.getRuntimeService("settings").snapshot().videoQuality;s=zt(Object.keys(e),s);let a=e[s],r=$('
      '),i=$(''),n=$(document.createElement("source")).attr("src",a),l=$('
      ');i.append(n),r.append(i),t.empty().append(r,l);let c=$("#preview-video"),h=c.find("source"),u=t.find(".jhs-video-quality-list");if(!c.length||!h.length)return;let p=this.getRuntimeService("settings"),g=c[0],m=p.snapshot().videoMuted;g.muted=m==null||m===!0,c.off("volumechange.jhsVideo").on("volumechange.jhsVideo",(()=>{p.set("videoMuted",g.muted).catch((v=>clog.error("保存视频静音设置失败",v)))})),rt.forEach((v=>{let b=e[v.quality];if(b){let w=s===v.quality,S=$('');w&&S.addClass("active"),S.attr({"data-quality":v.quality,"data-video-src":b,"aria-pressed":w?"true":"false"}).text(v.text),u.append(S)}}));let f=u.find(".jhs-video-quality-btn");u.off("click.jhsVideo").on("click.jhsVideo",".jhs-video-quality-btn",(async v=>{try{let b=$(v.currentTarget);if(b.hasClass("active"))return;let w=b.attr("data-video-src");h.attr("src",w);let S=g.currentTime;g.load(),g.currentTime=S,await de(g,{context:"JavBus 画质切换",notify:!0})&&(f.removeClass("active").attr("aria-pressed","false"),b.addClass("active").attr("aria-pressed","true"))}catch(b){clog.error("切换画质失败:",b)}}))}};d(tn,"BusPreviewVideoPlugin");var va=tn;var sn=class sn extends I{constructor(){super(...arguments),this.previewGeneration=0}getName(){return"CoverButtonPlugin"}async initCss(){return` `}async handle(){if(!window.isListPage)return;let e=await this.getRuntimeService("scope")(),t=this.getRuntimeService("settings"),s=d(a=>{let r=a.detail?.names||[];r.some(i=>i==="enablePreviewVideo"||i==="enableLoadPreviewVideo")&&(this.previewGeneration++,ga(t.snapshot())?this.addSvgBtn().catch((i=>clog.error("卡片预览重新挂载失败",i))):($('[id$="_preview_video"]').each((i,n)=>{n.pause?.(),$(n).parent().remove()}),this.enableSvgBtn())),r.some(i=>["enableScreenSvg","enableVideoSvg","enableHandleSvg","enableSiteSvg","enableCopySvg"].includes(i))&&this.enableSvgBtn()},"onSettingsChanged");this._settingsListenerBound||(this._settingsListenerBound=!0,t.addEventListener("settings.changed",s),e.addCleanup((()=>{t.removeEventListener("settings.changed",s),this._settingsListenerBound=!1}))),this.addSvgBtn(),await this.bindClick(e)}buildToolBox(){return` + `}async handle(){if(!window.isListPage)return;let e=await this.getRuntimeService("scope")(),t=this.getRuntimeService("settings"),s=d(a=>{let r=a.detail?.names||[];r.some(i=>i==="enablePreviewVideo"||i==="enableLoadPreviewVideo")&&(this.previewGeneration++,ma(t.snapshot())?this.addSvgBtn().catch((i=>clog.error("卡片预览重新挂载失败",i))):($('[id$="_preview_video"]').each((i,n)=>{n.pause?.(),$(n).parent().remove()}),this.enableSvgBtn())),r.some(i=>["enableScreenSvg","enableVideoSvg","enableHandleSvg","enableSiteSvg","enableCopySvg"].includes(i))&&this.enableSvgBtn()},"onSettingsChanged");this._settingsListenerBound||(this._settingsListenerBound=!0,t.addEventListener("settings.changed",s),e.addCleanup((()=>{t.removeEventListener("settings.changed",s),this._settingsListenerBound=!1}))),this.addSvgBtn(),await this.bindClick(e)}buildToolBox(){return`
      @@ -3373,7 +3368,7 @@ ${i}\r
      - `}async addSvgBtn(e=null){this.getOptionalDependency("ListPagePlugin")&&((e?$(e).toArray():$(this.getSelector().itemSelector).toArray()).forEach((t=>{let s=$(t);if(s.find(".tool-box").length||B&&s.find(".avatar-box").length)return;let a=M?s.find(".tags").first():s.find(".photo-info").first();a.length&&a.append(this.buildToolBox())})),this.enableSvgBtn(e))}async enableSvgBtn(e=null){let t=this.getRuntimeService("settings").snapshot(),{enableScreenSvg:s=R,enableVideoSvg:a=R,enablePreviewVideo:r=R,enableHandleSvg:i=R,enableSiteSvg:n=R,enableCopySvg:l=R}=t,c=e?$(e):$(document);[{selector:".screenSvg",enabled:s===R&&this.getOptionalDependency("ScreenShotPlugin")?R:"no"},{selector:".videoSvg",enabled:a===R&&ga(t)?R:"no"},{selector:".handleSvg",enabled:i},{selector:".siteSvg",enabled:n},{selector:".copySvg",enabled:l}].forEach((({selector:h,enabled:u})=>{c.find(h).toggle(u===R)}))}closeCardMenus(e=!1){let t=$(".jhs-card-menu.is-open"),s=t.siblings(".jhs-card-menu-trigger");t.removeClass("is-open"),s.attr("aria-expanded","false"),e&&s.first().trigger("focus")}async bindClick(e){this.getSelector();let t=this.getOptionalDependency("ListPagePlugin");if(!t)return;let s=$(document);s.off(".jhsCoverButton"),e.addCleanup((()=>s.off(".jhsCoverButton"))),s.on("click.jhsCoverButton",".jhs-card-menu-trigger",(h=>{h.preventDefault(),h.stopPropagation();let u=$(h.currentTarget),p=u.siblings(".jhs-card-menu"),g=!p.hasClass("is-open");this.closeCardMenus(),p.toggleClass("is-open",g),u.attr("aria-expanded",String(g)),g&&p.children().first().trigger("focus")})).on("keydown.jhsCoverButton",".jhs-card-menu [role='menuitem']",(h=>{let u=$(h.currentTarget).closest(".jhs-card-menu"),p=u.find("[role='menuitem']"),g=p.index(h.currentTarget);if(h.key==="Escape")return h.preventDefault(),this.closeCardMenus(!0);if(!["ArrowDown","ArrowUp","Home","End"].includes(h.key))return;h.preventDefault();let m=h.key==="Home"?0:h.key==="End"?p.length-1:h.key==="ArrowDown"?(g+1)%p.length:(g-1+p.length)%p.length;p.eq(m).trigger("focus")})).on("click.jhsCoverButton",(h=>{$(h.target).closest(".more-tools-container").length||this.closeCardMenus()})),s.on("click.jhsCoverButton",".videoSvg",(h=>{h.preventDefault(),$('.videoSvg[title!="播放视频"]').each(((g,m)=>{let f=$(m),v=f.closest(".item"),b=v.find("img"),{carNum:w}=t.findCarNumAndHref(v);this.showImg(f,b,w),f.html(this.videoSvg).attr({title:"播放视频","aria-label":"播放视频"})}));let u=$(h.target).closest(".item"),p=u.find(".videoSvg");if(p.attr("title")==="播放视频"){p.html(this.recoveryVideoSvg).attr({title:"切回封面","aria-label":"切回封面"});let{carNum:g}=t.findCarNumAndHref(u),m=u.find("img");if(!m.length)return void show.error("没有找到图片");this.showVideo(p,m,g).catch((f=>clog.error("卡片预览视频打开失败",f)))}})),s.on("click.jhsCoverButton",".screenSvg",(async h=>{h.preventDefault();let u=loading();try{let p=$(h.currentTarget).closest(".item"),{carNum:g}=t.findCarNumAndHref(p);g=g.replace("FC2-","");let m=this.getOptionalDependency("ScreenShotPlugin");if(!m)throw new Error("剧照功能已禁用");let f=await m.getScreenshot(g,{allowWhenDisabled:!0});u.close(),globalThis.showImageViewer(f)}catch(p){clog.error("图片预览出错:",p),show.error("图片预览出错:"+p)}finally{u.close()}})),s.on("click.jhsCoverButton",".filterBtn, .favoriteBtn, .hasDownBtn, .hasWatchBtn",(h=>{h.preventDefault(),h.stopPropagation();try{let u=$(h.currentTarget),p=u.closest(".item"),{carNum:g,url:m,publishTime:f,fc2Source:v}=t.findCarNumAndHref(p),b=d(async w=>{try{let S=await t.parseActressName(m),j=Ce(w);if(!j)throw new Error("不支持的状态操作");await this.getRuntimeService("state").patch(g,{[j]:!0},{type:"list-card-state",record:{carNum:g,url:m,names:S,publishTime:f,fc2Source:v}}),show.ok("操作成功")}catch(S){clog.error("保存操作失败:",S),show.error("操作失败")}},"r");u.hasClass("filterBtn")?utils.q(h,`是否屏蔽${C(g)}?`,(()=>b(ce))):u.hasClass("favoriteBtn")?b(ue):u.hasClass("hasDownBtn")?b(pe):u.hasClass("hasWatchBtn")&&b(me),this.closeCardMenus()}catch(u){clog.error("按钮点击处理失败:",u)}}));let a=this.getRuntimeService("settings").snapshot(),r=this.getRuntimeService("movie"),i=r.externalSiteOrigin("missAvBtn",a),n=r.externalSiteOrigin("jableBtn",a),l=r.externalSiteOrigin("avgleBtn",a),c=r.providerOrigin("av123")||"";$(this.getSelector().itemSelector).each(((h,u)=>{let p=$(u),{carNum:g}=t.findCarNumAndHref(p);p.find(".site-jable").attr({href:`${n}/search/${g}/`,target:"_blank",rel:"noopener noreferrer"}),p.find(".site-avgle").attr({href:`${l}/vod/search.html?wd=${g}`,target:"_blank",rel:"noopener noreferrer"}),p.find(".site-miss-av").attr({href:`${i}/search/${g}`,target:"_blank",rel:"noopener noreferrer"}),p.find(".site-123-av").attr({href:`${c}/cn/search?keyword=${encodeURIComponent(g)}`,target:"_blank",rel:"noopener noreferrer"})})),s.on("click.jhsCoverButton",".site-jable, .site-avgle, .site-miss-av, .site-123-av",(h=>{try{h.preventDefault(),h.stopPropagation();let u=$(h.currentTarget),p=u.closest(".item"),{carNum:g}=t.findCarNumAndHref(p),m=null;if(u.hasClass("site-jable")?m=`${n}/search/${g}/`:u.hasClass("site-avgle")?m=`${l}/vod/search.html?wd=${g}`:u.hasClass("site-miss-av")?m=`${i}/search/${g}`:u.hasClass("site-123-av")&&(m=`${c}/cn/search?keyword=${encodeURIComponent(g)}`),!m)return;h.ctrlKey||h.metaKey?GM_openInTab(m,{insert:0}):window.open(m),this.closeCardMenus()}catch(u){clog.error("站点按钮处理失败:",u)}})),s.on("click.jhsCoverButton",".titleSvg, .carNumSvg, .downSvg",(h=>{h.preventDefault(),h.stopPropagation();let u=$(h.currentTarget).closest(".item"),{carNum:p,title:g}=t.findCarNumAndHref(u),m=u.find(B?".photo-frame img":".cover img");$(h.currentTarget).hasClass("titleSvg")?utils.copyToClipboard("标题",g):$(h.currentTarget).hasClass("carNumSvg")?utils.copyToClipboard("番号",p):$(h.currentTarget).hasClass("downSvg")&&fetch(m.attr("src")).then((f=>f.blob())).then((f=>utils.download(f,p+" "+g+".jpg"))),this.closeCardMenus()}))}showImg(e,t,s){e.html(this.videoSvg).attr({title:"播放视频","aria-label":"播放视频"});let a=$(`#${`${s}_preview_video`}`);a.length>0&&(a[0].pause(),a.parent().hide()),t.show(),t.removeClass("loading"),t.next(".loading-spinner").remove()}async showVideo(e,t,s){let a=this.getRuntimeService("settings").snapshot();if(!ga(a))return show.error("预览视频已关闭");let r=this.previewGeneration,i=`${s}_preview_video`,n=$(`#${i}`);if(n.length>0)return n.parent().show(),await de(n[0],{context:"列表卡片预览",notify:!0}),void t.hide();t.addClass("loading"),t.after('
      ');let l=t.attr("data-full")||t.attr("src"),c=await this.getRuntimeService("scope")(),{sources:h,error:u}=await ma(s,this.getRuntimeService("storage"),this.getRuntimeService("movie"),c,a);if(r!==this.previewGeneration||!Pe(this.getRuntimeService("settings").snapshot()))return void this.showImg(e,t,s);if(!h)return show.error(u?.code==="REGION_BLOCKED"?u.message:"未解析到视频"),void this.showImg(e,t,s);let p=this.getRuntimeService("settings").snapshot().videoQuality;p=Ut(Object.keys(h),p);let g=h[p],m=document.createElement("div"),f=document.createElement("video");B||(m.className="jhs-layout-d543acf8"),f.src=g,f.poster=l||"",f.id=i,f.controls=!0,f.loop=!0,f.muted=!0,f.playsInline=!0,f.className="jhs-layout-a38a0e50",m.appendChild(f),t.parent().append(m),t.hide(),t.removeClass("loading"),t.next(".loading-spinner").remove(),n=$(f);let v=n[0];v.load(),v.muted=!1,await de(v,{context:"列表卡片预览",notify:!0,message:u?.code==="REGION_BLOCKED"?u.message:"当前视频源无法播放"}),n.trigger("focus")}};d(tn,"CoverButtonPlugin");var va=tn;var sn=class sn extends I{constructor(){super(...arguments),this.previewGeneration=0,this.previewSession=null}getName(){return"PreviewVideoPlugin"}async initCss(){return".jhs-dmm-preview-player{display:none;width:100%;height:auto}.jhs-dmm-preview-player.is-active{display:block}.jhs-native-preview-hidden{display:none!important}"}async handle(){if(!isDetailPage)return;let e=this.getRuntimeService("settings");if(this.lifecycleScope||(this.lifecycleScope=await this.getRuntimeService("scope")()),!this._settingsListenerBound){this._settingsListenerBound=!0;let t=d(s=>{s.detail?.names?.some(r=>r==="enablePreviewVideo"||r==="enableLoadPreviewVideo")&&this.reconfigure()},"onSettingsChanged");e.addEventListener("settings.changed",t),this.lifecycleScope.addCleanup((()=>{e.removeEventListener("settings.changed",t),this._settingsListenerBound=!1,this.unmountPreview()}))}this.reconfigure()}reconfigure(){this.previewGeneration++;let e=this.getRuntimeService("settings").snapshot();if(!_c(e))return void this.unmountPreview();this.mountPreview(),zt(e)?this.initDmm(this.lifecycleScope).catch((t=>clog.error("预加载 DMM 失败",t))):(this.unmountDmmPlayer(),$(".fancybox-content #preview-video").length&&!$("#video-bottom-toolbar").length&&this.handleVideo().catch(t=>clog.error("恢复原生预览操作失败",t)))}mountPreview(){if(this._previewMounted)return;this._previewMounted=!0,$(".preview-video-container").removeClass("jhs-native-preview-hidden");let e=$(".preview-video-container"),t=d(()=>{this.cancelOpenWait?.(),this.cancelOpenWait=utils.loopDetector((()=>$(".fancybox-content #preview-video").length>0),(()=>{this.handleVideo().catch((a=>clog.error("预览视频处理失败",a)))}),20,1e4,!0,this.lifecycleScope)},"openVideo");e.off("click.jhsVideo").on("click.jhsVideo",t),this.lifecycleScope.addCleanup((()=>e.off("click.jhsVideo",t)));let s=window.location.href;(s.includes("gallery-1")||s.includes("gallery-2"))&&t(),s.includes("autoPlay=1")&&e.length>0&&e[0].click()}unmountDmmPlayer(){this.dmmRequestScope?.dispose(),$("[data-jhs-dmm-trigger]").remove();let e=$("#jhs-preview-video"),t=e[0],s=this.previewSession?.native;s&&t&&this.isSessionOpen(this.previewSession)&&(this.seekVideo(s,t.currentTime),!t.paused&&Pe(this.getRuntimeService("settings").snapshot())?de(s,{context:"恢复原生预览",notify:!1}).then(()=>{this.previewSession?.native!==s&&s.pause()}):s.pause()),t&&(t.pause(),e.removeAttr("src"),t.load(),e.remove()),$("#video-bottom-toolbar .jhs-video-quality-list").empty(),$("#preview-video").removeClass("jhs-native-preview-hidden"),this.dmmPreviewPromise=null,this.previewSession&&!s&&this.disposePreviewSession()}unmountPreview(){this._previewMounted=!1,this.cancelOpenWait?.(),this.disposePreviewSession(),this.unmountDmmPlayer(),$("#video-bottom-toolbar").remove(),$(".preview-video-container").addClass("jhs-native-preview-hidden")}unmountJhsPreview(){this.disposePreviewSession(),$("[data-jhs-dmm-trigger]").remove();let e=$("#jhs-preview-video"),t=e[0];t&&(t.pause(),e.removeAttr("src"),t.load(),e.remove()),$("#video-bottom-toolbar").remove(),$("#preview-video").removeClass("jhs-native-preview-hidden"),$(".preview-video-container").addClass("jhs-native-preview-hidden")}async initDmm(e){let t=this.previewGeneration,s=this.getRuntimeService("settings");try{let{sources:a}=await this.getDmmPreview(e);if(t!==this.previewGeneration||e?.disposed||!Pe(s.snapshot())||!ds(s.snapshot())||!a)return;if($(".fancybox-content #preview-video").length){await this.handleVideo();return}if($("#preview-video")[0])return;clog.debug("JavDB没有视频播放元素, 开始创建...");let n=$(".column-video-cover img").attr("src");if($("[data-jhs-dmm-trigger]").length)return;let l=$('');l.append($('').attr("src",n||"")),$(".preview-images").first().prepend(l),l.on("click.jhsVideo",()=>this.openDmmDialog())}catch(a){clog.error("预加载 DMM 失败:",a)}}getDmmPreview(e=this.lifecycleScope){if(this.dmmPreviewPromise)return this.dmmPreviewPromise;let t=new te("javdb-dmm-request");this.dmmRequestScope=t;let s,a=Promise.resolve(e||this.getRuntimeService("scope")()).then(r=>{if(r?.disposed||t.disposed)throw new Error("预览请求已取消");return s=r?.addCleanup?.(()=>t.dispose()),Zi(this.getPageInfo().carNum,this.getRuntimeService("storage"),this.getRuntimeService("movie"),t)}).then((r=>(this.dmmPreviewPromise===a&&(r.error?.retryable||r.error?.code==="HTTP_ERROR")&&(this.dmmPreviewPromise=null),r)),(r=>{throw this.dmmPreviewPromise===a&&(this.dmmPreviewPromise=null),r})).finally(()=>{t.dispose(),typeof s=="function"&&s()});return this.dmmPreviewPromise=a,a}createDmmPlayer(e){let t=e.length?e.parent():$(this.previewSession?.host),s=t.find("#jhs-preview-video");if(s.length)return s;let a=$('');return t.append(a),a}isSessionOpen(e){if(!e||e.scope.disposed||!e.host.isConnected||e.native&&!e.host.contains(e.native))return!1;for(let t=e.host;t;t=t.parentElement)if(t.getAttribute("aria-hidden")==="true"||getComputedStyle(t).display==="none")return!1;return!0}seekVideo(e,t){let s=d(()=>{try{e.currentTime=Math.max(0,Math.min(t||0,Number.isFinite(e.duration)?e.duration:1/0))}catch{}},"seek");s();let a=this.previewSession;if(a?.seekCleanups?.get(e)?.(),!e.readyState&&a){a.seekCleanups||(a.seekCleanups=new Map);let r=d(()=>{l(),this.isSessionOpen(a)&&s()},"loaded"),i=d(()=>l(),"failed"),n=setTimeout(i,5e3),l=a.scope.addCleanup(()=>{clearTimeout(n),e.removeEventListener("loadedmetadata",r),e.removeEventListener("error",i),a.seekCleanups.delete(e)});e.addEventListener("loadedmetadata",r,{once:!0}),e.addEventListener("error",i,{once:!0}),a.seekCleanups.set(e,l)}}disposePreviewSession(){let e=this.previewSession;if(this.previewSession=null,!e)return;this.dmmRequestScope?.dispose(),this.dmmPreviewPromise=null,e.scope.dispose(),$(e.host).find("#video-bottom-toolbar").remove();let t=e.host.querySelector("#jhs-preview-video");t&&(t.pause(),t.removeAttribute("src"),t.load(),t.remove()),e.native?.classList.remove("jhs-native-preview-hidden"),e.native?.pause(),e.dialogId!=null&&this.getRuntimeService("dialog").close(e.dialogId)}openDmmDialog(){if(!zt(this.getRuntimeService("settings").snapshot())||this.previewSession)return;let e=$('
      ');this.getRuntimeService("dialog").open({type:1,title:"预告片",ui:{body:"media"},content:e,area:utils.getDialogArea("lg"),success:d((t,s)=>{this.handleVideo(e[0],s).catch(a=>clog.error("预览失败",a))},"success"),end:d(()=>{this.previewSession?.host===e[0]&&this.disposePreviewSession()},"end")})}waitForDmmReady(e){let t=this.previewSession?.scope.signal;return t?.aborted||e.error?Promise.resolve(!1):e.readyState>=3?Promise.resolve(!0):new Promise(s=>{let a=d(l=>{clearTimeout(n),e.removeEventListener("canplay",r),e.removeEventListener("error",i),t?.removeEventListener("abort",i),s(l)},"finish"),r=d(()=>a(!0),"loaded"),i=d(()=>a(!1),"failed"),n=setTimeout(i,1e4);e.addEventListener("canplay",r,{once:!0}),e.addEventListener("error",i,{once:!0}),t?.addEventListener("abort",i,{once:!0})})}async restoreNativePlayer(e,t,s=!1,a=!0){if(!t||!this.isSessionOpen(this.previewSession))return!1;let r=e.parent().find("#jhs-preview-video"),i=r[0];return i&&(i.pause(),r.removeAttr("src"),i.load(),r.remove()),e.removeClass("jhs-native-preview-hidden"),a?de(t,{context:"JavDB 原生预览回退",notify:s}):(t.pause(),!0)}async handleVideo(e=null,t=null){let s=$(".fancybox-content #preview-video"),a=e||s[0]?.closest(".fancybox-content");if(!a||!Pe(this.getRuntimeService("settings").snapshot())||getComputedStyle(a).display==="none")return;if(this.previewSession?.host!==a){this.disposePreviewSession();let L=new te("javdb-preview");this.previewSession={host:a,native:s[0]||null,scope:L,dialogId:t},L.observe(document.body,()=>{this.previewSession?.host===a&&!this.isSessionOpen(this.previewSession)&&this.disposePreviewSession()},{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class","style","aria-hidden"]})}let r=this.previewSession;if(r.generation===this.previewGeneration)return;r.generation=this.previewGeneration;let i=d(()=>this.previewSession===r&&this.isSessionOpen(r)&&u===this.previewGeneration&&Pe(this.getRuntimeService("settings").snapshot()),"alive"),n=this.getRuntimeService("settings"),l=$(a),c=s[0],h=n.snapshot().videoMuted,u=this.previewGeneration,p=ds(this.getRuntimeService("settings").snapshot()),g=p?await this.getDmmPreview():{sources:null,error:null};if(!i())return;let{sources:m,error:f}=g,v=$("
      ").attr("id","video-bottom-toolbar").addClass("jhs-video-toolbar"),b=$("
      ").addClass("jhs-video-quality-list").attr({role:"group","aria-label":"视频画质"});l.find("#video-bottom-toolbar").remove();let w=!1,S=null,j=null;if(m){let L=this.getRuntimeService("settings").snapshot().videoQuality,N=Ut(Object.keys(m),L),A=m[N],O=c?.currentTime||0,U=!c||!c.paused;S=this.createDmmPlayer(s),j=S[0],j.muted=h==null||h===!0,S.off("volumechange.jhsVideo").on("volumechange.jhsVideo",(()=>{n.set("videoMuted",j.muted).catch(Q=>clog.error("保存视频静音设置失败",Q))})),S.attr("src",A),j.load(),this.seekVideo(j,O),S.addClass("is-active");let H=await this.waitForDmmReady(j);if(!i()){j.pause();return}if(w=H&&(!U||await de(j,{context:"JavDB 高画质预览",notify:!1})),!i()){j.pause();return}if(H&&!w&&!j.muted&&(j.muted=!0,w=await de(j,{context:"JavDB 高画质预览静音重试",notify:!1})),!i()){j.pause();return}if(w?(c?.pause(),s.addClass("jhs-native-preview-hidden")):(S.removeClass("is-active"),await this.restoreNativePlayer(s,c,!0,U)),!i())return;if(!w&&!c){show.error("当前视频源无法播放"),this.disposePreviewSession();return}w&&rt.forEach((Q=>{let se=m[Q.quality];if(!se)return;let ge=w&&N===Q.quality;b.append($('').toggleClass("active",ge).attr({"data-quality":Q.quality,"data-video-src":se,"aria-pressed":String(ge)}).text(Q.text))}))}v.append(b);let x=$("
      ").addClass("jhs-toolbar");if(this.getOptionalDependency("DetailPageButtonPlugin")&&x.append(Lt({actions:["blocked","favorite"],ids:{blocked:"video-filterBtn",favorite:"video-favoriteBtn"}})),x.append(''),!i())return;v.append(x),l.append(v),v.off("click.jhsVideo").on("click.jhsVideo",".jhs-video-quality-btn",(async L=>{let N=$(L.currentTarget);if(!N.hasClass("active"))try{if(!j?.isConnected||!i())return;let A=j.currentTime,O=S.attr("src"),U=!j.paused;S.attr("src",N.data("video-src")),j.load(),this.seekVideo(j,A);let H=await this.waitForDmmReady(j);if(!i())return;let Q=H&&(!U||await de(j,{context:"JavDB 画质切换",notify:!1}));if(!i())return;if(Q)v.find(".jhs-video-quality-btn").removeClass("active").attr("aria-pressed","false"),N.addClass("active").attr("aria-pressed","true");else{O&&(S.attr("src",O),j.load(),j.currentTime=A);let se=O&&await this.waitForDmmReady(j)&&(!U||await de(j,{context:"JavDB 画质切换回退",notify:!1}));if(!i())return;se||await this.restoreNativePlayer(s,c,!0,U)}}catch(A){clog.error("切换画质失败:",A)}})),$("#speed-btn").off("click.jhsVideo").on("click.jhsVideo",(()=>{let L=l.find("#jhs-preview-video.is-active")[0]||c;L?.isConnected&&this.isSessionOpen(r)&&this.seekVideo(L,L.currentTime+10)})),v.off("contextmenu.jhsVideo").on("contextmenu.jhsVideo","#speed-btn",(L=>(L.preventDefault(),this.getOptionalDependency("DetailPageButtonPlugin")?.filterOne?.(L)))),$("#video-filterBtn").off("click.jhsVideo").on("click.jhsVideo",(L=>this.getOptionalDependency("DetailPageButtonPlugin")?.filterOne?.(L))),$("#video-favoriteBtn").off("click.jhsVideo").on("click.jhsVideo",(L=>this.getOptionalDependency("DetailPageButtonPlugin")?.favoriteOne?.(L)));let _=this.getOptionalDependency("DetailPageButtonPlugin"),E=_?.getDetailStateController?.();if(E){v.find("#video-filterBtn,#video-favoriteBtn").off("click.jhsVideo");let L=E.bind({root:v[0],closeRoot:document.documentElement,carNum:this.getPageInfo().carNum,layerIndex:utils.getOwningLayerIndex({root:document.documentElement}),getRecord:d(()=>_.getStateRecord(),"getRecord"),selectors:{blocked:"#video-filterBtn",favorite:"#video-favoriteBtn"}});r.stateCleanup?.(),r.stateCleanup=V?.on("car-state-changed",N=>{if(N.carNums?.includes(L.carNum)&&this.isSessionOpen(r))return E.render(L)}),r.stateCleanup&&r.scope.addCleanup(r.stateCleanup)}}};d(sn,"PreviewVideoPlugin");var ba=sn;function $c(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelectorAll=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelectorAll=="function")return e;throw new TypeError("JavStore document is invalid")}d($c,"resolveDocument");function hs(o,e="https://javstore.net"){if(!o)return null;try{let t=new URL(String(o),e),s=t.hostname.toLowerCase();return["http:","https:"].includes(t.protocol)?(t.protocol==="http:"&&(s==="javstore.net"||s.endsWith(".javstore.net"))&&(t.protocol="https:"),t.href):null}catch{return null}}d(hs,"normalizeJavStoreAssetUrl");function Tc(o,e,t="https://javstore.net"){let s=ee(e);if(!s)return[];if(typeof o?.find=="function"){let a=globalThis.jQuery??globalThis.$??o.constructor;return o.find('a[href$="-pn.html"]').filter(((r,i)=>a(i).text().trim().toUpperCase().includes(s.toUpperCase()))).map(((r,i)=>new URL(a(i).attr("href"),t).href)).get()}return[...$c(o).querySelectorAll('a[href$="-pn.html"]')].filter(a=>a.textContent?.trim().toUpperCase().includes(s.toUpperCase())).map(a=>new URL(a.getAttribute("href")||"",t).href)}d(Tc,"parseJavStoreSearch");function Ac(o,e){if(typeof o?.find=="function"){let a=globalThis.jQuery??globalThis.$??o.constructor,i=o.find("a").filter(((l,c)=>a(c).text().trim()==="CLICK HERE!")).first().attr("href");if(!i)return null;let n=hs(i,e);return n?n.replace(".th",""):null}let t=[...$c(o).querySelectorAll("a")].find(a=>a.textContent?.trim()==="CLICK HERE!")?.getAttribute("href");if(!t)return null;let s=hs(t,e);return s?s.replace(".th",""):null}d(Ac,"parseJavStorePreview");var an=class an extends I{getName(){return"ScreenShotPlugin"}getScreenshotService(){return this.getRuntimeService("screenshot")}getSettingsSnapshot(){return this.getRuntimeService("settings")?.snapshot?.()??{}}async initCss(){return""}async handle(){if(!isDetailPage)return;let e=this.getRuntimeService("settings"),t=await this.getRuntimeService("scope")(),s=d(a=>{a.detail?.names?.includes("enableLoadScreenShot")&&(e.snapshot().enableLoadScreenShot==="no"?this.unmountHosted():this.loadScreenShot().catch(i=>clog.error("长缩略图重新加载失败",i)))},"onSettingsChanged");e.addEventListener("settings.changed",s),t.addCleanup((()=>e.removeEventListener("settings.changed",s))),this.loadScreenShot().catch(a=>clog.error("长缩略图加载失败",a))}unmountHosted(){$(".screen-container, .jhs-screenshot-providers").remove()}async loadScreenShot(){if(!isDetailPage||!this.getScreenshotService().isEnabled(this.getSettingsSnapshot()))return;let t=this.getPageInfo().carNum;M&&$(".preview-images .tile-item").first().before('
      正在加载缩略图
      '),B&&$("#sample-waterfall .sample-box:first").after('
      正在加载缩略图
      ');try{let s=await this.getScreenshot(t);s?(this.addImg("缩略图",s),clog.log("加载缩略图:",s)):this.showErrorFallback(t,null)}catch(s){this.showErrorFallback(t,s)}}async getScreenshot(e){if(e=T(e),!e)throw clog.warn("跳过缩略图解析:番号不可用"),new Error("缩略图番号不可用");let t=arguments[1]||{},s=this.getScreenshotService(),a=this.getSettingsSnapshot();if(!t.allowWhenDisabled&&!s.isEnabled(a))return clog.warn("长缩略图功能已关闭,跳过请求"),null;let r=await this.getRuntimeService("scope")(),i=await s.resolve({carNum:e},{scope:r,settings:a,allowWhenDisabled:t.allowWhenDisabled===!0});return(Array.isArray(i)?i[0]:i)?.url||null}addImg(e,t){let s=hs(t);if(!s)return;let a=$(".screen-container").empty(),r=$("").attr({src:s,alt:e,loading:"lazy"});M&&a.append(r.addClass("jhs-layout-cad980f4")),B&&a.append($('
      ').append(r.attr("title",e).addClass("jhs-layout-d4a575e8"))),a.on("click",(i=>{i.stopPropagation(),i.preventDefault(),globalThis.showImageViewer(i.currentTarget)}))}showErrorFallback(e,t){let s=t instanceof Error?t.message:"";t&&clog.error("获取缩略图失败:",s.substring(0,100));let a=`jhs-screenshot-message${B?" jhs-screenshot-message--bus":""}`,r=T(e);if(!r)return void $(".screen-container").empty().append($("
      ").addClass(a).text("无法获取番号,缩略图未加载"));let i=this.getScreenshotService().getSearchUrl({carNum:r}),n=$(".screen-container").empty(),l=$("
      ").addClass(a).text(t instanceof Error?"获取缩略图失败":"暂无缩略图结果"),c=$('点击重试');n.append(l,$("
      "),c),i&&n.append(document.createTextNode(" 或 "),$('前往确认').attr("href",i)),n.off("click",".retry-link").off("click",".check-link").on("click",".retry-link",(async h=>{h.stopPropagation(),h.preventDefault(),n.empty().append($("
      ").addClass(a).text("正在重新加载..."));try{let u=await this.getScreenshot(r);u?this.addImg("缩略图",u):this.showErrorFallback(r,null)}catch(u){this.showErrorFallback(r,u)}})).on("click",".check-link",(h=>{h.stopPropagation(),h.preventDefault(),window.open(i,"_blank")}))}async loadInto(e,t,{isActive:s=d(()=>!0,"isActive")}={}){let a=$(e);if(!a.length||!this.getScreenshotService().isEnabled(this.getSettingsSnapshot()))return a.empty(),null;let r=await this.getRuntimeService("scope")();return ea({target:a,carNum:t,screenshot:this.getScreenshotService(),settings:this.getSettingsSnapshot(),scope:r,isActive:s})}renderInto(e,t,s){let a=$(e),r=$("").attr({src:hs(t),alt:s,loading:"lazy"}).addClass("jhs-fc2-gallery__image"),i=$('').attr("aria-label",`查看${s}大图`).append(r);a.empty().append(i).off("click.jhsScreenshot").on("click.jhsScreenshot",".jhs-fc2-screenshot-thumbnail",(n=>{n.preventDefault(),n.stopPropagation(),globalThis.showImageViewer(r[0])}))}};d(an,"ScreenShotPlugin");var wa=an;var Pc="jhs_img_cdn_index";function Fh(o,e,t,s=Date.now()){let a=new Map;for(let r of o)if(Array.isArray(r.newVideoList))for(let i of r.newVideoList){let n=typeof i=="object"?i:{},l=T(typeof i=="string"?i:i.carNum);if(!l)continue;let c=a.get(l)||{carNum:l,coverUrl:"",title:"",publishTime:"",actresses:[],starIds:[],categories:new Set,score:0,voteCount:0,url:"",isVr:!1};c.coverUrl||(c.coverUrl=n.coverUrl||""),c.title||(c.title=n.title||""),c.publishTime=[c.publishTime,n.publishTime||""].sort().at(-1),c.score=Math.max(c.score,Number(n.score)||0),c.voteCount=Math.max(c.voteCount,Number(n.voteCount)||0),c.url||(c.url=n.url||""),c.isVr||(c.isVr=n.isVr===!0||/(^|[^A-Z])VR([^A-Z]|$)/i.test(`${n.title||""} ${(n.tags||[]).join?.(" ")||""} ${(n.categories||[]).join?.(" ")||""}`)),r.name&&!c.actresses.includes(r.name)&&c.actresses.push(r.name),r.starId&&!c.starIds.includes(r.starId)&&c.starIds.push(r.starId),r.actressType&&c.categories.add(r.actressType),a.set(l,c)}return[...a.values()].map((r=>{let i=e.get(r.carNum),n=q(i?.stateFlags),l=t[r.carNum]||null,c=l?l.action==="snoozed"&&l.until&&Date.parse(l.until)<=s?"pending":l.action:"pending";return{...r,actressName:r.actresses.join("、"),starId:r.starIds[0]||"",categories:[...r.categories],flags:n,decision:l,decisionState:c}}))}d(Fh,"aggregateNewVideoRecords");var rn=class rn extends I{constructor(){super(...arguments),P(this,"currentPage",1),P(this,"pageSize",30),P(this,"nvCurrentPage",1),P(this,"nvPageSize",60),P(this,"nvFlatListCache",[]),P(this,"nvAllItemsMap",new Map),P(this,"nvActressesCache",[]),P(this,"nvCarMapCache",new Map),P(this,"nvSortBy","publishTime_desc"),P(this,"nvSelected",new Set),P(this,"nvDecisionsCache",{}),P(this,"nvCoverCache",new Map),P(this,"nvActorCoverRequests",new Map),P(this,"nvRenderGeneration",0),P(this,"nvSearchDebounced",null),P(this,"nvInvalidationTimer",null),P(this,"nvWorkspaceReloadPromise",null),P(this,"nvWorkspaceReloadDirty",!1),P(this,"nvWorkspaceMounted",!1),P(this,"nvEventUnsubscribe",null),P(this,"taskStatusUnsubscribe",null),P(this,"nvCoverPreview",null),P(this,"nvWorkspaceRoot",null),P(this,"nvJavDbUrl",""),P(this,"nvRuleTime",8760),P(this,"avatarSources",[]),P(this,"avatarSourceIndex",0)}getName(){return"NewVideoPlugin"}getStartupMode(){return"idle"}async initCss(){return` + `}async addSvgBtn(e=null){this.getOptionalDependency("ListPagePlugin")&&((e?$(e).toArray():$(this.getSelector().itemSelector).toArray()).forEach((t=>{let s=$(t);if(s.find(".tool-box").length||B&&s.find(".avatar-box").length)return;let a=M?s.find(".tags").first():s.find(".photo-info").first();a.length&&a.append(this.buildToolBox())})),this.enableSvgBtn(e))}async enableSvgBtn(e=null){let t=this.getRuntimeService("settings").snapshot(),{enableScreenSvg:s=E,enableVideoSvg:a=E,enablePreviewVideo:r=E,enableHandleSvg:i=E,enableSiteSvg:n=E,enableCopySvg:l=E}=t,c=e?$(e):$(document);[{selector:".screenSvg",enabled:s===E&&this.getOptionalDependency("ScreenShotPlugin")?E:"no"},{selector:".videoSvg",enabled:a===E&&ma(t)?E:"no"},{selector:".handleSvg",enabled:i},{selector:".siteSvg",enabled:n},{selector:".copySvg",enabled:l}].forEach((({selector:h,enabled:u})=>{c.find(h).toggle(u===E)}))}closeCardMenus(e=!1){let t=$(".jhs-card-menu.is-open"),s=t.siblings(".jhs-card-menu-trigger");t.removeClass("is-open"),s.attr("aria-expanded","false"),e&&s.first().trigger("focus")}async bindClick(e){this.getSelector();let t=this.getOptionalDependency("ListPagePlugin");if(!t)return;let s=$(document);s.off(".jhsCoverButton"),e.addCleanup((()=>s.off(".jhsCoverButton"))),s.on("click.jhsCoverButton",".jhs-card-menu-trigger",(h=>{h.preventDefault(),h.stopPropagation();let u=$(h.currentTarget),p=u.siblings(".jhs-card-menu"),g=!p.hasClass("is-open");this.closeCardMenus(),p.toggleClass("is-open",g),u.attr("aria-expanded",String(g)),g&&p.children().first().trigger("focus")})).on("keydown.jhsCoverButton",".jhs-card-menu [role='menuitem']",(h=>{let u=$(h.currentTarget).closest(".jhs-card-menu"),p=u.find("[role='menuitem']"),g=p.index(h.currentTarget);if(h.key==="Escape")return h.preventDefault(),this.closeCardMenus(!0);if(!["ArrowDown","ArrowUp","Home","End"].includes(h.key))return;h.preventDefault();let m=h.key==="Home"?0:h.key==="End"?p.length-1:h.key==="ArrowDown"?(g+1)%p.length:(g-1+p.length)%p.length;p.eq(m).trigger("focus")})).on("click.jhsCoverButton",(h=>{$(h.target).closest(".more-tools-container").length||this.closeCardMenus()})),s.on("click.jhsCoverButton",".videoSvg",(h=>{h.preventDefault(),$('.videoSvg[title!="播放视频"]').each(((g,m)=>{let f=$(m),v=f.closest(".item"),b=v.find("img"),{carNum:w}=t.findCarNumAndHref(v);this.showImg(f,b,w),f.html(this.videoSvg).attr({title:"播放视频","aria-label":"播放视频"})}));let u=$(h.target).closest(".item"),p=u.find(".videoSvg");if(p.attr("title")==="播放视频"){p.html(this.recoveryVideoSvg).attr({title:"切回封面","aria-label":"切回封面"});let{carNum:g}=t.findCarNumAndHref(u),m=u.find("img");if(!m.length)return void show.error("没有找到图片");this.showVideo(p,m,g).catch((f=>clog.error("卡片预览视频打开失败",f)))}})),s.on("click.jhsCoverButton",".screenSvg",(async h=>{h.preventDefault();let u=loading();try{let p=$(h.currentTarget).closest(".item"),{carNum:g}=t.findCarNumAndHref(p);g=g.replace("FC2-","");let m=this.getOptionalDependency("ScreenShotPlugin");if(!m)throw new Error("剧照功能已禁用");let f=await m.getScreenshot(g,{allowWhenDisabled:!0});u.close(),globalThis.showImageViewer(f)}catch(p){clog.error("图片预览出错:",p),show.error("图片预览出错:"+p)}finally{u.close()}})),s.on("click.jhsCoverButton",".filterBtn, .favoriteBtn, .hasDownBtn, .hasWatchBtn",(h=>{h.preventDefault(),h.stopPropagation();try{let u=$(h.currentTarget),p=u.closest(".item"),{carNum:g,url:m,publishTime:f,fc2Source:v}=t.findCarNumAndHref(p),b=d(async w=>{try{let S=await t.parseActressName(m),j=Ce(w);if(!j)throw new Error("不支持的状态操作");await this.getRuntimeService("state").patch(g,{[j]:!0},{type:"list-card-state",record:{carNum:g,url:m,names:S,publishTime:f,fc2Source:v}}),show.ok("操作成功")}catch(S){clog.error("保存操作失败:",S),show.error("操作失败")}},"r");u.hasClass("filterBtn")?utils.q(h,`是否屏蔽${T(g)}?`,(()=>b(ce))):u.hasClass("favoriteBtn")?b(ue):u.hasClass("hasDownBtn")?b(pe):u.hasClass("hasWatchBtn")&&b(me),this.closeCardMenus()}catch(u){clog.error("按钮点击处理失败:",u)}}));let a=this.getRuntimeService("settings").snapshot(),r=this.getRuntimeService("movie"),i=r.externalSiteOrigin("missAvBtn",a),n=r.externalSiteOrigin("jableBtn",a),l=r.externalSiteOrigin("avgleBtn",a),c=r.providerOrigin("av123")||"";$(this.getSelector().itemSelector).each(((h,u)=>{let p=$(u),{carNum:g}=t.findCarNumAndHref(p);p.find(".site-jable").attr({href:`${n}/search/${g}/`,target:"_blank",rel:"noopener noreferrer"}),p.find(".site-avgle").attr({href:`${l}/vod/search.html?wd=${g}`,target:"_blank",rel:"noopener noreferrer"}),p.find(".site-miss-av").attr({href:`${i}/search/${g}`,target:"_blank",rel:"noopener noreferrer"}),p.find(".site-123-av").attr({href:`${c}/cn/search?keyword=${encodeURIComponent(g)}`,target:"_blank",rel:"noopener noreferrer"})})),s.on("click.jhsCoverButton",".site-jable, .site-avgle, .site-miss-av, .site-123-av",(h=>{try{h.preventDefault(),h.stopPropagation();let u=$(h.currentTarget),p=u.closest(".item"),{carNum:g}=t.findCarNumAndHref(p),m=null;if(u.hasClass("site-jable")?m=`${n}/search/${g}/`:u.hasClass("site-avgle")?m=`${l}/vod/search.html?wd=${g}`:u.hasClass("site-miss-av")?m=`${i}/search/${g}`:u.hasClass("site-123-av")&&(m=`${c}/cn/search?keyword=${encodeURIComponent(g)}`),!m)return;h.ctrlKey||h.metaKey?GM_openInTab(m,{insert:0}):window.open(m),this.closeCardMenus()}catch(u){clog.error("站点按钮处理失败:",u)}})),s.on("click.jhsCoverButton",".titleSvg, .carNumSvg, .downSvg",(h=>{h.preventDefault(),h.stopPropagation();let u=$(h.currentTarget).closest(".item"),{carNum:p,title:g}=t.findCarNumAndHref(u),m=u.find(B?".photo-frame img":".cover img");$(h.currentTarget).hasClass("titleSvg")?utils.copyToClipboard("标题",g):$(h.currentTarget).hasClass("carNumSvg")?utils.copyToClipboard("番号",p):$(h.currentTarget).hasClass("downSvg")&&fetch(m.attr("src")).then((f=>f.blob())).then((f=>utils.download(f,p+" "+g+".jpg"))),this.closeCardMenus()}))}showImg(e,t,s){e.html(this.videoSvg).attr({title:"播放视频","aria-label":"播放视频"});let a=$(`#${`${s}_preview_video`}`);a.length>0&&(a[0].pause(),a.parent().hide()),t.show(),t.removeClass("loading"),t.next(".loading-spinner").remove()}async showVideo(e,t,s){let a=this.getRuntimeService("settings").snapshot();if(!ma(a))return show.error("预览视频已关闭");let r=this.previewGeneration,i=`${s}_preview_video`,n=$(`#${i}`);if(n.length>0)return n.parent().show(),await de(n[0],{context:"列表卡片预览",notify:!0}),void t.hide();t.addClass("loading"),t.after('
      ');let l=t.attr("data-full")||t.attr("src"),c=await this.getRuntimeService("scope")(),{sources:h,error:u}=await fa(s,this.getRuntimeService("storage"),this.getRuntimeService("movie"),c,a);if(r!==this.previewGeneration||!Re(this.getRuntimeService("settings").snapshot()))return void this.showImg(e,t,s);if(!h)return show.error(u?.code==="REGION_BLOCKED"?u.message:"未解析到视频"),void this.showImg(e,t,s);let p=this.getRuntimeService("settings").snapshot().videoQuality;p=zt(Object.keys(h),p);let g=h[p],m=document.createElement("div"),f=document.createElement("video");B||(m.className="jhs-layout-d543acf8"),f.src=g,f.poster=l||"",f.id=i,f.controls=!0,f.loop=!0,f.muted=!0,f.playsInline=!0,f.className="jhs-layout-a38a0e50",m.appendChild(f),t.parent().append(m),t.hide(),t.removeClass("loading"),t.next(".loading-spinner").remove(),n=$(f);let v=n[0];v.load(),v.muted=!1,await de(v,{context:"列表卡片预览",notify:!0,message:u?.code==="REGION_BLOCKED"?u.message:"当前视频源无法播放"}),n.trigger("focus")}};d(sn,"CoverButtonPlugin");var ba=sn;var an=class an extends I{constructor(){super(...arguments),this.previewGeneration=0,this.previewSession=null}getName(){return"PreviewVideoPlugin"}async initCss(){return".jhs-dmm-preview-player{display:none;width:100%;height:auto}.jhs-dmm-preview-player.is-active{display:block}.jhs-native-preview-hidden{display:none!important}"}async handle(){if(!isDetailPage)return;let e=this.getRuntimeService("settings");if(this.lifecycleScope||(this.lifecycleScope=await this.getRuntimeService("scope")()),!this._settingsListenerBound){this._settingsListenerBound=!0;let t=d(s=>{s.detail?.names?.some(r=>r==="enablePreviewVideo"||r==="enableLoadPreviewVideo")&&this.reconfigure()},"onSettingsChanged");e.addEventListener("settings.changed",t),this.lifecycleScope.addCleanup((()=>{e.removeEventListener("settings.changed",t),this._settingsListenerBound=!1,this.unmountPreview()}))}this.reconfigure()}reconfigure(){this.previewGeneration++;let e=this.getRuntimeService("settings").snapshot();if(!$c(e))return void this.unmountPreview();this.mountPreview(),Ft(e)?this.initDmm(this.lifecycleScope).catch((t=>clog.error("预加载 DMM 失败",t))):(this.unmountDmmPlayer(),$(".fancybox-content #preview-video").length&&!$("#video-bottom-toolbar").length&&this.handleVideo().catch(t=>clog.error("恢复原生预览操作失败",t)))}mountPreview(){if(this._previewMounted)return;this._previewMounted=!0,$(".preview-video-container").removeClass("jhs-native-preview-hidden");let e=$(".preview-video-container"),t=d(()=>{this.cancelOpenWait?.(),this.cancelOpenWait=utils.loopDetector((()=>$(".fancybox-content #preview-video").length>0),(()=>{this.handleVideo().catch((a=>clog.error("预览视频处理失败",a)))}),20,1e4,!0,this.lifecycleScope)},"openVideo");e.off("click.jhsVideo").on("click.jhsVideo",t),this.lifecycleScope.addCleanup((()=>e.off("click.jhsVideo",t)));let s=window.location.href;(s.includes("gallery-1")||s.includes("gallery-2"))&&t(),s.includes("autoPlay=1")&&e.length>0&&e[0].click()}unmountDmmPlayer(){this.dmmRequestScope?.dispose(),$("[data-jhs-dmm-trigger]").remove();let e=$("#jhs-preview-video"),t=e[0],s=this.previewSession?.native;s&&t&&this.isSessionOpen(this.previewSession)&&(this.seekVideo(s,t.currentTime),!t.paused&&Re(this.getRuntimeService("settings").snapshot())?de(s,{context:"恢复原生预览",notify:!1}).then(()=>{this.previewSession?.native!==s&&s.pause()}):s.pause()),t&&(t.pause(),e.removeAttr("src"),t.load(),e.remove()),$("#video-bottom-toolbar .jhs-video-quality-list").empty(),$("#preview-video").removeClass("jhs-native-preview-hidden"),this.dmmPreviewPromise=null,this.previewSession&&!s&&this.disposePreviewSession()}unmountPreview(){this._previewMounted=!1,this.cancelOpenWait?.(),this.disposePreviewSession(),this.unmountDmmPlayer(),$("#video-bottom-toolbar").remove(),$(".preview-video-container").addClass("jhs-native-preview-hidden")}unmountJhsPreview(){this.disposePreviewSession(),$("[data-jhs-dmm-trigger]").remove();let e=$("#jhs-preview-video"),t=e[0];t&&(t.pause(),e.removeAttr("src"),t.load(),e.remove()),$("#video-bottom-toolbar").remove(),$("#preview-video").removeClass("jhs-native-preview-hidden"),$(".preview-video-container").addClass("jhs-native-preview-hidden")}async initDmm(e){let t=this.previewGeneration,s=this.getRuntimeService("settings");try{let{sources:a}=await this.getDmmPreview(e);if(t!==this.previewGeneration||e?.disposed||!Re(s.snapshot())||!ds(s.snapshot())||!a)return;if($(".fancybox-content #preview-video").length){await this.handleVideo();return}if($("#preview-video")[0])return;clog.debug("JavDB没有视频播放元素, 开始创建...");let n=$(".column-video-cover img").attr("src");if($("[data-jhs-dmm-trigger]").length)return;let l=$('');l.append($('').attr("src",n||"")),$(".preview-images").first().prepend(l),l.on("click.jhsVideo",()=>this.openDmmDialog())}catch(a){clog.error("预加载 DMM 失败:",a)}}getDmmPreview(e=this.lifecycleScope){if(this.dmmPreviewPromise)return this.dmmPreviewPromise;let t=new te("javdb-dmm-request");this.dmmRequestScope=t;let s,a=Promise.resolve(e||this.getRuntimeService("scope")()).then(r=>{if(r?.disposed||t.disposed)throw new Error("预览请求已取消");return s=r?.addCleanup?.(()=>t.dispose()),Xi(this.getPageInfo().carNum,this.getRuntimeService("storage"),this.getRuntimeService("movie"),t)}).then((r=>(this.dmmPreviewPromise===a&&(r.error?.retryable||r.error?.code==="HTTP_ERROR")&&(this.dmmPreviewPromise=null),r)),(r=>{throw this.dmmPreviewPromise===a&&(this.dmmPreviewPromise=null),r})).finally(()=>{t.dispose(),typeof s=="function"&&s()});return this.dmmPreviewPromise=a,a}createDmmPlayer(e){let t=e.length?e.parent():$(this.previewSession?.host),s=t.find("#jhs-preview-video");if(s.length)return s;let a=$('');return t.append(a),a}isSessionOpen(e){if(!e||e.scope.disposed||!e.host.isConnected||e.native&&!e.host.contains(e.native))return!1;for(let t=e.host;t;t=t.parentElement)if(t.getAttribute("aria-hidden")==="true"||getComputedStyle(t).display==="none")return!1;return!0}seekVideo(e,t){let s=d(()=>{try{e.currentTime=Math.max(0,Math.min(t||0,Number.isFinite(e.duration)?e.duration:1/0))}catch{}},"seek");s();let a=this.previewSession;if(a?.seekCleanups?.get(e)?.(),!e.readyState&&a){a.seekCleanups||(a.seekCleanups=new Map);let r=d(()=>{l(),this.isSessionOpen(a)&&s()},"loaded"),i=d(()=>l(),"failed"),n=setTimeout(i,5e3),l=a.scope.addCleanup(()=>{clearTimeout(n),e.removeEventListener("loadedmetadata",r),e.removeEventListener("error",i),a.seekCleanups.delete(e)});e.addEventListener("loadedmetadata",r,{once:!0}),e.addEventListener("error",i,{once:!0}),a.seekCleanups.set(e,l)}}disposePreviewSession(){let e=this.previewSession;if(this.previewSession=null,!e)return;this.dmmRequestScope?.dispose(),this.dmmPreviewPromise=null,e.scope.dispose(),$(e.host).find("#video-bottom-toolbar").remove();let t=e.host.querySelector("#jhs-preview-video");t&&(t.pause(),t.removeAttribute("src"),t.load(),t.remove()),e.native?.classList.remove("jhs-native-preview-hidden"),e.native?.pause(),e.dialogId!=null&&this.getRuntimeService("dialog").close(e.dialogId)}openDmmDialog(){if(!Ft(this.getRuntimeService("settings").snapshot())||this.previewSession)return;let e=$('
      ');this.getRuntimeService("dialog").open({type:1,title:"预告片",ui:{body:"media"},content:e,area:utils.getDialogArea("lg"),success:d((t,s)=>{this.handleVideo(e[0],s).catch(a=>clog.error("预览失败",a))},"success"),end:d(()=>{this.previewSession?.host===e[0]&&this.disposePreviewSession()},"end")})}waitForDmmReady(e){let t=this.previewSession?.scope.signal;return t?.aborted||e.error?Promise.resolve(!1):e.readyState>=3?Promise.resolve(!0):new Promise(s=>{let a=d(l=>{clearTimeout(n),e.removeEventListener("canplay",r),e.removeEventListener("error",i),t?.removeEventListener("abort",i),s(l)},"finish"),r=d(()=>a(!0),"loaded"),i=d(()=>a(!1),"failed"),n=setTimeout(i,1e4);e.addEventListener("canplay",r,{once:!0}),e.addEventListener("error",i,{once:!0}),t?.addEventListener("abort",i,{once:!0})})}async restoreNativePlayer(e,t,s=!1,a=!0){if(!t||!this.isSessionOpen(this.previewSession))return!1;let r=e.parent().find("#jhs-preview-video"),i=r[0];return i&&(i.pause(),r.removeAttr("src"),i.load(),r.remove()),e.removeClass("jhs-native-preview-hidden"),a?de(t,{context:"JavDB 原生预览回退",notify:s}):(t.pause(),!0)}async handleVideo(e=null,t=null){let s=$(".fancybox-content #preview-video"),a=e||s[0]?.closest(".fancybox-content");if(!a||!Re(this.getRuntimeService("settings").snapshot())||getComputedStyle(a).display==="none")return;if(this.previewSession?.host!==a){this.disposePreviewSession();let L=new te("javdb-preview");this.previewSession={host:a,native:s[0]||null,scope:L,dialogId:t},L.observe(document.body,()=>{this.previewSession?.host===a&&!this.isSessionOpen(this.previewSession)&&this.disposePreviewSession()},{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class","style","aria-hidden"]})}let r=this.previewSession;if(r.generation===this.previewGeneration)return;r.generation=this.previewGeneration;let i=d(()=>this.previewSession===r&&this.isSessionOpen(r)&&u===this.previewGeneration&&Re(this.getRuntimeService("settings").snapshot()),"alive"),n=this.getRuntimeService("settings"),l=$(a),c=s[0],h=n.snapshot().videoMuted,u=this.previewGeneration,p=ds(this.getRuntimeService("settings").snapshot()),g=p?await this.getDmmPreview():{sources:null,error:null};if(!i())return;let{sources:m,error:f}=g,v=$("
      ").attr("id","video-bottom-toolbar").addClass("jhs-video-toolbar"),b=$("
      ").addClass("jhs-video-quality-list").attr({role:"group","aria-label":"视频画质"});l.find("#video-bottom-toolbar").remove();let w=!1,S=null,j=null;if(m){let L=this.getRuntimeService("settings").snapshot().videoQuality,N=zt(Object.keys(m),L),A=m[N],O=c?.currentTime||0,U=!c||!c.paused;S=this.createDmmPlayer(s),j=S[0],j.muted=h==null||h===!0,S.off("volumechange.jhsVideo").on("volumechange.jhsVideo",(()=>{n.set("videoMuted",j.muted).catch(Q=>clog.error("保存视频静音设置失败",Q))})),S.attr("src",A),j.load(),this.seekVideo(j,O),S.addClass("is-active");let q=await this.waitForDmmReady(j);if(!i()){j.pause();return}if(w=q&&(!U||await de(j,{context:"JavDB 高画质预览",notify:!1})),!i()){j.pause();return}if(q&&!w&&!j.muted&&(j.muted=!0,w=await de(j,{context:"JavDB 高画质预览静音重试",notify:!1})),!i()){j.pause();return}if(w?(c?.pause(),s.addClass("jhs-native-preview-hidden")):(S.removeClass("is-active"),await this.restoreNativePlayer(s,c,!0,U)),!i())return;if(!w&&!c){show.error("当前视频源无法播放"),this.disposePreviewSession();return}w&&rt.forEach((Q=>{let se=m[Q.quality];if(!se)return;let ge=w&&N===Q.quality;b.append($('').toggleClass("active",ge).attr({"data-quality":Q.quality,"data-video-src":se,"aria-pressed":String(ge)}).text(Q.text))}))}v.append(b);let k=$("
      ").addClass("jhs-toolbar");if(this.getOptionalDependency("DetailPageButtonPlugin")&&k.append(Mt({actions:["blocked","favorite"],ids:{blocked:"video-filterBtn",favorite:"video-favoriteBtn"}})),k.append(''),!i())return;v.append(k),l.append(v),v.off("click.jhsVideo").on("click.jhsVideo",".jhs-video-quality-btn",(async L=>{let N=$(L.currentTarget);if(!N.hasClass("active"))try{if(!j?.isConnected||!i())return;let A=j.currentTime,O=S.attr("src"),U=!j.paused;S.attr("src",N.data("video-src")),j.load(),this.seekVideo(j,A);let q=await this.waitForDmmReady(j);if(!i())return;let Q=q&&(!U||await de(j,{context:"JavDB 画质切换",notify:!1}));if(!i())return;if(Q)v.find(".jhs-video-quality-btn").removeClass("active").attr("aria-pressed","false"),N.addClass("active").attr("aria-pressed","true");else{O&&(S.attr("src",O),j.load(),j.currentTime=A);let se=O&&await this.waitForDmmReady(j)&&(!U||await de(j,{context:"JavDB 画质切换回退",notify:!1}));if(!i())return;se||await this.restoreNativePlayer(s,c,!0,U)}}catch(A){clog.error("切换画质失败:",A)}})),$("#speed-btn").off("click.jhsVideo").on("click.jhsVideo",(()=>{let L=l.find("#jhs-preview-video.is-active")[0]||c;L?.isConnected&&this.isSessionOpen(r)&&this.seekVideo(L,L.currentTime+10)})),v.off("contextmenu.jhsVideo").on("contextmenu.jhsVideo","#speed-btn",(L=>(L.preventDefault(),this.getOptionalDependency("DetailPageButtonPlugin")?.filterOne?.(L)))),$("#video-filterBtn").off("click.jhsVideo").on("click.jhsVideo",(L=>this.getOptionalDependency("DetailPageButtonPlugin")?.filterOne?.(L))),$("#video-favoriteBtn").off("click.jhsVideo").on("click.jhsVideo",(L=>this.getOptionalDependency("DetailPageButtonPlugin")?.favoriteOne?.(L)));let _=this.getOptionalDependency("DetailPageButtonPlugin"),R=_?.getDetailStateController?.();if(R){v.find("#video-filterBtn,#video-favoriteBtn").off("click.jhsVideo");let L=R.bind({root:v[0],closeRoot:document.documentElement,carNum:this.getPageInfo().carNum,layerIndex:utils.getOwningLayerIndex({root:document.documentElement}),getRecord:d(()=>_.getStateRecord(),"getRecord"),selectors:{blocked:"#video-filterBtn",favorite:"#video-favoriteBtn"}});r.stateCleanup?.(),r.stateCleanup=V?.on("car-state-changed",N=>{if(N.carNums?.includes(L.carNum)&&this.isSessionOpen(r))return R.render(L)}),r.stateCleanup&&r.scope.addCleanup(r.stateCleanup)}}};d(an,"PreviewVideoPlugin");var wa=an;function Tc(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelectorAll=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelectorAll=="function")return e;throw new TypeError("JavStore document is invalid")}d(Tc,"resolveDocument");function hs(o,e="https://javstore.net"){if(!o)return null;try{let t=new URL(String(o),e),s=t.hostname.toLowerCase();return["http:","https:"].includes(t.protocol)?(t.protocol==="http:"&&(s==="javstore.net"||s.endsWith(".javstore.net"))&&(t.protocol="https:"),t.href):null}catch{return null}}d(hs,"normalizeJavStoreAssetUrl");function Ac(o,e,t="https://javstore.net"){let s=ee(e);if(!s)return[];if(typeof o?.find=="function"){let a=globalThis.jQuery??globalThis.$??o.constructor;return o.find('a[href$="-pn.html"]').filter(((r,i)=>a(i).text().trim().toUpperCase().includes(s.toUpperCase()))).map(((r,i)=>new URL(a(i).attr("href"),t).href)).get()}return[...Tc(o).querySelectorAll('a[href$="-pn.html"]')].filter(a=>a.textContent?.trim().toUpperCase().includes(s.toUpperCase())).map(a=>new URL(a.getAttribute("href")||"",t).href)}d(Ac,"parseJavStoreSearch");function Pc(o,e){if(typeof o?.find=="function"){let a=globalThis.jQuery??globalThis.$??o.constructor,i=o.find("a").filter(((l,c)=>a(c).text().trim()==="CLICK HERE!")).first().attr("href");if(!i)return null;let n=hs(i,e);return n?n.replace(".th",""):null}let t=[...Tc(o).querySelectorAll("a")].find(a=>a.textContent?.trim()==="CLICK HERE!")?.getAttribute("href");if(!t)return null;let s=hs(t,e);return s?s.replace(".th",""):null}d(Pc,"parseJavStorePreview");var rn=class rn extends I{getName(){return"ScreenShotPlugin"}getScreenshotService(){return this.getRuntimeService("screenshot")}getSettingsSnapshot(){return this.getRuntimeService("settings")?.snapshot?.()??{}}async initCss(){return""}async handle(){if(!isDetailPage)return;let e=this.getRuntimeService("settings"),t=await this.getRuntimeService("scope")(),s=d(a=>{a.detail?.names?.includes("enableLoadScreenShot")&&(e.snapshot().enableLoadScreenShot==="no"?this.unmountHosted():this.loadScreenShot().catch(i=>clog.error("长缩略图重新加载失败",i)))},"onSettingsChanged");e.addEventListener("settings.changed",s),t.addCleanup((()=>e.removeEventListener("settings.changed",s))),this.loadScreenShot().catch(a=>clog.error("长缩略图加载失败",a))}unmountHosted(){$(".screen-container, .jhs-screenshot-providers").remove()}async loadScreenShot(){if(!isDetailPage||!this.getScreenshotService().isEnabled(this.getSettingsSnapshot()))return;let t=this.getPageInfo().carNum;M&&$(".preview-images .tile-item").first().before('
      正在加载缩略图
      '),B&&$("#sample-waterfall .sample-box:first").after('
      正在加载缩略图
      ');try{let s=await this.getScreenshot(t);s?(this.addImg("缩略图",s),clog.log("加载缩略图:",s)):this.showErrorFallback(t,null)}catch(s){this.showErrorFallback(t,s)}}async getScreenshot(e){if(e=C(e),!e)throw clog.warn("跳过缩略图解析:番号不可用"),new Error("缩略图番号不可用");let t=arguments[1]||{},s=this.getScreenshotService(),a=this.getSettingsSnapshot();if(!t.allowWhenDisabled&&!s.isEnabled(a))return clog.warn("长缩略图功能已关闭,跳过请求"),null;let r=await this.getRuntimeService("scope")(),i=await s.resolve({carNum:e},{scope:r,settings:a,allowWhenDisabled:t.allowWhenDisabled===!0});return(Array.isArray(i)?i[0]:i)?.url||null}addImg(e,t){let s=hs(t);if(!s)return;let a=$(".screen-container").empty(),r=$("").attr({src:s,alt:e,loading:"lazy"});M&&a.append(r.addClass("jhs-layout-cad980f4")),B&&a.append($('
      ').append(r.attr("title",e).addClass("jhs-layout-d4a575e8"))),a.on("click",(i=>{i.stopPropagation(),i.preventDefault(),globalThis.showImageViewer(i.currentTarget)}))}showErrorFallback(e,t){let s=t instanceof Error?t.message:"";t&&clog.error("获取缩略图失败:",s.substring(0,100));let a=`jhs-screenshot-message${B?" jhs-screenshot-message--bus":""}`,r=C(e);if(!r)return void $(".screen-container").empty().append($("
      ").addClass(a).text("无法获取番号,缩略图未加载"));let i=this.getScreenshotService().getSearchUrl({carNum:r}),n=$(".screen-container").empty(),l=$("
      ").addClass(a).text(t instanceof Error?"获取缩略图失败":"暂无缩略图结果"),c=$('点击重试');n.append(l,$("
      "),c),i&&n.append(document.createTextNode(" 或 "),$('前往确认').attr("href",i)),n.off("click",".retry-link").off("click",".check-link").on("click",".retry-link",(async h=>{h.stopPropagation(),h.preventDefault(),n.empty().append($("
      ").addClass(a).text("正在重新加载..."));try{let u=await this.getScreenshot(r);u?this.addImg("缩略图",u):this.showErrorFallback(r,null)}catch(u){this.showErrorFallback(r,u)}})).on("click",".check-link",(h=>{h.stopPropagation(),h.preventDefault(),window.open(i,"_blank")}))}async loadInto(e,t,{isActive:s=d(()=>!0,"isActive")}={}){let a=$(e);if(!a.length||!this.getScreenshotService().isEnabled(this.getSettingsSnapshot()))return a.empty(),null;let r=await this.getRuntimeService("scope")();return ta({target:a,carNum:t,screenshot:this.getScreenshotService(),settings:this.getSettingsSnapshot(),scope:r,isActive:s})}renderInto(e,t,s){let a=$(e),r=$("").attr({src:hs(t),alt:s,loading:"lazy"}).addClass("jhs-fc2-gallery__image"),i=$('').attr("aria-label",`查看${s}大图`).append(r);a.empty().append(i).off("click.jhsScreenshot").on("click.jhsScreenshot",".jhs-fc2-screenshot-thumbnail",(n=>{n.preventDefault(),n.stopPropagation(),globalThis.showImageViewer(r[0])}))}};d(rn,"ScreenShotPlugin");var ya=rn;var Rc="jhs_img_cdn_index";function Vh(o,e,t,s=Date.now()){let a=new Map;for(let r of o)if(Array.isArray(r.newVideoList))for(let i of r.newVideoList){let n=typeof i=="object"?i:{},l=C(typeof i=="string"?i:i.carNum);if(!l)continue;let c=a.get(l)||{carNum:l,coverUrl:"",title:"",publishTime:"",actresses:[],starIds:[],categories:new Set,score:0,voteCount:0,url:"",isVr:!1};c.coverUrl||(c.coverUrl=n.coverUrl||""),c.title||(c.title=n.title||""),c.publishTime=[c.publishTime,n.publishTime||""].sort().at(-1),c.score=Math.max(c.score,Number(n.score)||0),c.voteCount=Math.max(c.voteCount,Number(n.voteCount)||0),c.url||(c.url=n.url||""),c.isVr||(c.isVr=n.isVr===!0||/(^|[^A-Z])VR([^A-Z]|$)/i.test(`${n.title||""} ${(n.tags||[]).join?.(" ")||""} ${(n.categories||[]).join?.(" ")||""}`)),r.name&&!c.actresses.includes(r.name)&&c.actresses.push(r.name),r.starId&&!c.starIds.includes(r.starId)&&c.starIds.push(r.starId),r.actressType&&c.categories.add(r.actressType),a.set(l,c)}return[...a.values()].map((r=>{let i=e.get(r.carNum),n=H(i?.stateFlags),l=t[r.carNum]||null,c=l?l.action==="snoozed"&&l.until&&Date.parse(l.until)<=s?"pending":l.action:"pending";return{...r,actressName:r.actresses.join("、"),starId:r.starIds[0]||"",categories:[...r.categories],flags:n,decision:l,decisionState:c}}))}d(Vh,"aggregateNewVideoRecords");var nn=class nn extends I{constructor(){super(...arguments),P(this,"currentPage",1),P(this,"pageSize",30),P(this,"nvCurrentPage",1),P(this,"nvPageSize",60),P(this,"nvFlatListCache",[]),P(this,"nvAllItemsMap",new Map),P(this,"nvActressesCache",[]),P(this,"nvCarMapCache",new Map),P(this,"nvSortBy","publishTime_desc"),P(this,"nvSelected",new Set),P(this,"nvDecisionsCache",{}),P(this,"nvCoverCache",new Map),P(this,"nvActorCoverRequests",new Map),P(this,"nvRenderGeneration",0),P(this,"nvSearchDebounced",null),P(this,"nvInvalidationTimer",null),P(this,"nvWorkspaceReloadPromise",null),P(this,"nvWorkspaceReloadDirty",!1),P(this,"nvWorkspaceMounted",!1),P(this,"nvEventUnsubscribe",null),P(this,"taskStatusUnsubscribe",null),P(this,"nvCoverPreview",null),P(this,"nvWorkspaceRoot",null),P(this,"nvJavDbUrl",""),P(this,"nvRuleTime",8760),P(this,"avatarSources",[]),P(this,"avatarSourceIndex",0),P(this,"nvWorkspaceFullReloadRequested",!1),P(this,"nvPendingRemovals",new Set),P(this,"nvRemovingCards",new Set)}getName(){return"NewVideoPlugin"}getStartupMode(){return"idle"}async initCss(){return` - `}async handle(){this.initializeLocalState(),this.nvEventUnsubscribe||(this.nvEventUnsubscribe=V.on("new-video-changed",(()=>this.scheduleWorkspaceReload()))),this.taskStatusUnsubscribe||(this.taskStatusUnsubscribe=V.on("task-status-changed",(()=>this.isWorkspaceMounted()&&this.renderTaskStatuses()))),await this.showNewVideoCount()}initializeLocalState(){this.avatarSources=this.getRuntimeService("actressInfo").getAvatarSources();let e=parseInt(this.getRuntimeService("storage").getLocal(Pc)||"0",10);this.avatarSourceIndex=Number.isInteger(e)&&e>=0&&e0}scheduleWorkspaceReload(){this.nvWorkspaceReloadDirty=!0,this.nvInvalidationTimer||(this.nvInvalidationTimer=setTimeout((()=>{this.nvInvalidationTimer=null,this.flushWorkspaceReload()}),0))}async flushWorkspaceReload(){return this.nvWorkspaceReloadPromise?this.nvWorkspaceReloadPromise:(this.nvWorkspaceReloadPromise=(async()=>{do this.nvWorkspaceReloadDirty=!1,await this.showNewVideoCount(),this.isWorkspaceMounted()&&await this.reloadNewVideoWorkspaceData({preservePage:!0});while(this.nvWorkspaceReloadDirty)})().catch((e=>clog.error("新作品数据刷新失败",e))).finally((()=>{this.nvWorkspaceReloadPromise=null})),this.nvWorkspaceReloadPromise)}getPendingNewVideoCount(e,t){return Array.isArray(e?.newVideoList)?new Set(e.newVideoList.map((s=>T(typeof s=="string"?s:s.carNum))).filter((s=>s&&!t.has(s)&&!this.isDecisionHidden(s)))).size:0}isDecisionHidden(e){let t=this.nvDecisionsCache[T(e)];return t?["ignored","dismissed"].includes(t.action)||t.action==="snoozed"&&(!t.until||Date.parse(t.until)>Date.now()):!1}async getPendingNewVideoTotal(){let e=await storageManager.getCarMap(),t=new Set;return this.nvDecisionsCache=await this.getRuntimeService("state").getNewVideoDecisions(),(await storageManager.getFavoriteActressList()).forEach((s=>Array.isArray(s.newVideoList)&&s.newVideoList.forEach((a=>{let r=T(typeof a=="string"?a:a.carNum);r&&!oe(q(e.get(r)?.stateFlags))&&!this.isDecisionHidden(r)&&t.add(r)})))),t.size}async showNewVideoCount(){let e=await this.getPendingNewVideoTotal();$("#newVideoCount").text(`${e}`)}async resetBtnTip(){let e=this.getRuntimeService("storage"),t=this.getOptionalDependency("TaskPlugin"),s=await storageManager.getSetting(),a=t?e.getLocal(t.lastCheckFavoriteActressTimeKey)||"无":"任务已禁用",r=s.checkFavoriteActress_IntervalTime,i=t?e.getLocal(t.lastCheckNewVideoTimeKey)||"无":"任务已禁用",n=s.checkNewVideo_intervalTime;$("#checkFavoriteActress").attr("data-tip",`上次完整同步: ${a}; 检测间隔时间: ${r}小时`),$("#checkNewVideo").attr("data-tip",`上次整批检测: ${i}; 检测间隔时间: ${n}小时`)}async openDialog(){let e=this.getRuntimeService("storage");this.cleanupNewVideoWorkspace(),this._viewMode=e.getLocal("jhs_newVideoViewMode")==="list"?"list":"actress",this.currentPage=1,this.nvCurrentPage=1,this.nvSelected=new Set,this.nvCoverCache=new Map,this.nvActorCoverRequests=new Map,this.nvRenderGeneration++;let t=this.getOptionalDependency("TaskPlugin"),s=await storageManager.getSetting(),a=t?e.getLocal(t.lastCheckFavoriteActressTimeKey)||"无":"任务已禁用",r=s.checkFavoriteActress_IntervalTime,i=t?e.getLocal(t.lastCheckNewVideoTimeKey)||"无":"任务已禁用",n=s.checkNewVideo_intervalTime,l=` + `}async handle(){this.initializeLocalState(),this.nvEventUnsubscribe||(this.nvEventUnsubscribe=V.on("new-video-changed",(e=>this.scheduleWorkspaceReload(e)))),this.taskStatusUnsubscribe||(this.taskStatusUnsubscribe=V.on("task-status-changed",(()=>this.isWorkspaceMounted()&&this.renderTaskStatuses()))),await this.showNewVideoCount()}initializeLocalState(){this.avatarSources=this.getRuntimeService("actressInfo").getAvatarSources();let e=parseInt(this.getRuntimeService("storage").getLocal(Rc)||"0",10);this.avatarSourceIndex=Number.isInteger(e)&&e>=0&&e0}scheduleWorkspaceReload(e={}){let t=Array.isArray(e?.carNums)?e.carNums.map(C).filter(Boolean):[];["browse","state-handled","manual"].includes(e?.reason)&&t.length?t.forEach(s=>this.nvPendingRemovals.add(s)):this.nvWorkspaceFullReloadRequested=!0,this.nvWorkspaceReloadDirty=!0,this.nvInvalidationTimer||(this.nvInvalidationTimer=setTimeout((()=>{this.nvInvalidationTimer=null,this.flushWorkspaceReload()}),0))}async flushWorkspaceReload(){return this.nvWorkspaceReloadPromise?this.nvWorkspaceReloadPromise:(this.nvWorkspaceReloadPromise=(async()=>{do{let e=this.nvWorkspaceFullReloadRequested,t=new Set(this.nvPendingRemovals);this.nvWorkspaceFullReloadRequested=!1,this.nvPendingRemovals.clear(),this.nvWorkspaceReloadDirty=!1,await this.showNewVideoCount(),this.isWorkspaceMounted()&&(!e&&t.size&&this._viewMode==="list"&&$("#nv-grid").length?await this.applyNewVideoRemovals(t):await this.reloadNewVideoWorkspaceData({preservePage:!0}))}while(this.nvWorkspaceReloadDirty)})().catch((e=>clog.error("新作品数据刷新失败",e))).finally((()=>{this.nvWorkspaceReloadPromise=null})),this.nvWorkspaceReloadPromise)}async applyNewVideoRemovals(e){if(this.nvWorkspaceFullReloadRequested)return;let t=this.nvRenderGeneration,s=$("#new-video-list-container"),a=s[0],r=s.find(".nv-card").filter((l,c)=>e.has(C($(c).attr("data-car"))));e.forEach(l=>{this.nvAllItemsMap.delete(l),this.nvSelected.delete(l)}),this.nvFlatListCache=this.nvFlatListCache.filter(l=>!e.has(C(l.carNum))),this.nvCurrentPageItems=(this.nvCurrentPageItems||[]).filter(l=>!e.has(C(l.carNum))),this.nvActressesCache=this.nvActressesCache.map(l=>Array.isArray(l.newVideoList)?{...l,newVideoList:l.newVideoList.filter(c=>!e.has(C(typeof c=="string"?c:c?.carNum)))}:l),this.nvCoverPreview?.currentTarget&&r.toArray().some(l=>l.contains(this.nvCoverPreview.currentTarget))&&this.nvCoverPreview.hidePreview();let i=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches?0:180;r.each((l,c)=>this.nvRemovingCards.add(c));try{await Promise.all(r.toArray().map(l=>new Promise(c=>{$(l).animate({opacity:0},i,c)})))}finally{r.each((l,c)=>this.nvRemovingCards.delete(c))}if(!this.isWorkspaceMounted()||t!==this.nvRenderGeneration||a!==$("#new-video-list-container")[0]||this.nvWorkspaceFullReloadRequested)return;let n=s.add(s.parentsUntil(this.nvWorkspaceRoot||".newVideoToolBox")).add(this.nvWorkspaceRoot||s.closest(".newVideoToolBox")).map((l,c)=>({element:c,top:c.scrollTop,left:c.scrollLeft})).get();await this.renderNewVideoList({incremental:!0}),this.isWorkspaceMounted()&&t===this.nvRenderGeneration&&a===$("#new-video-list-container")[0]&&n.forEach(({element:l,top:c,left:h})=>{l.scrollTop=c,l.scrollLeft=h})}getPendingNewVideoCount(e,t){return Array.isArray(e?.newVideoList)?new Set(e.newVideoList.map((s=>C(typeof s=="string"?s:s.carNum))).filter((s=>s&&!t.has(s)&&!this.isDecisionHidden(s)))).size:0}isDecisionHidden(e){let t=this.nvDecisionsCache[C(e)];return t?["ignored","dismissed"].includes(t.action)||t.action==="snoozed"&&(!t.until||Date.parse(t.until)>Date.now()):!1}async getPendingNewVideoTotal(){let e=await storageManager.getCarMap(),t=new Set;return this.nvDecisionsCache=await this.getRuntimeService("state").getNewVideoDecisions(),(await storageManager.getFavoriteActressList()).forEach((s=>Array.isArray(s.newVideoList)&&s.newVideoList.forEach((a=>{let r=C(typeof a=="string"?a:a.carNum);r&&!oe(H(e.get(r)?.stateFlags))&&!this.isDecisionHidden(r)&&t.add(r)})))),t.size}async showNewVideoCount(){let e=await this.getPendingNewVideoTotal();$("#newVideoCount").text(`${e}`)}async resetBtnTip(){let e=this.getRuntimeService("storage"),t=this.getOptionalDependency("TaskPlugin"),s=await storageManager.getSetting(),a=t?e.getLocal(t.lastCheckFavoriteActressTimeKey)||"无":"任务已禁用",r=s.checkFavoriteActress_IntervalTime,i=t?e.getLocal(t.lastCheckNewVideoTimeKey)||"无":"任务已禁用",n=s.checkNewVideo_intervalTime;$("#checkFavoriteActress").attr("data-tip",`上次完整同步: ${a}; 检测间隔时间: ${r}小时`),$("#checkNewVideo").attr("data-tip",`上次整批检测: ${i}; 检测间隔时间: ${n}小时`)}async openDialog(){let e=this.getRuntimeService("storage");this.cleanupNewVideoWorkspace(),this._viewMode=e.getLocal("jhs_newVideoViewMode")==="list"?"list":"actress",this.currentPage=1,this.nvCurrentPage=1,this.nvSelected=new Set,this.nvCoverCache=new Map,this.nvActorCoverRequests=new Map,this.nvRenderGeneration++;let t=this.getOptionalDependency("TaskPlugin"),s=await storageManager.getSetting(),a=t?e.getLocal(t.lastCheckFavoriteActressTimeKey)||"无":"任务已禁用",r=s.checkFavoriteActress_IntervalTime,i=t?e.getLocal(t.lastCheckNewVideoTimeKey)||"无":"任务已禁用",n=s.checkNewVideo_intervalTime,l=`
      `;this.getRuntimeService("dialog").open({type:1,title:'新作品检测',content:l,scrollbar:!1,ui:{size:"workspace",body:"scroll"},area:utils.getDialogArea("workspace"),anim:-1,success:d(async(c,h)=>{this.nvWorkspaceMounted=!0,this.nvWorkspaceRoot=c,K.enhance(c),this.bindClick(),this.applyViewMode(),this.renderTaskStatuses(),await this.reloadNewVideoWorkspaceData(),utils.setupEscClose(h)},"success"),end:d(()=>this.cleanupNewVideoWorkspace(),"end")})}cleanupNewVideoWorkspace(){clearTimeout(this.nvInvalidationTimer),this.nvInvalidationTimer=null,this.nvWorkspaceReloadDirty=!1,this.nvWorkspaceFullReloadRequested=!1,this.nvPendingRemovals.clear(),this.nvSearchDebounced?.cancel?.(),this.nvSearchDebounced=null,this.nvWorkspaceMounted=!1,this.nvWorkspaceRoot=null,this.nvRenderGeneration++,this.nvSelected.clear(),this.nvCoverCache=new Map,this.nvActorCoverRequests=new Map,this.nvCoverPreview?.destroy?.(),this.nvCoverPreview=null,this.nvAllItemsMap.clear(),this.nvFlatListCache=[],this.nvActressesCache=[],this.nvCarMapCache=new Map,this.nvDecisionsCache={},this.nvCurrentPageItems=[],$(Array.from(this.nvRemovingCards)).stop(!0,!0),this.nvRemovingCards.clear()}bindClick(){let e=this.getOptionalDependency("TaskPlugin");e||$("#checkFavoriteActress,#checkNewVideo").prop("disabled",!0).attr("title","后台任务功能已禁用"),$("#reLoad").on("click",(()=>{this.reloadNewVideoWorkspaceData(),$("#checkNewVideoMsg").text("")})),$("#new-video-list-container").on("click",".nv-card__link",(async t=>{let s=$(t.currentTarget).closest(".nv-card").attr("data-car");if(s)try{if(await storageManager.getSetting("autoRemoveNewVideoMarkAfterBrowse",ne)!==E)return;await this.getRuntimeService("state").removeFromNewVideoList([s],"browse")}catch(a){clog.error("移除新作品标记失败:",a)}})),$("#toSetting").on("click",(t=>{this.getOptionalDependency("SettingPlugin")?.openSettingDialog?.("task-panel",(()=>{$("#setting-checkFavoriteActress").css({border:"1px solid var(--jhs-status-filter)"}),$("#setting-checkNewVideo").css({border:"1px solid var(--jhs-status-filter)"})}))})),$("#checkFavoriteActress").on("click",(t=>{this.runManualTask($(t.currentTarget),"同步中…",(async()=>{if(!$('a[href*="/users/profile"]').length)return void show.error("未登录 JavDB,同步失败");await e?.checkFavoriteActress?.(!0)}))})),$("#checkNewVideo").on("click",(t=>{this.runManualTask($(t.currentTarget),"检测中…",(()=>e?.checkNewVideo?.(!0)))})),$("#paramActressType").on("change",(t=>{this.currentPage=1,this.nvRenderGeneration++,this._viewMode==="actress"&&this.renderActressCards()})),$("#paramSortBy").on("change",(t=>{this.currentPage=1,this.nvRenderGeneration++,this._viewMode==="actress"&&this.renderActressCards()})),$("#nvSortBy").on("change",(t=>{this.nvSortBy=$("#nvSortBy").val(),this.nvCurrentPage=1,this.nvRenderGeneration++,this.renderNewVideoList()})),$("#nvCategoryFilter,#nvStateFilter,#nvDecisionFilter").on("change",(t=>{this.nvCurrentPage=1,this.nvRenderGeneration++,this._viewMode==="list"&&this.renderNewVideoList()})),this.nvSearchDebounced=utils.debounce((()=>{this.nvCurrentPage=1,this.nvRenderGeneration++,this._viewMode==="list"&&this.renderNewVideoList()}),200),$("#nvSearch").on("input",this.nvSearchDebounced),$(".jhs-new-video-view").on("click",'[role="tab"]',(t=>{this.setViewMode($(t.currentTarget).data("view"))})).on("keydown",'[role="tab"]',(t=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;t.preventDefault();let s=$(t.delegateTarget).find('[role="tab"]'),a=s.index(t.currentTarget),r=t.key==="Home"?0:t.key==="End"?s.length-1:t.key==="ArrowRight"?(a+1)%s.length:(a-1+s.length)%s.length;s.eq(r).trigger("click").trigger("focus")})),this.bindBatchActions()}async runManualTask(e,t,s){if(e.attr("aria-busy")==="true")return;let a=this.getOptionalDependency("TaskPlugin");if(!a)return void show.info("后台任务功能已禁用");let r=e.find("span").last(),i=r.text();e.attr("aria-busy","true").prop("disabled",!0),r.text(t);try{await navigator.locks.request(a.singleTaskKey,{ifAvailable:!0},(async n=>{if(!n)return void show.error("后台任务正在运行,请稍后再试");await s()}))}catch(n){clog.error("手动任务执行失败",n),a.isNetworkBlocked(n)&&show.error(n.message||"任务执行失败")}finally{e.removeAttr("aria-busy").prop("disabled",!1),r.text(i),this.renderTaskStatuses()}}setViewMode(e){!["actress","list"].includes(e)||e===this._viewMode||(this._viewMode=e,this.getRuntimeService("storage").setLocal("jhs_newVideoViewMode",e),e==="list"?this.nvCurrentPage=1:this.currentPage=1,this.nvRenderGeneration++,this.applyViewMode(),this.renderCurrentView())}applyViewMode(){let e=this._viewMode==="list";$("#nv-pagination-bar").toggle(e),$("#actress-card-container").toggle(!e),$("#actress-pagination").toggle(!e),$("#new-video-list-container").toggle(e),$("#new-video-list-footer").toggle(e),K.setVisible("#paramSortBy",!e),K.setVisible("#nvSortBy",e),K.setVisible("#paramActressType",!e),K.setVisible("#nvCategoryFilter",e),K.setVisible("#nvStateFilter",e),K.setVisible("#nvDecisionFilter",e),$("#nvSearch").toggleClass("jhs-is-hidden",!e),$(".jhs-new-video-view [role='tab']").each(((t,s)=>{let a=$(s).data("view")===this._viewMode;$(s).attr({"aria-selected":String(a),tabindex:a?"0":"-1"}).toggleClass("active",a)}))}renderCurrentView(){return this._viewMode==="list"?this.renderNewVideoList():this.renderActressCards()}loadData(){return this.currentPage=1,this.reloadNewVideoWorkspaceData()}async reloadNewVideoWorkspaceData({preservePage:e=!1}={}){if(!this.isWorkspaceMounted())return;let t=++this.nvRenderGeneration,s=this._viewMode==="list"?$("#new-video-list-container"):$("#actress-card-container");$("#nv-pagination-bar").remove(),Ue(s,{type:"loading",title:"加载中"});try{let a=await storageManager.getSetting(),[r,i,n,l]=await Promise.all([storageManager.getFavoriteActressList(),storageManager.getCarMap(),this.getRuntimeService("state").getNewVideoDecisions(),storageManager.getSetting("checkNewVideo_ruleTime",8760)]),c=this.getRuntimeService("movie").externalSiteOrigin("javDbBtn",a);if(!this.isWorkspaceMounted()||t!==this.nvRenderGeneration)return;this.nvActressesCache=r,this.nvCarMapCache=i,this.nvDecisionsCache=n,this.nvJavDbUrl=c,this.nvRuleTime=ae(l,8760,{min:0});let h=Vh(r,i,n),u=new Map;h.forEach((p=>u.set(C(p.carNum),{...p,carNum:C(p.carNum)}))),this.nvAllItemsMap=u,this.pruneNewVideoSelection(),e||(this.currentPage=1,this.nvCurrentPage=1),await this.renderCurrentView(),this.renderTaskStatuses()}catch(a){if(t!==this.nvRenderGeneration||!this.isWorkspaceMounted())return;clog.error("加载新作品工作区失败",a),Ue(s,{type:"error",title:"加载失败",description:a.message||String(a),actionLabel:"重试",onAction:d(()=>this.reloadNewVideoWorkspaceData({preservePage:!0}),"onAction")})}}renderTaskStatuses(){let e=$("#jhs-task-status-list");if(!e.length)return;let t=this.getOptionalDependency("TaskPlugin"),s={favoriteActress:"演员同步",newVideo:"新作品",blacklist:"黑名单"},a={idle:"正常",running:"运行中",pending:"等待下一次任务检查",due:"待运行"},r=d(i=>i?new Date(i).toLocaleString():"无","format");if(!t)return void e.empty().text("后台任务功能已禁用");e.empty(),["favoriteActress","newVideo","blacklist"].forEach((i=>{let n=t.getTaskStatusSnapshot(i),l=$('
      ');l.append($('').text(`${s[i]}:${a[n.state]}`)),l.append($('').text(`上次完成 ${r(n.completedAt)};下次检查 ${n.nextAt?r(n.nextAt):"立即"}`)),e.append(l)}))}async renderActressCards(){let e=$("#actress-card-container");if(!e.length)return;let t=[...this.nvActressesCache],s=$("#paramActressType").val();s!=="all"&&(t=t.filter((j=>j.actressType===s)));let a=this.nvCarMapCache,r=d(j=>this.getPendingNewVideoCount(j,a),"_newVideoCount"),i=$("#paramSortBy").val(),n={lastPublishTime_desc:[{key:"lastPublishTime",order:"desc"}],lastPublishTime_asc:[{key:"lastPublishTime",order:"asc"}],lastCheckTime_desc:[{key:"lastCheckTime",order:"desc"}],lastCheckTime_asc:[{key:"lastCheckTime",order:"asc"}],newVideoCount_desc:[{key:r,order:"desc"}],newVideoCount_asc:[{key:r,order:"asc"}]},l=[{key:r,order:"desc"},{key:"lastPublishTime",order:"desc"}],c=utils.genericSort(t,n[i]||l),h=c.length,u=Math.ceil(h/this.pageSize),p=(this.currentPage-1)*this.pageSize,g=p+this.pageSize;u>0&&this.currentPage>u&&(this.currentPage=u);let m=(this.currentPage-1)*this.pageSize,f=c.slice(m,m+this.pageSize),v=this.nvJavDbUrl,b=this.getOptionalDependency("TaskPlugin"),w=this.nvRuleTime;if(f.length===0)return Ue(e,{type:"empty",title:this.nvActressesCache.length?"没有符合当前筛选条件的演员":"暂无收藏演员"}),void this.renderPagination(h,u);let S=f.map((j=>{let k=Array.isArray(j.allName)?j.allName.join(","):"",x=String(j.name||""),_=String(j.remark||""),R=String(j.starId||""),L=this.getPendingNewVideoCount(j,a),N=j.lastPublishTime||"",A=Ye(`/actors/${encodeURIComponent(R)}?t=d`,v),O=Ye(j.avatar,v)||this.getRuntimeService("actressInfo").placeholderUrl("javdb"),U=mt(N,w),q="未知",Q="is-unknown";j.actressType===Ke?(q="无码",Q="is-uncensored"):j.actressType===Je&&(q="有码",Q="is-censored");let se=String(N||"暂无记录"),ge=U?`停更 ${w/24/365} 年以上,下轮任务不再检测`:_||"暂无备注",De=$('
      ').toggleClass("is-paused",U).attr("data-starId",R),lt=$('
      ');lt.append($('').attr("data-tip",`最新作品数量: ${L}`).text(`${L} 新`),$('').addClass(Q).text(q)),U&<.append('停更');let Ne=$('').attr("href",A||"#"),z=$("").append($('').text(x),$('').attr("title",k).text(k||"暂无别名"));Ne.append($('').attr({src:O,alt:k}),z);let Z=$('
      ').append($('
      最近作品
      ').append($("
      ").attr("title",se).text(se)),$('
      上次检测
      ').append($("
      ").text(String(j.lastCheckTime||"暂无记录")))),re=$('
      '),xt=$('').attr("data-starId",R).prepend(this.checkSvg),ps=$('').attr({"aria-label":`取消收藏 ${x}`,"data-starId":R}).append(this.deleteSvg),ye=$('').attr("data-starId",R).prepend(this.editSvg);return re.append(xt,ps,$('
      •••
      ').find(".actress-card__menu-popover").append(ye).end()),De.append(lt,Ne,Z,$('

      ').attr("title",ge).text(ge),re)[0]}));e.empty().append(S),$(".btn-delete-actress").off("click").on("click",(j=>{j.preventDefault();let k=$(j.currentTarget).attr("data-starId"),x=c.find((_=>_.starId===k));utils.q(j,`是否取消收藏 ${T(x.name)}?`,(async()=>{let _=this.getRuntimeService("movie").externalSiteOrigin("javDbBtn",await storageManager.getSetting()),R=document.querySelector("meta[name=csrf-token]").content,L=await this.getRuntimeService("actressInfo").uncollect("javdb",{actorId:k,baseUrl:_,csrfToken:R},{scope:await this.getRuntimeService("scope")()});L.success?(await storageManager.removeFavoriteActress(k),await V.emit("new-video-changed",{reason:"favorite-actress-removed"})):(show.error("移除失败"),clog.error("移除失败,返回值:",L))}))})),$(".btn-edit-actress").off("click").on("click",(j=>{j.preventDefault();let k=$(j.currentTarget).attr("data-starId"),x=c.find((_=>_.starId===k));x?this.editActress(x):show.error(`未找到 starId 为 ${k} 的女优记录。`)})),$(".btn-check-actress").off("click").on("click",(j=>{j.preventDefault();let k=$(j.currentTarget),x=k.attr("data-starId"),_=c.find((R=>R.starId===x));this.runManualTask(k,"检测中…",(()=>b?.checkOneNewVideo?.(_)))})),$(".actress-card__menu").on("keydown",(j=>{if(j.key!=="Escape")return;j.preventDefault(),$(j.currentTarget).prop("open",!1).find("summary").trigger("focus")})).on("click","[role='menuitem']",(j=>{$(j.currentTarget).closest("details").prop("open",!1)})),this.renderPagination(h,u)}async getNewVideoFlatList(){let e=$("#nvCategoryFilter").val()||"all",t=$("#nvStateFilter").val()||"pending",s=$("#nvDecisionFilter").val()||"pending",a=String($("#nvSearch").val()||"").trim().toUpperCase();return[...this.nvAllItemsMap.values()].filter((r=>{let i=e==="all"||e==="vr"?e==="all"||r.isVr:e==="unknown"?r.categories.length===0:r.categories.includes(e),n=t==="all"||t==="pending"?t==="all"||!oe(r.flags):!!r.flags[t],l=s==="all"||r.decisionState===s,c=!a||`${r.carNum} ${r.title} ${r.actressName}`.toUpperCase().includes(a);return i&&n&&l&&c})).sort(((r,i)=>(i.publishTime||"").localeCompare(r.publishTime||"")))}getActorCoverRequest(e,t){let s=t.get(e);if(s)return s;let a=this.getRuntimeService("scope")().then((r=>this.getRuntimeService("actressInfo").movies("javdb",{actorId:e,baseUrl:this.nvJavDbUrl},{scope:r}))).then((r=>{let i=new Map;return r.forEach((n=>n.carNum&&n.coverUrl&&i.set(C(n.carNum),{coverUrl:n.coverUrl,title:n.title}))),i})).finally((()=>{t.get(e)===a&&t.delete(e)}));return t.set(e,a),a}async loadCoverForItems(e,t=this.nvRenderGeneration){return this.hydrateVisibleCovers(e,t)}async hydrateVisibleCovers(e,t){let s=this.nvCoverCache,a=this.nvActorCoverRequests,r=[...new Set(e.filter((i=>!i.coverUrl&&!s.has(C(i.carNum))&&i.starId)).map((i=>i.starId)))];await Ae(r,3,(async i=>{try{let n=await this.getActorCoverRequest(i,a);if(t!==this.nvRenderGeneration||s!==this.nvCoverCache||!this.isWorkspaceMounted())return;n.forEach(((l,c)=>{s.set(C(c),l.coverUrl);let h=$(".nv-card").filter(((p,g)=>C($(g).attr("data-car"))===C(c)));if(!h.length)return;let u=$('').attr({src:l.coverUrl,"data-full":l.coverUrl}).on("error",(function(){$(this).addClass("jhs-is-hidden").siblings(".nv-card__empty").removeClass("jhs-is-hidden")}));h.find(".nv-placeholder").replaceWith(u),h.find(".nv-card__empty").addClass("jhs-is-hidden"),l.title&&h.attr("title",l.title)}))}catch(n){clog.warn(`获取演员封面失败: ${i}`,n)}}))}pruneNewVideoSelection(){for(let e of[...this.nvSelected])this.nvAllItemsMap.has(e)||this.nvSelected.delete(e)}async renderNewVideoList({incremental:e=!1}={}){let t=$("#new-video-list-container"),s=this.nvRenderGeneration;if(!t.length)return;let a=await this.getNewVideoFlatList();if(s!==this.nvRenderGeneration||!this.isWorkspaceMounted())return;this.pruneNewVideoSelection(),e||$("#nv-pagination-bar").remove(),this.nvFlatListCache=a,this.nvSortBy=$("#nvSortBy").val()||this.nvSortBy;let r=Math.ceil(a.length/this.nvPageSize);if(this.nvCurrentPage=r?Math.min(this.nvCurrentPage,r):1,!a.length){this.nvCurrentPageItems=[],$("#nv-pagination-bar").remove();let i=String($("#nvSearch").val()||"").trim(),n=["nvCategoryFilter","nvStateFilter","nvDecisionFilter"].some((l=>$("#"+l).val()!==(l==="nvCategoryFilter"?"all":"pending")));return this.nvAllItemsMap.size?i?Ue(t,{type:"empty",title:`没有找到“${i}”的作品`,actionLabel:"清除搜索",onAction:d(()=>{$("#nvSearch").val(""),this.nvCurrentPage=1,this.nvRenderGeneration++,this.renderNewVideoList()},"onAction")}):n?Ue(t,{type:"empty",title:"没有符合当前筛选条件的作品",actionLabel:"清除筛选",onAction:d(()=>{K.setValue("#nvCategoryFilter","all",!1),K.setValue("#nvStateFilter","pending",!1),K.setValue("#nvDecisionFilter","pending",!1),this.nvCurrentPage=1,this.nvRenderGeneration++,this.renderNewVideoList()},"onAction")}):Ue(t,{type:"empty",title:"暂无待处理的新作品"}):Ue(t,{type:"empty",title:"暂无新作品记录"}),void this.renderBatchBar()}this.nvRenderPage(s,{incremental:e}),this.renderBatchBar()}selectedItems(){return[...this.nvSelected].map((e=>this.nvAllItemsMap.get(C(e)))).filter(Boolean)}applyProcessedSelection(e){(e?.changed||[]).map(C).filter(Boolean).forEach((t=>this.nvSelected.delete(t))),this.renderBatchBar()}async runBatchMutation(e,t){let s=this.selectedItems();if(!s.length)return void show.info("请先选择作品");try{let a=await e(s);this.applyProcessedSelection(a),a?.changed?.length?show.ok(`${t} ${a.changed.length} 个番号`):show.info("没有需要更新的项目")}catch(a){clog.error("批量操作失败",a),show.error(`批量操作失败: ${a.message||a}`)}}bindBatchActions(){$("#new-video-list-footer").off(".jhsNvBatch").on("click.jhsNvBatch","#nvSelectPage",(()=>{(this.nvCurrentPageItems||[]).forEach((t=>this.nvSelected.add(C(t.carNum)))),$("#new-video-list-container .nv-select").prop("checked",!0),this.renderBatchBar()})).on("click.jhsNvBatch","#nvClearSelection",(()=>{this.nvSelected.clear(),$("#new-video-list-container .nv-select").prop("checked",!1),this.renderBatchBar()})).on("click.jhsNvBatch","#batchMarkFavorite,#batchMarkWatched,#batchMarkDownloaded",(t=>{let s={batchMarkFavorite:"favorite",batchMarkWatched:"watched",batchMarkDownloaded:"downloaded"}[t.currentTarget.id];this.runBatchMutation((a=>this.getRuntimeService("state").patch(a.map((r=>r.carNum)),{[s]:!0},{type:"new-video-batch-state",records:a.map((r=>({carNum:r.carNum,url:r.url||`/search?q=${encodeURIComponent(r.carNum)}`,names:r.actressName,publishTime:r.publishTime})))})),"已处理")})).on("click.jhsNvBatch","#batchIgnore",(()=>{this.runBatchMutation((t=>this.getRuntimeService("state").setNewVideoDecision(t.map((s=>s.carNum)),"ignored")),"已忽略")})).on("click.jhsNvBatch","#batchSnooze",(()=>{this.runBatchMutation((t=>this.getRuntimeService("state").setNewVideoDecision(t.map((s=>s.carNum)),"snoozed",new Date(Date.now()+7*864e5).toISOString())),"已暂缓")})).on("click.jhsNvBatch","#batchRestore",(()=>{this.runBatchMutation((t=>this.getRuntimeService("state").setNewVideoDecision(t.map((s=>s.carNum)),null)),"已恢复")})).on("click.jhsNvBatch","#batchRemoveFromNewVideo",(t=>{let s=this.selectedItems();s.length&&utils.q(t,`确认将 ${s.length} 个作品从新作列表移除?
      不会删除作品状态记录。`,(()=>{this.runBatchMutation((a=>this.getRuntimeService("state").removeFromNewVideoList(a.map((r=>r.carNum)),"manual")),"已移除")}))}))}renderBatchBar(){let e=$("#new-video-list-footer");if(!e.length)return;let t=new Set(this.nvFlatListCache.flatMap((r=>r.actresses||[r.actressName])).filter(Boolean)),s=this.nvSelected.size,a=this.nvFlatListCache.filter((r=>this.nvSelected.has(C(r.carNum)))).length;if(!s)return void e.html(`
      共 ${this.nvFlatListCache.length} 个番号,涉及 ${t.size} 位演员
      `);e.html(`
      已选择 ${s} 项${a!==s?`,当前结果中 ${a} 项`:""}
      更多 ▾
      `)}nvSortList(e){let t=this.nvSortBy||"publishTime_desc",[s,a]=t.split("_");return e.slice().sort(((r,i)=>{let n=0;switch(s){case"publishTime":n=(r.publishTime||"").localeCompare(i.publishTime||"");break;case"actress":n=(r.actressName||"").localeCompare(i.actressName||"");break;case"carNum":n=(r.carNum||"").localeCompare(i.carNum||"");break;case"voteCount":n=(r.voteCount||0)-(i.voteCount||0);break}return a==="desc"?-n:n}))}nvCardHtml(e){let t=this.nvJavDbUrl,s="",a=C(e.carNum),r=T(a),i=T(e.title||a),n=this.nvCoverCache.get(a),l=T((n||e.coverUrl||"").replace("thumbs","covers")),c=T(e.url||`${t}/search?q=${encodeURIComponent(a)}`),h=`番号: ${r}\\n演员: ${T(e.actressName)}\\n发行: ${T(String(e.publishTime||"未知"))}`;e.voteCount&&(h+=`\\n评价人数: ${e.voteCount}`);let u=e.voteCount?`${e.voteCount}人评价`:"";return s+=`",s}nvRenderPage(e=this.nvRenderGeneration,{incremental:t=!1}={}){if(e!==this.nvRenderGeneration)return;this.pruneNewVideoSelection();let s=this.nvFlatListCache;if(!s||s.length===0)return void this.renderNewVideoList();let a=this.nvSortList(s),r=this.nvPageSize,i=Math.ceil(a.length/r);this.nvCurrentPage=Math.max(1,Math.min(this.nvCurrentPage,i));let n=(this.nvCurrentPage-1)*r,l=n+r,c=a.slice(n,l);this.nvCurrentPageItems=c,$("#nv-pagination-bar").remove();let h=$("#new-video-list-container"),u=h.find("#nv-grid");t=t&&u.length>0;let p=t?new Map(u.children(".nv-card").toArray().map(b=>[C($(b).attr("data-car")),b])):new Map,g=$(document.activeElement).closest(".nv-card")[0],m=u.children(".nv-card").index(g),f="";f+='
      ';for(let b of c)(!t||!p.has(C(b.carNum)))&&(f+=this.nvCardHtml(b));if(f+="
      ",i>1){f+='
      ',this.nvCurrentPage>1&&(f+=``);let b=Math.max(1,this.nvCurrentPage-2),w=Math.min(i,b+4);w-b<4&&(b=Math.max(1,w-4));for(let S=b;S<=w;S++)f+=``;this.nvCurrentPage下一页`),f+=`第 ${this.nvCurrentPage}/${i} 页,共 ${a.length} 条`,f+="
      "}let v;if(t){let b=$(f),w=b.filter("#nv-grid").children(".nv-card"),S=new Set(c.map(x=>C(x.carNum))),j=new Map(w.toArray().map(x=>[C($(x).attr("data-car")),x]));u.children(".nv-card").filter((x,_)=>!S.has(C($(_).attr("data-car")))).remove();let k=u[0].firstElementChild;for(let x of c){let _=C(x.carNum),R=p.get(_)||j.get(_);R===k?k=k.nextElementSibling:u[0].insertBefore(R,k),$(R).find(".nv-select").prop("checked",this.nvSelected.has(_))}h.append(b.filter("#nv-pagination-bar")),v=w,m>=0&&!S.has(C($(g).attr("data-car")))&&u.children(".nv-card").eq(Math.min(m,c.length-1)).find(".nv-card__link")[0]?.focus({preventScroll:!0})}else h.html(f),v=h.find(".nv-card");v.find(".nv-cover-img").on("error",(function(){$(this).addClass("jhs-is-hidden").siblings(".nv-card__empty").removeClass("jhs-is-hidden")})),v.find(".nv-select").on("change",(b=>{let w=C(b.currentTarget.value);b.currentTarget.checked?this.nvSelected.add(w):this.nvSelected.delete(w),this.renderBatchBar()})),h.find(".pagination-btn").off("click").on("click",(b=>{let w=parseInt($(b.currentTarget).data("nvpage"));w>=1&&w<=i&&w!==this.nvCurrentPage&&(this.nvCurrentPage=w,this.nvRenderGeneration++,this.nvRenderPage(this.nvRenderGeneration),this.renderBatchBar(),h.scrollTop(0))})),h.find("#nv-pagination-bar").insertAfter(h),this.nvCoverPreview??(this.nvCoverPreview=new window.ImageHoverPreview({selector:".nv-cover-img",dataAttribute:"data-full",owner:this.nvWorkspaceRoot,resolveOwner:d(()=>this.nvWorkspaceRoot,"resolveOwner"),zIndexStrategy:"owner"})),this.hydrateVisibleCovers(c,e)}async editActress(e){let t=this.getRuntimeService("dialog"),s=null,a=String(e.name||""),r=Ye(e.avatar,this.nvJavDbUrl)||"",i=String(e.remark||""),n=Array.isArray(e.allName)?e.allName.join(","):"",l=Array.isArray(e.newVideoList)?e.newVideoList.map((g=>typeof g=="string"?g:g.carNum)).join(","):"",c=String(e.starId||""),h=e.actressType||"",u=d(g=>T(String(g||"")),"safe"),p=`
      Avatar Preview${u(i)}
      - `;t.open({type:1,title:`编辑女优: ${u(a)} (${u(c)})`,ui:{size:"sm",body:"scroll"},area:utils.getDialogArea("sm"),content:p,btn:["保存","取消"],success:d((g,m)=>{s=$(g),this._editActressRoot=s,K.enhance(g);let f=d(w=>{w.css("height","auto"),w.css("height",w[0].scrollHeight+15+"px")},"n");s.find("#edit-actress-avatar").on("input",(function(){let w=$(this).val();s.find("#edit-avatar-preview").attr("src",w)}));let v=s.find("#edit-actress-allname");v.on("input",(function(){f($(this))})),f(v);let b=s.find("#edit-actress-newvideolist");b.on("input",(function(){f($(this))})),f(b),s.find("#search-avatar-btn").on("click",(async()=>{await this.searchAvatar()})),s.find("#select-cdn-btn").on("click",(async()=>{await(async()=>{let w=this.avatarSourceIndex,S=this.avatarSources.map(((x,k)=>` -
      `),t=M?$(this.getSelector().boxSelector).first():$(".masonry").first();if(!t.length)return void clog.warn("JHS 页面工具栏未创建:列表容器尚未就绪");t.before(e),this.collectCommandControls(e)}getCarNum(){try{return this.getRuntimeService("host").readMovieRef?.()?.carNum||null}catch(e){clog.debug("移动端详情番号解析失败,已回退",e)}return null}createMenu(){let e=d((m,f,v="")=>``,"item"),t=d(m=>`
      ${m}
      `,"group"),s='',a=!!this.getOptionalDependency("ListPageButtonPlugin"),r=!!this.getOptionalDependency("ListPagePlugin"),i=!!this.getOptionalDependency("NewVideoPlugin"),n=!!this.getOptionalDependency("BlacklistPlugin"),l=!!this.getOptionalDependency("SettingPlugin"),c=!!this.getOptionalDependency("DetailPageButtonPlugin"),h=!!this.getOptionalDependency("HighlightMagnetPlugin"),u=!!this.getOptionalDependency("MagnetHubPlugin"),p=!!this.getOptionalDependency("HistoryPlugin"),g;if(window.isListPage){let m=this.getOptionalDependency("ListPageButtonPlugin")?.activeSortMethod?.()??this.getRuntimeService("settings").snapshot().sortMethod,f={default:"默认",rateCount:"评价人数",date:"时间"},v=typeof m=="string"&&m in f?m:"default",b=f[v],w=_e(this.getOptionalDependency("ListPagePlugin")?.activeQuickFilter),S=[...nt,...It].map(((k,x)=>`${x===nt.length?'':""}`)).join(""),j=Object.entries(f).map((([k,x])=>``)).join("");g=t((a?e("check","开始鉴定"):"")+(i?e("newVideo","新作品"):"")+(n?e("blacklist","黑名单"):"")+(p?e("history","鉴定记录"):"")+(a?e("sort",`排序: ${b}`,'aria-haspopup="menu" aria-expanded="false"'):"")+(r?e("quickFilter",`筛选:${Pe[w]}`,'aria-haspopup="menu" aria-expanded="false"'):""))+s+t(e("logger","运行日志")+(l?e("setting","设置"):""))+(r?``:"")+(a?``:"")}else window.isDetailPage?g=t(c?[{action:"filter",icon:Le,label:"屏蔽",key:"filter"},{action:"fav",icon:Me,label:"收藏",key:"fav"},{action:"down",icon:fe,label:"已下载",key:"down"},{action:"watch",icon:ve,label:"已观看",key:"watch"}].map((f=>e(f.action,`${f.icon}`,`aria-label="${f.label}" aria-pressed="false" data-label="${f.label}"`))).join(""):"")+s+t((h?e("magnetFilter","磁力过滤"):"")+(u?e("magnet","磁力搜索"):"")+(c?e("subtitle","字幕"):""))+s+t(e("logger","运行日志")+(l?e("setting","设置"):"")):g=t(e("logger","运行日志")+(l?e("setting","设置"):""));return $(``)}async refreshDetailStatus(){try{let e=this.getCarNum();if(!e)return;let t=await storageManager.getCar(e),s=$(".jhs-fab-menu"),a={filter:"var(--jhs-status-filter)",fav:"var(--jhs-status-fav)",down:"var(--jhs-status-down)",watch:"var(--jhs-status-watch)"},r=H(t?.stateFlags),i=new Set;r.blocked&&i.add("filter"),r.favorite&&i.add("fav"),r.downloaded&&i.add("down"),r.watched&&i.add("watch"),s.find(".jhs-fab-status-dot").each(((n,l)=>{let c=String($(l).data("status-key")||""),h=$(l).closest(".jhs-fab-menu-item");i.has(c)?($(l).css({background:a[c]||"var(--jhs-border-strong)"}),h.attr("aria-pressed","true")):($(l).css({background:"var(--jhs-border-strong)"}),h.attr("aria-pressed","false"))}))}catch(e){clog.warn("移动端详情状态刷新失败",e)}}bindEvents(e,t){let s=$(".jhs-fab-menu"),a=s.find(".jhs-mobile-filter-menu"),r=s.find(".jhs-mobile-sort-menu"),i=s.find('[data-action="quickFilter"]'),n=s.find('[data-action="sort"]'),l=d((p=!1)=>{s.removeClass("jhs-fab-filter-open"),i.attr("aria-expanded","false"),p&&i.trigger("focus")},"closeFilterMenu"),c=d((p=!1)=>{s.removeClass("jhs-fab-sort-open"),n.attr("aria-expanded","false"),p&&n.trigger("focus")},"closeSortMenu"),h=d((p=!1)=>{this._fabGeneration++,l(),c(),e.removeClass("jhs-fab-open").attr("aria-expanded","false"),s.removeClass("jhs-fab-menu-open").attr("aria-hidden","true"),t.removeClass("jhs-fab-backdrop-visible"),s.find(".jhs-fab-menu-item").removeClass("jhs-fab-item-visible"),p&&e.trigger("focus")},"closeMenu"),u=d(()=>{if(e.hasClass("jhs-fab-open"))h();else{if(e.addClass("jhs-fab-open").attr("aria-expanded","true"),s.addClass("jhs-fab-menu-open").attr("aria-hidden","false"),t.addClass("jhs-fab-backdrop-visible"),window.isListPage){let v=this.getOptionalDependency("ListPageButtonPlugin")?.activeSortMethod?.()??this.getRuntimeService("settings").snapshot().sortMethod,b={default:"默认",rateCount:"评价人数",date:"时间"},w=typeof v=="string"&&v in b?v:"default",S=b[w];s.find('[data-action="sort"]').text(`排序: ${S}`),this.getOptionalDependency("ListPagePlugin")?.syncQuickFilterUi?.()}window.isDetailPage&&this.refreshDetailStatus().catch((v=>clog.warn("移动端详情状态刷新失败",v)));let g=++this._fabGeneration,m=this,f=s.find(".jhs-fab-menu-item");f.first().trigger("focus"),f.each(((v,b)=>{let w=$(b);setTimeout(()=>{g===m._fabGeneration&&w.addClass("jhs-fab-item-visible")},30+v*35)}))}},"toggleMenu");e.on("click",u),t.on("click",(()=>h(!0))),s.on("keydown",".jhs-fab-menu-item",(p=>{let g=s.find(".jhs-fab-menu-item"),m=g.index(p.currentTarget);if(p.key==="Escape")return p.preventDefault(),h(!0);if(!["ArrowDown","ArrowUp","Home","End"].includes(p.key))return;p.preventDefault();let f=p.key==="Home"?0:p.key==="End"?g.length-1:p.key==="ArrowDown"?(m+1)%g.length:(m-1+g.length)%g.length;g.eq(f).trigger("focus")})),a.on("keydown",".jhs-mobile-filter-option",(p=>{let g=a.find(".jhs-mobile-filter-option"),m=g.index(p.currentTarget);if(p.key==="Escape")return p.preventDefault(),l(!0);if(!["ArrowDown","ArrowUp","Home","End"].includes(p.key))return;p.preventDefault();let f=p.key==="Home"?0:p.key==="End"?g.length-1:p.key==="ArrowDown"?(m+1)%g.length:(m-1+g.length)%g.length;g.eq(f).trigger("focus")})).on("click",".jhs-mobile-filter-option",(p=>{p.stopPropagation(),this.getOptionalDependency("ListPagePlugin")?.setQuickFilter?.($(p.currentTarget).data("jhs-filter")),h(!0)})),r.on("keydown",".jhs-mobile-sort-option",(p=>{let g=r.find(".jhs-mobile-sort-option"),m=g.index(p.currentTarget);if(p.key==="Escape")return p.preventDefault(),c(!0);if(!["ArrowDown","ArrowUp","Home","End"].includes(p.key))return;p.preventDefault();let f=p.key==="Home"?0:p.key==="End"?g.length-1:p.key==="ArrowDown"?(m+1)%g.length:(m-1+g.length)%g.length;g.eq(f).trigger("focus")})).on("click",".jhs-mobile-sort-option",(async p=>{p.stopPropagation();let g=$(p.currentTarget).data("jhs-sort"),m=r.find('.jhs-mobile-sort-option[aria-checked="true"]').first();r.find(".jhs-mobile-sort-option").attr("aria-checked","false"),$(p.currentTarget).attr("aria-checked","true");try{await this.getOptionalDependency("ListPageButtonPlugin")?.selectSortMethod?.(g)}catch(v){r.find(".jhs-mobile-sort-option").attr("aria-checked","false"),m.attr("aria-checked","true"),clog.error("排序设置保存失败,已恢复",v),show.error("排序设置保存失败,已恢复原设置");return}let f={default:"默认",rateCount:"评价人数",date:"时间"};s.find('[data-action="sort"]').text(`排序: ${f[String(g)]??g}`),h(!0)})),s.on("click",".jhs-fab-menu-item",p=>{let g=$(p.currentTarget).data("action");if(g==="quickFilter"){p.stopPropagation(),s.addClass("jhs-fab-filter-open"),i.attr("aria-expanded","true");let m=a.find('[aria-checked="true"]');return void(m.length?m.first():a.find(".jhs-mobile-filter-option").first()).trigger("focus")}if(g==="sort"){p.stopPropagation(),s.addClass("jhs-fab-sort-open"),n.attr("aria-expanded","true");let m=r.find('[aria-checked="true"]');return void(m.length?m.first():r.find(".jhs-mobile-sort-option").first()).trigger("focus")}h(!0),this.handleAction(g).catch((m=>clog.error(`移动端操作 ${g||"unknown"} 失败`,m)))})}async handleAction(e){switch(e){case"check":await this.getOptionalDependency("ListPageButtonPlugin")?.openWaitCheck?.();break;case"newVideo":this.getOptionalDependency("NewVideoPlugin")?.openDialog?.();break;case"blacklist":this.getOptionalDependency("BlacklistPlugin")?.openBlacklistDialog?.();break;case"history":await this.getOptionalDependency("HistoryPlugin")?.openHistory?.();break;case"sort":break;case"filter":$("#filterBtn").length&&$("#filterBtn").click();break;case"fav":$("#favoriteBtn").length&&$("#favoriteBtn").click();break;case"down":$("#hasDownBtn").length&&$("#hasDownBtn").click();break;case"watch":$("#hasWatchBtn").length&&$("#hasWatchBtn").click();break;case"magnetFilter":$("#enable-magnets-filter").length&&$("#enable-magnets-filter").click();break;case"magnet":$("#magnetSearchBtn").length&&$("#magnetSearchBtn").click();break;case"subtitle":$("#search-subtitle-btn").length&&$("#search-subtitle-btn").click();break;case"setting":await this.getOptionalDependency("SettingPlugin")?.openQuickSetting();break;case"logger":clog.openDialog?.();break}}};d(Dn,"MobileBottomBarPlugin");var Wa=Dn;var Nn=class Nn extends I{getName(){return"NavBarPlugin"}async initCss(){return` .highlight-red { /* 核心要求:高亮红色文本 */ color: var(--jhs-status-filter) !important; @@ -4070,9 +4065,9 @@ ${i}\r - `),$("#search-keyword").on("paste",(t=>{let s=t.originalEvent?.clipboardData?.items||[];for(let a=0;a{i.handleImageFile(r),i.resetSearchUI()})):void show.info("以图识图功能已禁用")}})).on("keypress",(t=>{t.key==="Enter"&&setTimeout((()=>{$("#search-btn").click()}),0)})),$("#search-btn").on("click",(t=>{let s=$("#search-keyword").val(),a=$("#search-type").val();s!==""&&(window.location.href.includes("/search")?window.location.href="/search?q="+encodeURIComponent(String(s))+"&f="+encodeURIComponent(String(a)):window.open("/search?q="+encodeURIComponent(String(s))+"&f="+encodeURIComponent(String(a))))})),e&&$("#search-img-btn").on("click",(()=>{this.getOptionalDependency("SearchByImagePlugin")?.open?.()}))}hookOldSearch(){let e=!!this.getOptionalDependency("SearchByImagePlugin");if(!e)return;let t=document.querySelector(".search-image");if(!t)return;let s=t.cloneNode(!0);t.parentNode?.replaceChild(s,t),$("#button-search-image").attr("data-tooltip","以图识图"),e&&$(".search-image").on("click",(a=>{this.getOptionalDependency("SearchByImagePlugin")?.open?.()}))}margeNav(){$('a[href*="/feedbacks/new"]').remove(),$('a[href*="theporndude.com"]').remove();let e=$(''),t=e.find(".navbar-dropdown");t.append($('反饋')),this.getRuntimeService("movie").externalNavigationLinks().forEach((s=>t.append($("").addClass("navbar-item").attr({href:s.url,rel:"nofollow noopener",target:"_blank"}).text(s.label)))),$('a.navbar-link[href="/makers"]').parent().after(e)}toggleOtherNavItem(){let e=$("#search-box"),t=$("#search-bar-container");$(window).width()>1600?(e.show(),t.hide()):(e.hide(),t.show())}};d(Dn,"NavBarPlugin");var Ja=Dn;var Nn=class Nn extends I{constructor(){super(...arguments),P(this,"flag",null)}getName(){return"WantAndWatchedVideosPlugin"}async handle(){window.location.href.includes("/want_watch_videos")&&($("h3").append(''),$("#wantWatchBtn").on("click",(e=>{this.flag="favorite",this.importWantWatchVideos(e,"是否将想看的影片导入到 JHS 收藏?")}))),window.location.href.includes("/watched_videos")&&($("h3").append(''),$("#wantWatchBtn").on("click",(e=>{this.flag="watched",this.importWantWatchVideos(e,"是否将看过的影片导入到 JHS 已观看?")})))}importWantWatchVideos(e,t){utils.q(null,`${t}
      执行此功能前请记得备份数据`,(async()=>{let s=loading();try{let a=await this.parseMovieList();show.ok(`导入完成:成功 ${a.imported},失败 ${a.failed},共 ${a.pages} 页`)}catch(a){clog.error(a),show.error(`导入失败:${a instanceof Error?a.message:String(a)}`)}finally{s.close()}}))}async parseMovieList(e=null,t={imported:0,failed:0,pages:0}){let s,a;e?(s=e.find(this.getSelector().itemSelector),a=e.find(".pagination-next").attr("href")):(s=$(this.getSelector().itemSelector),a=$(".pagination-next").attr("href")),t.pages++,show.info(`正在导入第 ${t.pages} 页`);for(let l of s){let c=$(l),h=c.find("a").attr("href"),u=c.find(".video-title strong").text().trim(),p=c.find(".meta").text().trim();if(h&&u)try{this.flag&&await this.getRuntimeService("state").patch(u,{[this.flag]:!0},{type:"javdb-list-import",record:{carNum:u,url:h,names:"",publishTime:p}}),t.imported++}catch(g){t.failed++,clog.error(`保存失败 [${u}]:`,g)}}if(!a)return t;await utils.sleep(1e3);let r=await this.getRuntimeService("scope")(),i=await He(this.getRuntimeService("http"),new URL(a,window.location.href),r),n=utils.htmlTo$dom(i);return this.parseMovieList(n,t)}};d(Nn,"WantAndWatchedVideosPlugin");var Wa=Nn;var Ln=class Ln extends I{getName(){return"SubTitleCatPlugin"}handle(){$(".t-banner-inner").hide(),$("#navbar").hide();let e=(new URLSearchParams(window.location.search).get("search")||"").toLowerCase(),t=$(".sub-table tr td a").toArray(),s=0;t.forEach((i=>{let n=$(i);n.text().toLowerCase().includes(e)?s++:n.parent().parent().hide()})),s===0&&show.error("该番号无字幕!");let a=$(".sec-title"),r=String(a.html()||"").replace(/^\d+/,String(s));a.html(r)}};d(Ln,"SubTitleCatPlugin");var Ka=Ln;var Mn=class Mn extends I{getName(){return"TranslatePlugin"}async initCss(){return` + `),$("#search-keyword").on("paste",(t=>{let s=t.originalEvent?.clipboardData?.items||[];for(let a=0;a{i.handleImageFile(r),i.resetSearchUI()})):void show.info("以图识图功能已禁用")}})).on("keypress",(t=>{t.key==="Enter"&&setTimeout((()=>{$("#search-btn").click()}),0)})),$("#search-btn").on("click",(t=>{let s=$("#search-keyword").val(),a=$("#search-type").val();s!==""&&(window.location.href.includes("/search")?window.location.href="/search?q="+encodeURIComponent(String(s))+"&f="+encodeURIComponent(String(a)):window.open("/search?q="+encodeURIComponent(String(s))+"&f="+encodeURIComponent(String(a))))})),e&&$("#search-img-btn").on("click",(()=>{this.getOptionalDependency("SearchByImagePlugin")?.open?.()}))}hookOldSearch(){let e=!!this.getOptionalDependency("SearchByImagePlugin");if(!e)return;let t=document.querySelector(".search-image");if(!t)return;let s=t.cloneNode(!0);t.parentNode?.replaceChild(s,t),$("#button-search-image").attr("data-tooltip","以图识图"),e&&$(".search-image").on("click",(a=>{this.getOptionalDependency("SearchByImagePlugin")?.open?.()}))}margeNav(){$('a[href*="/feedbacks/new"]').remove(),$('a[href*="theporndude.com"]').remove();let e=$(''),t=e.find(".navbar-dropdown");t.append($('反饋')),this.getRuntimeService("movie").externalNavigationLinks().forEach((s=>t.append($("").addClass("navbar-item").attr({href:s.url,rel:"nofollow noopener",target:"_blank"}).text(s.label)))),$('a.navbar-link[href="/makers"]').parent().after(e)}toggleOtherNavItem(){let e=$("#search-box"),t=$("#search-bar-container");$(window).width()>1600?(e.show(),t.hide()):(e.hide(),t.show())}};d(Nn,"NavBarPlugin");var Ja=Nn;var Ln=class Ln extends I{constructor(){super(...arguments),P(this,"flag",null)}getName(){return"WantAndWatchedVideosPlugin"}async handle(){window.location.href.includes("/want_watch_videos")&&($("h3").append(''),$("#wantWatchBtn").on("click",(e=>{this.flag="favorite",this.importWantWatchVideos(e,"是否将想看的影片导入到 JHS 收藏?")}))),window.location.href.includes("/watched_videos")&&($("h3").append(''),$("#wantWatchBtn").on("click",(e=>{this.flag="watched",this.importWantWatchVideos(e,"是否将看过的影片导入到 JHS 已观看?")})))}importWantWatchVideos(e,t){utils.q(null,`${t}
      执行此功能前请记得备份数据`,(async()=>{let s=loading();try{let a=await this.parseMovieList();show.ok(`导入完成:成功 ${a.imported},失败 ${a.failed},共 ${a.pages} 页`)}catch(a){clog.error(a),show.error(`导入失败:${a instanceof Error?a.message:String(a)}`)}finally{s.close()}}))}async parseMovieList(e=null,t={imported:0,failed:0,pages:0}){let s,a;e?(s=e.find(this.getSelector().itemSelector),a=e.find(".pagination-next").attr("href")):(s=$(this.getSelector().itemSelector),a=$(".pagination-next").attr("href")),t.pages++,show.info(`正在导入第 ${t.pages} 页`);for(let l of s){let c=$(l),h=c.find("a").attr("href"),u=c.find(".video-title strong").text().trim(),p=c.find(".meta").text().trim();if(h&&u)try{this.flag&&await this.getRuntimeService("state").patch(u,{[this.flag]:!0},{type:"javdb-list-import",record:{carNum:u,url:h,names:"",publishTime:p}}),t.imported++}catch(g){t.failed++,clog.error(`保存失败 [${u}]:`,g)}}if(!a)return t;await utils.sleep(1e3);let r=await this.getRuntimeService("scope")(),i=await qe(this.getRuntimeService("http"),new URL(a,window.location.href),r),n=utils.htmlTo$dom(i);return this.parseMovieList(n,t)}};d(Ln,"WantAndWatchedVideosPlugin");var Ka=Ln;var Mn=class Mn extends I{getName(){return"SubTitleCatPlugin"}handle(){$(".t-banner-inner").hide(),$("#navbar").hide();let e=(new URLSearchParams(window.location.search).get("search")||"").toLowerCase(),t=$(".sub-table tr td a").toArray(),s=0;t.forEach((i=>{let n=$(i);n.text().toLowerCase().includes(e)?s++:n.parent().parent().hide()})),s===0&&show.error("该番号无字幕!");let a=$(".sec-title"),r=String(a.html()||"").replace(/^\d+/,String(s));a.html(r)}};d(Mn,"SubTitleCatPlugin");var Ga=Mn;var Bn=class Bn extends I{getName(){return"TranslatePlugin"}async initCss(){return` `}async handle(){let e=this.getRuntimeService("settings"),t=await this.getRuntimeService("scope")();if(!this._settingsListenerBound){this._settingsListenerBound=!0;let s=d(a=>{a.detail?.names?.includes("translateTitle")&&this.reconfigure()},"onSettingsChanged");e.addEventListener("settings.changed",s),t.addCleanup((()=>{e.removeEventListener("settings.changed",s),this._settingsListenerBound=!1}))}this.reconfigure()}reconfigure(){(this.getRuntimeService("settings").snapshot().translateTitle??R)===R?this.applyTranslation():(this.getOptionalDependency("ListPagePlugin")?.invalidateTranslations?.(),this.revertTranslation())}async applyTranslation(){if(isDetailPage)return this.translate();if(!window.isListPage)return;let e=this.getOptionalDependency("ListPagePlugin");if(!e?.translateListItems||typeof e.getSelector!="function")return;let t=$(e.getSelector().itemSelector).toArray();await e.translateListItems(t)}revertTranslation(){$(".translated-title").remove(),this.getOptionalDependency("ListPagePlugin")?.revertTranslation?.()}async translate(e,t=!0,s={}){let a=this.getRuntimeService("settings");if((a.snapshot().translateTitle??R)!==R)return;B&&(t=!1);let r=await this.getRuntimeService("scope")(),i=e??this.getPageInfo().carNum;await Xs({root:s.root,carNum:i,translation:this.getRuntimeService("translation"),scope:r,isActive:d(()=>(a.snapshot().translateTitle??R)===R,"isActive")})}};d(Mn,"TranslatePlugin");var Ga=Mn;var F=d((o,e,t,s,a,r=[],i={})=>hl({id:o,featureId:e,legacyPluginId:t.legacyPluginId??t.name,plugin:t,sites:s,order:a,requires:r,routes:i.routes??(e==="detail"?["detail","owned-detail"]:[]),surfaces:i.surfaces??(e==="detail"?["detail-page"]:[])}),"manifest"),Qa=Object.freeze([F("list.core","list",Ha,["javdb","javbus"],{javdb:1,javbus:1},[Y.host,y.translation,y.http,y.storage,y.state,y.settings]),F("list.auto-page","list",Ta,["javdb","javbus"],{javdb:2,javbus:5},[y.http,y.settings]),F("detail.fc2-owned","detail",ta,["javdb"],{javdb:3},[y.movie,y.magnet,y.dialog,y.account,y.credential,y.translation,y.settings,y.storage,y.screenshot,y.review,y.related,y.state],{routes:["list","detail","owned-detail"],surfaces:["list-card","detail-page"]}),F("detail.fc2-navigation","detail",Na,["javdb"],{javdb:4},[Y.host],{routes:["list"],surfaces:["list-card"]}),F("list.fold-category","list",La,["javdb"],{javdb:5},[y.settings]),F("list.actions","list",Fa,["javdb","javbus"],{javdb:5,javbus:2},[y.settings]),F("library.history","library",za,["javdb","javbus"],{javdb:6,javbus:4},[y.dialog,y.movie,y.settings,y.state]),F("settings.core","settings",zs,["javdb","javbus"],{javdb:7,javbus:3},[Y.host,y.diagnostics,y.profile,y.webdav,y.dialog,y.storage,y.settings,y.cache,y.http,y.offline,y.magnet,y.movie,y.state,y.translation,Qe.settings]),F("identity.javdb-navigation","identity",Ja,["javdb"],{javdb:8},[y.movie]),F("discovery.hit-show","discovery",sa,["javdb"],{javdb:9},[Y.host]),F("discovery.top250","discovery",da,["javdb"],{javdb:10},[Y.host]),F("identity.image-search","identity",Is,["javdb","javbus"],{javdb:11,javbus:6},[y.dialog,y.storage,y.imageSearch]),F("detail.cover-state-actions","detail",va,["javdb","javbus"],{javdb:12,javbus:8},[y.storage,y.settings,y.movie,y.state],{routes:["list","detail","owned-detail"],surfaces:["list-card","detail-page"]}),F("detail.fc2-lookup","detail",Qs,["javdb"],{javdb:13},[Y.host,y.movie],{routes:["list","detail","owned-detail"],surfaces:["list-card","detail-page"]}),F("detail.javdb-native","detail",Ea,["javdb"],{javdb:14}),F("detail.workspace","detail",Da,["javdb","javbus"],{javdb:15,javbus:11},[Y.host]),F("detail.reviews","detail",ca,["javdb","javbus"],{javdb:16,javbus:13},[Y.host,y.review,y.movie,y.settings,y.storage]),F("detail.related","detail",la,["javdb"],{javdb:17},[Y.host,y.related,y.settings]),F("detail.page-state-actions","detail",Ra,["javdb","javbus"],{javdb:18,javbus:12},[y.movie,y.dialog,y.subtitle,y.state,y.settings]),F("detail.native-magnets","detail",Ma,["javdb","javbus"],{javdb:19,javbus:15},[Y.host,y.settings]),F("detail.javdb-preview","detail",ba,["javdb"],{javdb:20},[y.storage,y.settings,y.movie,y.dialog]),F("library.keyword-filter","library",Ws,["javdb","javbus"],{javdb:21,javbus:14}),F("identity.actress-info","identity",Ps,["javdb"],{javdb:22},[y.actressInfo,y.settings]),F("detail.external-sites","detail",oa,["javdb","javbus"],{javdb:23,javbus:19},[Y.host,y.movie,y.storage,y.settings]),F("external-bridge.translation","external-bridge",Ga,["javdb","javbus"],{javdb:24,javbus:20},[y.translation,y.settings]),F("library.state-actions","library",Wa,["javdb"],{javdb:25},[y.http,y.state]),F("detail.external-magnets","detail",na,["javdb","javbus"],{javdb:26,javbus:17},[y.storage,y.http,y.magnet]),F("detail.screenshot","detail",wa,["javdb","javbus"],{javdb:27,javbus:18},[y.screenshot,y.settings]),F("library.blacklist","library",Js,["javdb","javbus"],{javdb:28,javbus:21},[Y.host,y.dialog,y.storage,y.http,y.state]),F("library.favorite-actresses","library",ua,["javdb"],{javdb:29}),F("discovery.new-video","discovery",ya,["javdb"],{javdb:30},[y.dialog,y.storage,y.actressInfo,y.movie,y.state]),F("discovery.scheduler","discovery",Sa,["javdb","javbus"],{javdb:31,javbus:22},[y.storage,y.http,y.actressInfo,y.movie,y.state]),F("stats.dashboard","stats",$a,["javdb","javbus"],{javdb:32,javbus:23},[y.diagnostics,y.dialog,y.movie,y.state]),F("responsive-shell.bottom-bar","responsive-shell",qa,["javdb","javbus"],{javdb:33,javbus:24},[Y.host,y.settings,y.profile]),F("external-bridge.115-match","external-bridge",ka,["javdb","javbus"],{javdb:34,javbus:25},[Y.host,y.dialog,y.offline,y.settings]),F("external-bridge.offline","external-bridge",xa,["javdb","javbus"],{javdb:35,javbus:26},[Y.host,y.dialog,y.offline,y.state,y.settings]),F("compatibility.enhancements","compatibility",Ia,["javdb","javbus"],{javdb:36,javbus:27},[y.state]),F("identity.javbus-navigation","identity",Pa,["javbus"],{javbus:7}),F("detail.javbus-images","detail",pa,["javbus"],{javbus:9}),F("detail.javbus-native","detail",Aa,["javbus"],{javbus:10}),F("detail.javbus-preview","detail",fa,["javbus"],{javbus:16},[y.settings,y.storage,y.movie]),F("external-bridge.123pan","external-bridge",Ca,["javdb","javbus","123pan"],{javdb:0,javbus:0,"123pan":1},[y.storage]),F("external-bridge.javtrailers","external-bridge",aa,["javtrailers"],{javtrailers:1}),F("external-bridge.subtitle","external-bridge",Ka,["subtitlecat"],{subtitlecat:1})]),Ec=new Set,Dc=new Set;for(let o of Qa){if(Ec.has(o.id))throw new Error(`Duplicate contribution id: ${o.id}`);if(Dc.has(o.legacyPluginId))throw new Error(`Duplicate legacy plugin contribution: ${o.legacyPluginId}`);Ec.add(o.id),Dc.add(o.legacyPluginId)}function Nc(o,e,t){o.setDependencyDeclarations(bl),e.setContributionManifests?.(Qa),o.setCatalogDescriptors(Qa.filter(s=>s.sites.includes(t)).map(s=>({name:s.legacyPluginId,disableable:e.isFeatureDisableable(s.featureId)}))),Qa.filter(s=>s.sites.includes(t)&&e.isContributionEnabled(s.featureId,s.id,s.legacyPluginId)).sort((s,a)=>Number(s.order[t])-Number(a.order[t])).forEach(s=>{let a=e.resolveDeclaredDependencies(s.requires),r={};r.scope=()=>e.getContributionScope(s.featureId,s.id,s.legacyPluginId);let i=new Map([[Y.host,"host"],[y.diagnostics,"diagnostics"],[y.review,"review"],[y.related,"related"],[y.movie,"movie"],[y.magnet,"magnet"],[y.settings,"settings"],[y.cache,"cache"],[y.http,"http"],[y.profile,"profile"],[y.actressInfo,"actressInfo"],[y.imageSearch,"imageSearch"],[y.screenshot,"screenshot"],[y.translation,"translation"],[y.subtitle,"subtitle"],[y.account,"account"],[y.webdav,"webdav"],[y.credential,"credential"],[y.storage,"storage"],[y.state,"state"],[y.offline,"offline"],[y.dialog,"dialog"],[Qe.settings,"settingsRegistry"]]);for(let n of s.requires){let l=i.get(n);if(!l)throw new Error(`Legacy contribution ${s.id} has no runtime name for ${String(n)}`);r[l]=a[n]}o.register(s.plugin,r,{disableable:e.isFeatureDisableable(s.featureId)})})}d(Nc,"registerSitePlugins");function Lc(o,e){for(let t of["pluginManager","utils","gmHttp","storageManager","stateService","jhsEventBus","clog","show","loading"]){if(o[t]==null)throw new Error(`Compatibility facade is missing ${t}`);e[t]=o[t]}return Object.freeze(Object.fromEntries(Object.keys(o).map(t=>[t,e[t]])))}d(Lc,"attachCompatibilityFacade");function qe(o,e,t){if(!o||typeof o!="object")throw new TypeError(`${e} implementation is required`);for(let s of t)if(typeof o[s]!="function")throw new TypeError(`${e}.${s} is required`);return o}d(qe,"assertPort");var Je=Object.freeze({navigation:["open","assign","replace"],http:["request"],storage:["get","set","remove","keys","getLocal","setLocal","removeLocal","getValue","setValue","removeValue"],dialog:["open","close","confirm","alert"],style:["register","remove"]});var Bn=class Bn{constructor(e={}){this.location=e.location??window.location,this.openWindow=e.open??window.open.bind(window),qe(this,"NavigationPort",Je.navigation)}open(e,t={}){return t.newTab?this.openWindow(e,"_blank","noopener"):this.assign(e)}assign(e){this.location.assign(e)}replace(e){this.location.replace(e)}};d(Bn,"BrowserNavigationAdapter");var Ya=Bn;var On=class On{constructor(e=document){this.document=e}register(e,t){if(this.document.getElementById(e))throw new Error(`Duplicate style: ${e}`);let s=this.document.createElement("style");return s.id=e,s.textContent=t,this.document.head.append(s),()=>s.remove()}remove(e){this.document.getElementById(e)?.remove()}};d(On,"BrowserStyleAdapter");var Za=On;var Un=class Un{constructor(e,t,s,a,r=()=>{}){this.forage=e,this.localStore=t,this.gmGetValue=s,this.gmSetValue=a,this.gmDeleteValue=r}get(e){return this.forage.getItem(e)}async set(e,t){await this.forage.setItem(e,t)}async remove(e){await this.forage.removeItem(e)}keys(){return this.forage.keys()}getLocal(e){return this.localStore.getItem(e)}setLocal(e,t){this.localStore.setItem(e,t)}removeLocal(e){this.localStore.removeItem(e)}getValue(e,t){return this.gmGetValue(e,t)}setValue(e,t){this.gmSetValue(e,t)}removeValue(e){this.gmDeleteValue(e)}};d(Un,"IndexedDbStorageAdapter");var Xa=Un;var zn=class zn{constructor(e){this.layer=e}open(e){return this.layer.open(this.withDefaultLayer(e))}close(e){this.layer.close(e)}confirm(e,t,s){return this.layer.confirm(e,this.withDefaultLayer(t),s)}alert(e,t){return this.layer.alert(e,this.withDefaultLayer(t))}withDefaultLayer(e={}){let t={zIndex:W.layer,...e};return e.ui?kt(t,globalThis.utils):t}};d(zn,"LayerDialogAdapter");var er=zn;var Fn=class Fn{constructor(e,t=globalThis.fetch?.bind(globalThis)??null){if(typeof e!="function")throw new TypeError("GM_xmlhttpRequest is required");this.requestImplementation=e,this.fetchImplementation=t}request(e){return e.transport==="native-fetch"&&this.fetchImplementation?this.requestWithNativeFetch(e).catch((t=>{if(t instanceof D&&t.code==="ABORTED")throw t;return this.requestWithUserscript(e)})):this.requestWithUserscript(e)}async requestWithNativeFetch(e){let t=new AbortController,s=!1,a=Math.max(0,Number(e.nativeTimeout)||0),r=d(()=>t.abort(),"onAbort"),i=a>0?setTimeout((()=>{s=!0,t.abort()}),a):null;e.signal?.addEventListener("abort",r,{once:!0});try{e.signal?.aborted&&t.abort();let n=await this.fetchImplementation(e.url,{method:e.method??"GET",headers:e.headers,body:e.body,signal:t.signal}),l=await n.text(),c=e.responseType==="json"?JSON.parse(l):l;return{status:n.status,data:c,responseText:l,finalUrl:n.url||e.url,responseHeaders:[...n.headers.entries()].map((h=>h.join(": "))).join(`\r -`)}}catch(n){throw e.signal?.aborted?new D("ABORTED","网络请求已取消",{source:"UserscriptHttpAdapter",cause:n}):s?new D("TIMEOUT","原生网络请求超时",{source:"UserscriptHttpAdapter",cause:n,retryable:!0}):new D("NETWORK_ERROR","原生网络请求失败",{source:"UserscriptHttpAdapter",cause:n,retryable:!0})}finally{i!==null&&clearTimeout(i),e.signal?.removeEventListener("abort",r)}}requestWithUserscript(e){return new Promise((t,s)=>{let a=!1,r,i=d((l,c)=>{a||(a=!0,e.signal?.removeEventListener("abort",n),l(c))},"finish"),n=d(()=>{r?.abort?.(),i(s,new D("ABORTED","网络请求已取消",{source:"UserscriptHttpAdapter"}))},"onAbort");r=this.requestImplementation({...e.requestOptions,method:e.method??"GET",url:e.url,headers:e.headers,data:e.body,responseType:e.responseType,timeout:e.timeout,onload:d(l=>i(t,{status:l.status,data:l.response??l.responseText,responseText:l.responseText??"",finalUrl:l.finalUrl||e.url,responseHeaders:l.responseHeaders??""}),"onload"),onerror:d(l=>i(s,new D("NETWORK_ERROR","网络请求失败",{source:"UserscriptHttpAdapter",cause:l,retryable:!0})),"onerror"),ontimeout:d(()=>i(s,new D("TIMEOUT","网络请求超时",{source:"UserscriptHttpAdapter",retryable:!0})),"ontimeout"),onabort:d(()=>i(s,new D("ABORTED","网络请求已取消",{source:"UserscriptHttpAdapter"})),"onabort")}),e.signal?.aborted?n():e.signal?.addEventListener("abort",n,{once:!0})})}};d(Fn,"UserscriptHttpAdapter");var tr=Fn;async function Mc(o){let e=await globalThis.crypto.subtle.digest("SHA-256",new TextEncoder().encode(o));return Array.from(new Uint8Array(e),(t=>t.toString(16).padStart(2,"0"))).join("")}d(Mc,"digestKey");var Vn=class Vn{constructor(e={}){this.namespaceVersion=e.namespaceVersion??2,this.diagnostics=e.diagnostics??null,this.storage=e.storage??null,this.publicCache=new Map,this.sessionCaches=new Map,this.publicReads=new Map,this.publicGenerations=new Map,this.publicNamespaces=new Set(["default"]),this.publicWritesSincePrune=0,this.pruneScheduled=!1,this.pruneRunning=!1,this.prunePromise=null}get publicGeneration(){return this.publicGenerations.get("default")||0}generation(e){return this.publicGenerations.get(e)||0}get publicPrefix(){return this._publicPrefix("default")}_publicPrefix(e="default"){return`jhs_http_public_cache:v${this.namespaceVersion}:${encodeURIComponent(e)}:`}storeFor(e,t=""){if(e==="public")return this.publicCache;if(e==="session"){if(!t)throw new TypeError("sessionScopeId is required for session cache");let s=this.sessionCaches.get(t);return s||this.sessionCaches.set(t,s=new Map),s}return null}async get(e,t,s){arguments.length===2&&(s=t,t=e,e="default"),e=String(e||"default"),this.publicNamespaces.add(e);let a=this.storeFor(s.scope,s.sessionScopeId),r=`${e}:${this.namespaceVersion}:${t}`,i=Date.now(),n=this.storage,l=a?.get(r);if(l&&l.expiresAt>i)return this.diagnostics?.recordCache(!0),{hit:!0,value:l.value,negative:l.negative};if(l&&a?.delete(r),s.scope!=="public"||!n)return this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1};let c=`${e}:${t}`,h=this.publicReads.get(c);if(h)return h;let u=this.generation(e),p=(async()=>{let g=this._publicPrefix(e)+await Mc(t),m;try{m=await n.get(g)}catch{return this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1}}if(m?.version!==this.namespaceVersion||!Number.isFinite(m?.expiresAt)||m.expiresAt<=i)return m&&await n.remove(g).catch(()=>{}),this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1};if(u!==this.generation(e))return this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1};let f={value:m.value,expiresAt:m.expiresAt,negative:m.negative===!0};return this.publicCache.set(r,f),this.diagnostics?.recordCache(!0),{hit:!0,value:f.value,negative:f.negative}})().finally(()=>{this.publicReads.get(c)===p&&this.publicReads.delete(c)});return this.publicReads.set(c,p),p}async set(e,t,s,a){arguments.length===3&&(a=s,s=t,t=e,e="default"),e=String(e||"default"),this.publicNamespaces.add(e);let r=Math.min(2592e6,Math.max(0,Number(a.ttlMs)||0));if(!r||a.scope==="public"&&a.generation!=null&&a.generation!==this.generation(e))return;let i={value:s,expiresAt:Date.now()+r,negative:a.negative??!1},n=this.storeFor(a.scope,a.sessionScopeId),l=`${e}:${this.namespaceVersion}:${t}`,c=this.storage;if(a.scope!=="public"||!c){n?.set(l,i);return}if(a.generation!=null&&a.generation!==this.generation(e))return;let h=this._publicPrefix(e)+await Mc(t);if(!(a.generation!=null&&a.generation!==this.generation(e)))try{if(a.generation!=null&&a.generation!==this.generation(e))return;if(await c.set(h,{version:this.namespaceVersion,...i,lastUsed:Date.now()}),a.generation!=null&&a.generation!==this.generation(e)){await c.remove(h).catch(()=>{});return}n?.set(l,i),this.publicWritesSincePrune++,this.schedulePublicPrune()}catch{}}schedulePublicPrune(){if(!this.storage||this.publicWritesSincePrune<64||this.pruneScheduled||this.pruneRunning)return this.prunePromise;this.pruneScheduled=!0;let e=d(async()=>{this.pruneScheduled=!1,this.pruneRunning=!0,this.publicWritesSincePrune=0;try{await this.prunePublic()}catch{}finally{this.pruneRunning=!1,this.prunePromise=null,this.schedulePublicPrune()}},"run");return this.prunePromise=Promise.resolve().then(e),this.prunePromise}async waitForPrune(){await this.prunePromise?.catch(()=>{})}async prunePublic(){if(!this.storage)return;let e;try{e=await this.storage.keys()}catch{return}let t=Date.now(),s=[];for(let a of e.filter(r=>r.startsWith("jhs_http_public_cache:v"))){let r=await this.storage.get(a).catch(()=>null);if(!r||r.version!==this.namespaceVersion||!Number.isFinite(r.expiresAt)||r.expiresAt<=t){await this.storage.remove(a).catch(()=>{});continue}s.push({key:a,lastUsed:Number(r.lastUsed)||0})}if(s.length>500){s.sort((a,r)=>a.lastUsed-r.lastUsed);for(let a of s.slice(0,s.length-500))await this.storage.remove(a.key).catch(()=>{})}}async clearNamespace(e){e=String(e||"default"),this.publicGenerations.set(e,this.generation(e)+1);for(let a of this.publicCache.keys())a.startsWith(`${e}:`)&&this.publicCache.delete(a);for(let a of this.publicReads.keys())a.startsWith(`${e}:`)&&this.publicReads.delete(a);await this.waitForPrune();let t=this.storage;if(!t)return;let s;try{s=await t.keys()}catch{return}await Promise.all(s.filter((a=>a.startsWith(this._publicPrefix(e)))).map((a=>t.remove(a).catch(()=>{}))))}async clearAll(){let e=new Set(this.publicNamespaces);for(let t of e)await this.clearNamespace(t);if(this.publicCache.clear(),this.publicReads.clear(),this.sessionCaches.clear(),this.storage)try{let t=this.storage,s=`jhs_http_public_cache:v${this.namespaceVersion}:`,a=await t.keys();await Promise.all(a.filter(r=>r.startsWith(s)).map(r=>t.remove(r).catch(()=>{})))}catch{}}async clearPublic(){return this.clearAll()}async invalidateNamespace(){return this.clearAll()}};d(Vn,"CacheService");var sr=Vn;var Hn=class Hn{constructor(e,t){this.integrations=e,this.cache=t}profileUrl(e){for(let t of this.integrations.list("person.actress-info")){let s=this.integrations.getAdapter(t.id);if(typeof s.profileUrl=="function")return s.profileUrl(e)}return""}async lookup(e,t={}){let s=String(e).trim()==="三上悠亞"?"三上悠亜":String(e).trim();if(!s)return null;let a=`actress-info:${s}`,r=await this.cache.get("actress-info",a,{scope:"public"});if(r.hit)return r.value;let i=this.cache.generation("actress-info");for(let n of this.integrations.list("person.actress-info")){let l=this.integrations.getAdapter(n.id);if(typeof l.lookup!="function")continue;let c=await l.lookup(s,t);return await this.cache.set("actress-info",a,c,{scope:"public",ttlMs:6048e5,negative:!c,generation:i}),c}return null}async movies(e,t,s={}){let a=this.integrations.list("actor.movies").find(i=>i.id===e);if(!a)return[];let r=this.integrations.getAdapter(a.id);return typeof r?.listActorMovies=="function"?r.listActorMovies(t,s):[]}async collection(e,t,s={}){let a=this.integrations.list("actor.collection").find(i=>i.id===e);if(!a)throw new TypeError(`Actor collection provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.listActorCollection!="function")throw new TypeError(`Actor collection is unavailable: ${e}`);return r.listActorCollection(t,s)}async uncollect(e,t,s={}){let a=this.integrations.list("actor.uncollect").find(i=>i.id===e);if(!a)throw new TypeError(`Actor provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.uncollectActor!="function")throw new TypeError(`Actor uncollect is unavailable: ${e}`);return r.uncollectActor(t,s)}getAvatarSources(){return Object.freeze(this.integrations.list("person.avatar-search").flatMap(e=>{let t=this.integrations.getAdapter(e.id);return typeof t?.getSources=="function"?t.getSources():[]}))}async searchAvatars(e,t,s={}){for(let a of this.integrations.list("person.avatar-search")){let r=this.integrations.getAdapter(a.id);if(r?.getSources?.().some(i=>i.id===t))return r.searchAvatars(e,{...s,sourceId:t})}return[]}placeholderUrl(e){let t=this.integrations.getAdapter(e);return typeof t?.actorPlaceholderUrl=="function"?t.actorPlaceholderUrl():""}};d(Hn,"ActressInfoService");var ar=Hn;var Yh=/^(?:authorization|cookie|set-cookie|password|token|secret|credential)$/i;function qn(o,e=""){return Yh.test(e)?"[redacted]":Array.isArray(o)?o.map(t=>qn(t)):o&&typeof o=="object"?Object.fromEntries(Object.entries(o).map(([t,s])=>[t,qn(s,t)])):typeof o!="string"?o:o.replace(/(https?:\/\/)([^\s/@:]+):([^\s/@]+)@/gi,"$1[redacted]@")}d(qn,"sanitize");var Jn=class Jn{constructor(e={}){this.startedAt=performance.now(),this.activeFeatures=new Set,this.activeContributions=new Set,this.startupTimings=new Map,this.scopes=new Map,this.requestStats={consumers:0,underlying:0},this.cacheStats={hits:0,misses:0},this.providerHealth=new Map,this.errors=[],this.browserMetadata=null,this.legacyPlugins=[],this.legacyPluginDescriptors=[],this.legacyStartup=null,this.legacyTimings=[],this.legacyHttp=e.legacyHttp??null,this.networkController=null}recordStartup(e,t){this.startupTimings.set(e,t)}setFeature(e,t){t?this.activeFeatures.add(e):this.activeFeatures.delete(e)}setContribution(e,t){t?this.activeContributions.add(e):this.activeContributions.delete(e)}updateScope(e){this.scopes.set(e.id,Object.freeze({...e}))}updateRequests(e,t){this.requestStats={consumers:e,underlying:t}}recordCache(e){e?this.cacheStats.hits+=1:this.cacheStats.misses+=1}updateProvider(e,t){this.providerHealth.set(e,Object.freeze({...t}))}recordError(e){let t=e&&typeof e=="object"&&"toJSON"in e&&typeof e.toJSON=="function"?e.toJSON():e instanceof Error?{message:e.message}:e&&typeof e=="object"?{...e}:{message:String(e)};this.errors.push({...qn(t),timestamp:new Date().toISOString()}),this.errors.length>100&&this.errors.shift()}setBrowserMetadata(e){this.browserMetadata=Object.freeze({...e})}setLegacyRuntime(e,t,s){this.legacyPluginDescriptors=e.map(a=>Object.freeze({...a})),this.legacyPlugins=e.map(a=>a.name),this.legacyStartup=Object.freeze({...t}),this.legacyTimings=s.map(a=>Object.freeze({...a}))}clearErrors(){this.errors=[]}setNetworkController(e){this.networkController=e}getNetworkDiagnostics(){let e=this.networkController??this.legacyHttp;return Object.freeze({circuitBreakers:e?.getCircuitBreakerStatus?.()??{},domainStats:e?.getDomainStats?.()??{}})}resetCircuitBreaker(e){(this.networkController??this.legacyHttp)?.resetCircuitBreaker?.(e)}resetAllCircuitBreakers(){(this.networkController??this.legacyHttp)?.resetAllCircuitBreakers?.()}clearDomainStats(){(this.networkController??this.legacyHttp)?.clearDomainStats?.()}exportSnapshot(){let e=[...this.scopes.values()];return Object.freeze({activeFeatures:[...this.activeFeatures],activeContributions:[...this.activeContributions],startupTimings:Object.fromEntries(this.startupTimings),activeScopes:e,globalListeners:e.filter(t=>t.id==="app:root").reduce((t,s)=>t+Number(s.listeners??0),0),observers:e.reduce((t,s)=>t+Number(s.observers??0),0),requestConsumers:this.requestStats.consumers,underlyingRequests:this.requestStats.underlying,cacheHits:this.cacheStats.hits,cacheMisses:this.cacheStats.misses,providerHealth:Object.fromEntries(this.providerHealth),errors:this.errors.map(t=>({...t})),legacyPlugins:[...this.legacyPlugins],legacyPluginDescriptors:this.legacyPluginDescriptors.map(t=>({...t})),legacyStartup:this.legacyStartup,legacyTimings:this.legacyTimings.map(t=>({...t})),browser:this.browserMetadata,uptimeMs:performance.now()-this.startedAt})}};d(Jn,"DiagnosticsService");var rr=Jn;var Wn=class Wn{constructor(e){this.port=qe(e,"DialogPort",Je.dialog)}open(e){return this.port.open(e)}close(e){return this.port.close(e)}confirm(e,t,s){return this.port.confirm(e,t,s)}alert(e,t){return this.port.alert(e,t)}};d(Wn,"DialogService");var ir=Wn;var Zh=[/^10\./,/^127\./,/^169\.254\./,/^192\.168\./,/^172\.(?:1[6-9]|2\d|3[01])\./,/^0\./];function Xh(o){let e=o.replace(/^\[|\]$/g,"").toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="::1"?!0:e.includes(":")?e.startsWith("fc")||e.startsWith("fd")||e.startsWith("fe8")||e.startsWith("fe9")||e.startsWith("fea")||e.startsWith("feb"):Zh.some(t=>t.test(e))}d(Xh,"isPrivateLiteral");var Kn=class Kn{constructor(e={}){this.localOrigins=new Set,this.replaceLocalOrigins(e.localOrigins??[])}authorizeLocalOrigin(e){this.localOrigins.add(new URL(e).origin)}replaceLocalOrigins(e){let t=new Set(e.map(s=>new URL(s).origin));this.localOrigins=t}assertAllowed(e,t){let s;try{s=e instanceof URL?e:new URL(e)}catch(a){throw new D("INVALID_URL","外部地址无效",{source:"ExternalUrlPolicy",cause:a})}if(!new Set(["http:","https:"]).has(s.protocol))throw new D("INVALID_URL","仅允许 HTTP/HTTPS 地址",{source:"ExternalUrlPolicy"});if(t.expectedOrigin&&s.origin!==new URL(t.expectedOrigin).origin)throw new D("INVALID_URL","地址离开已声明的精确 origin",{source:"ExternalUrlPolicy"});if(t.trustClass==="builtin-public"){if(s.protocol!=="https:"||!(t.hosts??[]).some(a=>s.hostname===a||s.hostname.endsWith(`.${a}`)))throw new D("INVALID_URL","地址不在 Integration manifest 允许范围",{source:"ExternalUrlPolicy"})}else if(t.trustClass==="custom-public"){if(s.protocol!=="https:"||Xh(s.hostname))throw new D("INVALID_URL","自定义公开来源必须使用公网 HTTPS",{source:"ExternalUrlPolicy"})}else if(t.trustClass==="user-local"){let a=t.expectedOrigin?new URL(t.expectedOrigin).origin:s.origin;if(!this.localOrigins.has(a)||s.origin!==a)throw new D("INVALID_URL","本地来源未获得精确 origin 授权",{source:"ExternalUrlPolicy"})}else throw new D("INVALID_URL","未知 URL trust class",{source:"ExternalUrlPolicy"});return s}assertFinalUrl(e,t){return this.assertAllowed(e,t)}};d(Kn,"ExternalUrlPolicy");var nr=Kn;function us(o){if(o==null||typeof o!="object")return JSON.stringify(o);if(Array.isArray(o))return`[${o.map(us).join(",")}]`;let e=o;return`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${us(e[t])}`).join(",")}}`}d(us,"stableSerialize");async function Bc(o){let e=new TextEncoder().encode(o),t=await crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(t)].map(s=>s.toString(16).padStart(2,"0")).join("")}d(Bc,"sha256");function eu(o){let e=new URL(o),t=[...e.searchParams.entries()].sort(([s,a],[r,i])=>s.localeCompare(r)||a.localeCompare(i));e.search="";for(let[s,a]of t)e.searchParams.append(s,a);return e.hash="",e.href}d(eu,"canonicalizeUrl");function tu(o,e=0){if(typeof o!="string"||!o)return!1;let t=o.toLowerCase(),s=/]*>\s*just a moment(?:\.\.\.)?\s*<\/title>/i.test(o),a=/id=["']challenge-form["']/i.test(o),r=t.includes("cf-chl-")||t.includes("cf_chl_opt"),i=t.includes("/cdn-cgi/challenge-platform/")||t.includes("challenge-platform");return s||a&&(r||i)||[403,429,503].includes(e)&&r&&i}d(tu,"isCloudflareChallenge");function su(o,e){return o<=0?Promise.resolve():new Promise((t,s)=>{let r=setTimeout(d(()=>{e?.removeEventListener("abort",i),t()},"finish"),o),i=d(()=>{clearTimeout(r),s(new D("ABORTED","请求已取消",{source:"HttpService"}))},"onAbort");e?.addEventListener("abort",i,{once:!0}),Promise.resolve().then(()=>e?.aborted&&i())})}d(su,"waitForRetry");async function au(o){let e=String(o.method??"GET").toUpperCase(),t=Object.fromEntries(Object.entries(o.headers??{}).map(([i,n])=>[i.toLowerCase(),String(n)])),s=[...new Set((o.varyHeaders??[]).map(i=>String(i).toLowerCase()))].sort(),a=Object.fromEntries(s.map(i=>[i,t[i]??""])),r={providerId:String(o.providerId),cacheNamespace:String(o.cacheNamespace??o.providerId??"default"),method:e,canonicalUrl:eu(o.url),bodyHash:await Bc(us(o.body??null)),responseType:String(o.responseType??"text"),cacheScope:String(o.cacheScope??"none"),varyHeadersHash:await Bc(us(a)),sessionScopeId:o.cacheScope==="session"?String(o.sessionScopeId??""):""};if(r.cacheScope==="session"&&!r.sessionScopeId)throw new TypeError("sessionScopeId is required for session requests");return Object.freeze(r)}d(au,"createRequestKey");var Gn=class Gn{constructor(e,t,s={}){this.port=e,this.urlPolicy=t,this.diagnostics=s.diagnostics??null,this.cache=s.cache??null,this.settings=s.settings??null,this.inflight=new Map,this.circuitBreakers=new Map,this.domainStats=new Map}async request(e,t){t?.assertActive();let s=String(e.method??"GET").toUpperCase();if(this.settings){let m=this.settings.snapshot();e={...e,timeout:e.timeout??Math.max(1e3,Math.min(12e4,Number(m.httpTimeout)||5e3)),retryCount:e.retryCount??(["GET","HEAD"].includes(s)?Math.max(1,Math.min(10,Math.trunc(Number(m.httpRetryCount)||3)))-1:0),circuitThreshold:e.circuitThreshold??Number(m.circuitBreakerThreshold??3),circuitCooldownMs:e.circuitCooldownMs??Number(m.circuitBreakerCooldown??6e4)}}let a=e.cacheScope??"none";if(s!=="GET"&&a!=="none")throw new TypeError("Mutation requests cannot use generic cache/dedupe");let r=e.urlPolicy,i=this.urlPolicy.assertAllowed(e.url,r);if(s!=="GET"||a==="none")return this.executeUnderlying({...e,method:s,url:i.href,signal:t?.signal},r);let n=String(e.cacheNamespace??e.providerId??"default"),l=await au({...e,method:s,url:i.href,cacheScope:a,cacheNamespace:n});t?.assertActive();let c=us(l),h={scope:a,sessionScopeId:e.sessionScopeId};if(s==="GET"&&a!=="none"&&this.cache){let m=await this.cache.get(n,c,h);if(t?.assertActive(),m.hit)return m.value}let u=a==="public"&&this.cache?this.cache.generation(n):void 0,p=JSON.stringify([c,u??null]),g=this.inflight.get(p);if(!g){let m=new AbortController;g={controller:m,consumers:0,promise:Promise.resolve()},g.promise=this.executeUnderlying({...e,method:s,url:i.href,signal:m.signal},r).then(async f=>(this.cache&&(u==null||u===this.cache.generation(n))&&await this.cache.set(n,c,f,{...h,ttlMs:e.ttlMs??0,negative:e.negative===!0,generation:u}),f)).finally(()=>{this.inflight.get(p)===g&&this.inflight.delete(p),this.updateDiagnostics()}),this.inflight.set(p,g)}return this.consume(g,t)}async executeUnderlying(e,t){let s=new URL(e.url).hostname,a=Math.max(0,Math.min(9,Math.trunc(Number(e.retryCount??0)||0))),r=new Set((e.acceptableStatuses??[]).map(c=>Number(c)).filter(Number.isFinite)),i=this.ensureCircuit(s,e),n=!1,l=null;for(let c=0;c<=a;c+=1){if(e.signal?.aborted){l=new D("ABORTED","请求已取消",{source:e.providerId});break}let h=n?null:this.checkCircuit(s);if(h){l=new D("CIRCUIT_OPEN",`站点 ${s} 已熔断,${h.remaining}秒后重试`,{source:e.providerId,details:{domain:s,remainingSeconds:h.remaining}});break}i.state==="half-open"&&(i.probing=!0,n=!0);try{let u=await this.port.request(e);if(this.urlPolicy.assertFinalUrl(u.finalUrl||e.url,t),tu(u.responseText??u.data,u.status))throw new D("CF_BLOCKED",`Cloudflare challenge blocked: ${s}`,{source:e.providerId,details:{domain:s,status:Number(u.status)||0,contentLength:String(u.responseText??"").length}});if(r.has(Number(u.status)))return this.recordSuccess(s),u;if(u.status>=400){let p=[401,403].includes(u.status)?"AUTH_REQUIRED":u.status===404?"NOT_FOUND":u.status===429?"RATE_LIMITED":"NETWORK_ERROR";throw new D(p,`HTTP ${u.status}`,{source:e.providerId,retryable:u.status===429||u.status>=500,details:{status:u.status,domain:s}})}return this.recordSuccess(s),u}catch(u){let p=D.from(u,e.providerId);if(this.recordAttempt(s,!0),l=p,!p.retryable||c>=a||p.code==="CF_BLOCKED")break;try{await su(Number(e.retryDelayMs??250)*(c+1),e.signal)}catch(g){l=D.from(g,e.providerId);break}}}throw l&&["NETWORK_ERROR","TIMEOUT","CF_BLOCKED"].includes(l.code)&&this.recordBreakerFailure(s,e),n&&(i.probing=!1),this.diagnostics?.recordError(l),l}ensureCircuit(e,t={}){let s=this.circuitBreakers.get(e);return s?(t.circuitCooldownMs!=null&&(s.cooldownMs=Math.max(1e3,Number(t.circuitCooldownMs)||6e4)),t.circuitThreshold!=null&&(s.threshold=Math.max(1,Number(t.circuitThreshold)||3))):(s={state:"closed",failCount:0,openTime:0,cooldownMs:Math.max(1e3,Number(t.circuitCooldownMs??6e4)||6e4),threshold:Math.max(1,Number(t.circuitThreshold??3)||3),probing:!1},this.circuitBreakers.set(e,s)),s}checkCircuit(e){let t=this.circuitBreakers.get(e);if(!t)return null;if(t.state==="open"){let s=Date.now()-t.openTime;if(s=s.threshold)&&(s.state="open",s.openTime=Date.now(),s.probing=!1)}recordFailure(e,t={}){this.recordAttempt(e,!0),this.recordBreakerFailure(e,t)}getCircuitBreakerStatus(){return Object.fromEntries([...this.circuitBreakers].map(([e,t])=>[e,{...t}]))}getDomainStats(){return Object.fromEntries([...this.domainStats].map(([e,t])=>[e,{...t}]))}resetCircuitBreaker(e){this.circuitBreakers.delete(e)}resetAllCircuitBreakers(){this.circuitBreakers.clear()}clearDomainStats(){this.domainStats.clear()}consume(e,t){e.consumers+=1;let s=!1,a={release:d(()=>{s||(s=!0,e.consumers-=1,e.consumers===0&&!this.isSettled(e)&&e.controller.abort(),this.updateDiagnostics())},"release")},r;try{r=t?.ownRequestConsumer(a)}catch(l){throw a.release(),e.promise.catch(()=>{}),l}this.updateDiagnostics();let i=d(()=>{},"removeAbortListener");return(t?Promise.race([e.promise,new Promise((l,c)=>{let h=d(()=>c(new D("ABORTED","LifecycleScope 已释放",{source:t.id})),"onAbort");t.signal.addEventListener("abort",h,{once:!0}),i=d(()=>t.signal.removeEventListener("abort",h),"removeAbortListener")})]):e.promise).finally(()=>{i(),r?.(),a.release()})}isSettled(e){return![...this.inflight.values()].includes(e)}updateDiagnostics(){let e=[...this.inflight.values()].reduce((t,s)=>t+s.consumers,0);this.diagnostics?.updateRequests(e,this.inflight.size)}};d(Gn,"HttpService");var or=Gn;var Qn=class Qn{constructor(e){this.integrations=e}async resolve(e,t={}){let s=this.integrations.list("image.search-targets")[0];if(!s)throw new D("UNSUPPORTED","以图识图 Integration 不可用",{source:"ImageSearchService"});let a=this.integrations.getAdapter(s.id),r=String(e||"");if(r.startsWith("data:"))r=await a.upload(r,t);else{let i;try{i=new URL(r)}catch(n){throw new D("INVALID_URL","图片 URL 无效",{source:"ImageSearchService",cause:n})}if(!["http:","https:"].includes(i.protocol))throw new D("INVALID_URL","图片 URL 必须使用 HTTP/HTTPS",{source:"ImageSearchService"});r=i.href}return Object.freeze({imageUrl:r,targets:a.createTargets(r)})}};d(Qn,"ImageSearchService");var lr=Qn;var Yn=class Yn{constructor(e){this.port=qe(e,"NavigationPort",Je.navigation)}open(e,t){return this.port.open(String(e),t)}assign(e){return this.port.assign(String(e))}replace(e){return this.port.replace(String(e))}};d(Yn,"NavigationService");var cr=Yn;var Zn=class Zn{constructor(e,t=null){this.providers=e,this.integrations=t}async search(e,t={}){let s=[];for(let a of await this.providers.getAvailable("magnet",t))try{let r=await a.search(e,t);this.providers.updateHealth(a.id,{ok:!0}),Array.isArray(r)&&s.push(...r)}catch(r){this.providers.updateHealth(a.id,{ok:!1,error:r instanceof Error?r.message:String(r)})}return s}async listNative(e,t={}){let s=typeof e.providerId=="string"?e.providerId:"javdb",a=(this.integrations?.list("movie.magnets")??[]).find(i=>i.id===s);if(!a)return[];let r=this.integrations?.getAdapter(a.id);return typeof r?.listMagnets=="function"?r.listMagnets(e,t):[]}getBuiltInSources(){return(this.integrations?.list("magnet.search")??[]).flatMap(e=>{let t=this.integrations?.getAdapter(e.id);return typeof t?.getSources=="function"?t.getSources():[]})}async searchSource(e,t,s={}){for(let a of this.integrations?.list("magnet.search")??[]){let r=this.integrations?.getAdapter(a.id);if(r?.getSources?.().some(i=>i.id===e))return r.search(e,t,s)}return[]}getSourceTargetUrl(e,t,s={}){for(let a of this.integrations?.list("magnet.search")??[]){let r=this.integrations?.getAdapter(a.id);if(r?.getSources?.().some(i=>i.id===e))return r.targetUrl(e,t,s)}return null}assess(e){return xc(e)}};d(Zn,"MagnetService");var dr=Zn;var Xn=class Xn{constructor(e=null){this.integrations=e}normalize(e){return ee(e)}firstValid(...e){for(let t of e){let s=this.normalize(t);if(s)return s}return null}async resolve(e,t={}){let s=this.normalize(e.carNum);if(!s)return null;let a=this.integrations?.list("movie.search")??[],r=typeof e.providerId=="string"?e.providerId:null,i=r?a.filter(n=>n.id===r):[...a].sort((n,l)=>+(l.id==="javdb")-+(n.id==="javdb"));for(let n of i){let l=this.integrations?.getAdapter(n.id);if(typeof l?.resolveMovie!="function")continue;let c=await l.resolveMovie({...e,carNum:s},t);if(c)return c}return Object.freeze({...e,carNum:s})}async detail(e,t={}){let s=this.integrations?.list("movie.detail")??[],a=typeof e.providerId=="string"?e.providerId:e.movieId?"javdb":null,r=a?s.filter(i=>i.id===a):s;for(let i of r){let n=this.integrations?.getAdapter(i.id);if(typeof n?.getDetail=="function")return n.getDetail(e,t)}return null}async rankings(e={}){return this.playbackRankings(e)}async playbackRankings(e={}){for(let t of this.integrations?.list("movie.ranking")??[]){let s=this.integrations?.getAdapter(t.id);if(typeof s?.listRankings=="function")return s.listRankings(e)}return[]}async catalog(e,t={},s={}){let a=(this.integrations?.list("movie.catalog")??[]).find(i=>i.id===e);if(!a)throw new TypeError(`Movie catalog provider is unavailable: ${e}`);let r=this.integrations?.getAdapter(a.id);if(typeof r?.listCatalog!="function")throw new TypeError(`Movie catalog operation is unavailable: ${e}`);return r.listCatalog(t,s)}async people(e,t,s={}){let a=(this.integrations?.list("movie.credits")??[]).find(i=>i.id===e);if(!a)return Object.freeze({actors:Object.freeze([]),seller:null});let r=this.integrations?.getAdapter(a.id);return typeof r?.getPeople=="function"?r.getPeople(t,s):Object.freeze({actors:Object.freeze([]),seller:null})}async images(e,t,s={}){let a=(this.integrations?.list("movie.images")??[]).find(i=>i.id===e);if(!a)return[];let r=this.integrations?.getAdapter(a.id);return typeof r?.getImages=="function"?r.getImages(t,s):[]}async preview(e,t,s={}){let a=(this.integrations?.list("movie.preview")??[]).find(i=>i.id===e);if(!a)throw new TypeError(`Movie preview provider is unavailable: ${e}`);let r=this.integrations?.getAdapter(a.id);if(typeof r?.getPreviewForMovie!="function")throw new TypeError(`Movie preview operation is unavailable: ${e}`);return r.getPreviewForMovie(t,s)}sourceUrls(e,t){return Object.freeze(t.map(s=>{try{let a=this.integrations?.getAdapter(s),r=typeof a?.detailUrl=="function"?a.detailUrl(e):null;return r?Object.freeze({providerId:s,url:r}):null}catch{return null}}).filter(Boolean))}searchUrl(e,t){try{let s=this.integrations?.getAdapter(e);return typeof s?.searchUrl=="function"?s.searchUrl(t):null}catch{return null}}providerOrigin(e){try{let t=this.integrations?.getAdapter(e);return typeof t?.origin=="function"?t.origin():null}catch{return null}}matchesProviderUrl(e,t){try{let s=this.integrations?.getAdapter(e);return typeof s?.matchesUrl=="function"&&s.matchesUrl(t)}catch{return!1}}externalSites(e={}){let t=(this.integrations?.list("movie.external-sites")??[])[0],s=t&&this.integrations?.getAdapter(t.id);return typeof s?.getSites=="function"?s.getSites(e):[]}externalSiteOrigin(e,t={}){return this.externalSites(t).find(s=>s.id===e)?.baseUrl||""}async searchExternalSite(e,t,s={}){let a=(this.integrations?.list("movie.external-sites")??[])[0],r=a&&this.integrations?.getAdapter(a.id);return typeof r?.searchSite!="function"?Object.freeze({searchUrl:"",matches:Object.freeze([])}):r.searchSite(e,t,s)}externalNavigationLinks(){let e=(this.integrations?.list("navigation.external")??[])[0],t=e&&this.integrations?.getAdapter(e.id);return typeof t?.getNavigationLinks=="function"?t.getNavigationLinks():[]}};d(Xn,"MovieIdentityService");var hr=Xn;var eo=class eo{constructor(e,t){this.providers=e,this.integrations=t}submitWithIntegration(e,t,s={}){let a=this.integrations.getAdapter(e);if(typeof a.submit!="function")throw new TypeError(`Integration ${e} does not support offline submission`);return a.submit(t,s)}checkAccount(e,t={}){let s=this.integrations.getAdapter(e);if(typeof s.checkAccount!="function")throw new TypeError(`Integration ${e} does not support account checks`);return s.checkAccount(t)}searchFiles(e,t,s={}){let a=this.integrations.getAdapter(e);if(typeof a.searchFiles!="function")throw new TypeError(`Integration ${e} does not support file search`);return a.searchFiles(t,s)}renameFile(e,t,s,a={}){let r=this.integrations.getAdapter(e);if(typeof r.renameFile!="function")throw new TypeError(`Integration ${e} does not support file rename`);return r.renameFile(t,s,a)}getPlayUrl(e,t){let s=this.integrations.getAdapter(e);return typeof s.getPlayUrl=="function"?s.getPlayUrl(t):null}getIntegrationHomeUrl(e){let t=this.integrations.getAdapter(e);if(typeof t.homeUrl!="string")throw new TypeError(`Integration ${e} does not declare a home URL`);return t.homeUrl}async submit(e,t={}){let s=await this.providers.getAvailable("offline",t),a=[];for(let r of s)try{let i=await r.submit(e,t);return this.providers.updateHealth(r.id,{ok:!0}),i}catch(i){a.push(i),this.providers.updateHealth(r.id,{ok:!1,error:i instanceof Error?i.message:String(i)})}throw new AggregateError(a,s.length?"所有离线 Provider 均失败":"没有可用的离线 Provider")}};d(eo,"OfflineService");var ur=eo;var to=class to extends EventTarget{constructor(e){super(),this.window=e.windowRuntime??window,this.scope=e.scope,this.settings=e.settings??null,this.coarseQuery=this.window.matchMedia("(any-pointer: coarse)"),this.profile=this.calculate(),this.started=!1}calculate(){let e=this.window.innerWidth,t=(this.settings?.snapshot()??{}).mobileMode;if(t==="on")return"compact";if(t==="off")return e>=1200?"wide":"regular";let s=Math.min(this.window.innerWidth,this.window.innerHeight);return e<=767||this.coarseQuery.matches&&s<=480?"compact":e>=1200?"wide":"regular"}start(){if(this.started)return;this.started=!0;let e=d(()=>{let t=this.calculate();if(t===this.profile)return;let s=this.profile;this.profile=t,this.dispatchEvent(new CustomEvent("profile.changed",{detail:Object.freeze({previous:s,profile:t})}))},"update");this.scope.listen(this.window,"resize",e,{passive:!0}),this.scope.listen(this.window,"orientationchange",e,{passive:!0}),this.scope.listen(this.coarseQuery,"change",e),this.settings&&this.scope.listen(this.settings,"settings.changed",e),e()}current(){return this.profile}};d(to,"ProfileService");var pr=to;var so=class so{constructor(e){this.integrations=e}async list(e,t={}){for(let s of this.integrations.list("movie.related")){let a=this.integrations.getAdapter(s.id);if(typeof a.listRelated=="function")return a.listRelated(e,t)}return[]}};d(so,"RelatedService");var gr=so;var ao=class ao{constructor(e){this.integrations=e}async list(e,t={}){for(let s of this.integrations.list("movie.reviews")){let a=this.integrations.getAdapter(s.id);if(typeof a.listReviews=="function")return a.listReviews(e,t)}return[]}};d(ao,"ReviewService");var mr=ao;var Ft="javstore",Oc=new Set([Ft]),ro=class ro{constructor(e,t=null){this.providers=e,this.integrations=t}isEnabled(e){return e?.enableLoadScreenShot!=="no"}parseScreenshotProviders(e){if(Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}return[]}getScreenshotSettings(e){return{mode:e?.screenshotMode==="manual"?"manual":"auto",providers:this.parseScreenshotProviders(e?.screenshotProviders)}}getEnabledProviders(e){let t=this.parseScreenshotProviders(e?.screenshotProviders);return Ls.map(s=>({...s,...t.find(a=>a?.id===s.id)||{}})).filter(s=>s.enabled!==!1).sort((s,a)=>Number(s.priority??100)-Number(a.priority??100))}async resolve(e,t={}){if(t.settings&&!t.allowWhenDisabled&&!this.isEnabled(t.settings))return null;let s=t.settings?this.getEnabledProviders(t.settings):null,a=s?new Set(s.map(r=>r.id)):null;if(s&&!s.length)return null;if(t.providerId){if(a&&!a.has(t.providerId))return null;let r=this.providers.get?.(t.providerId);return r?r.enabled===!1||!r.capabilities?.includes("screenshot")?null:this.resolveFromProvider(r,e,t):this.resolveIntegration(t.providerId,e,t)}for(let r of await this.providers.getAvailable("screenshot",t)){if(a&&!a.has(r.id))continue;let i=await this.resolveFromProvider(r,e,t);if(i)return i}return a&&!a.has(Ft)?null:this.resolveIntegration(Ft,e,t)}async resolveFromProvider(e,t,s){try{let a=await e.resolve(t,s);if(this.providers.updateHealth(e.id,{ok:!0}),a)return a}catch(a){this.providers.updateHealth(e.id,{ok:!1,error:a instanceof Error?a.message:String(a)})}return null}async resolveIntegration(e,t,s){if(!Oc.has(e)||s.settings&&!s.allowWhenDisabled&&!this.isEnabled(s.settings))return null;let a=this.integrations?.list("movie.images")?.find(n=>n.id===e);if(!a)return null;let r=this.integrations?.getAdapter(a.id);if(typeof r?.getImages!="function")return null;let i=await r.getImages(t,s);return Array.isArray(i)&&i.length?i:null}getSearchUrl(e,t=null){if(!Oc.has(Ft)||t&&!this.isEnabled(t)||t&&!this.getEnabledProviders(t).some(s=>s.id===Ft))return null;for(let s of this.integrations?.list("movie.images")??[]){if(s.id!==Ft)continue;let a=this.integrations?.getAdapter(s.id);if(typeof a?.getSearchUrl=="function")return a.getSearchUrl(e)}return null}};d(ro,"ScreenshotService");var fr=ro;var io="translation_cache_v2",no="translation:v1:",oo=class oo{constructor(e,t=null){this.integrations=e,this.storage=t,this.memoryCache=new Map,this.inflight=new Map,this.legacyCache=null,this.hydrationPromise=null,this.cacheGeneration=0,this.persistTimer=null}cacheKey(e,t,s){return`${no}${t}:${s}:${e}`}readLegacyCache(){if(this.legacyCache!==null)return this.legacyCache;try{let e=JSON.parse(this.storage?.getLocal?.("jhs_translate")||"{}");this.legacyCache=e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch{this.legacyCache={}}return this.legacyCache}hydrate(){if(this.hydrationPromise)return this.hydrationPromise;let e=this.cacheGeneration;return this.hydrationPromise=(async()=>{if(!this.storage)return;let t=this.storage,s=[],a=!1;try{let r=await t.get(io);for(let[n,l]of Object.entries(r?.entries||{}))e===this.cacheGeneration&&typeof l?.value=="string"&&Number(l.expiresAt)>Date.now()?this.memoryCache.set(n,{value:l.value,expiresAt:Number(l.expiresAt),lastUsed:Number(l.lastUsed)||Date.now()}):a=!0;let i=await t.keys();for(let n of i.filter((l=>l.startsWith(no)))){let l=await t.get(n);e===this.cacheGeneration&&typeof l?.value=="string"&&Number(l.expiresAt)>Date.now()&&this.memoryCache.set(n,{value:l.value,expiresAt:Number(l.expiresAt),lastUsed:Number(l.lastUsed)||Date.now()}),s.push(n),a=!0}e===this.cacheGeneration&&(this.prune()||a)&&this.persistNow(e).then((()=>Promise.all(s.map((n=>t.remove(n)))))).catch((()=>{}))}catch{}})()}prune(){let e=Date.now(),t=!1;for(let[a,r]of this.memoryCache)r.expiresAt<=e&&(this.memoryCache.delete(a),t=!0);let s=this.memoryCache.size-1e3;if(s>0)for(let[a]of[...this.memoryCache].sort(((r,i)=>r[1].lastUsed-i[1].lastUsed)).slice(0,s))this.memoryCache.delete(a),t=!0;return t}schedulePersist(){if(!this.storage||this.persistTimer!==null)return;let e=this.cacheGeneration;this.persistTimer=setTimeout((()=>{this.persistTimer=null,this.persistNow(e).catch((()=>{}))}),300)}async persistNow(e=this.cacheGeneration){!this.storage||e!==this.cacheGeneration||(this.prune(),await this.storage.set(io,{version:2,entries:Object.fromEntries(this.memoryCache)}))}remember(e,t,s=this.cacheGeneration){if(s===this.cacheGeneration){let a=Date.now();this.memoryCache.set(e,{value:t,expiresAt:a+2592e6,lastUsed:a}),this.prune(),this.schedulePersist()}return t}async clearCache(){if(this.cacheGeneration+=1,this.persistTimer!==null&&clearTimeout(this.persistTimer),this.persistTimer=null,this.memoryCache.clear(),this.legacyCache={},this.storage?.removeLocal?.("jhs_translate"),this.storage){let e=this.storage;try{let t=await e.keys();await e.remove(io),await Promise.all(t.filter((s=>s.startsWith(no))).map((s=>e.remove(s))))}catch{}}this.hydrationPromise=Promise.resolve()}async inspectCache(){return await this.hydrate(),this.prune(),{version:2,size:this.memoryCache.size,entries:Object.fromEntries(this.memoryCache)}}async translate(e,t={}){let s=t.sourceLanguage??"ja",a=t.targetLanguage??"zh-CN",r=this.cacheKey(e,s,a),i=this.cacheGeneration,n=this.memoryCache.get(r);if(n?.expiresAt>Date.now())return n.lastUsed=Date.now(),this.schedulePersist(),n.value;n&&this.memoryCache.delete(r);let l=t.cacheAlias&&this.readLegacyCache()[t.cacheAlias];if(s==="ja"&&a==="zh-CN"&&typeof l=="string"&&l)return this.remember(r,l,i);if(await this.hydrate(),n=this.memoryCache.get(r),n?.expiresAt>Date.now())return n.lastUsed=Date.now(),this.schedulePersist(),n.value;let c=this.inflight.get(r);if(c)return c;let h=(async()=>{let u=this.integrations.list("text.translate")[0],p=u&&this.integrations.getAdapter(u.id);if(typeof p?.translate!="function")throw new TypeError(u?`Translation operation is unavailable: ${u.id}`:"Translation provider is unavailable");let g=await p.translate(e,{...t,sourceLanguage:s,targetLanguage:a});return typeof g=="string"?this.remember(r,g,i):g})().finally((()=>this.inflight.delete(r)));return this.inflight.set(r,h),h}};d(oo,"TranslationService");var vr=oo;var lo=class lo{constructor(e){this.integrations=e}async search(e,t,s={}){let a=this.integrations.list("subtitle.search").find(i=>i.id===e);if(!a)return[];let r=this.integrations.getAdapter(a.id);return typeof r?.search=="function"?r.search(t,s):[]}async download(e,t,s={}){let a=this.integrations.list("subtitle.download").find(i=>i.id===e);if(!a)throw new TypeError(`Subtitle provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.download!="function")throw new TypeError(`Subtitle download is unavailable: ${e}`);return r.download(t,s)}};d(lo,"SubtitleService");var br=lo;var co=class co{constructor(e){this.integrations=e}async login(e,t,s={}){let a=this.integrations.list("account.login").find(i=>i.id===e);if(!a)throw new TypeError(`Account provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.login!="function")throw new TypeError(`Account login is unavailable: ${e}`);return r.login(t,s)}};d(co,"AccountService");var wr=co;var ho=class ho extends EventTarget{constructor(e,t={}){super(),this.storage=e,this.validators=t.validators??{},this.normalizers=t.normalizers??{},this.afterPersist=t.afterPersist??null,this.snapshotValue=Object.freeze({}),this.writeChain=Promise.resolve()}async load(e="setting"){return this._enqueue(()=>this._withSettingLock(()=>this._readSnapshot(e)))}async refresh(e="setting"){return this._enqueue(()=>this._withSettingLock(async()=>{let t=this.snapshotValue,s=await this._readSnapshot(e),r=[...new Set([...Object.keys(t),...Object.keys(s)])].filter(i=>t[i]!==s[i]);return r.length&&this.dispatchEvent(new CustomEvent("settings.changed",{detail:Object.freeze({name:r.length===1?r[0]:null,value:void 0,names:Object.freeze([...r]),snapshot:s})})),s}))}snapshot(){return this.snapshotValue}waitForIdle(){return this.writeChain}async set(e,t,s="setting"){return this.update(a=>{a[e]=t},s)}async patch(e,t="setting"){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("Settings patch must be an object");return this.update(s=>{Object.assign(s,e)},t)}async replace(e,t="setting"){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("Settings replacement must be an object");return this.update(s=>{for(let a of Object.keys(s))delete s[a];Object.assign(s,e)},t)}async unset(e,t="setting"){let s=Array.isArray(e)?e:[e];if(!s.every(a=>typeof a=="string"&&a))throw new TypeError("unset names must be non-empty strings");return this.update(a=>{for(let r of s)delete a[r]},t)}async update(e,t="setting"){if(typeof e!="function")throw new TypeError("Settings update mutator must be a function");return this._enqueue(()=>this._withSettingLock(async()=>{let s=await this.storage.get(t),a=s&&typeof s=="object"&&!Array.isArray(s)?s:{},r={...a},i=e(r);if(i&&typeof i=="object"&&typeof i.then=="function")throw new TypeError("Settings update mutator must be synchronous");for(let[h,u]of Object.entries(this.normalizers))Object.prototype.hasOwnProperty.call(r,h)&&typeof u=="function"&&(r[h]=u(r[h]));let n=Object.freeze(r),l=[...new Set([...Object.keys(a),...Object.keys(n)])].filter(h=>a[h]!==n[h]);for(let h of l){let u=this.validators[h];if(u&&Object.prototype.hasOwnProperty.call(n,h)&&!u(n[h]))throw new TypeError(`Invalid setting: ${h}`)}let c=Object.freeze([...l]);if(!c.length)return this.snapshotValue=n,n;if(await this.storage.set(t,n),this.snapshotValue=n,c.length){let h=c.length===1?c[0]:null;this.dispatchEvent(new CustomEvent("settings.changed",{detail:Object.freeze({name:h,value:h?n[h]:void 0,names:c,snapshot:n})}))}try{await this.afterPersist?.(n,c)}catch(h){typeof globalThis.clog?.error=="function"&&globalThis.clog.error("[settings] afterPersist failed (ignored)",h)}return n}))}async _readSnapshot(e){let t=await this.storage.get(e);return this.snapshotValue=Object.freeze(t&&typeof t=="object"&&!Array.isArray(t)?{...t}:{}),this.snapshotValue}_enqueue(e){let t=this.writeChain.then(e);return this.writeChain=t.then(()=>{},()=>{}),t}async _withSettingLock(e){let t=globalThis.navigator?.locks;return t?.request?t.request("jhs_setting_lock",()=>e()):e()}};d(ho,"SettingsService");var yr=ho;var uo=class uo{constructor(e){this.port=qe(e,"StoragePort",Je.storage)}get(e){return this.port.get(e)}set(e,t){return this.port.set(e,t)}remove(e){return this.port.remove(e)}keys(){return this.port.keys()}getLocal(e){return this.port.getLocal(e)}setLocal(e,t){return this.port.setLocal(e,t)}removeLocal(e){return this.port.removeLocal(e)}getValue(e,t){return this.port.getValue(e,t)}setValue(e,t){return this.port.setValue(e,t)}removeValue(e){return this.port.removeValue(e)}};d(uo,"StorageService");var jr=uo;var go=class go{constructor(e,t,s,a){this.http=e,this.baseUrl=new URL(t.endsWith("/")?t:`${t}/`),this.username=s,this.password=a,this.folderName=null}authHeaders(){let e=new TextEncoder().encode(`${this.username}:${this.password}`),t="";for(let s of e)t+=String.fromCharCode(s);return{Authorization:`Basic ${btoa(t)}`,Depth:"1"}}async request(e,t,s={},a,r={}){let i=new URL(t.replace(/^\/+/,""),this.baseUrl),n=await this.http.request({providerId:"webdav",method:e,url:i.href,headers:{...this.authHeaders(),...s},body:a,responseType:"text",cacheScope:"none",...r,timeout:1e4,urlPolicy:{trustClass:"user-local",expectedOrigin:this.baseUrl.origin}});return n.data??n.responseText??""}async ensureFolder(e){await this.request("MKCOL",e,{},void 0,{acceptableStatuses:[405,409]})}async backup(e,t,s,a){let r=d(async(i,n,l)=>{let c=performance.now(),h="success",u,p;try{return await n()}catch(g){if(h="error",g&&typeof g=="object"){let m=g;u=typeof m.code=="string"?m.code:void 0,p=Number.isFinite(m.details?.status)?m.details.status:void 0}throw g}finally{try{a?.({stage:i,result:h,durationMs:Math.round(performance.now()-c),...l==null?{}:{bytes:l},...u?{code:u}:{},...p==null?{}:{status:p},timeoutMs:1e4})}catch{}}},"runStage");await r("建目录",()=>this.ensureFolder(e)),await r("上传",()=>this.request("PUT",`${e}/${t}`,{"Content-Type":"text/plain"},s),s.length)}async getFileList(e){let t=String(await this.request("PROPFIND",e,{"Content-Type":"application/xml"},'')),s=new DOMParser().parseFromString(t,"text/xml").getElementsByTagNameNS("DAV:","response"),a=[];for(let r=1;ri.getElementsByTagNameNS("DAV:",u)[0]?.textContent||"","node"),l=n("href"),c=n("displayname")||decodeURIComponent(l.replace(/\/$/,"").split("/").pop()||""),h=n("getcontentlength");h!=="0"&&a.push({fileId:c,name:c,size:Number(h),createTime:n("creationdate")||n("getlastmodified")})}return a.reverse()}async deleteFile(e){await this.request("DELETE",`${this.folderName}/${encodeURI(e)}`,{"Cache-Control":"no-cache"})}async getBackupList(e){return this.folderName=e,await this.ensureFolder(e),this.getFileList(e)}async getFileContent(e){return String(await this.request("GET",`${this.folderName}/${e}`,{Accept:"application/octet-stream"}))}};d(go,"WebDavClient");var po=go,mo=class mo{constructor(e,t=void 0,s=void 0){this.http=e,this.credential=t,this.settings=s}createClient(e){return new po(this.http,e.url,e.username,e.password)}async getProfile(){let e=this.settings?.snapshot?.()||{},t=this.credential?await this.credential.get("jhs_webdav_password"):"";return{url:String(e.webDavUrl||""),username:String(e.webDavUsername||""),password:t}}async saveProfile(e={}){if(!this.settings||!this.credential)throw new Error("WebDAV 配置服务未初始化");let t=await this.getProfile(),s=Object.prototype.hasOwnProperty.call(e,"password");s&&await this.credential.set("jhs_webdav_password",String(e.password||""));try{await this.settings.update(a=>{for(let r of["url","username"])Object.prototype.hasOwnProperty.call(e,r)&&(a[r==="url"?"webDavUrl":"webDavUsername"]=String(e[r]||""))})}catch(a){throw s&&await this.credential.set("jhs_webdav_password",t.password),a}return this.getProfile()}};d(mo,"WebDavService");var Sr=mo;var Ie=Object.freeze({installationSecret:"jhs_credential_install_secret",webDavPassword:"jhs_webdav_password",javdbToken:"jhs_appAuthorization"}),fo=class fo{constructor(e,t=globalThis.localStorage){this.storage=e,this.legacyStorage=t,this.cleanupValues=new Map,this.cleanupTargets=new Map}async installationSecret(){return String(await this.storage.getValue(Ie.installationSecret,"")||this.legacyStorage?.getItem?.(Ie.installationSecret)||"x7k9p3")}generateSecret(){return btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32))))}async decodeLegacy(e,t){let s=e.replace(/^AES:/,""),a=e.startsWith("AES:");try{a||(a=/^[A-Za-z0-9+/]+={0,2}$/.test(s)&&atob(s).length>=28)}catch{}return a?Xe(s,t||await this.installationSecret()):e}async decode(e){if(e&&typeof e=="object"){if(e.schema===2&&typeof e.id=="string"&&e.deleted===!0&&!Object.hasOwn(e,"secret")&&!Object.hasOwn(e,"ciphertext"))return"";if(e.schema!==2||typeof e.id!="string"||typeof e.secret!="string"||typeof e.ciphertext!="string")throw new Error("凭证格式无效");return Xe(e.ciphertext,e.secret,!1)}let t=String(e||"");return t?this.decodeLegacy(t):""}async get(e){try{return await this.decode(await this.storage.getValue(e,""))}catch{return""}}async set(e,t){let s=String(t||"");if(!s)return await this.remove(e),"";let a=this.generateSecret(),r={schema:2,id:crypto.randomUUID(),secret:a,ciphertext:await Xt(s,a)};await this.storage.setValue(e,r);let i=await this.storage.getValue(e,"");if(JSON.stringify(i)!==JSON.stringify(r)||await this.decode(i)!==s)throw new Error("凭证存储回读校验失败");return s}async remove(e){let t={schema:2,id:crypto.randomUUID(),deleted:!0};await this.storage.setValue(e,t);let s=await this.storage.getValue(e,"");if(JSON.stringify(s)!==JSON.stringify(t)||await this.decode(s)!=="")throw new Error("凭证删除回读校验失败")}async migrateLegacy(e,t={}){let s=this.legacyStorage?.getItem?.(Ie.installationSecret)||"",a=d(p=>this.decodeLegacy(p,s),"decodeLegacy"),r=[],i={},n=[],l=e?.snapshot?.()||{},c=this.legacyStorage?.getItem?.(Ie.javdbToken)||"",h=String(l.webDavPassword||"");for(let[p,g]of[[Ie.javdbToken,c],[Ie.webDavPassword,h]]){let m;try{m=await this.storage.getValue(p,"")}catch{r.push({key:p,code:"CREDENTIAL_MIGRATION_READ_FAILED"});continue}if(!m&&!g||m&&typeof m=="object"&&(p===Ie.javdbToken||!g||m.deleted===!0))continue;let f,v;try{f=m?await this.decode(m):await a(g),m&&typeof m=="string"&&p===Ie.javdbToken&&(f=await a(f)),v=g?await a(g):""}catch{r.push({key:p,code:"LEGACY_CREDENTIAL_UNREADABLE"});continue}try{(!m||typeof m=="string")&&await this.set(p,f)}catch{r.push({key:p,code:"CREDENTIAL_MIGRATION_WRITE_FAILED"});continue}g&&f===v&&await this.get(p)===f&&(this.cleanupTargets.set(p,f),p===Ie.webDavPassword&&(i.webDavPassword=g))}let u=await this.validateLegacyCleanup({settingKeys:Object.keys(i),settingValues:i,pageKeys:n});return t.deferCleanup||(u.settingKeys.length&&e?.update&&await e.update(p=>{for(let g of u.settingKeys)p[g]===i[g]&&delete p[g]}),await this.cleanupLegacyPageStorage(u.pageKeys,e)),{migrated:!!(c||h||s),cleanup:u,issues:r}}async validateLegacyCleanup(e){let t=[];if(!globalThis.navigator?.locks?.request)return{...e,settingKeys:t};for(let s of e.settingKeys||[])s==="webDavPassword"&&this.cleanupTargets.has(Ie.webDavPassword)&&await this.get(Ie.webDavPassword)===this.cleanupTargets.get(Ie.webDavPassword)&&t.push(s);return{...e,settingKeys:t}}async cleanupLegacyPageStorage(e=[],t=null){this.cleanupValues.clear(),this.cleanupTargets.clear()}};d(fo,"CredentialService");var xr=fo;var vo=class vo{constructor(e){this.port=qe(e,"StylePort",Je.style)}register(e,t){return this.port.register(e,t)}remove(e){return this.port.remove(e)}};d(vo,"StyleRegistry");var kr=vo;var bo=class bo{constructor(){this.owners=new Map,this.handlers=new Map,this.activateOwner=null,this.ownerEnabled=new Map}setOwnerEnabled(e,t){if(!this.owners.has(e))throw new Error(`Unknown command owner: ${e}`);this.ownerEnabled.set(e,t)}isAvailable(e){return this.owners.has(e)&&this.ownerEnabled.get(e)!==!1}setActivator(e){this.activateOwner=e}registerOwner(e,t){let s=this.owners.get(e);if(s&&s!==t)throw new Error(`Duplicate command owner: ${e}`);this.owners.set(e,t)}registerHandler(e,t,s){if(this.owners.get(e)!==s)throw new Error(`Feature ${s} does not own command ${e}`);if(this.handlers.has(e))throw new Error(`Duplicate command handler: ${e}`);this.handlers.set(e,t)}async execute(e,...t){let s=this.owners.get(e);if(!s)throw new Error(`Unknown command: ${e}`);if(!this.handlers.has(e)){if(!this.activateOwner)throw new Error("Command activator is not configured");await this.activateOwner(s)}let a=this.handlers.get(e);if(!a)throw new Error(`Feature ${s} did not register ${e}`);return a(...t)}};d(bo,"CommandRegistry");var Cr=bo;var wo=class wo{constructor(e=null){this.values=new Map,this.diagnostics=e}register(e,t){if(typeof e!="symbol")throw new TypeError("Dependency token must be a symbol");if(this.values.has(e)){let s=new D("DUPLICATE_TOKEN",`Duplicate dependency token: ${String(e)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(s),s}return this.values.set(e,t),this}resolveDeclared(e){let t=Object.create(null),s=new Set;for(let a of e){if(s.has(a)){let r=new D("DUPLICATE_TOKEN",`Duplicate declared dependency: ${String(a)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(r),r}if(s.add(a),!this.values.has(a)){let r=new D("MISSING_DEPENDENCY",`Missing declared dependency: ${String(a)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(r),r}Object.defineProperty(t,a,{value:this.values.get(a),enumerable:!0})}return Object.freeze(t),new Proxy(t,{get:d((a,r,i)=>{if((typeof r=="symbol"?Symbol.keyFor(r):null)?.startsWith("jhs.")&&!s.has(r)){let l=new D("UNDECLARED_DEPENDENCY",`Undeclared dependency access: ${String(r)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(l),l}return Reflect.get(a,r,i)},"get")})}};d(wo,"DependencyContainer");var _r=wo;var yo=class yo{constructor(e){this.container=e.container,this.commands=e.commands,this.diagnostics=e.diagnostics,this.disabled=new Set($t(e.disabled)),this.site=e.site??"unknown",this.route=e.route??"unknown",this.manifests=new Map,this.contributionOwners=new Map,this.contributionManifests=new Map,this.activations=new Map,this.contributionScopes=new Map,this.commands.setActivator(t=>this.activate(t).then(()=>{}))}setContributionManifests(e){this.contributionManifests=new Map(e.map(t=>[t.id,t]))}activeSurfaces(){return this.route==="list"?new Set(["global","list","list-page","list-card"]):this.route==="detail"||this.route==="owned-detail"?new Set(["global","detail","detail-page",this.route]):new Set(["global",this.route])}register(e){let t=Re(e);if(this.manifests.has(t.id))throw new Error(`Duplicate feature: ${t.id}`);for(let s of t.contributes){let a=this.contributionOwners.get(s);if(a)throw new Error(`Duplicate contribution ownership: ${s} (${a}, ${t.id})`)}this.manifests.set(t.id,t);for(let s of t.contributes)this.contributionOwners.set(s,t.id);for(let s of t.providesCommands)this.commands.registerOwner(s,t.id),this.commands.setOwnerEnabled(s,this.isEligible(t))}isEligible(e){return!(e.kind!=="system"&&this.disabled.has(e.id)||e.sites.length&&!e.sites.includes(this.site)||e.routes.length&&!e.routes.includes(this.route))}isContributionEnabled(e,t,s){let a=this.manifests.get(e);if(!a||a.sites.length&&!a.sites.includes(this.site)||!a.contributes.includes(t)||a.kind!=="system"&&this.disabled.has(a.id))return!1;if(a.kind==="system")return!0;let r=this.contributionManifests.get(t);return r?.routes?.length&&!r.routes.includes(this.route)||r?.surfaces?.length&&!r.surfaces.some(i=>this.activeSurfaces().has(i))?!1:!this.disabled.has(t)&&!this.disabled.has(s)}isFeatureDisableable(e){let t=this.manifests.get(e);if(!t)throw new Error(`Unknown feature: ${e}`);return t.kind!=="system"&&t.disableable!==!1}resolveDeclaredDependencies(e){return this.container.resolveDeclared(e)}async getScope(e){return(await this.activate(e)).scope}getContributionScope(e,t,s){if(!this.isContributionEnabled(e,t,s))return Promise.reject(new Error(`Contribution is disabled or ineligible: ${t}`));let a=this.contributionScopes.get(t);return(!a||a.disposed)&&(a=new te(`contribution:${t}`,{onChange:d(r=>this.diagnostics.updateScope(r),"onChange")}),this.contributionScopes.set(t,a)),Promise.resolve(a)}activate(e){let t=this.activations.get(e);if(t)return t;let s=this.manifests.get(e);if(!s)return Promise.reject(new Error(`Unknown feature: ${e}`));if(!this.isEligible(s))return Promise.reject(new Error(`Feature is disabled or ineligible: ${e}`));let a=this.activateManifest(s);return this.activations.set(e,a),a.catch(()=>this.activations.delete(e)),a}async activateManifest(e){let t=performance.now(),s=new te(`feature:${e.id}`,{onChange:d(a=>this.diagnostics.updateScope(a),"onChange")});try{let a=this.container.resolveDeclared(e.requires),r=Object.freeze(e.contributes.filter(n=>!this.disabled.has(n))),i=await e.activate(a,Object.freeze({scope:s,enabledContributions:r,route:this.route}));for(let n of e.providesCommands){let l=i?.commands?.[n];if(typeof l!="function")throw new Error(`Feature ${e.id} did not provide command ${n}`);this.commands.registerHandler(n,l,e.id)}return this.diagnostics.setFeature(e.id,!0),r.forEach(n=>this.diagnostics.setContribution(n,!0)),this.diagnostics.recordStartup(e.id,performance.now()-t),Object.freeze({manifest:e,scope:s,enabledContributions:r,dispose:d(()=>{i?.dispose?.();for(let n of e.contributes){let l=this.contributionScopes.get(n);l&&(l.dispose(),this.contributionScopes.delete(n))}s.dispose(),this.diagnostics.setFeature(e.id,!1),r.forEach(n=>this.diagnostics.setContribution(n,!1)),this.activations.delete(e.id)},"dispose")})}catch(a){throw s.dispose(),this.diagnostics.recordError(a),a}}async start(){for(let e of this.manifests.values())this.isEligible(e)&&(e.startup==="eager"?await this.activate(e.id):e.startup==="idle"&&(globalThis.requestIdleCallback??(s=>setTimeout(s,0)))(()=>{this.activate(e.id).catch(()=>{})}))}getActiveFeatureIds(){return[...this.activations.keys()]}};d(yo,"FeatureRuntime");var $r=yo;var jo=class jo{constructor(e=null){this.providers=new Map,this.health=new Map,this.diagnostics=e}register(e){if(!e||typeof e.id!="string"||!Array.isArray(e.capabilities))throw new TypeError("Provider requires id and capabilities");if(this.providers.has(e.id))throw new Error(`Duplicate provider: ${e.id}`);return this.providers.set(e.id,Object.freeze({priority:0,enabled:!0,...e})),e}get(e){return this.providers.get(e)??null}list(e){return[...this.providers.values()].filter(t=>t.enabled!==!1&&t.capabilities.includes(e)).sort((t,s)=>Number(s.priority??0)-Number(t.priority??0))}async getAvailable(e,t){let s=[];for(let a of this.list(e))(typeof a.isAvailable!="function"||await a.isAvailable(t))&&s.push(a);return s}updateHealth(e,t){if(!this.providers.has(e))throw new Error(`Unknown provider: ${e}`);this.health.set(e,Object.freeze({...t,updatedAt:Date.now()})),this.diagnostics?.updateProvider(e,t)}getHealth(e){return this.health.get(e)??null}};d(jo,"ProviderRegistry");var Tr=jo;var Uc=Object.freeze({none:{cacheScope:"none",ttlMs:0},"public-1d":{cacheScope:"public",ttlMs:864e5},"public-5m":{cacheScope:"public",ttlMs:3e5},"public-7d":{cacheScope:"public",ttlMs:6048e5},"external-detail-v1":{cacheScope:"public",ttlMs:6048e5,cacheNamespace:"external-detail-v1"},"screenshot-7d":{cacheScope:"public",ttlMs:6048e5,cacheNamespace:"screenshot"},"session-configured":{cacheScope:"session",ttlMs:36e5},"source-configured":{cacheScope:"public",ttlMs:216e5,cacheNamespace:"source",getOnly:!0}});function ru(o,e,t={}){let s=o.cachePolicy==="none"?"none":o.cachePolicy?.[e],a={...Uc[s]||Uc.none};return a.getOnly&&String(t.method||"GET").toUpperCase()!=="GET"?Object.freeze({cacheScope:"none",ttlMs:0}):(delete a.getOnly,s==="session-configured"&&(a.sessionScopeId=String(t.sessionScopeId||`${o.id}-session`)),Object.freeze(a))}d(ru,"resolveIntegrationCachePolicy");function iu(o,e){let t=d((a,r={})=>ru(e,a,r),"policyFor"),s=d(a=>{if(a.capability&&e.capabilities.includes(a.capability))return a.capability;if(e.capabilities.length===1)return e.capabilities[0];let r=String(a.providerId||"");return e.capabilities.find(i=>r.includes(String(i).split(".").pop()||""))||e.capabilities[0]},"inferCapability");return Object.freeze({request(a,r,i){let n=typeof a=="string",l=n?a:s(a),c=n?r||{}:a||{},h=n?i:r;if(!e.capabilities.includes(l))throw new TypeError(`Integration ${e.id} does not declare capability ${l}`);let u=t(l,c),p={...c,...u};return delete p.capability,o.request(p,h)}})}d(iu,"createIntegrationRequestFacade");var So=class So{constructor(e,t){this.container=e,this.diagnostics=t,this.manifests=new Map,this.adapters=new Map}register(e){try{let t=J(e);if(this.manifests.has(t.id))throw new Error(`Duplicate integration: ${t.id}`);this.manifests.set(t.id,t)}catch(t){throw this.diagnostics.recordError(t),t}}list(e){return[...this.manifests.values()].filter(t=>t.capabilities.includes(e))}getAdapter(e){let t=this.adapters.get(e);if(t)return t;let s=this.manifests.get(e);if(!s)throw new Error(`Unknown integration: ${e}`);try{let a=this.container.resolveDeclared(s.requires),r=Object.create(null);for(let l of s.requires)Object.defineProperty(r,l,{value:l===y.http?iu(a[l],s):a[l],enumerable:!0});Object.freeze(r);let i=s.createClient(r),n=s.createAdapter(i,r);return this.adapters.set(e,n),n}catch(a){throw this.diagnostics.recordError(a),a}}};d(So,"IntegrationRegistry");var Ar=So;var nu=new Set(["live","nextNavigation","manual"]),ou=new Set(["boolean","select","number","text","password","json"]),lu=new Set(["full","quick"]);function cu(o){if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError("Setting descriptor must be an object");let e=String(o.key??o.id??"");if(!e)throw new TypeError("Setting descriptor requires key (or id)");if(!o.owner)throw new TypeError(`Setting descriptor requires owner: ${e}`);let t=String(o.type??(o.defaultValue!=null&&typeof o.defaultValue=="boolean"?"boolean":"text"));if(!ou.has(t))throw new TypeError(`Setting descriptor has invalid type: ${e} (${t})`);let s=o.effect??"live";if(!nu.has(s))throw new TypeError(`Setting descriptor has invalid effect: ${e} (${s})`);let a=Array.isArray(o.surfaces)?[...new Set(o.surfaces)].filter(r=>lu.has(r)):[];if(o.surfaces!=null&&!Array.isArray(o.surfaces))throw new TypeError(`Setting descriptor surfaces must be an array: ${e}`);return Object.freeze({...o,key:e,owner:String(o.owner),label:String(o.label??o.key??e),description:o.description==null?"":String(o.description),type:t,effect:s,surfaces:Object.freeze(a),validate:typeof o.validate=="function"?o.validate:null,normalize:typeof o.normalize=="function"?o.normalize:null,contribution:o.contribution==null?void 0:String(o.contribution)})}d(cu,"normalizeSettingDescriptor");var xo=class xo{constructor(){this.descriptors=new Map}register(e){let t=cu(e);if(this.descriptors.has(t.key))throw new Error(`Duplicate setting descriptor: ${t.key}`);return this.descriptors.set(t.key,t),this}list(e={}){let t=e.surfaces;return[...this.descriptors.values()].filter(s=>!(s.contribution&&e.disabledContributions?.has(s.contribution)||t&&t.length&&!s.surfaces.includes(t[0])&&!t.some(a=>s.surfaces.includes(a))))}get(e){return this.descriptors.get(e)??null}isValid(e,t){let s=this.descriptors.get(e);return s&&typeof s.validate=="function"?s.validate(t)===!0:!0}normalizers(){return Object.fromEntries([...this.descriptors.values()].filter(e=>typeof e.normalize=="function").map(e=>[e.key,e.normalize]))}};d(xo,"SettingsRegistry");var Pr=xo;function zc(o){let e={type:"boolean",effect:"live"},t="yes",s="no",a=d((i,n,l,c={})=>o.register({key:i,owner:n,label:l,...e,defaultValue:c.defaultValue??t,...c}),"toggle"),r=d((i,n,l,c)=>{let h=Number(i);return Number.isFinite(h)?Math.min(c,Math.max(l,Math.round(h))):n},"normalizeInteger");a("enableScreenSvg","ScreenshotFeature","列表长缩略图",{description:"在列表卡片上显示长缩略图按钮;手动点击仍遵守截图来源白名单。",surfaces:["full"],defaultValue:t}),a("enableLoadScreenShot","ScreenshotFeature","长缩略图",{description:"在详情页与 FC2 页面自动加载长缩略图及对应截图来源请求。",surfaces:["full","quick"]}),a("enablePreviewVideo","PreviewVideoFeature","预览视频",{description:"预览视频总开关。关闭后 JavDB/JavBus 详情与列表卡片的预览入口、播放器与 DMM 请求全部消失。",surfaces:["full","quick"]}),a("enableLoadPreviewVideo","PreviewVideoFeature","DMM 高画质增强",{description:"解析更高画质的 DMM 预览视频;关闭后仍可使用宿主原生预览,但不发起 DMM 请求。",surfaces:["full","quick"],indent:!0}),a("enableVideoSvg","CoverButtonFeature","卡片播放视频",{description:"在列表卡片上显示播放视频按钮。",surfaces:["full"]}),a("enableHandleSvg","CoverButtonFeature","卡片鉴定处理",{description:"在列表卡片上显示鉴定处理菜单。",surfaces:["full"]}),a("enableSiteSvg","CoverButtonFeature","卡片第三方网站",{description:"在列表卡片上显示第三方网站菜单。",surfaces:["full"]}),a("enableCopySvg","CoverButtonFeature","卡片复制",{description:"在列表卡片上显示复制菜单。",surfaces:["full"]}),a("autoPage","AutoPageFeature","瀑布流",{description:"连续加载列表;启用后普通列表只支持默认排序。",surfaces:["full","quick"]}),a("translateTitle","TranslateFeature","标题翻译",{description:"翻译列表和详情页标题。",surfaces:["full","quick"]}),a("hoverBigImg","ListImageFeature","悬浮大图",{description:"鼠标悬停封面时显示大图。",surfaces:["full","quick"],defaultValue:s}),o.register({key:"defaultQuickFilterTab",owner:"ListPageFeature",label:"列表默认筛选",description:"进入列表页时默认选中的筛选标签,修改后下次进入列表生效。",type:"select",defaultValue:"waitCheck",effect:"nextNavigation",surfaces:["full"],options:Object.freeze([{value:"all",label:"全部"},{value:"waitCheck",label:"待鉴定"},{value:"favorite",label:"收藏"},{value:"hasDown",label:"下载"},{value:"hasWatch",label:"已看"},{value:"blockedItems",label:"屏蔽项"}])}),a("enableLoadReview","ReviewFeature","评论",{description:"在详情页与 FC2 页面加载评论;显式关闭 no 时保持关闭。",surfaces:["full","quick"]}),a("enableLoadOtherSite","OtherSiteFeature","外部站点",{description:"在详情页提供第三方站点入口。",surfaces:["full","quick"]}),a("enableLoadActressInfo","ActressInfoFeature","演员信息",{description:"在详情页与演员页展示演员资料。",surfaces:["full","quick"]}),a("enableMagnetsFilter","MagnetFeature","磁力质量过滤",{description:"在资源列表中过滤低质量磁力。",surfaces:["full"]}),a("needClosePage","WorkflowFeature","鉴定后立即关闭",{description:"完成鉴定后关闭当前详情窗口。",surfaces:["full","quick"]}),a("enableVerticalModel","LayoutFeature","竖图模式",{description:"使用竖图比例的列表卡片布局。",surfaces:["full","quick"],defaultValue:s}),o.register({key:"mobileMode",owner:"LayoutFeature",label:"移动模式",type:"select",defaultValue:"auto",effect:"live",surfaces:["full"],options:Object.freeze([{value:"auto",label:"自动检测"},{value:"on",label:"强制开启"},{value:"off",label:"强制关闭"}])}),o.register({key:"themeMode",owner:"ThemeFeature",label:"主题",type:"select",defaultValue:"light",effect:"live",surfaces:["full"],options:Object.freeze([{value:"light",label:"浅色"},{value:"dark",label:"深色"},{value:"auto",label:"跟随系统"}])}),o.register({key:"containerColumns",owner:"LayoutFeature",label:"列表列数",type:"number",defaultValue:5,effect:"live",surfaces:["full"]}),o.register({key:"containerWidth",owner:"LayoutFeature",label:"列表宽度",type:"number",defaultValue:100,effect:"live",surfaces:["full"]}),o.register({key:"screenshotMode",owner:"ScreenshotFeature",label:"截图来源模式",type:"select",defaultValue:"auto",effect:"manual",surfaces:["full"],options:Object.freeze([{value:"auto",label:"自动选择"},{value:"manual",label:"手动选择"}])}),o.register({key:"screenshotProviders",owner:"ScreenshotFeature",label:"截图来源",type:"json",defaultValue:[],effect:"manual",surfaces:["full"]}),o.register({key:"enableClog",owner:"CoreFeature",label:"日志",type:"select",defaultValue:t,effect:"live",surfaces:["full"],options:Object.freeze([{value:t,label:"开启"},{value:s,label:"关闭"}])}),o.register({key:"videoMuted",owner:"PreviewVideoFeature",label:"视频默认静音",type:"boolean",defaultValue:!0,effect:"live",surfaces:[]}),a("enable123Offline","OfflineFeature","123 云盘离线",{description:"支持 Magnet,需要先在 123 云盘页面同步授权。",surfaces:["full"],section:"cloud",defaultValue:!0,normalize:d(i=>be(i,!1),"normalize")}),a("enable115Offline","OfflineFeature","115 离线下载",{description:"支持 Magnet 与 ED2K。",surfaces:["full"],section:"cloud",defaultValue:!1,normalize:d(i=>be(i,!1),"normalize")}),o.register({key:"offlineProviderMode",owner:"OfflineFeature",label:"默认服务",description:"选择离线提交时优先使用的服务。",type:"select",defaultValue:"ask",effect:"live",surfaces:["full"],section:"cloud",options:Object.freeze([{value:"ask",label:"每次询问"},{value:"123",label:"优先 123"},{value:"115",label:"优先 115"}]),normalize:d(i=>["ask","123","115"].includes(String(i))?String(i):"ask","normalize")}),a("enable115Match","OfflineFeature","115 文件匹配",{description:"根据当前番号查找网盘中已存在的视频。",surfaces:["full"],section:"cloud",defaultValue:!1,normalize:d(i=>be(i,!1),"normalize")}),a("enable115LoginRedirect","OfflineFeature","未登录时提供登录入口",{description:"提交失败时显示 115 登录地址。",surfaces:["full"],section:"cloud",defaultValue:!1,normalize:d(i=>be(i,!1),"normalize")}),o.register({key:"oneOneFiveConcurrency",owner:"OfflineFeature",label:"匹配并发数",description:"控制 115 文件匹配的并发请求数,范围 1–10。",type:"number",defaultValue:4,effect:"live",surfaces:["full"],section:"cloud",min:1,max:10,step:1,normalize:d(i=>r(i,4,1,10),"normalize")}),o.register({key:"oneOneFiveCacheMinutes",owner:"OfflineFeature",label:"匹配缓存(分钟)",description:"设置 115 匹配结果缓存时间,范围 1–1440 分钟。",type:"number",defaultValue:60,effect:"live",surfaces:["full"],section:"cloud",min:1,max:1440,step:1,normalize:d(i=>r(i,60,1,1440),"normalize")})}d(zc,"registerDefaultSettings");function Fc(o){let e=new rr({legacyHttp:o.legacyHttp}),t=new te("app:root",{onChange:d(Ne=>e.updateScope(Ne),"onChange")}),s=new _r(e),a=new Ya,r=new tr(o.gmRequest),i=new Xa(o.storageForage,o.localStorage,o.gmGetValue,o.gmSetValue,o.gmDeleteValue),n=new er(o.layer),l=new Za,c=new nr({localOrigins:o.localOrigins}),h=new cr(a),u=new jr(i),p=new sr({diagnostics:e,storage:u}),g=new ir(n),m=new kr(l),f=new Pr;zc(f);let v=new yr(u,{afterPersist:d(async(Ne,z)=>{o.legacyStorage?.invalidateSettingCache?.(),await o.eventBus?.emit?.("settings-changed",{changedNames:z,source:"service"})},"afterPersist"),normalizers:f.normalizers()}),b=new or(r,c,{diagnostics:e,cache:p,settings:v});e.setNetworkController(b);let w=new xr(u,o.localStorage),S=new Sr(b,w,v);t.listen(v,"settings.changed",Ne=>{if(!(Ne.detail?.names??[]).includes("trustedLocalOrigins"))return;let Z=v.snapshot().trustedLocalOrigins;c.replaceLocalOrigins(Array.isArray(Z)?Z:[])}),o.eventBus&&t.addCleanup(o.eventBus.on("settings-changed",async(Ne,z)=>{let Z=z.originId!==o.eventBus.originId,re=z.originId===o.eventBus.originId&&z.payload?.source==="legacy";!Z&&!re||(o.legacyStorage?.invalidateSettingCache?.(),await v.refresh())})),typeof window<"u"&&t.listen(window,"pageshow",async()=>{o.legacyStorage?.invalidateSettingCache?.(),await v.refresh()});let j=new pr({scope:t,settings:v}),x=new Cr,k=new Tr(e),_=new Ar(s,e),E=new hr(_),L=new ar(_,p),N=new lr(_),A=new mr(_),O=new gr(_),U=new dr(k,_),H=new fr(k,_),Q=new vr(_,u),se=new br(_),ge=new wr(_),De=new ur(k,_);s.register(Y.navigation,a).register(Y.http,r).register(Y.storage,i).register(Y.dialog,n).register(Y.style,l).register(y.diagnostics,e).register(y.urlPolicy,c).register(y.navigation,h).register(y.http,b).register(y.storage,u).register(y.webdav,S).register(y.credential,w).register(y.dialog,g).register(y.settings,v).register(y.cache,p).register(y.profile,j).register(y.state,o.stateService).register(y.movie,E).register(y.actressInfo,L).register(y.imageSearch,N).register(y.review,A).register(y.related,O).register(y.magnet,U).register(y.screenshot,H).register(y.offline,De).register(y.translation,Q).register(y.subtitle,se).register(y.account,ge).register(Qe.command,x).register(Qe.provider,k).register(Qe.integration,_).register(Qe.settings,f),o.hostAdapter&&s.register(Y.host,o.hostAdapter),o.hostAdapters?.javdb&&s.register(Y.javdbHost,o.hostAdapters.javdb),o.hostAdapters?.javbus&&s.register(Y.javbusHost,o.hostAdapters.javbus);let ot=new $r({container:s,commands:x,diagnostics:e,disabled:o.disabled,site:o.site,route:o.route});return s.register(Qe.feature,ot),Object.freeze({rootScope:t,container:s,ports:Object.freeze({navigationPort:a,httpPort:r,storagePort:i,dialogPort:n,stylePort:l}),services:Object.freeze({diagnostics:e,urlPolicy:c,navigation:h,http:b,storage:u,webdav:S,credential:w,dialog:g,styles:m,settings:v,cache:p,profile:j,state:o.stateService,movie:E,actressInfo:L,imageSearch:N,review:A,related:O,magnet:U,screenshot:H,translation:Q,subtitle:se,account:ge,offline:De}),registries:Object.freeze({commands:x,providers:k,integrations:_,settings:f,features:ot})})}d(Fc,"createAppContext");var Jk=Object.freeze({censored:"censored",uncensored:"uncensored"});function Ir(o){if(typeof o.carNum!="string"||!o.carNum)throw new TypeError("MovieRef.carNum is required");return Object.freeze({...o})}d(Ir,"defineMovieRef");function Vt(o){if(typeof o.carNum!="string"||!o.carNum)throw new TypeError("MovieDetail.carNum is required");return Object.freeze({...o})}d(Vt,"defineMovieDetail");function ko(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelectorAll=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelectorAll=="function")return e;throw new TypeError("123AV document is invalid")}d(ko,"resolveDocument");function Co(o,e="https://123av.com"){let t=new Map;if(typeof o?.find!="function"){for(let a of ko(o).querySelectorAll(".card")){let r=a.querySelector('a.card__link[href*="/cn/v/fc2-ppv-"]'),i=r?.getAttribute("href"),n=r?.textContent?.trim()??"",l=n.match(/FC2-PPV-(\d+)/i);if(!i||!l)continue;let c=`FC2-${l[1]}`,h=new URL(i,e);h.hash="",t.set(c,{imgSrc:a.querySelector("img.card__img[src]")?.getAttribute("src")||"",carNum:c,href:h.href,title:n.replace(/^FC2-PPV-\d+\s*[—–-]\s*/i,"").trim(),preview:a.querySelector(".card__poster[data-preview]")?.getAttribute("data-preview")||null})}return[...t.values()]}let s=globalThis.jQuery??globalThis.$??o.constructor;return o.find(".card").each(((a,r)=>{let i=s(r),n=i.find('a.card__link[href*="/cn/v/fc2-ppv-"]').first(),l=n.attr("href"),c=n.text().trim(),h=c.match(/FC2-PPV-(\d+)/i);if(!l||!h)return;let u=`FC2-${h[1]}`,p=new URL(l,e);p.hash="",t.set(u,{imgSrc:i.find("img.card__img[src]").first().attr("src")||"",carNum:u,href:p.href,title:c.replace(/^FC2-PPV-\d+\s*[—–-]\s*/i,"").trim(),preview:i.find(".card__poster[data-preview]").first().attr("data-preview")||null})})),[...t.values()]}d(Co,"parse123AvCards");function Vc(o){let e=new Map;return o.flat().forEach((t=>e.set(t.carNum,t))),[...e.values()]}d(Vc,"merge123AvCards");function Hc(o,e="https://123av.com"){if(typeof o?.find!="function"){let r=ko(o),i=r.querySelector('a[rel="last"]')?.getAttribute("href");if(i){let c=Number.parseInt(new URL(i,e).searchParams.get("page")??"",10);if(Number.isFinite(c))return c}let n=Number.parseInt(r.querySelector("input.pager__input[max]")?.getAttribute("max")??"",10);if(Number.isFinite(n))return n;let l=r.querySelector(".pager__total")?.textContent?.match(/(\d[\d,]*)/);return l?Number.parseInt(l[1].replaceAll(",",""),10):null}let t=o.find('a[rel="last"]').first().attr("href");if(t){let r=Number.parseInt(new URL(t,e).searchParams.get("page")??"",10);if(Number.isFinite(r))return r}let s=Number.parseInt(o.find("input.pager__input[max]").first().attr("max"),10);if(Number.isFinite(s))return s;let a=o.find(".pager__total").first().text().match(/(\d[\d,]*)/);return a?Number.parseInt(a[1].replaceAll(",",""),10):null}d(Hc,"parse123AvSourceMaxPage");function qc(o,e){let t=new URL(e).pathname.match(/fc2-ppv-(\d+)/i),s=t?t[1]:null,a=typeof o?.find=="function"?null:ko(o),r=a?a.querySelector("h1.watch__title")?.textContent?.trim()??"":o.find("h1.watch__title").first().text().trim(),i=s?r.replace(new RegExp(`^FC2-PPV-${s}\\s*[—–-]\\s*`,"i"),"").trim():r,l=(a?a.body?.textContent??"":o.find("body").text()).match(/发布日期\s*(\d{4}-\d{2}-\d{2})/)?.[1]||"";return{id:s,publishDate:l,title:i,moviePoster:null}}d(qc,"parse123AvVideoInfo");var Rr="https://123av.com";function du(o){try{let e=new URL(String(o||Rr));return e.protocol!=="https:"?Rr:e.origin}catch{return Rr}}d(du,"normalizeBaseOrigin");function hu(o,e=null){let t=d(()=>du(e?.snapshot().av123Url),"baseOrigin"),s=d((a,r,i="movie.detail")=>{let n=new URL(a).origin,l=n===Rr;return o.request({providerId:"av123",capability:i,method:"GET",url:a,responseType:"text",requestOptions:{cookiePartition:{topLevelSite:n}},urlPolicy:l?{trustClass:"builtin-public",hosts:["123av.com"],expectedOrigin:n}:{trustClass:"custom-public",expectedOrigin:n}},r)},"request");return Object.freeze({contracts:["MovieRef","MovieDetail"],origin:t,searchUrl(a){let r=ee(a?.carNum);return r?`${t()}/cn/search?keyword=${encodeURIComponent(r)}`:null},detailUrl(a){let r=ee(a.carNum)?.match(/^FC2-(\d+)$/)?.[1];return a.url?new URL(a.url).href:r?`${t()}/cn/v/fc2-ppv-${r}`:null},matchesUrl(a){try{let r=new URL(a);return r.origin===t()||/^\/cn\/v\/fc2-ppv-\d+\/?$/i.test(r.pathname)}catch{return!1}},async listCatalog(a={},r={}){let i=Math.max(1,Number(a.page)||1),n=String(a.keyword||"").trim(),c=(n?[i]:[i*2-1,i*2]).map(m=>n?`${t()}/cn/search?keyword=${encodeURIComponent(n)}&page=${m}`:`${t()}/cn/makers/fc2?page=${m}`),h=await Promise.all(c.map(m=>s(m,r.scope,n?"movie.search":"movie.catalog"))),u=h.map((m,f)=>Co(m.data,m.finalUrl||c[f])),p=Vc(u).map(m=>Object.freeze({carNum:m.carNum,title:m.title,url:m.href,imageUrl:m.imgSrc?new URL(m.imgSrc,t()).href:null,previewUrl:m.preview?new URL(m.preview,t()).href:null,providerId:"av123"})),g=h.length?Hc(h[0].data,h[0].finalUrl||c[0]):null;return Object.freeze({items:p,maxPage:g?n?g:Math.ceil(g/2):null})},async resolveMovie(a,r={}){let i=ee(a.carNum);if(!i)return null;let n=this.searchUrl({carNum:i});if(!n)return null;let l=await s(n,r.scope,"movie.search"),c=Co(l.data,l.finalUrl||n).find(h=>ee(h.carNum)===i);return c?Ir({carNum:i,url:c.href,providerId:"av123"}):null},async getDetail(a,r={}){let i=ee(a.carNum),n=i?.match(/^FC2-(\d+)$/)?.[1];if(!i||!a.url&&!n)throw new TypeError("123AV movie reference is invalid");let l=new URL(a.url||`${t()}/cn/v/fc2-ppv-${n}`).href,c=await s(l,r.scope),h=qc(c.data,c.finalUrl||l);if(!h.title)throw new TypeError("123AV detail is malformed");return Vt({carNum:i,title:h.title,releaseDate:h.publishDate||null,url:c.finalUrl||l,providerId:"av123"})}})}d(hu,"create123AvAdapter");var Jc=J({id:"av123",trustClass:"builtin-public",hosts:["123av.com"],capabilities:["movie.search","movie.detail","movie.catalog"],requires:[y.http,y.settings],createClient:d(o=>Object.freeze({http:o[y.http],settings:o[y.settings]}),"createClient"),createAdapter:d(o=>hu(o.http,o.settings),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.search":"public-7d","movie.detail":ke.externalDetail,"movie.catalog":"public-7d"},quality:"silver"});function uu(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelector=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelector=="function")return e;throw new TypeError("DMM preview document is invalid")}d(uu,"resolveDocument");function Wc(o,e){let t=uu(o),s=t.querySelector("[data-video-url]")?.getAttribute("data-video-url")??t.querySelector("video source[src]")?.getAttribute("src");if(!s)throw new TypeError("DMM preview URL is missing");let a=new URL(s,e);if(a.protocol!=="https:")throw new TypeError("DMM preview must use HTTPS");return Object.freeze({url:a.href})}d(Wc,"parseDmmPreview");function Kc(o,e,t){if(o?.result?.result_count===0&&!Array.isArray(o.result.items))return Object.freeze([]);if(!o||typeof o!="object"||!o.result||!Array.isArray(o.result.items))throw new we("dmm","INVALID_RESPONSE","DMM API 返回结构无效");let s=e.toLowerCase(),a=s.replace(/-/g,""),r=t.toLowerCase().replace(/-/g,"");return Object.freeze(o.result.items.flatMap(i=>{let n=String(i?.content_id??""),l=String(i?.maker_product??"");return!n.toLowerCase().includes(r)&&l.toLowerCase()!==s&&!n.toLowerCase().includes(a)?[]:[Object.freeze({serviceCode:String(i.service_code??""),floorCode:String(i.floor_code??""),contentId:n,pageUrl:new URL(String(i.URL)).href})]}).slice(0,2))}d(Kc,"parseDmmItemCandidates");function Gc(o,e){if(typeof o!="string")throw new we("dmm","PARSE_ERROR","解析播放页内容失败, 非文本内容",{url:e});if(o.includes("このサービスはお住まいの地域からは"))throw new we("dmm","REGION_BLOCKED","DMM 预览源不可用,请将 DMM 域名分流到日本 IP",{url:e});let t=o.match(/const\s+args\s+=\s+(.*);/);if(!t)throw new we("dmm","PARSE_ERROR","未在脚本中找到 const args = ... 变量",{url:e});let s;try{({bitrates:s}=JSON.parse(t[1]))}catch(r){throw new we("dmm","PARSE_ERROR",`解析播放器脚本 JSON 失败: ${r instanceof Error?r.message:String(r)}`,{cause:r,url:e})}if(!Array.isArray(s))throw new we("dmm","PARSE_ERROR","解析画质链接失败: bitrates 字段不是一个数组或不存在",{url:e});let a={};for(let r of s){let i=r?.src;if(typeof i!="string"||!i.endsWith(".mp4"))continue;let n=new URL(i,e);if(n.protocol!=="https:")continue;let l=n.pathname.match(/\/([^/]+)\.mp4$/)?.[1];l&&!a[l]&&(a[l]=n.href)}if(Object.keys(a).length===0)throw new we("dmm","PARSE_ERROR","未找到匹配要求的预览画质视频",{url:e});return Object.freeze(a)}d(Gc,"parseDmmPlayerSources");var _o=["dmm.co.jp","dmm.com"];function pu(o){return Object.freeze({contracts:["MoviePreview"],searchUrl(e){return`https://www.dmm.co.jp/search/=/searchstr=${encodeURIComponent(String(e.carNum??""))}`},async getPreview(e,t={}){let s=new URL(e.url),a=await o.request({providerId:"dmm",capability:"movie.preview",method:"GET",url:s.href,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["dmm.co.jp"]}},t.scope);return Wc(a.data,a.finalUrl||s.href)},async getPreviewForMovie(e,t={}){let s=String(e.carNum),a=s.replace(/-/g,""),r=[s.replace("-","00"),s,a],i=this.searchUrl(e),n=[],l=null,c=!1;for(let p of r){let g=`https://api.dmm.com/affiliate/v3/ItemList?${new URLSearchParams({api_id:"UrwskPfkqQ0DuVry2gYL",affiliate_id:"10278-996",output:"json",site:"FANZA",sort:"match",keyword:p})}`;try{let m=await o.request({providerId:"dmm",capability:"movie.preview",method:"GET",url:g,responseType:"json",urlPolicy:{trustClass:"builtin-public",hosts:_o}},t.scope);if(n=Kc(m.data,s,p),c=!0,n.length)break}catch(m){l=m;break}}if(!n.length){if(!c&&l)throw l;return Object.freeze({sources:null,pageUrl:i,searchUrl:i,matchType:"none"})}let h=n.map(async p=>{let g=`https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${encodeURIComponent(p.contentId)}/mtype=AhRVShI_/service=${encodeURIComponent(p.serviceCode)}/floor=${encodeURIComponent(p.floorCode)}/mode=/`,m=await o.request({providerId:"dmm",capability:"movie.preview",method:"GET",url:g,responseType:"text",headers:{"accept-language":"ja-JP,ja;q=0.9",Cookie:"age_check_done=1"},urlPolicy:{trustClass:"builtin-public",hosts:_o}},t.scope);return Gc(m.data,m.finalUrl||g)}),u;try{u=await Promise.any(h)}catch(p){let g=p instanceof AggregateError?p.errors:[p];throw g.find(m=>m?.code==="REGION_BLOCKED")??g[0]??p}return Object.freeze({sources:u,pageUrl:n.length>1?i:n[0].pageUrl,searchUrl:i,matchType:n.length>1?"multiple":"single"})}})}d(pu,"createDmmAdapter");var Qc=J({id:"dmm",trustClass:"builtin-public",hosts:_o,capabilities:["movie.preview"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>pu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.preview":"none"},quality:"silver"});var Yc=Object.freeze([Object.freeze({id:"javTrailersBtn",name:"javTrailers",settingKey:"javTrailersUrl",defaultBaseUrl:"https://javtrailers.com",itemSelector:".videos-list .video-link",textSelector:"p.card-text",hrefSelector:null,searchPath:d(o=>`/search/${o}`,"searchPath")}),Object.freeze({id:"jableBtn",name:"jable",settingKey:"jableUrl",defaultBaseUrl:"https://jable.tv",itemSelector:"#list_videos_videos_list_search_result .detail .title a",textSelector:null,hrefSelector:null,searchPath:d(o=>`/search/${o}/`,"searchPath")}),Object.freeze({id:"avgleBtn",name:"avgle",settingKey:"avgleUrl",defaultBaseUrl:"https://jav.rs",itemSelector:".text-secondary",textSelector:null,hrefSelector:null,searchPath:d(o=>`/vod/search.html?wd=${o}`,"searchPath")}),Object.freeze({id:"missAvBtn",name:"missAv",settingKey:"missAvUrl",defaultBaseUrl:"https://missav.live",itemSelector:".text-secondary",textSelector:null,hrefSelector:null,searchPath:d(o=>`/search/${o}`,"searchPath")}),Object.freeze({id:"supJavBtn",name:"supJav",settingKey:"supJavUrl",defaultBaseUrl:"https://supjav.com",itemSelector:".posts post",textSelector:null,hrefSelector:null,titleAttribute:!0,searchPath:d(o=>`/?s=${o}`,"searchPath")}),Object.freeze({id:"javDbBtn",name:"javDb",settingKey:"javDbUrl",defaultBaseUrl:"https://javdb.com",itemSelector:".movie-list .item",textSelector:".video-title",hrefSelector:"a",searchPath:d(o=>`/search?q=${o}`,"searchPath")}),Object.freeze({id:"javBusBtn",name:"javBus",settingKey:"javBusUrl",defaultBaseUrl:"https://www.javbus.com",itemSelector:".container h3",textSelector:null,hrefSelector:null,directDetail:!0,searchPath:d(o=>`/${o}`,"searchPath")})]);function Zc(o,e){let t=new URL(e[o.settingKey]||o.defaultBaseUrl).origin;return Object.freeze({id:o.id,name:o.name,baseUrl:t,searchUrl:d(s=>new URL(o.searchPath(encodeURIComponent(s)),`${t}/`).href,"searchUrl")})}d(Zc,"siteDefinition");function gu(o,e,t,s){if(typeof o!="string")throw new D("INVALID_RESPONSE","外部站点响应不是 HTML",{source:e.id});let a=new DOMParser().parseFromString(o,"text/html"),r=[];for(let i of a.querySelectorAll(e.itemSelector)){let n=e.textSelector?i.querySelector(e.textSelector):i;if((e.titleAttribute?i.getAttribute("title")||"":n?.textContent?.trim()||"").toLowerCase().includes(t.toLowerCase()))if(e.directDetail)r.push(new URL(`/${encodeURIComponent(t)}`,`${s}/`).href);else{let c=e.hrefSelector?i.querySelector(e.hrefSelector):i,h=c?.getAttribute("href");if(!h)throw new D("PARSE_ERROR","外部站点结果缺少链接",{source:e.id});r.push(new URL(h,`${s}/`).href)}}return Object.freeze([...new Set(r)])}d(gu,"parseExternalSiteResults");function mu(o){return Object.freeze({contracts:["ExternalSiteResult"],getSites(e={}){return Object.freeze(Yc.map(t=>Zc(t,e)))},getNavigationLinks:d(()=>Object.freeze([Object.freeze({id:"theporndude",label:"ThePornDude",url:"https://theporndude.com/zh"})]),"getNavigationLinks"),async searchSite(e,t,s={}){let a=Yc.find(u=>u.id===e);if(!a)throw new D("UNSUPPORTED",`未知外部站点:${e}`,{source:"external-sites"});let r=Zc(a,s.settings||{}),i=r.searchUrl(t),n=new URL(i),l=new URL(a.defaultBaseUrl).hostname.replace(/^www\./,""),c=n.hostname===l||n.hostname.endsWith(`.${l}`)?{trustClass:"builtin-public",hosts:[l],expectedOrigin:n.origin}:{trustClass:"custom-public",expectedOrigin:n.origin},h=await o.request({capability:"movie.external-sites",providerId:`external-site:${e}`,method:"GET",url:i,responseType:"text",urlPolicy:c},s.scope);return Object.freeze({searchUrl:i,matches:gu(h.data,a,t,r.baseUrl)})}})}d(mu,"createExternalSitesAdapter");var Xc=J({id:"external-sites",trustClass:"builtin-public",hosts:["javtrailers.com","jable.tv","jav.rs","missav.live","supjav.com","javdb.com","javbus.com","theporndude.com"],capabilities:["movie.external-sites","navigation.external"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>mu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.external-sites":"public-1d","navigation.external":"none"},quality:"silver"});function ed(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelector=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelector=="function")return e;throw new TypeError("FC2PPVDB detail document is invalid")}d(ed,"resolveDocument");function td(o,e){let t=new URL(e).pathname.match(/(?:articles?|videos?)\/(\d+)/i)?.[1],s=ee(t?`FC2-${t}`:""),a=ed(o).querySelector("h1")?.textContent?.trim()??"";if(!s||!a)throw new TypeError("FC2PPVDB detail is malformed");return Vt({carNum:s,title:a,url:new URL(e).href})}d(td,"parseFc2PpvDbDetail");function sd(o,e){let t=ed(o),s=new URL(e),a=[...t.querySelectorAll("div")],r=a.find(h=>h.textContent?.trim().startsWith("女優:")),i=a.find(h=>h.textContent?.trim().startsWith("販売者:")),n=[...r?.querySelectorAll("a[href]")??[]].map(h=>Object.freeze({name:h.textContent?.trim()||"",url:new URL(h.getAttribute("href")||"",s).href})).filter(h=>h.name),l=i?.querySelector("a[href]"),c=l?Object.freeze({name:l.textContent?.trim()||"",url:new URL(l.getAttribute("href")||"",s).href}):null;return Object.freeze({actors:Object.freeze(n),seller:c})}d(sd,"parseFc2PpvDbPeople");function fu(o){let e=d(s=>{let a=String(s.carNum||"").match(/^(?:FC2-)?(?:PPV-)?(\d+)$/i)?.[1];if(!a)throw new TypeError("FC2PPVDB movie identifier is invalid");return new URL(s.url||`https://fc2ppvdb.com/articles/${a}`)},"resolveUrl"),t=d((s,a,r="movie.detail")=>o.request({capability:r,providerId:"fc2ppvdb",method:"GET",url:s.href,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["fc2ppvdb.com"]}},a),"request");return Object.freeze({contracts:["MovieDetail","MovieCredits"],detailUrl(s){return e(s).href},async getDetail(s,a={}){let r=e(s),i=await t(r,a.scope,"movie.detail");return td(i.data,i.finalUrl||r.href)},async getPeople(s,a={}){let r=e(s),i=await t(r,a.scope,"movie.credits");return sd(i.data,i.finalUrl||r.href)}})}d(fu,"createFc2PpvDbAdapter");var ad=J({id:"fc2ppvdb",trustClass:"builtin-public",hosts:["fc2ppvdb.com"],capabilities:["movie.detail","movie.credits"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>fu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.detail":ke.externalDetail,"movie.credits":ke.externalDetail},quality:"silver"});function rd(o,e){let t=new DOMParser().parseFromString(o,"text/html"),s=new Set;for(let a of t.querySelectorAll(".items_article_SampleImagesArea img[src]")){let r=new URL(a.getAttribute("src")||"",e);r.protocol==="https:"&&s.add(r.href)}return Object.freeze([...s].map(a=>Object.freeze({url:a,providerId:"fc2content"})))}d(rd,"parseFc2ContentImages");function vu(o){return Object.freeze({contracts:["Screenshot"],detailUrl(e){let t=String(e.carNum||"").match(/^(?:FC2-)?(?:PPV-)?(\d+)$/i)?.[1];return t?`https://adult.contents.fc2.com/article/${t}/`:null},async getImages(e,t={}){let s=String(e.carNum||"").match(/^(?:FC2-)?(?:PPV-)?(\d+)$/i)?.[1];if(!s)return[];let a=`https://adult.contents.fc2.com/article/${s}/`,r=await o.request({providerId:"fc2content",capability:"movie.images",method:"GET",url:a,responseType:"text",headers:{referer:a},urlPolicy:{trustClass:"builtin-public",hosts:["adult.contents.fc2.com"]}},t.scope);return rd(r.data,r.finalUrl||a)}})}d(vu,"createFc2ContentAdapter");var id=J({id:"fc2content",trustClass:"builtin-public",hosts:["adult.contents.fc2.com"],capabilities:["movie.images"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>vu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.images":ke.externalDetail},quality:"silver"});function nd(o){if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError("Translation response is invalid");let e=o.translation;if(typeof e!="string"||!e.trim())throw new TypeError("Translation text is missing");return e}d(nd,"parseGoogleTranslation");var bu="https://translate-pa.googleapis.com/v1/translate";function wu(o){return Object.freeze({contracts:["Translation"],async translate(e,t={}){if(!String(e||"").trim())throw new TypeError("Translation text cannot be empty");let s=new URL(bu);s.search=new URLSearchParams({"params.client":"gtx",dataTypes:"TRANSLATION",key:"AIzaSyDLEeFI5OtFBwYBIoK_jj5m32rZK5CkCXA","query.sourceLanguage":t.sourceLanguage??"ja","query.targetLanguage":t.targetLanguage??"zh-CN","query.text":e}).toString();let a=await o.request({providerId:"google-translate",capability:"text.translate",method:"GET",url:s.href,responseType:"json",transport:"native-fetch",nativeTimeout:1500,timeout:5e3,urlPolicy:{trustClass:"builtin-public",hosts:["translate-pa.googleapis.com"]}},t.scope);return nd(a.data)}})}d(wu,"createGoogleTranslateAdapter");var od=J({id:"google-translate",trustClass:"builtin-public",hosts:["translate-pa.googleapis.com"],capabilities:["text.translate"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>wu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"text.translate":"none"},quality:"silver"});var $o=Object.freeze([Object.freeze({id:"jsdelivr",name:"jsDelivr (全球CDN)",catalogUrl:"https://cdn.jsdelivr.net/gh/gfriends/gfriends/Filetree.json",contentBaseUrl:"https://cdn.jsdelivr.net/gh/gfriends/gfriends/Content/",recommended:!0}),Object.freeze({id:"github-raw",name:"GitHub Raw (备用)",catalogUrl:"https://raw.githubusercontent.com/gfriends/gfriends/master/Filetree.json",contentBaseUrl:"https://raw.githubusercontent.com/gfriends/gfriends/master/Content/",recommended:!1})]);function yu(o,e){let t=o?.Content;if(!t||typeof t!="object"||Array.isArray(t))throw new D("INVALID_RESPONSE","头像数据源缺少 Content",{source:"gfriends"});let s=new Map;for(let[a,r]of Object.entries(t))if(!(!r||typeof r!="object"||Array.isArray(r)))for(let[i,n]of Object.entries(r)){if(typeof n!="string")continue;let l=i.replace(/\.jpg$/i,"").split("-")[0];if(l.startsWith("AI-Fix-")&&(l=l.slice(7)),l=l.toLowerCase().trim(),!l)continue;let c=n.indexOf("?"),h=c>=0?n.slice(0,c):n,u=c>=0?n.slice(c):"",p=`${e}${encodeURIComponent(a)}/${encodeURIComponent(h)}${u}`,g=s.get(l)||[];g.includes(p)||g.push(p),s.set(l,g)}return s}d(yu,"parseGfriendsCatalog");function ju(o){return Object.freeze({contracts:["ActorAvatar"],getSources:d(()=>Object.freeze($o.map(e=>Object.freeze({id:e.id,name:e.name,recommended:e.recommended}))),"getSources"),async searchAvatars(e,t={}){let s=$o.find(n=>n.id===(t.sourceId||$o[0].id));if(!s)throw new D("UNSUPPORTED",`未知头像数据源:${t.sourceId}`,{source:"gfriends"});let a=await o.request({providerId:`gfriends:${s.id}`,capability:"person.avatar-search",method:"GET",url:s.catalogUrl,responseType:"json",timeout:2e4,urlPolicy:{trustClass:"builtin-public",hosts:[new URL(s.catalogUrl).hostname]}},t.scope),r=yu(a.data,s.contentBaseUrl),i=new Set;return e.map(n=>String(n).toLowerCase().trim()).filter(Boolean).forEach(n=>r.get(n)?.forEach(l=>i.add(l))),Object.freeze([...i])}})}d(ju,"createGfriendsAdapter");var ld=J({id:"gfriends",trustClass:"builtin-public",hosts:["cdn.jsdelivr.net","raw.githubusercontent.com"],capabilities:["person.avatar-search"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>ju(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"person.avatar-search":"public-7d"},quality:"silver"});var cd=J({id:"host-list",trustClass:"builtin-public",hosts:["javdb.com","javbus.com"],capabilities:["host.list.parse"],requires:[],createClient:d(()=>Object.freeze({id:"host-list"}),"createClient"),createAdapter:d(()=>Object.freeze({contracts:["MovieRef"]}),"createAdapter"),createHostAdapter:null,cachePolicy:"none",quality:"bronze"});var Su="https://api.imgur.com/3/image",xu="d70305e7c3ac5c6",ku=Object.freeze({trustClass:"builtin-public",hosts:["imgur.com","google.com","yandex.ru"]}),Cu=Object.freeze([Object.freeze({id:"google-legacy",name:"Google旧版",urlTemplate:"https://www.google.com/searchbyimage?image_url={imageUrl}&client=firefox-b-d",iconUrl:"https://www.google.com/favicon.ico"}),Object.freeze({id:"google-lens",name:"Google",urlTemplate:"https://lens.google.com/uploadbyurl?url={imageUrl}",iconUrl:"https://www.google.com/favicon.ico"}),Object.freeze({id:"yandex",name:"Yandex",urlTemplate:"https://yandex.ru/images/search?rpt=imageview&url={imageUrl}",iconUrl:"https://yandex.ru/favicon.ico"})]);function _u(o){let e=o;if(typeof e=="string")try{e=JSON.parse(e)}catch(s){throw new D("INVALID_RESPONSE","Imgur 返回了无效 JSON",{source:"image-search",cause:s})}let t=e;if(t?.success&&typeof t?.data?.link=="string"&&/^https:\/\//i.test(t.data.link))return t.data.link;throw new D("INVALID_RESPONSE",String(t?.data?.error||"Imgur 上传响应无效"),{source:"image-search"})}d(_u,"parseImgurUpload");function $u(o){let e=o.match(/^data:(image\/[a-z0-9.+-]+);base64,([a-z0-9+/=\s]+)$/i);if(!e)throw new D("INVALID_RESPONSE","无效的 Base64 图片数据",{source:"image-search"});let t=atob(e[2].replace(/\s/g,"")),s=new Uint8Array(t.length);for(let r=0;rObject.freeze({id:s.id,name:s.name,url:s.urlTemplate.replace("{imageUrl}",t),iconUrl:s.iconUrl})))}})}d(Tu,"createImageSearchAdapter");var dd=J({id:"image-search",trustClass:"builtin-public",hosts:["imgur.com","google.com","yandex.ru"],capabilities:["image.upload","image.search-targets"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Tu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"image.upload":"none","image.search-targets":"none"},quality:"silver"});var hd=0,Er="";function To(){let o=Math.floor(Date.now()/1e3);if(Er&&o-hd<=20)return Er;let e=globalThis.md5;if(typeof e!="function")throw new Error("Missing userscript vendor runtime: md5");return hd=o,Er=`${o}.lpw6vgqzsp.${e(`${o}71cf27bb3c0bcdf207b64abecddc970098c7421ee7203b9cdae54478478a199e7d5a6e1a57691123c1a931c057842fb73ba3b3c83bcd69c17ccf174081e3d8aa`)}`,Er}d(To,"createJavDbSignature");var ud="https://jdforrepam.com";function Au(o,e=To,t=null){let s=d(r=>{let i=new URL(r).origin,n=new URL(r).hostname;return n==="javdb.com"||n.endsWith(".javdb.com")?{trustClass:"builtin-public",hosts:["javdb.com"],expectedOrigin:i}:{trustClass:"custom-public",expectedOrigin:i}},"hostPolicy"),a=d(async(r,i,n={},l={},c="movie.detail")=>{let h=new URL(r,ud);return Object.entries(i).forEach(([p,g])=>h.searchParams.set(p,String(g))),(await o.request({providerId:"javdb",capability:c,method:"GET",url:h.href,responseType:"json",headers:{jdSignature:e(),...l},urlPolicy:{trustClass:"builtin-public",hosts:["jdforrepam.com"]}},n.scope)).data},"request");return Object.freeze({contracts:["MovieRef","MovieDetail","Actor","Magnet","Review","RelatedList","AccountSession"],actorPlaceholderUrl:d(()=>"https://c0.jdbstatic.com/images/actor_unknow.jpg","actorPlaceholderUrl"),async login(r,i={}){let n=new URL("/api/v1/sessions",ud);Object.entries({username:r.username,password:r.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"}).forEach(([h,u])=>n.searchParams.set(h,u));let c=(await o.request({providerId:"javdb",capability:"account.login",method:"POST",url:n.href,responseType:"json",headers:{"user-agent":"Dart/3.5 (dart:io)","accept-language":"zh-TW","content-type":"multipart/form-data; boundary=--dio-boundary-2210433284",jdsignature:e()},urlPolicy:{trustClass:"builtin-public",hosts:["jdforrepam.com"]}},i.scope)).data;if(c?.success===0)return Object.freeze({success:!1,token:null,message:String(c.message||"登录失败")});if(c?.success!==1||typeof c?.data?.token!="string")throw new D("INVALID_RESPONSE",String(c?.message||"JavDB 登录响应无效"),{source:"javdb"});return Object.freeze({success:!0,token:c.data.token,message:String(c.message||"")})},async listActorMovies(r,i={}){let n=new URL(r.baseUrl||"https://javdb.com").origin,l=new URL(`/actors/${encodeURIComponent(r.actorId)}?t=d`,n),c=await o.request({providerId:"javdb-host",capability:"actor.movies",method:"GET",url:l.href,responseType:"text",urlPolicy:s(n)},i.scope);if(typeof t?.parseActorMovies!="function")throw new TypeError("JavDB HostAdapter parser is unavailable");return t.parseActorMovies(c.data,c.finalUrl||l.href)},async listActorCollection(r,i={}){let n=new URL(r.baseUrl||"https://javdb.com").origin,l=new URL(r.pageUrl||"/users/collection_actors",n),c=await o.request({providerId:"javdb-host",capability:"actor.collection",method:"GET",url:l.href,responseType:"text",urlPolicy:s(n)},i.scope);if(typeof t?.parseActorCollection!="function")throw new TypeError("JavDB HostAdapter collection parser is unavailable");return t.parseActorCollection(c.data,c.finalUrl||l.href)},async uncollectActor(r,i={}){let n=new URL(r.baseUrl||"https://javdb.com").origin,l=new URL(`/actors/${encodeURIComponent(r.actorId)}/uncollect`,n),c=await o.request({providerId:"javdb-host",capability:"actor.uncollect",method:"POST",url:l.href,body:"null",responseType:"text",headers:{"Content-Type":"application/json","x-csrf-token":r.csrfToken},urlPolicy:s(n)},i.scope);return Object.freeze({success:typeof c.data=="string"&&c.data.includes("removeClass")})},async resolveMovie(r,i={}){let n=ee(r.carNum);if(!n)return null;let l=await a("/api/v2/search",{q:n,page:1,type:"movie",limit:20,movie_type:"all",from_recent:"false",movie_filter_by:"all",movie_sort_by:"relevance"},i,{"user-agent":"Dart/3.5 (dart:io)","accept-language":"zh-TW",host:"jdforrepam.com"},"movie.search");if(!Array.isArray(l?.data?.movies))throw new Error(l?.message||"JavDB search response is invalid");let c=l.data.movies.find(h=>ee(h.number)===n);return c?.id?Object.freeze({carNum:n,movieId:String(c.id),providerId:"javdb"}):null},async getDetail(r,i={}){let n=String(r.movieId||"").trim();if(!n)throw new TypeError("JavDB movie id is required");let l=await a(`/api/v4/movies/${encodeURIComponent(n)}`,{},i,{},"movie.detail"),c=l?.data?.movie;if(!c?.number)throw new Error(l?.message||"JavDB detail response is invalid");let h=Array.isArray(c.preview_images)?c.preview_images.map(p=>String(p.large_url||"").replace(/https:\/\/[^/]+\/rhe951l4q/,"https://c0.jdbstatic.com")).filter(Boolean):[],u=c.cover_url?String(c.cover_url).replace(/https:\/\/[^/]+\/rhe951l4q/,"https://c0.jdbstatic.com"):"";return Object.freeze({movieId:String(c.id||n),carNum:ee(c.number),title:String(c.title||c.origin_title||""),originalTitle:String(c.origin_title||c.title||""),coverUrl:u||null,actors:Array.isArray(c.actors)?c.actors.map(p=>Object.freeze({id:String(p.id),name:String(p.name||""),gender:Number(p.gender)})):[],duration:Number(c.duration)||null,score:Number(c.score)||0,releaseDate:c.release_date||null,watchedCount:Number(c.watched_count)||0,imageUrls:Object.freeze(h),providerId:"javdb"})},async listMagnets(r,i={}){let n=String(r.movieId||"").trim();if(!n)return[];let l=await a(`/api/v1/movies/${encodeURIComponent(n)}/magnets`,{},i,{},"movie.magnets");if(!Array.isArray(l?.data?.magnets))throw new Error(l?.message||"JavDB magnet response is invalid");return l.data.magnets.map(c=>Object.freeze({hash:String(c.hash||""),title:String(c.name||""),hasHdTag:!!c.hd,hasSubtitleTag:!!c.cnsub,createdAt:c.created_at||null,seeders:Number(c.seeders)||0,sizeMb:Number(c.size)||0,fileCount:Number(c.files_count)||0,providerId:"javdb"}))},async listRankings(r={}){let i=await a("/api/v1/rankings/playback",{period:r.period||"daily",filter_by:r.filter||"high_score"},r,{},"movie.ranking");if(!Array.isArray(i?.data?.movies))throw new Error(i?.message||"JavDB ranking response is invalid");return i.data.movies.map(n=>Object.freeze({movieId:String(n.id),carNum:ee(n.number),title:String(n.origin_title||""),coverUrl:String(n.cover_url||"").replace(/https:\/\/[^/]+\/rhe951l4q/,"https://c0.jdbstatic.com"),releaseDate:n.release_date||null,hasSubtitle:!!n.has_cnsub,magnetCount:Number(n.magnets_count)||0,newMagnets:!!n.new_magnets,providerId:"javdb"}))},async listReviews(r,i={}){let n=String(r.movieId||"").trim();if(!n)return[];let l=await a(`/api/v1/movies/${encodeURIComponent(n)}/reviews`,{page:i.page??1,sort_by:"hotly",limit:i.limit??20},i,{},"movie.reviews");if(!Array.isArray(l?.data?.reviews))throw new Error(l?.message||"JavDB review response is invalid");return l.data.reviews.map(c=>Object.freeze({author:String(c.username||"匿名用户"),content:String(c.content||""),score:Number(c.score)||0,createdAt:c.created_at||null,likes:Number(c.likes_count)||0}))},async listRelated(r,i={}){let n=String(r.movieId||"").trim();if(!n)return[];let l=await a("/api/v1/lists/related",{movie_id:n,page:i.page??1,limit:i.limit??20},i,{},"movie.related");if(!Array.isArray(l?.data?.lists))throw new Error(l?.message||"JavDB related response is invalid");return l.data.lists.map(c=>Object.freeze({id:String(c.id),name:String(c.name||"未命名清单"),movieCount:Number(c.movies_count)||0,collectionCount:Number(c.collections_count)||0,viewCount:Number(c.views_count)||0,createdAt:c.created_at||null}))}})}d(Au,"createJavDbAdapter");var pd=J({id:"javdb",trustClass:"builtin-public",hosts:["javdb.com","jdforrepam.com","c0.jdbstatic.com"],capabilities:["movie.search","movie.detail","movie.magnets","movie.ranking","movie.state","movie.reviews","movie.related","actor.lookup","actor.movies","actor.collection","actor.uncollect","actor.avatar-placeholder","account.login"],requires:[y.http,Y.javdbHost],createClient:d(o=>Object.freeze({http:o[y.http],hostAdapter:o[Y.javdbHost]}),"createClient"),createAdapter:d(o=>Au(o.http,To,o.hostAdapter),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.search":"public-7d","movie.detail":ke.externalDetail,"movie.magnets":"public-1d","movie.ranking":"public-1d","movie.state":"none","movie.reviews":"public-1d","movie.related":"public-1d","actor.lookup":"none","actor.movies":"public-5m","actor.collection":"none","actor.uncollect":"none","actor.avatar-placeholder":"none","account.login":"none"},quality:"silver"});function gd(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelector=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelector=="function")return e;throw new TypeError("JavBus document is invalid")}d(gd,"resolveDocument");function Pu(o,e){if(typeof o?.find=="function")return ee(o.find("span.header:contains('識別碼:')").parent().text().replace("識別碼:",""))??ee(new URL(e).pathname.split("/").filter(Boolean).pop());let s=[...gd(o).querySelectorAll("span.header")].find(a=>a.textContent?.includes("識別碼"));return ee(s?.parentElement?.textContent?.replace("識別碼:",""))??ee(new URL(e).pathname.split("/").filter(Boolean).pop())}d(Pu,"readMovieRef");function Iu(o,e){let t=Pu(o,e);if(!t)throw new TypeError("JavBus movie identifier is missing");return Ir({carNum:t,url:new URL(e).href})}d(Iu,"parseJavBusMovieRef");function md(o,e){let t=Iu(o,e),s=typeof o?.find=="function"?null:gd(o),a=s?s.querySelector("h3")?.textContent?.trim()||t.carNum:o.find("h3").first().text().trim()||t.carNum,r=s?s.querySelector(".bigImage img[src], a.bigImage img[src]")?.getAttribute("src"):o.find(".bigImage img[src], a.bigImage img[src]").first().attr("src");return Vt({...t,title:a,coverUrl:r?new URL(r,e).href:null,providerId:"javbus"})}d(md,"parseJavBusMovieDetail");function Ru(o){return Object.freeze({contracts:["MovieDetail","Screenshot"],async getDetail(e,t={}){let s=ee(e.carNum);if(!s)throw new TypeError("JavBus movie reference is invalid");let a=new URL(e.url||`https://www.javbus.com/${encodeURIComponent(s)}`).href,r=await o.request({providerId:"javbus",capability:"movie.detail",method:"GET",url:a,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["javbus.com"]}},t.scope);return md(r.data,r.finalUrl||a)},async getImages(e,t={}){let s=await this.getDetail(e,t);return s.coverUrl?[Object.freeze({url:s.coverUrl,providerId:"javbus"})]:[]}})}d(Ru,"createJavBusAdapter");var fd=J({id:"javbus",trustClass:"builtin-public",hosts:["javbus.com"],capabilities:["movie.detail","movie.images"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Ru(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.detail":ke.externalDetail,"movie.images":ke.externalDetail},quality:"silver"});function Eu(o){let e=d((t,s)=>o.request({providerId:"javstore",capability:"movie.images",method:"GET",url:t,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["javstore.net"]}},s),"request");return Object.freeze({contracts:["Screenshot"],getSearchUrl(t){return`https://javstore.net/search?q=${encodeURIComponent(t.carNum||"")}`},async getImages(t,s={}){let a=this.getSearchUrl(t),r=await e(a,s.scope),i=Tc(r.data,t.carNum,r.finalUrl||a);if(!i.length)return[];for(let n of i)try{let l=await e(n,s.scope),c=Ac(l.data,l.finalUrl||n);if(c)return[Object.freeze({url:c,providerId:"javstore"})]}catch(l){if(!(l&&typeof l=="object"&&"code"in l&&l.code==="NOT_FOUND"))throw l}return[]}})}d(Eu,"createJavStoreAdapter");var vd=J({id:"javstore",trustClass:"builtin-public",hosts:["javstore.net"],capabilities:["movie.images"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Eu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.images":"screenshot-7d"},quality:"silver"});var bd=J({id:"javtrailers",trustClass:"builtin-public",hosts:["javtrailers.com"],capabilities:["movie.preview"],requires:[Y.http,y.urlPolicy],createClient:d(()=>Object.freeze({id:"javtrailers"}),"createClient"),createAdapter:d(()=>Object.freeze({contracts:["MoviePreview"]}),"createAdapter"),createHostAdapter:null,cachePolicy:"none",quality:"bronze"});var Du="https://115.com",Nu=Object.freeze({trustClass:"builtin-public",hosts:["115.com"]});function Lu(o){if(typeof o!="string")return o;try{return JSON.parse(o)}catch{return{state:!1,error_msg:/login|登录|sign in|未授权|授权|expire|expired|token|cookie/i.test(o)?"115 未登录":"115 返回异常响应"}}}d(Lu,"parsePayload");function Mu(o){let e=String(o).toLowerCase();return/未登录|请登录|登录|login|sign|授权|过期|token|cookie|uid|身份|auth|expire|needlogin|need login/i.test(e)?"AUTH_REQUIRED":/已存在|重复|exists|duplicate|already|same|conflict|exist/i.test(e)?"TASK_EXISTS":"OPERATION_FAILED"}d(Mu,"classify115OfflineError");function Bu(o){let e=o;if(!e||!Array.isArray(e.data))throw new D("INVALID_RESPONSE","115 文件搜索响应无效",{source:"one115"});return Object.freeze(e.data.map(t=>{let s=String(t.n||t.file_name||"");return Object.freeze({folderId:String(t.pid||t.cid||""),fileId:t.fid?String(t.fid):null,videoId:String(t.pc||t.pick_code||""),name:s,size:Number(t.s||t.size)||0,createTime:String(t.t||t.create_time||""),isVideo:/\.(mp4|mkv|avi|mov|flv|wmv|ts|m2ts)$/i.test(s)})}).filter(t=>t.isVideo))}d(Bu,"normalize115SearchResults");function Ou(o){let e=d((t,s={})=>o.request({providerId:"one115",capability:s.capability||"account.status",method:s.method||"GET",url:t,body:s.body,headers:s.headers,responseType:s.responseType||"json",urlPolicy:Nu},s.scope),"request");return Object.freeze({contracts:["AccountStatus","CloudFile","OfflineSubmission"],homeUrl:Du,async checkAccount(t={}){let a=(await e("https://webapi.115.com/offine/downpath",{capability:"account.status",scope:t.scope})).data;return Object.freeze({authenticated:!!(a?.state&&a?.data?.length)})},async searchFiles(t,s={}){let a=new URL("https://webapi.115.com/files/search");a.searchParams.set("search_value",t),a.searchParams.set("offset",String(s.offset??0)),a.searchParams.set("limit",String(s.limit??50));let r=await e(a.href,{capability:"file.search",scope:s.scope,force:s.force});return Bu(r.data)},async submit(t,s={}){if(!/^magnet:/i.test(t)&&!/^ed2k:/i.test(t))throw new D("UNSUPPORTED","Unsupported offline URL",{source:"one115"});let r=(await e(`https://115.com/?ct=offline&ac=space&_=${Date.now()}`,{capability:"offline.submit",scope:s.scope})).data;if(!r?.sign)throw new D("AUTH_REQUIRED","115 未登录或离线空间信息获取失败",{source:"one115"});let i=new URLSearchParams({url:t,wp_path_id:s.folderId||"",uid:String(r.uid||""),sign:r.sign,time:String(r.time||"")}).toString(),n=await e("https://115.com/web/lixian/?ct=lixian&ac=add_task_url",{capability:"offline.submit",scope:s.scope,method:"POST",body:i,responseType:"text",headers:{"Content-Type":"application/x-www-form-urlencoded"}}),l=Lu(n.data);if(!l||l.state===!1||l.state===0){let c=String(l?.error_msg||l?.error||l?.msg||"115 离线任务创建失败"),h=Mu(c);throw new D(h,c,{source:"one115",details:{state:l?.state??null}})}if(l.state!==!0&&l.state!==1)throw new D("INVALID_RESPONSE","115 未返回明确的离线任务创建成功状态",{source:"one115"});return Object.freeze({success:!0,taskId:String(l.task_id||l.info_hash||"")})},async renameFile(t,s,a={}){let r=new URLSearchParams({fid:t,file_name:s}).toString(),n=(await e("https://webapi.115.com/files/edit",{capability:"file.rename",scope:a.scope,method:"POST",body:r,responseType:"json",headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;if(!n||n.state===!1||n.state===0)throw new D("OPERATION_FAILED",String(n?.error||n?.error_msg||"115 重命名失败"),{source:"one115"});return Object.freeze({success:!0})},getPlayUrl(t){return t?.videoId?`https://115.com/?ct=play&pickcode=${encodeURIComponent(t.videoId)}`:null}})}d(Ou,"createOne115Adapter");var wd=J({id:"one115",trustClass:"builtin-public",hosts:["115.com"],capabilities:["account.status","file.search","file.rename","offline.submit"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Ou(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"account.status":"none","file.search":"none","file.rename":"none","offline.submit":"none"},quality:"silver"});var Uu=Object.freeze({trustClass:"builtin-public",hosts:["123pan.com"]});function yd(o){let e=new Uint32Array(256);for(let s=0;s<256;s+=1){let a=s;for(let r=0;r<8;r+=1)a=a&1?3988292384^a>>>1:a>>>1;e[s]=a}let t=4294967295;for(let s=0;s>>8;return(t^4294967295)>>>0}d(yd,"crc32");function zu(){let o=new Uint32Array(1);return crypto.getRandomValues(o),o[0]%1e7}d(zu,"secureNonce");function Fu(o,e={}){let t=["a","d","e","f","g","h","l","m","y","i","j","n","o","p","k","q","r","s","t","u","b","c","v","w","s","z"],s=e.nonce??zu(),a=e.now??new Date,r=new Date(a.getTime()+6e4*a.getTimezoneOffset()+288e5),n=[...`${r.getFullYear()}${String(r.getMonth()+1).padStart(2,"0")}${String(r.getDate()).padStart(2,"0")}${String(r.getHours()).padStart(2,"0")}${String(r.getMinutes()).padStart(2,"0")}`].map(p=>t[Number(p)]).join(""),l=yd(n),c=Math.floor(r.getTime()/1e3),h=new URL(o),u=yd(`${c}|${s}|${h.pathname}|web|3|${l}`);return h.searchParams.set(String(l),`${c}-${s}-${u}`),h.href}d(Fu,"signPan123Url");function jd(o){if(typeof o!="string")return o;try{return JSON.parse(o)}catch(e){throw new D("PARSE_ERROR","123 云盘响应不是有效 JSON",{source:"pan123",cause:e})}}d(jd,"parsePayload");function Sd(o,e){if(!o||typeof o!="object")throw new D("INVALID_RESPONSE",`123 云盘${e}响应无效`,{source:"pan123"});if(o.code===0)return o;let t=String(o.message||o.msg||`${e}失败`);throw/token is expired|unauthorized|登录|授权/i.test(t)?new D("AUTH_REQUIRED",t,{source:"pan123"}):new D("INVALID_RESPONSE",t,{source:"pan123"})}d(Sd,"assertSuccess");function Vu(o,e={}){let t=d(async(s,a,r,i,n)=>{let l=Fu(`https://yun.123pan.com${s}`,{now:e.now?.(),nonce:e.nonce?.()});return o.request({providerId:"pan123",capability:n,method:"POST",url:l,body:JSON.stringify(a),responseType:"json",timeout:e.getTimeout?.()??5e3,headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`,"App-Version":"3",platform:"web",Origin:"https://yun.123pan.com",Referer:"https://yun.123pan.com/"},urlPolicy:Uu},i)},"request");return Object.freeze({contracts:["OfflineResolvedResource","OfflineSubmission"],homeUrl:"https://yun.123pan.com",async resolve(s,a={}){let{token:r,scope:i}=a;if(!r)throw new D("AUTH_REQUIRED","尚未同步 123 授权",{source:"pan123"});let n=await t("/b/api/v2/offline_download/task/resolve",{urls:s},r,i,"offline.resolve"),l=Sd(jd(n.data),"解析"),c=l.data?.list?.[0];if(!c?.id||!Array.isArray(c.files))throw new D("INVALID_RESPONSE","123 云盘解析结果缺少资源文件",{source:"pan123"});return Object.freeze({id:c.id,files:Object.freeze(c.files.map(h=>Object.freeze({id:h.id,size:Number(h.size||0)})))})},async submitResolved(s,a={}){let{token:r,scope:i}=a;if(!r)throw new D("AUTH_REQUIRED","尚未同步 123 授权",{source:"pan123"});if(!s?.id||!Array.isArray(s.files)||s.files.length===0)throw new D("INVALID_RESPONSE","没有可建立离线的文件",{source:"pan123"});let n=s.files.map(h=>h.id),l=s.files.reduce((h,u)=>h+Number(u.size||0),0),c=await t("/b/api/v2/offline_download/task/submit",{resource_list:[{resource_id:s.id,select_file_id:n}]},r,i,"offline.submit");return Sd(jd(c.data),"提交"),Object.freeze({fileCount:n.length,totalSize:l})},async submit(s,a={}){let r=await this.resolve(s,a);return this.submitResolved(r,a)}})}d(Vu,"createPan123Adapter");var xd=J({id:"pan123",trustClass:"builtin-public",hosts:["123pan.com"],capabilities:["offline.resolve","offline.submit"],requires:[y.http,y.settings],createClient:d(o=>Object.freeze({http:o[y.http],settings:o[y.settings]}),"createClient"),createAdapter:d(o=>Vu(o.http,{getTimeout:d(()=>Number(o.settings.snapshot().httpTimeout??5e3),"getTimeout")}),"createAdapter"),createHostAdapter:null,cachePolicy:{"offline.resolve":"none","offline.submit":"none"},quality:"silver"});function Hu(){return Object.freeze({contracts:["Subtitle"],detailUrl(o){let e=String(o?.carNum||"").trim();if(!e)return null;let t=new URL("/index.php","https://subtitlecat.com");return t.searchParams.set("search",e),t.href}})}d(Hu,"createSubtitleCatAdapter");var kd=J({id:"subtitlecat",trustClass:"builtin-public",hosts:["subtitlecat.com"],capabilities:["subtitle.search"],requires:[],createClient:d(()=>Object.freeze({id:"subtitlecat"}),"createClient"),createAdapter:d(()=>Hu(),"createAdapter"),createHostAdapter:null,cachePolicy:"none",quality:"bronze"});var Cd=Object.freeze([Object.freeze({id:"u9a9",name:"U9A9",type:"网页来源",domain:"u9a9.com",baseUrl:"https://u9a9.com",priority:20,enabled:!0,searchPath:d(o=>`/?type=2&search=${encodeURIComponent(o)}`,"searchPath")}),Object.freeze({id:"u3c3",name:"U3C3",type:"网页来源",domain:"u3c3.com",baseUrl:"https://u3c3.com",priority:30,enabled:!0,searchPath:d(o=>`/?search2=a8lr16lo&search=${encodeURIComponent(o)}`,"searchPath")}),Object.freeze({id:"sukebei",name:"Sukebei",type:"网页来源",domain:"sukebei.nyaa.si",baseUrl:"https://sukebei.nyaa.si",priority:40,enabled:!0,searchPath:d(o=>`/?f=0&c=0_0&q=${encodeURIComponent(o)}`,"searchPath")}),Object.freeze({id:"btsow",name:"BTSOW",type:"API 来源",domain:"btsow.lol",baseUrl:"https://btsow.lol",priority:50,enabled:!0,searchPath:d(o=>`/search/${encodeURIComponent(o)}`,"searchPath")})]);function _d(o,e){let t=o,s=String(t?.magnet||"");return s.startsWith("magnet:")?Object.freeze({title:String(t.title||""),magnet:s,size:String(t.size||""),date:String(t.date||""),seeders:Number(t.seeders)||0,leechers:Number(t.leechers)||0,source:e,files:Object.freeze([])}):null}d(_d,"normalizeMagnet");function qu(o,e,t){if(typeof o!="string")throw new D("INVALID_RESPONSE","磁力来源响应不是 HTML",{source:t});let s=new DOMParser().parseFromString(o,"text/html"),a=`${s.title} ${s.body?.textContent||""}`;if(/Just a moment|cf-chl-|Cloudflare/i.test(a))throw new D("CF_BLOCKED","磁力来源被 Cloudflare 拦截",{source:t});return Object.freeze([...s.querySelectorAll(".torrent-list tbody tr")].flatMap(r=>{if(r.textContent?.includes("置顶"))return[];let i=r.querySelector("td:nth-child(2) a"),n=i?.getAttribute("title")||i?.textContent?.trim()||"";if(!n.toLowerCase().includes(e.toLowerCase()))return[];let l=_d({title:n,magnet:r.querySelector('td:nth-child(3) a[href^="magnet:"]')?.getAttribute("href"),size:r.querySelector("td:nth-child(4)")?.textContent?.trim(),date:r.querySelector("td:nth-child(5)")?.textContent?.trim(),seeders:r.querySelector("td:nth-child(6)")?.textContent?.trim(),leechers:r.querySelector("td:nth-child(7)")?.textContent?.trim()},t);return l?[l]:[]}))}d(qu,"parseTorrentSource");function Ju(o){let e=o;if(typeof e=="string")try{e=JSON.parse(e)}catch(s){throw new D("INVALID_RESPONSE","BTSOW 返回了无效 JSON",{source:"btsow",cause:s})}let t=e?.data;if(!Array.isArray(t))throw new D("INVALID_RESPONSE","BTSOW 响应缺少结果数组",{source:"btsow"});return Object.freeze(t.flatMap(s=>{let a=Number(s.lastUpdateTime),r=Number.isFinite(a)?new Date(1e3*a).toISOString().slice(0,10):"",i=_d({title:s.name,magnet:`magnet:?xt=urn:btih:${s.hash}`,size:`${(Number(s.size)/1073741824).toFixed(2)} GB`,date:r},"btsow");return i?[i]:[]}))}d(Ju,"parseBtsowSource");function Wu(o){let e=d(t=>Cd.find(s=>s.id===t),"find");return Object.freeze({contracts:["Magnet","MagnetSource"],getSources:d(()=>Object.freeze(Cd.map(t=>Object.freeze({id:t.id,name:t.name,type:t.type,domain:t.domain,baseUrl:t.baseUrl,priority:t.priority,enabled:t.enabled}))),"getSources"),targetUrl(t,s,a={}){let r=e(t);if(!r)throw new D("UNSUPPORTED",`未知磁力来源:${t}`,{source:"torrent-sources"});return`${new URL(a.baseUrl||r.baseUrl).origin}${r.searchPath(s)}`},async search(t,s,a={}){let r=e(t);if(!r)throw new D("UNSUPPORTED",`未知磁力来源:${t}`,{source:"torrent-sources"});let i=new URL(a.baseUrl||r.baseUrl).origin,l=new URL(i).hostname!==r.domain?{trustClass:"custom-public",expectedOrigin:i}:{trustClass:"builtin-public",hosts:[r.domain],expectedOrigin:i};if(r.id==="btsow"){let u=await o.request({capability:"magnet.search",providerId:"magnet:btsow",method:"POST",url:`${i}/search`,body:JSON.stringify([{search:s},50,1]),headers:{"Content-Type":"application/json"},responseType:"json",urlPolicy:l},a.scope);return Ju(u.data)}let c=`${i}${r.searchPath(s)}`,h=await o.request({capability:"magnet.search",providerId:`magnet:${r.id}`,method:"GET",url:c,responseType:"text",urlPolicy:l},a.scope);return qu(h.data,s,r.id)}})}d(Wu,"createTorrentSourcesAdapter");var $d=J({id:"torrent-sources",trustClass:"builtin-public",hosts:["u9a9.com","u3c3.com","sukebei.nyaa.si","btsow.lol"],capabilities:["magnet.search"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Wu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"magnet.search":"source-configured"},quality:"silver"});function St(o){return o.replace(/\s+/g," ").trim()}d(St,"compact");function Td(o,e){let t=new DOMParser().parseFromString(o,"text/html"),s=St(t.querySelector('a[title="誕生日"]')?.closest("tr")?.querySelector("td")?.textContent??""),a=[...t.querySelectorAll("th")].find(g=>g.textContent?.includes("現年齢"))?.parentElement?.querySelector("td"),r=t.querySelector('a[title="身長"]')?.closest("tr")?.querySelector("td"),i=t.querySelector('a[title="体重"]')?.closest("tr")?.querySelector("td"),n=t.querySelector('a[title="スリーサイズ"]')?.closest("tr")?.querySelector("td"),l=[...t.querySelectorAll("th")].find(g=>g.textContent?.includes("ブラサイズ"))?.nextElementSibling;if(!s&&!r&&!n)throw new TypeError("Wikipedia actress information is missing");let c=Number.parseInt(St(a?.textContent??""),10),h=St(r?.textContent??"").split(" ")[0],u=St(i?.textContent??"").split("/"),p=St(u.at(-1)??"").replace(/^―\s*kg$/,"");return Object.freeze({birthday:s,age:Number.isFinite(c)?`${c}岁`:"",height:h&&!h.endsWith("cm")?`${h}cm`:h,weight:p,threeSizeText:St(n?.textContent??"").replace("cm","").trim(),braSize:St(l?.textContent??""),url:new URL(e).href})}d(Td,"parseWikipediaActressInfo");function Ku(o){return Object.freeze({contracts:["ActressInfo"],profileUrl(e){return new URL(`/wiki/${encodeURIComponent(String(e))}`,"https://ja.wikipedia.org").href},async lookup(e,t={}){let s=this.profileUrl(e),a=await o.request({providerId:"wikipedia",capability:"person.actress-info",method:"GET",url:s,responseType:"text",timeout:15e3,urlPolicy:{trustClass:"builtin-public",hosts:["ja.wikipedia.org"]}},t.scope);try{return Td(a.data,a.finalUrl||s)}catch(r){if(r instanceof TypeError&&/actress information is missing/.test(r.message))return null;throw r}}})}d(Ku,"createWikipediaAdapter");var Ad=J({id:"wikipedia",trustClass:"builtin-public",hosts:["ja.wikipedia.org"],capabilities:["person.actress-info"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Ku(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"person.actress-info":ke.externalDetail},quality:"silver"});function Pd(o){if(!o||typeof o!="object"||!Array.isArray(o.data))throw new D("INVALID_RESPONSE","迅雷字幕响应结构无效",{source:"xunlei"});return Object.freeze(o.data.flatMap(e=>{try{let t=new URL(String(e?.url??""));if(t.protocol!=="https:")return[];let s=String(e?.ext??"").toLowerCase().replace(/^\./,"");return s?[Object.freeze({name:String(e?.name??""),extension:s,url:t.href,providerId:"xunlei"})]:[]}catch{return[]}}))}d(Pd,"parseXunleiSubtitles");var Id=["xunlei.com"];function Gu(o){return Object.freeze({contracts:["Subtitle"],async search(e,t={}){let s=String(e.carNum??"").trim();if(!s)return[];let a=new URL("https://api-shoulei-ssl.xunlei.com/oracle/subtitle");a.searchParams.set("gcid",""),a.searchParams.set("cid",""),a.searchParams.set("name",s);let r=await o.request({providerId:"xunlei",capability:"subtitle.search",method:"GET",url:a.href,responseType:"json",urlPolicy:{trustClass:"builtin-public",hosts:Id}},t.scope);return Pd(r.data)},async download(e,t={}){let s=new URL(String(e.url??"")),a=await o.request({providerId:"xunlei",capability:"subtitle.download",method:"GET",url:s.href,responseType:"text",urlPolicy:{trustClass:"custom-public"}},t.scope);if(typeof a.data!="string")throw new TypeError("迅雷字幕正文不是文本");return a.data}})}d(Gu,"createXunleiAdapter");var Rd=J({id:"xunlei",trustClass:"builtin-public",hosts:Id,capabilities:["subtitle.search","subtitle.download"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Gu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"subtitle.search":"public-1d","subtitle.download":"public-1d"},quality:"silver"});var Ed=Object.freeze([Jc,Qc,Xc,ad,id,ld,od,cd,dd,pd,fd,vd,bd,wd,xd,kd,$d,Ad,Rd]);function Qu(o,e){let t=o.close;o.close=function(a){let r=t.call(this,a);return e?.releaseEscClose?.(a),setTimeout(()=>{let i=document.querySelectorAll(".layui-layer-shade").length;document.documentElement.style.overflow=i>0?"hidden":""},10),r};let s=o.open;o.open=function(a={}){a=kt(a,e);let r=a.success;return s.call(this,{...a,success(i,n){typeof r=="function"&&r.call(this,i,n),e.setupEscClose(n)}})}}d(Qu,"patchLayerRuntime");function Yu(o){for(let e of["https://cdn.jsdelivr.net/npm/layui-layer@1.0.9/layer.min.css","https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.css","https://cdn.jsdelivr.net/npm/viewerjs@1.11.1/dist/viewer.min.css","https://cdn.jsdelivr.net/npm/tabulator-tables@6.3.1/dist/css/tabulator_semanticui.min.css"])o.importResource(e)}d(Yu,"importVendorStyles");async function Zu(o){let e=await o.getSetting("disabledPlugins","[]"),t=Ge(e),s=$t(t);return{migrated:s,needsMigration:JSON.stringify(t)!==JSON.stringify(s)}}d(Zu,"readDisabledPluginSettings");async function Xu(o,e,t,s,a,r,i=null){await o.update(n=>{let l=Ge(typeof n.disabledPlugins=="string"?n.disabledPlugins:"[]"),c=$t(l);if(JSON.stringify(l)!==JSON.stringify(c)&&(n.disabledPlugins=JSON.stringify(c)),t.needsOrigin){let h=new Set(Array.isArray(n.trustedLocalOrigins)?n.trustedLocalOrigins:[]);for(let u of t.origins)h.add(u);n.trustedLocalOrigins=[...h]}t.needsNotice&&(n.localOriginTrustNoticeV1=!0),Object.prototype.hasOwnProperty.call(n,"enableLoadScreenShot")||(n.enableLoadScreenShot="yes"),Object.prototype.hasOwnProperty.call(n,"enableScreenSvg")||(n.enableScreenSvg=n.enableLoadScreenShot??"yes"),n.sortMethod==null&&["default","rateCount","date"].includes(s||"")&&(n.sortMethod=s),n.foldCategoryCollapsed==null&&["yes","no"].includes(a||"")&&(n.foldCategoryCollapsed=a==="yes"),n.videoMuted==null&&["yes","no"].includes(r||"")&&(n.videoMuted=r==="yes");for(let h of i?.cleanup?.settingKeys||[])n[h]===i.cleanup.settingValues?.[h]&&delete n[h]})}d(Xu,"persistBootstrapMigration");async function ep(o){let e=await o.getSetting(),t=new Set(Array.isArray(e.trustedLocalOrigins)?e.trustedLocalOrigins:[]),s=null;try{e.webDavUrl&&(s=new URL(e.webDavUrl).origin)}catch{}return s&&!t.has(s)?(t.add(s),{origins:[...t],notice:`已按现有 WebDAV 配置授权本地来源:${s}`,needsOrigin:!0}):s&&!e.localOriginTrustNoticeV1?{origins:[...t],notice:`WebDAV 仅信任精确来源:${s}`,needsNotice:!0}:{origins:[...t],notice:null}}d(ep,"resolveLocalOrigins");async function Dd(){try{if(Ct(window.location).isJavDB){let E=Io(window.location);if(E)return void window.location.replace(E)}let o=performance.now(),e=globalThis.__jhsBrowserDiagnostics,t=d(E=>e&&((e.bootstrapPhases||(e.bootstrapPhases={}))[E]=performance.now()-o),"markPhase"),s=Ro(window.location),a=ll(),r=nl(),{utils:i,gmHttp:n,storageManager:l,stateService:c}=il(r);t("legacy-runtime"),Object.assign(globalThis,{utils:i,gmHttp:n,storageManager:l,stateService:c,jhsEventBus:r}),["blacklist-rules-changed","filter-rules-changed","legacy-refresh"].forEach((E=>r.on(E,(()=>l._invalidateCache())))),r.on("car-state-changed",()=>l._invalidateCache(l.car_list_key)),Qu(a.layer,i),await Promise.resolve(),Yu(i),t("pre-settings");let h=await Zu(l),u=h.migrated,p=await ep(l),g=new $s,m=new _s,f=M?g:B?m:null,v=f?.detectRoute()??"other",b=Fc({gmRequest:globalThis.GM_xmlhttpRequest,gmGetValue:globalThis.GM_getValue,gmSetValue:globalThis.GM_setValue,gmDeleteValue:globalThis.GM_deleteValue,legacyHttp:n,legacyStorage:l,eventBus:r,storageForage:l.forage,localStorage:globalThis.localStorage,layer:a.layer,stateService:c,hostAdapter:f,hostAdapters:{javdb:g,javbus:m},site:s.site,route:v,disabled:u,localOrigins:p.origins});t("context"),Vo(b.services.styles,Ho()),Object.assign(globalThis,{settingsService:b.services.settings,credentialService:b.services.credential}),await b.services.settings.load(),t("settings-load");let w=await b.services.credential.migrateLegacy(b.services.settings,{deferCleanup:!0});b.services.profile.start();let S=localStorage.getItem("jhs_sortMethod"),j=localStorage.getItem("jhs_foldCategory"),x=localStorage.getItem("jhs_videoMuted");w.cleanup=await b.services.credential.validateLegacyCleanup(w.cleanup),await Xu(b.services.settings,h,p,S,j,x,w),await b.services.credential.cleanupLegacyPageStorage(w.cleanup?.pageKeys,b.services.settings),t("settings-migration");let k=ol(b.rootScope,{clogMsgCount:b.services.settings.snapshot().clogMsgCount});t("logger"),Oo(b.rootScope),zo(b.rootScope),t("theme-ui"),b.services.diagnostics.setBrowserMetadata({userAgent:navigator.userAgent,platform:navigator.platform,...globalThis.__jhsBrowserTestMetadata??{}}),Object.assign(globalThis,k),w.issues?.length&&k.show.info("部分旧凭证未能安全迁移,已保留原数据,请重新保存对应凭证"),p.notice&&k.show.info(p.notice);let _=new ys({diagnostics:b.services.diagnostics});for(let E of Ed)b.registries.integrations.register(E);for(let E of vl)b.registries.features.register(E);return Nc(_,b.registries.features,s.site),t("registry"),Lc({pluginManager:_,utils:i,gmHttp:n,storageManager:l,stateService:c,jhsEventBus:r,clog:k.clog,show:k.show,loading:k.loading},globalThis.unsafeWindow),window.isDetailPage=v==="detail",window.isListPage=v==="list",await b.registries.features.start(),t("feature-runtime"),await ws(l),await l.getReviewFilterKeywordList(),await c.recoverPendingTransaction(),t("data-prepare"),await Promise.all([_.processCss(),Promise.resolve(Ht(b.services.settings.snapshot().themeMode))]),t("plugin-css"),M&&/(^|;)\s*locale\s*=\s*en\s*($|;)/i.test(document.cookie)&&k.show.error("请切换到中文语言下才可正常使用本脚本",{duration:-1}),await _.processPlugins(),t("plugin-runtime"),t("first-ready"),t("total"),b}catch(o){throw o instanceof D?o:new D("BOOTSTRAP_FAILED",o instanceof Error?o.message:"JHS 启动失败",{source:"bootstrap",cause:o})}}d(Dd,"bootstrapJhs");function Nd(o){if(console.error("[JHS] bootstrap failed:",o),globalThis.show?.error)return globalThis.show.error(o?.message||"JHS 启动失败",{duration:-1});let e=document.createElement("div");e.id="jhs-bootstrap-error",e.setAttribute("role","alert"),e.textContent=`JHS 启动失败:${o?.message||"未知错误"}`,Object.assign(e.style,{position:"fixed",inset:"12px 12px auto",zIndex:"2147483647",padding:"12px",background:"#7f1d1d",color:"white"}),document.documentElement.append(e)}d(Nd,"mountBootstrapError");Dd().catch(Nd);})(); + `}async handle(){let e=this.getRuntimeService("settings"),t=await this.getRuntimeService("scope")();if(!this._settingsListenerBound){this._settingsListenerBound=!0;let s=d(a=>{a.detail?.names?.includes("translateTitle")&&this.reconfigure()},"onSettingsChanged");e.addEventListener("settings.changed",s),t.addCleanup((()=>{e.removeEventListener("settings.changed",s),this._settingsListenerBound=!1}))}this.reconfigure()}reconfigure(){(this.getRuntimeService("settings").snapshot().translateTitle??E)===E?this.applyTranslation():(this.getOptionalDependency("ListPagePlugin")?.invalidateTranslations?.(),this.revertTranslation())}async applyTranslation(){if(isDetailPage)return this.translate();if(!window.isListPage)return;let e=this.getOptionalDependency("ListPagePlugin");if(!e?.translateListItems||typeof e.getSelector!="function")return;let t=$(e.getSelector().itemSelector).toArray();await e.translateListItems(t)}revertTranslation(){$(".translated-title").remove(),this.getOptionalDependency("ListPagePlugin")?.revertTranslation?.()}async translate(e,t=!0,s={}){let a=this.getRuntimeService("settings");if((a.snapshot().translateTitle??E)!==E)return;B&&(t=!1);let r=await this.getRuntimeService("scope")(),i=e??this.getPageInfo().carNum;await ea({root:s.root,carNum:i,translation:this.getRuntimeService("translation"),scope:r,isActive:d(()=>(a.snapshot().translateTitle??E)===E,"isActive")})}};d(Bn,"TranslatePlugin");var Qa=Bn;var F=d((o,e,t,s,a,r=[],i={})=>ul({id:o,featureId:e,legacyPluginId:t.legacyPluginId??t.name,plugin:t,sites:s,order:a,requires:r,routes:i.routes??(e==="detail"?["detail","owned-detail"]:[]),surfaces:i.surfaces??(e==="detail"?["detail-page"]:[])}),"manifest"),Ya=Object.freeze([F("list.core","list",Ha,["javdb","javbus"],{javdb:1,javbus:1},[Y.host,y.translation,y.http,y.storage,y.state,y.settings]),F("list.auto-page","list",Aa,["javdb","javbus"],{javdb:2,javbus:5},[y.http,y.settings]),F("detail.fc2-owned","detail",sa,["javdb"],{javdb:3},[y.movie,y.magnet,y.dialog,y.account,y.credential,y.translation,y.settings,y.storage,y.screenshot,y.review,y.related,y.state],{routes:["list","detail","owned-detail"],surfaces:["list-card","detail-page"]}),F("detail.fc2-navigation","detail",La,["javdb"],{javdb:4},[Y.host],{routes:["list"],surfaces:["list-card"]}),F("list.fold-category","list",Ma,["javdb"],{javdb:5},[y.settings]),F("list.actions","list",Va,["javdb","javbus"],{javdb:5,javbus:2},[y.settings]),F("library.history","library",Fa,["javdb","javbus"],{javdb:6,javbus:4},[y.dialog,y.movie,y.settings,y.state]),F("settings.core","settings",Fs,["javdb","javbus"],{javdb:7,javbus:3},[Y.host,y.diagnostics,y.profile,y.webdav,y.dialog,y.storage,y.settings,y.cache,y.http,y.offline,y.magnet,y.movie,y.state,y.translation,Qe.settings]),F("identity.javdb-navigation","identity",Ja,["javdb"],{javdb:8},[y.movie]),F("discovery.hit-show","discovery",aa,["javdb"],{javdb:9},[Y.host]),F("discovery.top250","discovery",ha,["javdb"],{javdb:10},[Y.host]),F("identity.image-search","identity",Rs,["javdb","javbus"],{javdb:11,javbus:6},[y.dialog,y.storage,y.imageSearch]),F("detail.cover-state-actions","detail",ba,["javdb","javbus"],{javdb:12,javbus:8},[y.storage,y.settings,y.movie,y.state],{routes:["list","detail","owned-detail"],surfaces:["list-card","detail-page"]}),F("detail.fc2-lookup","detail",Ys,["javdb"],{javdb:13},[Y.host,y.movie],{routes:["list","detail","owned-detail"],surfaces:["list-card","detail-page"]}),F("detail.javdb-native","detail",Da,["javdb"],{javdb:14}),F("detail.workspace","detail",Na,["javdb","javbus"],{javdb:15,javbus:11},[Y.host]),F("detail.reviews","detail",da,["javdb","javbus"],{javdb:16,javbus:13},[Y.host,y.review,y.movie,y.settings,y.storage]),F("detail.related","detail",ca,["javdb"],{javdb:17},[Y.host,y.related,y.settings]),F("detail.page-state-actions","detail",Ea,["javdb","javbus"],{javdb:18,javbus:12},[y.movie,y.dialog,y.subtitle,y.state,y.settings]),F("detail.native-magnets","detail",Ba,["javdb","javbus"],{javdb:19,javbus:15},[Y.host,y.settings]),F("detail.javdb-preview","detail",wa,["javdb"],{javdb:20},[y.storage,y.settings,y.movie,y.dialog]),F("library.keyword-filter","library",Ks,["javdb","javbus"],{javdb:21,javbus:14}),F("identity.actress-info","identity",Ps,["javdb"],{javdb:22},[y.actressInfo,y.settings]),F("detail.external-sites","detail",la,["javdb","javbus"],{javdb:23,javbus:19},[Y.host,y.movie,y.storage,y.settings]),F("external-bridge.translation","external-bridge",Qa,["javdb","javbus"],{javdb:24,javbus:20},[y.translation,y.settings]),F("library.state-actions","library",Ka,["javdb"],{javdb:25},[y.http,y.state]),F("detail.external-magnets","detail",oa,["javdb","javbus"],{javdb:26,javbus:17},[y.storage,y.http,y.magnet]),F("detail.screenshot","detail",ya,["javdb","javbus"],{javdb:27,javbus:18},[y.screenshot,y.settings]),F("library.blacklist","library",Js,["javdb","javbus"],{javdb:28,javbus:21},[Y.host,y.dialog,y.storage,y.http,y.state]),F("library.favorite-actresses","library",pa,["javdb"],{javdb:29}),F("discovery.new-video","discovery",ja,["javdb"],{javdb:30},[y.dialog,y.storage,y.actressInfo,y.movie,y.state]),F("discovery.scheduler","discovery",xa,["javdb","javbus"],{javdb:31,javbus:22},[y.storage,y.http,y.actressInfo,y.movie,y.state]),F("stats.dashboard","stats",Ta,["javdb","javbus"],{javdb:32,javbus:23},[y.diagnostics,y.dialog,y.movie,y.state]),F("responsive-shell.bottom-bar","responsive-shell",Wa,["javdb","javbus"],{javdb:33,javbus:24},[Y.host,y.settings,y.profile]),F("external-bridge.115-match","external-bridge",Ca,["javdb","javbus"],{javdb:34,javbus:25},[Y.host,y.dialog,y.offline,y.settings]),F("external-bridge.offline","external-bridge",ka,["javdb","javbus"],{javdb:35,javbus:26},[Y.host,y.dialog,y.offline,y.state,y.settings]),F("compatibility.enhancements","compatibility",Ia,["javdb","javbus"],{javdb:36,javbus:27},[y.state]),F("identity.javbus-navigation","identity",Ra,["javbus"],{javbus:7}),F("detail.javbus-images","detail",ga,["javbus"],{javbus:9}),F("detail.javbus-native","detail",Pa,["javbus"],{javbus:10}),F("detail.javbus-preview","detail",va,["javbus"],{javbus:16},[y.settings,y.storage,y.movie]),F("external-bridge.123pan","external-bridge",_a,["javdb","javbus","123pan"],{javdb:0,javbus:0,"123pan":1},[y.storage]),F("external-bridge.javtrailers","external-bridge",ra,["javtrailers"],{javtrailers:1}),F("external-bridge.subtitle","external-bridge",Ga,["subtitlecat"],{subtitlecat:1})]),Dc=new Set,Nc=new Set;for(let o of Ya){if(Dc.has(o.id))throw new Error(`Duplicate contribution id: ${o.id}`);if(Nc.has(o.legacyPluginId))throw new Error(`Duplicate legacy plugin contribution: ${o.legacyPluginId}`);Dc.add(o.id),Nc.add(o.legacyPluginId)}function Lc(o,e,t){o.setDependencyDeclarations(wl),e.setContributionManifests?.(Ya),o.setCatalogDescriptors(Ya.filter(s=>s.sites.includes(t)).map(s=>({name:s.legacyPluginId,disableable:e.isFeatureDisableable(s.featureId)}))),Ya.filter(s=>s.sites.includes(t)&&e.isContributionEnabled(s.featureId,s.id,s.legacyPluginId)).sort((s,a)=>Number(s.order[t])-Number(a.order[t])).forEach(s=>{let a=e.resolveDeclaredDependencies(s.requires),r={};r.scope=()=>e.getContributionScope(s.featureId,s.id,s.legacyPluginId);let i=new Map([[Y.host,"host"],[y.diagnostics,"diagnostics"],[y.review,"review"],[y.related,"related"],[y.movie,"movie"],[y.magnet,"magnet"],[y.settings,"settings"],[y.cache,"cache"],[y.http,"http"],[y.profile,"profile"],[y.actressInfo,"actressInfo"],[y.imageSearch,"imageSearch"],[y.screenshot,"screenshot"],[y.translation,"translation"],[y.subtitle,"subtitle"],[y.account,"account"],[y.webdav,"webdav"],[y.credential,"credential"],[y.storage,"storage"],[y.state,"state"],[y.offline,"offline"],[y.dialog,"dialog"],[Qe.settings,"settingsRegistry"]]);for(let n of s.requires){let l=i.get(n);if(!l)throw new Error(`Legacy contribution ${s.id} has no runtime name for ${String(n)}`);r[l]=a[n]}o.register(s.plugin,r,{disableable:e.isFeatureDisableable(s.featureId)})})}d(Lc,"registerSitePlugins");function Mc(o,e){for(let t of["pluginManager","utils","gmHttp","storageManager","stateService","jhsEventBus","clog","show","loading"]){if(o[t]==null)throw new Error(`Compatibility facade is missing ${t}`);e[t]=o[t]}return Object.freeze(Object.fromEntries(Object.keys(o).map(t=>[t,e[t]])))}d(Mc,"attachCompatibilityFacade");function He(o,e,t){if(!o||typeof o!="object")throw new TypeError(`${e} implementation is required`);for(let s of t)if(typeof o[s]!="function")throw new TypeError(`${e}.${s} is required`);return o}d(He,"assertPort");var We=Object.freeze({navigation:["open","assign","replace"],http:["request"],storage:["get","set","remove","keys","getLocal","setLocal","removeLocal","getValue","setValue","removeValue"],dialog:["open","close","confirm","alert"],style:["register","remove"]});var On=class On{constructor(e={}){this.location=e.location??window.location,this.openWindow=e.open??window.open.bind(window),He(this,"NavigationPort",We.navigation)}open(e,t={}){return t.newTab?this.openWindow(e,"_blank","noopener"):this.assign(e)}assign(e){this.location.assign(e)}replace(e){this.location.replace(e)}};d(On,"BrowserNavigationAdapter");var Za=On;var Un=class Un{constructor(e=document){this.document=e}register(e,t){if(this.document.getElementById(e))throw new Error(`Duplicate style: ${e}`);let s=this.document.createElement("style");return s.id=e,s.textContent=t,this.document.head.append(s),()=>s.remove()}remove(e){this.document.getElementById(e)?.remove()}};d(Un,"BrowserStyleAdapter");var Xa=Un;var zn=class zn{constructor(e,t,s,a,r=()=>{}){this.forage=e,this.localStore=t,this.gmGetValue=s,this.gmSetValue=a,this.gmDeleteValue=r}get(e){return this.forage.getItem(e)}async set(e,t){await this.forage.setItem(e,t)}async remove(e){await this.forage.removeItem(e)}keys(){return this.forage.keys()}getLocal(e){return this.localStore.getItem(e)}setLocal(e,t){this.localStore.setItem(e,t)}removeLocal(e){this.localStore.removeItem(e)}getValue(e,t){return this.gmGetValue(e,t)}setValue(e,t){this.gmSetValue(e,t)}removeValue(e){this.gmDeleteValue(e)}};d(zn,"IndexedDbStorageAdapter");var er=zn;var Fn=class Fn{constructor(e){this.layer=e}open(e){return this.layer.open(this.withDefaultLayer(e))}close(e){this.layer.close(e)}confirm(e,t,s){return this.layer.confirm(e,this.withDefaultLayer(t),s)}alert(e,t){return this.layer.alert(e,this.withDefaultLayer(t))}withDefaultLayer(e={}){let t={zIndex:J.layer,...e};return e.ui?kt(t,globalThis.utils):t}};d(Fn,"LayerDialogAdapter");var tr=Fn;var Vn=class Vn{constructor(e,t=globalThis.fetch?.bind(globalThis)??null){if(typeof e!="function")throw new TypeError("GM_xmlhttpRequest is required");this.requestImplementation=e,this.fetchImplementation=t}request(e){return e.transport==="native-fetch"&&this.fetchImplementation?this.requestWithNativeFetch(e).catch((t=>{if(t instanceof D&&t.code==="ABORTED")throw t;return this.requestWithUserscript(e)})):this.requestWithUserscript(e)}async requestWithNativeFetch(e){let t=new AbortController,s=!1,a=Math.max(0,Number(e.nativeTimeout)||0),r=d(()=>t.abort(),"onAbort"),i=a>0?setTimeout((()=>{s=!0,t.abort()}),a):null;e.signal?.addEventListener("abort",r,{once:!0});try{e.signal?.aborted&&t.abort();let n=await this.fetchImplementation(e.url,{method:e.method??"GET",headers:e.headers,body:e.body,signal:t.signal}),l=await n.text(),c=e.responseType==="json"?JSON.parse(l):l;return{status:n.status,data:c,responseText:l,finalUrl:n.url||e.url,responseHeaders:[...n.headers.entries()].map((h=>h.join(": "))).join(`\r +`)}}catch(n){throw e.signal?.aborted?new D("ABORTED","网络请求已取消",{source:"UserscriptHttpAdapter",cause:n}):s?new D("TIMEOUT","原生网络请求超时",{source:"UserscriptHttpAdapter",cause:n,retryable:!0}):new D("NETWORK_ERROR","原生网络请求失败",{source:"UserscriptHttpAdapter",cause:n,retryable:!0})}finally{i!==null&&clearTimeout(i),e.signal?.removeEventListener("abort",r)}}requestWithUserscript(e){return new Promise((t,s)=>{let a=!1,r,i=d((l,c)=>{a||(a=!0,e.signal?.removeEventListener("abort",n),l(c))},"finish"),n=d(()=>{r?.abort?.(),i(s,new D("ABORTED","网络请求已取消",{source:"UserscriptHttpAdapter"}))},"onAbort");r=this.requestImplementation({...e.requestOptions,method:e.method??"GET",url:e.url,headers:e.headers,data:e.body,responseType:e.responseType,timeout:e.timeout,onload:d(l=>i(t,{status:l.status,data:l.response??l.responseText,responseText:l.responseText??"",finalUrl:l.finalUrl||e.url,responseHeaders:l.responseHeaders??""}),"onload"),onerror:d(l=>i(s,new D("NETWORK_ERROR","网络请求失败",{source:"UserscriptHttpAdapter",cause:l,retryable:!0})),"onerror"),ontimeout:d(()=>i(s,new D("TIMEOUT","网络请求超时",{source:"UserscriptHttpAdapter",retryable:!0})),"ontimeout"),onabort:d(()=>i(s,new D("ABORTED","网络请求已取消",{source:"UserscriptHttpAdapter"})),"onabort")}),e.signal?.aborted?n():e.signal?.addEventListener("abort",n,{once:!0})})}};d(Vn,"UserscriptHttpAdapter");var sr=Vn;async function Bc(o){let e=await globalThis.crypto.subtle.digest("SHA-256",new TextEncoder().encode(o));return Array.from(new Uint8Array(e),(t=>t.toString(16).padStart(2,"0"))).join("")}d(Bc,"digestKey");var qn=class qn{constructor(e={}){this.namespaceVersion=e.namespaceVersion??2,this.diagnostics=e.diagnostics??null,this.storage=e.storage??null,this.publicCache=new Map,this.sessionCaches=new Map,this.publicReads=new Map,this.publicGenerations=new Map,this.publicNamespaces=new Set(["default"]),this.publicWritesSincePrune=0,this.pruneScheduled=!1,this.pruneRunning=!1,this.prunePromise=null}get publicGeneration(){return this.publicGenerations.get("default")||0}generation(e){return this.publicGenerations.get(e)||0}get publicPrefix(){return this._publicPrefix("default")}_publicPrefix(e="default"){return`jhs_http_public_cache:v${this.namespaceVersion}:${encodeURIComponent(e)}:`}storeFor(e,t=""){if(e==="public")return this.publicCache;if(e==="session"){if(!t)throw new TypeError("sessionScopeId is required for session cache");let s=this.sessionCaches.get(t);return s||this.sessionCaches.set(t,s=new Map),s}return null}async get(e,t,s){arguments.length===2&&(s=t,t=e,e="default"),e=String(e||"default"),this.publicNamespaces.add(e);let a=this.storeFor(s.scope,s.sessionScopeId),r=`${e}:${this.namespaceVersion}:${t}`,i=Date.now(),n=this.storage,l=a?.get(r);if(l&&l.expiresAt>i)return this.diagnostics?.recordCache(!0),{hit:!0,value:l.value,negative:l.negative};if(l&&a?.delete(r),s.scope!=="public"||!n)return this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1};let c=`${e}:${t}`,h=this.publicReads.get(c);if(h)return h;let u=this.generation(e),p=(async()=>{let g=this._publicPrefix(e)+await Bc(t),m;try{m=await n.get(g)}catch{return this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1}}if(m?.version!==this.namespaceVersion||!Number.isFinite(m?.expiresAt)||m.expiresAt<=i)return m&&await n.remove(g).catch(()=>{}),this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1};if(u!==this.generation(e))return this.diagnostics?.recordCache(!1),{hit:!1,value:void 0,negative:!1};let f={value:m.value,expiresAt:m.expiresAt,negative:m.negative===!0};return this.publicCache.set(r,f),this.diagnostics?.recordCache(!0),{hit:!0,value:f.value,negative:f.negative}})().finally(()=>{this.publicReads.get(c)===p&&this.publicReads.delete(c)});return this.publicReads.set(c,p),p}async set(e,t,s,a){arguments.length===3&&(a=s,s=t,t=e,e="default"),e=String(e||"default"),this.publicNamespaces.add(e);let r=Math.min(2592e6,Math.max(0,Number(a.ttlMs)||0));if(!r||a.scope==="public"&&a.generation!=null&&a.generation!==this.generation(e))return;let i={value:s,expiresAt:Date.now()+r,negative:a.negative??!1},n=this.storeFor(a.scope,a.sessionScopeId),l=`${e}:${this.namespaceVersion}:${t}`,c=this.storage;if(a.scope!=="public"||!c){n?.set(l,i);return}if(a.generation!=null&&a.generation!==this.generation(e))return;let h=this._publicPrefix(e)+await Bc(t);if(!(a.generation!=null&&a.generation!==this.generation(e)))try{if(a.generation!=null&&a.generation!==this.generation(e))return;if(await c.set(h,{version:this.namespaceVersion,...i,lastUsed:Date.now()}),a.generation!=null&&a.generation!==this.generation(e)){await c.remove(h).catch(()=>{});return}n?.set(l,i),this.publicWritesSincePrune++,this.schedulePublicPrune()}catch{}}schedulePublicPrune(){if(!this.storage||this.publicWritesSincePrune<64||this.pruneScheduled||this.pruneRunning)return this.prunePromise;this.pruneScheduled=!0;let e=d(async()=>{this.pruneScheduled=!1,this.pruneRunning=!0,this.publicWritesSincePrune=0;try{await this.prunePublic()}catch{}finally{this.pruneRunning=!1,this.prunePromise=null,this.schedulePublicPrune()}},"run");return this.prunePromise=Promise.resolve().then(e),this.prunePromise}async waitForPrune(){await this.prunePromise?.catch(()=>{})}async prunePublic(){if(!this.storage)return;let e;try{e=await this.storage.keys()}catch{return}let t=Date.now(),s=[];for(let a of e.filter(r=>r.startsWith("jhs_http_public_cache:v"))){let r=await this.storage.get(a).catch(()=>null);if(!r||r.version!==this.namespaceVersion||!Number.isFinite(r.expiresAt)||r.expiresAt<=t){await this.storage.remove(a).catch(()=>{});continue}s.push({key:a,lastUsed:Number(r.lastUsed)||0})}if(s.length>500){s.sort((a,r)=>a.lastUsed-r.lastUsed);for(let a of s.slice(0,s.length-500))await this.storage.remove(a.key).catch(()=>{})}}async clearNamespace(e){e=String(e||"default"),this.publicGenerations.set(e,this.generation(e)+1);for(let a of this.publicCache.keys())a.startsWith(`${e}:`)&&this.publicCache.delete(a);for(let a of this.publicReads.keys())a.startsWith(`${e}:`)&&this.publicReads.delete(a);await this.waitForPrune();let t=this.storage;if(!t)return;let s;try{s=await t.keys()}catch{return}await Promise.all(s.filter((a=>a.startsWith(this._publicPrefix(e)))).map((a=>t.remove(a).catch(()=>{}))))}async clearAll(){let e=new Set(this.publicNamespaces);for(let t of e)await this.clearNamespace(t);if(this.publicCache.clear(),this.publicReads.clear(),this.sessionCaches.clear(),this.storage)try{let t=this.storage,s=`jhs_http_public_cache:v${this.namespaceVersion}:`,a=await t.keys();await Promise.all(a.filter(r=>r.startsWith(s)).map(r=>t.remove(r).catch(()=>{})))}catch{}}async clearPublic(){return this.clearAll()}async invalidateNamespace(){return this.clearAll()}};d(qn,"CacheService");var ar=qn;var Hn=class Hn{constructor(e,t){this.integrations=e,this.cache=t}profileUrl(e){for(let t of this.integrations.list("person.actress-info")){let s=this.integrations.getAdapter(t.id);if(typeof s.profileUrl=="function")return s.profileUrl(e)}return""}async lookup(e,t={}){let s=String(e).trim()==="三上悠亞"?"三上悠亜":String(e).trim();if(!s)return null;let a=`actress-info:${s}`,r=await this.cache.get("actress-info",a,{scope:"public"});if(r.hit)return r.value;let i=this.cache.generation("actress-info");for(let n of this.integrations.list("person.actress-info")){let l=this.integrations.getAdapter(n.id);if(typeof l.lookup!="function")continue;let c=await l.lookup(s,t);return await this.cache.set("actress-info",a,c,{scope:"public",ttlMs:6048e5,negative:!c,generation:i}),c}return null}async movies(e,t,s={}){let a=this.integrations.list("actor.movies").find(i=>i.id===e);if(!a)return[];let r=this.integrations.getAdapter(a.id);return typeof r?.listActorMovies=="function"?r.listActorMovies(t,s):[]}async collection(e,t,s={}){let a=this.integrations.list("actor.collection").find(i=>i.id===e);if(!a)throw new TypeError(`Actor collection provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.listActorCollection!="function")throw new TypeError(`Actor collection is unavailable: ${e}`);return r.listActorCollection(t,s)}async uncollect(e,t,s={}){let a=this.integrations.list("actor.uncollect").find(i=>i.id===e);if(!a)throw new TypeError(`Actor provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.uncollectActor!="function")throw new TypeError(`Actor uncollect is unavailable: ${e}`);return r.uncollectActor(t,s)}getAvatarSources(){return Object.freeze(this.integrations.list("person.avatar-search").flatMap(e=>{let t=this.integrations.getAdapter(e.id);return typeof t?.getSources=="function"?t.getSources():[]}))}async searchAvatars(e,t,s={}){for(let a of this.integrations.list("person.avatar-search")){let r=this.integrations.getAdapter(a.id);if(r?.getSources?.().some(i=>i.id===t))return r.searchAvatars(e,{...s,sourceId:t})}return[]}placeholderUrl(e){let t=this.integrations.getAdapter(e);return typeof t?.actorPlaceholderUrl=="function"?t.actorPlaceholderUrl():""}};d(Hn,"ActressInfoService");var rr=Hn;var Zh=/^(?:authorization|cookie|set-cookie|password|token|secret|credential)$/i;function Wn(o,e=""){return Zh.test(e)?"[redacted]":Array.isArray(o)?o.map(t=>Wn(t)):o&&typeof o=="object"?Object.fromEntries(Object.entries(o).map(([t,s])=>[t,Wn(s,t)])):typeof o!="string"?o:o.replace(/(https?:\/\/)([^\s/@:]+):([^\s/@]+)@/gi,"$1[redacted]@")}d(Wn,"sanitize");var Jn=class Jn{constructor(e={}){this.startedAt=performance.now(),this.activeFeatures=new Set,this.activeContributions=new Set,this.startupTimings=new Map,this.scopes=new Map,this.requestStats={consumers:0,underlying:0},this.cacheStats={hits:0,misses:0},this.providerHealth=new Map,this.errors=[],this.browserMetadata=null,this.legacyPlugins=[],this.legacyPluginDescriptors=[],this.legacyStartup=null,this.legacyTimings=[],this.legacyHttp=e.legacyHttp??null,this.networkController=null}recordStartup(e,t){this.startupTimings.set(e,t)}setFeature(e,t){t?this.activeFeatures.add(e):this.activeFeatures.delete(e)}setContribution(e,t){t?this.activeContributions.add(e):this.activeContributions.delete(e)}updateScope(e){this.scopes.set(e.id,Object.freeze({...e}))}updateRequests(e,t){this.requestStats={consumers:e,underlying:t}}recordCache(e){e?this.cacheStats.hits+=1:this.cacheStats.misses+=1}updateProvider(e,t){this.providerHealth.set(e,Object.freeze({...t}))}recordError(e){let t=e&&typeof e=="object"&&"toJSON"in e&&typeof e.toJSON=="function"?e.toJSON():e instanceof Error?{message:e.message}:e&&typeof e=="object"?{...e}:{message:String(e)};this.errors.push({...Wn(t),timestamp:new Date().toISOString()}),this.errors.length>100&&this.errors.shift()}setBrowserMetadata(e){this.browserMetadata=Object.freeze({...e})}setLegacyRuntime(e,t,s){this.legacyPluginDescriptors=e.map(a=>Object.freeze({...a})),this.legacyPlugins=e.map(a=>a.name),this.legacyStartup=Object.freeze({...t}),this.legacyTimings=s.map(a=>Object.freeze({...a}))}clearErrors(){this.errors=[]}setNetworkController(e){this.networkController=e}getNetworkDiagnostics(){let e=this.networkController??this.legacyHttp;return Object.freeze({circuitBreakers:e?.getCircuitBreakerStatus?.()??{},domainStats:e?.getDomainStats?.()??{}})}resetCircuitBreaker(e){(this.networkController??this.legacyHttp)?.resetCircuitBreaker?.(e)}resetAllCircuitBreakers(){(this.networkController??this.legacyHttp)?.resetAllCircuitBreakers?.()}clearDomainStats(){(this.networkController??this.legacyHttp)?.clearDomainStats?.()}exportSnapshot(){let e=[...this.scopes.values()];return Object.freeze({activeFeatures:[...this.activeFeatures],activeContributions:[...this.activeContributions],startupTimings:Object.fromEntries(this.startupTimings),activeScopes:e,globalListeners:e.filter(t=>t.id==="app:root").reduce((t,s)=>t+Number(s.listeners??0),0),observers:e.reduce((t,s)=>t+Number(s.observers??0),0),requestConsumers:this.requestStats.consumers,underlyingRequests:this.requestStats.underlying,cacheHits:this.cacheStats.hits,cacheMisses:this.cacheStats.misses,providerHealth:Object.fromEntries(this.providerHealth),errors:this.errors.map(t=>({...t})),legacyPlugins:[...this.legacyPlugins],legacyPluginDescriptors:this.legacyPluginDescriptors.map(t=>({...t})),legacyStartup:this.legacyStartup,legacyTimings:this.legacyTimings.map(t=>({...t})),browser:this.browserMetadata,uptimeMs:performance.now()-this.startedAt})}};d(Jn,"DiagnosticsService");var ir=Jn;var Kn=class Kn{constructor(e){this.port=He(e,"DialogPort",We.dialog)}open(e){return this.port.open(e)}close(e){return this.port.close(e)}confirm(e,t,s){return this.port.confirm(e,t,s)}alert(e,t){return this.port.alert(e,t)}};d(Kn,"DialogService");var nr=Kn;var Xh=[/^10\./,/^127\./,/^169\.254\./,/^192\.168\./,/^172\.(?:1[6-9]|2\d|3[01])\./,/^0\./];function eu(o){let e=o.replace(/^\[|\]$/g,"").toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="::1"?!0:e.includes(":")?e.startsWith("fc")||e.startsWith("fd")||e.startsWith("fe8")||e.startsWith("fe9")||e.startsWith("fea")||e.startsWith("feb"):Xh.some(t=>t.test(e))}d(eu,"isPrivateLiteral");var Gn=class Gn{constructor(e={}){this.localOrigins=new Set,this.replaceLocalOrigins(e.localOrigins??[])}authorizeLocalOrigin(e){this.localOrigins.add(new URL(e).origin)}replaceLocalOrigins(e){let t=new Set(e.map(s=>new URL(s).origin));this.localOrigins=t}assertAllowed(e,t){let s;try{s=e instanceof URL?e:new URL(e)}catch(a){throw new D("INVALID_URL","外部地址无效",{source:"ExternalUrlPolicy",cause:a})}if(!new Set(["http:","https:"]).has(s.protocol))throw new D("INVALID_URL","仅允许 HTTP/HTTPS 地址",{source:"ExternalUrlPolicy"});if(t.expectedOrigin&&s.origin!==new URL(t.expectedOrigin).origin)throw new D("INVALID_URL","地址离开已声明的精确 origin",{source:"ExternalUrlPolicy"});if(t.trustClass==="builtin-public"){if(s.protocol!=="https:"||!(t.hosts??[]).some(a=>s.hostname===a||s.hostname.endsWith(`.${a}`)))throw new D("INVALID_URL","地址不在 Integration manifest 允许范围",{source:"ExternalUrlPolicy"})}else if(t.trustClass==="custom-public"){if(s.protocol!=="https:"||eu(s.hostname))throw new D("INVALID_URL","自定义公开来源必须使用公网 HTTPS",{source:"ExternalUrlPolicy"})}else if(t.trustClass==="user-local"){let a=t.expectedOrigin?new URL(t.expectedOrigin).origin:s.origin;if(!this.localOrigins.has(a)||s.origin!==a)throw new D("INVALID_URL","本地来源未获得精确 origin 授权",{source:"ExternalUrlPolicy"})}else throw new D("INVALID_URL","未知 URL trust class",{source:"ExternalUrlPolicy"});return s}assertFinalUrl(e,t){return this.assertAllowed(e,t)}};d(Gn,"ExternalUrlPolicy");var or=Gn;function us(o){if(o==null||typeof o!="object")return JSON.stringify(o);if(Array.isArray(o))return`[${o.map(us).join(",")}]`;let e=o;return`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${us(e[t])}`).join(",")}}`}d(us,"stableSerialize");async function Oc(o){let e=new TextEncoder().encode(o),t=await crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(t)].map(s=>s.toString(16).padStart(2,"0")).join("")}d(Oc,"sha256");function tu(o){let e=new URL(o),t=[...e.searchParams.entries()].sort(([s,a],[r,i])=>s.localeCompare(r)||a.localeCompare(i));e.search="";for(let[s,a]of t)e.searchParams.append(s,a);return e.hash="",e.href}d(tu,"canonicalizeUrl");function su(o,e=0){if(typeof o!="string"||!o)return!1;let t=o.toLowerCase(),s=/]*>\s*just a moment(?:\.\.\.)?\s*<\/title>/i.test(o),a=/id=["']challenge-form["']/i.test(o),r=t.includes("cf-chl-")||t.includes("cf_chl_opt"),i=t.includes("/cdn-cgi/challenge-platform/")||t.includes("challenge-platform");return s||a&&(r||i)||[403,429,503].includes(e)&&r&&i}d(su,"isCloudflareChallenge");function au(o,e){return o<=0?Promise.resolve():new Promise((t,s)=>{let r=setTimeout(d(()=>{e?.removeEventListener("abort",i),t()},"finish"),o),i=d(()=>{clearTimeout(r),s(new D("ABORTED","请求已取消",{source:"HttpService"}))},"onAbort");e?.addEventListener("abort",i,{once:!0}),Promise.resolve().then(()=>e?.aborted&&i())})}d(au,"waitForRetry");async function ru(o){let e=String(o.method??"GET").toUpperCase(),t=Object.fromEntries(Object.entries(o.headers??{}).map(([i,n])=>[i.toLowerCase(),String(n)])),s=[...new Set((o.varyHeaders??[]).map(i=>String(i).toLowerCase()))].sort(),a=Object.fromEntries(s.map(i=>[i,t[i]??""])),r={providerId:String(o.providerId),cacheNamespace:String(o.cacheNamespace??o.providerId??"default"),method:e,canonicalUrl:tu(o.url),bodyHash:await Oc(us(o.body??null)),responseType:String(o.responseType??"text"),cacheScope:String(o.cacheScope??"none"),varyHeadersHash:await Oc(us(a)),sessionScopeId:o.cacheScope==="session"?String(o.sessionScopeId??""):""};if(r.cacheScope==="session"&&!r.sessionScopeId)throw new TypeError("sessionScopeId is required for session requests");return Object.freeze(r)}d(ru,"createRequestKey");var Qn=class Qn{constructor(e,t,s={}){this.port=e,this.urlPolicy=t,this.diagnostics=s.diagnostics??null,this.cache=s.cache??null,this.settings=s.settings??null,this.inflight=new Map,this.circuitBreakers=new Map,this.domainStats=new Map}async request(e,t){t?.assertActive();let s=String(e.method??"GET").toUpperCase();if(this.settings){let m=this.settings.snapshot();e={...e,timeout:e.timeout??Math.max(1e3,Math.min(12e4,Number(m.httpTimeout)||5e3)),retryCount:e.retryCount??(["GET","HEAD"].includes(s)?Math.max(1,Math.min(10,Math.trunc(Number(m.httpRetryCount)||3)))-1:0),circuitThreshold:e.circuitThreshold??Number(m.circuitBreakerThreshold??3),circuitCooldownMs:e.circuitCooldownMs??Number(m.circuitBreakerCooldown??6e4)}}let a=e.cacheScope??"none";if(s!=="GET"&&a!=="none")throw new TypeError("Mutation requests cannot use generic cache/dedupe");let r=e.urlPolicy,i=this.urlPolicy.assertAllowed(e.url,r);if(s!=="GET"||a==="none")return this.executeUnderlying({...e,method:s,url:i.href,signal:t?.signal},r);let n=String(e.cacheNamespace??e.providerId??"default"),l=await ru({...e,method:s,url:i.href,cacheScope:a,cacheNamespace:n});t?.assertActive();let c=us(l),h={scope:a,sessionScopeId:e.sessionScopeId};if(s==="GET"&&a!=="none"&&this.cache){let m=await this.cache.get(n,c,h);if(t?.assertActive(),m.hit)return m.value}let u=a==="public"&&this.cache?this.cache.generation(n):void 0,p=JSON.stringify([c,u??null]),g=this.inflight.get(p);if(!g){let m=new AbortController;g={controller:m,consumers:0,promise:Promise.resolve()},g.promise=this.executeUnderlying({...e,method:s,url:i.href,signal:m.signal},r).then(async f=>(this.cache&&(u==null||u===this.cache.generation(n))&&await this.cache.set(n,c,f,{...h,ttlMs:e.ttlMs??0,negative:e.negative===!0,generation:u}),f)).finally(()=>{this.inflight.get(p)===g&&this.inflight.delete(p),this.updateDiagnostics()}),this.inflight.set(p,g)}return this.consume(g,t)}async executeUnderlying(e,t){let s=new URL(e.url).hostname,a=Math.max(0,Math.min(9,Math.trunc(Number(e.retryCount??0)||0))),r=new Set((e.acceptableStatuses??[]).map(c=>Number(c)).filter(Number.isFinite)),i=this.ensureCircuit(s,e),n=!1,l=null;for(let c=0;c<=a;c+=1){if(e.signal?.aborted){l=new D("ABORTED","请求已取消",{source:e.providerId});break}let h=n?null:this.checkCircuit(s);if(h){l=new D("CIRCUIT_OPEN",`站点 ${s} 已熔断,${h.remaining}秒后重试`,{source:e.providerId,details:{domain:s,remainingSeconds:h.remaining}});break}i.state==="half-open"&&(i.probing=!0,n=!0);try{let u=await this.port.request(e);if(this.urlPolicy.assertFinalUrl(u.finalUrl||e.url,t),su(u.responseText??u.data,u.status))throw new D("CF_BLOCKED",`Cloudflare challenge blocked: ${s}`,{source:e.providerId,details:{domain:s,status:Number(u.status)||0,contentLength:String(u.responseText??"").length}});if(r.has(Number(u.status)))return this.recordSuccess(s),u;if(u.status>=400){let p=[401,403].includes(u.status)?"AUTH_REQUIRED":u.status===404?"NOT_FOUND":u.status===429?"RATE_LIMITED":"NETWORK_ERROR";throw new D(p,`HTTP ${u.status}`,{source:e.providerId,retryable:u.status===429||u.status>=500,details:{status:u.status,domain:s}})}return this.recordSuccess(s),u}catch(u){let p=D.from(u,e.providerId);if(this.recordAttempt(s,!0),l=p,!p.retryable||c>=a||p.code==="CF_BLOCKED")break;try{await au(Number(e.retryDelayMs??250)*(c+1),e.signal)}catch(g){l=D.from(g,e.providerId);break}}}throw l&&["NETWORK_ERROR","TIMEOUT","CF_BLOCKED"].includes(l.code)&&this.recordBreakerFailure(s,e),n&&(i.probing=!1),this.diagnostics?.recordError(l),l}ensureCircuit(e,t={}){let s=this.circuitBreakers.get(e);return s?(t.circuitCooldownMs!=null&&(s.cooldownMs=Math.max(1e3,Number(t.circuitCooldownMs)||6e4)),t.circuitThreshold!=null&&(s.threshold=Math.max(1,Number(t.circuitThreshold)||3))):(s={state:"closed",failCount:0,openTime:0,cooldownMs:Math.max(1e3,Number(t.circuitCooldownMs??6e4)||6e4),threshold:Math.max(1,Number(t.circuitThreshold??3)||3),probing:!1},this.circuitBreakers.set(e,s)),s}checkCircuit(e){let t=this.circuitBreakers.get(e);if(!t)return null;if(t.state==="open"){let s=Date.now()-t.openTime;if(s=s.threshold)&&(s.state="open",s.openTime=Date.now(),s.probing=!1)}recordFailure(e,t={}){this.recordAttempt(e,!0),this.recordBreakerFailure(e,t)}getCircuitBreakerStatus(){return Object.fromEntries([...this.circuitBreakers].map(([e,t])=>[e,{...t}]))}getDomainStats(){return Object.fromEntries([...this.domainStats].map(([e,t])=>[e,{...t}]))}resetCircuitBreaker(e){this.circuitBreakers.delete(e)}resetAllCircuitBreakers(){this.circuitBreakers.clear()}clearDomainStats(){this.domainStats.clear()}consume(e,t){e.consumers+=1;let s=!1,a={release:d(()=>{s||(s=!0,e.consumers-=1,e.consumers===0&&!this.isSettled(e)&&e.controller.abort(),this.updateDiagnostics())},"release")},r;try{r=t?.ownRequestConsumer(a)}catch(l){throw a.release(),e.promise.catch(()=>{}),l}this.updateDiagnostics();let i=d(()=>{},"removeAbortListener");return(t?Promise.race([e.promise,new Promise((l,c)=>{let h=d(()=>c(new D("ABORTED","LifecycleScope 已释放",{source:t.id})),"onAbort");t.signal.addEventListener("abort",h,{once:!0}),i=d(()=>t.signal.removeEventListener("abort",h),"removeAbortListener")})]):e.promise).finally(()=>{i(),r?.(),a.release()})}isSettled(e){return![...this.inflight.values()].includes(e)}updateDiagnostics(){let e=[...this.inflight.values()].reduce((t,s)=>t+s.consumers,0);this.diagnostics?.updateRequests(e,this.inflight.size)}};d(Qn,"HttpService");var lr=Qn;var Yn=class Yn{constructor(e){this.integrations=e}async resolve(e,t={}){let s=this.integrations.list("image.search-targets")[0];if(!s)throw new D("UNSUPPORTED","以图识图 Integration 不可用",{source:"ImageSearchService"});let a=this.integrations.getAdapter(s.id),r=String(e||"");if(r.startsWith("data:"))r=await a.upload(r,t);else{let i;try{i=new URL(r)}catch(n){throw new D("INVALID_URL","图片 URL 无效",{source:"ImageSearchService",cause:n})}if(!["http:","https:"].includes(i.protocol))throw new D("INVALID_URL","图片 URL 必须使用 HTTP/HTTPS",{source:"ImageSearchService"});r=i.href}return Object.freeze({imageUrl:r,targets:a.createTargets(r)})}};d(Yn,"ImageSearchService");var cr=Yn;var Zn=class Zn{constructor(e){this.port=He(e,"NavigationPort",We.navigation)}open(e,t){return this.port.open(String(e),t)}assign(e){return this.port.assign(String(e))}replace(e){return this.port.replace(String(e))}};d(Zn,"NavigationService");var dr=Zn;var Xn=class Xn{constructor(e,t=null){this.providers=e,this.integrations=t}async search(e,t={}){let s=[];for(let a of await this.providers.getAvailable("magnet",t))try{let r=await a.search(e,t);this.providers.updateHealth(a.id,{ok:!0}),Array.isArray(r)&&s.push(...r)}catch(r){this.providers.updateHealth(a.id,{ok:!1,error:r instanceof Error?r.message:String(r)})}return s}async listNative(e,t={}){let s=typeof e.providerId=="string"?e.providerId:"javdb",a=(this.integrations?.list("movie.magnets")??[]).find(i=>i.id===s);if(!a)return[];let r=this.integrations?.getAdapter(a.id);return typeof r?.listMagnets=="function"?r.listMagnets(e,t):[]}getBuiltInSources(){return(this.integrations?.list("magnet.search")??[]).flatMap(e=>{let t=this.integrations?.getAdapter(e.id);return typeof t?.getSources=="function"?t.getSources():[]})}async searchSource(e,t,s={}){for(let a of this.integrations?.list("magnet.search")??[]){let r=this.integrations?.getAdapter(a.id);if(r?.getSources?.().some(i=>i.id===e))return r.search(e,t,s)}return[]}getSourceTargetUrl(e,t,s={}){for(let a of this.integrations?.list("magnet.search")??[]){let r=this.integrations?.getAdapter(a.id);if(r?.getSources?.().some(i=>i.id===e))return r.targetUrl(e,t,s)}return null}assess(e){return kc(e)}};d(Xn,"MagnetService");var hr=Xn;var eo=class eo{constructor(e=null){this.integrations=e}normalize(e){return ee(e)}firstValid(...e){for(let t of e){let s=this.normalize(t);if(s)return s}return null}async resolve(e,t={}){let s=this.normalize(e.carNum);if(!s)return null;let a=this.integrations?.list("movie.search")??[],r=typeof e.providerId=="string"?e.providerId:null,i=r?a.filter(n=>n.id===r):[...a].sort((n,l)=>+(l.id==="javdb")-+(n.id==="javdb"));for(let n of i){let l=this.integrations?.getAdapter(n.id);if(typeof l?.resolveMovie!="function")continue;let c=await l.resolveMovie({...e,carNum:s},t);if(c)return c}return Object.freeze({...e,carNum:s})}async detail(e,t={}){let s=this.integrations?.list("movie.detail")??[],a=typeof e.providerId=="string"?e.providerId:e.movieId?"javdb":null,r=a?s.filter(i=>i.id===a):s;for(let i of r){let n=this.integrations?.getAdapter(i.id);if(typeof n?.getDetail=="function")return n.getDetail(e,t)}return null}async rankings(e={}){return this.playbackRankings(e)}async playbackRankings(e={}){for(let t of this.integrations?.list("movie.ranking")??[]){let s=this.integrations?.getAdapter(t.id);if(typeof s?.listRankings=="function")return s.listRankings(e)}return[]}async catalog(e,t={},s={}){let a=(this.integrations?.list("movie.catalog")??[]).find(i=>i.id===e);if(!a)throw new TypeError(`Movie catalog provider is unavailable: ${e}`);let r=this.integrations?.getAdapter(a.id);if(typeof r?.listCatalog!="function")throw new TypeError(`Movie catalog operation is unavailable: ${e}`);return r.listCatalog(t,s)}async people(e,t,s={}){let a=(this.integrations?.list("movie.credits")??[]).find(i=>i.id===e);if(!a)return Object.freeze({actors:Object.freeze([]),seller:null});let r=this.integrations?.getAdapter(a.id);return typeof r?.getPeople=="function"?r.getPeople(t,s):Object.freeze({actors:Object.freeze([]),seller:null})}async images(e,t,s={}){let a=(this.integrations?.list("movie.images")??[]).find(i=>i.id===e);if(!a)return[];let r=this.integrations?.getAdapter(a.id);return typeof r?.getImages=="function"?r.getImages(t,s):[]}async preview(e,t,s={}){let a=(this.integrations?.list("movie.preview")??[]).find(i=>i.id===e);if(!a)throw new TypeError(`Movie preview provider is unavailable: ${e}`);let r=this.integrations?.getAdapter(a.id);if(typeof r?.getPreviewForMovie!="function")throw new TypeError(`Movie preview operation is unavailable: ${e}`);return r.getPreviewForMovie(t,s)}sourceUrls(e,t){return Object.freeze(t.map(s=>{try{let a=this.integrations?.getAdapter(s),r=typeof a?.detailUrl=="function"?a.detailUrl(e):null;return r?Object.freeze({providerId:s,url:r}):null}catch{return null}}).filter(Boolean))}searchUrl(e,t){try{let s=this.integrations?.getAdapter(e);return typeof s?.searchUrl=="function"?s.searchUrl(t):null}catch{return null}}providerOrigin(e){try{let t=this.integrations?.getAdapter(e);return typeof t?.origin=="function"?t.origin():null}catch{return null}}matchesProviderUrl(e,t){try{let s=this.integrations?.getAdapter(e);return typeof s?.matchesUrl=="function"&&s.matchesUrl(t)}catch{return!1}}externalSites(e={}){let t=(this.integrations?.list("movie.external-sites")??[])[0],s=t&&this.integrations?.getAdapter(t.id);return typeof s?.getSites=="function"?s.getSites(e):[]}externalSiteOrigin(e,t={}){return this.externalSites(t).find(s=>s.id===e)?.baseUrl||""}async searchExternalSite(e,t,s={}){let a=(this.integrations?.list("movie.external-sites")??[])[0],r=a&&this.integrations?.getAdapter(a.id);return typeof r?.searchSite!="function"?Object.freeze({searchUrl:"",matches:Object.freeze([])}):r.searchSite(e,t,s)}externalNavigationLinks(){let e=(this.integrations?.list("navigation.external")??[])[0],t=e&&this.integrations?.getAdapter(e.id);return typeof t?.getNavigationLinks=="function"?t.getNavigationLinks():[]}};d(eo,"MovieIdentityService");var ur=eo;var to=class to{constructor(e,t){this.providers=e,this.integrations=t}submitWithIntegration(e,t,s={}){let a=this.integrations.getAdapter(e);if(typeof a.submit!="function")throw new TypeError(`Integration ${e} does not support offline submission`);return a.submit(t,s)}checkAccount(e,t={}){let s=this.integrations.getAdapter(e);if(typeof s.checkAccount!="function")throw new TypeError(`Integration ${e} does not support account checks`);return s.checkAccount(t)}searchFiles(e,t,s={}){let a=this.integrations.getAdapter(e);if(typeof a.searchFiles!="function")throw new TypeError(`Integration ${e} does not support file search`);return a.searchFiles(t,s)}renameFile(e,t,s,a={}){let r=this.integrations.getAdapter(e);if(typeof r.renameFile!="function")throw new TypeError(`Integration ${e} does not support file rename`);return r.renameFile(t,s,a)}getPlayUrl(e,t){let s=this.integrations.getAdapter(e);return typeof s.getPlayUrl=="function"?s.getPlayUrl(t):null}getIntegrationHomeUrl(e){let t=this.integrations.getAdapter(e);if(typeof t.homeUrl!="string")throw new TypeError(`Integration ${e} does not declare a home URL`);return t.homeUrl}async submit(e,t={}){let s=await this.providers.getAvailable("offline",t),a=[];for(let r of s)try{let i=await r.submit(e,t);return this.providers.updateHealth(r.id,{ok:!0}),i}catch(i){a.push(i),this.providers.updateHealth(r.id,{ok:!1,error:i instanceof Error?i.message:String(i)})}throw new AggregateError(a,s.length?"所有离线 Provider 均失败":"没有可用的离线 Provider")}};d(to,"OfflineService");var pr=to;var so=class so extends EventTarget{constructor(e){super(),this.window=e.windowRuntime??window,this.scope=e.scope,this.settings=e.settings??null,this.coarseQuery=this.window.matchMedia("(any-pointer: coarse)"),this.profile=this.calculate(),this.started=!1}calculate(){let e=this.window.innerWidth,t=(this.settings?.snapshot()??{}).mobileMode;if(t==="on")return"compact";if(t==="off")return e>=1200?"wide":"regular";let s=Math.min(this.window.innerWidth,this.window.innerHeight);return e<=767||this.coarseQuery.matches&&s<=480?"compact":e>=1200?"wide":"regular"}start(){if(this.started)return;this.started=!0;let e=d(()=>{let t=this.calculate();if(t===this.profile)return;let s=this.profile;this.profile=t,this.dispatchEvent(new CustomEvent("profile.changed",{detail:Object.freeze({previous:s,profile:t})}))},"update");this.scope.listen(this.window,"resize",e,{passive:!0}),this.scope.listen(this.window,"orientationchange",e,{passive:!0}),this.scope.listen(this.coarseQuery,"change",e),this.settings&&this.scope.listen(this.settings,"settings.changed",e),e()}current(){return this.profile}};d(so,"ProfileService");var gr=so;var ao=class ao{constructor(e){this.integrations=e}async list(e,t={}){for(let s of this.integrations.list("movie.related")){let a=this.integrations.getAdapter(s.id);if(typeof a.listRelated=="function")return a.listRelated(e,t)}return[]}};d(ao,"RelatedService");var mr=ao;var ro=class ro{constructor(e){this.integrations=e}async list(e,t={}){for(let s of this.integrations.list("movie.reviews")){let a=this.integrations.getAdapter(s.id);if(typeof a.listReviews=="function")return a.listReviews(e,t)}return[]}};d(ro,"ReviewService");var fr=ro;var Vt="javstore",Uc=new Set([Vt]),io=class io{constructor(e,t=null){this.providers=e,this.integrations=t}isEnabled(e){return e?.enableLoadScreenShot!=="no"}parseScreenshotProviders(e){if(Array.isArray(e))return e;if(typeof e=="string")try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}return[]}getScreenshotSettings(e){return{mode:e?.screenshotMode==="manual"?"manual":"auto",providers:this.parseScreenshotProviders(e?.screenshotProviders)}}getEnabledProviders(e){let t=this.parseScreenshotProviders(e?.screenshotProviders);return Ms.map(s=>({...s,...t.find(a=>a?.id===s.id)||{}})).filter(s=>s.enabled!==!1).sort((s,a)=>Number(s.priority??100)-Number(a.priority??100))}async resolve(e,t={}){if(t.settings&&!t.allowWhenDisabled&&!this.isEnabled(t.settings))return null;let s=t.settings?this.getEnabledProviders(t.settings):null,a=s?new Set(s.map(r=>r.id)):null;if(s&&!s.length)return null;if(t.providerId){if(a&&!a.has(t.providerId))return null;let r=this.providers.get?.(t.providerId);return r?r.enabled===!1||!r.capabilities?.includes("screenshot")?null:this.resolveFromProvider(r,e,t):this.resolveIntegration(t.providerId,e,t)}for(let r of await this.providers.getAvailable("screenshot",t)){if(a&&!a.has(r.id))continue;let i=await this.resolveFromProvider(r,e,t);if(i)return i}return a&&!a.has(Vt)?null:this.resolveIntegration(Vt,e,t)}async resolveFromProvider(e,t,s){try{let a=await e.resolve(t,s);if(this.providers.updateHealth(e.id,{ok:!0}),a)return a}catch(a){this.providers.updateHealth(e.id,{ok:!1,error:a instanceof Error?a.message:String(a)})}return null}async resolveIntegration(e,t,s){if(!Uc.has(e)||s.settings&&!s.allowWhenDisabled&&!this.isEnabled(s.settings))return null;let a=this.integrations?.list("movie.images")?.find(n=>n.id===e);if(!a)return null;let r=this.integrations?.getAdapter(a.id);if(typeof r?.getImages!="function")return null;let i=await r.getImages(t,s);return Array.isArray(i)&&i.length?i:null}getSearchUrl(e,t=null){if(!Uc.has(Vt)||t&&!this.isEnabled(t)||t&&!this.getEnabledProviders(t).some(s=>s.id===Vt))return null;for(let s of this.integrations?.list("movie.images")??[]){if(s.id!==Vt)continue;let a=this.integrations?.getAdapter(s.id);if(typeof a?.getSearchUrl=="function")return a.getSearchUrl(e)}return null}};d(io,"ScreenshotService");var vr=io;var no="translation_cache_v2",oo="translation:v1:",lo=class lo{constructor(e,t=null){this.integrations=e,this.storage=t,this.memoryCache=new Map,this.inflight=new Map,this.legacyCache=null,this.hydrationPromise=null,this.cacheGeneration=0,this.persistTimer=null}cacheKey(e,t,s){return`${oo}${t}:${s}:${e}`}readLegacyCache(){if(this.legacyCache!==null)return this.legacyCache;try{let e=JSON.parse(this.storage?.getLocal?.("jhs_translate")||"{}");this.legacyCache=e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch{this.legacyCache={}}return this.legacyCache}hydrate(){if(this.hydrationPromise)return this.hydrationPromise;let e=this.cacheGeneration;return this.hydrationPromise=(async()=>{if(!this.storage)return;let t=this.storage,s=[],a=!1;try{let r=await t.get(no);for(let[n,l]of Object.entries(r?.entries||{}))e===this.cacheGeneration&&typeof l?.value=="string"&&Number(l.expiresAt)>Date.now()?this.memoryCache.set(n,{value:l.value,expiresAt:Number(l.expiresAt),lastUsed:Number(l.lastUsed)||Date.now()}):a=!0;let i=await t.keys();for(let n of i.filter((l=>l.startsWith(oo)))){let l=await t.get(n);e===this.cacheGeneration&&typeof l?.value=="string"&&Number(l.expiresAt)>Date.now()&&this.memoryCache.set(n,{value:l.value,expiresAt:Number(l.expiresAt),lastUsed:Number(l.lastUsed)||Date.now()}),s.push(n),a=!0}e===this.cacheGeneration&&(this.prune()||a)&&this.persistNow(e).then((()=>Promise.all(s.map((n=>t.remove(n)))))).catch((()=>{}))}catch{}})()}prune(){let e=Date.now(),t=!1;for(let[a,r]of this.memoryCache)r.expiresAt<=e&&(this.memoryCache.delete(a),t=!0);let s=this.memoryCache.size-1e3;if(s>0)for(let[a]of[...this.memoryCache].sort(((r,i)=>r[1].lastUsed-i[1].lastUsed)).slice(0,s))this.memoryCache.delete(a),t=!0;return t}schedulePersist(){if(!this.storage||this.persistTimer!==null)return;let e=this.cacheGeneration;this.persistTimer=setTimeout((()=>{this.persistTimer=null,this.persistNow(e).catch((()=>{}))}),300)}async persistNow(e=this.cacheGeneration){!this.storage||e!==this.cacheGeneration||(this.prune(),await this.storage.set(no,{version:2,entries:Object.fromEntries(this.memoryCache)}))}remember(e,t,s=this.cacheGeneration){if(s===this.cacheGeneration){let a=Date.now();this.memoryCache.set(e,{value:t,expiresAt:a+2592e6,lastUsed:a}),this.prune(),this.schedulePersist()}return t}async clearCache(){if(this.cacheGeneration+=1,this.persistTimer!==null&&clearTimeout(this.persistTimer),this.persistTimer=null,this.memoryCache.clear(),this.legacyCache={},this.storage?.removeLocal?.("jhs_translate"),this.storage){let e=this.storage;try{let t=await e.keys();await e.remove(no),await Promise.all(t.filter((s=>s.startsWith(oo))).map((s=>e.remove(s))))}catch{}}this.hydrationPromise=Promise.resolve()}async inspectCache(){return await this.hydrate(),this.prune(),{version:2,size:this.memoryCache.size,entries:Object.fromEntries(this.memoryCache)}}async translate(e,t={}){let s=t.sourceLanguage??"ja",a=t.targetLanguage??"zh-CN",r=this.cacheKey(e,s,a),i=this.cacheGeneration,n=this.memoryCache.get(r);if(n?.expiresAt>Date.now())return n.lastUsed=Date.now(),this.schedulePersist(),n.value;n&&this.memoryCache.delete(r);let l=t.cacheAlias&&this.readLegacyCache()[t.cacheAlias];if(s==="ja"&&a==="zh-CN"&&typeof l=="string"&&l)return this.remember(r,l,i);if(await this.hydrate(),n=this.memoryCache.get(r),n?.expiresAt>Date.now())return n.lastUsed=Date.now(),this.schedulePersist(),n.value;let c=this.inflight.get(r);if(c)return c;let h=(async()=>{let u=this.integrations.list("text.translate")[0],p=u&&this.integrations.getAdapter(u.id);if(typeof p?.translate!="function")throw new TypeError(u?`Translation operation is unavailable: ${u.id}`:"Translation provider is unavailable");let g=await p.translate(e,{...t,sourceLanguage:s,targetLanguage:a});return typeof g=="string"?this.remember(r,g,i):g})().finally((()=>this.inflight.delete(r)));return this.inflight.set(r,h),h}};d(lo,"TranslationService");var br=lo;var co=class co{constructor(e){this.integrations=e}async search(e,t,s={}){let a=this.integrations.list("subtitle.search").find(i=>i.id===e);if(!a)return[];let r=this.integrations.getAdapter(a.id);return typeof r?.search=="function"?r.search(t,s):[]}async download(e,t,s={}){let a=this.integrations.list("subtitle.download").find(i=>i.id===e);if(!a)throw new TypeError(`Subtitle provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.download!="function")throw new TypeError(`Subtitle download is unavailable: ${e}`);return r.download(t,s)}};d(co,"SubtitleService");var wr=co;var ho=class ho{constructor(e){this.integrations=e}async login(e,t,s={}){let a=this.integrations.list("account.login").find(i=>i.id===e);if(!a)throw new TypeError(`Account provider is unavailable: ${e}`);let r=this.integrations.getAdapter(a.id);if(typeof r?.login!="function")throw new TypeError(`Account login is unavailable: ${e}`);return r.login(t,s)}};d(ho,"AccountService");var yr=ho;var uo=class uo extends EventTarget{constructor(e,t={}){super(),this.storage=e,this.validators=t.validators??{},this.normalizers=t.normalizers??{},this.afterPersist=t.afterPersist??null,this.snapshotValue=Object.freeze({}),this.writeChain=Promise.resolve()}async load(e="setting"){return this._enqueue(()=>this._withSettingLock(()=>this._readSnapshot(e)))}async refresh(e="setting"){return this._enqueue(()=>this._withSettingLock(async()=>{let t=this.snapshotValue,s=await this._readSnapshot(e),r=[...new Set([...Object.keys(t),...Object.keys(s)])].filter(i=>t[i]!==s[i]);return r.length&&this.dispatchEvent(new CustomEvent("settings.changed",{detail:Object.freeze({name:r.length===1?r[0]:null,value:void 0,names:Object.freeze([...r]),snapshot:s})})),s}))}snapshot(){return this.snapshotValue}waitForIdle(){return this.writeChain}async set(e,t,s="setting"){return this.update(a=>{a[e]=t},s)}async patch(e,t="setting"){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("Settings patch must be an object");return this.update(s=>{Object.assign(s,e)},t)}async replace(e,t="setting"){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("Settings replacement must be an object");return this.update(s=>{for(let a of Object.keys(s))delete s[a];Object.assign(s,e)},t)}async unset(e,t="setting"){let s=Array.isArray(e)?e:[e];if(!s.every(a=>typeof a=="string"&&a))throw new TypeError("unset names must be non-empty strings");return this.update(a=>{for(let r of s)delete a[r]},t)}async update(e,t="setting"){if(typeof e!="function")throw new TypeError("Settings update mutator must be a function");return this._enqueue(()=>this._withSettingLock(async()=>{let s=await this.storage.get(t),a=s&&typeof s=="object"&&!Array.isArray(s)?s:{},r={...a},i=e(r);if(i&&typeof i=="object"&&typeof i.then=="function")throw new TypeError("Settings update mutator must be synchronous");for(let[h,u]of Object.entries(this.normalizers))Object.prototype.hasOwnProperty.call(r,h)&&typeof u=="function"&&(r[h]=u(r[h]));let n=Object.freeze(r),l=[...new Set([...Object.keys(a),...Object.keys(n)])].filter(h=>a[h]!==n[h]);for(let h of l){let u=this.validators[h];if(u&&Object.prototype.hasOwnProperty.call(n,h)&&!u(n[h]))throw new TypeError(`Invalid setting: ${h}`)}let c=Object.freeze([...l]);if(!c.length)return this.snapshotValue=n,n;if(await this.storage.set(t,n),this.snapshotValue=n,c.length){let h=c.length===1?c[0]:null;this.dispatchEvent(new CustomEvent("settings.changed",{detail:Object.freeze({name:h,value:h?n[h]:void 0,names:c,snapshot:n})}))}try{await this.afterPersist?.(n,c)}catch(h){typeof globalThis.clog?.error=="function"&&globalThis.clog.error("[settings] afterPersist failed (ignored)",h)}return n}))}async _readSnapshot(e){let t=await this.storage.get(e);return this.snapshotValue=Object.freeze(t&&typeof t=="object"&&!Array.isArray(t)?{...t}:{}),this.snapshotValue}_enqueue(e){let t=this.writeChain.then(e);return this.writeChain=t.then(()=>{},()=>{}),t}async _withSettingLock(e){let t=globalThis.navigator?.locks;return t?.request?t.request("jhs_setting_lock",()=>e()):e()}};d(uo,"SettingsService");var jr=uo;var po=class po{constructor(e){this.port=He(e,"StoragePort",We.storage)}get(e){return this.port.get(e)}set(e,t){return this.port.set(e,t)}remove(e){return this.port.remove(e)}keys(){return this.port.keys()}getLocal(e){return this.port.getLocal(e)}setLocal(e,t){return this.port.setLocal(e,t)}removeLocal(e){return this.port.removeLocal(e)}getValue(e,t){return this.port.getValue(e,t)}setValue(e,t){return this.port.setValue(e,t)}removeValue(e){return this.port.removeValue(e)}};d(po,"StorageService");var Sr=po;var mo=class mo{constructor(e,t,s,a){this.http=e,this.baseUrl=new URL(t.endsWith("/")?t:`${t}/`),this.username=s,this.password=a,this.folderName=null}authHeaders(){let e=new TextEncoder().encode(`${this.username}:${this.password}`),t="";for(let s of e)t+=String.fromCharCode(s);return{Authorization:`Basic ${btoa(t)}`,Depth:"1"}}async request(e,t,s={},a,r={}){let i=new URL(t.replace(/^\/+/,""),this.baseUrl),n=await this.http.request({providerId:"webdav",method:e,url:i.href,headers:{...this.authHeaders(),...s},body:a,responseType:"text",cacheScope:"none",...r,timeout:1e4,urlPolicy:{trustClass:"user-local",expectedOrigin:this.baseUrl.origin}});return n.data??n.responseText??""}async ensureFolder(e){await this.request("MKCOL",e,{},void 0,{acceptableStatuses:[405,409]})}async backup(e,t,s,a){let r=d(async(i,n,l)=>{let c=performance.now(),h="success",u,p;try{return await n()}catch(g){if(h="error",g&&typeof g=="object"){let m=g;u=typeof m.code=="string"?m.code:void 0,p=Number.isFinite(m.details?.status)?m.details.status:void 0}throw g}finally{try{a?.({stage:i,result:h,durationMs:Math.round(performance.now()-c),...l==null?{}:{bytes:l},...u?{code:u}:{},...p==null?{}:{status:p},timeoutMs:1e4})}catch{}}},"runStage");await r("建目录",()=>this.ensureFolder(e)),await r("上传",()=>this.request("PUT",`${e}/${t}`,{"Content-Type":"text/plain"},s),s.length)}async getFileList(e){let t=String(await this.request("PROPFIND",e,{"Content-Type":"application/xml"},'')),s=new DOMParser().parseFromString(t,"text/xml").getElementsByTagNameNS("DAV:","response"),a=[];for(let r=1;ri.getElementsByTagNameNS("DAV:",u)[0]?.textContent||"","node"),l=n("href"),c=n("displayname")||decodeURIComponent(l.replace(/\/$/,"").split("/").pop()||""),h=n("getcontentlength");h!=="0"&&a.push({fileId:c,name:c,size:Number(h),createTime:n("creationdate")||n("getlastmodified")})}return a.reverse()}async deleteFile(e){await this.request("DELETE",`${this.folderName}/${encodeURI(e)}`,{"Cache-Control":"no-cache"})}async getBackupList(e){return this.folderName=e,await this.ensureFolder(e),this.getFileList(e)}async getFileContent(e){return String(await this.request("GET",`${this.folderName}/${e}`,{Accept:"application/octet-stream"}))}};d(mo,"WebDavClient");var go=mo,fo=class fo{constructor(e,t=void 0,s=void 0){this.http=e,this.credential=t,this.settings=s}createClient(e){return new go(this.http,e.url,e.username,e.password)}async getProfile(){let e=this.settings?.snapshot?.()||{},t=this.credential?await this.credential.get("jhs_webdav_password"):"";return{url:String(e.webDavUrl||""),username:String(e.webDavUsername||""),password:t}}async saveProfile(e={}){if(!this.settings||!this.credential)throw new Error("WebDAV 配置服务未初始化");let t=await this.getProfile(),s=Object.prototype.hasOwnProperty.call(e,"password");s&&await this.credential.set("jhs_webdav_password",String(e.password||""));try{await this.settings.update(a=>{for(let r of["url","username"])Object.prototype.hasOwnProperty.call(e,r)&&(a[r==="url"?"webDavUrl":"webDavUsername"]=String(e[r]||""))})}catch(a){throw s&&await this.credential.set("jhs_webdav_password",t.password),a}return this.getProfile()}};d(fo,"WebDavService");var xr=fo;var Ie=Object.freeze({installationSecret:"jhs_credential_install_secret",webDavPassword:"jhs_webdav_password",javdbToken:"jhs_appAuthorization"}),vo=class vo{constructor(e,t=globalThis.localStorage){this.storage=e,this.legacyStorage=t,this.cleanupValues=new Map,this.cleanupTargets=new Map}async installationSecret(){return String(await this.storage.getValue(Ie.installationSecret,"")||this.legacyStorage?.getItem?.(Ie.installationSecret)||"x7k9p3")}generateSecret(){return btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32))))}async decodeLegacy(e,t){let s=e.replace(/^AES:/,""),a=e.startsWith("AES:");try{a||(a=/^[A-Za-z0-9+/]+={0,2}$/.test(s)&&atob(s).length>=28)}catch{}return a?Xe(s,t||await this.installationSecret()):e}async decode(e){if(e&&typeof e=="object"){if(e.schema===2&&typeof e.id=="string"&&e.deleted===!0&&!Object.hasOwn(e,"secret")&&!Object.hasOwn(e,"ciphertext"))return"";if(e.schema!==2||typeof e.id!="string"||typeof e.secret!="string"||typeof e.ciphertext!="string")throw new Error("凭证格式无效");return Xe(e.ciphertext,e.secret,!1)}let t=String(e||"");return t?this.decodeLegacy(t):""}async get(e){try{return await this.decode(await this.storage.getValue(e,""))}catch{return""}}async set(e,t){let s=String(t||"");if(!s)return await this.remove(e),"";let a=this.generateSecret(),r={schema:2,id:crypto.randomUUID(),secret:a,ciphertext:await Xt(s,a)};await this.storage.setValue(e,r);let i=await this.storage.getValue(e,"");if(JSON.stringify(i)!==JSON.stringify(r)||await this.decode(i)!==s)throw new Error("凭证存储回读校验失败");return s}async remove(e){let t={schema:2,id:crypto.randomUUID(),deleted:!0};await this.storage.setValue(e,t);let s=await this.storage.getValue(e,"");if(JSON.stringify(s)!==JSON.stringify(t)||await this.decode(s)!=="")throw new Error("凭证删除回读校验失败")}async migrateLegacy(e,t={}){let s=this.legacyStorage?.getItem?.(Ie.installationSecret)||"",a=d(p=>this.decodeLegacy(p,s),"decodeLegacy"),r=[],i={},n=[],l=e?.snapshot?.()||{},c=this.legacyStorage?.getItem?.(Ie.javdbToken)||"",h=String(l.webDavPassword||"");for(let[p,g]of[[Ie.javdbToken,c],[Ie.webDavPassword,h]]){let m;try{m=await this.storage.getValue(p,"")}catch{r.push({key:p,code:"CREDENTIAL_MIGRATION_READ_FAILED"});continue}if(!m&&!g||m&&typeof m=="object"&&(p===Ie.javdbToken||!g||m.deleted===!0))continue;let f,v;try{f=m?await this.decode(m):await a(g),m&&typeof m=="string"&&p===Ie.javdbToken&&(f=await a(f)),v=g?await a(g):""}catch{r.push({key:p,code:"LEGACY_CREDENTIAL_UNREADABLE"});continue}try{(!m||typeof m=="string")&&await this.set(p,f)}catch{r.push({key:p,code:"CREDENTIAL_MIGRATION_WRITE_FAILED"});continue}g&&f===v&&await this.get(p)===f&&(this.cleanupTargets.set(p,f),p===Ie.webDavPassword&&(i.webDavPassword=g))}let u=await this.validateLegacyCleanup({settingKeys:Object.keys(i),settingValues:i,pageKeys:n});return t.deferCleanup||(u.settingKeys.length&&e?.update&&await e.update(p=>{for(let g of u.settingKeys)p[g]===i[g]&&delete p[g]}),await this.cleanupLegacyPageStorage(u.pageKeys,e)),{migrated:!!(c||h||s),cleanup:u,issues:r}}async validateLegacyCleanup(e){let t=[];if(!globalThis.navigator?.locks?.request)return{...e,settingKeys:t};for(let s of e.settingKeys||[])s==="webDavPassword"&&this.cleanupTargets.has(Ie.webDavPassword)&&await this.get(Ie.webDavPassword)===this.cleanupTargets.get(Ie.webDavPassword)&&t.push(s);return{...e,settingKeys:t}}async cleanupLegacyPageStorage(e=[],t=null){this.cleanupValues.clear(),this.cleanupTargets.clear()}};d(vo,"CredentialService");var kr=vo;var bo=class bo{constructor(e){this.port=He(e,"StylePort",We.style)}register(e,t){return this.port.register(e,t)}remove(e){return this.port.remove(e)}};d(bo,"StyleRegistry");var Cr=bo;var wo=class wo{constructor(){this.owners=new Map,this.handlers=new Map,this.activateOwner=null,this.ownerEnabled=new Map}setOwnerEnabled(e,t){if(!this.owners.has(e))throw new Error(`Unknown command owner: ${e}`);this.ownerEnabled.set(e,t)}isAvailable(e){return this.owners.has(e)&&this.ownerEnabled.get(e)!==!1}setActivator(e){this.activateOwner=e}registerOwner(e,t){let s=this.owners.get(e);if(s&&s!==t)throw new Error(`Duplicate command owner: ${e}`);this.owners.set(e,t)}registerHandler(e,t,s){if(this.owners.get(e)!==s)throw new Error(`Feature ${s} does not own command ${e}`);if(this.handlers.has(e))throw new Error(`Duplicate command handler: ${e}`);this.handlers.set(e,t)}async execute(e,...t){let s=this.owners.get(e);if(!s)throw new Error(`Unknown command: ${e}`);if(!this.handlers.has(e)){if(!this.activateOwner)throw new Error("Command activator is not configured");await this.activateOwner(s)}let a=this.handlers.get(e);if(!a)throw new Error(`Feature ${s} did not register ${e}`);return a(...t)}};d(wo,"CommandRegistry");var _r=wo;var yo=class yo{constructor(e=null){this.values=new Map,this.diagnostics=e}register(e,t){if(typeof e!="symbol")throw new TypeError("Dependency token must be a symbol");if(this.values.has(e)){let s=new D("DUPLICATE_TOKEN",`Duplicate dependency token: ${String(e)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(s),s}return this.values.set(e,t),this}resolveDeclared(e){let t=Object.create(null),s=new Set;for(let a of e){if(s.has(a)){let r=new D("DUPLICATE_TOKEN",`Duplicate declared dependency: ${String(a)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(r),r}if(s.add(a),!this.values.has(a)){let r=new D("MISSING_DEPENDENCY",`Missing declared dependency: ${String(a)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(r),r}Object.defineProperty(t,a,{value:this.values.get(a),enumerable:!0})}return Object.freeze(t),new Proxy(t,{get:d((a,r,i)=>{if((typeof r=="symbol"?Symbol.keyFor(r):null)?.startsWith("jhs.")&&!s.has(r)){let l=new D("UNDECLARED_DEPENDENCY",`Undeclared dependency access: ${String(r)}`,{source:"DependencyContainer"});throw this.diagnostics?.recordError?.(l),l}return Reflect.get(a,r,i)},"get")})}};d(yo,"DependencyContainer");var $r=yo;var jo=class jo{constructor(e){this.container=e.container,this.commands=e.commands,this.diagnostics=e.diagnostics,this.disabled=new Set($t(e.disabled)),this.site=e.site??"unknown",this.route=e.route??"unknown",this.manifests=new Map,this.contributionOwners=new Map,this.contributionManifests=new Map,this.activations=new Map,this.contributionScopes=new Map,this.commands.setActivator(t=>this.activate(t).then(()=>{}))}setContributionManifests(e){this.contributionManifests=new Map(e.map(t=>[t.id,t]))}activeSurfaces(){return this.route==="list"?new Set(["global","list","list-page","list-card"]):this.route==="detail"||this.route==="owned-detail"?new Set(["global","detail","detail-page",this.route]):new Set(["global",this.route])}register(e){let t=Ee(e);if(this.manifests.has(t.id))throw new Error(`Duplicate feature: ${t.id}`);for(let s of t.contributes){let a=this.contributionOwners.get(s);if(a)throw new Error(`Duplicate contribution ownership: ${s} (${a}, ${t.id})`)}this.manifests.set(t.id,t);for(let s of t.contributes)this.contributionOwners.set(s,t.id);for(let s of t.providesCommands)this.commands.registerOwner(s,t.id),this.commands.setOwnerEnabled(s,this.isEligible(t))}isEligible(e){return!(e.kind!=="system"&&this.disabled.has(e.id)||e.sites.length&&!e.sites.includes(this.site)||e.routes.length&&!e.routes.includes(this.route))}isContributionEnabled(e,t,s){let a=this.manifests.get(e);if(!a||a.sites.length&&!a.sites.includes(this.site)||!a.contributes.includes(t)||a.kind!=="system"&&this.disabled.has(a.id))return!1;if(a.kind==="system")return!0;let r=this.contributionManifests.get(t);return r?.routes?.length&&!r.routes.includes(this.route)||r?.surfaces?.length&&!r.surfaces.some(i=>this.activeSurfaces().has(i))?!1:!this.disabled.has(t)&&!this.disabled.has(s)}isFeatureDisableable(e){let t=this.manifests.get(e);if(!t)throw new Error(`Unknown feature: ${e}`);return t.kind!=="system"&&t.disableable!==!1}resolveDeclaredDependencies(e){return this.container.resolveDeclared(e)}async getScope(e){return(await this.activate(e)).scope}getContributionScope(e,t,s){if(!this.isContributionEnabled(e,t,s))return Promise.reject(new Error(`Contribution is disabled or ineligible: ${t}`));let a=this.contributionScopes.get(t);return(!a||a.disposed)&&(a=new te(`contribution:${t}`,{onChange:d(r=>this.diagnostics.updateScope(r),"onChange")}),this.contributionScopes.set(t,a)),Promise.resolve(a)}activate(e){let t=this.activations.get(e);if(t)return t;let s=this.manifests.get(e);if(!s)return Promise.reject(new Error(`Unknown feature: ${e}`));if(!this.isEligible(s))return Promise.reject(new Error(`Feature is disabled or ineligible: ${e}`));let a=this.activateManifest(s);return this.activations.set(e,a),a.catch(()=>this.activations.delete(e)),a}async activateManifest(e){let t=performance.now(),s=new te(`feature:${e.id}`,{onChange:d(a=>this.diagnostics.updateScope(a),"onChange")});try{let a=this.container.resolveDeclared(e.requires),r=Object.freeze(e.contributes.filter(n=>!this.disabled.has(n))),i=await e.activate(a,Object.freeze({scope:s,enabledContributions:r,route:this.route}));for(let n of e.providesCommands){let l=i?.commands?.[n];if(typeof l!="function")throw new Error(`Feature ${e.id} did not provide command ${n}`);this.commands.registerHandler(n,l,e.id)}return this.diagnostics.setFeature(e.id,!0),r.forEach(n=>this.diagnostics.setContribution(n,!0)),this.diagnostics.recordStartup(e.id,performance.now()-t),Object.freeze({manifest:e,scope:s,enabledContributions:r,dispose:d(()=>{i?.dispose?.();for(let n of e.contributes){let l=this.contributionScopes.get(n);l&&(l.dispose(),this.contributionScopes.delete(n))}s.dispose(),this.diagnostics.setFeature(e.id,!1),r.forEach(n=>this.diagnostics.setContribution(n,!1)),this.activations.delete(e.id)},"dispose")})}catch(a){throw s.dispose(),this.diagnostics.recordError(a),a}}async start(){for(let e of this.manifests.values())this.isEligible(e)&&(e.startup==="eager"?await this.activate(e.id):e.startup==="idle"&&(globalThis.requestIdleCallback??(s=>setTimeout(s,0)))(()=>{this.activate(e.id).catch(()=>{})}))}getActiveFeatureIds(){return[...this.activations.keys()]}};d(jo,"FeatureRuntime");var Tr=jo;var So=class So{constructor(e=null){this.providers=new Map,this.health=new Map,this.diagnostics=e}register(e){if(!e||typeof e.id!="string"||!Array.isArray(e.capabilities))throw new TypeError("Provider requires id and capabilities");if(this.providers.has(e.id))throw new Error(`Duplicate provider: ${e.id}`);return this.providers.set(e.id,Object.freeze({priority:0,enabled:!0,...e})),e}get(e){return this.providers.get(e)??null}list(e){return[...this.providers.values()].filter(t=>t.enabled!==!1&&t.capabilities.includes(e)).sort((t,s)=>Number(s.priority??0)-Number(t.priority??0))}async getAvailable(e,t){let s=[];for(let a of this.list(e))(typeof a.isAvailable!="function"||await a.isAvailable(t))&&s.push(a);return s}updateHealth(e,t){if(!this.providers.has(e))throw new Error(`Unknown provider: ${e}`);this.health.set(e,Object.freeze({...t,updatedAt:Date.now()})),this.diagnostics?.updateProvider(e,t)}getHealth(e){return this.health.get(e)??null}};d(So,"ProviderRegistry");var Ar=So;var zc=Object.freeze({none:{cacheScope:"none",ttlMs:0},"public-1d":{cacheScope:"public",ttlMs:864e5},"public-5m":{cacheScope:"public",ttlMs:3e5},"public-7d":{cacheScope:"public",ttlMs:6048e5},"external-detail-v1":{cacheScope:"public",ttlMs:6048e5,cacheNamespace:"external-detail-v1"},"screenshot-7d":{cacheScope:"public",ttlMs:6048e5,cacheNamespace:"screenshot"},"session-configured":{cacheScope:"session",ttlMs:36e5},"source-configured":{cacheScope:"public",ttlMs:216e5,cacheNamespace:"source",getOnly:!0}});function iu(o,e,t={}){let s=o.cachePolicy==="none"?"none":o.cachePolicy?.[e],a={...zc[s]||zc.none};return a.getOnly&&String(t.method||"GET").toUpperCase()!=="GET"?Object.freeze({cacheScope:"none",ttlMs:0}):(delete a.getOnly,s==="session-configured"&&(a.sessionScopeId=String(t.sessionScopeId||`${o.id}-session`)),Object.freeze(a))}d(iu,"resolveIntegrationCachePolicy");function nu(o,e){let t=d((a,r={})=>iu(e,a,r),"policyFor"),s=d(a=>{if(a.capability&&e.capabilities.includes(a.capability))return a.capability;if(e.capabilities.length===1)return e.capabilities[0];let r=String(a.providerId||"");return e.capabilities.find(i=>r.includes(String(i).split(".").pop()||""))||e.capabilities[0]},"inferCapability");return Object.freeze({request(a,r,i){let n=typeof a=="string",l=n?a:s(a),c=n?r||{}:a||{},h=n?i:r;if(!e.capabilities.includes(l))throw new TypeError(`Integration ${e.id} does not declare capability ${l}`);let u=t(l,c),p={...c,...u};return delete p.capability,o.request(p,h)}})}d(nu,"createIntegrationRequestFacade");var xo=class xo{constructor(e,t){this.container=e,this.diagnostics=t,this.manifests=new Map,this.adapters=new Map}register(e){try{let t=W(e);if(this.manifests.has(t.id))throw new Error(`Duplicate integration: ${t.id}`);this.manifests.set(t.id,t)}catch(t){throw this.diagnostics.recordError(t),t}}list(e){return[...this.manifests.values()].filter(t=>t.capabilities.includes(e))}getAdapter(e){let t=this.adapters.get(e);if(t)return t;let s=this.manifests.get(e);if(!s)throw new Error(`Unknown integration: ${e}`);try{let a=this.container.resolveDeclared(s.requires),r=Object.create(null);for(let l of s.requires)Object.defineProperty(r,l,{value:l===y.http?nu(a[l],s):a[l],enumerable:!0});Object.freeze(r);let i=s.createClient(r),n=s.createAdapter(i,r);return this.adapters.set(e,n),n}catch(a){throw this.diagnostics.recordError(a),a}}};d(xo,"IntegrationRegistry");var Pr=xo;var ou=new Set(["live","nextNavigation","manual"]),lu=new Set(["boolean","select","number","text","password","json"]),cu=new Set(["full","quick"]);function du(o){if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError("Setting descriptor must be an object");let e=String(o.key??o.id??"");if(!e)throw new TypeError("Setting descriptor requires key (or id)");if(!o.owner)throw new TypeError(`Setting descriptor requires owner: ${e}`);let t=String(o.type??(o.defaultValue!=null&&typeof o.defaultValue=="boolean"?"boolean":"text"));if(!lu.has(t))throw new TypeError(`Setting descriptor has invalid type: ${e} (${t})`);let s=o.effect??"live";if(!ou.has(s))throw new TypeError(`Setting descriptor has invalid effect: ${e} (${s})`);let a=Array.isArray(o.surfaces)?[...new Set(o.surfaces)].filter(r=>cu.has(r)):[];if(o.surfaces!=null&&!Array.isArray(o.surfaces))throw new TypeError(`Setting descriptor surfaces must be an array: ${e}`);return Object.freeze({...o,key:e,owner:String(o.owner),label:String(o.label??o.key??e),description:o.description==null?"":String(o.description),type:t,effect:s,surfaces:Object.freeze(a),validate:typeof o.validate=="function"?o.validate:null,normalize:typeof o.normalize=="function"?o.normalize:null,contribution:o.contribution==null?void 0:String(o.contribution)})}d(du,"normalizeSettingDescriptor");var ko=class ko{constructor(){this.descriptors=new Map}register(e){let t=du(e);if(this.descriptors.has(t.key))throw new Error(`Duplicate setting descriptor: ${t.key}`);return this.descriptors.set(t.key,t),this}list(e={}){let t=e.surfaces;return[...this.descriptors.values()].filter(s=>!(s.contribution&&e.disabledContributions?.has(s.contribution)||t&&t.length&&!s.surfaces.includes(t[0])&&!t.some(a=>s.surfaces.includes(a))))}get(e){return this.descriptors.get(e)??null}isValid(e,t){let s=this.descriptors.get(e);return s&&typeof s.validate=="function"?s.validate(t)===!0:!0}normalizers(){return Object.fromEntries([...this.descriptors.values()].filter(e=>typeof e.normalize=="function").map(e=>[e.key,e.normalize]))}};d(ko,"SettingsRegistry");var Rr=ko;function Fc(o){let e={type:"boolean",effect:"live"},t="yes",s="no",a=d((i,n,l,c={})=>o.register({key:i,owner:n,label:l,...e,defaultValue:c.defaultValue??t,...c}),"toggle"),r=d((i,n,l,c)=>{let h=Number(i);return Number.isFinite(h)?Math.min(c,Math.max(l,Math.round(h))):n},"normalizeInteger");a("enableScreenSvg","ScreenshotFeature","列表长缩略图",{description:"在列表卡片上显示长缩略图按钮;手动点击仍遵守截图来源白名单。",surfaces:["full"],defaultValue:t}),a("enableLoadScreenShot","ScreenshotFeature","长缩略图",{description:"在详情页与 FC2 页面自动加载长缩略图及对应截图来源请求。",surfaces:["full","quick"]}),a("enablePreviewVideo","PreviewVideoFeature","预览视频",{description:"预览视频总开关。关闭后 JavDB/JavBus 详情与列表卡片的预览入口、播放器与 DMM 请求全部消失。",surfaces:["full","quick"]}),a("enableLoadPreviewVideo","PreviewVideoFeature","DMM 高画质增强",{description:"解析更高画质的 DMM 预览视频;关闭后仍可使用宿主原生预览,但不发起 DMM 请求。",surfaces:["full","quick"],indent:!0}),a("enableVideoSvg","CoverButtonFeature","卡片播放视频",{description:"在列表卡片上显示播放视频按钮。",surfaces:["full"]}),a("enableHandleSvg","CoverButtonFeature","卡片鉴定处理",{description:"在列表卡片上显示鉴定处理菜单。",surfaces:["full"]}),a("enableSiteSvg","CoverButtonFeature","卡片第三方网站",{description:"在列表卡片上显示第三方网站菜单。",surfaces:["full"]}),a("enableCopySvg","CoverButtonFeature","卡片复制",{description:"在列表卡片上显示复制菜单。",surfaces:["full"]}),a("autoPage","AutoPageFeature","瀑布流",{description:"连续加载列表;启用后普通列表只支持默认排序。",surfaces:["full","quick"]}),a("translateTitle","TranslateFeature","标题翻译",{description:"翻译列表和详情页标题。",surfaces:["full","quick"]}),a("hoverBigImg","ListImageFeature","悬浮大图",{description:"鼠标悬停封面时显示大图。",surfaces:["full","quick"],defaultValue:s}),o.register({key:"defaultQuickFilterTab",owner:"ListPageFeature",label:"列表默认筛选",description:"进入列表页时默认选中的筛选标签,修改后下次进入列表生效。",type:"select",defaultValue:"waitCheck",effect:"nextNavigation",surfaces:["full"],options:Is}),a("enableLoadReview","ReviewFeature","评论",{description:"在详情页与 FC2 页面加载评论;显式关闭 no 时保持关闭。",surfaces:["full","quick"]}),a("enableLoadOtherSite","OtherSiteFeature","外部站点",{description:"在详情页提供第三方站点入口。",surfaces:["full","quick"]}),a("enableLoadActressInfo","ActressInfoFeature","演员信息",{description:"在详情页与演员页展示演员资料。",surfaces:["full","quick"]}),a("enableMagnetsFilter","MagnetFeature","磁力质量过滤",{description:"在资源列表中过滤低质量磁力。",surfaces:["full"]}),a("needClosePage","WorkflowFeature","鉴定后立即关闭",{description:"完成鉴定后关闭当前详情窗口。",surfaces:["full","quick"]}),a("enableVerticalModel","LayoutFeature","竖图模式",{description:"使用竖图比例的列表卡片布局。",surfaces:["full","quick"],defaultValue:s}),o.register({key:"mobileMode",owner:"LayoutFeature",label:"移动模式",type:"select",defaultValue:"auto",effect:"live",surfaces:["full"],options:Object.freeze([{value:"auto",label:"自动检测"},{value:"on",label:"强制开启"},{value:"off",label:"强制关闭"}])}),o.register({key:"themeMode",owner:"ThemeFeature",label:"主题",type:"select",defaultValue:"light",effect:"live",surfaces:["full"],options:Object.freeze([{value:"light",label:"浅色"},{value:"dark",label:"深色"},{value:"auto",label:"跟随系统"}])}),o.register({key:"containerColumns",owner:"LayoutFeature",label:"列表列数",type:"number",defaultValue:5,effect:"live",surfaces:["full"]}),o.register({key:"containerWidth",owner:"LayoutFeature",label:"列表宽度",type:"number",defaultValue:100,effect:"live",surfaces:["full"]}),o.register({key:"screenshotMode",owner:"ScreenshotFeature",label:"截图来源模式",type:"select",defaultValue:"auto",effect:"manual",surfaces:["full"],options:Object.freeze([{value:"auto",label:"自动选择"},{value:"manual",label:"手动选择"}])}),o.register({key:"screenshotProviders",owner:"ScreenshotFeature",label:"截图来源",type:"json",defaultValue:[],effect:"manual",surfaces:["full"]}),o.register({key:"enableClog",owner:"CoreFeature",label:"日志",type:"select",defaultValue:t,effect:"live",surfaces:["full"],options:Object.freeze([{value:t,label:"开启"},{value:s,label:"关闭"}])}),o.register({key:"videoMuted",owner:"PreviewVideoFeature",label:"视频默认静音",type:"boolean",defaultValue:!0,effect:"live",surfaces:[]}),a("enable123Offline","OfflineFeature","123 云盘离线",{description:"支持 Magnet,需要先在 123 云盘页面同步授权。",surfaces:["full"],section:"cloud",defaultValue:!0,normalize:d(i=>be(i,!1),"normalize")}),a("enable115Offline","OfflineFeature","115 离线下载",{description:"支持 Magnet 与 ED2K。",surfaces:["full"],section:"cloud",defaultValue:!1,normalize:d(i=>be(i,!1),"normalize")}),o.register({key:"offlineProviderMode",owner:"OfflineFeature",label:"默认服务",description:"选择离线提交时优先使用的服务。",type:"select",defaultValue:"ask",effect:"live",surfaces:["full"],section:"cloud",options:Object.freeze([{value:"ask",label:"每次询问"},{value:"123",label:"优先 123"},{value:"115",label:"优先 115"}]),normalize:d(i=>["ask","123","115"].includes(String(i))?String(i):"ask","normalize")}),a("enable115Match","OfflineFeature","115 文件匹配",{description:"根据当前番号查找网盘中已存在的视频。",surfaces:["full"],section:"cloud",defaultValue:!1,normalize:d(i=>be(i,!1),"normalize")}),a("enable115LoginRedirect","OfflineFeature","未登录时提供登录入口",{description:"提交失败时显示 115 登录地址。",surfaces:["full"],section:"cloud",defaultValue:!1,normalize:d(i=>be(i,!1),"normalize")}),o.register({key:"oneOneFiveConcurrency",owner:"OfflineFeature",label:"匹配并发数",description:"控制 115 文件匹配的并发请求数,范围 1–10。",type:"number",defaultValue:4,effect:"live",surfaces:["full"],section:"cloud",min:1,max:10,step:1,normalize:d(i=>r(i,4,1,10),"normalize")}),o.register({key:"oneOneFiveCacheMinutes",owner:"OfflineFeature",label:"匹配缓存(分钟)",description:"设置 115 匹配结果缓存时间,范围 1–1440 分钟。",type:"number",defaultValue:60,effect:"live",surfaces:["full"],section:"cloud",min:1,max:1440,step:1,normalize:d(i=>r(i,60,1,1440),"normalize")})}d(Fc,"registerDefaultSettings");function Vc(o){let e=new ir({legacyHttp:o.legacyHttp}),t=new te("app:root",{onChange:d(Ne=>e.updateScope(Ne),"onChange")}),s=new $r(e),a=new Za,r=new sr(o.gmRequest),i=new er(o.storageForage,o.localStorage,o.gmGetValue,o.gmSetValue,o.gmDeleteValue),n=new tr(o.layer),l=new Xa,c=new or({localOrigins:o.localOrigins}),h=new dr(a),u=new Sr(i),p=new ar({diagnostics:e,storage:u}),g=new nr(n),m=new Cr(l),f=new Rr;Fc(f);let v=new jr(u,{afterPersist:d(async(Ne,z)=>{o.legacyStorage?.invalidateSettingCache?.(),await o.eventBus?.emit?.("settings-changed",{changedNames:z,source:"service"})},"afterPersist"),normalizers:f.normalizers()}),b=new lr(r,c,{diagnostics:e,cache:p,settings:v});e.setNetworkController(b);let w=new kr(u,o.localStorage),S=new xr(b,w,v);t.listen(v,"settings.changed",Ne=>{if(!(Ne.detail?.names??[]).includes("trustedLocalOrigins"))return;let Z=v.snapshot().trustedLocalOrigins;c.replaceLocalOrigins(Array.isArray(Z)?Z:[])}),o.eventBus&&t.addCleanup(o.eventBus.on("settings-changed",async(Ne,z)=>{let Z=z.originId!==o.eventBus.originId,re=z.originId===o.eventBus.originId&&z.payload?.source==="legacy";!Z&&!re||(o.legacyStorage?.invalidateSettingCache?.(),await v.refresh())})),typeof window<"u"&&t.listen(window,"pageshow",async()=>{o.legacyStorage?.invalidateSettingCache?.(),await v.refresh()});let j=new gr({scope:t,settings:v}),k=new _r,x=new Ar(e),_=new Pr(s,e),R=new ur(_),L=new rr(_,p),N=new cr(_),A=new fr(_),O=new mr(_),U=new hr(x,_),q=new vr(x,_),Q=new br(_,u),se=new wr(_),ge=new yr(_),De=new pr(x,_);s.register(Y.navigation,a).register(Y.http,r).register(Y.storage,i).register(Y.dialog,n).register(Y.style,l).register(y.diagnostics,e).register(y.urlPolicy,c).register(y.navigation,h).register(y.http,b).register(y.storage,u).register(y.webdav,S).register(y.credential,w).register(y.dialog,g).register(y.settings,v).register(y.cache,p).register(y.profile,j).register(y.state,o.stateService).register(y.movie,R).register(y.actressInfo,L).register(y.imageSearch,N).register(y.review,A).register(y.related,O).register(y.magnet,U).register(y.screenshot,q).register(y.offline,De).register(y.translation,Q).register(y.subtitle,se).register(y.account,ge).register(Qe.command,k).register(Qe.provider,x).register(Qe.integration,_).register(Qe.settings,f),o.hostAdapter&&s.register(Y.host,o.hostAdapter),o.hostAdapters?.javdb&&s.register(Y.javdbHost,o.hostAdapters.javdb),o.hostAdapters?.javbus&&s.register(Y.javbusHost,o.hostAdapters.javbus);let lt=new Tr({container:s,commands:k,diagnostics:e,disabled:o.disabled,site:o.site,route:o.route});return s.register(Qe.feature,lt),Object.freeze({rootScope:t,container:s,ports:Object.freeze({navigationPort:a,httpPort:r,storagePort:i,dialogPort:n,stylePort:l}),services:Object.freeze({diagnostics:e,urlPolicy:c,navigation:h,http:b,storage:u,webdav:S,credential:w,dialog:g,styles:m,settings:v,cache:p,profile:j,state:o.stateService,movie:R,actressInfo:L,imageSearch:N,review:A,related:O,magnet:U,screenshot:q,translation:Q,subtitle:se,account:ge,offline:De}),registries:Object.freeze({commands:k,providers:x,integrations:_,settings:f,features:lt})})}d(Vc,"createAppContext");var Gk=Object.freeze({censored:"censored",uncensored:"uncensored"});function Ir(o){if(typeof o.carNum!="string"||!o.carNum)throw new TypeError("MovieRef.carNum is required");return Object.freeze({...o})}d(Ir,"defineMovieRef");function qt(o){if(typeof o.carNum!="string"||!o.carNum)throw new TypeError("MovieDetail.carNum is required");return Object.freeze({...o})}d(qt,"defineMovieDetail");function Co(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelectorAll=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelectorAll=="function")return e;throw new TypeError("123AV document is invalid")}d(Co,"resolveDocument");function _o(o,e="https://123av.com"){let t=new Map;if(typeof o?.find!="function"){for(let a of Co(o).querySelectorAll(".card")){let r=a.querySelector('a.card__link[href*="/cn/v/fc2-ppv-"]'),i=r?.getAttribute("href"),n=r?.textContent?.trim()??"",l=n.match(/FC2-PPV-(\d+)/i);if(!i||!l)continue;let c=`FC2-${l[1]}`,h=new URL(i,e);h.hash="",t.set(c,{imgSrc:a.querySelector("img.card__img[src]")?.getAttribute("src")||"",carNum:c,href:h.href,title:n.replace(/^FC2-PPV-\d+\s*[—–-]\s*/i,"").trim(),preview:a.querySelector(".card__poster[data-preview]")?.getAttribute("data-preview")||null})}return[...t.values()]}let s=globalThis.jQuery??globalThis.$??o.constructor;return o.find(".card").each(((a,r)=>{let i=s(r),n=i.find('a.card__link[href*="/cn/v/fc2-ppv-"]').first(),l=n.attr("href"),c=n.text().trim(),h=c.match(/FC2-PPV-(\d+)/i);if(!l||!h)return;let u=`FC2-${h[1]}`,p=new URL(l,e);p.hash="",t.set(u,{imgSrc:i.find("img.card__img[src]").first().attr("src")||"",carNum:u,href:p.href,title:c.replace(/^FC2-PPV-\d+\s*[—–-]\s*/i,"").trim(),preview:i.find(".card__poster[data-preview]").first().attr("data-preview")||null})})),[...t.values()]}d(_o,"parse123AvCards");function qc(o){let e=new Map;return o.flat().forEach((t=>e.set(t.carNum,t))),[...e.values()]}d(qc,"merge123AvCards");function Hc(o,e="https://123av.com"){if(typeof o?.find!="function"){let r=Co(o),i=r.querySelector('a[rel="last"]')?.getAttribute("href");if(i){let c=Number.parseInt(new URL(i,e).searchParams.get("page")??"",10);if(Number.isFinite(c))return c}let n=Number.parseInt(r.querySelector("input.pager__input[max]")?.getAttribute("max")??"",10);if(Number.isFinite(n))return n;let l=r.querySelector(".pager__total")?.textContent?.match(/(\d[\d,]*)/);return l?Number.parseInt(l[1].replaceAll(",",""),10):null}let t=o.find('a[rel="last"]').first().attr("href");if(t){let r=Number.parseInt(new URL(t,e).searchParams.get("page")??"",10);if(Number.isFinite(r))return r}let s=Number.parseInt(o.find("input.pager__input[max]").first().attr("max"),10);if(Number.isFinite(s))return s;let a=o.find(".pager__total").first().text().match(/(\d[\d,]*)/);return a?Number.parseInt(a[1].replaceAll(",",""),10):null}d(Hc,"parse123AvSourceMaxPage");function Wc(o,e){let t=new URL(e).pathname.match(/fc2-ppv-(\d+)/i),s=t?t[1]:null,a=typeof o?.find=="function"?null:Co(o),r=a?a.querySelector("h1.watch__title")?.textContent?.trim()??"":o.find("h1.watch__title").first().text().trim(),i=s?r.replace(new RegExp(`^FC2-PPV-${s}\\s*[—–-]\\s*`,"i"),"").trim():r,l=(a?a.body?.textContent??"":o.find("body").text()).match(/发布日期\s*(\d{4}-\d{2}-\d{2})/)?.[1]||"";return{id:s,publishDate:l,title:i,moviePoster:null}}d(Wc,"parse123AvVideoInfo");var Er="https://123av.com";function hu(o){try{let e=new URL(String(o||Er));return e.protocol!=="https:"?Er:e.origin}catch{return Er}}d(hu,"normalizeBaseOrigin");function uu(o,e=null){let t=d(()=>hu(e?.snapshot().av123Url),"baseOrigin"),s=d((a,r,i="movie.detail")=>{let n=new URL(a).origin,l=n===Er;return o.request({providerId:"av123",capability:i,method:"GET",url:a,responseType:"text",requestOptions:{cookiePartition:{topLevelSite:n}},urlPolicy:l?{trustClass:"builtin-public",hosts:["123av.com"],expectedOrigin:n}:{trustClass:"custom-public",expectedOrigin:n}},r)},"request");return Object.freeze({contracts:["MovieRef","MovieDetail"],origin:t,searchUrl(a){let r=ee(a?.carNum);return r?`${t()}/cn/search?keyword=${encodeURIComponent(r)}`:null},detailUrl(a){let r=ee(a.carNum)?.match(/^FC2-(\d+)$/)?.[1];return a.url?new URL(a.url).href:r?`${t()}/cn/v/fc2-ppv-${r}`:null},matchesUrl(a){try{let r=new URL(a);return r.origin===t()||/^\/cn\/v\/fc2-ppv-\d+\/?$/i.test(r.pathname)}catch{return!1}},async listCatalog(a={},r={}){let i=Math.max(1,Number(a.page)||1),n=String(a.keyword||"").trim(),c=(n?[i]:[i*2-1,i*2]).map(m=>n?`${t()}/cn/search?keyword=${encodeURIComponent(n)}&page=${m}`:`${t()}/cn/makers/fc2?page=${m}`),h=await Promise.all(c.map(m=>s(m,r.scope,n?"movie.search":"movie.catalog"))),u=h.map((m,f)=>_o(m.data,m.finalUrl||c[f])),p=qc(u).map(m=>Object.freeze({carNum:m.carNum,title:m.title,url:m.href,imageUrl:m.imgSrc?new URL(m.imgSrc,t()).href:null,previewUrl:m.preview?new URL(m.preview,t()).href:null,providerId:"av123"})),g=h.length?Hc(h[0].data,h[0].finalUrl||c[0]):null;return Object.freeze({items:p,maxPage:g?n?g:Math.ceil(g/2):null})},async resolveMovie(a,r={}){let i=ee(a.carNum);if(!i)return null;let n=this.searchUrl({carNum:i});if(!n)return null;let l=await s(n,r.scope,"movie.search"),c=_o(l.data,l.finalUrl||n).find(h=>ee(h.carNum)===i);return c?Ir({carNum:i,url:c.href,providerId:"av123"}):null},async getDetail(a,r={}){let i=ee(a.carNum),n=i?.match(/^FC2-(\d+)$/)?.[1];if(!i||!a.url&&!n)throw new TypeError("123AV movie reference is invalid");let l=new URL(a.url||`${t()}/cn/v/fc2-ppv-${n}`).href,c=await s(l,r.scope),h=Wc(c.data,c.finalUrl||l);if(!h.title)throw new TypeError("123AV detail is malformed");return qt({carNum:i,title:h.title,releaseDate:h.publishDate||null,url:c.finalUrl||l,providerId:"av123"})}})}d(uu,"create123AvAdapter");var Jc=W({id:"av123",trustClass:"builtin-public",hosts:["123av.com"],capabilities:["movie.search","movie.detail","movie.catalog"],requires:[y.http,y.settings],createClient:d(o=>Object.freeze({http:o[y.http],settings:o[y.settings]}),"createClient"),createAdapter:d(o=>uu(o.http,o.settings),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.search":"public-7d","movie.detail":ke.externalDetail,"movie.catalog":"public-7d"},quality:"silver"});function pu(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelector=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelector=="function")return e;throw new TypeError("DMM preview document is invalid")}d(pu,"resolveDocument");function Kc(o,e){let t=pu(o),s=t.querySelector("[data-video-url]")?.getAttribute("data-video-url")??t.querySelector("video source[src]")?.getAttribute("src");if(!s)throw new TypeError("DMM preview URL is missing");let a=new URL(s,e);if(a.protocol!=="https:")throw new TypeError("DMM preview must use HTTPS");return Object.freeze({url:a.href})}d(Kc,"parseDmmPreview");function Gc(o,e,t){if(o?.result?.result_count===0&&!Array.isArray(o.result.items))return Object.freeze([]);if(!o||typeof o!="object"||!o.result||!Array.isArray(o.result.items))throw new we("dmm","INVALID_RESPONSE","DMM API 返回结构无效");let s=e.toLowerCase(),a=s.replace(/-/g,""),r=t.toLowerCase().replace(/-/g,"");return Object.freeze(o.result.items.flatMap(i=>{let n=String(i?.content_id??""),l=String(i?.maker_product??"");return!n.toLowerCase().includes(r)&&l.toLowerCase()!==s&&!n.toLowerCase().includes(a)?[]:[Object.freeze({serviceCode:String(i.service_code??""),floorCode:String(i.floor_code??""),contentId:n,pageUrl:new URL(String(i.URL)).href})]}).slice(0,2))}d(Gc,"parseDmmItemCandidates");function Qc(o,e){if(typeof o!="string")throw new we("dmm","PARSE_ERROR","解析播放页内容失败, 非文本内容",{url:e});if(o.includes("このサービスはお住まいの地域からは"))throw new we("dmm","REGION_BLOCKED","DMM 预览源不可用,请将 DMM 域名分流到日本 IP",{url:e});let t=o.match(/const\s+args\s+=\s+(.*);/);if(!t)throw new we("dmm","PARSE_ERROR","未在脚本中找到 const args = ... 变量",{url:e});let s;try{({bitrates:s}=JSON.parse(t[1]))}catch(r){throw new we("dmm","PARSE_ERROR",`解析播放器脚本 JSON 失败: ${r instanceof Error?r.message:String(r)}`,{cause:r,url:e})}if(!Array.isArray(s))throw new we("dmm","PARSE_ERROR","解析画质链接失败: bitrates 字段不是一个数组或不存在",{url:e});let a={};for(let r of s){let i=r?.src;if(typeof i!="string"||!i.endsWith(".mp4"))continue;let n=new URL(i,e);if(n.protocol!=="https:")continue;let l=n.pathname.match(/\/([^/]+)\.mp4$/)?.[1];l&&!a[l]&&(a[l]=n.href)}if(Object.keys(a).length===0)throw new we("dmm","PARSE_ERROR","未找到匹配要求的预览画质视频",{url:e});return Object.freeze(a)}d(Qc,"parseDmmPlayerSources");var $o=["dmm.co.jp","dmm.com"];function gu(o){return Object.freeze({contracts:["MoviePreview"],searchUrl(e){return`https://www.dmm.co.jp/search/=/searchstr=${encodeURIComponent(String(e.carNum??""))}`},async getPreview(e,t={}){let s=new URL(e.url),a=await o.request({providerId:"dmm",capability:"movie.preview",method:"GET",url:s.href,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["dmm.co.jp"]}},t.scope);return Kc(a.data,a.finalUrl||s.href)},async getPreviewForMovie(e,t={}){let s=String(e.carNum),a=s.replace(/-/g,""),r=[s.replace("-","00"),s,a],i=this.searchUrl(e),n=[],l=null,c=!1;for(let p of r){let g=`https://api.dmm.com/affiliate/v3/ItemList?${new URLSearchParams({api_id:"UrwskPfkqQ0DuVry2gYL",affiliate_id:"10278-996",output:"json",site:"FANZA",sort:"match",keyword:p})}`;try{let m=await o.request({providerId:"dmm",capability:"movie.preview",method:"GET",url:g,responseType:"json",urlPolicy:{trustClass:"builtin-public",hosts:$o}},t.scope);if(n=Gc(m.data,s,p),c=!0,n.length)break}catch(m){l=m;break}}if(!n.length){if(!c&&l)throw l;return Object.freeze({sources:null,pageUrl:i,searchUrl:i,matchType:"none"})}let h=n.map(async p=>{let g=`https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${encodeURIComponent(p.contentId)}/mtype=AhRVShI_/service=${encodeURIComponent(p.serviceCode)}/floor=${encodeURIComponent(p.floorCode)}/mode=/`,m=await o.request({providerId:"dmm",capability:"movie.preview",method:"GET",url:g,responseType:"text",headers:{"accept-language":"ja-JP,ja;q=0.9",Cookie:"age_check_done=1"},urlPolicy:{trustClass:"builtin-public",hosts:$o}},t.scope);return Qc(m.data,m.finalUrl||g)}),u;try{u=await Promise.any(h)}catch(p){let g=p instanceof AggregateError?p.errors:[p];throw g.find(m=>m?.code==="REGION_BLOCKED")??g[0]??p}return Object.freeze({sources:u,pageUrl:n.length>1?i:n[0].pageUrl,searchUrl:i,matchType:n.length>1?"multiple":"single"})}})}d(gu,"createDmmAdapter");var Yc=W({id:"dmm",trustClass:"builtin-public",hosts:$o,capabilities:["movie.preview"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>gu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.preview":"none"},quality:"silver"});var Zc=Object.freeze([Object.freeze({id:"javTrailersBtn",name:"javTrailers",settingKey:"javTrailersUrl",defaultBaseUrl:"https://javtrailers.com",itemSelector:".videos-list .video-link",textSelector:"p.card-text",hrefSelector:null,searchPath:d(o=>`/search/${o}`,"searchPath")}),Object.freeze({id:"jableBtn",name:"jable",settingKey:"jableUrl",defaultBaseUrl:"https://jable.tv",itemSelector:"#list_videos_videos_list_search_result .detail .title a",textSelector:null,hrefSelector:null,searchPath:d(o=>`/search/${o}/`,"searchPath")}),Object.freeze({id:"avgleBtn",name:"avgle",settingKey:"avgleUrl",defaultBaseUrl:"https://jav.rs",itemSelector:".text-secondary",textSelector:null,hrefSelector:null,searchPath:d(o=>`/vod/search.html?wd=${o}`,"searchPath")}),Object.freeze({id:"missAvBtn",name:"missAv",settingKey:"missAvUrl",defaultBaseUrl:"https://missav.live",itemSelector:".text-secondary",textSelector:null,hrefSelector:null,searchPath:d(o=>`/search/${o}`,"searchPath")}),Object.freeze({id:"supJavBtn",name:"supJav",settingKey:"supJavUrl",defaultBaseUrl:"https://supjav.com",itemSelector:".posts post",textSelector:null,hrefSelector:null,titleAttribute:!0,searchPath:d(o=>`/?s=${o}`,"searchPath")}),Object.freeze({id:"javDbBtn",name:"javDb",settingKey:"javDbUrl",defaultBaseUrl:"https://javdb.com",itemSelector:".movie-list .item",textSelector:".video-title",hrefSelector:"a",searchPath:d(o=>`/search?q=${o}`,"searchPath")}),Object.freeze({id:"javBusBtn",name:"javBus",settingKey:"javBusUrl",defaultBaseUrl:"https://www.javbus.com",itemSelector:".container h3",textSelector:null,hrefSelector:null,directDetail:!0,searchPath:d(o=>`/${o}`,"searchPath")})]);function Xc(o,e){let t=new URL(e[o.settingKey]||o.defaultBaseUrl).origin;return Object.freeze({id:o.id,name:o.name,baseUrl:t,searchUrl:d(s=>new URL(o.searchPath(encodeURIComponent(s)),`${t}/`).href,"searchUrl")})}d(Xc,"siteDefinition");function mu(o,e,t,s){if(typeof o!="string")throw new D("INVALID_RESPONSE","外部站点响应不是 HTML",{source:e.id});let a=new DOMParser().parseFromString(o,"text/html"),r=[];for(let i of a.querySelectorAll(e.itemSelector)){let n=e.textSelector?i.querySelector(e.textSelector):i;if((e.titleAttribute?i.getAttribute("title")||"":n?.textContent?.trim()||"").toLowerCase().includes(t.toLowerCase()))if(e.directDetail)r.push(new URL(`/${encodeURIComponent(t)}`,`${s}/`).href);else{let c=e.hrefSelector?i.querySelector(e.hrefSelector):i,h=c?.getAttribute("href");if(!h)throw new D("PARSE_ERROR","外部站点结果缺少链接",{source:e.id});r.push(new URL(h,`${s}/`).href)}}return Object.freeze([...new Set(r)])}d(mu,"parseExternalSiteResults");function fu(o){return Object.freeze({contracts:["ExternalSiteResult"],getSites(e={}){return Object.freeze(Zc.map(t=>Xc(t,e)))},getNavigationLinks:d(()=>Object.freeze([Object.freeze({id:"theporndude",label:"ThePornDude",url:"https://theporndude.com/zh"})]),"getNavigationLinks"),async searchSite(e,t,s={}){let a=Zc.find(u=>u.id===e);if(!a)throw new D("UNSUPPORTED",`未知外部站点:${e}`,{source:"external-sites"});let r=Xc(a,s.settings||{}),i=r.searchUrl(t),n=new URL(i),l=new URL(a.defaultBaseUrl).hostname.replace(/^www\./,""),c=n.hostname===l||n.hostname.endsWith(`.${l}`)?{trustClass:"builtin-public",hosts:[l],expectedOrigin:n.origin}:{trustClass:"custom-public",expectedOrigin:n.origin},h=await o.request({capability:"movie.external-sites",providerId:`external-site:${e}`,method:"GET",url:i,responseType:"text",urlPolicy:c},s.scope);return Object.freeze({searchUrl:i,matches:mu(h.data,a,t,r.baseUrl)})}})}d(fu,"createExternalSitesAdapter");var ed=W({id:"external-sites",trustClass:"builtin-public",hosts:["javtrailers.com","jable.tv","jav.rs","missav.live","supjav.com","javdb.com","javbus.com","theporndude.com"],capabilities:["movie.external-sites","navigation.external"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>fu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.external-sites":"public-1d","navigation.external":"none"},quality:"silver"});function td(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelector=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelector=="function")return e;throw new TypeError("FC2PPVDB detail document is invalid")}d(td,"resolveDocument");function sd(o,e){let t=new URL(e).pathname.match(/(?:articles?|videos?)\/(\d+)/i)?.[1],s=ee(t?`FC2-${t}`:""),a=td(o).querySelector("h1")?.textContent?.trim()??"";if(!s||!a)throw new TypeError("FC2PPVDB detail is malformed");return qt({carNum:s,title:a,url:new URL(e).href})}d(sd,"parseFc2PpvDbDetail");function ad(o,e){let t=td(o),s=new URL(e),a=[...t.querySelectorAll("div")],r=a.find(h=>h.textContent?.trim().startsWith("女優:")),i=a.find(h=>h.textContent?.trim().startsWith("販売者:")),n=[...r?.querySelectorAll("a[href]")??[]].map(h=>Object.freeze({name:h.textContent?.trim()||"",url:new URL(h.getAttribute("href")||"",s).href})).filter(h=>h.name),l=i?.querySelector("a[href]"),c=l?Object.freeze({name:l.textContent?.trim()||"",url:new URL(l.getAttribute("href")||"",s).href}):null;return Object.freeze({actors:Object.freeze(n),seller:c})}d(ad,"parseFc2PpvDbPeople");function vu(o){let e=d(s=>{let a=String(s.carNum||"").match(/^(?:FC2-)?(?:PPV-)?(\d+)$/i)?.[1];if(!a)throw new TypeError("FC2PPVDB movie identifier is invalid");return new URL(s.url||`https://fc2ppvdb.com/articles/${a}`)},"resolveUrl"),t=d((s,a,r="movie.detail")=>o.request({capability:r,providerId:"fc2ppvdb",method:"GET",url:s.href,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["fc2ppvdb.com"]}},a),"request");return Object.freeze({contracts:["MovieDetail","MovieCredits"],detailUrl(s){return e(s).href},async getDetail(s,a={}){let r=e(s),i=await t(r,a.scope,"movie.detail");return sd(i.data,i.finalUrl||r.href)},async getPeople(s,a={}){let r=e(s),i=await t(r,a.scope,"movie.credits");return ad(i.data,i.finalUrl||r.href)}})}d(vu,"createFc2PpvDbAdapter");var rd=W({id:"fc2ppvdb",trustClass:"builtin-public",hosts:["fc2ppvdb.com"],capabilities:["movie.detail","movie.credits"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>vu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.detail":ke.externalDetail,"movie.credits":ke.externalDetail},quality:"silver"});function id(o,e){let t=new DOMParser().parseFromString(o,"text/html"),s=new Set;for(let a of t.querySelectorAll(".items_article_SampleImagesArea img[src]")){let r=new URL(a.getAttribute("src")||"",e);r.protocol==="https:"&&s.add(r.href)}return Object.freeze([...s].map(a=>Object.freeze({url:a,providerId:"fc2content"})))}d(id,"parseFc2ContentImages");function bu(o){return Object.freeze({contracts:["Screenshot"],detailUrl(e){let t=String(e.carNum||"").match(/^(?:FC2-)?(?:PPV-)?(\d+)$/i)?.[1];return t?`https://adult.contents.fc2.com/article/${t}/`:null},async getImages(e,t={}){let s=String(e.carNum||"").match(/^(?:FC2-)?(?:PPV-)?(\d+)$/i)?.[1];if(!s)return[];let a=`https://adult.contents.fc2.com/article/${s}/`,r=await o.request({providerId:"fc2content",capability:"movie.images",method:"GET",url:a,responseType:"text",headers:{referer:a},urlPolicy:{trustClass:"builtin-public",hosts:["adult.contents.fc2.com"]}},t.scope);return id(r.data,r.finalUrl||a)}})}d(bu,"createFc2ContentAdapter");var nd=W({id:"fc2content",trustClass:"builtin-public",hosts:["adult.contents.fc2.com"],capabilities:["movie.images"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>bu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.images":ke.externalDetail},quality:"silver"});function od(o){if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError("Translation response is invalid");let e=o.translation;if(typeof e!="string"||!e.trim())throw new TypeError("Translation text is missing");return e}d(od,"parseGoogleTranslation");var wu="https://translate-pa.googleapis.com/v1/translate";function yu(o){return Object.freeze({contracts:["Translation"],async translate(e,t={}){if(!String(e||"").trim())throw new TypeError("Translation text cannot be empty");let s=new URL(wu);s.search=new URLSearchParams({"params.client":"gtx",dataTypes:"TRANSLATION",key:"AIzaSyDLEeFI5OtFBwYBIoK_jj5m32rZK5CkCXA","query.sourceLanguage":t.sourceLanguage??"ja","query.targetLanguage":t.targetLanguage??"zh-CN","query.text":e}).toString();let a=await o.request({providerId:"google-translate",capability:"text.translate",method:"GET",url:s.href,responseType:"json",transport:"native-fetch",nativeTimeout:1500,timeout:5e3,urlPolicy:{trustClass:"builtin-public",hosts:["translate-pa.googleapis.com"]}},t.scope);return od(a.data)}})}d(yu,"createGoogleTranslateAdapter");var ld=W({id:"google-translate",trustClass:"builtin-public",hosts:["translate-pa.googleapis.com"],capabilities:["text.translate"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>yu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"text.translate":"none"},quality:"silver"});var To=Object.freeze([Object.freeze({id:"jsdelivr",name:"jsDelivr (全球CDN)",catalogUrl:"https://cdn.jsdelivr.net/gh/gfriends/gfriends/Filetree.json",contentBaseUrl:"https://cdn.jsdelivr.net/gh/gfriends/gfriends/Content/",recommended:!0}),Object.freeze({id:"github-raw",name:"GitHub Raw (备用)",catalogUrl:"https://raw.githubusercontent.com/gfriends/gfriends/master/Filetree.json",contentBaseUrl:"https://raw.githubusercontent.com/gfriends/gfriends/master/Content/",recommended:!1})]);function ju(o,e){let t=o?.Content;if(!t||typeof t!="object"||Array.isArray(t))throw new D("INVALID_RESPONSE","头像数据源缺少 Content",{source:"gfriends"});let s=new Map;for(let[a,r]of Object.entries(t))if(!(!r||typeof r!="object"||Array.isArray(r)))for(let[i,n]of Object.entries(r)){if(typeof n!="string")continue;let l=i.replace(/\.jpg$/i,"").split("-")[0];if(l.startsWith("AI-Fix-")&&(l=l.slice(7)),l=l.toLowerCase().trim(),!l)continue;let c=n.indexOf("?"),h=c>=0?n.slice(0,c):n,u=c>=0?n.slice(c):"",p=`${e}${encodeURIComponent(a)}/${encodeURIComponent(h)}${u}`,g=s.get(l)||[];g.includes(p)||g.push(p),s.set(l,g)}return s}d(ju,"parseGfriendsCatalog");function Su(o){return Object.freeze({contracts:["ActorAvatar"],getSources:d(()=>Object.freeze(To.map(e=>Object.freeze({id:e.id,name:e.name,recommended:e.recommended}))),"getSources"),async searchAvatars(e,t={}){let s=To.find(n=>n.id===(t.sourceId||To[0].id));if(!s)throw new D("UNSUPPORTED",`未知头像数据源:${t.sourceId}`,{source:"gfriends"});let a=await o.request({providerId:`gfriends:${s.id}`,capability:"person.avatar-search",method:"GET",url:s.catalogUrl,responseType:"json",timeout:2e4,urlPolicy:{trustClass:"builtin-public",hosts:[new URL(s.catalogUrl).hostname]}},t.scope),r=ju(a.data,s.contentBaseUrl),i=new Set;return e.map(n=>String(n).toLowerCase().trim()).filter(Boolean).forEach(n=>r.get(n)?.forEach(l=>i.add(l))),Object.freeze([...i])}})}d(Su,"createGfriendsAdapter");var cd=W({id:"gfriends",trustClass:"builtin-public",hosts:["cdn.jsdelivr.net","raw.githubusercontent.com"],capabilities:["person.avatar-search"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Su(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"person.avatar-search":"public-7d"},quality:"silver"});var dd=W({id:"host-list",trustClass:"builtin-public",hosts:["javdb.com","javbus.com"],capabilities:["host.list.parse"],requires:[],createClient:d(()=>Object.freeze({id:"host-list"}),"createClient"),createAdapter:d(()=>Object.freeze({contracts:["MovieRef"]}),"createAdapter"),createHostAdapter:null,cachePolicy:"none",quality:"bronze"});var xu="https://api.imgur.com/3/image",ku="d70305e7c3ac5c6",Cu=Object.freeze({trustClass:"builtin-public",hosts:["imgur.com","google.com","yandex.ru"]}),_u=Object.freeze([Object.freeze({id:"google-legacy",name:"Google旧版",urlTemplate:"https://www.google.com/searchbyimage?image_url={imageUrl}&client=firefox-b-d",iconUrl:"https://www.google.com/favicon.ico"}),Object.freeze({id:"google-lens",name:"Google",urlTemplate:"https://lens.google.com/uploadbyurl?url={imageUrl}",iconUrl:"https://www.google.com/favicon.ico"}),Object.freeze({id:"yandex",name:"Yandex",urlTemplate:"https://yandex.ru/images/search?rpt=imageview&url={imageUrl}",iconUrl:"https://yandex.ru/favicon.ico"})]);function $u(o){let e=o;if(typeof e=="string")try{e=JSON.parse(e)}catch(s){throw new D("INVALID_RESPONSE","Imgur 返回了无效 JSON",{source:"image-search",cause:s})}let t=e;if(t?.success&&typeof t?.data?.link=="string"&&/^https:\/\//i.test(t.data.link))return t.data.link;throw new D("INVALID_RESPONSE",String(t?.data?.error||"Imgur 上传响应无效"),{source:"image-search"})}d($u,"parseImgurUpload");function Tu(o){let e=o.match(/^data:(image\/[a-z0-9.+-]+);base64,([a-z0-9+/=\s]+)$/i);if(!e)throw new D("INVALID_RESPONSE","无效的 Base64 图片数据",{source:"image-search"});let t=atob(e[2].replace(/\s/g,"")),s=new Uint8Array(t.length);for(let r=0;rObject.freeze({id:s.id,name:s.name,url:s.urlTemplate.replace("{imageUrl}",t),iconUrl:s.iconUrl})))}})}d(Au,"createImageSearchAdapter");var hd=W({id:"image-search",trustClass:"builtin-public",hosts:["imgur.com","google.com","yandex.ru"],capabilities:["image.upload","image.search-targets"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Au(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"image.upload":"none","image.search-targets":"none"},quality:"silver"});var ud=0,Dr="";function Ao(){let o=Math.floor(Date.now()/1e3);if(Dr&&o-ud<=20)return Dr;let e=globalThis.md5;if(typeof e!="function")throw new Error("Missing userscript vendor runtime: md5");return ud=o,Dr=`${o}.lpw6vgqzsp.${e(`${o}71cf27bb3c0bcdf207b64abecddc970098c7421ee7203b9cdae54478478a199e7d5a6e1a57691123c1a931c057842fb73ba3b3c83bcd69c17ccf174081e3d8aa`)}`,Dr}d(Ao,"createJavDbSignature");var pd="https://jdforrepam.com";function Pu(o,e=Ao,t=null){let s=d(r=>{let i=new URL(r).origin,n=new URL(r).hostname;return n==="javdb.com"||n.endsWith(".javdb.com")?{trustClass:"builtin-public",hosts:["javdb.com"],expectedOrigin:i}:{trustClass:"custom-public",expectedOrigin:i}},"hostPolicy"),a=d(async(r,i,n={},l={},c="movie.detail")=>{let h=new URL(r,pd);return Object.entries(i).forEach(([p,g])=>h.searchParams.set(p,String(g))),(await o.request({providerId:"javdb",capability:c,method:"GET",url:h.href,responseType:"json",headers:{jdSignature:e(),...l},urlPolicy:{trustClass:"builtin-public",hosts:["jdforrepam.com"]}},n.scope)).data},"request");return Object.freeze({contracts:["MovieRef","MovieDetail","Actor","Magnet","Review","RelatedList","AccountSession"],actorPlaceholderUrl:d(()=>"https://c0.jdbstatic.com/images/actor_unknow.jpg","actorPlaceholderUrl"),async login(r,i={}){let n=new URL("/api/v1/sessions",pd);Object.entries({username:r.username,password:r.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"}).forEach(([h,u])=>n.searchParams.set(h,u));let c=(await o.request({providerId:"javdb",capability:"account.login",method:"POST",url:n.href,responseType:"json",headers:{"user-agent":"Dart/3.5 (dart:io)","accept-language":"zh-TW","content-type":"multipart/form-data; boundary=--dio-boundary-2210433284",jdsignature:e()},urlPolicy:{trustClass:"builtin-public",hosts:["jdforrepam.com"]}},i.scope)).data;if(c?.success===0)return Object.freeze({success:!1,token:null,message:String(c.message||"登录失败")});if(c?.success!==1||typeof c?.data?.token!="string")throw new D("INVALID_RESPONSE",String(c?.message||"JavDB 登录响应无效"),{source:"javdb"});return Object.freeze({success:!0,token:c.data.token,message:String(c.message||"")})},async listActorMovies(r,i={}){let n=new URL(r.baseUrl||"https://javdb.com").origin,l=new URL(`/actors/${encodeURIComponent(r.actorId)}?t=d`,n),c=await o.request({providerId:"javdb-host",capability:"actor.movies",method:"GET",url:l.href,responseType:"text",urlPolicy:s(n)},i.scope);if(typeof t?.parseActorMovies!="function")throw new TypeError("JavDB HostAdapter parser is unavailable");return t.parseActorMovies(c.data,c.finalUrl||l.href)},async listActorCollection(r,i={}){let n=new URL(r.baseUrl||"https://javdb.com").origin,l=new URL(r.pageUrl||"/users/collection_actors",n),c=await o.request({providerId:"javdb-host",capability:"actor.collection",method:"GET",url:l.href,responseType:"text",urlPolicy:s(n)},i.scope);if(typeof t?.parseActorCollection!="function")throw new TypeError("JavDB HostAdapter collection parser is unavailable");return t.parseActorCollection(c.data,c.finalUrl||l.href)},async uncollectActor(r,i={}){let n=new URL(r.baseUrl||"https://javdb.com").origin,l=new URL(`/actors/${encodeURIComponent(r.actorId)}/uncollect`,n),c=await o.request({providerId:"javdb-host",capability:"actor.uncollect",method:"POST",url:l.href,body:"null",responseType:"text",headers:{"Content-Type":"application/json","x-csrf-token":r.csrfToken},urlPolicy:s(n)},i.scope);return Object.freeze({success:typeof c.data=="string"&&c.data.includes("removeClass")})},async resolveMovie(r,i={}){let n=ee(r.carNum);if(!n)return null;let l=await a("/api/v2/search",{q:n,page:1,type:"movie",limit:20,movie_type:"all",from_recent:"false",movie_filter_by:"all",movie_sort_by:"relevance"},i,{"user-agent":"Dart/3.5 (dart:io)","accept-language":"zh-TW",host:"jdforrepam.com"},"movie.search");if(!Array.isArray(l?.data?.movies))throw new Error(l?.message||"JavDB search response is invalid");let c=l.data.movies.find(h=>ee(h.number)===n);return c?.id?Object.freeze({carNum:n,movieId:String(c.id),providerId:"javdb"}):null},async getDetail(r,i={}){let n=String(r.movieId||"").trim();if(!n)throw new TypeError("JavDB movie id is required");let l=await a(`/api/v4/movies/${encodeURIComponent(n)}`,{},i,{},"movie.detail"),c=l?.data?.movie;if(!c?.number)throw new Error(l?.message||"JavDB detail response is invalid");let h=Array.isArray(c.preview_images)?c.preview_images.map(p=>String(p.large_url||"").replace(/https:\/\/[^/]+\/rhe951l4q/,"https://c0.jdbstatic.com")).filter(Boolean):[],u=c.cover_url?String(c.cover_url).replace(/https:\/\/[^/]+\/rhe951l4q/,"https://c0.jdbstatic.com"):"";return Object.freeze({movieId:String(c.id||n),carNum:ee(c.number),title:String(c.title||c.origin_title||""),originalTitle:String(c.origin_title||c.title||""),coverUrl:u||null,actors:Array.isArray(c.actors)?c.actors.map(p=>Object.freeze({id:String(p.id),name:String(p.name||""),gender:Number(p.gender)})):[],duration:Number(c.duration)||null,score:Number(c.score)||0,releaseDate:c.release_date||null,watchedCount:Number(c.watched_count)||0,imageUrls:Object.freeze(h),providerId:"javdb"})},async listMagnets(r,i={}){let n=String(r.movieId||"").trim();if(!n)return[];let l=await a(`/api/v1/movies/${encodeURIComponent(n)}/magnets`,{},i,{},"movie.magnets");if(!Array.isArray(l?.data?.magnets))throw new Error(l?.message||"JavDB magnet response is invalid");return l.data.magnets.map(c=>Object.freeze({hash:String(c.hash||""),title:String(c.name||""),hasHdTag:!!c.hd,hasSubtitleTag:!!c.cnsub,createdAt:c.created_at||null,seeders:Number(c.seeders)||0,sizeMb:Number(c.size)||0,fileCount:Number(c.files_count)||0,providerId:"javdb"}))},async listRankings(r={}){let i=await a("/api/v1/rankings/playback",{period:r.period||"daily",filter_by:r.filter||"high_score"},r,{},"movie.ranking");if(!Array.isArray(i?.data?.movies))throw new Error(i?.message||"JavDB ranking response is invalid");return i.data.movies.map(n=>Object.freeze({movieId:String(n.id),carNum:ee(n.number),title:String(n.origin_title||""),coverUrl:String(n.cover_url||"").replace(/https:\/\/[^/]+\/rhe951l4q/,"https://c0.jdbstatic.com"),releaseDate:n.release_date||null,hasSubtitle:!!n.has_cnsub,magnetCount:Number(n.magnets_count)||0,newMagnets:!!n.new_magnets,providerId:"javdb"}))},async listReviews(r,i={}){let n=String(r.movieId||"").trim();if(!n)return[];let l=await a(`/api/v1/movies/${encodeURIComponent(n)}/reviews`,{page:i.page??1,sort_by:"hotly",limit:i.limit??20},i,{},"movie.reviews");if(!Array.isArray(l?.data?.reviews))throw new Error(l?.message||"JavDB review response is invalid");return l.data.reviews.map(c=>Object.freeze({author:String(c.username||"匿名用户"),content:String(c.content||""),score:Number(c.score)||0,createdAt:c.created_at||null,likes:Number(c.likes_count)||0}))},async listRelated(r,i={}){let n=String(r.movieId||"").trim();if(!n)return[];let l=await a("/api/v1/lists/related",{movie_id:n,page:i.page??1,limit:i.limit??20},i,{},"movie.related");if(!Array.isArray(l?.data?.lists))throw new Error(l?.message||"JavDB related response is invalid");return l.data.lists.map(c=>Object.freeze({id:String(c.id),name:String(c.name||"未命名清单"),movieCount:Number(c.movies_count)||0,collectionCount:Number(c.collections_count)||0,viewCount:Number(c.views_count)||0,createdAt:c.created_at||null}))}})}d(Pu,"createJavDbAdapter");var gd=W({id:"javdb",trustClass:"builtin-public",hosts:["javdb.com","jdforrepam.com","c0.jdbstatic.com"],capabilities:["movie.search","movie.detail","movie.magnets","movie.ranking","movie.state","movie.reviews","movie.related","actor.lookup","actor.movies","actor.collection","actor.uncollect","actor.avatar-placeholder","account.login"],requires:[y.http,Y.javdbHost],createClient:d(o=>Object.freeze({http:o[y.http],hostAdapter:o[Y.javdbHost]}),"createClient"),createAdapter:d(o=>Pu(o.http,Ao,o.hostAdapter),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.search":"public-7d","movie.detail":ke.externalDetail,"movie.magnets":"public-1d","movie.ranking":"public-1d","movie.state":"none","movie.reviews":"public-1d","movie.related":"public-1d","actor.lookup":"none","actor.movies":"public-5m","actor.collection":"none","actor.uncollect":"none","actor.avatar-placeholder":"none","account.login":"none"},quality:"silver"});function md(o){if(typeof o=="string")return new DOMParser().parseFromString(o,"text/html");if(typeof o?.querySelector=="function")return o;let e=o?.[0]??o?.get?.(0);if(typeof e?.querySelector=="function")return e;throw new TypeError("JavBus document is invalid")}d(md,"resolveDocument");function Ru(o,e){if(typeof o?.find=="function")return ee(o.find("span.header:contains('識別碼:')").parent().text().replace("識別碼:",""))??ee(new URL(e).pathname.split("/").filter(Boolean).pop());let s=[...md(o).querySelectorAll("span.header")].find(a=>a.textContent?.includes("識別碼"));return ee(s?.parentElement?.textContent?.replace("識別碼:",""))??ee(new URL(e).pathname.split("/").filter(Boolean).pop())}d(Ru,"readMovieRef");function Iu(o,e){let t=Ru(o,e);if(!t)throw new TypeError("JavBus movie identifier is missing");return Ir({carNum:t,url:new URL(e).href})}d(Iu,"parseJavBusMovieRef");function fd(o,e){let t=Iu(o,e),s=typeof o?.find=="function"?null:md(o),a=s?s.querySelector("h3")?.textContent?.trim()||t.carNum:o.find("h3").first().text().trim()||t.carNum,r=s?s.querySelector(".bigImage img[src], a.bigImage img[src]")?.getAttribute("src"):o.find(".bigImage img[src], a.bigImage img[src]").first().attr("src");return qt({...t,title:a,coverUrl:r?new URL(r,e).href:null,providerId:"javbus"})}d(fd,"parseJavBusMovieDetail");function Eu(o){return Object.freeze({contracts:["MovieDetail","Screenshot"],async getDetail(e,t={}){let s=ee(e.carNum);if(!s)throw new TypeError("JavBus movie reference is invalid");let a=new URL(e.url||`https://www.javbus.com/${encodeURIComponent(s)}`).href,r=await o.request({providerId:"javbus",capability:"movie.detail",method:"GET",url:a,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["javbus.com"]}},t.scope);return fd(r.data,r.finalUrl||a)},async getImages(e,t={}){let s=await this.getDetail(e,t);return s.coverUrl?[Object.freeze({url:s.coverUrl,providerId:"javbus"})]:[]}})}d(Eu,"createJavBusAdapter");var vd=W({id:"javbus",trustClass:"builtin-public",hosts:["javbus.com"],capabilities:["movie.detail","movie.images"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Eu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.detail":ke.externalDetail,"movie.images":ke.externalDetail},quality:"silver"});function Du(o){let e=d((t,s)=>o.request({providerId:"javstore",capability:"movie.images",method:"GET",url:t,responseType:"text",urlPolicy:{trustClass:"builtin-public",hosts:["javstore.net"]}},s),"request");return Object.freeze({contracts:["Screenshot"],getSearchUrl(t){return`https://javstore.net/search?q=${encodeURIComponent(t.carNum||"")}`},async getImages(t,s={}){let a=this.getSearchUrl(t),r=await e(a,s.scope),i=Ac(r.data,t.carNum,r.finalUrl||a);if(!i.length)return[];for(let n of i)try{let l=await e(n,s.scope),c=Pc(l.data,l.finalUrl||n);if(c)return[Object.freeze({url:c,providerId:"javstore"})]}catch(l){if(!(l&&typeof l=="object"&&"code"in l&&l.code==="NOT_FOUND"))throw l}return[]}})}d(Du,"createJavStoreAdapter");var bd=W({id:"javstore",trustClass:"builtin-public",hosts:["javstore.net"],capabilities:["movie.images"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Du(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"movie.images":"screenshot-7d"},quality:"silver"});var wd=W({id:"javtrailers",trustClass:"builtin-public",hosts:["javtrailers.com"],capabilities:["movie.preview"],requires:[Y.http,y.urlPolicy],createClient:d(()=>Object.freeze({id:"javtrailers"}),"createClient"),createAdapter:d(()=>Object.freeze({contracts:["MoviePreview"]}),"createAdapter"),createHostAdapter:null,cachePolicy:"none",quality:"bronze"});var Nu="https://115.com",Lu=Object.freeze({trustClass:"builtin-public",hosts:["115.com"]});function Mu(o){if(typeof o!="string")return o;try{return JSON.parse(o)}catch{return{state:!1,error_msg:/login|登录|sign in|未授权|授权|expire|expired|token|cookie/i.test(o)?"115 未登录":"115 返回异常响应"}}}d(Mu,"parsePayload");function Bu(o){let e=String(o).toLowerCase();return/未登录|请登录|登录|login|sign|授权|过期|token|cookie|uid|身份|auth|expire|needlogin|need login/i.test(e)?"AUTH_REQUIRED":/已存在|重复|exists|duplicate|already|same|conflict|exist/i.test(e)?"TASK_EXISTS":"OPERATION_FAILED"}d(Bu,"classify115OfflineError");function Ou(o){let e=o;if(!e||!Array.isArray(e.data))throw new D("INVALID_RESPONSE","115 文件搜索响应无效",{source:"one115"});return Object.freeze(e.data.map(t=>{let s=String(t.n||t.file_name||"");return Object.freeze({folderId:String(t.pid||t.cid||""),fileId:t.fid?String(t.fid):null,videoId:String(t.pc||t.pick_code||""),name:s,size:Number(t.s||t.size)||0,createTime:String(t.t||t.create_time||""),isVideo:/\.(mp4|mkv|avi|mov|flv|wmv|ts|m2ts)$/i.test(s)})}).filter(t=>t.isVideo))}d(Ou,"normalize115SearchResults");function Uu(o){let e=d((t,s={})=>o.request({providerId:"one115",capability:s.capability||"account.status",method:s.method||"GET",url:t,body:s.body,headers:s.headers,responseType:s.responseType||"json",urlPolicy:Lu},s.scope),"request");return Object.freeze({contracts:["AccountStatus","CloudFile","OfflineSubmission"],homeUrl:Nu,async checkAccount(t={}){let a=(await e("https://webapi.115.com/offine/downpath",{capability:"account.status",scope:t.scope})).data;return Object.freeze({authenticated:!!(a?.state&&a?.data?.length)})},async searchFiles(t,s={}){let a=new URL("https://webapi.115.com/files/search");a.searchParams.set("search_value",t),a.searchParams.set("offset",String(s.offset??0)),a.searchParams.set("limit",String(s.limit??50));let r=await e(a.href,{capability:"file.search",scope:s.scope,force:s.force});return Ou(r.data)},async submit(t,s={}){if(!/^magnet:/i.test(t)&&!/^ed2k:/i.test(t))throw new D("UNSUPPORTED","Unsupported offline URL",{source:"one115"});let r=(await e(`https://115.com/?ct=offline&ac=space&_=${Date.now()}`,{capability:"offline.submit",scope:s.scope})).data;if(!r?.sign)throw new D("AUTH_REQUIRED","115 未登录或离线空间信息获取失败",{source:"one115"});let i=new URLSearchParams({url:t,wp_path_id:s.folderId||"",uid:String(r.uid||""),sign:r.sign,time:String(r.time||"")}).toString(),n=await e("https://115.com/web/lixian/?ct=lixian&ac=add_task_url",{capability:"offline.submit",scope:s.scope,method:"POST",body:i,responseType:"text",headers:{"Content-Type":"application/x-www-form-urlencoded"}}),l=Mu(n.data);if(!l||l.state===!1||l.state===0){let c=String(l?.error_msg||l?.error||l?.msg||"115 离线任务创建失败"),h=Bu(c);throw new D(h,c,{source:"one115",details:{state:l?.state??null}})}if(l.state!==!0&&l.state!==1)throw new D("INVALID_RESPONSE","115 未返回明确的离线任务创建成功状态",{source:"one115"});return Object.freeze({success:!0,taskId:String(l.task_id||l.info_hash||"")})},async renameFile(t,s,a={}){let r=new URLSearchParams({fid:t,file_name:s}).toString(),n=(await e("https://webapi.115.com/files/edit",{capability:"file.rename",scope:a.scope,method:"POST",body:r,responseType:"json",headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;if(!n||n.state===!1||n.state===0)throw new D("OPERATION_FAILED",String(n?.error||n?.error_msg||"115 重命名失败"),{source:"one115"});return Object.freeze({success:!0})},getPlayUrl(t){return t?.videoId?`https://115.com/?ct=play&pickcode=${encodeURIComponent(t.videoId)}`:null}})}d(Uu,"createOne115Adapter");var yd=W({id:"one115",trustClass:"builtin-public",hosts:["115.com"],capabilities:["account.status","file.search","file.rename","offline.submit"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Uu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"account.status":"none","file.search":"none","file.rename":"none","offline.submit":"none"},quality:"silver"});var zu=Object.freeze({trustClass:"builtin-public",hosts:["123pan.com"]});function jd(o){let e=new Uint32Array(256);for(let s=0;s<256;s+=1){let a=s;for(let r=0;r<8;r+=1)a=a&1?3988292384^a>>>1:a>>>1;e[s]=a}let t=4294967295;for(let s=0;s>>8;return(t^4294967295)>>>0}d(jd,"crc32");function Fu(){let o=new Uint32Array(1);return crypto.getRandomValues(o),o[0]%1e7}d(Fu,"secureNonce");function Vu(o,e={}){let t=["a","d","e","f","g","h","l","m","y","i","j","n","o","p","k","q","r","s","t","u","b","c","v","w","s","z"],s=e.nonce??Fu(),a=e.now??new Date,r=new Date(a.getTime()+6e4*a.getTimezoneOffset()+288e5),n=[...`${r.getFullYear()}${String(r.getMonth()+1).padStart(2,"0")}${String(r.getDate()).padStart(2,"0")}${String(r.getHours()).padStart(2,"0")}${String(r.getMinutes()).padStart(2,"0")}`].map(p=>t[Number(p)]).join(""),l=jd(n),c=Math.floor(r.getTime()/1e3),h=new URL(o),u=jd(`${c}|${s}|${h.pathname}|web|3|${l}`);return h.searchParams.set(String(l),`${c}-${s}-${u}`),h.href}d(Vu,"signPan123Url");function Sd(o){if(typeof o!="string")return o;try{return JSON.parse(o)}catch(e){throw new D("PARSE_ERROR","123 云盘响应不是有效 JSON",{source:"pan123",cause:e})}}d(Sd,"parsePayload");function xd(o,e){if(!o||typeof o!="object")throw new D("INVALID_RESPONSE",`123 云盘${e}响应无效`,{source:"pan123"});if(o.code===0)return o;let t=String(o.message||o.msg||`${e}失败`);throw/token is expired|unauthorized|登录|授权/i.test(t)?new D("AUTH_REQUIRED",t,{source:"pan123"}):new D("INVALID_RESPONSE",t,{source:"pan123"})}d(xd,"assertSuccess");function qu(o,e={}){let t=d(async(s,a,r,i,n)=>{let l=Vu(`https://yun.123pan.com${s}`,{now:e.now?.(),nonce:e.nonce?.()});return o.request({providerId:"pan123",capability:n,method:"POST",url:l,body:JSON.stringify(a),responseType:"json",timeout:e.getTimeout?.()??5e3,headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`,"App-Version":"3",platform:"web",Origin:"https://yun.123pan.com",Referer:"https://yun.123pan.com/"},urlPolicy:zu},i)},"request");return Object.freeze({contracts:["OfflineResolvedResource","OfflineSubmission"],homeUrl:"https://yun.123pan.com",async resolve(s,a={}){let{token:r,scope:i}=a;if(!r)throw new D("AUTH_REQUIRED","尚未同步 123 授权",{source:"pan123"});let n=await t("/b/api/v2/offline_download/task/resolve",{urls:s},r,i,"offline.resolve"),l=xd(Sd(n.data),"解析"),c=l.data?.list?.[0];if(!c?.id||!Array.isArray(c.files))throw new D("INVALID_RESPONSE","123 云盘解析结果缺少资源文件",{source:"pan123"});return Object.freeze({id:c.id,files:Object.freeze(c.files.map(h=>Object.freeze({id:h.id,size:Number(h.size||0)})))})},async submitResolved(s,a={}){let{token:r,scope:i}=a;if(!r)throw new D("AUTH_REQUIRED","尚未同步 123 授权",{source:"pan123"});if(!s?.id||!Array.isArray(s.files)||s.files.length===0)throw new D("INVALID_RESPONSE","没有可建立离线的文件",{source:"pan123"});let n=s.files.map(h=>h.id),l=s.files.reduce((h,u)=>h+Number(u.size||0),0),c=await t("/b/api/v2/offline_download/task/submit",{resource_list:[{resource_id:s.id,select_file_id:n}]},r,i,"offline.submit");return xd(Sd(c.data),"提交"),Object.freeze({fileCount:n.length,totalSize:l})},async submit(s,a={}){let r=await this.resolve(s,a);return this.submitResolved(r,a)}})}d(qu,"createPan123Adapter");var kd=W({id:"pan123",trustClass:"builtin-public",hosts:["123pan.com"],capabilities:["offline.resolve","offline.submit"],requires:[y.http,y.settings],createClient:d(o=>Object.freeze({http:o[y.http],settings:o[y.settings]}),"createClient"),createAdapter:d(o=>qu(o.http,{getTimeout:d(()=>Number(o.settings.snapshot().httpTimeout??5e3),"getTimeout")}),"createAdapter"),createHostAdapter:null,cachePolicy:{"offline.resolve":"none","offline.submit":"none"},quality:"silver"});function Hu(){return Object.freeze({contracts:["Subtitle"],detailUrl(o){let e=String(o?.carNum||"").trim();if(!e)return null;let t=new URL("/index.php","https://subtitlecat.com");return t.searchParams.set("search",e),t.href}})}d(Hu,"createSubtitleCatAdapter");var Cd=W({id:"subtitlecat",trustClass:"builtin-public",hosts:["subtitlecat.com"],capabilities:["subtitle.search"],requires:[],createClient:d(()=>Object.freeze({id:"subtitlecat"}),"createClient"),createAdapter:d(()=>Hu(),"createAdapter"),createHostAdapter:null,cachePolicy:"none",quality:"bronze"});var _d=Object.freeze([Object.freeze({id:"u9a9",name:"U9A9",type:"网页来源",domain:"u9a9.com",baseUrl:"https://u9a9.com",priority:20,enabled:!0,searchPath:d(o=>`/?type=2&search=${encodeURIComponent(o)}`,"searchPath")}),Object.freeze({id:"u3c3",name:"U3C3",type:"网页来源",domain:"u3c3.com",baseUrl:"https://u3c3.com",priority:30,enabled:!0,searchPath:d(o=>`/?search2=a8lr16lo&search=${encodeURIComponent(o)}`,"searchPath")}),Object.freeze({id:"sukebei",name:"Sukebei",type:"网页来源",domain:"sukebei.nyaa.si",baseUrl:"https://sukebei.nyaa.si",priority:40,enabled:!0,searchPath:d(o=>`/?f=0&c=0_0&q=${encodeURIComponent(o)}`,"searchPath")}),Object.freeze({id:"btsow",name:"BTSOW",type:"API 来源",domain:"btsow.lol",baseUrl:"https://btsow.lol",priority:50,enabled:!0,searchPath:d(o=>`/search/${encodeURIComponent(o)}`,"searchPath")})]);function $d(o,e){let t=o,s=String(t?.magnet||"");return s.startsWith("magnet:")?Object.freeze({title:String(t.title||""),magnet:s,size:String(t.size||""),date:String(t.date||""),seeders:Number(t.seeders)||0,leechers:Number(t.leechers)||0,source:e,files:Object.freeze([])}):null}d($d,"normalizeMagnet");function Wu(o,e,t){if(typeof o!="string")throw new D("INVALID_RESPONSE","磁力来源响应不是 HTML",{source:t});let s=new DOMParser().parseFromString(o,"text/html"),a=`${s.title} ${s.body?.textContent||""}`;if(/Just a moment|cf-chl-|Cloudflare/i.test(a))throw new D("CF_BLOCKED","磁力来源被 Cloudflare 拦截",{source:t});return Object.freeze([...s.querySelectorAll(".torrent-list tbody tr")].flatMap(r=>{if(r.textContent?.includes("置顶"))return[];let i=r.querySelector("td:nth-child(2) a"),n=i?.getAttribute("title")||i?.textContent?.trim()||"";if(!n.toLowerCase().includes(e.toLowerCase()))return[];let l=$d({title:n,magnet:r.querySelector('td:nth-child(3) a[href^="magnet:"]')?.getAttribute("href"),size:r.querySelector("td:nth-child(4)")?.textContent?.trim(),date:r.querySelector("td:nth-child(5)")?.textContent?.trim(),seeders:r.querySelector("td:nth-child(6)")?.textContent?.trim(),leechers:r.querySelector("td:nth-child(7)")?.textContent?.trim()},t);return l?[l]:[]}))}d(Wu,"parseTorrentSource");function Ju(o){let e=o;if(typeof e=="string")try{e=JSON.parse(e)}catch(s){throw new D("INVALID_RESPONSE","BTSOW 返回了无效 JSON",{source:"btsow",cause:s})}let t=e?.data;if(!Array.isArray(t))throw new D("INVALID_RESPONSE","BTSOW 响应缺少结果数组",{source:"btsow"});return Object.freeze(t.flatMap(s=>{let a=Number(s.lastUpdateTime),r=Number.isFinite(a)?new Date(1e3*a).toISOString().slice(0,10):"",i=$d({title:s.name,magnet:`magnet:?xt=urn:btih:${s.hash}`,size:`${(Number(s.size)/1073741824).toFixed(2)} GB`,date:r},"btsow");return i?[i]:[]}))}d(Ju,"parseBtsowSource");function Ku(o){let e=d(t=>_d.find(s=>s.id===t),"find");return Object.freeze({contracts:["Magnet","MagnetSource"],getSources:d(()=>Object.freeze(_d.map(t=>Object.freeze({id:t.id,name:t.name,type:t.type,domain:t.domain,baseUrl:t.baseUrl,priority:t.priority,enabled:t.enabled}))),"getSources"),targetUrl(t,s,a={}){let r=e(t);if(!r)throw new D("UNSUPPORTED",`未知磁力来源:${t}`,{source:"torrent-sources"});return`${new URL(a.baseUrl||r.baseUrl).origin}${r.searchPath(s)}`},async search(t,s,a={}){let r=e(t);if(!r)throw new D("UNSUPPORTED",`未知磁力来源:${t}`,{source:"torrent-sources"});let i=new URL(a.baseUrl||r.baseUrl).origin,l=new URL(i).hostname!==r.domain?{trustClass:"custom-public",expectedOrigin:i}:{trustClass:"builtin-public",hosts:[r.domain],expectedOrigin:i};if(r.id==="btsow"){let u=await o.request({capability:"magnet.search",providerId:"magnet:btsow",method:"POST",url:`${i}/search`,body:JSON.stringify([{search:s},50,1]),headers:{"Content-Type":"application/json"},responseType:"json",urlPolicy:l},a.scope);return Ju(u.data)}let c=`${i}${r.searchPath(s)}`,h=await o.request({capability:"magnet.search",providerId:`magnet:${r.id}`,method:"GET",url:c,responseType:"text",urlPolicy:l},a.scope);return Wu(h.data,s,r.id)}})}d(Ku,"createTorrentSourcesAdapter");var Td=W({id:"torrent-sources",trustClass:"builtin-public",hosts:["u9a9.com","u3c3.com","sukebei.nyaa.si","btsow.lol"],capabilities:["magnet.search"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Ku(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"magnet.search":"source-configured"},quality:"silver"});function St(o){return o.replace(/\s+/g," ").trim()}d(St,"compact");function Ad(o,e){let t=new DOMParser().parseFromString(o,"text/html"),s=St(t.querySelector('a[title="誕生日"]')?.closest("tr")?.querySelector("td")?.textContent??""),a=[...t.querySelectorAll("th")].find(g=>g.textContent?.includes("現年齢"))?.parentElement?.querySelector("td"),r=t.querySelector('a[title="身長"]')?.closest("tr")?.querySelector("td"),i=t.querySelector('a[title="体重"]')?.closest("tr")?.querySelector("td"),n=t.querySelector('a[title="スリーサイズ"]')?.closest("tr")?.querySelector("td"),l=[...t.querySelectorAll("th")].find(g=>g.textContent?.includes("ブラサイズ"))?.nextElementSibling;if(!s&&!r&&!n)throw new TypeError("Wikipedia actress information is missing");let c=Number.parseInt(St(a?.textContent??""),10),h=St(r?.textContent??"").split(" ")[0],u=St(i?.textContent??"").split("/"),p=St(u.at(-1)??"").replace(/^―\s*kg$/,"");return Object.freeze({birthday:s,age:Number.isFinite(c)?`${c}岁`:"",height:h&&!h.endsWith("cm")?`${h}cm`:h,weight:p,threeSizeText:St(n?.textContent??"").replace("cm","").trim(),braSize:St(l?.textContent??""),url:new URL(e).href})}d(Ad,"parseWikipediaActressInfo");function Gu(o){return Object.freeze({contracts:["ActressInfo"],profileUrl(e){return new URL(`/wiki/${encodeURIComponent(String(e))}`,"https://ja.wikipedia.org").href},async lookup(e,t={}){let s=this.profileUrl(e),a=await o.request({providerId:"wikipedia",capability:"person.actress-info",method:"GET",url:s,responseType:"text",timeout:15e3,urlPolicy:{trustClass:"builtin-public",hosts:["ja.wikipedia.org"]}},t.scope);try{return Ad(a.data,a.finalUrl||s)}catch(r){if(r instanceof TypeError&&/actress information is missing/.test(r.message))return null;throw r}}})}d(Gu,"createWikipediaAdapter");var Pd=W({id:"wikipedia",trustClass:"builtin-public",hosts:["ja.wikipedia.org"],capabilities:["person.actress-info"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Gu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"person.actress-info":ke.externalDetail},quality:"silver"});function Rd(o){if(!o||typeof o!="object"||!Array.isArray(o.data))throw new D("INVALID_RESPONSE","迅雷字幕响应结构无效",{source:"xunlei"});return Object.freeze(o.data.flatMap(e=>{try{let t=new URL(String(e?.url??""));if(t.protocol!=="https:")return[];let s=String(e?.ext??"").toLowerCase().replace(/^\./,"");return s?[Object.freeze({name:String(e?.name??""),extension:s,url:t.href,providerId:"xunlei"})]:[]}catch{return[]}}))}d(Rd,"parseXunleiSubtitles");var Id=["xunlei.com"];function Qu(o){return Object.freeze({contracts:["Subtitle"],async search(e,t={}){let s=String(e.carNum??"").trim();if(!s)return[];let a=new URL("https://api-shoulei-ssl.xunlei.com/oracle/subtitle");a.searchParams.set("gcid",""),a.searchParams.set("cid",""),a.searchParams.set("name",s);let r=await o.request({providerId:"xunlei",capability:"subtitle.search",method:"GET",url:a.href,responseType:"json",urlPolicy:{trustClass:"builtin-public",hosts:Id}},t.scope);return Rd(r.data)},async download(e,t={}){let s=new URL(String(e.url??"")),a=await o.request({providerId:"xunlei",capability:"subtitle.download",method:"GET",url:s.href,responseType:"text",urlPolicy:{trustClass:"custom-public"}},t.scope);if(typeof a.data!="string")throw new TypeError("迅雷字幕正文不是文本");return a.data}})}d(Qu,"createXunleiAdapter");var Ed=W({id:"xunlei",trustClass:"builtin-public",hosts:Id,capabilities:["subtitle.search","subtitle.download"],requires:[y.http],createClient:d(o=>Object.freeze({http:o[y.http]}),"createClient"),createAdapter:d(o=>Qu(o.http),"createAdapter"),createHostAdapter:null,cachePolicy:{"subtitle.search":"public-1d","subtitle.download":"public-1d"},quality:"silver"});var Dd=Object.freeze([Jc,Yc,ed,rd,nd,cd,ld,dd,hd,gd,vd,bd,wd,yd,kd,Cd,Td,Pd,Ed]);function Yu(o,e){let t=o.close;o.close=function(a){let r=t.call(this,a);return e?.releaseEscClose?.(a),setTimeout(()=>{let i=document.querySelectorAll(".layui-layer-shade").length;document.documentElement.style.overflow=i>0?"hidden":""},10),r};let s=o.open;o.open=function(a={}){a=kt(a,e);let r=a.success;return s.call(this,{...a,success(i,n){typeof r=="function"&&r.call(this,i,n),e.setupEscClose(n)}})}}d(Yu,"patchLayerRuntime");function Zu(o){for(let e of["https://cdn.jsdelivr.net/npm/layui-layer@1.0.9/layer.min.css","https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.css","https://cdn.jsdelivr.net/npm/viewerjs@1.11.1/dist/viewer.min.css","https://cdn.jsdelivr.net/npm/tabulator-tables@6.3.1/dist/css/tabulator_semanticui.min.css"])o.importResource(e)}d(Zu,"importVendorStyles");async function Xu(o){let e=await o.getSetting("disabledPlugins","[]"),t=Ge(e),s=$t(t);return{migrated:s,needsMigration:JSON.stringify(t)!==JSON.stringify(s)}}d(Xu,"readDisabledPluginSettings");async function ep(o,e,t,s,a,r,i=null){await o.update(n=>{let l=Ge(typeof n.disabledPlugins=="string"?n.disabledPlugins:"[]"),c=$t(l);if(JSON.stringify(l)!==JSON.stringify(c)&&(n.disabledPlugins=JSON.stringify(c)),t.needsOrigin){let h=new Set(Array.isArray(n.trustedLocalOrigins)?n.trustedLocalOrigins:[]);for(let u of t.origins)h.add(u);n.trustedLocalOrigins=[...h]}t.needsNotice&&(n.localOriginTrustNoticeV1=!0),Object.prototype.hasOwnProperty.call(n,"enableLoadScreenShot")||(n.enableLoadScreenShot="yes"),Object.prototype.hasOwnProperty.call(n,"enableScreenSvg")||(n.enableScreenSvg=n.enableLoadScreenShot??"yes"),n.sortMethod==null&&["default","rateCount","date"].includes(s||"")&&(n.sortMethod=s),n.foldCategoryCollapsed==null&&["yes","no"].includes(a||"")&&(n.foldCategoryCollapsed=a==="yes"),n.videoMuted==null&&["yes","no"].includes(r||"")&&(n.videoMuted=r==="yes");for(let h of i?.cleanup?.settingKeys||[])n[h]===i.cleanup.settingValues?.[h]&&delete n[h]})}d(ep,"persistBootstrapMigration");async function tp(o){let e=await o.getSetting(),t=new Set(Array.isArray(e.trustedLocalOrigins)?e.trustedLocalOrigins:[]),s=null;try{e.webDavUrl&&(s=new URL(e.webDavUrl).origin)}catch{}return s&&!t.has(s)?(t.add(s),{origins:[...t],notice:`已按现有 WebDAV 配置授权本地来源:${s}`,needsOrigin:!0}):s&&!e.localOriginTrustNoticeV1?{origins:[...t],notice:`WebDAV 仅信任精确来源:${s}`,needsNotice:!0}:{origins:[...t],notice:null}}d(tp,"resolveLocalOrigins");async function Nd(){try{if(Ct(window.location).isJavDB){let R=Io(window.location);if(R)return void window.location.replace(R)}let o=performance.now(),e=globalThis.__jhsBrowserDiagnostics,t=d(R=>e&&((e.bootstrapPhases||(e.bootstrapPhases={}))[R]=performance.now()-o),"markPhase"),s=Eo(window.location),a=cl(),r=ol(),{utils:i,gmHttp:n,storageManager:l,stateService:c}=nl(r);t("legacy-runtime"),Object.assign(globalThis,{utils:i,gmHttp:n,storageManager:l,stateService:c,jhsEventBus:r}),["blacklist-rules-changed","filter-rules-changed","legacy-refresh"].forEach((R=>r.on(R,(()=>l._invalidateCache())))),r.on("car-state-changed",()=>l._invalidateCache(l.car_list_key)),Yu(a.layer,i),await Promise.resolve(),Zu(i),t("pre-settings");let h=await Xu(l),u=h.migrated,p=await tp(l),g=new $s,m=new _s,f=M?g:B?m:null,v=f?.detectRoute()??"other",b=Vc({gmRequest:globalThis.GM_xmlhttpRequest,gmGetValue:globalThis.GM_getValue,gmSetValue:globalThis.GM_setValue,gmDeleteValue:globalThis.GM_deleteValue,legacyHttp:n,legacyStorage:l,eventBus:r,storageForage:l.forage,localStorage:globalThis.localStorage,layer:a.layer,stateService:c,hostAdapter:f,hostAdapters:{javdb:g,javbus:m},site:s.site,route:v,disabled:u,localOrigins:p.origins});t("context"),qo(b.services.styles,Ho()),Object.assign(globalThis,{settingsService:b.services.settings,credentialService:b.services.credential}),await b.services.settings.load(),t("settings-load");let w=await b.services.credential.migrateLegacy(b.services.settings,{deferCleanup:!0});b.services.profile.start();let S=localStorage.getItem("jhs_sortMethod"),j=localStorage.getItem("jhs_foldCategory"),k=localStorage.getItem("jhs_videoMuted");w.cleanup=await b.services.credential.validateLegacyCleanup(w.cleanup),await ep(b.services.settings,h,p,S,j,k,w),await b.services.credential.cleanupLegacyPageStorage(w.cleanup?.pageKeys,b.services.settings),t("settings-migration");let x=ll(b.rootScope,{clogMsgCount:b.services.settings.snapshot().clogMsgCount});t("logger"),Uo(b.rootScope),Fo(b.rootScope),t("theme-ui"),b.services.diagnostics.setBrowserMetadata({userAgent:navigator.userAgent,platform:navigator.platform,...globalThis.__jhsBrowserTestMetadata??{}}),Object.assign(globalThis,x),w.issues?.length&&x.show.info("部分旧凭证未能安全迁移,已保留原数据,请重新保存对应凭证"),p.notice&&x.show.info(p.notice);let _=new ys({diagnostics:b.services.diagnostics});for(let R of Dd)b.registries.integrations.register(R);for(let R of bl)b.registries.features.register(R);return Lc(_,b.registries.features,s.site),t("registry"),Mc({pluginManager:_,utils:i,gmHttp:n,storageManager:l,stateService:c,jhsEventBus:r,clog:x.clog,show:x.show,loading:x.loading},globalThis.unsafeWindow),window.isDetailPage=v==="detail",window.isListPage=v==="list",await b.registries.features.start(),t("feature-runtime"),await ws(l),await l.getReviewFilterKeywordList(),await c.recoverPendingTransaction(),t("data-prepare"),await Promise.all([_.processCss(),Promise.resolve(Ht(b.services.settings.snapshot().themeMode))]),t("plugin-css"),M&&/(^|;)\s*locale\s*=\s*en\s*($|;)/i.test(document.cookie)&&x.show.error("请切换到中文语言下才可正常使用本脚本",{duration:-1}),await _.processPlugins(),t("plugin-runtime"),t("first-ready"),t("total"),b}catch(o){throw o instanceof D?o:new D("BOOTSTRAP_FAILED",o instanceof Error?o.message:"JHS 启动失败",{source:"bootstrap",cause:o})}}d(Nd,"bootstrapJhs");function Ld(o){if(console.error("[JHS] bootstrap failed:",o),globalThis.show?.error)return globalThis.show.error(o?.message||"JHS 启动失败",{duration:-1});let e=document.createElement("div");e.id="jhs-bootstrap-error",e.setAttribute("role","alert"),e.textContent=`JHS 启动失败:${o?.message||"未知错误"}`,Object.assign(e.style,{position:"fixed",inset:"12px 12px auto",zIndex:"2147483647",padding:"12px",background:"#7f1d1d",color:"white"}),document.documentElement.append(e)}d(Ld,"mountBootstrapError");Nd().catch(Ld);})(); diff --git a/README.md b/README.md index 729e950d..561c705d 100644 --- a/README.md +++ b/README.md @@ -19,22 +19,21 @@ JHS 将作品状态、演员收藏、新作追踪、外部检索、媒体预览 > 本项目仅提供网页信息整理与效率增强能力。请遵守所在地法律、目标网站条款及第三方服务规则,并仅处理你有权访问的内容。 -## 6.5.1 更新 +## 6.5.2 更新 -当前正式版为 **6.5.1**(2026-09-25)。这次主要修复: +当前正式版为 **6.5.2**(2026-10-16)。这次主要更新: -- **榜单回到原生页面**:JavDB 分类影片榜(Movies)、热播(Playback)和 TOP250 各有自己的入口与筛选条件;保留原生类别、周期、年份、排名、分页和链接。旧版榜单书签会迁移到有效页面。 -- **榜单操作范围更清楚**:本地排序只作用于当前榜单,恢复默认顺序会回到原生排名;TOP250 字幕按钮只过滤当前已加载卡片的中字磁链标记,批量操作也只处理当前榜单页。 -- **FC2 来源分明**:JavDB 的 FC2 分类浏览与 FC2 排行榜仍是不同入口;123AV FC2 片库作为标明来源的外部目录,放在分类浏览区域。 -- **WebDAV 超时修复**:每次 WebDAV 网络请求单独使用 10 秒超时,导出与加密不计入期限;备份诊断分别记录本地准备、建目录与上传耗时。延长等待期限不会提高传输速度。 +- **全部未下载筛选**:“更多筛选”可以查看所有未下载且未被屏蔽的作品,包含待鉴定、收藏和已看内容。 +- **默认选项卡更完整**:设置可选择全部筛选,保留“屏蔽项”,加入“全部未下载”等智能筛选,下次进入列表页生效。 +- **新作品保持浏览位置**:打开作品后,已浏览卡片渐隐移除,后续作品自动补位;保留筛选、滚动位置和其他选择项。连续移除、切换筛选和关闭重开弹窗也能正确处理。 -完整内容见 [6.5.1 更新记录](https://github.com/Teamper/JHS/releases/tag/v6.5.1)。 +完整内容见 [6.5.2 更新记录](CHANGELOG.md#652---2026-10-16)。 ## 功能概览 | 分类 | 主要能力 | | --- | --- | -| 状态管理 | 收藏、已下载、已观看和主动屏蔽可独立组合;支持待鉴定、屏蔽项、智能筛选、跨页批量收藏和标记已下载 | +| 状态管理 | 收藏、已下载、已观看和主动屏蔽可独立组合;支持待鉴定、屏蔽项、全部未下载等智能筛选、跨页批量收藏和标记已下载 | | 演员管理 | 收藏演员、演员黑名单、演员信息补充、收藏同步与已收藏演员高亮 | | 新作追踪 | 按规范化番号聚合演员新作,支持搜索、类别/VR/状态/决策筛选、多选状态、忽略、暂缓、恢复及“从新作列表移除” | | 内容过滤 | 手动屏蔽、关键词和演员规则命中的作品统一在“屏蔽项”中查看;自动过滤不会改写作品状态 | @@ -87,6 +86,12 @@ JHS 将作品状态、演员收藏、新作追踪、外部检索、媒体预览 移动端可从右下角悬浮菜单访问鉴定、新作品、黑名单、排序、筛选和设置。 +启用“浏览后自动移除新作品标记”后,新作品列表中的已浏览卡片会渐隐移除,并由后续作品补位,保留浏览位置、筛选和其他选择项;最后一页移空时回到上一页,全部移空时显示空状态;减少动态效果时直接完成补位。 + +列表“更多筛选”中的“全部未下载”显示所有未标记为已下载且未被屏蔽的作品,包括待鉴定、收藏和已看内容。 + +设置中的“默认显示选项卡”可选择全部筛选,包括“屏蔽项”和“全部未下载”等智能筛选,下次进入列表页生效。 + 批量操作前请确认提示中的范围。普通列表中的“全部”仍会隐藏屏蔽项;**跨页批量操作选择“全部”时会包含屏蔽项**,确认框会明确说明。 ## 数据、备份与隐私 diff --git a/docs/sleazyfork.zh-CN.md b/docs/sleazyfork.zh-CN.md index 0e2c4185..09c7f07e 100644 --- a/docs/sleazyfork.zh-CN.md +++ b/docs/sleazyfork.zh-CN.md @@ -7,28 +7,28 @@ JHS(JAV Helper Suite)是一款面向 JavDB、JavBus 的 Tampermonkey 用户脚本,用于整理作品状态、追踪演员新作、聚合资源与媒体信息,并提供统一离线、备份和统计工具。 -> 当前稳定版本:**6.5.1**(2026-09-25) +> 当前稳定版本:**6.5.2**(2026-10-16) > > [GitHub 项目](https://github.com/Teamper/JHS) · [完整更新记录](https://github.com/Teamper/JHS/blob/main/CHANGELOG.md) · [问题反馈](https://github.com/Teamper/JHS/issues) -## 6.5.1 更新了什么 +## 6.5.2 更新了什么 -- **榜单入口分清楚了**:JavDB 的分类影片榜(Movies)、热播(Playback)和 TOP250 保留各自的原生页面、排名与筛选;旧版榜单书签会迁移到有效页面。 -- **榜单筛选有明确范围**:排序和批量操作只作用于当前榜单页;TOP250 的字幕按钮只筛选当前已加载卡片是否带中字磁链标记。 -- **FC2 片库标明来源**:JavDB 的 FC2 分类浏览、FC2 排行榜和外部 123AV FC2 片库分别保留各自入口。 -- **WebDAV 请求可等 10 秒**:建目录、上传等网络请求分别计时,导出与加密不占用网络请求期限;备份日志可区分本地准备与网络阶段。超时调整不会提高上传速度。 +- **全部未下载筛选**:“更多筛选”新增“全部未下载”,排除屏蔽项和已下载作品,保留未下载的待鉴定、收藏和已看内容。 +- **默认选项卡更完整**:设置支持全部筛选,保留“屏蔽项”,加入“全部未下载”等智能筛选,下次进入列表页生效。 +- **新作品保持浏览位置**:打开作品后,卡片渐隐移除,后续作品自动补位;保留筛选、浏览位置和其他选择项,连续移除、快速切换筛选和关闭重开弹窗也能正确处理。 -完整版本记录见 [6.5.1 更新说明](https://github.com/Teamper/JHS/releases/tag/v6.5.1)。 +完整版本记录见 [6.5.2 更新说明](../CHANGELOG.md#652---2026-10-16)。 ## 主要功能 ### 作品状态与列表管理 - 收藏、已下载、已观看和主动屏蔽可以独立组合,不会互相覆盖。 -- 提供“待鉴定”工作流,以及收藏未下载、收藏未观看、下载未观看、最近 7 天等智能筛选。 +- 提供“待鉴定”工作流,以及全部未下载、收藏未下载、收藏未观看、下载未观看、最近 7 天等智能筛选。“全部未下载”排除屏蔽项和已下载内容,保留未下载的收藏、已看和待鉴定内容。 - 手动屏蔽、关键词和演员过滤统一收入口径明确的“屏蔽项”,不会混入普通列表。 - 支持自动翻页、跨页批量收藏和标记已下载、鉴定记录、状态撤销和跨标签页同步。 - 桌面使用快捷筛选;移动端通过右下角悬浮菜单访问鉴定、筛选、排序和常用工具。 +- 设置中的“默认显示选项卡”支持全部筛选,包括“屏蔽项”和“全部未下载”等智能筛选,下次进入列表页生效。 ### 演员与新作品 @@ -36,6 +36,7 @@ JHS(JAV Helper Suite)是一款面向 JavDB、JavBus 的 Tampermonkey 用户 - 定时检查收藏演员的新作品,并合并相同番号;协调多个标签页的检查任务,减少重复请求,失败后稍后重试。 - 新作品页面支持按关键词、类别、VR、作品状态和处理方式组合筛选,也可以批量标记、忽略、暂缓、恢复或移出列表。 - 搜索、筛选、排序和翻页更加流畅,封面只在翻到对应页面时加载。批量操作失败的项目会继续保持选中,方便再次处理。 +- 启用“浏览后自动移除新作品标记”后,已浏览卡片会渐隐移除并由后续作品补位,保留浏览位置、筛选和其他选择项;最后一页移空时回到上一页,全部移空时显示空状态;减少动态效果时直接补位。 - 新作品、黑名单和设置面板会显示任务运行状态、上次完成时间与下次检查时间。 ### 磁力、字幕与媒体 diff --git a/package-lock.json b/package-lock.json index 1cfd17eb..8ac83bcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jhs-userscript", - "version": "6.5.1", + "version": "6.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jhs-userscript", - "version": "6.5.1", + "version": "6.5.2", "license": "MIT", "devDependencies": { "esbuild": "^0.28.0", diff --git a/package.json b/package.json index a82b48a0..cd48bada 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jhs-userscript", - "version": "6.5.1", + "version": "6.5.2", "description": "JAV Helper Suite for JavDB and JavBus", "private": true, "license": "MIT", diff --git a/src/app/settings-catalog.js b/src/app/settings-catalog.js index d424fe56..787fb82f 100644 --- a/src/app/settings-catalog.js +++ b/src/app/settings-catalog.js @@ -9,6 +9,7 @@ * changes apply immediately through the feature owner's mount/unmount/reconfigure. */ import { parseBooleanSetting } from "../core/feature-helpers.js"; +import { DEFAULT_QUICK_FILTER_OPTIONS } from "../features/list/list-filters.js"; /** @param {import("./settings-registry.js").SettingsRegistry} registry */ export function registerDefaultSettings(registry) { @@ -68,10 +69,7 @@ export function registerDefaultSettings(registry) { key: "defaultQuickFilterTab", owner: "ListPageFeature", label: "列表默认筛选", description: "进入列表页时默认选中的筛选标签,修改后下次进入列表生效。", type: "select", defaultValue: "waitCheck", effect: "nextNavigation", surfaces: ["full"], - options: Object.freeze([ - { value: "all", label: "全部" }, { value: "waitCheck", label: "待鉴定" }, { value: "favorite", label: "收藏" }, - { value: "hasDown", label: "下载" }, { value: "hasWatch", label: "已看" }, { value: "blockedItems", label: "屏蔽项" }, - ]), + options: DEFAULT_QUICK_FILTER_OPTIONS, }); // ---- 详情 ---- diff --git a/src/features/list/list-filters.js b/src/features/list/list-filters.js index 31a2dbc5..65eb8d1c 100644 --- a/src/features/list/list-filters.js +++ b/src/features/list/list-filters.js @@ -7,7 +7,7 @@ import { hasAnyState } from "../../core/state-model.js"; export const QUICK_FILTER_LABELS = Object.freeze({ all: "全部", waitCheck: "待鉴定", favorite: "收藏", hasDown: "下载", hasWatch: "已看", - blockedItems: "屏蔽项", favoriteUndownloaded: "收藏未下载", favoriteUnwatched: "收藏未观看", + blockedItems: "屏蔽项", undownloaded: "全部未下载", favoriteUndownloaded: "收藏未下载", favoriteUnwatched: "收藏未观看", downloadedUnwatched: "下载未观看", recent7d: "最近 7 天" }); @@ -15,7 +15,9 @@ export const QUICK_FILTER_LABELS = Object.freeze({ /** @type {ReadonlyArray} */ export const PRIMARY_QUICK_FILTERS = Object.freeze([ "all", "waitCheck", "favorite", "hasDown", "hasWatch" ]); /** @type {ReadonlyArray} */ -export const SECONDARY_QUICK_FILTERS = Object.freeze([ "blockedItems", "favoriteUndownloaded", "favoriteUnwatched", "downloadedUnwatched", "recent7d" ]); +export const SECONDARY_QUICK_FILTERS = Object.freeze([ "blockedItems", "undownloaded", "favoriteUndownloaded", "favoriteUnwatched", "downloadedUnwatched", "recent7d" ]); +export const DEFAULT_QUICK_FILTER_OPTIONS = Object.freeze([ ...PRIMARY_QUICK_FILTERS, ...SECONDARY_QUICK_FILTERS ] + .map(value => Object.freeze({ value, label: QUICK_FILTER_LABELS[value] }))); const VALID_QUICK_FILTERS = new Set([ ...PRIMARY_QUICK_FILTERS, ...SECONDARY_QUICK_FILTERS ]); /** @param {unknown} value @returns {QuickFilterKey} */ @@ -40,7 +42,7 @@ export function matchesQuickFilter(filter, flags, { visibilityReasons = {}, rece if ("favorite" === normalizedFilter) return !!flags.favorite; if ("hasDown" === normalizedFilter) return !!flags.downloaded; if ("hasWatch" === normalizedFilter) return !!flags.watched; - if ("favoriteUndownloaded" === normalizedFilter) return !!flags.favorite && !flags.downloaded; + if ("undownloaded" === normalizedFilter || "favoriteUndownloaded" === normalizedFilter) return !flags.downloaded && ("undownloaded" === normalizedFilter || !!flags.favorite); if ("favoriteUnwatched" === normalizedFilter) return !!flags.favorite && !flags.watched; if ("downloadedUnwatched" === normalizedFilter) return !!flags.downloaded && !flags.watched; return "recent7d" === normalizedFilter && recent; diff --git a/src/main.js b/src/main.js index 17b68d18..150662f6 100644 --- a/src/main.js +++ b/src/main.js @@ -1,7 +1,7 @@ // ==UserScript== // @name JHS // @namespace https://sleazyfork.org/zh-CN/scripts/578503-jhs-ya -// @version 6.5.1 +// @version 6.5.2 // @author JHS Contributors // @description JAV Helper Suite:为 JavDB / JavBus 提供浏览、收藏、筛选、资源检索、数据备份与统计增强。 // @license MIT diff --git a/src/plugins/backup/setting-templates.js b/src/plugins/backup/setting-templates.js index 3ed8d229..5a66d44d 100644 --- a/src/plugins/backup/setting-templates.js +++ b/src/plugins/backup/setting-templates.js @@ -1,6 +1,7 @@ // @ts-check import { L, r } from "../../core/constants.js"; +import { DEFAULT_QUICK_FILTER_OPTIONS } from "../../features/list/list-filters.js"; import { buildQuickSettingsHtml } from "../../ui/settings/setting-control-renderer.js"; /** @@ -134,12 +135,7 @@ export function buildSettingDialogHtml(activePanel, cacheItems) { 默认显示选项卡:
      diff --git a/src/plugins/backup/setting.js b/src/plugins/backup/setting.js index 3416564f..f9751ba5 100644 --- a/src/plugins/backup/setting.js +++ b/src/plugins/backup/setting.js @@ -337,7 +337,7 @@ i(this, "_desktopSettingNavMounted", !1), i(this, "_settingScope", null), i(this selector: "#defaultQuickFilterTab", key: "defaultQuickFilterTab", getValue: () => normalizeQuickFilterKey(root.find("#defaultQuickFilterTab").val()), - setValue: (value) => root.find("#defaultQuickFilterTab").val(String(value ?? "")), + setValue: (value) => root.find("#defaultQuickFilterTab").val(normalizeQuickFilterKey(value)), fallback: "waitCheck", label: "列表默认筛选", }); diff --git a/src/plugins/new-video/new-video.js b/src/plugins/new-video/new-video.js index c104a861..10be1b02 100644 --- a/src/plugins/new-video/new-video.js +++ b/src/plugins/new-video/new-video.js @@ -30,6 +30,7 @@ function aggregateNewVideoRecords(actresses, carMap, decisions, now = Date.now() export class NewVideoPlugin extends BasePlugin { constructor() { super(...arguments), i(this, "currentPage", 1), i(this, "pageSize", 30), i(this, "nvCurrentPage", 1), i(this, "nvPageSize", 60), i(this, "nvFlatListCache", []), i(this, "nvAllItemsMap", new Map), i(this, "nvActressesCache", []), i(this, "nvCarMapCache", new Map), i(this, "nvSortBy", "publishTime_desc"), i(this, "nvSelected", new Set), i(this, "nvDecisionsCache", {}), i(this, "nvCoverCache", new Map), i(this, "nvActorCoverRequests", new Map), i(this, "nvRenderGeneration", 0), i(this, "nvSearchDebounced", null), i(this, "nvInvalidationTimer", null), i(this, "nvWorkspaceReloadPromise", null), i(this, "nvWorkspaceReloadDirty", !1), i(this, "nvWorkspaceMounted", !1), i(this, "nvEventUnsubscribe", null), i(this, "taskStatusUnsubscribe", null), i(this, "nvCoverPreview", null), i(this, "nvWorkspaceRoot", null), i(this, "nvJavDbUrl", ""), i(this, "nvRuleTime", 8760), i(this, "avatarSources", []), i(this, "avatarSourceIndex", 0); + i(this, "nvWorkspaceFullReloadRequested", !1), i(this, "nvPendingRemovals", new Set), i(this, "nvRemovingCards", new Set); } getName() { return "NewVideoPlugin"; @@ -118,7 +119,7 @@ export class NewVideoPlugin extends BasePlugin { } async handle() { this.initializeLocalState(); - this.nvEventUnsubscribe || (this.nvEventUnsubscribe = jhsEventBus.on("new-video-changed", (() => this.scheduleWorkspaceReload()))); + this.nvEventUnsubscribe || (this.nvEventUnsubscribe = jhsEventBus.on("new-video-changed", (payload => this.scheduleWorkspaceReload(payload)))); this.taskStatusUnsubscribe || (this.taskStatusUnsubscribe = jhsEventBus.on("task-status-changed", (() => this.isWorkspaceMounted() && this.renderTaskStatuses()))); await this.showNewVideoCount(); } @@ -130,7 +131,10 @@ export class NewVideoPlugin extends BasePlugin { isWorkspaceMounted() { return this.nvWorkspaceMounted && $(".newVideoToolBox").length > 0; } - scheduleWorkspaceReload() { + scheduleWorkspaceReload(payload = {}) { + const carNums = Array.isArray(payload?.carNums) ? payload.carNums.map(normalizeCarNum).filter(Boolean) : []; + if ([ "browse", "state-handled", "manual" ].includes(payload?.reason) && carNums.length) carNums.forEach(carNum => this.nvPendingRemovals.add(carNum)); + else this.nvWorkspaceFullReloadRequested = !0; this.nvWorkspaceReloadDirty = !0; this.nvInvalidationTimer || (this.nvInvalidationTimer = setTimeout((() => { this.nvInvalidationTimer = null, void this.flushWorkspaceReload(); @@ -140,13 +144,48 @@ export class NewVideoPlugin extends BasePlugin { if (this.nvWorkspaceReloadPromise) return this.nvWorkspaceReloadPromise; return this.nvWorkspaceReloadPromise = (async () => { do { + const fullReload = this.nvWorkspaceFullReloadRequested, removals = new Set(this.nvPendingRemovals); + this.nvWorkspaceFullReloadRequested = !1, this.nvPendingRemovals.clear(); this.nvWorkspaceReloadDirty = !1, await this.showNewVideoCount(); - this.isWorkspaceMounted() && await this.reloadNewVideoWorkspaceData({ preservePage: !0 }); + if (this.isWorkspaceMounted()) { + if (!fullReload && removals.size && this._viewMode === "list" && $("#nv-grid").length) await this.applyNewVideoRemovals(removals); + else await this.reloadNewVideoWorkspaceData({ preservePage: !0 }); + } } while (this.nvWorkspaceReloadDirty); })().catch((error => clog.error("新作品数据刷新失败", error))).finally((() => { this.nvWorkspaceReloadPromise = null; })), this.nvWorkspaceReloadPromise; } + async applyNewVideoRemovals(carNums) { + if (this.nvWorkspaceFullReloadRequested) return; + const generation = this.nvRenderGeneration, container = $("#new-video-list-container"), root = container[0]; + const cards = container.find(".nv-card").filter((_, card) => carNums.has(normalizeCarNum($(card).attr("data-car")))); + carNums.forEach(carNum => { this.nvAllItemsMap.delete(carNum); this.nvSelected.delete(carNum); }); + // Pagination can interrupt the animation; its data must already reflect the committed removal. + this.nvFlatListCache = this.nvFlatListCache.filter(item => !carNums.has(normalizeCarNum(item.carNum))); + this.nvCurrentPageItems = (this.nvCurrentPageItems || []).filter(item => !carNums.has(normalizeCarNum(item.carNum))); + this.nvActressesCache = this.nvActressesCache.map(actress => Array.isArray(actress.newVideoList) ? { + ...actress, newVideoList: actress.newVideoList.filter(item => !carNums.has(normalizeCarNum(typeof item === "string" ? item : item?.carNum))) + } : actress); + if (this.nvCoverPreview?.currentTarget && cards.toArray().some(card => card.contains(this.nvCoverPreview.currentTarget))) this.nvCoverPreview.hidePreview(); + const duration = window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches ? 0 : 180; + cards.each((_, card) => this.nvRemovingCards.add(card)); + try { + // Only fade opacity: keep the grid height stable until the replacement cards are ready. + await Promise.all(cards.toArray().map(card => new Promise(resolve => { + $(card).animate({ opacity: 0 }, duration, resolve); + }))); + } finally { + cards.each((_, card) => this.nvRemovingCards.delete(card)); + } + if (!this.isWorkspaceMounted() || generation !== this.nvRenderGeneration || root !== $("#new-video-list-container")[0] || this.nvWorkspaceFullReloadRequested) return; + const positions = container.add(container.parentsUntil(this.nvWorkspaceRoot || ".newVideoToolBox")).add(this.nvWorkspaceRoot || container.closest(".newVideoToolBox")) + .map((_, element) => ({ element, top: element.scrollTop, left: element.scrollLeft })).get(); + await this.renderNewVideoList({ incremental: !0 }); + if (this.isWorkspaceMounted() && generation === this.nvRenderGeneration && root === $("#new-video-list-container")[0]) { + positions.forEach(({ element, top, left }) => { element.scrollTop = top; element.scrollLeft = left; }); + } + } getPendingNewVideoCount(e, t) { return Array.isArray(e?.newVideoList) ? new Set(e.newVideoList.map((item => normalizeCarNum("string" == typeof item ? item : item.carNum))).filter((carNum => carNum && !t.has(carNum) && !this.isDecisionHidden(carNum)))).size : 0; } @@ -222,9 +261,11 @@ export class NewVideoPlugin extends BasePlugin { }); } cleanupNewVideoWorkspace() { + clearTimeout(this.nvInvalidationTimer), this.nvInvalidationTimer = null, this.nvWorkspaceReloadDirty = !1, this.nvWorkspaceFullReloadRequested = !1, this.nvPendingRemovals.clear(); this.nvSearchDebounced?.cancel?.(), this.nvSearchDebounced = null, this.nvWorkspaceMounted = !1, this.nvWorkspaceRoot = null, this.nvRenderGeneration++, this.nvSelected.clear(), this.nvCoverCache = new Map, this.nvActorCoverRequests = new Map, this.nvCoverPreview?.destroy?.(), this.nvCoverPreview = null, this.nvAllItemsMap.clear(), this.nvFlatListCache = [], this.nvActressesCache = [], this.nvCarMapCache = new Map, this.nvDecisionsCache = {}, this.nvCurrentPageItems = []; + $(Array.from(this.nvRemovingCards)).stop(!0, !0), this.nvRemovingCards.clear(); } bindClick() { const taskPlugin = this.getOptionalDependency("TaskPlugin"); @@ -324,7 +365,7 @@ export class NewVideoPlugin extends BasePlugin { this.nvActressesCache = actresses, this.nvCarMapCache = carMap, this.nvDecisionsCache = decisions, this.nvJavDbUrl = javDbUrl, this.nvRuleTime = parseNumberSetting(ruleTime, 8760, { min: 0 }); const items = aggregateNewVideoRecords(actresses, carMap, decisions), nextMap = new Map; items.forEach((item => nextMap.set(normalizeCarNum(item.carNum), { ...item, carNum: normalizeCarNum(item.carNum) }))), this.nvAllItemsMap = nextMap; - for (const carNum of [ ...this.nvSelected ]) nextMap.has(carNum) || this.nvSelected.delete(carNum); + this.pruneNewVideoSelection(); preservePage || (this.currentPage = 1, this.nvCurrentPage = 1), await this.renderCurrentView(), this.renderTaskStatuses(); } catch (error) { if (generation !== this.nvRenderGeneration || !this.isWorkspaceMounted()) return; @@ -462,16 +503,21 @@ export class NewVideoPlugin extends BasePlugin { } })); } - async renderNewVideoList() { + pruneNewVideoSelection() { + for (const carNum of [ ...this.nvSelected ]) this.nvAllItemsMap.has(carNum) || this.nvSelected.delete(carNum); + } + async renderNewVideoList({ incremental = !1 } = {}) { const container = $("#new-video-list-container"), generation = this.nvRenderGeneration; if (!container.length) return; const items = await this.getNewVideoFlatList(); if (generation !== this.nvRenderGeneration || !this.isWorkspaceMounted()) return; - $("#nv-pagination-bar").remove(); + this.pruneNewVideoSelection(); + incremental || $("#nv-pagination-bar").remove(); this.nvFlatListCache = items, this.nvSortBy = $("#nvSortBy").val() || this.nvSortBy; const totalPages = Math.ceil(items.length / this.nvPageSize); this.nvCurrentPage = totalPages ? Math.min(this.nvCurrentPage, totalPages) : 1; if (!items.length) { + this.nvCurrentPageItems = [], $("#nv-pagination-bar").remove(); const query = String($("#nvSearch").val() || "").trim(), filtered = [ "nvCategoryFilter", "nvStateFilter", "nvDecisionFilter" ].some((id => $("#" + id).val() !== ("nvCategoryFilter" === id ? "all" : "pending"))); if (!this.nvAllItemsMap.size) renderStateView(container, { type: "empty", title: "暂无新作品记录" }); else if (query) renderStateView(container, { type: "empty", title: `没有找到“${query}”的作品`, actionLabel: "清除搜索", onAction: () => { $("#nvSearch").val(""), this.nvCurrentPage = 1, this.nvRenderGeneration++, this.renderNewVideoList(); @@ -480,7 +526,7 @@ export class NewVideoPlugin extends BasePlugin { } }); else renderStateView(container, { type: "empty", title: "暂无待处理的新作品" }); return void this.renderBatchBar(); } - this.nvRenderPage(generation), this.renderBatchBar(); + this.nvRenderPage(generation, { incremental }), this.renderBatchBar(); } selectedItems() { return [ ...this.nvSelected ].map((carNum => this.nvAllItemsMap.get(normalizeCarNum(carNum)))).filter(Boolean); @@ -540,46 +586,78 @@ export class NewVideoPlugin extends BasePlugin { return "desc" === a ? -i : i; })); } - nvRenderPage(generation = this.nvRenderGeneration) { + nvCardHtml(n) { + const r = this.nvJavDbUrl; + let c = ""; + const key = normalizeCarNum(n.carNum), e = escapeHtml(key), t = escapeHtml(n.title || key), cachedCover = this.nvCoverCache.get(key), a = escapeHtml((cachedCover || n.coverUrl || "").replace("thumbs", "covers")), i = escapeHtml(n.url || `${r}/search?q=${encodeURIComponent(key)}`); + let o = `番号: ${e}\\n演员: ${escapeHtml(n.actressName)}\\n发行: ${escapeHtml(String(n.publishTime || "未知"))}`; + n.voteCount && (o += `\\n评价人数: ${n.voteCount}`); + const l = n.voteCount ? `${n.voteCount}人评价` : ""; + c += ``; + return c; + } + nvRenderPage(generation = this.nvRenderGeneration, { incremental = !1 } = {}) { + if (generation !== this.nvRenderGeneration) return; + this.pruneNewVideoSelection(); const e = this.nvFlatListCache; - if (!e || 0 === e.length) return; - const t = this.nvSortList(e), n = this.nvPageSize, a = (this.nvCurrentPage - 1) * n, i = a + n, s = t.slice(a, i), o = Math.ceil(t.length / n), r = this.nvJavDbUrl; + if (!e || 0 === e.length) return void this.renderNewVideoList(); + const t = this.nvSortList(e), n = this.nvPageSize, o = Math.ceil(t.length / n); + this.nvCurrentPage = Math.max(1, Math.min(this.nvCurrentPage, o)); + const a = (this.nvCurrentPage - 1) * n, i = a + n, s = t.slice(a, i); this.nvCurrentPageItems = s; - if (generation !== this.nvRenderGeneration) return; $("#nv-pagination-bar").remove(); - const l = $("#new-video-list-container"); - let c = ""; - c += '
      '; - for (const n of s) { - const key = normalizeCarNum(n.carNum), e = escapeHtml(key), t = escapeHtml(n.title || key), cachedCover = this.nvCoverCache.get(key), a = escapeHtml((cachedCover || n.coverUrl || "").replace("thumbs", "covers")), i = escapeHtml(n.url || `${r}/search?q=${encodeURIComponent(key)}`); - let o = `番号: ${e}\\n演员: ${escapeHtml(n.actressName)}\\n发行: ${escapeHtml(String(n.publishTime || "未知"))}`; - n.voteCount && (o += `\\n评价人数: ${n.voteCount}`); - const l = n.voteCount ? `${n.voteCount}人评价` : ""; - c += ``; + const l = $("#new-video-list-container"), grid = l.find("#nv-grid"); + incremental = incremental && grid.length > 0; + const existingCards = incremental ? new Map(grid.children(".nv-card").toArray().map(card => [ normalizeCarNum($(card).attr("data-car")), card ])) : new Map; + const focusedCard = $(document.activeElement).closest(".nv-card")[0], focusIndex = grid.children(".nv-card").index(focusedCard); + let c = ""; + c += '
      '; + for (const item of s) { + if (!incremental || !existingCards.has(normalizeCarNum(item.carNum))) c += this.nvCardHtml(item); + } + c += "
      "; + if (o > 1) { + c += '
      '; + this.nvCurrentPage > 1 && (c += ``); + let e = Math.max(1, this.nvCurrentPage - 2), n = Math.min(o, e + 4); + n - e < 4 && (e = Math.max(1, n - 4)); + for (let t = e; t <= n; t++) c += ``; + this.nvCurrentPage < o && (c += ``), + c += `第 ${this.nvCurrentPage}/${o} 页,共 ${t.length} 条`, c += "
      "; + } + let createdCards; + if (incremental) { + const content = $(c), additions = content.filter("#nv-grid").children(".nv-card"); + const wanted = new Set(s.map(item => normalizeCarNum(item.carNum))), added = new Map(additions.toArray().map(card => [ normalizeCarNum($(card).attr("data-car")), card ])); + grid.children(".nv-card").filter((_, card) => !wanted.has(normalizeCarNum($(card).attr("data-car")))).remove(); + let cursor = grid[0].firstElementChild; + for (const item of s) { + const key = normalizeCarNum(item.carNum), card = existingCards.get(key) || added.get(key); + if (card === cursor) cursor = cursor.nextElementSibling; + else grid[0].insertBefore(card, cursor); + $(card).find(".nv-select").prop("checked", this.nvSelected.has(key)); } - c += "
      "; - if (o > 1) { - c += '
      '; - this.nvCurrentPage > 1 && (c += ``); - let e = Math.max(1, this.nvCurrentPage - 2), n = Math.min(o, e + 4); - n - e < 4 && (e = Math.max(1, n - 4)); - for (let t = e; t <= n; t++) c += ``; - this.nvCurrentPage < o && (c += ``), - c += `第 ${this.nvCurrentPage}/${o} 页,共 ${t.length} 条`, c += "
      "; + l.append(content.filter("#nv-pagination-bar")); + createdCards = additions; + if (focusIndex >= 0 && !wanted.has(normalizeCarNum($(focusedCard).attr("data-car")))) { + grid.children(".nv-card").eq(Math.min(focusIndex, s.length - 1)).find(".nv-card__link")[0]?.focus({ preventScroll: !0 }); } - l.html(c), l.find(".nv-cover-img").on("error", (function() { $(this).addClass("jhs-is-hidden").siblings(".nv-card__empty").removeClass("jhs-is-hidden"); })), l.find(".nv-select").on("change", (event => { const carNum = normalizeCarNum(event.currentTarget.value); event.currentTarget.checked ? this.nvSelected.add(carNum) : this.nvSelected.delete(carNum), this.renderBatchBar(); })), l.find(".pagination-btn").off("click").on("click", (e => { - const n = parseInt($(e.currentTarget).data("nvpage")); - n >= 1 && n <= o && n !== this.nvCurrentPage && (this.nvCurrentPage = n, this.nvRenderGeneration++, this.nvRenderPage(this.nvRenderGeneration), this.renderBatchBar(), l.scrollTop(0)); - })), l.find("#nv-pagination-bar").insertAfter(l), this.nvCoverPreview ??= new window.ImageHoverPreview({ selector: ".nv-cover-img", dataAttribute: "data-full", owner: this.nvWorkspaceRoot, resolveOwner: () => this.nvWorkspaceRoot, zIndexStrategy: "owner" }), void this.hydrateVisibleCovers(s, generation); + } else { + l.html(c), createdCards = l.find(".nv-card"); + } + createdCards.find(".nv-cover-img").on("error", (function() { $(this).addClass("jhs-is-hidden").siblings(".nv-card__empty").removeClass("jhs-is-hidden"); })), createdCards.find(".nv-select").on("change", (event => { const carNum = normalizeCarNum(event.currentTarget.value); event.currentTarget.checked ? this.nvSelected.add(carNum) : this.nvSelected.delete(carNum), this.renderBatchBar(); })), l.find(".pagination-btn").off("click").on("click", (e => { + const n = parseInt($(e.currentTarget).data("nvpage")); + n >= 1 && n <= o && n !== this.nvCurrentPage && (this.nvCurrentPage = n, this.nvRenderGeneration++, this.nvRenderPage(this.nvRenderGeneration), this.renderBatchBar(), l.scrollTop(0)); + })), l.find("#nv-pagination-bar").insertAfter(l), this.nvCoverPreview ??= new window.ImageHoverPreview({ selector: ".nv-cover-img", dataAttribute: "data-full", owner: this.nvWorkspaceRoot, resolveOwner: () => this.nvWorkspaceRoot, zIndexStrategy: "owner" }), void this.hydrateVisibleCovers(s, generation); } async editActress(e) { const dialog = this.getRuntimeService("dialog"); diff --git a/tests/browser/specs/new-video-layout.spec.js b/tests/browser/specs/new-video-layout.spec.js index 3725b968..2e243900 100644 --- a/tests/browser/specs/new-video-layout.spec.js +++ b/tests/browser/specs/new-video-layout.spec.js @@ -1,6 +1,126 @@ import {test,expect} from "@playwright/test"; import {fulfillHostFixtures,injectUserscriptRuntime} from "../harness/runtime.js"; +for (const scenario of [ + { name: "returning to the first page", count: 9, removed: ["ABC-002"], target: 2, back: true, page: 1, expected: ["ABC-001", "ABC-003", "ABC-004"] }, + { name: "using an outdated last-page button", count: 7, removed: ["ABC-002"], target: 3, page: 2, expected: ["ABC-005", "ABC-006", "ABC-007"] }, + { name: "removing every record", count: 4, removed: ["ABC-001", "ABC-002", "ABC-003", "ABC-004"], target: 2, page: 1, expected: [] }, +]) test(`pagination during a real removal stays current when ${scenario.name}`, async ({ page, context }, info) => { + test.skip(!["desktop-wide", "mobile"].includes(info.project.name), "desktop and mobile pagination acceptance"); + await fulfillHostFixtures(context); + await page.goto("https://javdb.com/"); + await injectUserscriptRuntime(page, { disabledPlugins: ["TaskPlugin"], settingOverrides: { enableLoadReview: "no" } }); + await page.waitForFunction(() => window.unsafeWindow.pluginManager.getBean("NewVideoPlugin")?.nvEventUnsubscribe); + await page.evaluate(async count => { + const storage = window.storageManager; + await storage.forage.setItem(storage.favorite_actresses_key, [{ starId: "fixture", name: "Fixture", actressType: "censored", + newVideoList: Array.from({ length: count }, (_, index) => ({ + carNum: `ABC-${String(index + 1).padStart(3, "0")}`, publishTime: "2026-09-09", title: "Fixture", + coverUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", + })), + }]); + storage._invalidateCache(storage.favorite_actresses_key); + localStorage.setItem("jhs_newVideoViewMode", "list"); + const plugin = window.unsafeWindow.pluginManager.getBean("NewVideoPlugin"); + plugin.nvPageSize = 3; + await plugin.openDialog(); + }, scenario.count); + await expect(page.locator("#nv-grid .nv-card")).toHaveCount(3); + const result = await page.evaluate(async ({ removed, target, back }) => { + const plugin = window.unsafeWindow.pluginManager.getBean("NewVideoPlugin"); + await plugin.getRuntimeService("state").removeFromNewVideoList(removed, "manual"); + const pending = plugin.flushWorkspaceReload(); + for (let attempt = 0; attempt < 50 && !plugin.nvRemovingCards.size; attempt++) await new Promise(resolve => setTimeout(resolve, 0)); + const animationWasActive = plugin.nvRemovingCards.size > 0; + window.jQuery(`.nv-card[data-car="${removed[0]}"] .nv-select`).prop("checked", true).trigger("change"); + window.jQuery('.nv-card[data-car="ABC-003"] .nv-select').prop("checked", true).trigger("change"); + document.querySelector(`#nv-pagination-bar [data-nvpage="${target}"]`).click(); + await pending; + if (back) document.querySelector('#nv-pagination-bar [data-nvpage="1"]').click(); + const actresses = await window.storageManager.getFavoriteActressList(); + return { animationWasActive, page: plugin.nvCurrentPage, selected: [...plugin.nvSelected], + visible: [...document.querySelectorAll("#nv-grid .nv-card")].map(card => card.dataset.car), + cached: plugin.nvFlatListCache.map(item => item.carNum), + stored: actresses.flatMap(actress => actress.newVideoList.map(item => typeof item === "string" ? item : item.carNum)), + }; + }, scenario); + expect(result.animationWasActive).toBe(true); + expect(result.visible).toEqual(scenario.expected); + expect(result.page).toBe(scenario.page); + expect(result.selected).toEqual(scenario.removed.includes("ABC-003") ? [] : ["ABC-003"]); + expect(result.cached).toHaveLength(scenario.count - scenario.removed.length); + for (const carNum of scenario.removed) expect(result.stored).not.toContain(carNum); + if (!scenario.expected.length) { + await expect(page.locator("#new-video-list-container")).toContainText("暂无新作品记录"); + await expect(page.locator("#nv-pagination-bar")).toHaveCount(0); + } +}); + +test("browsing new video fades only that card and fills the page without losing position",async({page,context},info)=>{ + test.skip(!["desktop-wide","mobile"].includes(info.project.name),"desktop and mobile scrolling owners"); + await fulfillHostFixtures(context); + await page.goto("https://javdb.com/"); + await injectUserscriptRuntime(page,{ + disabledPlugins:["TaskPlugin"], + settingOverrides:{enableLoadReview:"no",autoRemoveNewVideoMarkAfterBrowse:"yes"} + }); + await page.waitForFunction(()=>window.__jhsBrowserDiagnostics.bootstrapPhases["first-ready"]); + await page.waitForFunction(()=>window.unsafeWindow.pluginManager.getBean("NewVideoPlugin")?.nvEventUnsubscribe); + await page.evaluate(async()=>{ + const storage=window.storageManager; + await storage.forage.setItem(storage.favorite_actresses_key,[{ + starId:"fixture",name:"Fixture",actressType:"censored", + newVideoList:Array.from({length:150},(_,index)=>({ + carNum:`ABC-${String(index+1).padStart(3,"0")}`,publishTime:"2026-09-09",title:"Fixture title", + url:`https://javdb.com/v/nv-${index+1}`, + coverUrl:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" + })) + }]); + storage._invalidateCache(storage.favorite_actresses_key); + localStorage.setItem("jhs_newVideoViewMode","list"); + await window.unsafeWindow.pluginManager.getBean("NewVideoPlugin").openDialog(); + }); + await expect(page.locator("#nv-grid .nv-card")).toHaveCount(60); + await page.locator("#nv-pagination-bar").getByRole("button",{name:"下一页",exact:true}).click(); + await expect(page.locator('#nv-grid .nv-card').first()).toHaveAttribute("data-car","ABC-061"); + const target=page.locator('.nv-card[data-car="ABC-090"] .nv-card__link'); + await page.locator('.nv-card[data-car="ABC-091"] .nv-select').check(); + await target.scrollIntoViewIfNeeded(); + const before=await page.evaluate(()=>{ + const container=document.querySelector("#new-video-list-container"),workspace=document.querySelector(".newVideoToolBox"); + const card=document.querySelector('.nv-card[data-car="ABC-091"]'); + window.nvRetainedNodes={grid:document.querySelector("#nv-grid"),card,image:card.querySelector("img")}; + const animate=window.jQuery.fn.animate; + window.nvBrowseFades=0; + window.jQuery.fn.animate=function(properties,...args){ + if(this.is('.nv-card[data-car="ABC-090"]') && properties.opacity===0) window.nvBrowseFades++; + return animate.call(this,properties,...args); + }; + return {list:container.scrollTop,workspace:workspace.scrollTop}; + }); + expect(Math.max(before.list,before.workspace)).toBeGreaterThan(0); + const popupPromise=page.waitForEvent("popup"); + await target.click(); + const popup=await popupPromise; + await popup.close(); + await expect(page.locator('.nv-card[data-car="ABC-090"]')).toHaveCount(0); + await expect(page.locator("#nv-grid .nv-card")).toHaveCount(60); + await expect(page.locator("#nv-grid .nv-card").last()).toHaveAttribute("data-car","ABC-121"); + await expect(page.locator('.nv-card[data-car="ABC-091"] .nv-select')).toBeChecked(); + await expect(page.locator("#nv-pagination-bar")).toContainText("第 2/3 页,共 149 条"); + await expect.poll(()=>page.evaluate(()=>{ + const container=document.querySelector("#new-video-list-container"),workspace=document.querySelector(".newVideoToolBox"); + return {list:container.scrollTop,workspace:workspace.scrollTop}; + })).toEqual(before); + expect(await page.evaluate(()=>({ + grid:window.nvRetainedNodes.grid===document.querySelector("#nv-grid"), + card:window.nvRetainedNodes.card===document.querySelector('.nv-card[data-car="ABC-091"]'), + image:window.nvRetainedNodes.image===document.querySelector('.nv-card[data-car="ABC-091"] img'), + page:window.unsafeWindow.pluginManager.getBean("NewVideoPlugin").nvCurrentPage, + fades:window.nvBrowseFades + }))).toEqual({grid:true,card:true,image:true,page:2,fades:1}); +}); + test("new video pagination remains reachable without scrolling through sixty cards",async({page,context},info)=>{ test.skip(info.project.name!=="desktop-wide","explicit viewport matrix owner"); await fulfillHostFixtures(context); diff --git a/tests/browser/specs/setting-effects.spec.js b/tests/browser/specs/setting-effects.spec.js index f6529c98..78e0caf2 100644 --- a/tests/browser/specs/setting-effects.spec.js +++ b/tests/browser/specs/setting-effects.spec.js @@ -1,6 +1,30 @@ import { expect, test } from "@playwright/test"; import { fulfillHostFixtures, injectUserscriptRuntime } from "../harness/runtime.js"; +for (const defaultQuickFilterTab of ["blockedItems", "filter"]) test(`blocked default ${defaultQuickFilterTab} agrees with settings and remains selectable`, async ({ context, page }, info) => { + test.skip(!["desktop-wide", "mobile"].includes(info.project.name), "desktop and mobile default-filter compatibility"); + await fulfillHostFixtures(context); + await page.goto("https://javdb.com/"); + await injectUserscriptRuntime(page, { settingOverrides: { defaultQuickFilterTab, enableLoadReview: "no" } }); + await expect.poll(() => page.evaluate(() => window.unsafeWindow.pluginManager.getBean("ListPagePlugin").activeQuickFilter)).toBe("blockedItems"); + await page.evaluate(() => window.unsafeWindow.pluginManager.getBean("SettingPlugin").openSettingDialog("base-panel")); + const select = page.locator("#defaultQuickFilterTab"); + await expect(select).toHaveValue("blockedItems"); + await expect(select.locator("option")).toHaveCount(11); + await expect(select.locator('option[value="blockedItems"]')).toHaveText("屏蔽项"); + await page.evaluate(async () => { + window.jQuery("#defaultQuickFilterTab").val("undownloaded").trigger("change"); + await window.unsafeWindow.pluginManager.getBean("SettingPlugin").getRuntimeService("settings").waitForIdle(); + }); + await expect(select).toHaveValue("undownloaded"); + await expect.poll(() => page.evaluate(() => window.unsafeWindow.pluginManager.getBean("SettingPlugin").getRuntimeService("settings").snapshot().defaultQuickFilterTab)).toBe("undownloaded"); + await page.evaluate(async () => { + window.jQuery("#defaultQuickFilterTab").val("blockedItems").trigger("change"); + await window.unsafeWindow.pluginManager.getBean("SettingPlugin").getRuntimeService("settings").waitForIdle(); + }); + await expect.poll(() => page.evaluate(() => window.unsafeWindow.pluginManager.getBean("SettingPlugin").getRuntimeService("settings").snapshot().defaultQuickFilterTab)).toBe("blockedItems"); +}); + test("feature disabled leaves no dead list button", async ({ context, page }, testInfo) => { test.skip(testInfo.project.name !== "desktop-wide", "one deterministic project covers capability rendering"); await fulfillHostFixtures(context); diff --git a/tests/default-quick-filter-setting.test.js b/tests/default-quick-filter-setting.test.js new file mode 100644 index 00000000..0402575e --- /dev/null +++ b/tests/default-quick-filter-setting.test.js @@ -0,0 +1,81 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import jqueryFactory from "jquery"; +import { JSDOM } from "jsdom"; +import { SettingsRegistry } from "../src/app/settings-registry.js"; +import { registerDefaultSettings } from "../src/app/settings-catalog.js"; +import { SettingsService } from "../src/services/settings-service.js"; +import { SettingPlugin } from "../src/plugins/backup/setting.js"; +import { buildSettingDialogHtml } from "../src/plugins/backup/setting-templates.js"; +import { normalizeQuickFilterKey } from "../src/features/list/list-filters.js"; + +const harnesses = []; + +async function createHarness(initial = {}) { + const dom = new JSDOM("", { url: "https://javdb.com/" }); + const jq = jqueryFactory(dom.window); + vi.stubGlobal("$", jq); + vi.stubGlobal("window", dom.window); + vi.stubGlobal("document", dom.window.document); + vi.stubGlobal("storageManager", {}); + const stored = { setting: { ...initial } }; + const registry = new SettingsRegistry(); + registerDefaultSettings(registry); + const storage = { get: async key => stored[key], set: async (key, value) => { stored[key] = value; } }; + const settings = new SettingsService(storage); + await settings.load(); + const plugin = new SettingPlugin(); + plugin.runtimeServices = { + settingsRegistry: registry, settings, + host: { locateListRoot: () => null, getListLayoutContainer: () => null }, + }; + const root = jq(buildSettingDialogHtml("base-panel", [])).appendTo(jq("body")); + const binding = plugin.hydrateLiveSettings(root); + const harness = { dom, root, binding, registry, settings, storage, stored }; + harnesses.push(harness); + return harness; +} + +describe("default quick-filter setting", () => { + afterEach(() => { + for (const { dom, binding } of harnesses.splice(0)) { + binding.dispose(); + dom.window.close(); + } + vi.unstubAllGlobals(); + }); + + it("renders every quick filter in the dialog and registry without changing the default", async () => { + const { root, registry } = await createHarness(); + const select = root.find("#defaultQuickFilterTab"); + const options = select.find("option").map((_, option) => ({ value: option.value, label: option.textContent })).get(); + expect(options.map(({ value }) => value)).toEqual([ + "all", "waitCheck", "favorite", "hasDown", "hasWatch", "blockedItems", "undownloaded", + "favoriteUndownloaded", "favoriteUnwatched", "downloadedUnwatched", "recent7d", + ]); + expect(registry.get("defaultQuickFilterTab").options).toEqual(options); + expect(select.find('option[value="undownloaded"]').text()).toBe("全部未下载"); + expect(select.find('option[value="blockedItems"]').text()).toBe("屏蔽项"); + expect(select.val()).toBe("waitCheck"); + }); + + it.each(["blockedItems", "undownloaded", "favoriteUndownloaded", "favoriteUnwatched", "downloadedUnwatched", "recent7d"])( + "persists and reloads %s through the original settings binding", async value => { + const { root, binding, stored, storage } = await createHarness({ defaultQuickFilterTab: "waitCheck" }); + root.find("#defaultQuickFilterTab").val(value).trigger("change"); + await binding.flush(); + expect(stored.setting.defaultQuickFilterTab).toBe(value); + const reloaded = new SettingsService(storage); + await reloaded.load(); + expect(normalizeQuickFilterKey(reloaded.snapshot().defaultQuickFilterTab)).toBe(value); + binding.sync(reloaded.snapshot()); + expect(root.find("#defaultQuickFilterTab").val()).toBe(value); + } + ); + + it.each(["blockedItems", "filter"])("preserves the effective blocked default %s without writing during hydration", async value => { + const { root, stored } = await createHarness({ defaultQuickFilterTab: value }); + expect(root.find("#defaultQuickFilterTab").val()).toBe("blockedItems"); + expect(root.find("#defaultQuickFilterTab").val()).toBe(normalizeQuickFilterKey(stored.setting.defaultQuickFilterTab)); + expect(stored.setting.defaultQuickFilterTab).toBe(value); + }); +}); diff --git a/tests/list-evaluator.test.js b/tests/list-evaluator.test.js index 0219d676..cf5ec5e0 100644 --- a/tests/list-evaluator.test.js +++ b/tests/list-evaluator.test.js @@ -50,6 +50,31 @@ describe("ListEvaluator (唯一列表判定器)", () => { expect(result.visibilityReasons).toEqual({ keyword: false, actorBlacklist: false, actressBlacklist: false }); }); + it("undownloaded includes pending, favorite and watched items while excluding downloads and every blocking rule", () => { + const context = makeContext({ + cars: { + pending: {}, favorite: { favorite: true }, watched: { watched: true }, + favoriteWatched: { favorite: true, watched: true }, + downloaded: { downloaded: true }, favoriteDownloaded: { favorite: true, downloaded: true }, + watchedDownloaded: { watched: true, downloaded: true }, + favoriteWatchedDownloaded: { favorite: true, watched: true, downloaded: true }, + blocked: { blocked: true }, favoriteBlocked: { favorite: true, blocked: true }, + }, + titleKeywords: [ "禁播" ], + actorBlacklist: { actorBlocked: "男优甲" }, + actressBlacklist: { actressBlocked: "女优甲" }, + }); + const records = [ + ...Array.from(context.carMap.keys()).map(carNum => ({ carNum })), + { carNum: "keywordBlocked", title: "禁播合集" }, + { carNum: "actorBlocked" }, { carNum: "actressBlocked" }, + ]; + const before = structuredClone(context.carMap); + expect(records.filter(record => evaluateListItem(record, context, { filter: "undownloaded" }).matchesCurrentFilter) + .map(record => record.carNum)).toEqual([ "pending", "favorite", "watched", "favoriteWatched" ]); + expect(context.carMap).toEqual(before); + }); + it("finds the matched keyword for badge tips", () => { expect(findMatchedTitleKeyword([ "禁播", "4K" ], "4K 合集", "ABC-123")).toBe("4K"); expect(findMatchedTitleKeyword([ "ABC" ], "普通标题", "ABC-001")).toBe("ABC"); diff --git a/tests/list-visibility.test.js b/tests/list-visibility.test.js index 82dc420b..fb3f800a 100644 --- a/tests/list-visibility.test.js +++ b/tests/list-visibility.test.js @@ -8,9 +8,10 @@ describe("multi-state list visibility", () => { it("normalizes legacy and invalid quick-filter keys at the boundary", () => { expect(api.normalizeQuickFilterKey("filter")).toBe("blockedItems"); expect(api.normalizeQuickFilterKey("recent7d")).toBe("recent7d"); + expect(api.normalizeQuickFilterKey("undownloaded")).toBe("undownloaded"); expect(api.normalizeQuickFilterKey("unknown")).toBe("waitCheck"); expect(Array.from(api.PRIMARY_QUICK_FILTERS)).toEqual(["all", "waitCheck", "favorite", "hasDown", "hasWatch"]); - expect(Array.from(api.SECONDARY_QUICK_FILTERS)).toEqual(["blockedItems", "favoriteUndownloaded", "favoriteUnwatched", "downloadedUnwatched", "recent7d"]); + expect(Array.from(api.SECONDARY_QUICK_FILTERS)).toEqual(["blockedItems", "undownloaded", "favoriteUndownloaded", "favoriteUnwatched", "downloadedUnwatched", "recent7d"]); }); it.each([ @@ -70,6 +71,8 @@ describe("multi-state list visibility", () => { expect(visible("hasDown")).toEqual([ "C", "E", "G", "H" ]); expect(visible("hasWatch")).toEqual([ "D", "F", "G", "H" ]); expect(visible("blockedItems")).toEqual([ "I" ]); + expect(visible("undownloaded")).toEqual([ "A", "B", "D", "F" ]); + expect(visible("favoriteUndownloaded")).toEqual([ "B", "F" ]); }); it("keeps all hard-hidden reasons inside all and exposes them through blocked items", () => { @@ -78,6 +81,8 @@ describe("multi-state list visibility", () => { expect(api.shouldShowItem({ filter: "blockedItems", flags: flags("favorite"), visibilityReasons, recent: false })).toBe(true); expect(api.shouldShowItem({ filter: "favorite", flags: flags("favorite"), visibilityReasons, recent: false })).toBe(false); expect(api.shouldShowItem({ filter: "waitCheck", flags: flags(), visibilityReasons, recent: false })).toBe(false); + expect(api.shouldShowItem({ filter: "undownloaded", flags: flags("favorite", "watched"), visibilityReasons, recent: false })).toBe(false); + expect(api.shouldShowItem({ filter: "favoriteUndownloaded", flags: flags("favorite", "watched"), visibilityReasons, recent: false })).toBe(false); } }); }); diff --git a/tests/mobile-fab.test.js b/tests/mobile-fab.test.js index 5432c7f3..61dc191d 100644 --- a/tests/mobile-fab.test.js +++ b/tests/mobile-fab.test.js @@ -5,6 +5,7 @@ import vm from "node:vm"; import jqueryFactory from "jquery"; import { JSDOM } from "jsdom"; import { describe, expect, it, vi } from "vitest"; +import { PRIMARY_QUICK_FILTERS, QUICK_FILTER_LABELS, SECONDARY_QUICK_FILTERS, normalizeQuickFilterKey } from "../src/features/list/list-filters.js"; function loadMobilePlugin({ beans: beanOverrides = null, isListPage = true, isDetailPage = false } = {}) { const dom = new JSDOM("", { url: "https://javdb.com/" }), $ = jqueryFactory(dom.window); @@ -13,12 +14,9 @@ function loadMobilePlugin({ beans: beanOverrides = null, isListPage = true, isDe const beans = beanOverrides ?? { ListPagePlugin: listPage, ListPageButtonPlugin: listButtons, NewVideoPlugin: {}, BlacklistPlugin: {}, SettingPlugin: {}, DetailPageButtonPlugin: {}, HighlightMagnetPlugin: {}, MagnetHubPlugin: {} }; const settings = { snapshot: () => ({ sortMethod: "default" }), set: vi.fn(async () => {}) }, host = { readMovieRef: vi.fn(() => ({ carNum: "ABC-123" })) }; class BasePlugin { getBean(name) { return beans[name]; } getRuntimeService(name) { return "host" === name ? host : settings; } } - const labels = { all: "全部", waitCheck: "待鉴定", favorite: "收藏", hasDown: "下载", hasWatch: "已看", blockedItems: "屏蔽项", favoriteUndownloaded: "收藏未下载", favoriteUnwatched: "收藏未观看", downloadedUnwatched: "下载未观看", recent7d: "最近 7 天" }; const context = vm.createContext({ window: dom.window, document: dom.window.document, $, BasePlugin, localStorage: dom.window.localStorage, - PRIMARY_QUICK_FILTERS: [ "all", "waitCheck", "favorite", "hasDown", "hasWatch" ], - SECONDARY_QUICK_FILTERS: [ "blockedItems", "favoriteUndownloaded", "favoriteUnwatched", "downloadedUnwatched", "recent7d" ], - QUICK_FILTER_LABELS: labels, normalizeQuickFilterKey: value => labels[value] ? value : "waitCheck", + PRIMARY_QUICK_FILTERS, SECONDARY_QUICK_FILTERS, QUICK_FILTER_LABELS, normalizeQuickFilterKey, r: true, l: false, m: "屏蔽", v: "收藏", y: "下载", k: "观看", normalizeStateFlags: value => value || {}, storageManager: {}, stateService: {}, show: { info: vi.fn() }, utils: {}, clog: { debug: vi.fn(), warn: vi.fn(), error: vi.fn() }, setTimeout, clearTimeout }); @@ -41,10 +39,11 @@ describe("mobile list FAB", () => { expect($("html").hasClass("jhs-fab-mounted")).toBe(false); }); - it("projects list actions, ten quick filters and a radio-style sort submenu", () => { + it("projects list actions, eleven quick filters and a radio-style sort submenu", () => { const { plugin } = loadMobilePlugin(), menu = plugin.createMenu(); expect(menu.find(".jhs-fab-menu-item")).toHaveLength(7); - expect(menu.find(".jhs-mobile-filter-option")).toHaveLength(10); + expect(menu.find(".jhs-mobile-filter-option")).toHaveLength(11); + expect(menu.find('.jhs-mobile-filter-option[data-jhs-filter="undownloaded"]').text()).toBe("全部未下载"); expect(menu.find('.jhs-mobile-sort-option[role="menuitemradio"]')).toHaveLength(3); expect(menu.find('.jhs-mobile-sort-option[aria-checked="true"]')).toHaveLength(1); expect(menu.find('[data-action="quickFilter"]')).toHaveLength(1); diff --git a/tests/new-video-incremental.test.js b/tests/new-video-incremental.test.js new file mode 100644 index 00000000..bf23a45f --- /dev/null +++ b/tests/new-video-incremental.test.js @@ -0,0 +1,268 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import jqueryFactory from "jquery"; +import { JSDOM } from "jsdom"; +import { NewVideoPlugin } from "../src/plugins/new-video/new-video.js"; +import { initializeEventBus } from "../src/core/event-bus.js"; +import { normalizeCarNum } from "../src/core/constants.js"; + +const html = `
      + + + + +
      +
      `; +const harnesses = []; + +async function createHarness(count = 9) { + const dom = new JSDOM(html, { url: "https://javdb.com/" }), $ = jqueryFactory(dom.window); + vi.stubGlobal("window", dom.window); + vi.stubGlobal("document", dom.window.document); + vi.stubGlobal("$", $); + vi.stubGlobal("BroadcastChannel", class { addEventListener() {} postMessage() {} }); + vi.stubGlobal("clog", { error: vi.fn(), warn: vi.fn(), log: vi.fn(), debug: vi.fn() }); + vi.stubGlobal("show", { info: vi.fn(), ok: vi.fn(), error: vi.fn() }); + vi.stubGlobal("utils", { debounce: fn => Object.assign(fn, { cancel() {} }), q: vi.fn() }); + dom.window.matchMedia = () => ({ matches: true }); + dom.window.ImageHoverPreview = class { + destroy() {} + hidePreview() { this.currentTarget = null; } + }; + let actresses = [{ name: "Fixture", starId: "fixture", actressType: "censored", newVideoList: Array.from({ length: count }, (_, index) => ({ + carNum: `ABC-${String(index + 1).padStart(3, "0")}`, title: index % 2 ? "Other" : "Keep", + publishTime: "2026-09-09", coverUrl: `https://images.example.test/${index}.jpg`, + })) }]; + const decisions = {}, bus = initializeEventBus(); + const storageManager = { + getFavoriteActressList: vi.fn(async () => actresses), getCarMap: vi.fn(async () => new Map()), + getSetting: vi.fn(async key => key === "autoRemoveNewVideoMarkAfterBrowse" ? "yes" : key === "checkNewVideo_ruleTime" ? 8760 : {}), + }; + vi.stubGlobal("storageManager", storageManager); + const state = { + getNewVideoDecisions: vi.fn(async () => decisions), + removeFromNewVideoList: vi.fn(async (values, reason) => { + const keys = values.map(normalizeCarNum), removed = new Set(keys); + actresses = actresses.map(actress => ({ ...actress, newVideoList: actress.newVideoList.filter(item => !removed.has(item.carNum)) })); + keys.forEach(key => { decisions[key] = { action: "dismissed" }; }); + await bus.emit("new-video-changed", { carNums: keys, reason }, { broadcast: false }); + return { changed: keys }; + }), + }; + const plugin = new NewVideoPlugin(); + plugin.runtimeServices = { + state, movie: { externalSiteOrigin: () => "https://javdb.com" }, + storage: { getLocal: () => null }, actressInfo: { getAvatarSources: () => [] }, + }; + vi.spyOn(plugin, "getOptionalDependency").mockReturnValue(null); + plugin.nvWorkspaceMounted = true, plugin.nvWorkspaceRoot = $(".newVideoToolBox"), plugin._viewMode = "list", plugin.nvPageSize = 3; + await plugin.handle(); + await plugin.reloadNewVideoWorkspaceData(); + plugin.bindClick(); + $("#new-video-list-container").on("click.test", ".nv-card__link", event => event.preventDefault()); + const harness = { plugin, dom, $, state, storageManager }; + harnesses.push(harness); + return harness; +} + +function visibleKeys($) { + return $("#nv-grid .nv-card").map((_, card) => card.getAttribute("data-car")).get(); +} + +afterEach(async () => { + for (const { plugin, dom } of harnesses.splice(0)) { + plugin.cleanupNewVideoWorkspace(); + plugin.nvEventUnsubscribe?.(); + plugin.taskStatusUnsubscribe?.(); + await plugin.nvWorkspaceReloadPromise; + dom.window.close(); + } + vi.restoreAllMocks(); + vi.unstubAllGlobals(); +}); + +describe("new-video browse removal", () => { + it("keeps the page, both scroll containers, retained card/image nodes and selection while filling the gap", async () => { + const { plugin, $, state, dom, storageManager } = await createHarness(); + plugin.nvCurrentPage = 2, plugin.nvRenderPage(); + const grid = $("#nv-grid")[0], retained = $('.nv-card[data-car="ABC-006"]')[0], image = $(retained).find("img")[0]; + $(retained).find(".nv-select").prop("checked", true).trigger("change"); + $('.nv-card[data-car="ABC-005"] .nv-card__link')[0].focus(); + $("#new-video-list-container").scrollTop(180), $(".newVideoToolBox").scrollTop(90); + const reload = vi.spyOn(plugin, "reloadNewVideoWorkspaceData"); + storageManager.getFavoriteActressList.mockClear(); + await state.removeFromNewVideoList(["abc_005"], "browse"); + await plugin.flushWorkspaceReload(); + expect(reload).not.toHaveBeenCalled(); + expect(storageManager.getFavoriteActressList).toHaveBeenCalledOnce(); + expect($("#nv-grid")[0]).toBe(grid); + expect(visibleKeys($)).toEqual(["ABC-004", "ABC-006", "ABC-007"]); + expect($('.nv-card[data-car="ABC-006"]')[0]).toBe(retained); + expect($(retained).find("img")[0]).toBe(image); + expect($(retained).find(".nv-select").prop("checked")).toBe(true); + expect(plugin.nvCurrentPage).toBe(2); + expect($("#new-video-list-container").scrollTop()).toBe(180); + expect($(".newVideoToolBox").scrollTop()).toBe(90); + expect($(dom.window.document.activeElement).closest(".nv-card").attr("data-car")).toBe("ABC-006"); + expect($("#nv-pagination-bar").text()).toContain("共 8 条"); + expect($("#newVideoCount").text()).toBe("8"); + expect(plugin.nvAllItemsMap.has("ABC-005")).toBe(false); + expect(plugin.nvActressesCache[0].newVideoList.some(item => normalizeCarNum(item.carNum) === "ABC-005")).toBe(false); + }); + + it("coalesces consecutive removals and retains the remaining selected card", async () => { + const { plugin, $, state } = await createHarness(10); + plugin.nvCurrentPage = 2, plugin.nvRenderPage(); + const retained = $('.nv-card[data-car="ABC-004"]')[0]; + $(retained).find(".nv-select").prop("checked", true).trigger("change"); + await Promise.all([ state.removeFromNewVideoList(["ABC-005"], "browse"), state.removeFromNewVideoList(["ABC-006"], "browse") ]); + await plugin.flushWorkspaceReload(); + expect(visibleKeys($)).toEqual(["ABC-004", "ABC-007", "ABC-008"]); + expect($('.nv-card[data-car="ABC-004"]')[0]).toBe(retained); + expect([...plugin.nvSelected]).toEqual(["ABC-004"]); + expect(plugin.nvCurrentPageItems.map(item => item.carNum)).toEqual(visibleKeys($)); + }); + + it("uses the existing search and sort rules to choose the replacement card", async () => { + const { plugin, $, state } = await createHarness(10); + $("#nvSearch").val("keep"), $("#nvSortBy").val("carNum_desc"); + await plugin.renderNewVideoList(); + expect(visibleKeys($)).toEqual(["ABC-009", "ABC-007", "ABC-005"]); + await state.removeFromNewVideoList(["ABC-007"], "browse"); + await plugin.flushWorkspaceReload(); + expect(visibleKeys($)).toEqual(["ABC-009", "ABC-005", "ABC-003"]); + expect($("#nvSearch").val()).toBe("keep"); + expect($("#nvSortBy").val()).toBe("carNum_desc"); + }); + + it("clamps an emptied last page to the previous page using the existing pagination", async () => { + const { plugin, $, state } = await createHarness(4); + plugin.nvCurrentPage = 2, plugin.nvRenderPage(); + const grid = $("#nv-grid")[0]; + await state.removeFromNewVideoList(["ABC-004"], "browse"); + await plugin.flushWorkspaceReload(); + expect(plugin.nvCurrentPage).toBe(1); + expect($("#nv-grid")[0]).toBe(grid); + expect(visibleKeys($)).toEqual(["ABC-001", "ABC-002", "ABC-003"]); + expect($("#nv-pagination-bar")).toHaveLength(0); + }); + + it("reuses the empty view after the final item and clears the current-page selection source", async () => { + const { plugin, $, state } = await createHarness(1); + await state.removeFromNewVideoList(["ABC-001"], "browse"); + await plugin.flushWorkspaceReload(); + expect($(".nv-card")).toHaveLength(0); + expect($("#new-video-list-container").text()).toContain("暂无新作品记录"); + expect(plugin.nvCurrentPageItems).toEqual([]); + expect($("#newVideoCount").text()).toBe("0"); + }); + + it("does not remove a clicked card when persistence fails or automatic removal is disabled", async () => { + const { plugin, $, state, storageManager } = await createHarness(); + state.removeFromNewVideoList.mockRejectedValueOnce(new Error("storage failed")); + $('.nv-card[data-car="ABC-002"] .nv-card__link').trigger("click"); + await new Promise(resolve => setTimeout(resolve, 0)); + expect(visibleKeys($)).toEqual(["ABC-001", "ABC-002", "ABC-003"]); + expect(plugin.nvAllItemsMap.has("ABC-002")).toBe(true); + state.removeFromNewVideoList.mockClear(); + storageManager.getSetting.mockImplementation(async key => key === "autoRemoveNewVideoMarkAfterBrowse" ? "no" : {}); + $('.nv-card[data-car="ABC-002"] .nv-card__link').trigger("click"); + await new Promise(resolve => setTimeout(resolve, 0)); + expect(state.removeFromNewVideoList).not.toHaveBeenCalled(); + expect(visibleKeys($)).toEqual(["ABC-001", "ABC-002", "ABC-003"]); + }); + + it("keeps the fading card in layout until completion and rejects the old callback after reopening", async () => { + const { plugin, $, state, dom } = await createHarness(); + let finish; + const animate = vi.spyOn($.fn, "animate").mockImplementation(function(properties, duration, complete) { + expect(properties).toEqual({ opacity: 0 }); + expect(duration).toBe(180); + finish = complete; + return this; + }); + dom.window.matchMedia = () => ({ matches: false }); + await state.removeFromNewVideoList(["ABC-002"], "browse"); + const pending = plugin.flushWorkspaceReload(); + for (let attempt = 0; !finish && attempt < 20; attempt++) await Promise.resolve(); + expect(animate).toHaveBeenCalledOnce(); + expect($('.nv-card[data-car="ABC-002"]')).toHaveLength(1); + expect($('.nv-card[data-car="ABC-002"]').css("display")).not.toBe("none"); + plugin.cleanupNewVideoWorkspace(); + $(".newVideoToolBox").remove(); + $(dom.window.document.body).append($(html).find(".newVideoToolBox").addBack(".newVideoToolBox")); + plugin.nvWorkspaceMounted = true, plugin.nvWorkspaceRoot = $(".newVideoToolBox"); + await plugin.reloadNewVideoWorkspaceData(); + const newGrid = $("#nv-grid")[0], before = visibleKeys($); + expect(newGrid).toBeDefined(); + expect(before).toEqual(["ABC-001", "ABC-003", "ABC-004"]); + finish(); + await pending; + expect($("#nv-grid")[0]).toBe(newGrid); + expect(visibleKeys($)).toEqual(before); + expect(plugin.nvRemovingCards.size).toBe(0); + }); + + it("preserves a filter change during fading and prunes a fading card selected again", async () => { + const { plugin, $, state, dom } = await createHarness(); + dom.window.matchMedia = () => ({ matches: false }); + await state.removeFromNewVideoList(["ABC-002"], "browse"); + const pending = plugin.flushWorkspaceReload(); + await vi.waitFor(() => expect(plugin.nvRemovingCards.size).toBe(1)); + $('.nv-card[data-car="ABC-002"] .nv-select').prop("checked", true).trigger("change"); + $('.nv-card[data-car="ABC-003"] .nv-select').prop("checked", true).trigger("change"); + $("#nvSearch").val("keep"), plugin.nvRenderGeneration++; + await plugin.renderNewVideoList(); + const grid = $("#nv-grid")[0]; + await pending; + expect($("#nv-grid")[0]).toBe(grid); + expect(visibleKeys($)).toEqual(["ABC-001", "ABC-003", "ABC-005"]); + expect([...plugin.nvSelected]).toEqual(["ABC-003"]); + expect($('.nv-card[data-car="ABC-003"] .nv-select').prop("checked")).toBe(true); + expect($("#nvSearch").val()).toBe("keep"); + }); + + it.each([ + { name: "returns to an updated first page", count: 9, removed: ["ABC-002"], target: 2, back: true, page: 1, expected: ["ABC-001", "ABC-003", "ABC-004"] }, + { name: "clamps an old last-page button", count: 7, removed: ["ABC-002"], target: 3, page: 2, expected: ["ABC-005", "ABC-006", "ABC-007"] }, + { name: "shows the empty view after all records are removed", count: 4, removed: ["ABC-001", "ABC-002", "ABC-003", "ABC-004"], target: 2, page: 1, expected: [] }, + ])("pagination during a removal $name", async ({ count, removed, target, back, page, expected }) => { + const { plugin, $, state, dom } = await createHarness(count), finishes = []; + dom.window.matchMedia = () => ({ matches: false }); + vi.spyOn($.fn, "animate").mockImplementation(function(_properties, _duration, complete) { + finishes.push(complete); + return this; + }); + await state.removeFromNewVideoList(removed, "manual"); + const pending = plugin.flushWorkspaceReload(); + await vi.waitFor(() => expect(finishes.length).toBeGreaterThan(0)); + try { + $(`.nv-card[data-car="${removed[0]}"] .nv-select`).prop("checked", true).trigger("change"); + $('.nv-card[data-car="ABC-003"] .nv-select').prop("checked", true).trigger("change"); + $(`#nv-pagination-bar [data-nvpage="${target}"]`).trigger("click"); + } finally { + finishes.forEach(finish => finish()); + await pending; + } + if (back) $('#nv-pagination-bar [data-nvpage="1"]').trigger("click"); + expect(visibleKeys($)).toEqual(expected); + expect(plugin.nvCurrentPage).toBe(page); + expect(plugin.nvCurrentPageItems.map(item => item.carNum)).toEqual(expected); + expect(plugin.nvFlatListCache).toHaveLength(count - removed.length); + expect([...plugin.nvSelected]).toEqual(removed.includes("ABC-003") ? [] : ["ABC-003"]); + if (expected.length) expect($("#nv-pagination-bar").text()).toContain(`共 ${count - removed.length} 条`); + else { + expect($("#nv-pagination-bar")).toHaveLength(0); + expect($("#new-video-list-container").text()).toContain("暂无新作品记录"); + } + }); + + it.each(["state-handled", "manual"])("shares the same incremental path for a committed %s removal", async reason => { + const { plugin, $, state } = await createHarness(); + const grid = $("#nv-grid")[0], reload = vi.spyOn(plugin, "reloadNewVideoWorkspaceData"); + await state.removeFromNewVideoList(["ABC-002"], reason); + await plugin.flushWorkspaceReload(); + expect(reload).not.toHaveBeenCalled(); + expect($("#nv-grid")[0]).toBe(grid); + expect(visibleKeys($)).toEqual(["ABC-001", "ABC-003", "ABC-004"]); + }); +}); diff --git a/tests/performance-hotpaths.test.js b/tests/performance-hotpaths.test.js index c04b4d31..1436d207 100644 --- a/tests/performance-hotpaths.test.js +++ b/tests/performance-hotpaths.test.js @@ -206,6 +206,17 @@ describe("list mutation hot path", () => { expect($(".item").filter(((_, item) => "none" !== $(item).css("display"))).length).toBe(1); expect($(".jhs-segmented__item[data-jhs-filter='favorite']").attr("aria-selected")).toBe("true"); expect($(".jhs-quick-filter__label").text()).toBe("更多筛选"); + + $(".jhs-quick-filter__toggle").trigger("click"); + const undownloadedOption = $('.jhs-quick-filter__menu [data-jhs-filter="undownloaded"]'); + expect(undownloadedOption.text()).toBe("全部未下载"); + undownloadedOption.trigger("click"); + expect(plugin.activeQuickFilter).toBe("undownloaded"); + expect($(".item").filter(((_, item) => "none" !== $(item).css("display"))).length).toBe(1); + expect(appended.css("display")).toBe("none"); + expect(undownloadedOption.attr("aria-checked")).toBe("true"); + expect($(".jhs-quick-filter__label").text()).toBe("筛选:全部未下载"); + expect($(".jhs-quick-filter__menu").hasClass("is-open")).toBe(false); }); });