diff --git a/README.md b/README.md index 472cfc0e..96ef2bbe 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # drpyS(drpy-node) - [![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=plastic&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/hjdhnx/drpy-node) -[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/hjdhnx/drpy-node) - +[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/hjdhnx/drpy-node) +![drpyS](./public/images/drpys.png) nodejs作为服务端的drpy实现。全面升级异步写法 ~~积极开发中,每日一更~~,当前进度 `100%` ~~找工作中,随缘更新~~ @@ -36,6 +35,7 @@ nodejs作为服务端的drpy实现。全面升级异步写法 ### 插件应用列表 +* [Admin 管理面板](/apps/admin) * [DrPlayer](/apps/drplayer) * [Websocket实时日志](/apps/websocket) * [cookie管理插件](/apps/cookie-butler/index.html) @@ -71,33 +71,25 @@ nodejs作为服务端的drpy实现。全面升级异步写法 ## 更新记录 -### 20260314 - -更新至V1.3.28 - -### 20260301 - -更新至V1.3.27 - -### 20260228 +### 20260320 -更新至V1.3.26 +更新至V1.4.1 -### 20260225 +### 20260319 -更新至V1.3.25 +更新至V1.3.31 -### 20260214 +### 20260317 -更新至V1.3.24 +更新至V1.3.30 -### 20260212 +### 20260315 -更新至V1.3.23 +更新至V1.3.29 -### 20260208 +### 20260314 -更新至V1.3.22 +更新至V1.3.28 [点此查看完整更新记录](docs/updateRecord.md) diff --git a/apps/admin/assets/ApiDocs-BtbZJGsl.css b/apps/admin/assets/ApiDocs-BtbZJGsl.css new file mode 100644 index 00000000..0d1d89a7 --- /dev/null +++ b/apps/admin/assets/ApiDocs-BtbZJGsl.css @@ -0,0 +1 @@ +.apidocs-page[data-v-e8a883e4]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.apidocs-header[data-v-e8a883e4]{flex-shrink:0;padding-bottom:1rem}.apidocs-content[data-v-e8a883e4]{flex:1;overflow-y:auto;min-height:0} diff --git a/apps/admin/assets/ApiDocs-WdRyZWIi.js b/apps/admin/assets/ApiDocs-WdRyZWIi.js new file mode 100644 index 00000000..4acd6d94 --- /dev/null +++ b/apps/admin/assets/ApiDocs-WdRyZWIi.js @@ -0,0 +1 @@ +import{z as w,o as r,b as a,e,E as C,G as L,k as p,F as v,f as k,r as g,y as A,t as n,n as m}from"./vendor-B6xRL-fs.js";import{s as E}from"./system-CxybzrTo.js";import{_ as M}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./admin-DEAtY0pm.js";import"./ui-42ANG6Sg.js";const P={class:"apidocs-page"},j={class:"apidocs-header"},B={class:"card p-4 mt-4"},D={class:"relative w-full"},I={class:"apidocs-content"},T={key:0,class:"flex justify-center py-12"},F={key:1,class:"space-y-4"},U=["onClick"],V={class:"font-semibold text-gray-900 dark:text-gray-100"},z={key:0,class:"divide-y divide-gray-200 dark:divide-gray-700"},G={class:"flex items-start gap-4"},N={class:"flex-1 min-w-0"},O={class:"text-sm font-mono text-gray-900 dark:text-gray-100 break-all"},S={class:"text-sm text-gray-600 dark:text-gray-400 mt-1"},$={key:0,class:"mt-4"},q={class:"bg-gray-50 dark:bg-gray-900 rounded-lg p-3 space-y-2"},Q={class:"px-2 py-0.5 bg-gray-200 dark:bg-gray-700 rounded text-xs font-mono flex-shrink-0"},H={class:"flex-1 min-w-0"},J={class:"font-medium text-gray-900 dark:text-gray-100"},K={key:0,class:"ml-2 text-red-600 dark:text-red-400 text-xs"},R={class:"text-gray-600 dark:text-gray-400 mt-0.5"},W={__name:"ApiDocs",setup(X){const x=g([]),y=g(!1),u=g(null),d=g("");w(async()=>{await f()});const f=async()=>{y.value=!0;try{const s=await E.getApiList();x.value=s||[]}catch(s){console.error("Failed to load API list:",s)}finally{y.value=!1}},_=A(()=>d.value?x.value.map(s=>({...s,endpoints:s.endpoints.filter(t=>{var l,i,c;const o=d.value.toLowerCase();return((l=t.path)==null?void 0:l.toLowerCase().includes(o))||((i=t.description)==null?void 0:i.toLowerCase().includes(o))||((c=t.method)==null?void 0:c.toLowerCase().includes(o))})})).filter(s=>s.endpoints.length>0):x.value),h=s=>{u.value===s?u.value=null:u.value=s},b=s=>{switch(s==null?void 0:s.toUpperCase()){case"GET":return"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200";case"POST":return"bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200";case"PUT":return"bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200";case"DELETE":return"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200";case"ALL":return"bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200";default:return"bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300"}};return(s,t)=>(r(),a("div",P,[e("div",j,[t[3]||(t[3]=e("div",null,[e("h2",{class:"text-xl font-semibold"},"API 文档"),e("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," drpy-node 可用的 API 接口文档 ")],-1)),e("div",B,[e("div",D,[C(e("input",{"onUpdate:modelValue":t[0]||(t[0]=o=>d.value=o),type:"text",placeholder:"搜索 API 端点...",class:"input w-full pr-8"},null,512),[[L,d.value]]),d.value?(r(),a("button",{key:0,onClick:t[1]||(t[1]=o=>d.value=""),class:"absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 p-1"},[...t[2]||(t[2]=[e("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])])):p("",!0)])])]),e("div",I,[y.value?(r(),a("div",T,[...t[4]||(t[4]=[e("div",{class:"animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"},null,-1)])])):(r(),a("div",F,[(r(!0),a(v,null,k(_.value,o=>(r(),a("div",{key:o.category,class:"card overflow-hidden"},[e("button",{onClick:l=>h(o.category),class:"w-full px-6 py-4 flex items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors"},[e("h3",V,n(o.category),1),(r(),a("svg",{class:m(["w-5 h-5 text-gray-500 transition-transform",{"rotate-180":u.value===o.category}]),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[...t[5]||(t[5]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 9l-7 7-7-7"},null,-1)])],2))],8,U),u.value===o.category?(r(),a("div",z,[(r(!0),a(v,null,k(o.endpoints,l=>(r(),a("div",{key:l.path,class:"p-6"},[e("div",G,[e("span",{class:m(["px-2.5 py-1 rounded text-xs font-bold flex-shrink-0",b(l.method)])},n(l.method),3),e("div",N,[e("code",O,n(l.path),1),e("p",S,n(l.description),1),l.params&&Object.keys(l.params).length>0?(r(),a("div",$,[t[6]||(t[6]=e("h4",{class:"text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"},"参数",-1)),e("div",q,[(r(!0),a(v,null,k(l.params,(i,c)=>(r(),a("div",{key:c,class:"flex items-start gap-3 text-sm"},[e("code",Q,n(i.type||c),1),e("div",H,[e("span",J,n(c),1),i.required?(r(),a("span",K,"*")):p("",!0),e("p",R,n(i.description),1)])]))),128))])])):p("",!0)])])]))),128))])):p("",!0)]))),128))]))])]))}},re=M(W,[["__scopeId","data-v-e8a883e4"]]);export{re as default}; diff --git a/apps/admin/assets/Backup-BzNwk845.css b/apps/admin/assets/Backup-BzNwk845.css new file mode 100644 index 00000000..6d4f88e2 --- /dev/null +++ b/apps/admin/assets/Backup-BzNwk845.css @@ -0,0 +1 @@ +.backup-page[data-v-7ae98012]{display:flex;flex-direction:column;height:calc(100vh - 8rem);min-height:400px}.backup-header[data-v-7ae98012]{flex-shrink:0;padding-bottom:1rem}.backup-content[data-v-7ae98012]{flex:1;min-height:0} diff --git a/apps/admin/assets/Backup-qwqZIMqv.js b/apps/admin/assets/Backup-qwqZIMqv.js new file mode 100644 index 00000000..be974e90 --- /dev/null +++ b/apps/admin/assets/Backup-qwqZIMqv.js @@ -0,0 +1 @@ +import{z as F,o as n,b as l,e,j as g,t as i,F as _,f as C,k as f,r as m,n as R,L as S}from"./vendor-B6xRL-fs.js";import{a as y}from"./admin-DEAtY0pm.js";import{f as $}from"./file-D4KCgIsA.js";import{_ as E}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./ui-42ANG6Sg.js";const N={class:"backup-page"},T={class:"backup-header"},I={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"},U={class:"flex items-center gap-4"},W={class:"hidden sm:flex flex-col text-xs text-gray-500 dark:text-gray-400 border-l border-gray-200 dark:border-gray-700 pl-4"},q={class:"flex gap-2"},G={class:"font-mono text-gray-900 dark:text-gray-300"},J={class:"flex gap-2"},K={class:"font-mono text-gray-900 dark:text-gray-300"},O={class:"flex flex-wrap items-center gap-2"},Q={class:"w-full sm:hidden flex justify-between text-xs text-gray-500 mb-2"},X={class:"font-mono text-gray-900 dark:text-gray-300"},Y={class:"font-mono text-gray-900 dark:text-gray-300"},Z=["disabled"],ee=["disabled"],te=["disabled"],se={class:"backup-content flex-1 flex flex-col lg:flex-row gap-4 min-h-0"},re={class:"card flex-1 flex flex-col min-h-0 min-h-[300px] lg:min-h-0"},ae={class:"flex-1 overflow-y-auto p-2"},oe={class:"bg-white dark:bg-gray-800 font-mono text-xs text-gray-600 dark:text-gray-400"},ne=["title"],le=["onClick"],ie={key:0,class:"py-8 text-center text-gray-400 flex flex-col items-center"},de={class:"card flex-1 flex flex-col min-h-0 min-h-[300px] lg:min-h-0"},ce={class:"px-4 py-3 border-b border-gray-200 dark:border-gray-700 font-semibold text-gray-700 dark:text-gray-200 text-sm bg-gray-50 dark:bg-gray-800/50 flex justify-between items-center"},ue={class:"text-xs font-normal text-gray-400"},ge={class:"flex-1 overflow-y-auto p-3 bg-gray-50/50 dark:bg-gray-900/50 font-mono text-xs"},me={class:"text-gray-400 select-none min-w-[70px] flex-shrink-0"},xe={key:0,class:"py-8 text-center text-gray-400 flex flex-col items-center"},fe={key:0,class:"fixed inset-0 z-50 overflow-y-auto","aria-labelledby":"modal-title",role:"dialog","aria-modal":"true"},ye={class:"flex items-center justify-center min-h-screen p-4 text-center sm:block sm:p-0"},pe={class:"inline-block align-middle bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 max-w-lg w-full"},ve={class:"px-4 pt-5 pb-4 sm:p-6 sm:pb-4"},ke={class:"sm:flex sm:items-start"},he={class:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full"},be={class:"mt-2 text-sm text-gray-500 dark:text-gray-400 font-mono mb-2 bg-gray-100 dark:bg-gray-700 p-2 rounded flex items-center"},we={class:"mt-2 border border-gray-200 dark:border-gray-700 rounded-md overflow-hidden h-64 overflow-y-auto"},_e={class:"divide-y divide-gray-200 dark:divide-gray-700"},Ce=["onClick"],Be={key:0,class:"w-5 h-5 text-yellow-400 mr-3",fill:"currentColor",viewBox:"0 0 20 20"},je={key:1,class:"w-5 h-5 text-gray-400 mr-3",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},De={class:"text-sm font-medium text-gray-900 dark:text-gray-100 flex-1 truncate"},Me=["onClick"],Ae={key:0,class:"px-4 py-4 text-center text-sm text-gray-500"},Le={__name:"Backup",setup(Ve){const o=m({paths:[]}),B=m(!1),d=m(!1),p=m([]),v=m(!1),c=m("."),k=m([]),x=m(["."]),a=(s,t="info")=>{p.value.unshift({time:new Date().toLocaleTimeString(),msg:s,type:t})},h=async()=>{B.value=!0;try{const s=await y.getBackupConfig();s.success?(o.value=s,o.value.paths||(o.value.paths=[])):a("加载配置失败: "+(s.message||"未知错误"),"error")}catch(s){a("加载配置失败: "+s.message,"error")}finally{B.value=!1}},j=async()=>{try{const s=await y.updateBackupConfig(o.value.paths);s.success?a("配置保存成功","success"):a("配置保存失败: "+s.message,"error")}catch(s){a("配置保存出错: "+s.message,"error")}},M=s=>{o.value.paths.splice(s,1),j()},A=async()=>{if(confirm("确定要重置包含文件为默认列表吗?")){d.value=!0,a("正在重置包含文件...","info");try{const s=await y.resetBackupConfig();s.success?(o.value.paths=s.paths,a("重置包含文件成功","success")):a("重置失败: "+s.message,"error")}catch(s){a("重置出错: "+s.message,"error")}finally{d.value=!1}}},L=async()=>{c.value=".",x.value=["."],await w(c.value),v.value=!0},b=()=>{v.value=!1},w=async s=>{try{const t=await $.listDirectory(s);t&&t.files&&(k.value=t.files.sort((r,u)=>r.isDirectory===u.isDirectory?r.name.localeCompare(u.name):r.isDirectory?-1:1))}catch(t){a("加载文件列表失败: "+t.message,"error")}},V=async s=>{const t=c.value==="."?s.name:`${c.value}/${s.name}`;x.value.push(t),c.value=t,await w(t)},H=async()=>{x.value.length>1&&(x.value.pop(),c.value=x.value[x.value.length-1],await w(c.value))},D=s=>{let t=s.path;t.startsWith("./")&&(t=t.substring(2)),o.value.paths.includes(t)||(o.value.paths.push(t),j()),b()},P=async()=>{if(confirm("确定要开始备份吗?")){d.value=!0,a("开始备份...","info");try{const s=await y.createBackup();s.success?(a("备份成功: "+s.message,"success"),s.details&&s.details.forEach(t=>a(t,"info")),await h()):a("备份失败: "+s.message,"error")}catch(s){a("备份出错: "+s.message,"error")}finally{d.value=!1}}},z=async()=>{if(confirm("⚠️ 确定要恢复备份吗?这将覆盖当前系统文件!")){d.value=!0,a("开始恢复...","warning");try{const s=await y.restoreBackup();s.success?(a("恢复成功: "+s.message,"success"),s.details&&s.details.forEach(t=>a(t,"info")),await h()):a("恢复失败: "+s.message,"error")}catch(s){a("恢复出错: "+s.message,"error")}finally{d.value=!1}}};return F(()=>{h(),a("系统准备就绪")}),(s,t)=>(n(),l("div",N,[e("div",T,[e("div",I,[e("div",U,[t[4]||(t[4]=e("div",null,[e("h2",{class:"text-xl font-semibold"},"系统备份与恢复"),e("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 管理系统关键配置 ")],-1)),e("div",W,[e("div",q,[t[0]||(t[0]=e("span",{class:"w-16 text-right flex-shrink-0"},"上回备份:",-1)),t[1]||(t[1]=g()),e("span",G,i(o.value.lastBackupAt?new Date(o.value.lastBackupAt).toLocaleString():"从未"),1)]),e("div",J,[t[2]||(t[2]=e("span",{class:"w-16 text-right flex-shrink-0"},"上回恢复:",-1)),t[3]||(t[3]=g()),e("span",K,i(o.value.lastRestoreAt?new Date(o.value.lastRestoreAt).toLocaleString():"从未"),1)])])]),e("div",O,[e("div",Q,[e("span",null,[t[5]||(t[5]=g("备份: ",-1)),e("span",X,i(o.value.lastBackupAt?new Date(o.value.lastBackupAt).toLocaleDateString():"从未"),1)]),e("span",null,[t[6]||(t[6]=g("恢复: ",-1)),e("span",Y,i(o.value.lastRestoreAt?new Date(o.value.lastRestoreAt).toLocaleDateString():"从未"),1)])]),e("button",{onClick:P,disabled:d.value,class:"btn btn-success flex-1 sm:flex-none"},[...t[7]||(t[7]=[e("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"})],-1),e("span",null,"立即备份",-1)])],8,Z),e("button",{onClick:z,disabled:d.value,class:"btn btn-secondary bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-300 dark:hover:bg-orange-900/50 flex-1 sm:flex-none"},[...t[8]||(t[8]=[e("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m-4-4v12"})],-1),e("span",null,"恢复备份",-1)])],8,ee),e("button",{onClick:A,disabled:d.value,class:"btn btn-secondary bg-red-50 text-red-600 hover:bg-red-100 dark:bg-red-900/30 dark:text-red-400 dark:hover:bg-red-900/50 border-red-200 dark:border-red-800/50 flex-1 sm:flex-none"},[...t[9]||(t[9]=[e("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})],-1),e("span",null,"重置包含",-1)])],8,te)])])]),e("div",se,[e("div",re,[e("div",{class:"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center bg-gray-50 dark:bg-gray-800/50"},[t[11]||(t[11]=e("h3",{class:"text-sm font-semibold text-gray-700 dark:text-gray-200"},"包含文件",-1)),e("button",{onClick:L,class:"text-xs text-primary-600 hover:text-primary-700 dark:text-primary-400 font-medium flex items-center gap-1"},[...t[10]||(t[10]=[e("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 4v16m8-8H4"})],-1),g(" 添加 ",-1)])])]),e("div",ae,[e("div",oe,[(n(!0),l(_,null,C(o.value.paths,(r,u)=>(n(),l("div",{key:r,class:"py-2 px-3 flex justify-between items-center border-b border-dashed border-gray-100 dark:border-gray-700 last:border-0 hover:bg-gray-50 dark:hover:bg-gray-700/50 rounded transition-colors"},[e("span",{class:"truncate break-all mr-2",title:r},i(r),9,ne),e("button",{onClick:He=>M(u),class:"text-gray-400 hover:text-red-500 p-1 flex-shrink-0 transition-colors",title:"删除"},[...t[12]||(t[12]=[e("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"})],-1)])],8,le)]))),128)),!o.value.paths||o.value.paths.length===0?(n(),l("div",ie,[...t[13]||(t[13]=[e("svg",{class:"w-8 h-8 mb-2 opacity-50",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})],-1),g(" 暂无包含文件 ",-1)])])):f("",!0)])])]),e("div",de,[e("div",ce,[t[14]||(t[14]=e("span",null,"操作日志",-1)),e("span",ue,i(p.value.length)+" 条记录",1)]),e("div",ge,[(n(!0),l(_,null,C(p.value,(r,u)=>(n(),l("div",{key:u,class:"mb-2 flex gap-2 pb-1 border-b border-gray-100 dark:border-gray-800/50 last:border-0"},[e("span",me,i(r.time),1),e("span",{class:R(["break-words",{"text-green-600 dark:text-green-400":r.type==="success","text-red-600 dark:text-red-400":r.type==="error","text-orange-500":r.type==="warning","text-gray-700 dark:text-gray-300":r.type==="info"}])},i(r.msg),3)]))),128)),p.value.length===0?(n(),l("div",xe,[...t[15]||(t[15]=[e("svg",{class:"w-8 h-8 mb-2 opacity-50",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})],-1),g(" 暂无日志记录 ",-1)])])):f("",!0)])])]),v.value?(n(),l("div",fe,[e("div",ye,[e("div",{class:"fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity",onClick:b}),t[20]||(t[20]=e("span",{class:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true"},"​",-1)),e("div",pe,[e("div",ve,[e("div",ke,[e("div",he,[t[19]||(t[19]=e("h3",{class:"text-lg leading-6 font-medium text-gray-900 dark:text-gray-100",id:"modal-title"}," 选择文件或目录 ",-1)),e("div",be,[x.value.length>1?(n(),l("button",{key:0,onClick:H,class:"mr-2 text-primary-600 hover:text-primary-700"},[...t[16]||(t[16]=[e("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10 19l-7-7m0 0l7-7m-7 7h18"})],-1)])])):f("",!0),g(" "+i(c.value),1)]),e("div",we,[e("ul",_e,[(n(!0),l(_,null,C(k.value,r=>(n(),l("li",{key:r.name,class:"hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},[e("div",{class:"flex items-center px-4 py-2 cursor-pointer",onClick:u=>r.isDirectory?V(r):D(r)},[r.isDirectory?(n(),l("svg",Be,[...t[17]||(t[17]=[e("path",{d:"M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z"},null,-1)])])):(n(),l("svg",je,[...t[18]||(t[18]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"},null,-1)])])),e("span",De,i(r.name),1),r.isDirectory?(n(),l("button",{key:2,onClick:S(u=>D(r),["stop"]),class:"ml-2 px-2 py-1 text-xs bg-primary-50 text-primary-600 dark:bg-primary-900/30 dark:text-primary-400 rounded hover:bg-primary-100 dark:hover:bg-primary-900/50 transition-colors"}," 选择此目录 ",8,Me)):f("",!0)],8,Ce)]))),128)),k.value.length===0?(n(),l("li",Ae," 空目录 ")):f("",!0)])])])])]),e("div",{class:"bg-gray-50 dark:bg-gray-700/50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"},[e("button",{type:"button",class:"w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-800 text-base font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm",onClick:b}," 取消 ")])])])])):f("",!0)]))}},$e=E(Le,[["__scopeId","data-v-7ae98012"]]);export{$e as default}; diff --git a/apps/admin/assets/Config-B72N75gm.js b/apps/admin/assets/Config-B72N75gm.js new file mode 100644 index 00000000..2626e9a9 --- /dev/null +++ b/apps/admin/assets/Config-B72N75gm.js @@ -0,0 +1 @@ +import{d as R,r as f,z as U,o as n,b as i,e as t,E as M,G as S,k as h,i as y,j as w,F as C,f as j,t as p,y as v,n as q}from"./vendor-B6xRL-fs.js";import{a as A}from"./admin-DEAtY0pm.js";import{_ as F}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./ui-42ANG6Sg.js";const O={async getConfig(){return await A.getConfig()},async updateConfig(g,o){return await A.updateConfig(g,o)},async getConfigValue(g){return await A.getConfig(g)}},N=R("config",()=>{const g=f(null),o=f(!1),l=f(null),c=async()=>{o.value=!0,l.value=null;try{g.value=await O.getConfig()}catch(d){l.value=d.message,console.error("Failed to fetch config:",d)}finally{o.value=!1}};return{config:g,loading:o,error:l,fetchConfig:c,updateConfig:async(d,b)=>{o.value=!0,l.value=null;try{await O.updateConfig(d,b),await c()}catch(k){throw l.value=k.message,console.error("Failed to update config:",k),k}finally{o.value=!1}}}}),$={class:"config-page"},E={class:"config-header"},G={class:"flex flex-col sm:flex-row sm:items-center justify-between gap-4"},J={class:"flex flex-col sm:flex-row items-center gap-3"},X={class:"relative w-full sm:w-64"},Y=["disabled"],Q={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},W={key:1,class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},Z={class:"mt-4 flex overflow-x-auto hide-scrollbar gap-2 pb-1"},ee=["onClick"],te={class:"config-content"},oe={key:0,class:"flex justify-center py-12"},se={key:1,class:"card p-6 border-red-200 dark:border-red-800"},re={class:"text-red-600 dark:text-red-400"},ae={key:2,class:"card p-12 flex flex-col items-center justify-center text-gray-500 dark:text-gray-400"},ne={key:3,class:"space-y-6 pb-6"},ie={class:"px-4 sm:px-6 py-3 sm:py-4 bg-gray-50 dark:bg-gray-700/50 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between"},le={class:"font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2"},de={class:"text-xs font-medium bg-gray-200 dark:bg-gray-600 text-gray-600 dark:text-gray-300 px-2 py-0.5 rounded-full"},ce={class:"divide-y divide-gray-100 dark:divide-gray-800"},ue={class:"flex flex-col sm:flex-row sm:items-start gap-4"},pe={class:"flex-1 min-w-0"},_e={class:"flex items-center gap-2 mb-1"},me={class:"text-base sm:text-lg opacity-80",title:"数据类型"},ge={class:"font-mono text-sm sm:text-base font-bold text-gray-900 dark:text-gray-100 break-all"},ye={key:0,class:"text-xs sm:text-sm text-gray-500 dark:text-gray-400 mb-3 pl-6 sm:pl-7"},fe={key:1,class:"pl-6 sm:pl-7 mt-2"},ke={class:"relative bg-gray-100 dark:bg-gray-800 rounded-md border border-gray-200 dark:border-gray-700 overflow-hidden group-hover:border-primary-300 dark:group-hover:border-primary-700 transition-colors"},be={class:"block p-3 text-xs sm:text-sm font-mono text-gray-800 dark:text-gray-200 break-all whitespace-pre-wrap max-h-32 overflow-y-auto custom-scrollbar"},xe={key:2,class:"pl-0 sm:pl-7 mt-3"},he={class:"bg-primary-50 dark:bg-primary-900/10 p-3 sm:p-4 rounded-lg border border-primary-200 dark:border-primary-800"},ve={class:"block text-xs font-medium text-primary-700 dark:text-primary-400 mb-2"},we=["placeholder"],Ce={class:"flex flex-wrap gap-3 mt-4"},je=["onClick"],Ae={key:0,class:"flex sm:flex-col gap-2 pl-6 sm:pl-0 mt-2 sm:mt-0 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity"},Be=["onClick"],Ke={__name:"Config",setup(g){const o=N(),l=f(null),c=f(""),_=f(""),d=f("全部"),b={quark_cookie:"夸克网盘 Cookie,用于夸克网盘资源解析",quark_token_cookie:"夸克网盘 Token",uc_cookie:"UC 网盘 Cookie",uc_token_cookie:"UC 网盘 Token",ali_token:"阿里云盘 Token",ali_refresh_token:"阿里云盘刷新令牌",pikpak_token:"PikPak Token",xun_username:"迅雷账号",xun_password:"迅雷密码",yun_account:"移动云盘账号",yun_cookie:"移动云盘 Cookie",bili_cookie:"Bilibili Cookie,用于 B站资源解析",spark_ai_authKey:"讯飞星火 AI 认证密钥",deepseek_apiKey:"DeepSeek API 密钥",kimi_apiKey:"Kimi API 密钥",now_ai:"当前使用的 AI 服务 (1=讯飞, 2=DeepSeek, 3=Kimi)",sparkBotObject:"讯飞机器人配置对象",enable_system_proxy:"启用系统代理 (0=禁用, 1=启用)",PROXY_AUTH:"代理认证密码",play_proxy_mode:"播放代理模式",play_local_proxy_type:"本地代理类型",enable_doh:"启用 DoH (0=禁用, 1=启用)",allow_ftp_cache_clear:"允许 FTP 缓存清理 (0=禁用, 1=启用)",allow_webdav_cache_clear:"允许 WebDAV 缓存清理 (0=禁用, 1=启用)",cloud_account:"云盘账号",cloud_password:"云盘密码",cloud_cookie:"云盘 Cookie",pan_passport:"网盘账号",pan_password:"网盘密码",pan_auth:"网盘认证令牌",thread:"并发线程数",api_pwd:"API 访问密码",allow_forward:"允许转发 (0=禁用, 1=启用)",link_url:"链接推送 URL",enable_link_data:"启用链接数据",enable_link_push:"启用链接推送",enable_link_jar:"启用 JAR 链接",mg_hz:"MG 赫兹设置",baidu_cookie:"百度 Cookie,用于百度网盘",enable_rule_name:"显示规则名称 (0=禁用, 1=启用)",must_sub_code:"强制订阅代码 (0=禁用, 1=启用)",enable_dr2:"启用 DR2 引擎 (0=禁用, 1=启用)",enable_py:"启用 Python 引擎 (0=禁用, 1=启用, 2=自动)",enable_php:"启用 PHP 引擎 (0=禁用, 1=启用)",enable_cat:"启用 CatVod 引擎 (0=禁用, 1=启用, 2=自动)",enable_old_config:"启用旧配置格式",show_curl:"显示 cURL 命令",show_req:"显示请求详情",hide_adult:"隐藏成人内容 (0=显示, 1=隐藏)",enable_self_jx:"启用自建解析",cat_sub_code:"CatVod 订阅代码"},k={云盘配置:["quark_cookie","quark_token_cookie","uc_cookie","uc_token_cookie","ali_token","ali_refresh_token","pikpak_token","cloud_account","cloud_password","cloud_cookie","yun_account","yun_cookie","pan_passport","pan_password","pan_auth","xun_username","xun_password"],视频平台:["bili_cookie","baidu_cookie"],"AI 服务":["spark_ai_authKey","deepseek_apiKey","kimi_apiKey","now_ai","sparkBotObject"],代理设置:["enable_system_proxy","PROXY_AUTH","play_proxy_mode","play_local_proxy_type","enable_doh","allow_forward","allow_ftp_cache_clear","allow_webdav_cache_clear"],引擎设置:["enable_dr2","enable_py","enable_php","enable_cat","enable_old_config","enable_self_jx"],其他设置:["thread","api_pwd","link_url","enable_link_data","enable_link_push","enable_link_jar","mg_hz","show_curl","show_req","enable_rule_name","hide_adult","cat_sub_code","must_sub_code"]},B=v(()=>{const s={...k};if(o.config){const e=new Set(Object.values(k).flat()),r=Object.keys(o.config).filter(m=>!e.has(m));r.length>0&&(s.未分类配置=r)}return s}),P=v(()=>["全部",...Object.keys(B.value)]),K=v(()=>{if(!o.config)return{};const s={},e=_.value.toLowerCase().trim();for(const[r,m]of Object.entries(B.value)){if(d.value!=="全部"&&d.value!==r)continue;const u={};for(const a of m)if(o.config){a in o.config&&String(o.config[a]);const x=b[a]||"";(!e||a.toLowerCase().includes(e)||x.toLowerCase().includes(e))&&(u[a]=a in o.config?o.config[a]:"")}Object.keys(u).length>0&&(s[r]=u)}return s}),V=v(()=>Object.keys(K.value).length>0);U(()=>{o.fetchConfig()});const z=(s,e)=>{l.value=s,c.value=typeof e=="object"?JSON.stringify(e,null,2):e},H=()=>{l.value=null,c.value=""},L=async s=>{try{await o.updateConfig(s,c.value),l.value=null,c.value=""}catch(e){alert("保存失败: "+e.message)}},T=(s,e)=>e&&(["cookie","token","password","authKey","apiKey","auth"].some(u=>s.toLowerCase().includes(u))&&typeof e=="string"&&e.length>8?e.substring(0,4)+"****"+e.substring(e.length-4):e),D=s=>s==="0"||s==="1"?"🔢":typeof s=="object"?"📦":"📝",I=s=>typeof s=="object"?JSON.stringify(s):String(s);return(s,e)=>(n(),i("div",$,[t("div",E,[t("div",G,[e[10]||(e[10]=t("div",null,[t("h2",{class:"text-xl font-semibold"},"环境变量配置"),t("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 管理 drpy-node 的环境变量和配置项 ")],-1)),t("div",J,[t("div",X,[e[6]||(e[6]=t("div",{class:"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"},[t("svg",{class:"h-4 w-4 text-gray-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})])],-1)),M(t("input",{"onUpdate:modelValue":e[0]||(e[0]=r=>_.value=r),type:"text",class:"input pl-10 pr-8 w-full",placeholder:"搜索变量名或描述..."},null,512),[[S,_.value]]),_.value?(n(),i("button",{key:0,onClick:e[1]||(e[1]=r=>_.value=""),class:"absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 p-1"},[...e[5]||(e[5]=[t("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])])):h("",!0)]),t("button",{onClick:e[2]||(e[2]=r=>y(o).fetchConfig()),disabled:y(o).loading,class:"btn btn-secondary whitespace-nowrap shrink-0 w-full sm:w-auto justify-center"},[y(o).loading?(n(),i("svg",Q,[...e[7]||(e[7]=[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):(n(),i("svg",W,[...e[8]||(e[8]=[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])),e[9]||(e[9]=w(" 刷新 ",-1))],8,Y)])]),t("div",Z,[(n(!0),i(C,null,j(P.value,r=>(n(),i("button",{key:r,onClick:m=>d.value=r,class:q(["px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap transition-colors",d.value===r?"bg-primary-100 text-primary-700 dark:bg-primary-900/30 dark:text-primary-400":"bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 border border-gray-200 dark:border-gray-700"])},p(r),11,ee))),128))])]),t("div",te,[y(o).loading&&!y(o).config?(n(),i("div",oe,[...e[11]||(e[11]=[t("div",{class:"animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"},null,-1)])])):y(o).error?(n(),i("div",se,[t("p",re,"加载配置失败: "+p(y(o).error),1)])):V.value?(n(),i("div",ne,[(n(!0),i(C,null,j(K.value,(r,m)=>(n(),i("div",{key:m,class:"card overflow-hidden shadow-sm"},[t("div",ie,[t("h3",le,[e[15]||(e[15]=t("span",{class:"w-1.5 h-4 bg-primary-500 rounded-full"},null,-1)),w(" "+p(m),1)]),t("span",de,p(Object.keys(r).length)+" 项 ",1)]),t("div",ce,[(n(!0),i(C,null,j(r,(u,a)=>(n(),i("div",{key:a,class:"p-4 sm:p-5 hover:bg-gray-50 dark:hover:bg-gray-700/30 transition-colors group"},[t("div",ue,[t("div",pe,[t("div",_e,[t("span",me,p(D(u)),1),t("h4",ge,p(a),1)]),b[a]?(n(),i("p",ye,p(b[a]),1)):h("",!0),l.value!==a?(n(),i("div",fe,[t("div",ke,[t("code",be,p(T(a,I(u))||" "),1)])])):(n(),i("div",xe,[t("div",he,[t("label",ve,"编辑 "+p(a),1),M(t("textarea",{"onUpdate:modelValue":e[4]||(e[4]=x=>c.value=x),class:"input min-h-[120px] font-mono text-sm w-full resize-y focus:ring-2 focus:ring-primary-500",placeholder:"输入 "+a+" 的值"},null,8,we),[[S,c.value]]),t("div",Ce,[t("button",{onClick:x=>L(a),class:"btn btn-primary text-sm flex-1 sm:flex-none justify-center"},[...e[16]||(e[16]=[t("svg",{class:"w-4 h-4 mr-1.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M5 13l4 4L19 7"})],-1),w(" 保存更改 ",-1)])],8,je),t("button",{onClick:H,class:"btn btn-secondary text-sm flex-1 sm:flex-none justify-center"}," 取消编辑 ")])])]))]),l.value!==a?(n(),i("div",Ae,[t("button",{onClick:x=>z(a,u),class:"flex items-center gap-1.5 px-3 py-1.5 sm:p-2 rounded-md bg-white sm:bg-transparent border border-gray-300 sm:border-transparent text-gray-700 dark:text-gray-300 hover:bg-primary-50 dark:hover:bg-gray-700 hover:text-primary-600 dark:hover:text-primary-400 transition-colors shadow-sm sm:shadow-none text-sm font-medium",title:"编辑此项"},[...e[17]||(e[17]=[t("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"})],-1),t("span",{class:"sm:hidden"},"编辑",-1)])],8,Be)])):h("",!0)])]))),128))])]))),128))])):(n(),i("div",ae,[e[12]||(e[12]=t("svg",{class:"w-12 h-12 mb-4 text-gray-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"1.5",d:"M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})],-1)),e[13]||(e[13]=t("p",{class:"text-lg font-medium text-gray-900 dark:text-gray-100"},"未找到匹配的配置项",-1)),e[14]||(e[14]=t("p",{class:"mt-1"},"请尝试更换搜索词或选择其他分类",-1)),_.value||d.value!=="全部"?(n(),i("button",{key:0,onClick:e[3]||(e[3]=r=>{_.value="",d.value="全部"}),class:"mt-4 text-primary-600 hover:text-primary-700 font-medium"}," 清除筛选 ")):h("",!0)]))])]))}},Ve=F(Ke,[["__scopeId","data-v-1086944a"]]);export{Ve as default}; diff --git a/apps/admin/assets/Config-CsAT4E8O.css b/apps/admin/assets/Config-CsAT4E8O.css new file mode 100644 index 00000000..4917d826 --- /dev/null +++ b/apps/admin/assets/Config-CsAT4E8O.css @@ -0,0 +1 @@ +.config-page[data-v-1086944a]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.config-header[data-v-1086944a]{flex-shrink:0;padding-bottom:1rem}.config-content[data-v-1086944a]{flex:1;overflow-y:auto;min-height:0}.hide-scrollbar[data-v-1086944a]{-ms-overflow-style:none;scrollbar-width:none}.hide-scrollbar[data-v-1086944a]::-webkit-scrollbar{display:none}.custom-scrollbar[data-v-1086944a]::-webkit-scrollbar{width:6px;height:6px}.custom-scrollbar[data-v-1086944a]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-1086944a]::-webkit-scrollbar-thumb{background:#9ca3af80;border-radius:3px}.custom-scrollbar[data-v-1086944a]::-webkit-scrollbar-thumb:hover{background:#6b7280cc} diff --git a/apps/admin/assets/Dashboard-CB7r-Nk7.js b/apps/admin/assets/Dashboard-CB7r-Nk7.js new file mode 100644 index 00000000..08e8a54d --- /dev/null +++ b/apps/admin/assets/Dashboard-CB7r-Nk7.js @@ -0,0 +1 @@ +import{u as V}from"./system-BaTh0baW.js";import{_ as H}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{z as S,v as z,o as u,b as p,e,n as x,j as N,t as a,i as o,k as L,g as d,h as i,r as _,D as A}from"./vendor-B6xRL-fs.js";import"./system-CxybzrTo.js";import"./admin-DEAtY0pm.js";import"./ui-42ANG6Sg.js";import"./spider-Bxy9e0gU.js";const U={class:"dashboard-page"},D={class:"dashboard-header"},I={class:"card p-6"},J={class:"flex items-center justify-between mb-4"},O={class:"flex items-center gap-3"},P=["disabled"],R={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},$={key:1,class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},E={class:"flex items-center justify-between"},K={class:"flex items-center gap-3"},T={class:"text-gray-600 dark:text-gray-400"},W={key:0,class:"text-sm text-gray-500"},Y={class:"mt-4 pt-4 border-t border-gray-100 dark:border-gray-700 flex justify-between items-center text-sm"},q={class:"badge badge-info font-mono text-xs"},F={class:"dashboard-content flex flex-col gap-4"},G={class:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3"},Q={class:"card p-4"},X={class:"flex items-center justify-between"},Z={class:"text-xl font-bold text-gray-900 dark:text-gray-100 mt-0.5"},ee={class:"card p-4"},te={class:"flex items-center justify-between"},re={class:"text-xl font-bold text-gray-900 dark:text-gray-100 mt-0.5"},se={class:"card p-4"},oe={class:"flex items-center justify-between"},ae={class:"text-xl font-bold text-gray-900 dark:text-gray-100 mt-0.5"},le={class:"card p-4"},ne={class:"flex items-center justify-between"},de={class:"text-xl font-bold text-gray-900 dark:text-gray-100 mt-0.5"},ie={class:"card p-4"},ce={class:"flex items-center justify-between"},ge={class:"text-xl font-bold text-gray-900 dark:text-gray-100 mt-0.5"},ue={class:"card p-4"},pe={class:"flex items-center justify-between"},he={class:"text-xl font-bold text-gray-900 dark:text-gray-100 mt-0.5"},xe={class:"card p-5"},me={class:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3"},fe={__name:"Dashboard",setup(ke){const r=V(),h=_(null);S(async()=>{await r.checkHealth(),await r.fetchRoutes(),await r.fetchSources(),h.value=setInterval(()=>{r.checkHealth()},3e4)}),z(()=>{h.value&&clearInterval(h.value)});const M=l=>{switch(l){case"ok":case"healthy":return"badge-success";case"error":case"unhealthy":return"badge-error";default:return"badge-warning"}},g=_(!1),C=l=>{if(!l)return"0秒";const t=Math.floor(l/(3600*24)),s=Math.floor(l%(3600*24)/3600),n=Math.floor(l%3600/60);let c="";return t>0&&(c+=`${t}天`),(s>0||t>0)&&(c+=`${s}时`),c+=`${n}分`,c},B=async()=>{var l,t;if(confirm("确定要重启 drpy-node 服务吗?这将中断所有连接。")){g.value=!0;try{const s=await r.restartService();let n="操作已完成";try{(t=(l=s==null?void 0:s.content)==null?void 0:l[0])!=null&&t.text?n=JSON.parse(s.content[0].text).message||n:typeof s=="string"&&(n=JSON.parse(s).message||s)}catch{n="操作已完成,请检查服务状态"}alert(n)}catch(s){alert("重启失败: "+s.message)}finally{g.value=!1}}};return(l,t)=>{var n,c,m,f,k,v,y,b,w,j;const s=A("RouterLink");return u(),p("div",U,[e("div",D,[e("div",I,[e("div",J,[t[2]||(t[2]=e("h3",{class:"text-lg font-semibold"},"服务状态",-1)),e("div",O,[e("button",{onClick:B,disabled:g.value,class:x(["btn btn-secondary text-sm",{"opacity-50 cursor-not-allowed":g.value}])},[g.value?(u(),p("svg",R,[...t[0]||(t[0]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):(u(),p("svg",$,[...t[1]||(t[1]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])),N(" "+a(g.value?"重启中...":"重启服务"),1)],10,P),e("span",{class:x(["badge",M(o(r).health.status)])},a(((n=o(r).health.status)==null?void 0:n.toUpperCase())||"UNKNOWN"),3)])]),e("div",E,[e("div",K,[e("div",{class:x(["w-3 h-3 rounded-full animate-pulse-slow",o(r).health.status==="ok"||o(r).health.status==="healthy"?"bg-green-500":"bg-red-500"])},null,2),e("span",T,a(o(r).health.status==="ok"||o(r).health.status==="healthy"?"服务运行正常":"服务异常"),1)]),o(r).health.uptime?(u(),p("span",W," 运行时长: "+a(C(o(r).health.uptime)),1)):L("",!0)]),e("div",Y,[t[3]||(t[3]=e("span",{class:"text-gray-500"},"系统版本",-1)),e("span",q,"v"+a(o(r).health.version||"Unknown"),1)])])]),e("div",F,[e("div",G,[e("div",Q,[e("div",X,[e("div",null,[t[4]||(t[4]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"JS 源",-1)),e("p",Z,a(((c=o(r).sources.js)==null?void 0:c.length)||0),1)]),t[5]||(t[5]=e("div",{class:"w-10 h-10 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center"},[e("svg",{class:"w-5 h-5 text-blue-600 dark:text-blue-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})])],-1))])]),e("div",ee,[e("div",te,[e("div",null,[t[6]||(t[6]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"CatVod 源",-1)),e("p",re,a(((m=o(r).sources.catvod)==null?void 0:m.length)||0),1)]),t[7]||(t[7]=e("div",{class:"w-10 h-10 rounded-lg bg-purple-100 dark:bg-purple-900/30 flex items-center justify-center"},[e("svg",{class:"w-5 h-5 text-purple-600 dark:text-purple-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M5 19a2 2 0 01-2-2V7a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1M5 19h14a2 2 0 002-2v-5a2 2 0 00-2-2H9a2 2 0 00-2 2v5a2 2 0 01-2 2z"})])],-1))])]),e("div",se,[e("div",oe,[e("div",null,[t[8]||(t[8]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"PHP 源",-1)),e("p",ae,a(((f=o(r).sources.php)==null?void 0:f.length)||0),1)]),t[9]||(t[9]=e("div",{class:"w-10 h-10 rounded-lg bg-indigo-100 dark:bg-indigo-900/30 flex items-center justify-center"},[e("svg",{class:"w-5 h-5 text-indigo-600 dark:text-indigo-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"})])],-1))])]),e("div",le,[e("div",ne,[e("div",null,[t[10]||(t[10]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"PY 源",-1)),e("p",de,a(((k=o(r).sources.py)==null?void 0:k.length)||0),1)]),t[11]||(t[11]=e("div",{class:"w-10 h-10 rounded-lg bg-yellow-100 dark:bg-yellow-900/30 flex items-center justify-center"},[e("svg",{class:"w-5 h-5 text-yellow-600 dark:text-yellow-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 10V3L4 14h7v7l9-11h-7z"})])],-1))])]),e("div",ie,[e("div",ce,[e("div",null,[t[12]||(t[12]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"总源数",-1)),e("p",ge,a((((v=o(r).sources.js)==null?void 0:v.length)||0)+(((y=o(r).sources.catvod)==null?void 0:y.length)||0)+(((b=o(r).sources.php)==null?void 0:b.length)||0)+(((w=o(r).sources.py)==null?void 0:w.length)||0)),1)]),t[13]||(t[13]=e("div",{class:"w-10 h-10 rounded-lg bg-orange-100 dark:bg-orange-900/30 flex items-center justify-center"},[e("svg",{class:"w-5 h-5 text-orange-600 dark:text-orange-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 6h16M4 10h16M4 14h16M4 18h16"})])],-1))])]),e("div",ue,[e("div",pe,[e("div",null,[t[14]||(t[14]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"路由数",-1)),e("p",he,a(((j=o(r).routes.registered_controllers)==null?void 0:j.length)||0),1)]),t[15]||(t[15]=e("div",{class:"w-10 h-10 rounded-lg bg-green-100 dark:bg-green-900/30 flex items-center justify-center"},[e("svg",{class:"w-5 h-5 text-green-600 dark:text-green-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"})])],-1))])])]),e("div",xe,[t[26]||(t[26]=e("h3",{class:"text-base font-semibold mb-3"},"快捷操作",-1)),e("div",me,[d(s,{to:"/config",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[16]||(t[16]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z"})],-1),e("span",{class:"text-sm font-medium"},"环境配置",-1)])]),_:1}),d(s,{to:"/sources",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[17]||(t[17]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 6h16M4 10h16M4 14h16M4 18h16"})],-1),e("span",{class:"text-sm font-medium"},"源管理",-1)])]),_:1}),d(s,{to:"/map-manager",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[18]||(t[18]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7"})],-1),e("span",{class:"text-sm font-medium"},"站源映射",-1)])]),_:1}),d(s,{to:"/parses",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[19]||(t[19]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"})],-1),e("span",{class:"text-sm font-medium"},"解析管理",-1)])]),_:1}),d(s,{to:"/files",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[20]||(t[20]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"})],-1),e("span",{class:"text-sm font-medium"},"文件管理",-1)])]),_:1}),d(s,{to:"/database",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[21]||(t[21]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"})],-1),e("span",{class:"text-sm font-medium"},"数据库",-1)])]),_:1}),d(s,{to:"/api-docs",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[22]||(t[22]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})],-1),e("span",{class:"text-sm font-medium"},"接口文档",-1)])]),_:1}),d(s,{to:"/logs",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[23]||(t[23]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})],-1),e("span",{class:"text-sm font-medium"},"日志查看",-1)])]),_:1}),d(s,{to:"/subscription",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[24]||(t[24]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"})],-1),e("span",{class:"text-sm font-medium"},"订阅管理",-1)])]),_:1}),d(s,{to:"/backup",class:"flex flex-col items-center justify-center gap-2 p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"},{default:i(()=>[...t[25]||(t[25]=[e("svg",{class:"w-6 h-6 text-primary-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})],-1),e("span",{class:"text-sm font-medium"},"备份恢复",-1)])]),_:1})])])])])}}},Ce=H(fe,[["__scopeId","data-v-7050095a"]]);export{Ce as default}; diff --git a/apps/admin/assets/Dashboard-CDeJVBM_.css b/apps/admin/assets/Dashboard-CDeJVBM_.css new file mode 100644 index 00000000..3f3e163d --- /dev/null +++ b/apps/admin/assets/Dashboard-CDeJVBM_.css @@ -0,0 +1 @@ +.dashboard-page[data-v-7050095a]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.dashboard-header[data-v-7050095a]{flex-shrink:0;padding-bottom:1rem}.dashboard-content[data-v-7050095a]{flex:1;overflow-y:auto;min-height:0} diff --git a/apps/admin/assets/Database-CBuEZ2qV.js b/apps/admin/assets/Database-CBuEZ2qV.js new file mode 100644 index 00000000..ca1f627c --- /dev/null +++ b/apps/admin/assets/Database-CBuEZ2qV.js @@ -0,0 +1 @@ +import{o as t,b as a,e,F as y,f as g,E,G as q,K as k,L as h,k as m,j as A,t as i,r as b}from"./vendor-B6xRL-fs.js";import{a as _}from"./admin-DEAtY0pm.js";import{_ as T}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./ui-42ANG6Sg.js";const C={async query(d){return(await _.executeQuery(d)).data},async getTables(){return(await _.getTables()).tables},async getTableSchema(d){return(await _.getTableSchema(d)).columns}},L={class:"database-page"},M={class:"database-header"},R={class:"card p-4"},S={class:"flex flex-wrap gap-2"},Q=["onClick"],j={class:"database-content"},B={class:"card overflow-hidden"},D={class:"p-4 border-b border-gray-200 dark:border-gray-700"},O=["onKeydown"],F={class:"flex items-center justify-between mt-3"},K=["disabled"],V={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},H={key:0,class:"p-4 bg-red-50 dark:bg-red-900/20 border-t border-red-200 dark:border-red-800"},I={class:"text-red-600 dark:text-red-400 font-mono text-sm"},N={key:1,class:"overflow-x-auto"},G={key:0,class:"min-w-full"},z={class:"w-full text-sm"},P={class:"bg-gray-50 dark:bg-gray-700/50"},U={class:"divide-y divide-gray-200 dark:divide-gray-700"},W={key:1,class:"p-8 text-center text-gray-500"},Y={key:2,class:"p-4 text-sm text-gray-500 dark:text-gray-400 border-t border-gray-200 dark:border-gray-700"},$={__name:"Database",setup(d){const l=b(""),s=b(null),u=b(!1),c=b(null),f=[{name:"查看所有表",sql:"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"},{name:"查看表结构",sql:"PRAGMA table_info(table_name);"},{name:"查询前10条记录",sql:"SELECT * FROM table_name LIMIT 10;"}],v=async()=>{if(l.value.trim()){u.value=!0,c.value=null,s.value=null;try{const n=await C.query(l.value);s.value=n}catch(n){c.value=n.message}finally{u.value=!1}}},w=n=>{l.value=n};return(n,r)=>(t(),a("div",L,[e("div",M,[r[2]||(r[2]=e("div",null,[e("h2",{class:"text-xl font-semibold"},"数据库查询"),e("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 执行只读 SQL 查询 ")],-1)),e("div",R,[r[1]||(r[1]=e("h3",{class:"text-sm font-medium text-gray-700 dark:text-gray-300 mb-3"},"示例查询",-1)),e("div",S,[(t(),a(y,null,g(f,o=>e("button",{key:o.name,onClick:x=>w(o.sql),class:"px-3 py-1.5 text-sm rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"},i(o.name),9,Q)),64))])])]),e("div",j,[e("div",B,[e("div",D,[E(e("textarea",{"onUpdate:modelValue":r[0]||(r[0]=o=>l.value=o),placeholder:"输入 SQL 查询语句...",class:"w-full min-h-[120px] p-3 bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg font-mono text-sm resize-none focus:outline-none focus:ring-2 focus:ring-primary-500",spellcheck:"false",onKeydown:[k(h(v,["ctrl"]),["enter"]),k(h(v,["meta"]),["enter"])]},null,40,O),[[q,l.value]]),e("div",F,[r[5]||(r[5]=e("span",{class:"text-xs text-gray-500"}," 按 Ctrl+Enter 执行查询 ",-1)),e("button",{onClick:v,disabled:u.value||!l.value.trim(),class:"btn btn-primary"},[u.value?(t(),a("svg",V,[...r[3]||(r[3]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):m("",!0),r[4]||(r[4]=A(" 执行查询 ",-1))],8,K)])]),c.value?(t(),a("div",H,[e("p",I,i(c.value),1)])):m("",!0),s.value?(t(),a("div",N,[Array.isArray(s.value)&&s.value.length>0?(t(),a("div",G,[e("table",z,[e("thead",P,[e("tr",null,[(t(!0),a(y,null,g(Object.keys(s.value[0]),o=>(t(),a("th",{key:o,class:"px-4 py-3 text-left font-medium text-gray-700 dark:text-gray-300 border-b border-gray-200 dark:border-gray-700"},i(o),1))),128))])]),e("tbody",U,[(t(!0),a(y,null,g(s.value,(o,x)=>(t(),a("tr",{key:x,class:"hover:bg-gray-50 dark:hover:bg-gray-700/30"},[(t(!0),a(y,null,g(Object.keys(s.value[0]),p=>(t(),a("td",{key:p,class:"px-4 py-3 font-mono text-gray-900 dark:text-gray-100"},i(o[p]),1))),128))]))),128))])])])):(t(),a("div",W," 查询成功,无结果返回 ")),s.value&&Array.isArray(s.value)?(t(),a("div",Y," 查询返回 "+i(s.value.length)+" 行结果 ",1)):m("",!0)])):m("",!0)])])]))}},te=T($,[["__scopeId","data-v-b4aae15e"]]);export{te as default}; diff --git a/apps/admin/assets/Database-VwOSuNal.css b/apps/admin/assets/Database-VwOSuNal.css new file mode 100644 index 00000000..f7b41b98 --- /dev/null +++ b/apps/admin/assets/Database-VwOSuNal.css @@ -0,0 +1 @@ +.database-page[data-v-b4aae15e]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.database-header[data-v-b4aae15e]{flex-shrink:0;padding-bottom:1rem}.database-content[data-v-b4aae15e]{flex:1;overflow-y:auto;min-height:0} diff --git a/apps/admin/assets/Files-67eeMvv5.js b/apps/admin/assets/Files-67eeMvv5.js new file mode 100644 index 00000000..08b5eaf5 --- /dev/null +++ b/apps/admin/assets/Files-67eeMvv5.js @@ -0,0 +1 @@ +import{f as F}from"./file-D4KCgIsA.js";import{_ as N}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{z as A,o,b as r,e,F as D,f as E,k as h,t as i,I as T,r as p,y as P,n as _,j as V}from"./vendor-B6xRL-fs.js";import"./admin-DEAtY0pm.js";import"./ui-42ANG6Sg.js";const z={class:"files-page"},U={class:"files-header"},X={class:"card p-4"},O={class:"flex items-center gap-2 text-sm overflow-x-auto"},R=["onClick"],$={key:0,class:"w-4 h-4 text-gray-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},q={class:"files-content"},G={class:"grid grid-cols-1 lg:grid-cols-2 gap-6 h-full"},H={class:"card flex flex-col h-full overflow-hidden"},W={class:"divide-y divide-gray-200 dark:divide-gray-700 flex-1 overflow-y-auto"},J={key:0,class:"p-12 text-center"},K=["onClick"],Q={class:"text-xl"},Y={key:0,class:"badge badge-info text-xs shrink-0"},Z={key:1,class:"badge badge-gray text-xs shrink-0"},ee={key:2,class:"text-xs text-gray-500 shrink-0"},te={key:1,class:"p-12 text-center text-gray-500"},se={class:"card hidden lg:flex flex-col h-full overflow-hidden"},ae={key:0,class:"h-full flex flex-col"},oe={class:"px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between shrink-0"},re={class:"flex items-center gap-3 overflow-hidden"},le={class:"text-xl shrink-0"},ne={class:"min-w-0"},ie={class:"font-semibold truncate"},de={class:"text-xs text-gray-500 truncate"},ce={class:"flex-1 overflow-y-auto p-4 bg-gray-50 dark:bg-gray-900"},ue={key:0,class:"h-full flex items-center justify-center"},pe=["src","alt"],ve={key:2,class:"text-sm font-mono whitespace-pre-wrap break-words"},ge={key:1,class:"h-full flex items-center justify-center p-12 text-gray-500"},he={key:0,class:"fixed inset-0 z-50 flex lg:hidden items-center justify-center p-4 bg-black/50 backdrop-blur-sm"},me={class:"bg-white dark:bg-gray-800 rounded-xl shadow-xl w-full h-full max-h-[90vh] flex flex-col overflow-hidden"},xe={class:"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between shrink-0"},ye={class:"flex items-center gap-3 overflow-hidden"},fe={class:"text-xl shrink-0"},ke={class:"min-w-0"},_e={class:"font-semibold truncate"},be={class:"text-xs text-gray-500 truncate"},we={class:"flex-1 overflow-y-auto p-4 bg-gray-50 dark:bg-gray-900"},je={key:0,class:"h-full flex items-center justify-center"},Ce=["src","alt"],Se={key:2,class:"text-sm font-mono whitespace-pre-wrap break-words"},Fe={__name:"Files",setup(De){const b=p("."),m=p([]),v=p(!1),n=p(null),d=p(""),u=p("text"),c=p(""),B=new Set(["js","json","md","txt","html","htm","css","scss","less","xml","py","php","ts","vue","jsx","tsx","yaml","yml","ini","conf","config","env","gitignore","eslintrc","prettierrc","babelrc","editorconfig","lock","csv","sql","sh","bat","cmd","ps1","log","out","err","c","cpp","h","hpp","cs","go","rs","rb","java","kt","dart","swift","properties","toml","pom","gradle"]),M=new Set(["png","jpg","jpeg","gif","svg","webp","ico","bmp","tiff","tif"]),L=new Set(["license","makefile","dockerfile","caddyfile","readme","changelog","authors"]),w=a=>{const t=a.toLowerCase();let s="";return t.includes(".")&&(s=t.split(".").pop()),s&&M.has(s)?"image":s&&B.has(s)||L.has(t)?"text":"unsupported"},j=a=>w(a)!=="unsupported",x=P(()=>{const a=b.value.split("/").filter(Boolean);return[{name:"根目录",path:"."},...a.map((t,s)=>({name:t,path:a.slice(0,s+1).join("/")}))]}),C=a=>!a.includes("..")&&!a.startsWith("~");A(()=>{y(".")});const y=async a=>{if(!C(a)){alert("不安全的路径");return}v.value=!0,b.value=a,n.value=null,d.value="",u.value="text",c.value="";try{const t=await F.listDirectory(a);m.value=t.files||[]}catch(t){alert("加载目录失败: "+t.message)}finally{v.value=!1}},I=async a=>{if(!C(a.path)){alert("不安全的路径");return}const t=w(a.name);if(t==="unsupported"){n.value=a,u.value="unsupported",d.value="",c.value="";return}v.value=!0;try{const s=await F.readFile(a.path);console.log("File read result:",typeof s,s),n.value=a,u.value=t,t==="image"?(typeof s=="string"?c.value=s:(s==null?void 0:s.type)==="image"&&s.dataUrl?c.value=s.dataUrl:c.value=s||"",d.value=""):(typeof s=="string"?d.value=s:(s==null?void 0:s.type)==="text"&&s.content?d.value=s.content:d.value=String(s||""),c.value="")}catch(s){console.error("Read file error:",s),alert("读取文件失败: "+s.message),n.value=null}finally{v.value=!1}},S=()=>{n.value=null,d.value="",u.value="text",c.value=""},f=a=>{var g;if(a.isDirectory)return"📁";const t=(g=a.name.split(".").pop())==null?void 0:g.toLowerCase();return{js:"📜",json:"📋",md:"📝",txt:"📄",html:"🌐",css:"🎨",png:"🖼️",jpg:"🖼️",svg:"🎭",gif:"🎞️"}[t]||"📄"};return(a,t)=>{var s,g;return o(),r("div",z,[e("div",U,[t[1]||(t[1]=e("div",null,[e("h2",{class:"text-xl font-semibold"},"文件管理"),e("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 浏览和编辑项目文件 ")],-1)),e("div",X,[e("nav",O,[(o(!0),r(D,null,E(x.value,(l,k)=>(o(),r("button",{key:l.path,onClick:Ee=>y(l.path),class:_(["flex items-center gap-2 px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors whitespace-nowrap",{"font-medium":k===x.value.length-1}])},[V(i(l.name)+" ",1),k(o(),r("div",{key:l.name,onClick:k=>l.isDirectory?y(l.path):I(l),class:_(["px-6 py-3 hover:bg-gray-50 dark:hover:bg-gray-700/30 cursor-pointer transition-colors flex items-center gap-3",{"opacity-50":!l.isDirectory&&!j(l.name)}])},[e("span",Q,i(f(l)),1),e("span",{class:_(["flex-1 truncate",{"font-medium":l.isDirectory}])},i(l.name),3),l.isDirectory?(o(),r("span",Y,"DIR")):j(l.name)?(o(),r("span",ee,i(l.size||""),1)):(o(),r("span",Z,"不支持预览"))],10,K))),128)),!v.value&&m.value.length===0?(o(),r("div",te," 此目录为空 ")):h("",!0)])]),e("div",se,[n.value?(o(),r("div",ae,[e("div",oe,[e("div",re,[e("span",le,i(f(n.value)),1),e("div",ne,[e("h3",ie,i(n.value.name),1),e("p",de,i(n.value.path),1)])]),e("button",{onClick:S,class:"p-2 shrink-0 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600"},[...t[4]||(t[4]=[e("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])])]),e("div",ce,[u.value==="unsupported"?(o(),r("div",ue,[...t[5]||(t[5]=[T('

暂不支持预览此文件类型

支持的文件类型:文本文件 (.js, .json, .md, .txt 等) 和 图片文件 (.png, .jpg, .svg 等)

',1)])])):u.value==="image"?(o(),r("img",{key:1,src:c.value,alt:(s=n.value)==null?void 0:s.name,class:"max-w-full h-auto mx-auto"},null,8,pe)):(o(),r("pre",ve,i(d.value),1))])])):(o(),r("div",ge,[...t[6]||(t[6]=[e("div",{class:"text-center"},[e("svg",{class:"w-16 h-16 mx-auto mb-4 text-gray-300 dark:text-gray-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})]),e("p",null,"选择一个文件查看内容")],-1)])]))])])]),n.value?(o(),r("div",he,[e("div",me,[e("div",xe,[e("div",ye,[e("span",fe,i(f(n.value)),1),e("div",ke,[e("h3",_e,i(n.value.name),1),e("p",be,i(n.value.path),1)])]),e("button",{onClick:S,class:"p-2 shrink-0 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600"},[...t[7]||(t[7]=[e("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])])]),e("div",we,[u.value==="unsupported"?(o(),r("div",je,[...t[8]||(t[8]=[T('

暂不支持预览此文件类型

支持的文件类型:文本文件 和 图片文件

',1)])])):u.value==="image"?(o(),r("img",{key:1,src:c.value,alt:(g=n.value)==null?void 0:g.name,class:"max-w-full h-auto mx-auto"},null,8,Ce)):(o(),r("pre",Se,i(d.value),1))])])])):h("",!0)])}}},Ne=N(Fe,[["__scopeId","data-v-5524d645"]]);export{Ne as default}; diff --git a/apps/admin/assets/Files-DRnFcRx1.css b/apps/admin/assets/Files-DRnFcRx1.css new file mode 100644 index 00000000..4b1af8f8 --- /dev/null +++ b/apps/admin/assets/Files-DRnFcRx1.css @@ -0,0 +1 @@ +.files-page[data-v-5524d645]{display:flex;flex-direction:column;height:calc(100vh - 6rem);min-height:500px}.files-header[data-v-5524d645]{flex-shrink:0;padding-bottom:1rem}.files-content[data-v-5524d645]{flex:1;overflow:hidden;min-height:0} diff --git a/apps/admin/assets/Logs-D_O--y9N.js b/apps/admin/assets/Logs-D_O--y9N.js new file mode 100644 index 00000000..c0f71863 --- /dev/null +++ b/apps/admin/assets/Logs-D_O--y9N.js @@ -0,0 +1 @@ +import{z as $,v as V,w as j,o as u,b as g,e as t,n as h,j as k,t as b,E as I,J as A,F as S,f as J,r as v,A as _}from"./vendor-B6xRL-fs.js";import{_ as U}from"./_plugin-vue_export-helper-DlAUqK2U.js";const z={class:"logs-page"},D={class:"logs-header"},P={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"},F={class:"flex items-center gap-2"},G={class:"logs-viewer card"},H={class:"logs-toolbar"},R={class:"flex items-center gap-4"},K={class:"flex items-center gap-2 text-sm"},q={class:"text-sm text-gray-500 dark:text-gray-400"},Q={key:0,class:"text-center py-12 text-gray-500"},X={class:"text-gray-500 flex-shrink-0 select-none"},N=5,Y={__name:"Logs",setup(Z){const a=v(null),p=v(!0),n=v(!1),f=v(null),c=v([]),T=v(1e3);let o=null,d=null,i=0;const W=()=>{const s=window.BACKEND_URL;if(s){const m=s.startsWith("https")?"wss:":"ws:",M=s.replace(/^https?:\/\//,"").replace(/\/$/,"");return`${m}//${M}/api/admin/logs/stream`}const e=window.location.protocol==="https:"?"wss:":"ws:",r=window.location.host;return`${e}//${r}/ws`},y=()=>{o&&(o.readyState===WebSocket.CONNECTING||o.readyState===WebSocket.OPEN)||(o=new WebSocket(W()),o.onopen=()=>{console.log("WebSocket connected"),n.value=!0,f.value=null,i=0,o.readyState===WebSocket.OPEN&&o.send(JSON.stringify({type:"heartbeat"}))},o.onmessage=s=>{try{const e=JSON.parse(s.data);switch(e.type){case"welcome":l("✓ 已连接到日志服务器","info");break;case"console":case"log":e.content?l(e.content,e.level||"info"):e.message&&l(e.message,e.level||"info");break;case"broadcast":e.content&&l(`[广播] ${e.content}`,"info");break;case"echo":case"pong":break;default:e.message||e.content?l(e.message||e.content,"info"):l(JSON.stringify(e),"debug")}}catch{l(s.data,"log")}},o.onerror=s=>{console.error("WebSocket error:",s),f.value="连接错误"},o.onclose=s=>{console.log("WebSocket closed:",s.code,s.reason),n.value=!1,i{y()},i*1e3)):(l("连接已断开,请刷新页面重试","error"),f.value="连接已断开")})},C=()=>{d&&(clearTimeout(d),d=null),o&&(o.onopen=null,o.onmessage=null,o.onerror=null,o.onclose=null,(o.readyState===WebSocket.OPEN||o.readyState===WebSocket.CONNECTING)&&o.close(1e3,"Component unmounted"),o=null),n.value=!1,f.value=null},l=(s,e="info")=>{const r=new Date().toLocaleTimeString(),m=typeof s=="string"?s:String(s);c.value.push({timestamp:r,message:m,level:e}),c.value.length>T.value&&c.value.shift(),p.value&&_(()=>{_(()=>{w()})})},E=()=>{c.value=[]},w=()=>{if(a.value){const s=a.value.lastElementChild;s?s.scrollIntoView({behavior:"instant",block:"end"}):a.value.scrollTop=a.value.scrollHeight}},L=()=>{a.value&&(a.value.scrollTop=0)},B=()=>{n.value?C():(i=0,y())},O=s=>{switch(s){case"error":case"err":return"text-red-400";case"warn":case"warning":return"text-yellow-400";case"info":return"text-blue-400";case"debug":return"text-gray-500";default:return"text-gray-300"}};let x=null;return $(()=>{y(),x=setInterval(()=>{o&&o.readyState===WebSocket.OPEN&&o.send(JSON.stringify({type:"heartbeat"}))},3e4)}),V(()=>{x&&(clearInterval(x),x=null),C(),d&&(clearTimeout(d),d=null),n.value=!1,f.value=null,c.value=[],i=0,a.value=null}),j(p,()=>{p.value&&w()}),(s,e)=>(u(),g("div",z,[t("div",D,[t("div",P,[e[3]||(e[3]=t("div",null,[t("h2",{class:"text-xl font-semibold"},"日志查看"),t("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 实时查看应用运行日志 ")],-1)),t("div",F,[t("div",{class:h(["flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm font-medium",n.value?"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400":"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"])},[t("span",{class:h(["w-2 h-2 rounded-full animate-pulse",n.value?"bg-green-500":"bg-red-500"])},null,2),k(" "+b(n.value?"已连接":"未连接"),1)],2),t("button",{onClick:B,class:h(["btn",n.value?"btn-secondary":"btn-primary"])},[e[1]||(e[1]=t("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 10V3L4 14h7v7l9-11h-7z"})],-1)),k(" "+b(n.value?"断开":"连接"),1)],2),t("button",{onClick:E,class:"btn btn-secondary"},[...e[2]||(e[2]=[t("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"})],-1),k(" 清空 ",-1)])])])])]),t("div",G,[t("div",H,[t("div",R,[t("label",K,[I(t("input",{type:"checkbox","onUpdate:modelValue":e[0]||(e[0]=r=>p.value=r),class:"rounded border-gray-300 dark:border-gray-600 text-primary-600 focus:ring-primary-500"},null,512),[[A,p.value]]),e[4]||(e[4]=k(" 自动滚动到底部 ",-1))]),t("span",q,b(c.value.length)+" 条日志 ",1)]),t("div",{class:"flex gap-2"},[t("button",{onClick:L,class:"p-1.5 rounded hover:bg-gray-200 dark:hover:bg-gray-600",title:"滚动到顶部"},[...e[5]||(e[5]=[t("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M5 10l7-7m0 0l7 7m-7-7v18"})],-1)])]),t("button",{onClick:w,class:"p-1.5 rounded hover:bg-gray-200 dark:hover:bg-gray-600",title:"滚动到底部"},[...e[6]||(e[6]=[t("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 14l-7 7m0 0l-7-7m7 7V3"})],-1)])])])]),t("div",{ref_key:"logContainer",ref:a,class:"logs-content"},[c.value.length===0?(u(),g("div",Q,[n.value?(u(),g(S,{key:1},[k(" 等待日志... ")],64)):(u(),g(S,{key:0},[e[7]||(e[7]=t("svg",{class:"w-16 h-16 mx-auto mb-4 text-gray-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 10V3L4 14h7v7l9-11h-7z"})],-1)),e[8]||(e[8]=t("p",null,'点击"连接"按钮开始接收实时日志',-1))],64))])):(u(!0),g(S,{key:1},J(c.value,(r,m)=>(u(),g("div",{key:m,class:"flex gap-3 hover:bg-gray-800/50 rounded px-2 py-0.5"},[t("span",X,b(r.timestamp),1),t("span",{class:h(["flex-1 break-words",O(r.level)])},b(r.message),3)]))),128))],512)])]))}},oe=U(Y,[["__scopeId","data-v-41485a66"]]);export{oe as default}; diff --git a/apps/admin/assets/Logs-GOoAwrBO.css b/apps/admin/assets/Logs-GOoAwrBO.css new file mode 100644 index 00000000..193cacad --- /dev/null +++ b/apps/admin/assets/Logs-GOoAwrBO.css @@ -0,0 +1 @@ +.logs-page[data-v-41485a66]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.logs-header[data-v-41485a66]{flex-shrink:0;padding-bottom:1rem}.logs-viewer[data-v-41485a66]{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden}.logs-toolbar[data-v-41485a66]{flex-shrink:0;padding:.75rem 1rem;border-bottom:1px solid rgb(229 231 235);border-bottom-color:#e5e7eb}.dark .logs-toolbar[data-v-41485a66]{border-bottom-color:#374151}.logs-toolbar[data-v-41485a66]{display:flex;align-items:center;justify-content:space-between}.logs-content[data-v-41485a66]{flex:1;overflow-y:auto;overflow-x:hidden;padding:1rem;background-color:#111827;color:#d1d5db;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.875rem;line-height:1.625}.dark .logs-content[data-v-41485a66]{background-color:#000}input[type=checkbox][data-v-41485a66]{accent-color:rgb(2 132 199)} diff --git a/apps/admin/assets/MapManager-BYA8aptO.css b/apps/admin/assets/MapManager-BYA8aptO.css new file mode 100644 index 00000000..3e2893e3 --- /dev/null +++ b/apps/admin/assets/MapManager-BYA8aptO.css @@ -0,0 +1 @@ +.map-page[data-v-78ec96e4]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.map-header[data-v-78ec96e4]{flex-shrink:0} diff --git a/apps/admin/assets/MapManager-CSfQvEnp.js b/apps/admin/assets/MapManager-CSfQvEnp.js new file mode 100644 index 00000000..cd1f8453 --- /dev/null +++ b/apps/admin/assets/MapManager-CSfQvEnp.js @@ -0,0 +1,9 @@ +import{z as Kt,A as ot,w as Et,o as N,b as F,e as h,j as ke,k as Te,E as Ie,J as Qt,t as we,g as Zt,i as Jt,G as Le,n as Dt,I as en,F as St,f as tn,r as G,y as it,D as nn,H as on}from"./vendor-B6xRL-fs.js";import{f as Ct}from"./file-D4KCgIsA.js";import{u as rn}from"./index-B24wRYHh.js";import{_ as an}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./admin-DEAtY0pm.js";import"./ui-42ANG6Sg.js";/**! + * Sortable 1.15.7 + * @author RubaXa + * @author owenm + * @license MIT + */function ln(o,e,t){return(e=cn(e))in o?Object.defineProperty(o,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):o[e]=t,o}function le(){return le=Object.assign?Object.assign.bind():function(o){for(var e=1;e"&&(e=e.substring(1)),o)try{if(o.matches)return o.matches(e);if(o.msMatchesSelector)return o.msMatchesSelector(e);if(o.webkitMatchesSelector)return o.webkitMatchesSelector(e)}catch{return!1}return!1}}function jt(o){return o.host&&o!==document&&o.host.nodeType&&o.host!==o?o.host:o.parentNode}function J(o,e,t,n){if(o){t=t||document;do{if(e!=null&&(e[0]===">"?o.parentNode===t&&Ke(o,e):Ke(o,e))||n&&o===t)return o;if(o===t)break}while(o=jt(o))}return null}var It=/\s+/g;function V(o,e,t){if(o&&e)if(o.classList)o.classList[t?"add":"remove"](e);else{var n=(" "+o.className+" ").replace(It," ").replace(" "+e+" "," ");o.className=(n+(t?" "+e:"")).replace(It," ")}}function m(o,e,t){var n=o&&o.style;if(n){if(t===void 0)return document.defaultView&&document.defaultView.getComputedStyle?t=document.defaultView.getComputedStyle(o,""):o.currentStyle&&(t=o.currentStyle),e===void 0?t:t[e];!(e in n)&&e.indexOf("webkit")===-1&&(e="-webkit-"+e),n[e]=t+(typeof t=="string"?"":"px")}}function Se(o,e){var t="";if(typeof o=="string")t=o;else do{var n=m(o,"transform");n&&n!=="none"&&(t=n+" "+t)}while(!e&&(o=o.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(t)}function Xt(o,e,t){if(o){var n=o.getElementsByTagName(e),i=0,r=n.length;if(t)for(;i=r,!a)return n;if(n===te())break;n=fe(n,!1)}return!1}function Ce(o,e,t,n){for(var i=0,r=0,a=o.children;r2&&arguments[2]!==void 0?arguments[2]:{},i=n.evt,r=sn(n,wn);Xe.pluginEvent.bind(v)(e,t,ne({dragEl:c,parentEl:I,ghostEl:b,rootEl:C,nextEl:ve,lastDownEl:Ve,cloneEl:k,cloneHidden:ce,dragStarted:Oe,putSortable:B,activeSortable:v.active,originalEvent:i,oldIndex:De,oldDraggableIndex:Fe,newIndex:U,newDraggableIndex:de,hideGhostForTarget:Ut,unhideGhostForTarget:$t,cloneNowHidden:function(){ce=!0},cloneNowShown:function(){ce=!1},dispatchSortableEvent:function(l){L({sortable:t,name:l,originalEvent:i})}},r))};function L(o){yn(ne({putSortable:B,cloneEl:k,targetEl:c,rootEl:C,oldIndex:De,oldDraggableIndex:Fe,newIndex:U,newDraggableIndex:de},o))}var c,I,b,C,ve,Ve,k,ce,De,U,Fe,de,He,B,Ee=!1,Qe=!1,Ze=[],ge,Z,lt,st,Mt,Pt,Oe,xe,Be,Re=!1,We=!1,Ue,j,ut=[],gt=!1,Je=[],tt=typeof document<"u",ze=yt,Nt=je||se?"cssFloat":"float",_n=tt&&!Bt&&!yt&&"draggable"in document.createElement("div"),zt=(function(){if(tt){if(se)return!1;var o=document.createElement("x");return o.style.cssText="pointer-events:auto",o.style.pointerEvents==="auto"}})(),Gt=function(e,t){var n=m(e),i=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),r=Ce(e,0,t),a=Ce(e,1,t),l=r&&m(r),s=a&&m(a),d=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+M(r).width,p=s&&parseInt(s.marginLeft)+parseInt(s.marginRight)+M(a).width;if(n.display==="flex")return n.flexDirection==="column"||n.flexDirection==="column-reverse"?"vertical":"horizontal";if(n.display==="grid")return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(r&&l.float&&l.float!=="none"){var f=l.float==="left"?"left":"right";return a&&(s.clear==="both"||s.clear===f)?"vertical":"horizontal"}return r&&(l.display==="block"||l.display==="flex"||l.display==="table"||l.display==="grid"||d>=i&&n[Nt]==="none"||a&&n[Nt]==="none"&&d+p>i)?"vertical":"horizontal"},xn=function(e,t,n){var i=n?e.left:e.top,r=n?e.right:e.bottom,a=n?e.width:e.height,l=n?t.left:t.top,s=n?t.right:t.bottom,d=n?t.width:t.height;return i===l||r===s||i+a/2===l+d/2},En=function(e,t){var n;return Ze.some(function(i){var r=i[z].options.emptyInsertThreshold;if(!(!r||wt(i))){var a=M(i),l=e>=a.left-r&&e<=a.right+r,s=t>=a.top-r&&t<=a.bottom+r;if(l&&s)return n=i}}),n},Vt=function(e){function t(r,a){return function(l,s,d,p){var f=l.options.group.name&&s.options.group.name&&l.options.group.name===s.options.group.name;if(r==null&&(a||f))return!0;if(r==null||r===!1)return!1;if(a&&r==="clone")return r;if(typeof r=="function")return t(r(l,s,d,p),a)(l,s,d,p);var _=(a?l:s).options.group.name;return r===!0||typeof r=="string"&&r===_||r.join&&r.indexOf(_)>-1}}var n={},i=e.group;(!i||ht(i)!="object")&&(i={name:i}),n.name=i.name,n.checkPull=t(i.pull,!0),n.checkPut=t(i.put),n.revertClone=i.revertClone,e.group=n},Ut=function(){!zt&&b&&m(b,"display","none")},$t=function(){!zt&&b&&m(b,"display","")};tt&&!Bt&&document.addEventListener("click",function(o){if(Qe)return o.preventDefault(),o.stopPropagation&&o.stopPropagation(),o.stopImmediatePropagation&&o.stopImmediatePropagation(),Qe=!1,!1},!0);var me=function(e){if(c){e=e.touches?e.touches[0]:e;var t=En(e.clientX,e.clientY);if(t){var n={};for(var i in e)e.hasOwnProperty(i)&&(n[i]=e[i]);n.target=n.rootEl=t,n.preventDefault=void 0,n.stopPropagation=void 0,t[z]._onDragOver(n)}}},Dn=function(e){c&&c.parentNode[z]._isOutsideThisEl(e.target)};function v(o,e){if(!(o&&o.nodeType&&o.nodeType===1))throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(o));this.el=o,this.options=e=le({},e),o[z]=this;var t={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(o.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Gt(o,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(a,l){a.setData("Text",l.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:v.supportPointer!==!1&&"PointerEvent"in window&&(!Pe||yt),emptyInsertThreshold:5};Xe.initializePlugins(this,o,t);for(var n in t)!(n in e)&&(e[n]=t[n]);Vt(e);for(var i in this)i.charAt(0)==="_"&&typeof this[i]=="function"&&(this[i]=this[i].bind(this));this.nativeDraggable=e.forceFallback?!1:_n,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?D(o,"pointerdown",this._onTapStart):(D(o,"mousedown",this._onTapStart),D(o,"touchstart",this._onTapStart)),this.nativeDraggable&&(D(o,"dragover",this),D(o,"dragenter",this)),Ze.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),le(this,mn())}v.prototype={constructor:v,_isOutsideThisEl:function(e){!this.el.contains(e)&&e!==this.el&&(xe=null)},_getDirection:function(e,t){return typeof this.options.direction=="function"?this.options.direction.call(this,e,t,c):this.options.direction},_onTapStart:function(e){if(e.cancelable){var t=this,n=this.el,i=this.options,r=i.preventOnFilter,a=e.type,l=e.touches&&e.touches[0]||e.pointerType&&e.pointerType==="touch"&&e,s=(l||e).target,d=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||s,p=i.filter;if(Mn(n),!c&&!(/mousedown|pointerdown/.test(a)&&e.button!==0||i.disabled)&&!d.isContentEditable&&!(!this.nativeDraggable&&Pe&&s&&s.tagName.toUpperCase()==="SELECT")&&(s=J(s,i.draggable,n,!1),!(s&&s.animated)&&Ve!==s)){if(De=q(s),Fe=q(s,i.draggable),typeof p=="function"){if(p.call(this,e,s,this)){L({sortable:t,rootEl:d,name:"filter",targetEl:s,toEl:n,fromEl:n}),W("filter",t,{evt:e}),r&&e.preventDefault();return}}else if(p&&(p=p.split(",").some(function(f){if(f=J(d,f.trim(),n,!1),f)return L({sortable:t,rootEl:f,name:"filter",targetEl:s,fromEl:n,toEl:n}),W("filter",t,{evt:e}),!0}),p)){r&&e.preventDefault();return}i.handle&&!J(d,i.handle,n,!1)||this._prepareDragStart(e,l,s)}}},_prepareDragStart:function(e,t,n){var i=this,r=i.el,a=i.options,l=r.ownerDocument,s;if(n&&!c&&n.parentNode===r){var d=M(n);if(C=r,c=n,I=c.parentNode,ve=c.nextSibling,Ve=n,He=a.group,v.dragged=c,ge={target:c,clientX:(t||e).clientX,clientY:(t||e).clientY},Mt=ge.clientX-d.left,Pt=ge.clientY-d.top,this._lastX=(t||e).clientX,this._lastY=(t||e).clientY,c.style["will-change"]="all",s=function(){if(W("delayEnded",i,{evt:e}),v.eventCanceled){i._onDrop();return}i._disableDelayedDragEvents(),!Tt&&i.nativeDraggable&&(c.draggable=!0),i._triggerDragStart(e,t),L({sortable:i,name:"choose",originalEvent:e}),V(c,a.chosenClass,!0)},a.ignore.split(",").forEach(function(p){Xt(c,p.trim(),dt)}),D(l,"dragover",me),D(l,"mousemove",me),D(l,"touchmove",me),a.supportPointer?(D(l,"pointerup",i._onDrop),!this.nativeDraggable&&D(l,"pointercancel",i._onDrop)):(D(l,"mouseup",i._onDrop),D(l,"touchend",i._onDrop),D(l,"touchcancel",i._onDrop)),Tt&&this.nativeDraggable&&(this.options.touchStartThreshold=4,c.draggable=!0),W("delayStart",this,{evt:e}),a.delay&&(!a.delayOnTouchOnly||t)&&(!this.nativeDraggable||!(je||se))){if(v.eventCanceled){this._onDrop();return}a.supportPointer?(D(l,"pointerup",i._disableDelayedDrag),D(l,"pointercancel",i._disableDelayedDrag)):(D(l,"mouseup",i._disableDelayedDrag),D(l,"touchend",i._disableDelayedDrag),D(l,"touchcancel",i._disableDelayedDrag)),D(l,"mousemove",i._delayedDragTouchMoveHandler),D(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&D(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(s,a.delay)}else s()}},_delayedDragTouchMoveHandler:function(e){var t=e.touches?e.touches[0]:e;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){c&&dt(c),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var e=this.el.ownerDocument;E(e,"mouseup",this._disableDelayedDrag),E(e,"touchend",this._disableDelayedDrag),E(e,"touchcancel",this._disableDelayedDrag),E(e,"pointerup",this._disableDelayedDrag),E(e,"pointercancel",this._disableDelayedDrag),E(e,"mousemove",this._delayedDragTouchMoveHandler),E(e,"touchmove",this._delayedDragTouchMoveHandler),E(e,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(e,t){t=t||e.pointerType=="touch"&&e,!this.nativeDraggable||t?this.options.supportPointer?D(document,"pointermove",this._onTouchMove):t?D(document,"touchmove",this._onTouchMove):D(document,"mousemove",this._onTouchMove):(D(c,"dragend",this),D(C,"dragstart",this._onDragStart));try{document.selection?$e(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch{}},_dragStarted:function(e,t){if(Ee=!1,C&&c){W("dragStarted",this,{evt:t}),this.nativeDraggable&&D(document,"dragover",Dn);var n=this.options;!e&&V(c,n.dragClass,!1),V(c,n.ghostClass,!0),v.active=this,e&&this._appendGhost(),L({sortable:this,name:"start",originalEvent:t})}else this._nulling()},_emulateDragOver:function(){if(Z){this._lastX=Z.clientX,this._lastY=Z.clientY,Ut();for(var e=document.elementFromPoint(Z.clientX,Z.clientY),t=e;e&&e.shadowRoot&&(e=e.shadowRoot.elementFromPoint(Z.clientX,Z.clientY),e!==t);)t=e;if(c.parentNode[z]._isOutsideThisEl(e),t)do{if(t[z]){var n=void 0;if(n=t[z]._onDragOver({clientX:Z.clientX,clientY:Z.clientY,target:e,rootEl:t}),n&&!this.options.dragoverBubble)break}e=t}while(t=jt(t));$t()}},_onTouchMove:function(e){if(ge){var t=this.options,n=t.fallbackTolerance,i=t.fallbackOffset,r=e.touches?e.touches[0]:e,a=b&&Se(b,!0),l=b&&a&&a.a,s=b&&a&&a.d,d=ze&&j&&At(j),p=(r.clientX-ge.clientX+i.x)/(l||1)+(d?d[0]-ut[0]:0)/(l||1),f=(r.clientY-ge.clientY+i.y)/(s||1)+(d?d[1]-ut[1]:0)/(s||1);if(!v.active&&!Ee){if(n&&Math.max(Math.abs(r.clientX-this._lastX),Math.abs(r.clientY-this._lastY))=0&&(L({rootEl:I,name:"add",toEl:I,fromEl:C,originalEvent:e}),L({sortable:this,name:"remove",toEl:I,originalEvent:e}),L({rootEl:I,name:"sort",toEl:I,fromEl:C,originalEvent:e}),L({sortable:this,name:"sort",toEl:I,originalEvent:e})),B&&B.save()):U!==De&&U>=0&&(L({sortable:this,name:"update",toEl:I,originalEvent:e}),L({sortable:this,name:"sort",toEl:I,originalEvent:e})),v.active&&((U==null||U===-1)&&(U=De,de=Fe),L({sortable:this,name:"end",toEl:I,originalEvent:e}),this.save()))),this._nulling()},_nulling:function(){W("nulling",this),C=c=I=b=ve=k=Ve=ce=ge=Z=Oe=U=de=De=Fe=xe=Be=B=He=v.dragged=v.ghost=v.clone=v.active=null;var e=this.el;Je.forEach(function(t){e.contains(t)&&(t.checked=!0)}),Je.length=lt=st=0},handleEvent:function(e){switch(e.type){case"drop":case"dragend":this._onDrop(e);break;case"dragenter":case"dragover":c&&(this._onDragOver(e),Sn(e));break;case"selectstart":e.preventDefault();break}},toArray:function(){for(var e=[],t,n=this.el.children,i=0,r=n.length,a=this.options;ii.right+r||o.clientY>n.bottom&&o.clientX>n.left:o.clientY>i.bottom+r||o.clientX>n.right&&o.clientY>n.top}function In(o,e,t,n,i,r,a,l){var s=n?o.clientY:o.clientX,d=n?t.height:t.width,p=n?t.top:t.left,f=n?t.bottom:t.right,_=!1;if(!a){if(l&&Uep+d*r/2:sf-Ue)return-Be}else if(s>p+d*(1-i)/2&&sf-d*r/2)?s>p+d/2?1:-1:0}function On(o){return q(c)i.value==="list"?X(l.value)!==a.value:r.value!==a.value),S=it(()=>({automaticLayout:!0,wordWrap:p.value?"on":"off",wordWrapColumn:80,wrappingIndent:"same",minimap:{enabled:!1},scrollBeyondLastLine:!1,fontSize:14,lineNumbers:"on",renderWhitespace:"none",padding:{top:16,bottom:16}})),w=G(-1),y=G({source:"",params:"",alias:""}),O=G(!1);let H=0;const P=g=>{var x,be,nt;if(!g)return[];const u=g.split(` +`),T=[];for(const he of u){const ye=he.trim();if(!ye)continue;if(ye.startsWith("//")||ye.startsWith("#")){T.push({id:H++,type:"comment",raw:he});continue}const Ye=ye.split("@@");Ye.length>=1?T.push({id:H++,type:"record",raw:he,source:((x=Ye[0])==null?void 0:x.trim())||"",params:((be=Ye[1])==null?void 0:be.trim())||"",alias:((nt=Ye[2])==null?void 0:nt.trim())||""}):T.push({id:H++,type:"raw",raw:he})}return T},X=g=>g.map(u=>{if(u.type==="record"){const T=[u.source];return(u.params||u.alias)&&T.push(u.params),u.alias&&T.push(u.alias),T.join("@@")}return u.raw}).join(` +`),Y=async()=>{t.value=!0;try{const g=await Ct.readFile("config/map.txt");let u="";typeof g=="string"?u=g:(g==null?void 0:g.type)==="text"&&g.content||g!=null&&g.content?u=g.content:u=String(g||""),r.value=u,a.value=u,l.value=P(u)}catch(g){console.error("Load map.txt error:",g),g.message&&g.message.includes("not found")?(r.value="",a.value="",l.value=[]):alert("加载 map.txt 失败: "+g.message)}finally{t.value=!1}},oe=async()=>{if(confirm(`确定要保存对映射配置的修改吗? +此操作将直接写入 config/map.txt 文件。`)){n.value=!0;try{i.value==="list"&&(r.value=X(l.value)),await Ct.writeFile("config/map.txt",r.value),a.value=r.value,i.value==="editor"&&(l.value=P(r.value)),alert("保存成功")}catch(g){alert("保存失败: "+g.message)}finally{n.value=!1}}};Kt(async()=>{await Y(),await ot(),i.value==="list"&&K()});const $=()=>{i.value==="list"?(r.value=X(l.value),i.value="editor",s.value&&(s.value.destroy(),s.value=null)):(l.value=P(r.value),i.value="list",ot(()=>{s.value||K()}))},K=()=>{const g=document.getElementById("map-records-list")||d.value;g&&!s.value&&i.value==="list"&&(s.value=new v(g,{animation:150,handle:".drag-handle",ghostClass:"bg-gray-100",onEnd:u=>{if(f.value)return;const T=u.item;u.newIndex!==u.oldIndex&&(u.oldIndex>u.newIndex?T.parentNode.insertBefore(T,T.parentNode.children[u.oldIndex+1]||null):T.parentNode.insertBefore(T,T.parentNode.children[u.oldIndex]||null));const x=l.value.splice(u.oldIndex,1)[0];l.value.splice(u.newIndex,0,x),l.value=[...l.value]}}))};Et(i,async g=>{g==="list"&&(await ot(),s.value||K())}),Et(f,g=>{s.value&&s.value.option("disabled",!!g)});const ie=it(()=>{if(!f.value)return l.value;const g=f.value.toLowerCase();return l.value.filter(u=>u.type!=="record"?!0:u.type!=="record"?!1:u.source&&u.source.toLowerCase().includes(g)||u.alias&&u.alias.toLowerCase().includes(g))}),R=g=>l.value.indexOf(g),pe=()=>{O.value=!0,w.value=-1,y.value={id:null,source:"",params:"",alias:""}},ee=g=>{O.value=!1,w.value=g;const u=l.value[g];y.value={...u}},ue=()=>{O.value=!1,w.value=-1},Q=()=>{if(!y.value.source.trim()){alert("站名不能为空");return}const g={id:O.value?H++:y.value.id,type:"record",source:y.value.source.trim(),params:y.value.params.trim(),alias:y.value.alias.trim()};O.value?l.value.push(g):w.value>=0&&(l.value[w.value]=g),ue()},re=g=>{confirm("确定要删除这条映射记录吗?")&&l.value.splice(g,1)};return(g,u)=>{const T=nn("vue-monaco-editor");return N(),F("div",Nn,[h("div",Fn,[h("div",Bn,[h("div",null,[h("h2",Rn,[u[7]||(u[7]=ke(" 站源映射管理 ",-1)),_.value?(N(),F("span",jn,"未保存")):Te("",!0)]),u[8]||(u[8]=h("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 管理 config/map.txt 别名映射配置 ",-1))]),h("div",Xn,[i.value==="editor"?(N(),F("label",Yn,[Ie(h("input",{type:"checkbox","onUpdate:modelValue":u[0]||(u[0]=x=>p.value=x),class:"rounded border-gray-300 text-primary-600 focus:ring-primary-500"},null,512),[[Qt,p.value]]),u[9]||(u[9]=ke(" 自动换行 ",-1))])):Te("",!0),h("button",{onClick:$,class:"btn btn-secondary"},[i.value==="list"?(N(),F("svg",Ln,[...u[10]||(u[10]=[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"},null,-1)])])):(N(),F("svg",Hn,[...u[11]||(u[11]=[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 6h16M4 10h16M4 14h16M4 18h16"},null,-1)])])),ke(" "+we(i.value==="list"?"文本编辑模式":"列表模式"),1)]),h("button",{onClick:oe,disabled:n.value,class:"btn btn-primary"},[n.value?(N(),F("svg",zn,[...u[12]||(u[12]=[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):(N(),F("svg",Gn,[...u[13]||(u[13]=[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"},null,-1)])])),u[14]||(u[14]=ke(" 保存配置 ",-1))],8,Wn)])])]),h("div",Vn,[t.value?(N(),F("div",Un,[...u[15]||(u[15]=[h("div",{class:"animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600"},null,-1)])])):i.value==="editor"?(N(),F("div",$n,[Zt(T,{value:r.value,"onUpdate:value":u[1]||(u[1]=x=>r.value=x),language:"plaintext",theme:Jt(e).isDark?"vs-dark":"vs",options:S.value,class:"flex-1 w-full"},null,8,["value","theme","options"])])):(N(),F("div",qn,[h("div",Kn,[h("button",{onClick:pe,class:"btn btn-primary whitespace-nowrap",disabled:O.value||w.value>=0},[...u[16]||(u[16]=[h("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 4v16m8-8H4"})],-1),ke(" 添加映射 ",-1)])],8,Qn),h("div",Zn,[Ie(h("input",{"onUpdate:modelValue":u[2]||(u[2]=x=>f.value=x),type:"text",class:"input w-full pl-9 pr-8",placeholder:"搜索站名或别名..."},null,512),[[Le,f.value]]),u[18]||(u[18]=h("svg",{class:"w-4 h-4 text-gray-400 absolute left-3 top-1/2 transform -translate-y-1/2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})],-1)),f.value?(N(),F("button",{key:0,onClick:u[3]||(u[3]=x=>f.value=""),class:"absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 p-1"},[...u[17]||(u[17]=[h("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])])):Te("",!0)])]),O.value||w.value>=0?(N(),F("div",Jn,[h("h3",eo,we(O.value?"添加映射记录":"编辑映射记录"),1),h("div",to,[h("div",no,[u[19]||(u[19]=h("label",{class:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"},"站名 (必填)",-1)),Ie(h("input",{"onUpdate:modelValue":u[4]||(u[4]=x=>y.value.source=x),type:"text",class:"input w-full",placeholder:"例如: webdav[盘]"},null,512),[[Le,y.value.source]])]),h("div",oo,[u[20]||(u[20]=h("label",{class:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"},"别名",-1)),Ie(h("input",{"onUpdate:modelValue":u[5]||(u[5]=x=>y.value.alias=x),type:"text",class:"input w-full",placeholder:"例如: WebDav[盘]"},null,512),[[Le,y.value.alias]])]),h("div",io,[u[21]||(u[21]=h("label",{class:"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"},"参数",-1)),Ie(h("textarea",{"onUpdate:modelValue":u[6]||(u[6]=x=>y.value.params=x),class:"input w-full resize-y min-h-[42px]",rows:"2",placeholder:"例如: ?render=1&type=url¶ms=..."},null,512),[[Le,y.value.params]])])]),h("div",{class:"flex justify-end gap-2"},[h("button",{onClick:ue,class:"btn btn-secondary"},"取消"),h("button",{onClick:Q,class:"btn btn-primary"},"确定")])])):Te("",!0),h("div",ro,[ie.value.length===0?(N(),F("div",ao," 暂无映射记录 ")):Te("",!0),h("div",{class:Dt(["overflow-auto flex-1 relative flex flex-col",{"overflow-hidden":ie.value.length===0}])},[h("div",lo,[u[25]||(u[25]=en('
排序
站名
别名
参数
操作
',1)),h("div",{class:"p-2 flex-1 relative",ref_key:"listContainer",ref:d,id:"map-records-list"},[(N(!0),F(St,null,tn(ie.value,x=>(N(),F(St,{key:x.id},[x.type==="record"?(N(),F("div",{key:0,class:"group flex items-center px-2 py-2 hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-lg mb-1 border border-transparent hover:border-gray-200 dark:hover:border-gray-700 bg-white dark:bg-gray-800 transition-colors","data-id":x.id},[h("div",uo,[h("div",co,[h("button",{class:Dt(["drag-handle p-1 text-gray-400 hover:text-gray-600 cursor-move",{"cursor-not-allowed opacity-50":f.value}])},[...u[22]||(u[22]=[h("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 8h16M4 16h16"})],-1)])],2)]),h("div",{class:"col-span-2 font-medium truncate text-gray-900 dark:text-gray-100",title:x.source},we(x.source),9,fo),h("div",{class:"col-span-2 text-primary-600 dark:text-primary-400 truncate",title:x.alias},we(x.alias||"-"),9,po),h("div",{class:"col-span-6 font-mono text-xs text-gray-500 truncate",title:x.params},we(x.params||"-"),9,ho),h("div",go,[h("button",{onClick:be=>ee(R(x)),class:"p-1.5 text-blue-600 hover:bg-blue-50 rounded",title:"编辑"},[...u[23]||(u[23]=[h("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"})],-1)])],8,mo),h("button",{onClick:be=>re(R(x)),class:"p-1.5 text-red-600 hover:bg-red-50 rounded",title:"删除"},[...u[24]||(u[24]=[h("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"})],-1)])],8,vo)])])],8,so)):(N(),F("div",bo,we(x.raw),1))],64))),128))],512)])],2)])]))])])}}},Co=an(yo,[["__scopeId","data-v-78ec96e4"]]);export{Co as default}; diff --git a/apps/admin/assets/Parses-D-4NY5Ez.js b/apps/admin/assets/Parses-D-4NY5Ez.js new file mode 100644 index 00000000..2e615fed --- /dev/null +++ b/apps/admin/assets/Parses-D-4NY5Ez.js @@ -0,0 +1 @@ +import{z as v,o as s,b as r,e,j as l,I as x,F as y,f as h,r as m,H as b,t as u}from"./vendor-B6xRL-fs.js";import{f as g}from"./file-D4KCgIsA.js";import{_ as k}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./admin-DEAtY0pm.js";import"./ui-42ANG6Sg.js";const w={class:"parses-page"},_={class:"parses-header"},j={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"},C=["disabled"],B={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},M={key:1,class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},F={class:"parses-content space-y-6 mt-6"},H={key:0,class:"flex justify-center py-8"},z={key:1,class:"card p-8 text-center text-gray-500 dark:text-gray-400"},S={key:2,class:"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4"},V=["onClick"],J={class:"flex items-start justify-between"},A={class:"flex items-center gap-3 overflow-hidden"},D={class:"min-w-0"},N=["title"],q={class:"text-sm text-gray-500 dark:text-gray-400"},I={__name:"Parses",setup(L){const d=b(),a=m(!1),i=m([]);v(async()=>{await c()});const c=async()=>{a.value=!0;try{const o=await g.listDirectory("jx");i.value=(o.files||[]).filter(t=>!t.isDirectory&&t.name.endsWith(".js"))}catch(o){console.error("Load jx files error:",o),i.value=[]}finally{a.value=!1}},f=()=>{d.push({name:"source-editor",query:{path:"config/parses.conf"}})},p=o=>{d.push({name:"source-editor",query:{path:`jx/${o.name}`}})};return(o,t)=>(s(),r("div",w,[e("div",_,[e("div",j,[t[3]||(t[3]=e("div",null,[e("h2",{class:"text-xl font-semibold"},"解析管理"),e("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 管理系统解析配置文件及 jx 目录下的解析脚本 ")],-1)),e("button",{onClick:c,disabled:a.value,class:"btn btn-secondary"},[a.value?(s(),r("svg",B,[...t[0]||(t[0]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):(s(),r("svg",M,[...t[1]||(t[1]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])),t[2]||(t[2]=l(" 刷新 ",-1))],8,C)])]),e("div",F,[e("section",null,[t[5]||(t[5]=e("h3",{class:"text-lg font-medium mb-4 flex items-center gap-2"},[e("svg",{class:"w-5 h-5 text-primary-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z"})]),l(" 全局解析配置 ")],-1)),e("div",{class:"card p-4 flex items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors cursor-pointer",onClick:f},[...t[4]||(t[4]=[x('

parses.conf

drpy-node/config/parses.conf

',2)])])]),e("section",null,[t[8]||(t[8]=e("h3",{class:"text-lg font-medium mb-4 flex items-center gap-2"},[e("svg",{class:"w-5 h-5 text-primary-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"})]),l(" JS 解析脚本 (jx 目录) ")],-1)),a.value?(s(),r("div",H,[...t[6]||(t[6]=[e("div",{class:"animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600"},null,-1)])])):i.value.length===0?(s(),r("div",z," jx 目录下没有找到 JS 解析脚本 ")):(s(),r("div",S,[(s(!0),r(y,null,h(i.value,n=>(s(),r("div",{key:n.name,class:"card p-4 hover:shadow-md transition-shadow cursor-pointer border border-transparent hover:border-primary-200 dark:hover:border-primary-800",onClick:P=>p(n)},[e("div",J,[e("div",A,[t[7]||(t[7]=e("div",{class:"w-10 h-10 rounded-lg bg-yellow-100 dark:bg-yellow-900/30 flex items-center justify-center flex-shrink-0"},[e("span",{class:"text-yellow-600 dark:text-yellow-500 font-bold text-sm"},"JS")],-1)),e("div",D,[e("h4",{class:"font-medium text-gray-900 dark:text-gray-100 truncate",title:n.name},u(n.name),9,N),e("p",q,u((n.size/1024).toFixed(2))+" KB ",1)])])])],8,V))),128))]))])])]))}},W=k(I,[["__scopeId","data-v-a0fcbb2f"]]);export{W as default}; diff --git a/apps/admin/assets/Parses-DhTkA6XJ.css b/apps/admin/assets/Parses-DhTkA6XJ.css new file mode 100644 index 00000000..2ab95982 --- /dev/null +++ b/apps/admin/assets/Parses-DhTkA6XJ.css @@ -0,0 +1 @@ +.parses-page[data-v-a0fcbb2f]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.parses-header[data-v-a0fcbb2f]{flex-shrink:0;padding-bottom:1rem}.parses-content[data-v-a0fcbb2f]{flex:1;overflow-y:auto;min-height:0} diff --git a/apps/admin/assets/SourceEditor-Cg6Yu9PP.css b/apps/admin/assets/SourceEditor-Cg6Yu9PP.css new file mode 100644 index 00000000..abdc81a6 --- /dev/null +++ b/apps/admin/assets/SourceEditor-Cg6Yu9PP.css @@ -0,0 +1 @@ +.editor-page[data-v-0c0f239e]{display:flex;flex-direction:column;flex:1;height:100%}.editor-header[data-v-0c0f239e]{flex-shrink:0}.editor-content[data-v-0c0f239e]{flex:1;display:flex;flex-direction:column;min-height:0}[data-v-0c0f239e] .monaco-editor,[data-v-0c0f239e] .monaco-scrollable-element{touch-action:pan-x pan-y!important} diff --git a/apps/admin/assets/SourceEditor-DNi9VzRp.js b/apps/admin/assets/SourceEditor-DNi9VzRp.js new file mode 100644 index 00000000..0b307dfb --- /dev/null +++ b/apps/admin/assets/SourceEditor-DNi9VzRp.js @@ -0,0 +1,2 @@ +import{r as s,z,w as b,o as n,b as l,e as a,t as y,k as f,j as w,g as A,i as N,u as D,y as _,H as I}from"./vendor-B6xRL-fs.js";import{f as C}from"./file-D4KCgIsA.js";import{s as W}from"./spider-Bxy9e0gU.js";import{u as q,V as R}from"./index-B24wRYHh.js";import{_ as U}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./admin-DEAtY0pm.js";import"./ui-42ANG6Sg.js";const G={class:"editor-page"},O={class:"editor-header"},J={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-4"},K={class:"flex items-center gap-4"},P={class:"text-sm text-gray-500 dark:text-gray-400 font-mono"},Q={class:"flex items-center gap-2 flex-wrap"},X={class:"flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300 bg-gray-100 dark:bg-gray-800 px-3 py-1.5 rounded-lg border border-gray-200 dark:border-gray-700"},Y=["checked"],Z=["disabled"],$={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},ee=["disabled"],te={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},ae={class:"editor-content"},oe={key:0,class:"card p-4 mb-4 border-red-200 dark:border-red-800 bg-red-50 dark:bg-red-900/20"},se={class:"flex items-start gap-3"},re={class:"mt-2 text-sm text-red-700 dark:text-red-300 whitespace-pre-wrap"},ne={class:"card flex-1 overflow-hidden flex flex-col relative min-h-[400px]"},le={key:0,class:"h-full flex items-center justify-center flex-1"},ie={key:1,class:"absolute inset-0"},de={class:"mt-2 flex-shrink-0 flex items-center justify-between text-sm text-gray-500 dark:text-gray-400"},ue={key:0,class:"text-orange-600 dark:text-orange-400"},ce={__name:"SourceEditor",setup(pe){const x=D(),j=I(),M=q(),r=s(x.query.path||""),o=s(""),c=s(""),g=s(!1),p=s(!1),v=s(!1),i=s(null),m=s(!1),u=s("on");let h=null;const B=e=>{h=e},S=()=>{u.value=u.value==="on"?"off":"on",h&&h.updateOptions({wordWrap:u.value})},E=_(()=>{const e=r.value.toLowerCase();return e.endsWith(".js")?"javascript":e.endsWith(".php")?"php":e.endsWith(".py")?"python":e.endsWith(".conf")||e.endsWith(".txt")?"plaintext":"javascript"}),F=_(()=>M.isDark);z(async()=>{r.value&&await k()}),b(()=>x.query.path,async e=>{e&&(r.value=e,await k())}),b(o,()=>{m.value=o.value!==c.value});const k=async()=>{g.value=!0;try{const e=await C.readFile(r.value);console.log("File loaded:",typeof e,e);let t="";typeof e=="string"?t=e:(e==null?void 0:e.type)==="text"&&e.content?t=e.content:(e==null?void 0:e.type)==="image"&&e.dataUrl?t="[图片文件,无法在源编辑器中显示]":e!=null&&e.content?t=e.content:t=String(e||""),console.log("File content extracted, type:",typeof t,"length:",t==null?void 0:t.length),o.value=t,c.value=t}catch(e){console.error("Load file error:",e),alert("加载文件失败: "+e.message),o.value="",c.value=""}finally{g.value=!1}},L=async()=>{p.value=!0;try{await C.writeFile(r.value,o.value),c.value=o.value,m.value=!1,alert("保存成功")}catch(e){alert("保存失败: "+e.message)}finally{p.value=!1}},V=async()=>{var e,t;v.value=!0,i.value=null;try{const d=await W.checkSyntax(r.value);d.isError?i.value=((t=(e=d.content)==null?void 0:e[0])==null?void 0:t.text)||"语法错误":(i.value=null,alert("语法检查通过"))}catch(d){i.value=d.message}finally{v.value=!1}},H=async()=>{try{const e=await W.getTemplate();console.log("Template loaded:",typeof e,e==null?void 0:e.substring(0,50)),o.value=e||""}catch(e){console.error("Get template error:",e),alert("获取模板失败: "+e.message)}},T=()=>{j.back()};return(e,t)=>(n(),l("div",G,[a("div",O,[a("div",J,[a("div",K,[a("button",{onClick:T,class:"p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700"},[...t[1]||(t[1]=[a("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[a("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M15 19l-7-7 7-7"})],-1)])]),a("div",null,[t[2]||(t[2]=a("h2",{class:"text-xl font-semibold"},"源编辑器",-1)),a("p",P,y(r.value),1)])]),a("div",Q,[a("div",X,[a("input",{type:"checkbox",id:"wordWrap",checked:u.value==="on",onChange:S,class:"rounded text-primary-600 focus:ring-primary-500 bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 w-4 h-4"},null,40,Y),t[3]||(t[3]=a("label",{for:"wordWrap",class:"cursor-pointer select-none"},"自动换行",-1))]),a("button",{onClick:H,class:"btn btn-secondary text-sm"}," 获取模板 "),a("button",{onClick:V,disabled:v.value,class:"btn btn-secondary text-sm"},[v.value?(n(),l("svg",$,[...t[4]||(t[4]=[a("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):f("",!0),t[5]||(t[5]=w(" 验证语法 ",-1))],8,Z),a("button",{onClick:L,disabled:p.value||!m.value,class:"btn btn-primary text-sm"},[p.value?(n(),l("svg",te,[...t[6]||(t[6]=[a("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):f("",!0),t[7]||(t[7]=w(" 保存 ",-1))],8,ee)])])]),a("div",ae,[i.value?(n(),l("div",oe,[a("div",se,[t[9]||(t[9]=a("svg",{class:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[a("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})],-1)),a("div",null,[t[8]||(t[8]=a("h4",{class:"font-medium text-red-900 dark:text-red-100"},"验证失败",-1)),a("pre",re,y(i.value),1)])])])):f("",!0),a("div",ne,[g.value?(n(),l("div",le,[...t[10]||(t[10]=[a("div",{class:"animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"},null,-1)])])):(n(),l("div",ie,[A(N(R),{value:o.value,"onUpdate:value":t[0]||(t[0]=d=>o.value=d),language:E.value,theme:F.value?"vs-dark":"vs",options:{automaticLayout:!0,minimap:{enabled:!1},fontSize:14,wordWrap:u.value,wordWrapColumn:80,wrappingIndent:"same",scrollBeyondLastLine:!1,tabSize:4},height:"100%",onMount:B},null,8,["value","language","theme","options"])]))]),a("div",de,[a("span",null,y(o.value.split(` +`).length)+" 行",1),m.value?(n(),l("span",ue,"有未保存的更改")):f("",!0)])])]))}},ke=U(ce,[["__scopeId","data-v-0c0f239e"]]);export{ke as default}; diff --git a/apps/admin/assets/Sources-BgVOQd1-.js b/apps/admin/assets/Sources-BgVOQd1-.js new file mode 100644 index 00000000..a1dd8441 --- /dev/null +++ b/apps/admin/assets/Sources-BgVOQd1-.js @@ -0,0 +1 @@ +import{z as B,o as l,b as n,e as t,i as c,k as m,j as M,E as P,G as L,F as w,f as C,t as i,r as y,y as S,H as V,n as k}from"./vendor-B6xRL-fs.js";import{u as z}from"./system-BaTh0baW.js";import{s as I}from"./spider-Bxy9e0gU.js";import{_ as T}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./system-CxybzrTo.js";import"./admin-DEAtY0pm.js";import"./ui-42ANG6Sg.js";const A={class:"sources-page"},E={class:"sources-header"},N={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"},Y=["disabled"],D={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},F={class:"card p-4"},J={class:"flex flex-col sm:flex-row gap-4 items-start sm:items-center"},R={class:"relative flex-1 w-full"},U={class:"flex gap-2 flex-wrap"},q=["onClick"],G={class:"sources-content"},Q={class:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-4"},K={class:"card p-4 text-center"},O={class:"text-2xl font-bold text-gray-900 dark:text-gray-100"},W={class:"card p-4 text-center"},X={class:"text-2xl font-bold text-blue-600"},Z={class:"card p-4 text-center"},tt={class:"text-2xl font-bold text-purple-600"},et={class:"card p-4 text-center"},st={class:"text-2xl font-bold text-indigo-600"},at={class:"card p-4 text-center"},ot={class:"text-2xl font-bold text-yellow-600"},rt={class:"card overflow-hidden"},lt={key:0,class:"p-12 text-center"},nt={key:1,class:"p-12 text-center text-gray-500 dark:text-gray-400"},it={key:2,class:"divide-y divide-gray-200 dark:divide-gray-700"},dt={class:"flex items-center justify-between gap-4"},pt={class:"flex-1 min-w-0"},ct={class:"flex items-center gap-3"},ut={class:"font-medium text-gray-900 dark:text-gray-100 truncate"},vt={class:"text-xs text-gray-500 dark:text-gray-400 mt-1 font-mono"},gt={key:0,class:"mt-2"},xt={class:"flex items-center gap-2"},yt=["onClick","disabled"],ht={key:0,class:"w-4 h-4 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},mt={key:1,class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},kt=["onClick"],ft={__name:"Sources",setup(_t){const j=V(),o=z(),g=y(null),u=y({}),f=S(()=>{const r=(o.sources.js||[]).map(a=>({name:a,type:"js",path:`spider/js/${a}`})),e=(o.sources.catvod||[]).map(a=>({name:a,type:"catvod",path:`spider/catvod/${a}`})),d=(o.sources.php||[]).map(a=>({name:a,type:"php",path:`spider/php/${a}`})),p=(o.sources.py||[]).map(a=>({name:a,type:"py",path:`spider/py/${a}`}));return[...r,...e,...d,...p]}),x=y("all"),v=y(""),h=S(()=>f.value.filter(r=>{const e=x.value==="all"||r.type===x.value,d=!v.value||r.name.toLowerCase().includes(v.value.toLowerCase());return e&&d}));B(()=>{o.fetchSources()});const H=async r=>{var e,d;g.value=r.path,u.value[r.path]=null;try{const p=await I.validateSpider(r.path);u.value[r.path]={success:!p.isError,message:((d=(e=p.content)==null?void 0:e[0])==null?void 0:d.text)||"验证完成"}}catch(p){u.value[r.path]={success:!1,message:p.message}}finally{g.value=null}},$=r=>{j.push({name:"source-editor",query:{path:r.path}})};return(r,e)=>{var d,p,a,_;return l(),n("div",A,[t("div",E,[t("div",N,[e[5]||(e[5]=t("div",null,[t("h2",{class:"text-xl font-semibold"},"源管理"),t("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 管理和验证 drpy 源文件 ")],-1)),t("button",{onClick:e[0]||(e[0]=s=>c(o).fetchSources()),disabled:c(o).loading,class:"btn btn-secondary"},[c(o).loading?(l(),n("svg",D,[...e[3]||(e[3]=[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):m("",!0),e[4]||(e[4]=M(" 刷新列表 ",-1))],8,Y)]),t("div",F,[t("div",J,[t("div",R,[P(t("input",{"onUpdate:modelValue":e[1]||(e[1]=s=>v.value=s),type:"text",placeholder:"搜索源文件...",class:"input w-full pr-8"},null,512),[[L,v.value]]),v.value?(l(),n("button",{key:0,onClick:e[2]||(e[2]=s=>v.value=""),class:"absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 p-1"},[...e[6]||(e[6]=[t("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])])):m("",!0)]),t("div",U,[(l(),n(w,null,C([{value:"all",label:"全部"},{value:"js",label:"JS"},{value:"catvod",label:"CatVod"},{value:"php",label:"PHP"},{value:"py",label:"HIPY"}],s=>t("button",{key:s.value,onClick:b=>x.value=s.value,class:k(["px-4 py-2 rounded-lg text-sm font-medium transition-colors",x.value===s.value?"bg-primary-600 text-white":"bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"])},i(s.label),11,q)),64))])])])]),t("div",G,[t("div",Q,[t("div",K,[t("p",O,i(h.value.length),1),e[7]||(e[7]=t("p",{class:"text-sm text-gray-500 dark:text-gray-400"},"显示",-1))]),t("div",W,[t("p",X,i(((d=c(o).sources.js)==null?void 0:d.length)||0),1),e[8]||(e[8]=t("p",{class:"text-sm text-gray-500 dark:text-gray-400"},"JS 源",-1))]),t("div",Z,[t("p",tt,i(((p=c(o).sources.catvod)==null?void 0:p.length)||0),1),e[9]||(e[9]=t("p",{class:"text-sm text-gray-500 dark:text-gray-400"},"CatVod 源",-1))]),t("div",et,[t("p",st,i(((a=c(o).sources.php)==null?void 0:a.length)||0),1),e[10]||(e[10]=t("p",{class:"text-sm text-gray-500 dark:text-gray-400"},"PHP 源",-1))]),t("div",at,[t("p",ot,i(((_=c(o).sources.py)==null?void 0:_.length)||0),1),e[11]||(e[11]=t("p",{class:"text-sm text-gray-500 dark:text-gray-400"},"HIPY 源",-1))])]),t("div",rt,[c(o).loading&&f.value.length===0?(l(),n("div",lt,[...e[12]||(e[12]=[t("div",{class:"inline-block animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"},null,-1),t("p",{class:"mt-4 text-gray-500 dark:text-gray-400"},"加载中...",-1)])])):h.value.length===0?(l(),n("div",nt," 没有找到匹配的源文件 ")):(l(),n("div",it,[(l(!0),n(w,null,C(h.value,s=>(l(),n("div",{key:s.path,class:"p-4 hover:bg-gray-50 dark:hover:bg-gray-700/30 transition-colors"},[t("div",dt,[t("div",pt,[t("div",ct,[t("span",{class:k(["badge text-xs",{"badge-info":s.type==="js","badge-warning":s.type==="catvod","badge-primary":s.type==="php","badge-success":s.type==="py"}])},i(s.type==="py"?"HIPY":s.type.toUpperCase()),3),t("h4",ut,i(s.name),1)]),t("p",vt,i(s.path),1),u.value[s.path]?(l(),n("div",gt,[t("span",{class:k(["text-sm",u.value[s.path].success?"text-green-600 dark:text-green-400":"text-red-600 dark:text-red-400"])},i(u.value[s.path].message),3)])):m("",!0)]),t("div",xt,[t("button",{onClick:b=>H(s),disabled:g.value===s.path,class:"p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",title:"验证源"},[g.value===s.path?(l(),n("svg",ht,[...e[13]||(e[13]=[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):(l(),n("svg",mt,[...e[14]||(e[14]=[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"},null,-1)])]))],8,yt),t("button",{onClick:b=>$(s),class:"p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors",title:"编辑源"},[...e[15]||(e[15]=[t("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"})],-1)])],8,kt)])])]))),128))]))])])])}}},Bt=T(ft,[["__scopeId","data-v-1745fff8"]]);export{Bt as default}; diff --git a/apps/admin/assets/Sources-DFGjYw1B.css b/apps/admin/assets/Sources-DFGjYw1B.css new file mode 100644 index 00000000..5dd5cd12 --- /dev/null +++ b/apps/admin/assets/Sources-DFGjYw1B.css @@ -0,0 +1 @@ +.sources-page[data-v-1745fff8]{display:flex;flex-direction:column;height:calc(100vh - 12rem);min-height:500px}.sources-header[data-v-1745fff8]{flex-shrink:0;padding-bottom:1rem}.sources-content[data-v-1745fff8]{flex:1;overflow-y:auto;min-height:0} diff --git a/apps/admin/assets/Subscription-DRivvSBF.css b/apps/admin/assets/Subscription-DRivvSBF.css new file mode 100644 index 00000000..5b51d4e3 --- /dev/null +++ b/apps/admin/assets/Subscription-DRivvSBF.css @@ -0,0 +1 @@ +.subscription-page[data-v-fe388a54]{display:flex;flex-direction:column;height:100%}.subscription-header[data-v-fe388a54]{flex-shrink:0;padding-bottom:1rem}.subscription-content[data-v-fe388a54]{flex:1;min-height:0} diff --git a/apps/admin/assets/Subscription-umbnLjo7.js b/apps/admin/assets/Subscription-umbnLjo7.js new file mode 100644 index 00000000..ca04ceea --- /dev/null +++ b/apps/admin/assets/Subscription-umbnLjo7.js @@ -0,0 +1 @@ +import{a as m}from"./admin-DEAtY0pm.js";import{u as C,V as S}from"./index-B24wRYHh.js";import{_ as F}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{z as j,o as t,b as o,e as s,k as y,F as B,f as V,m as M,i as z,r,y as D,n as H,t as b}from"./vendor-B6xRL-fs.js";import"./ui-42ANG6Sg.js";const L={class:"subscription-page"},A={class:"subscription-header"},E={class:"flex items-center justify-between gap-4"},N={class:"flex gap-2"},W=["disabled"],I={key:0,class:"w-4 h-4 mr-2 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},T={class:"subscription-content flex flex-col lg:flex-row gap-6 overflow-hidden"},U={class:"card w-full lg:w-64 flex-shrink-0 flex flex-col overflow-hidden"},$={class:"flex-1 overflow-y-auto"},q={key:0,class:"p-4 text-center text-gray-500"},G={key:1,class:"flex flex-col"},J=["onClick"],K={class:"font-medium truncate"},O={class:"text-xs text-gray-400 mt-1"},P={class:"card flex-1 flex flex-col overflow-hidden relative"},Q={key:0,class:"absolute inset-0 flex items-center justify-center text-gray-400 flex-col"},R={__name:"Subscription",setup(X){const h=C(),f=r([]),u=r(!1),l=r(null),i=r(""),v=r(""),c=r(!1),d=r(!1),g=async()=>{u.value=!0;try{const a=await m.getSubFiles();a.success?f.value=a.data:alert("加载文件列表失败: "+(a.message||"未知错误"))}catch(a){alert("加载文件列表失败: "+a.message)}finally{u.value=!1}},x=async a=>{if(!(c.value&&!confirm("当前文件有未保存的修改,确定要切换吗?"))){l.value=a,u.value=!0;try{const e=await m.getSubFile(a.name);e.success?(i.value=e.data,v.value=e.data,c.value=!1):alert("加载文件内容失败: "+(e.message||"未知错误"))}catch(e){alert("加载文件内容失败: "+e.message)}finally{u.value=!1}}},k=async()=>{if(l.value){d.value=!0;try{const a=await m.saveSubFile(l.value.name,i.value);a.success?(v.value=i.value,c.value=!1,alert("保存成功")):alert("保存失败: "+(a.message||"未知错误"))}catch(a){alert("保存出错: "+a.message)}finally{d.value=!1}}},_=a=>{i.value=a,c.value=a!==v.value},w=D(()=>h.isDark);return j(()=>{g()}),(a,e)=>(t(),o("div",L,[s("div",A,[s("div",E,[e[3]||(e[3]=s("div",null,[s("h2",{class:"text-xl font-semibold"},"订阅管理"),s("p",{class:"text-sm text-gray-500 dark:text-gray-400 mt-1"}," 编辑 public/sub 目录下的订阅文件 (sub.json) 和排序文件 ")],-1)),s("div",N,[l.value?(t(),o("button",{key:0,onClick:k,disabled:!c.value||d.value,class:"btn btn-primary"},[d.value?(t(),o("svg",I,[...e[1]||(e[1]=[s("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)])])):y("",!0),e[2]||(e[2]=s("span",null,"保存",-1))],8,W)):y("",!0),s("button",{onClick:g,class:"btn btn-secondary"},"刷新")])])]),s("div",T,[s("div",U,[e[4]||(e[4]=s("div",{class:"px-4 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 font-medium"}," 文件列表 ",-1)),s("div",$,[u.value&&!l.value?(t(),o("div",q,"加载中...")):(t(),o("div",G,[(t(!0),o(B,null,V(f.value,n=>{var p;return t(),o("button",{key:n.name,onClick:Y=>x(n),class:H(["px-4 py-3 text-left hover:bg-gray-100 dark:hover:bg-gray-700 border-b border-gray-100 dark:border-gray-700/50 transition-colors",{"bg-primary-50 dark:bg-primary-900/20 text-primary-600 dark:text-primary-400":((p=l.value)==null?void 0:p.name)===n.name}])},[s("div",K,b(n.name),1),s("div",O,b(new Date(n.mtime).toLocaleString()),1)],10,J)}),128))]))])]),s("div",P,[l.value?(t(),M(z(S),{key:1,value:i.value,"onUpdate:value":e[0]||(e[0]=n=>i.value=n),language:l.value.name.endsWith(".json")?"json":"html",theme:w.value?"vs-dark":"vs",options:{automaticLayout:!0,minimap:{enabled:!1},fontSize:14,wordWrap:"on"},onChange:_,class:"h-full w-full"},null,8,["value","language","theme"])):(t(),o("div",Q,[...e[5]||(e[5]=[s("svg",{class:"w-16 h-16 mb-4 text-gray-300 dark:text-gray-600",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[s("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})],-1),s("span",null,"请选择左侧文件进行编辑",-1)])]))])])]))}},le=F(R,[["__scopeId","data-v-fe388a54"]]);export{le as default}; diff --git a/apps/admin/assets/_plugin-vue_export-helper-DlAUqK2U.js b/apps/admin/assets/_plugin-vue_export-helper-DlAUqK2U.js new file mode 100644 index 00000000..718edd33 --- /dev/null +++ b/apps/admin/assets/_plugin-vue_export-helper-DlAUqK2U.js @@ -0,0 +1 @@ +const s=(t,r)=>{const o=t.__vccOpts||t;for(const[c,e]of r)o[c]=e;return o};export{s as _}; diff --git a/apps/admin/assets/admin-DEAtY0pm.js b/apps/admin/assets/admin-DEAtY0pm.js new file mode 100644 index 00000000..274603a4 --- /dev/null +++ b/apps/admin/assets/admin-DEAtY0pm.js @@ -0,0 +1 @@ +import{a as c}from"./ui-42ANG6Sg.js";const a=c.create({baseURL:"",timeout:3e4,headers:{"Content-Type":"application/json"}});a.interceptors.request.use(e=>e,e=>Promise.reject(e));a.interceptors.response.use(e=>e.data,e=>{var n,r,s,i,p;const t=((r=(n=e.response)==null?void 0:n.data)==null?void 0:r.message)||((i=(s=e.response)==null?void 0:s.data)==null?void 0:i.error)||e.message||"请求失败";return console.error("API Error:",t,(p=e.response)==null?void 0:p.data),Promise.reject(new Error(t))});const o={async getHealth(){return a.get("/api/admin/health")},async restartService(){return a.post("/api/admin/restart")},async getLogs(e=50){return a.get("/api/admin/logs",{params:{lines:e}})},async getConfig(e){return a.get("/api/admin/config",{params:{key:e}})},async updateConfig(e,t){return a.post("/api/admin/config",{key:e,value:t})},async getEnv(){return a.get("/api/admin/env")},async listSources(){return a.get("/api/admin/sources")},async validateSource(e){return a.post("/api/admin/sources/validate",{path:e})},async checkSyntax(e){return a.post("/api/admin/sources/syntax",{path:e})},async getTemplate(){return a.get("/api/admin/sources/template")},async getLibsInfo(){return a.get("/api/admin/sources/libs")},async listDirectory(e){return a.get("/api/admin/files/list",{params:{path:e}})},async readFile(e){return a.get("/api/admin/files/read",{params:{path:e}})},async writeFile(e,t){return a.post("/api/admin/files/write",{path:e,content:t})},async deleteFile(e){return a.delete("/api/admin/files/delete",{params:{path:e}})},async executeQuery(e){return a.post("/api/admin/db/query",{sql:e})},async getTables(){return a.get("/api/admin/db/tables")},async getTableSchema(e){return a.get(`/api/admin/db/tables/${e}/schema`)},async getRoutes(){return a.get("/api/admin/routes")},async getApiDocs(){return a.get("/api/admin/docs")},async getSubFiles(){return a.get("/api/admin/sub/files")},async getSubFile(e){return a.get("/api/admin/sub/file",{params:{name:e}})},async saveSubFile(e,t){return a.post("/api/admin/sub/file",{name:e,content:t})},async getBackupConfig(){return a.get("/api/admin/backup/config")},async updateBackupConfig(e){return a.post("/api/admin/backup/config",{paths:e})},async resetBackupConfig(){return a.post("/api/admin/backup/config/reset")},async createBackup(){return a.post("/api/admin/backup/create")},async restoreBackup(){return a.post("/api/admin/backup/restore")}};export{o as a}; diff --git a/apps/admin/assets/file-D4KCgIsA.js b/apps/admin/assets/file-D4KCgIsA.js new file mode 100644 index 00000000..c89fb2e5 --- /dev/null +++ b/apps/admin/assets/file-D4KCgIsA.js @@ -0,0 +1 @@ +import{a as r}from"./admin-DEAtY0pm.js";const l={async listDirectory(e="."){return await r.listDirectory(e)},async readFile(e){return await r.readFile(e)},async writeFile(e,t){return await r.writeFile(e,t)},async deleteFile(e){return await r.deleteFile(e)}};export{l as f}; diff --git a/apps/admin/assets/index-B24wRYHh.js b/apps/admin/assets/index-B24wRYHh.js new file mode 100644 index 00000000..441c4f92 --- /dev/null +++ b/apps/admin/assets/index-B24wRYHh.js @@ -0,0 +1,12 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-CB7r-Nk7.js","assets/system-BaTh0baW.js","assets/vendor-B6xRL-fs.js","assets/system-CxybzrTo.js","assets/admin-DEAtY0pm.js","assets/ui-42ANG6Sg.js","assets/spider-Bxy9e0gU.js","assets/_plugin-vue_export-helper-DlAUqK2U.js","assets/Dashboard-CDeJVBM_.css","assets/Config-B72N75gm.js","assets/Config-CsAT4E8O.css","assets/Sources-BgVOQd1-.js","assets/Sources-DFGjYw1B.css","assets/SourceEditor-DNi9VzRp.js","assets/file-D4KCgIsA.js","assets/SourceEditor-Cg6Yu9PP.css","assets/Parses-D-4NY5Ez.js","assets/Parses-DhTkA6XJ.css","assets/MapManager-CSfQvEnp.js","assets/MapManager-BYA8aptO.css","assets/Logs-D_O--y9N.js","assets/Logs-GOoAwrBO.css","assets/ApiDocs-WdRyZWIi.js","assets/ApiDocs-BtbZJGsl.css","assets/Files-67eeMvv5.js","assets/Files-DRnFcRx1.css","assets/Database-CBuEZ2qV.js","assets/Database-VwOSuNal.css","assets/Subscription-umbnLjo7.js","assets/Subscription-DRivvSBF.css","assets/Backup-qwqZIMqv.js","assets/Backup-BzNwk845.css"])))=>i.map(i=>d[i]); +import{d as Ee,w as b,r as $,c as je,a as xe,u as me,o as w,b as S,e as f,F as Ie,f as Ve,g as I,h as W,t as ve,n as Q,i as g,R as Ae,j as De,k as Te,l as ke,T as $e,m as Le,p as Ce,q as pe,s as j,v as ge,x as D,y as L,z as G,A as J,B as ze,C as Ne}from"./vendor-B6xRL-fs.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))n(a);new MutationObserver(a=>{for(const o of a)if(o.type==="childList")for(const l of o.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&n(l)}).observe(document,{childList:!0,subtree:!0});function r(a){const o={};return a.integrity&&(o.integrity=a.integrity),a.referrerPolicy&&(o.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?o.credentials="include":a.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function n(a){if(a.ep)return;a.ep=!0;const o=r(a);fetch(a.href,o)}})();const Re="modulepreload",He=function(e){return"/apps/admin/"+e},X={},y=function(t,r,n){let a=Promise.resolve();if(r&&r.length>0){let l=function(d){return Promise.all(d.map(u=>Promise.resolve(u).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),c=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));a=l(r.map(d=>{if(d=He(d),d in X)return;X[d]=!0;const u=d.endsWith(".css"),m=u?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${d}"]${m}`))return;const s=document.createElement("link");if(s.rel=u?"stylesheet":Re,u||(s.as="script"),s.crossOrigin="",s.href=d,c&&s.setAttribute("nonce",c),document.head.appendChild(s),u)return new Promise((v,h)=>{s.addEventListener("load",v),s.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${d}`)))})}))}function o(l){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=l,window.dispatchEvent(i),!i.defaultPrevented)throw l}return a.then(l=>{for(const i of l||[])i.status==="rejected"&&o(i.reason);return t().catch(o)})},N=Ee("theme",()=>{const e=$(!1),t=$(!1),r=()=>{const i=localStorage.getItem("theme");i?e.value=i==="dark":e.value=window.matchMedia("(prefers-color-scheme: dark)").matches,n()},n=()=>{e.value?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")},a=()=>{e.value=!e.value},o=()=>{t.value=!1},l=()=>{t.value=!t.value};return b(e,()=>{localStorage.setItem("theme",e.value?"dark":"light"),n()}),{isDark:e,sidebarOpen:t,initTheme:r,toggleTheme:a,closeSidebar:o,toggleSidebar:l}}),Be=[{path:"/",name:"dashboard",component:()=>y(()=>import("./Dashboard-CB7r-Nk7.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8])),meta:{title:"仪表盘"}},{path:"/config",name:"config",component:()=>y(()=>import("./Config-B72N75gm.js"),__vite__mapDeps([9,2,4,5,7,10])),meta:{title:"环境配置"}},{path:"/sources",name:"sources",component:()=>y(()=>import("./Sources-BgVOQd1-.js"),__vite__mapDeps([11,2,1,3,4,5,6,7,12])),meta:{title:"源管理"}},{path:"/sources/editor",name:"source-editor",component:()=>y(()=>import("./SourceEditor-DNi9VzRp.js"),__vite__mapDeps([13,2,14,4,5,6,7,15])),meta:{title:"源编辑器"}},{path:"/parses",name:"parses",component:()=>y(()=>import("./Parses-D-4NY5Ez.js"),__vite__mapDeps([16,2,14,4,5,7,17])),meta:{title:"解析管理"}},{path:"/map-manager",name:"map-manager",component:()=>y(()=>import("./MapManager-CSfQvEnp.js"),__vite__mapDeps([18,2,14,4,5,7,19])),meta:{title:"站源映射"}},{path:"/logs",name:"logs",component:()=>y(()=>import("./Logs-D_O--y9N.js"),__vite__mapDeps([20,2,7,21])),meta:{title:"日志查看"}},{path:"/api-docs",name:"api",component:()=>y(()=>import("./ApiDocs-WdRyZWIi.js"),__vite__mapDeps([22,2,3,4,5,7,23])),meta:{title:"API 文档"}},{path:"/files",name:"files",component:()=>y(()=>import("./Files-67eeMvv5.js"),__vite__mapDeps([24,14,4,5,7,2,25])),meta:{title:"文件管理"}},{path:"/database",name:"database",component:()=>y(()=>import("./Database-CBuEZ2qV.js"),__vite__mapDeps([26,2,4,5,7,27])),meta:{title:"数据库"}},{path:"/subscription",name:"subscription",component:()=>y(()=>import("./Subscription-umbnLjo7.js"),__vite__mapDeps([28,4,5,7,2,29])),meta:{title:"订阅管理"}},{path:"/backup",name:"backup",component:()=>y(()=>import("./Backup-qwqZIMqv.js"),__vite__mapDeps([30,2,4,5,14,7,31])),meta:{title:"系统备份"}}],he=je({history:xe("/apps/admin/"),routes:Be});he.beforeEach((e,t,r)=>{const n=N();window.innerWidth<1024&&n.closeSidebar(),document.title=e.meta.title?`${e.meta.title} - DRPYS ADMIN`:"DRPYS ADMIN",r()});const Fe="/apps/admin/drpys.png",qe={class:"p-4 space-y-1 overflow-y-auto flex-1"},Ue={class:"w-5 h-5 flex-shrink-0",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},We=["d"],Ye={class:"font-medium"},Ke={__name:"Sidebar",setup(e){const t=N(),r=me(),n=[{path:"/",name:"dashboard",icon:"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"},{path:"/config",name:"config",icon:"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z"},{path:"/sources",name:"sources",icon:"M4 6h16M4 10h16M4 14h16M4 18h16"},{path:"/map-manager",name:"map-manager",icon:"M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7"},{path:"/parses",name:"parses",icon:"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"},{path:"/logs",name:"logs",icon:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"},{path:"/api-docs",name:"api",icon:"M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"},{path:"/files",name:"files",icon:"M5 19a2 2 0 01-2-2V7a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1M5 19h14a2 2 0 002-2v-5a2 2 0 00-2-2H9a2 2 0 00-2 2v5a2 2 0 01-2 2z"},{path:"/subscription",name:"subscription",icon:"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"},{path:"/database",name:"database",icon:"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"},{path:"/backup",name:"backup",icon:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"}],a={dashboard:"仪表盘",config:"环境配置",sources:"源管理","map-manager":"站源映射",parses:"解析管理",logs:"日志查看",api:"API 文档",files:"文件管理",subscription:"订阅管理",database:"数据库",backup:"备份恢复"};return(o,l)=>(w(),S("aside",{class:Q(["fixed inset-y-0 left-0 z-50 w-56 bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 transform transition-transform duration-300 flex flex-col",g(t).sidebarOpen?"translate-x-0":"-translate-x-full lg:translate-x-0"])},[l[0]||(l[0]=f("div",{class:"flex items-center h-16 px-4 border-b border-gray-200 dark:border-gray-700 shrink-0"},[f("div",{class:"flex items-center gap-2"},[f("img",{src:Fe,alt:"Logo",class:"w-7 h-7 rounded-full"}),f("h1",{class:"text-lg font-bold text-primary-600 dark:text-primary-400 truncate"}," DRPYS ADMIN ")])],-1)),f("nav",qe,[(w(),S(Ie,null,Ve(n,i=>I(g(Ae),{key:i.path,to:i.path,class:Q(["flex items-center gap-3 px-4 py-3 rounded-lg transition-colors",g(r).path===i.path?"bg-primary-50 text-primary-600 dark:bg-primary-900/20 dark:text-primary-400":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"])},{default:W(()=>[(w(),S("svg",Ue,[f("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:i.icon},null,8,We)])),f("span",Ye,ve(a[i.name]),1)]),_:2},1032,["to","class"])),64))])],2))}},Ge={class:"fixed top-0 right-0 left-0 lg:left-56 z-30 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 h-16 flex items-center justify-between px-4 lg:px-6"},Je={class:"flex items-center gap-4"},Qe={class:"text-lg font-semibold text-gray-900 dark:text-gray-100"},Xe={class:"flex items-center gap-3"},Ze=["title"],et={key:0,class:"w-5 h-5 text-yellow-500",fill:"currentColor",viewBox:"0 0 20 20"},tt={key:1,class:"w-5 h-5 text-gray-700",fill:"currentColor",viewBox:"0 0 20 20"},rt={__name:"Header",setup(e){const t=N(),r=me();return(n,a)=>(w(),S("header",Ge,[f("div",Je,[f("button",{onClick:a[0]||(a[0]=(...o)=>g(t).toggleSidebar&&g(t).toggleSidebar(...o)),class:"lg:hidden p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700"},[...a[2]||(a[2]=[f("svg",{class:"w-6 h-6",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[f("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 6h16M4 12h16M4 18h16"})],-1)])]),f("h2",Qe,ve(g(r).meta.title||"DRPYS ADMIN"),1)]),f("div",Xe,[f("button",{onClick:a[1]||(a[1]=(...o)=>g(t).toggleTheme&&g(t).toggleTheme(...o)),class:"p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",title:g(t).isDark?"切换到亮色模式":"切换到暗色模式"},[g(t).isDark?(w(),S("svg",et,[...a[3]||(a[3]=[f("path",{"fill-rule":"evenodd",d:"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z","clip-rule":"evenodd"},null,-1)])])):(w(),S("svg",tt,[...a[4]||(a[4]=[f("path",{d:"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"},null,-1)])]))],8,Ze),a[5]||(a[5]=f("a",{href:"https://github.com/hjdhnx/drpy-node",target:"_blank",rel:"noopener noreferrer",class:"hidden sm:flex btn btn-secondary text-sm"},[f("svg",{class:"w-4 h-4 mr-2",fill:"currentColor",viewBox:"0 0 24 24"},[f("path",{d:"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"})]),De(" GitHub ")],-1))])]))}},nt={class:"app-container"},at={class:"main-content"},ot={class:"content-area"},it={__name:"App",setup(e){const t=N();return(r,n)=>(w(),S("div",nt,[g(t).sidebarOpen?(w(),S("div",{key:0,onClick:n[0]||(n[0]=(...a)=>g(t).closeSidebar&&g(t).closeSidebar(...a)),class:"fixed inset-0 bg-black/50 z-40 lg:hidden"})):Te("",!0),I(Ke),f("div",at,[I(rt),f("main",ot,[I(g(ke),null,{default:W(({Component:a})=>[I($e,{name:"fade",mode:"out-in"},{default:W(()=>[(w(),Le(Ce(a),{key:r.$route.path}))]),_:2},1024)]),_:1})])])]))}};function Z(e,t){(t==null||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r=e.length?e.apply(this,a):function(){for(var l=arguments.length,i=new Array(l),c=0;c1&&arguments[1]!==void 0?arguments[1]:{};k.initial(e),k.handler(t);var r={current:e},n=V(Vt)(r,t),a=V(It)(r),o=V(k.changes)(e),l=V(xt)(r);function i(){var d=arguments.length>0&&arguments[0]!==void 0?arguments[0]:function(u){return u};return k.selector(d),d(r.current)}function c(d){yt(n,a,o,l)(d)}return[i,c]}function xt(e,t){return A(t)?t(e.current):t}function It(e,t){return e.current=ne(ne({},e.current),t),t}function Vt(e,t,r){return A(t)?t(e.current):Object.keys(r).forEach(function(n){var a;return(a=t[n])===null||a===void 0?void 0:a.call(t,e.current[n])}),r}var At={create:jt},Dt={paths:{vs:"https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs"}};function Tt(e){return function t(){for(var r=this,n=arguments.length,a=new Array(n),o=0;o=e.length?e.apply(this,a):function(){for(var l=arguments.length,i=new Array(l),c=0;ct in e?Jt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,q=(e,t)=>{for(var r in t||(t={}))Zt.call(t,r)&&ie(e,r,t[r]);if(oe)for(var r of oe(t))er.call(t,r)&&ie(e,r,t[r]);return e},tr=(e,t)=>Qt(e,Xt(t));const U={wrapper:{display:"flex",position:"relative",textAlign:"initial"},fullWidth:{width:"100%"},hide:{display:"none"}};function we(e,t){const r=L(()=>{const{width:a,height:o}=e;return tr(q({},U.wrapper),{width:a,height:o})}),n=L(()=>q(q({},U.fullWidth),!t.value&&U.hide));return{wrapperStyle:r,containerStyle:n}}function Se(){const e=D(Y.__getMonacoInstance()),t=$(!1);let r;return G(()=>{e.value||(r=Y.init(),r.then(a=>e.value=a).catch(a=>{(a==null?void 0:a.type)!=="cancelation"&&(t.value=!0,console.error("Monaco initialization error:",a))}))}),{monacoRef:e,unload:()=>r==null?void 0:r.cancel(),isLoadFailed:t}}function z(e){return typeof e=="function"?e():e}function K(e){return e===void 0}function x(e,t,r,n){return rr(e,n)||nr(e,t,r,n)}function rr(e,t){return e.editor.getModel(Pe(e,t))}function nr(e,t,r,n){return e.editor.createModel(t,r,n?Pe(e,n):void 0)}function Pe(e,t){return e.Uri.parse(t)}var ar=Object.defineProperty,le=Object.getOwnPropertySymbols,or=Object.prototype.hasOwnProperty,ir=Object.prototype.propertyIsEnumerable,ue=(e,t,r)=>t in e?ar(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,lr=(e,t)=>{for(var r in t||(t={}))or.call(t,r)&&ue(e,r,t[r]);if(le)for(var r of le(t))ir.call(t,r)&&ue(e,r,t[r]);return e};const ur={display:"flex",height:"100%",width:"100%",justifyContent:"center",alignItems:"center"};var se=pe({name:"VueMonacoEditor",model:{prop:"value",event:"update:value"},props:{defaultValue:String,defaultPath:String,defaultLanguage:String,value:String,language:String,path:String,theme:{type:String,default:"vs"},line:Number,options:{type:Object,default:()=>({})},overrideServices:{type:Object,default:()=>({})},saveViewState:{type:Boolean,default:!0},width:{type:[Number,String],default:"100%"},height:{type:[Number,String],default:"100%"},className:String},emits:["update:value","beforeMount","mount","change","validate"],setup(e,t){const r=new Map,n=D(null),{monacoRef:a,unload:o,isLoadFailed:l}=Se(),{editorRef:i}=sr(t,e,a,n),{disposeValidator:c}=cr(t,e,a,i),d=L(()=>!!a.value&&!!i.value),{wrapperStyle:u,containerStyle:m}=we(e,d);return ge(()=>{var s,v;(s=c.value)==null||s.call(c),i.value?((v=i.value.getModel())==null||v.dispose(),i.value.dispose()):o()}),b([()=>e.path,()=>e.value,()=>e.language,()=>e.line],([s,v,h,_],[O,M,p,E])=>{if(d.value){if(s!==O){const Me=x(a.value,v||e.defaultValue||"",h||e.defaultLanguage||"",s||e.defaultPath||"");e.saveViewState&&r.set(O,i.value.saveViewState()),i.value.setModel(Me),e.saveViewState&&i.value.restoreViewState(r.get(s)),K(_)||i.value.revealLine(_);return}i.value.getValue()!==v&&i.value.setValue(v),h!==p&&a.value.editor.setModelLanguage(i.value.getModel(),h),!K(_)&&_!==E&&i.value.revealLine(_)}}),b(()=>e.options,s=>i.value&&i.value.updateOptions(s),{deep:!0}),b(()=>e.theme,s=>a.value&&a.value.editor.setTheme(s)),{containerRef:n,isEditorReady:d,isLoadFailed:l,wrapperStyle:u,containerStyle:m}},render(){const{$slots:e,isEditorReady:t,isLoadFailed:r,wrapperStyle:n,containerStyle:a,className:o}=this;return j("div",{style:n},[!t&&j("div",{style:ur},r?e.failure?z(e.failure):"load failed":e.default?z(e.default):"loading..."),j("div",{ref:"containerRef",key:"monaco_editor_container",style:a,class:o})])}});function sr({emit:e},t,r,n){const a=D(null);G(()=>{const l=b(r,()=>{n.value&&r.value&&(J(()=>l()),o())},{immediate:!0})});function o(){var l;if(!n.value||!r.value||a.value)return;e("beforeMount",r.value);const i=t.path||t.defaultPath,c=x(r.value,t.value||t.defaultValue||"",t.language||t.defaultLanguage||"",i||"");a.value=r.value.editor.create(n.value,lr({model:c,theme:t.theme,automaticLayout:!0,autoIndent:"brackets",formatOnPaste:!0,formatOnType:!0},t.options),t.overrideServices),(l=a.value)==null||l.onDidChangeModelContent(d=>{const u=a.value.getValue();u!==t.value&&(e("update:value",u),e("change",u,d))}),a.value&&!K(t.line)&&a.value.revealLine(t.line),e("mount",a.value,r.value)}return{editorRef:a}}function cr({emit:e},t,r,n){const a=$(null),o=b([r,n],()=>{if(r.value&&n.value){J(()=>o());const l=r.value.editor.onDidChangeMarkers(i=>{var c,d;const u=(d=(c=n.value)==null?void 0:c.getModel())==null?void 0:d.uri;if(u&&i.find(s=>s.path===u.path)){const s=r.value.editor.getModelMarkers({resource:u});e("validate",s)}});a.value=()=>l==null?void 0:l.dispose()}});return{disposeValidator:a}}var dr=Object.defineProperty,ce=Object.getOwnPropertySymbols,fr=Object.prototype.hasOwnProperty,mr=Object.prototype.propertyIsEnumerable,de=(e,t,r)=>t in e?dr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,vr=(e,t)=>{for(var r in t||(t={}))fr.call(t,r)&&de(e,r,t[r]);if(ce)for(var r of ce(t))mr.call(t,r)&&de(e,r,t[r]);return e};const pr={display:"flex",height:"100%",width:"100%",justifyContent:"center",alignItems:"center"};var fe=pe({name:"VueMonacoDiffEditor",props:{original:String,modified:String,language:String,originalLanguage:String,modifiedLanguage:String,originalModelPath:String,modifiedModelPath:String,theme:{type:String,default:"vs"},options:{type:Object,default:()=>({})},width:{type:[Number,String],default:"100%"},height:{type:[Number,String],default:"100%"},className:String},setup(e,t){const r=D(null),{monacoRef:n,unload:a,isLoadFailed:o}=Se(),{diffEditorRef:l}=gr(t,e,n,r),i=L(()=>!!n.value&&!!l.value),{wrapperStyle:c,containerStyle:d}=we(e,i);return ge(()=>{var u,m,s,v,h,_,O,M;!n.value&&a();const p=(m=(u=l.value)==null?void 0:u.getModel)==null?void 0:m.call(u);(v=(s=p==null?void 0:p.original)==null?void 0:s.dispose)==null||v.call(s),(_=(h=p==null?void 0:p.modified)==null?void 0:h.dispose)==null||_.call(h),(M=(O=l.value)==null?void 0:O.dispose)==null||M.call(O)}),b([()=>e.originalModelPath,()=>e.original,()=>e.originalLanguage,()=>e.language],([u,m,s,v],[h,_,O,M])=>{if(!i.value)return;const p=l.value.getOriginalEditor();if(u!==h){const E=x(n.value,m||"",s||v||"text",u||"");p.setModel(E);return}m!==p.getValue()&&p.setValue(m||""),(s!==O||v!==M)&&n.value.editor.setModelLanguage(l.value.getModel().original,s||v||"text")}),b([()=>e.modifiedModelPath,()=>e.modified,()=>e.modifiedLanguage,()=>e.language],([u,m,s,v],[h,_,O,M])=>{if(!i.value)return;const p=l.value.getModifiedEditor();if(h!==u){const E=x(n.value,m||"",s||v||"text",u||"");p.setModel(E);return}if(m!==p.getValue()){const E=n.value.editor.EditorOption.readOnly;p.getOption(E)?p.setValue(m||""):(p.executeEdits("",[{range:p.getModel().getFullModelRange(),text:m||"",forceMoveMarkers:!0}]),p.pushUndoStop())}(s!==O||v!==M)&&n.value.editor.setModelLanguage(l.value.getModel().modified,s||v||"text")}),b(()=>e.theme,()=>{var u;return(u=n.value)==null?void 0:u.editor.setTheme(e.theme)}),b(()=>e.options,()=>{var u;return(u=l.value)==null?void 0:u.updateOptions(e.options)},{deep:!0}),{containerRef:r,isDiffEditorReady:i,isLoadFailed:o,wrapperStyle:c,containerStyle:d}},render(){const{$slots:e,isDiffEditorReady:t,isLoadFailed:r,wrapperStyle:n,containerStyle:a,className:o}=this;return j("div",{style:n},[!t&&j("div",{style:pr},r?e.failure?z(e.failure):"load failed":e.default?z(e.default):"loading..."),j("div",{ref:"containerRef",key:"monaco_diff_editor_container",style:a,class:o})])}});function gr({emit:e},t,r,n){const a=D(null);G(()=>{const l=b(r,()=>{n.value&&r.value&&(J(()=>l()),o())},{immediate:!0})});function o(){var l;if(!n.value||!r.value||a.value)return;e("beforeMount",r.value),a.value=r.value.editor.createDiffEditor(n.value,vr({automaticLayout:!0,autoIndent:"brackets",theme:t.theme,formatOnPaste:!0,formatOnType:!0},t.options));const i=x(r.value,t.original||"",t.originalLanguage||t.language||"text",t.originalModelPath||""),c=x(r.value,t.modified||"",t.modifiedLanguage||t.language||"text",t.modifiedModelPath||"");(l=a.value)==null||l.setModel({original:i,modified:c}),e("mount",a.value,r.value)}return{diffEditorRef:a}}function hr(e,t){t&&Y.config(t),e.component(se.name,se),e.component(fe.name,fe)}const H=ze(it);H.use(Ne());H.use(he);H.use(hr,{paths:{vs:"https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs"},"vs/nls":{availableLanguages:{"*":"zh-cn"}}});H.mount("#app");export{se as V,N as u}; diff --git a/apps/admin/assets/index-DBe7exyC.css b/apps/admin/assets/index-DBe7exyC.css new file mode 100644 index 00000000..4da63d38 --- /dev/null +++ b/apps/admin/assets/index-DBe7exyC.css @@ -0,0 +1 @@ +.app-container{height:100vh;width:100vw;overflow:hidden;background-color:#f9fafb;display:flex}.dark .app-container{background-color:#111827}.main-content{flex:1;display:flex;flex-direction:column;height:100vh;overflow:hidden;margin-left:0}@media(min-width:1024px){.main-content{margin-left:14rem}}.content-area{flex:1;padding:1rem;margin-top:4rem;overflow-y:auto;height:calc(100vh - 4rem);display:flex;flex-direction:column}@media(min-width:1024px){.content-area{padding:1.5rem}}.fade-enter-active,.fade-leave-active{transition:opacity .2s ease}.fade-enter-from,.fade-leave-to{opacity:0}.content-area>div{flex:1;display:flex;flex-direction:column;min-height:0}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}body{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}body:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(243 244 246 / var(--tw-text-opacity, 1))}body{font-feature-settings:"rlig" 1,"calt" 1}.btn{display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn:disabled{pointer-events:none;opacity:.5}.btn-primary{display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn-primary:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn-primary:disabled{pointer-events:none;opacity:.5}.btn-primary{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-primary:hover{--tw-bg-opacity: 1;background-color:rgb(3 105 161 / var(--tw-bg-opacity, 1))}.btn-primary:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(14 165 233 / var(--tw-ring-opacity, 1))}.btn-secondary{display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn-secondary:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn-secondary:disabled{pointer-events:none;opacity:.5}.btn-secondary{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.btn-secondary:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.btn-secondary:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity, 1))}.btn-secondary:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(243 244 246 / var(--tw-text-opacity, 1))}.btn-secondary:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.btn-success{display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn-success:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn-success:disabled{pointer-events:none;opacity:.5}.btn-success{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-success:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.btn-success:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity, 1))}.card{border-radius:.75rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.card:is(.dark *){--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.input{height:38px;width:100%;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.5rem .75rem;--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.input::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity, 1))}.input::placeholder{--tw-placeholder-opacity: 1;color:rgb(107 114 128 / var(--tw-placeholder-opacity, 1))}.input{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.input:focus{border-color:transparent;outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(14 165 233 / var(--tw-ring-opacity, 1))}.input:is(.dark *){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(243 244 246 / var(--tw-text-opacity, 1))}textarea.input{height:auto}.badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;line-height:1rem;font-weight:500}.badge-success{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;line-height:1rem;font-weight:500;--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.badge-success:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(20 83 45 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(187 247 208 / var(--tw-text-opacity, 1))}.badge-warning{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;line-height:1rem;font-weight:500;--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.badge-warning:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(113 63 18 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.badge-error{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;line-height:1rem;font-weight:500;--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.badge-error:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(127 29 29 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.badge-info{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;line-height:1rem;font-weight:500;--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.badge-info:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 58 138 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(191 219 254 / var(--tw-text-opacity, 1))}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-3{left:.75rem}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.col-span-1{grid-column:span 1 / span 1}.col-span-2{grid-column:span 2 / span 2}.col-span-6{grid-column:span 6 / span 6}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:.5rem}.mr-1\.5{margin-right:.375rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-32{max-height:8rem}.max-h-\[90vh\]{max-height:90vh}.min-h-0{min-height:0px}.min-h-\[120px\]{min-height:120px}.min-h-\[300px\]{min-height:300px}.min-h-\[400px\]{min-height:400px}.min-h-\[42px\]{min-height:42px}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[40px\]{min-width:40px}.min-w-\[700px\]{min-width:700px}.min-w-\[70px\]{min-width:70px}.min-w-full{min-width:100%}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes pulse{50%{opacity:.5}}.animate-pulse-slow{animation:pulse 3s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-move{cursor:move}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.resize-y{resize:vertical}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity, 1))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity, 1))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-primary-200{--tw-border-opacity: 1;border-color:rgb(186 230 253 / var(--tw-border-opacity, 1))}.border-primary-600{--tw-border-opacity: 1;border-color:rgb(2 132 199 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.bg-black\/50{background-color:#00000080}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-50\/50{background-color:#f9fafb80}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-indigo-100{--tw-bg-opacity: 1;background-color:rgb(224 231 255 / var(--tw-bg-opacity, 1))}.bg-orange-100{--tw-bg-opacity: 1;background-color:rgb(255 237 213 / var(--tw-bg-opacity, 1))}.bg-primary-100{--tw-bg-opacity: 1;background-color:rgb(224 242 254 / var(--tw-bg-opacity, 1))}.bg-primary-50{--tw-bg-opacity: 1;background-color:rgb(240 249 255 / var(--tw-bg-opacity, 1))}.bg-primary-500{--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity, 1))}.bg-primary-600{--tw-bg-opacity: 1;background-color:rgb(2 132 199 / var(--tw-bg-opacity, 1))}.bg-purple-100{--tw-bg-opacity: 1;background-color:rgb(243 232 255 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.bg-opacity-75{--tw-bg-opacity: .75}.p-0{padding:0}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1{padding-bottom:.25rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pl-0{padding-left:0}.pl-10{padding-left:2.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-6{padding-left:1.5rem}.pl-9{padding-left:2.25rem}.pr-8{padding-right:2rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.italic{font-style:italic}.leading-6{line-height:1.5rem}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-orange-500{--tw-text-opacity: 1;color:rgb(249 115 22 / var(--tw-text-opacity, 1))}.text-orange-600{--tw-text-opacity: 1;color:rgb(234 88 12 / var(--tw-text-opacity, 1))}.text-orange-700{--tw-text-opacity: 1;color:rgb(194 65 12 / var(--tw-text-opacity, 1))}.text-primary-400{--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.text-primary-500{--tw-text-opacity: 1;color:rgb(14 165 233 / var(--tw-text-opacity, 1))}.text-primary-600{--tw-text-opacity: 1;color:rgb(2 132 199 / var(--tw-text-opacity, 1))}.text-primary-700{--tw-text-opacity: 1;color:rgb(3 105 161 / var(--tw-text-opacity, 1))}.text-purple-600{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.text-purple-800{--tw-text-opacity: 1;color:rgb(107 33 168 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-red-900{--tw-text-opacity: 1;color:rgb(127 29 29 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.text-yellow-800{--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-80{opacity:.8}.shadow-\[-4px_0_6px_-2px_rgba\(0\,0\,0\,0\.05\)\]{--tw-shadow: -4px 0 6px -2px rgba(0,0,0,.05);--tw-shadow-colored: -4px 0 6px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}:is(.dark *)::-webkit-scrollbar-track{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}::-webkit-scrollbar-thumb{border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}:is(.dark *)::-webkit-scrollbar-thumb{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}::-webkit-scrollbar-thumb:hover{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}:is(.dark *)::-webkit-scrollbar-thumb:hover{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.last\:border-0:last-child{border-width:0px}.hover\:border-gray-200:hover{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.hover\:border-primary-200:hover{--tw-border-opacity: 1;border-color:rgb(186 230 253 / var(--tw-border-opacity, 1))}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-800\/50:hover{background-color:#1f293780}.hover\:bg-orange-200:hover{--tw-bg-opacity: 1;background-color:rgb(254 215 170 / var(--tw-bg-opacity, 1))}.hover\:bg-primary-100:hover{--tw-bg-opacity: 1;background-color:rgb(224 242 254 / var(--tw-bg-opacity, 1))}.hover\:bg-primary-50:hover{--tw-bg-opacity: 1;background-color:rgb(240 249 255 / var(--tw-bg-opacity, 1))}.hover\:bg-red-100:hover{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.hover\:text-primary-600:hover{--tw-text-opacity: 1;color:rgb(2 132 199 / var(--tw-text-opacity, 1))}.hover\:text-primary-700:hover{--tw-text-opacity: 1;color:rgb(3 105 161 / var(--tw-text-opacity, 1))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-primary-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(14 165 233 / var(--tw-ring-opacity, 1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.group:hover .group-hover\:border-primary-300{--tw-border-opacity: 1;border-color:rgb(125 211 252 / var(--tw-border-opacity, 1))}.group:hover .group-hover\:bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.dark\:divide-gray-700:is(.dark *)>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(55 65 81 / var(--tw-divide-opacity, 1))}.dark\:divide-gray-800:is(.dark *)>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(31 41 55 / var(--tw-divide-opacity, 1))}.dark\:border-gray-600:is(.dark *){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.dark\:border-gray-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.dark\:border-gray-700\/50:is(.dark *){border-color:#37415180}.dark\:border-gray-800\/50:is(.dark *){border-color:#1f293780}.dark\:border-primary-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(7 89 133 / var(--tw-border-opacity, 1))}.dark\:border-red-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(153 27 27 / var(--tw-border-opacity, 1))}.dark\:border-red-800\/50:is(.dark *){border-color:#991b1b80}.dark\:bg-blue-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 58 138 / var(--tw-bg-opacity, 1))}.dark\:bg-blue-900\/30:is(.dark *){background-color:#1e3a8a4d}.dark\:bg-gray-600:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-700\/50:is(.dark *){background-color:#37415180}.dark\:bg-gray-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-800\/30:is(.dark *){background-color:#1f29374d}.dark\:bg-gray-800\/50:is(.dark *){background-color:#1f293780}.dark\:bg-gray-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-900\/50:is(.dark *){background-color:#11182780}.dark\:bg-green-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(20 83 45 / var(--tw-bg-opacity, 1))}.dark\:bg-green-900\/30:is(.dark *){background-color:#14532d4d}.dark\:bg-indigo-900\/30:is(.dark *){background-color:#312e814d}.dark\:bg-orange-900\/30:is(.dark *){background-color:#7c2d124d}.dark\:bg-primary-900\/10:is(.dark *){background-color:#0c4a6e1a}.dark\:bg-primary-900\/20:is(.dark *){background-color:#0c4a6e33}.dark\:bg-primary-900\/30:is(.dark *){background-color:#0c4a6e4d}.dark\:bg-purple-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(88 28 135 / var(--tw-bg-opacity, 1))}.dark\:bg-purple-900\/30:is(.dark *){background-color:#581c874d}.dark\:bg-red-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(127 29 29 / var(--tw-bg-opacity, 1))}.dark\:bg-red-900\/20:is(.dark *){background-color:#7f1d1d33}.dark\:bg-red-900\/30:is(.dark *){background-color:#7f1d1d4d}.dark\:bg-yellow-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(113 63 18 / var(--tw-bg-opacity, 1))}.dark\:bg-yellow-900\/30:is(.dark *){background-color:#713f124d}.dark\:text-blue-200:is(.dark *){--tw-text-opacity: 1;color:rgb(191 219 254 / var(--tw-text-opacity, 1))}.dark\:text-blue-400:is(.dark *){--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.dark\:text-gray-100:is(.dark *){--tw-text-opacity: 1;color:rgb(243 244 246 / var(--tw-text-opacity, 1))}.dark\:text-gray-200:is(.dark *){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.dark\:text-gray-300:is(.dark *){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.dark\:text-gray-400:is(.dark *){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.dark\:text-gray-600:is(.dark *){--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.dark\:text-green-200:is(.dark *){--tw-text-opacity: 1;color:rgb(187 247 208 / var(--tw-text-opacity, 1))}.dark\:text-green-400:is(.dark *){--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.dark\:text-indigo-400:is(.dark *){--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.dark\:text-orange-300:is(.dark *){--tw-text-opacity: 1;color:rgb(253 186 116 / var(--tw-text-opacity, 1))}.dark\:text-orange-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.dark\:text-primary-400:is(.dark *){--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.dark\:text-purple-200:is(.dark *){--tw-text-opacity: 1;color:rgb(233 213 255 / var(--tw-text-opacity, 1))}.dark\:text-purple-400:is(.dark *){--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.dark\:text-red-100:is(.dark *){--tw-text-opacity: 1;color:rgb(254 226 226 / var(--tw-text-opacity, 1))}.dark\:text-red-200:is(.dark *){--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.dark\:text-red-300:is(.dark *){--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-yellow-200:is(.dark *){--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.dark\:text-yellow-400:is(.dark *){--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.dark\:text-yellow-500:is(.dark *){--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.dark\:hover\:border-gray-700:hover:is(.dark *){--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.dark\:hover\:border-primary-800:hover:is(.dark *){--tw-border-opacity: 1;border-color:rgb(7 89 133 / var(--tw-border-opacity, 1))}.dark\:hover\:bg-gray-600:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-gray-700:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-gray-700\/30:hover:is(.dark *){background-color:#3741514d}.dark\:hover\:bg-gray-700\/50:hover:is(.dark *){background-color:#37415180}.dark\:hover\:bg-gray-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-gray-800\/50:hover:is(.dark *){background-color:#1f293780}.dark\:hover\:bg-orange-900\/50:hover:is(.dark *){background-color:#7c2d1280}.dark\:hover\:bg-primary-900\/50:hover:is(.dark *){background-color:#0c4a6e80}.dark\:hover\:bg-red-900\/50:hover:is(.dark *){background-color:#7f1d1d80}.dark\:hover\:text-gray-300:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.dark\:hover\:text-primary-400:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.group:hover .dark\:group-hover\:border-primary-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(3 105 161 / var(--tw-border-opacity, 1))}.group:hover .dark\:group-hover\:bg-gray-800\/50:is(.dark *){background-color:#1f293780}@media(min-width:640px){.sm\:my-8{margin-top:2rem;margin-bottom:2rem}.sm\:ml-3{margin-left:.75rem}.sm\:ml-4{margin-left:1rem}.sm\:mt-0{margin-top:0}.sm\:block{display:block}.sm\:inline-block{display:inline-block}.sm\:flex{display:flex}.sm\:hidden{display:none}.sm\:h-screen{height:100vh}.sm\:w-64{width:16rem}.sm\:w-auto{width:auto}.sm\:flex-none{flex:none}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:flex-row-reverse{flex-direction:row-reverse}.sm\:flex-col{flex-direction:column}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:border-transparent{border-color:transparent}.sm\:bg-transparent{background-color:transparent}.sm\:p-0{padding:0}.sm\:p-2{padding:.5rem}.sm\:p-4{padding:1rem}.sm\:p-5{padding:1.25rem}.sm\:p-6{padding:1.5rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-4{padding-top:1rem;padding-bottom:1rem}.sm\:pb-4{padding-bottom:1rem}.sm\:pl-0{padding-left:0}.sm\:pl-7{padding-left:1.75rem}.sm\:text-left{text-align:left}.sm\:align-middle{vertical-align:middle}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-lg{font-size:1.125rem;line-height:1.75rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:opacity-0{opacity:0}.sm\:shadow-none{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.group:hover .sm\:group-hover\:opacity-100{opacity:1}}@media(min-width:768px){.md\:col-span-3{grid-column:span 3 / span 3}.md\:col-span-6{grid-column:span 6 / span 6}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:1024px){.lg\:left-56{left:14rem}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:min-h-0{min-height:0px}.lg\:w-64{width:16rem}.lg\:translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media(min-width:1280px){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}} diff --git a/apps/admin/assets/spider-Bxy9e0gU.js b/apps/admin/assets/spider-Bxy9e0gU.js new file mode 100644 index 00000000..398249ba --- /dev/null +++ b/apps/admin/assets/spider-Bxy9e0gU.js @@ -0,0 +1 @@ +import{a as r}from"./admin-DEAtY0pm.js";const a={async listSources(){const t=await r.listSources();return{js:t.js||[],catvod:t.catvod||[],php:t.php||[],py:t.py||[]}},async validateSpider(t){const e=await r.validateSource(t);return e.isValid?{isError:!1,content:[{text:e.message||"验证通过"}]}:{isError:!0,content:[{text:e.error}]}},async checkSyntax(t){const e=await r.checkSyntax(t);return e.isValid?{isError:!1,content:[{text:e.message||"语法正确"}]}:{isError:!0,content:[{text:e.error}]}},async getTemplate(){return(await r.getTemplate()).template},async debugRule(t){return{isError:!0,content:[{text:"调试功能暂未实现"}]}}};export{a as s}; diff --git a/apps/admin/assets/system-BaTh0baW.js b/apps/admin/assets/system-BaTh0baW.js new file mode 100644 index 00000000..8f8b766c --- /dev/null +++ b/apps/admin/assets/system-BaTh0baW.js @@ -0,0 +1 @@ +import{d as i,r as a}from"./vendor-B6xRL-fs.js";import{s as r}from"./system-CxybzrTo.js";import{s as h}from"./spider-Bxy9e0gU.js";const w=i("system",()=>{const o=a({status:"unknown"}),c=a([]),l=a([]),u=a({js:[],catvod:[],php:[],py:[]}),s=a(!1),t=a(null);return{health:o,logs:c,routes:l,sources:u,loading:s,error:t,checkHealth:async()=>{try{o.value=await r.getHealth()}catch(e){o.value={status:"error",message:e.message}}},fetchLogs:async(e=100)=>{s.value=!0,t.value=null;try{c.value=await r.getLogs(e)}catch(n){t.value=n.message,console.error("Failed to fetch logs:",n)}finally{s.value=!1}},fetchRoutes:async()=>{try{l.value=await r.getRoutes()}catch(e){t.value=e.message,console.error("Failed to fetch routes:",e)}},fetchSources:async()=>{s.value=!0,t.value=null;try{u.value=await h.listSources()}catch(e){t.value=e.message,console.error("Failed to fetch sources:",e)}finally{s.value=!1}},restartService:async()=>{s.value=!0,t.value=null;try{await r.restartService()}catch(e){throw t.value=e.message,console.error("Failed to restart service:",e),e}finally{s.value=!1}}}});export{w as u}; diff --git a/apps/admin/assets/system-CxybzrTo.js b/apps/admin/assets/system-CxybzrTo.js new file mode 100644 index 00000000..c797d857 --- /dev/null +++ b/apps/admin/assets/system-CxybzrTo.js @@ -0,0 +1 @@ +import{a as t}from"./admin-DEAtY0pm.js";const r={async getHealth(){return await t.getHealth()},async restartService(){return await t.restartService()},async getRoutes(){return await t.getRoutes()},async getLogs(e=100){return await t.getLogs(e)},async getApiList(){return await t.getApiDocs()}};export{r as s}; diff --git a/apps/admin/assets/ui-42ANG6Sg.js b/apps/admin/assets/ui-42ANG6Sg.js new file mode 100644 index 00000000..ed39c512 --- /dev/null +++ b/apps/admin/assets/ui-42ANG6Sg.js @@ -0,0 +1,6 @@ +function We(e,t){return function(){return e.apply(t,arguments)}}const{toString:mt}=Object.prototype,{getPrototypeOf:we}=Object,{iterator:re,toStringTag:Ke}=Symbol,se=(e=>t=>{const n=mt.call(t);return e[n]||(e[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),F=e=>(e=e.toLowerCase(),t=>se(t)===e),oe=e=>t=>typeof t===e,{isArray:M}=Array,H=oe("undefined");function J(e){return e!==null&&!H(e)&&e.constructor!==null&&!H(e.constructor)&&A(e.constructor.isBuffer)&&e.constructor.isBuffer(e)}const ve=F("ArrayBuffer");function yt(e){let t;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?t=ArrayBuffer.isView(e):t=e&&e.buffer&&ve(e.buffer),t}const bt=oe("string"),A=oe("function"),Xe=oe("number"),V=e=>e!==null&&typeof e=="object",wt=e=>e===!0||e===!1,Y=e=>{if(se(e)!=="object")return!1;const t=we(e);return(t===null||t===Object.prototype||Object.getPrototypeOf(t)===null)&&!(Ke in e)&&!(re in e)},Rt=e=>{if(!V(e)||J(e))return!1;try{return Object.keys(e).length===0&&Object.getPrototypeOf(e)===Object.prototype}catch{return!1}},Et=F("Date"),gt=F("File"),St=e=>!!(e&&typeof e.uri<"u"),Ot=e=>e&&typeof e.getParts<"u",Tt=F("Blob"),At=F("FileList"),Ct=e=>V(e)&&A(e.pipe);function xt(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}}const Ne=xt(),Pe=typeof Ne.FormData<"u"?Ne.FormData:void 0,_t=e=>{let t;return e&&(Pe&&e instanceof Pe||A(e.append)&&((t=se(e))==="formdata"||t==="object"&&A(e.toString)&&e.toString()==="[object FormData]"))},Nt=F("URLSearchParams"),[Pt,Ft,Ut,Lt]=["ReadableStream","Request","Response","Headers"].map(F),Dt=e=>e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function W(e,t,{allOwnKeys:n=!1}={}){if(e===null||typeof e>"u")return;let r,s;if(typeof e!="object"&&(e=[e]),M(e))for(r=0,s=e.length;r0;)if(s=n[r],t===s.toLowerCase())return s;return null}const k=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,Qe=e=>!H(e)&&e!==k;function he(){const{caseless:e,skipUndefined:t}=Qe(this)&&this||{},n={},r=(s,o)=>{if(o==="__proto__"||o==="constructor"||o==="prototype")return;const i=e&&Ge(n,o)||o;Y(n[i])&&Y(s)?n[i]=he(n[i],s):Y(s)?n[i]=he({},s):M(s)?n[i]=s.slice():(!t||!H(s))&&(n[i]=s)};for(let s=0,o=arguments.length;s(W(t,(s,o)=>{n&&A(s)?Object.defineProperty(e,o,{value:We(s,n),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(e,o,{value:s,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:r}),e),kt=e=>(e.charCodeAt(0)===65279&&(e=e.slice(1)),e),jt=(e,t,n,r)=>{e.prototype=Object.create(t.prototype,r),Object.defineProperty(e.prototype,"constructor",{value:e,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(e,"super",{value:t.prototype}),n&&Object.assign(e.prototype,n)},qt=(e,t,n,r)=>{let s,o,i;const c={};if(t=t||{},e==null)return t;do{for(s=Object.getOwnPropertyNames(e),o=s.length;o-- >0;)i=s[o],(!r||r(i,e,t))&&!c[i]&&(t[i]=e[i],c[i]=!0);e=n!==!1&&we(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},It=(e,t,n)=>{e=String(e),(n===void 0||n>e.length)&&(n=e.length),n-=t.length;const r=e.indexOf(t,n);return r!==-1&&r===n},Ht=e=>{if(!e)return null;if(M(e))return e;let t=e.length;if(!Xe(t))return null;const n=new Array(t);for(;t-- >0;)n[t]=e[t];return n},Mt=(e=>t=>e&&t instanceof e)(typeof Uint8Array<"u"&&we(Uint8Array)),$t=(e,t)=>{const r=(e&&e[re]).call(e);let s;for(;(s=r.next())&&!s.done;){const o=s.value;t.call(e,o[0],o[1])}},zt=(e,t)=>{let n;const r=[];for(;(n=e.exec(t))!==null;)r.push(n);return r},Jt=F("HTMLFormElement"),Vt=e=>e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(n,r,s){return r.toUpperCase()+s}),Fe=(({hasOwnProperty:e})=>(t,n)=>e.call(t,n))(Object.prototype),Wt=F("RegExp"),Ze=(e,t)=>{const n=Object.getOwnPropertyDescriptors(e),r={};W(n,(s,o)=>{let i;(i=t(s,o,e))!==!1&&(r[o]=i||s)}),Object.defineProperties(e,r)},Kt=e=>{Ze(e,(t,n)=>{if(A(e)&&["arguments","caller","callee"].indexOf(n)!==-1)return!1;const r=e[n];if(A(r)){if(t.enumerable=!1,"writable"in t){t.writable=!1;return}t.set||(t.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")})}})},vt=(e,t)=>{const n={},r=s=>{s.forEach(o=>{n[o]=!0})};return M(e)?r(e):r(String(e).split(t)),n},Xt=()=>{},Gt=(e,t)=>e!=null&&Number.isFinite(e=+e)?e:t;function Qt(e){return!!(e&&A(e.append)&&e[Ke]==="FormData"&&e[re])}const Zt=e=>{const t=new Array(10),n=(r,s)=>{if(V(r)){if(t.indexOf(r)>=0)return;if(J(r))return r;if(!("toJSON"in r)){t[s]=r;const o=M(r)?[]:{};return W(r,(i,c)=>{const p=n(i,s+1);!H(p)&&(o[c]=p)}),t[s]=void 0,o}}return r};return n(e,0)},Yt=F("AsyncFunction"),en=e=>e&&(V(e)||A(e))&&A(e.then)&&A(e.catch),Ye=((e,t)=>e?setImmediate:t?((n,r)=>(k.addEventListener("message",({source:s,data:o})=>{s===k&&o===n&&r.length&&r.shift()()},!1),s=>{r.push(s),k.postMessage(n,"*")}))(`axios@${Math.random()}`,[]):n=>setTimeout(n))(typeof setImmediate=="function",A(k.postMessage)),tn=typeof queueMicrotask<"u"?queueMicrotask.bind(k):typeof process<"u"&&process.nextTick||Ye,nn=e=>e!=null&&A(e[re]),a={isArray:M,isArrayBuffer:ve,isBuffer:J,isFormData:_t,isArrayBufferView:yt,isString:bt,isNumber:Xe,isBoolean:wt,isObject:V,isPlainObject:Y,isEmptyObject:Rt,isReadableStream:Pt,isRequest:Ft,isResponse:Ut,isHeaders:Lt,isUndefined:H,isDate:Et,isFile:gt,isReactNativeBlob:St,isReactNative:Ot,isBlob:Tt,isRegExp:Wt,isFunction:A,isStream:Ct,isURLSearchParams:Nt,isTypedArray:Mt,isFileList:At,forEach:W,merge:he,extend:Bt,trim:Dt,stripBOM:kt,inherits:jt,toFlatObject:qt,kindOf:se,kindOfTest:F,endsWith:It,toArray:Ht,forEachEntry:$t,matchAll:zt,isHTMLForm:Jt,hasOwnProperty:Fe,hasOwnProp:Fe,reduceDescriptors:Ze,freezeMethods:Kt,toObjectSet:vt,toCamelCase:Vt,noop:Xt,toFiniteNumber:Gt,findKey:Ge,global:k,isContextDefined:Qe,isSpecCompliantForm:Qt,toJSONObject:Zt,isAsyncFn:Yt,isThenable:en,setImmediate:Ye,asap:tn,isIterable:nn};let y=class et extends Error{static from(t,n,r,s,o,i){const c=new et(t.message,n||t.code,r,s,o);return c.cause=t,c.name=t.name,t.status!=null&&c.status==null&&(c.status=t.status),i&&Object.assign(c,i),c}constructor(t,n,r,s,o){super(t),Object.defineProperty(this,"message",{value:t,enumerable:!0,writable:!0,configurable:!0}),this.name="AxiosError",this.isAxiosError=!0,n&&(this.code=n),r&&(this.config=r),s&&(this.request=s),o&&(this.response=o,this.status=o.status)}toJSON(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:a.toJSONObject(this.config),code:this.code,status:this.status}}};y.ERR_BAD_OPTION_VALUE="ERR_BAD_OPTION_VALUE";y.ERR_BAD_OPTION="ERR_BAD_OPTION";y.ECONNABORTED="ECONNABORTED";y.ETIMEDOUT="ETIMEDOUT";y.ERR_NETWORK="ERR_NETWORK";y.ERR_FR_TOO_MANY_REDIRECTS="ERR_FR_TOO_MANY_REDIRECTS";y.ERR_DEPRECATED="ERR_DEPRECATED";y.ERR_BAD_RESPONSE="ERR_BAD_RESPONSE";y.ERR_BAD_REQUEST="ERR_BAD_REQUEST";y.ERR_CANCELED="ERR_CANCELED";y.ERR_NOT_SUPPORT="ERR_NOT_SUPPORT";y.ERR_INVALID_URL="ERR_INVALID_URL";const rn=null;function me(e){return a.isPlainObject(e)||a.isArray(e)}function tt(e){return a.endsWith(e,"[]")?e.slice(0,-2):e}function ue(e,t,n){return e?e.concat(t).map(function(s,o){return s=tt(s),!n&&o?"["+s+"]":s}).join(n?".":""):t}function sn(e){return a.isArray(e)&&!e.some(me)}const on=a.toFlatObject(a,{},null,function(t){return/^is[A-Z]/.test(t)});function ie(e,t,n){if(!a.isObject(e))throw new TypeError("target must be an object");t=t||new FormData,n=a.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,function(m,d){return!a.isUndefined(d[m])});const r=n.metaTokens,s=n.visitor||l,o=n.dots,i=n.indexes,p=(n.Blob||typeof Blob<"u"&&Blob)&&a.isSpecCompliantForm(t);if(!a.isFunction(s))throw new TypeError("visitor must be a function");function f(u){if(u===null)return"";if(a.isDate(u))return u.toISOString();if(a.isBoolean(u))return u.toString();if(!p&&a.isBlob(u))throw new y("Blob is not supported. Use a Buffer instead.");return a.isArrayBuffer(u)||a.isTypedArray(u)?p&&typeof Blob=="function"?new Blob([u]):Buffer.from(u):u}function l(u,m,d){let w=u;if(a.isReactNative(t)&&a.isReactNativeBlob(u))return t.append(ue(d,m,o),f(u)),!1;if(u&&!d&&typeof u=="object"){if(a.endsWith(m,"{}"))m=r?m:m.slice(0,-2),u=JSON.stringify(u);else if(a.isArray(u)&&sn(u)||(a.isFileList(u)||a.endsWith(m,"[]"))&&(w=a.toArray(u)))return m=tt(m),w.forEach(function(E,O){!(a.isUndefined(E)||E===null)&&t.append(i===!0?ue([m],O,o):i===null?m:m+"[]",f(E))}),!1}return me(u)?!0:(t.append(ue(d,m,o),f(u)),!1)}const h=[],b=Object.assign(on,{defaultVisitor:l,convertValue:f,isVisitable:me});function g(u,m){if(!a.isUndefined(u)){if(h.indexOf(u)!==-1)throw Error("Circular reference detected in "+m.join("."));h.push(u),a.forEach(u,function(w,x){(!(a.isUndefined(w)||w===null)&&s.call(t,w,a.isString(x)?x.trim():x,m,b))===!0&&g(w,m?m.concat(x):[x])}),h.pop()}}if(!a.isObject(e))throw new TypeError("data must be an object");return g(e),t}function Ue(e){const t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,function(r){return t[r]})}function Re(e,t){this._pairs=[],e&&ie(e,this,t)}const nt=Re.prototype;nt.append=function(t,n){this._pairs.push([t,n])};nt.toString=function(t){const n=t?function(r){return t.call(this,r,Ue)}:Ue;return this._pairs.map(function(s){return n(s[0])+"="+n(s[1])},"").join("&")};function an(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function rt(e,t,n){if(!t)return e;const r=n&&n.encode||an,s=a.isFunction(n)?{serialize:n}:n,o=s&&s.serialize;let i;if(o?i=o(t,s):i=a.isURLSearchParams(t)?t.toString():new Re(t,s).toString(r),i){const c=e.indexOf("#");c!==-1&&(e=e.slice(0,c)),e+=(e.indexOf("?")===-1?"?":"&")+i}return e}class Le{constructor(){this.handlers=[]}use(t,n,r){return this.handlers.push({fulfilled:t,rejected:n,synchronous:r?r.synchronous:!1,runWhen:r?r.runWhen:null}),this.handlers.length-1}eject(t){this.handlers[t]&&(this.handlers[t]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(t){a.forEach(this.handlers,function(r){r!==null&&t(r)})}}const Ee={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0},cn=typeof URLSearchParams<"u"?URLSearchParams:Re,ln=typeof FormData<"u"?FormData:null,un=typeof Blob<"u"?Blob:null,fn={isBrowser:!0,classes:{URLSearchParams:cn,FormData:ln,Blob:un},protocols:["http","https","file","blob","url","data"]},ge=typeof window<"u"&&typeof document<"u",ye=typeof navigator=="object"&&navigator||void 0,dn=ge&&(!ye||["ReactNative","NativeScript","NS"].indexOf(ye.product)<0),pn=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",hn=ge&&window.location.href||"http://localhost",mn=Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:ge,hasStandardBrowserEnv:dn,hasStandardBrowserWebWorkerEnv:pn,navigator:ye,origin:hn},Symbol.toStringTag,{value:"Module"})),S={...mn,...fn};function yn(e,t){return ie(e,new S.classes.URLSearchParams,{visitor:function(n,r,s,o){return S.isNode&&a.isBuffer(n)?(this.append(r,n.toString("base64")),!1):o.defaultVisitor.apply(this,arguments)},...t})}function bn(e){return a.matchAll(/\w+|\[(\w*)]/g,e).map(t=>t[0]==="[]"?"":t[1]||t[0])}function wn(e){const t={},n=Object.keys(e);let r;const s=n.length;let o;for(r=0;r=n.length;return i=!i&&a.isArray(s)?s.length:i,p?(a.hasOwnProp(s,i)?s[i]=[s[i],r]:s[i]=r,!c):((!s[i]||!a.isObject(s[i]))&&(s[i]=[]),t(n,r,s[i],o)&&a.isArray(s[i])&&(s[i]=wn(s[i])),!c)}if(a.isFormData(e)&&a.isFunction(e.entries)){const n={};return a.forEachEntry(e,(r,s)=>{t(bn(r),s,n,0)}),n}return null}function Rn(e,t,n){if(a.isString(e))try{return(t||JSON.parse)(e),a.trim(e)}catch(r){if(r.name!=="SyntaxError")throw r}return(n||JSON.stringify)(e)}const K={transitional:Ee,adapter:["xhr","http","fetch"],transformRequest:[function(t,n){const r=n.getContentType()||"",s=r.indexOf("application/json")>-1,o=a.isObject(t);if(o&&a.isHTMLForm(t)&&(t=new FormData(t)),a.isFormData(t))return s?JSON.stringify(st(t)):t;if(a.isArrayBuffer(t)||a.isBuffer(t)||a.isStream(t)||a.isFile(t)||a.isBlob(t)||a.isReadableStream(t))return t;if(a.isArrayBufferView(t))return t.buffer;if(a.isURLSearchParams(t))return n.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),t.toString();let c;if(o){if(r.indexOf("application/x-www-form-urlencoded")>-1)return yn(t,this.formSerializer).toString();if((c=a.isFileList(t))||r.indexOf("multipart/form-data")>-1){const p=this.env&&this.env.FormData;return ie(c?{"files[]":t}:t,p&&new p,this.formSerializer)}}return o||s?(n.setContentType("application/json",!1),Rn(t)):t}],transformResponse:[function(t){const n=this.transitional||K.transitional,r=n&&n.forcedJSONParsing,s=this.responseType==="json";if(a.isResponse(t)||a.isReadableStream(t))return t;if(t&&a.isString(t)&&(r&&!this.responseType||s)){const i=!(n&&n.silentJSONParsing)&&s;try{return JSON.parse(t,this.parseReviver)}catch(c){if(i)throw c.name==="SyntaxError"?y.from(c,y.ERR_BAD_RESPONSE,this,null,this.response):c}}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:S.classes.FormData,Blob:S.classes.Blob},validateStatus:function(t){return t>=200&&t<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};a.forEach(["delete","get","head","post","put","patch"],e=>{K.headers[e]={}});const En=a.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),gn=e=>{const t={};let n,r,s;return e&&e.split(` +`).forEach(function(i){s=i.indexOf(":"),n=i.substring(0,s).trim().toLowerCase(),r=i.substring(s+1).trim(),!(!n||t[n]&&En[n])&&(n==="set-cookie"?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)}),t},De=Symbol("internals");function z(e){return e&&String(e).trim().toLowerCase()}function ee(e){return e===!1||e==null?e:a.isArray(e)?e.map(ee):String(e)}function Sn(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=n.exec(e);)t[r[1]]=r[2];return t}const On=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function fe(e,t,n,r,s){if(a.isFunction(r))return r.call(this,t,n);if(s&&(t=n),!!a.isString(t)){if(a.isString(r))return t.indexOf(r)!==-1;if(a.isRegExp(r))return r.test(t)}}function Tn(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(t,n,r)=>n.toUpperCase()+r)}function An(e,t){const n=a.toCamelCase(" "+t);["get","set","has"].forEach(r=>{Object.defineProperty(e,r+n,{value:function(s,o,i){return this[r].call(this,t,s,o,i)},configurable:!0})})}let C=class{constructor(t){t&&this.set(t)}set(t,n,r){const s=this;function o(c,p,f){const l=z(p);if(!l)throw new Error("header name must be a non-empty string");const h=a.findKey(s,l);(!h||s[h]===void 0||f===!0||f===void 0&&s[h]!==!1)&&(s[h||p]=ee(c))}const i=(c,p)=>a.forEach(c,(f,l)=>o(f,l,p));if(a.isPlainObject(t)||t instanceof this.constructor)i(t,n);else if(a.isString(t)&&(t=t.trim())&&!On(t))i(gn(t),n);else if(a.isObject(t)&&a.isIterable(t)){let c={},p,f;for(const l of t){if(!a.isArray(l))throw TypeError("Object iterator must return a key-value pair");c[f=l[0]]=(p=c[f])?a.isArray(p)?[...p,l[1]]:[p,l[1]]:l[1]}i(c,n)}else t!=null&&o(n,t,r);return this}get(t,n){if(t=z(t),t){const r=a.findKey(this,t);if(r){const s=this[r];if(!n)return s;if(n===!0)return Sn(s);if(a.isFunction(n))return n.call(this,s,r);if(a.isRegExp(n))return n.exec(s);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,n){if(t=z(t),t){const r=a.findKey(this,t);return!!(r&&this[r]!==void 0&&(!n||fe(this,this[r],r,n)))}return!1}delete(t,n){const r=this;let s=!1;function o(i){if(i=z(i),i){const c=a.findKey(r,i);c&&(!n||fe(r,r[c],c,n))&&(delete r[c],s=!0)}}return a.isArray(t)?t.forEach(o):o(t),s}clear(t){const n=Object.keys(this);let r=n.length,s=!1;for(;r--;){const o=n[r];(!t||fe(this,this[o],o,t,!0))&&(delete this[o],s=!0)}return s}normalize(t){const n=this,r={};return a.forEach(this,(s,o)=>{const i=a.findKey(r,o);if(i){n[i]=ee(s),delete n[o];return}const c=t?Tn(o):String(o).trim();c!==o&&delete n[o],n[c]=ee(s),r[c]=!0}),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const n=Object.create(null);return a.forEach(this,(r,s)=>{r!=null&&r!==!1&&(n[s]=t&&a.isArray(r)?r.join(", "):r)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([t,n])=>t+": "+n).join(` +`)}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...n){const r=new this(t);return n.forEach(s=>r.set(s)),r}static accessor(t){const r=(this[De]=this[De]={accessors:{}}).accessors,s=this.prototype;function o(i){const c=z(i);r[c]||(An(s,i),r[c]=!0)}return a.isArray(t)?t.forEach(o):o(t),this}};C.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);a.reduceDescriptors(C.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(r){this[n]=r}}});a.freezeMethods(C);function de(e,t){const n=this||K,r=t||n,s=C.from(r.headers);let o=r.data;return a.forEach(e,function(c){o=c.call(n,o,s.normalize(),t?t.status:void 0)}),s.normalize(),o}function ot(e){return!!(e&&e.__CANCEL__)}let v=class extends y{constructor(t,n,r){super(t??"canceled",y.ERR_CANCELED,n,r),this.name="CanceledError",this.__CANCEL__=!0}};function it(e,t,n){const r=n.config.validateStatus;!n.status||!r||r(n.status)?e(n):t(new y("Request failed with status code "+n.status,[y.ERR_BAD_REQUEST,y.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function Cn(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function xn(e,t){e=e||10;const n=new Array(e),r=new Array(e);let s=0,o=0,i;return t=t!==void 0?t:1e3,function(p){const f=Date.now(),l=r[o];i||(i=f),n[s]=p,r[s]=f;let h=o,b=0;for(;h!==s;)b+=n[h++],h=h%e;if(s=(s+1)%e,s===o&&(o=(o+1)%e),f-i{n=l,s=null,o&&(clearTimeout(o),o=null),e(...f)};return[(...f)=>{const l=Date.now(),h=l-n;h>=r?i(f,l):(s=f,o||(o=setTimeout(()=>{o=null,i(s)},r-h)))},()=>s&&i(s)]}const ne=(e,t,n=3)=>{let r=0;const s=xn(50,250);return _n(o=>{const i=o.loaded,c=o.lengthComputable?o.total:void 0,p=i-r,f=s(p),l=i<=c;r=i;const h={loaded:i,total:c,progress:c?i/c:void 0,bytes:p,rate:f||void 0,estimated:f&&c&&l?(c-i)/f:void 0,event:o,lengthComputable:c!=null,[t?"download":"upload"]:!0};e(h)},n)},Be=(e,t)=>{const n=e!=null;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},ke=e=>(...t)=>a.asap(()=>e(...t)),Nn=S.hasStandardBrowserEnv?((e,t)=>n=>(n=new URL(n,S.origin),e.protocol===n.protocol&&e.host===n.host&&(t||e.port===n.port)))(new URL(S.origin),S.navigator&&/(msie|trident)/i.test(S.navigator.userAgent)):()=>!0,Pn=S.hasStandardBrowserEnv?{write(e,t,n,r,s,o,i){if(typeof document>"u")return;const c=[`${e}=${encodeURIComponent(t)}`];a.isNumber(n)&&c.push(`expires=${new Date(n).toUTCString()}`),a.isString(r)&&c.push(`path=${r}`),a.isString(s)&&c.push(`domain=${s}`),o===!0&&c.push("secure"),a.isString(i)&&c.push(`SameSite=${i}`),document.cookie=c.join("; ")},read(e){if(typeof document>"u")return null;const t=document.cookie.match(new RegExp("(?:^|; )"+e+"=([^;]*)"));return t?decodeURIComponent(t[1]):null},remove(e){this.write(e,"",Date.now()-864e5,"/")}}:{write(){},read(){return null},remove(){}};function Fn(e){return typeof e!="string"?!1:/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function Un(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function at(e,t,n){let r=!Fn(t);return e&&(r||n==!1)?Un(e,t):t}const je=e=>e instanceof C?{...e}:e;function q(e,t){t=t||{};const n={};function r(f,l,h,b){return a.isPlainObject(f)&&a.isPlainObject(l)?a.merge.call({caseless:b},f,l):a.isPlainObject(l)?a.merge({},l):a.isArray(l)?l.slice():l}function s(f,l,h,b){if(a.isUndefined(l)){if(!a.isUndefined(f))return r(void 0,f,h,b)}else return r(f,l,h,b)}function o(f,l){if(!a.isUndefined(l))return r(void 0,l)}function i(f,l){if(a.isUndefined(l)){if(!a.isUndefined(f))return r(void 0,f)}else return r(void 0,l)}function c(f,l,h){if(h in t)return r(f,l);if(h in e)return r(void 0,f)}const p={url:o,method:o,data:o,baseURL:i,transformRequest:i,transformResponse:i,paramsSerializer:i,timeout:i,timeoutMessage:i,withCredentials:i,withXSRFToken:i,adapter:i,responseType:i,xsrfCookieName:i,xsrfHeaderName:i,onUploadProgress:i,onDownloadProgress:i,decompress:i,maxContentLength:i,maxBodyLength:i,beforeRedirect:i,transport:i,httpAgent:i,httpsAgent:i,cancelToken:i,socketPath:i,responseEncoding:i,validateStatus:c,headers:(f,l,h)=>s(je(f),je(l),h,!0)};return a.forEach(Object.keys({...e,...t}),function(l){if(l==="__proto__"||l==="constructor"||l==="prototype")return;const h=a.hasOwnProp(p,l)?p[l]:s,b=h(e[l],t[l],l);a.isUndefined(b)&&h!==c||(n[l]=b)}),n}const ct=e=>{const t=q({},e);let{data:n,withXSRFToken:r,xsrfHeaderName:s,xsrfCookieName:o,headers:i,auth:c}=t;if(t.headers=i=C.from(i),t.url=rt(at(t.baseURL,t.url,t.allowAbsoluteUrls),e.params,e.paramsSerializer),c&&i.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):""))),a.isFormData(n)){if(S.hasStandardBrowserEnv||S.hasStandardBrowserWebWorkerEnv)i.setContentType(void 0);else if(a.isFunction(n.getHeaders)){const p=n.getHeaders(),f=["content-type","content-length"];Object.entries(p).forEach(([l,h])=>{f.includes(l.toLowerCase())&&i.set(l,h)})}}if(S.hasStandardBrowserEnv&&(r&&a.isFunction(r)&&(r=r(t)),r||r!==!1&&Nn(t.url))){const p=s&&o&&Pn.read(o);p&&i.set(s,p)}return t},Ln=typeof XMLHttpRequest<"u",Dn=Ln&&function(e){return new Promise(function(n,r){const s=ct(e);let o=s.data;const i=C.from(s.headers).normalize();let{responseType:c,onUploadProgress:p,onDownloadProgress:f}=s,l,h,b,g,u;function m(){g&&g(),u&&u(),s.cancelToken&&s.cancelToken.unsubscribe(l),s.signal&&s.signal.removeEventListener("abort",l)}let d=new XMLHttpRequest;d.open(s.method.toUpperCase(),s.url,!0),d.timeout=s.timeout;function w(){if(!d)return;const E=C.from("getAllResponseHeaders"in d&&d.getAllResponseHeaders()),P={data:!c||c==="text"||c==="json"?d.responseText:d.response,status:d.status,statusText:d.statusText,headers:E,config:e,request:d};it(function(_){n(_),m()},function(_){r(_),m()},P),d=null}"onloadend"in d?d.onloadend=w:d.onreadystatechange=function(){!d||d.readyState!==4||d.status===0&&!(d.responseURL&&d.responseURL.indexOf("file:")===0)||setTimeout(w)},d.onabort=function(){d&&(r(new y("Request aborted",y.ECONNABORTED,e,d)),d=null)},d.onerror=function(O){const P=O&&O.message?O.message:"Network Error",D=new y(P,y.ERR_NETWORK,e,d);D.event=O||null,r(D),d=null},d.ontimeout=function(){let O=s.timeout?"timeout of "+s.timeout+"ms exceeded":"timeout exceeded";const P=s.transitional||Ee;s.timeoutErrorMessage&&(O=s.timeoutErrorMessage),r(new y(O,P.clarifyTimeoutError?y.ETIMEDOUT:y.ECONNABORTED,e,d)),d=null},o===void 0&&i.setContentType(null),"setRequestHeader"in d&&a.forEach(i.toJSON(),function(O,P){d.setRequestHeader(P,O)}),a.isUndefined(s.withCredentials)||(d.withCredentials=!!s.withCredentials),c&&c!=="json"&&(d.responseType=s.responseType),f&&([b,u]=ne(f,!0),d.addEventListener("progress",b)),p&&d.upload&&([h,g]=ne(p),d.upload.addEventListener("progress",h),d.upload.addEventListener("loadend",g)),(s.cancelToken||s.signal)&&(l=E=>{d&&(r(!E||E.type?new v(null,e,d):E),d.abort(),d=null)},s.cancelToken&&s.cancelToken.subscribe(l),s.signal&&(s.signal.aborted?l():s.signal.addEventListener("abort",l)));const x=Cn(s.url);if(x&&S.protocols.indexOf(x)===-1){r(new y("Unsupported protocol "+x+":",y.ERR_BAD_REQUEST,e));return}d.send(o||null)})},Bn=(e,t)=>{const{length:n}=e=e?e.filter(Boolean):[];if(t||n){let r=new AbortController,s;const o=function(f){if(!s){s=!0,c();const l=f instanceof Error?f:this.reason;r.abort(l instanceof y?l:new v(l instanceof Error?l.message:l))}};let i=t&&setTimeout(()=>{i=null,o(new y(`timeout of ${t}ms exceeded`,y.ETIMEDOUT))},t);const c=()=>{e&&(i&&clearTimeout(i),i=null,e.forEach(f=>{f.unsubscribe?f.unsubscribe(o):f.removeEventListener("abort",o)}),e=null)};e.forEach(f=>f.addEventListener("abort",o));const{signal:p}=r;return p.unsubscribe=()=>a.asap(c),p}},kn=function*(e,t){let n=e.byteLength;if(n{const s=jn(e,t);let o=0,i,c=p=>{i||(i=!0,r&&r(p))};return new ReadableStream({async pull(p){try{const{done:f,value:l}=await s.next();if(f){c(),p.close();return}let h=l.byteLength;if(n){let b=o+=h;n(b)}p.enqueue(new Uint8Array(l))}catch(f){throw c(f),f}},cancel(p){return c(p),s.return()}},{highWaterMark:2})},Ie=64*1024,{isFunction:Z}=a,In=(({Request:e,Response:t})=>({Request:e,Response:t}))(a.global),{ReadableStream:He,TextEncoder:Me}=a.global,$e=(e,...t)=>{try{return!!e(...t)}catch{return!1}},Hn=e=>{e=a.merge.call({skipUndefined:!0},In,e);const{fetch:t,Request:n,Response:r}=e,s=t?Z(t):typeof fetch=="function",o=Z(n),i=Z(r);if(!s)return!1;const c=s&&Z(He),p=s&&(typeof Me=="function"?(u=>m=>u.encode(m))(new Me):async u=>new Uint8Array(await new n(u).arrayBuffer())),f=o&&c&&$e(()=>{let u=!1;const m=new n(S.origin,{body:new He,method:"POST",get duplex(){return u=!0,"half"}}).headers.has("Content-Type");return u&&!m}),l=i&&c&&$e(()=>a.isReadableStream(new r("").body)),h={stream:l&&(u=>u.body)};s&&["text","arrayBuffer","blob","formData","stream"].forEach(u=>{!h[u]&&(h[u]=(m,d)=>{let w=m&&m[u];if(w)return w.call(m);throw new y(`Response type '${u}' is not supported`,y.ERR_NOT_SUPPORT,d)})});const b=async u=>{if(u==null)return 0;if(a.isBlob(u))return u.size;if(a.isSpecCompliantForm(u))return(await new n(S.origin,{method:"POST",body:u}).arrayBuffer()).byteLength;if(a.isArrayBufferView(u)||a.isArrayBuffer(u))return u.byteLength;if(a.isURLSearchParams(u)&&(u=u+""),a.isString(u))return(await p(u)).byteLength},g=async(u,m)=>{const d=a.toFiniteNumber(u.getContentLength());return d??b(m)};return async u=>{let{url:m,method:d,data:w,signal:x,cancelToken:E,timeout:O,onDownloadProgress:P,onUploadProgress:D,responseType:_,headers:ce,withCredentials:X="same-origin",fetchOptions:Oe}=ct(u),Te=t||fetch;_=_?(_+"").toLowerCase():"text";let G=Bn([x,E&&E.toAbortSignal()],O),$=null;const B=G&&G.unsubscribe&&(()=>{G.unsubscribe()});let Ae;try{if(D&&f&&d!=="get"&&d!=="head"&&(Ae=await g(ce,w))!==0){let L=new n(m,{method:"POST",body:w,duplex:"half"}),I;if(a.isFormData(w)&&(I=L.headers.get("content-type"))&&ce.setContentType(I),L.body){const[le,Q]=Be(Ae,ne(ke(D)));w=qe(L.body,Ie,le,Q)}}a.isString(X)||(X=X?"include":"omit");const T=o&&"credentials"in n.prototype,Ce={...Oe,signal:G,method:d.toUpperCase(),headers:ce.normalize().toJSON(),body:w,duplex:"half",credentials:T?X:void 0};$=o&&new n(m,Ce);let U=await(o?Te($,Oe):Te(m,Ce));const xe=l&&(_==="stream"||_==="response");if(l&&(P||xe&&B)){const L={};["status","statusText","headers"].forEach(_e=>{L[_e]=U[_e]});const I=a.toFiniteNumber(U.headers.get("content-length")),[le,Q]=P&&Be(I,ne(ke(P),!0))||[];U=new r(qe(U.body,Ie,le,()=>{Q&&Q(),B&&B()}),L)}_=_||"text";let ht=await h[a.findKey(h,_)||"text"](U,u);return!xe&&B&&B(),await new Promise((L,I)=>{it(L,I,{data:ht,headers:C.from(U.headers),status:U.status,statusText:U.statusText,config:u,request:$})})}catch(T){throw B&&B(),T&&T.name==="TypeError"&&/Load failed|fetch/i.test(T.message)?Object.assign(new y("Network Error",y.ERR_NETWORK,u,$,T&&T.response),{cause:T.cause||T}):y.from(T,T&&T.code,u,$,T&&T.response)}}},Mn=new Map,lt=e=>{let t=e&&e.env||{};const{fetch:n,Request:r,Response:s}=t,o=[r,s,n];let i=o.length,c=i,p,f,l=Mn;for(;c--;)p=o[c],f=l.get(p),f===void 0&&l.set(p,f=c?new Map:Hn(t)),l=f;return f};lt();const Se={http:rn,xhr:Dn,fetch:{get:lt}};a.forEach(Se,(e,t)=>{if(e){try{Object.defineProperty(e,"name",{value:t})}catch{}Object.defineProperty(e,"adapterName",{value:t})}});const ze=e=>`- ${e}`,$n=e=>a.isFunction(e)||e===null||e===!1;function zn(e,t){e=a.isArray(e)?e:[e];const{length:n}=e;let r,s;const o={};for(let i=0;i`adapter ${p} `+(f===!1?"is not supported by the environment":"is not available in the build"));let c=n?i.length>1?`since : +`+i.map(ze).join(` +`):" "+ze(i[0]):"as no adapter specified";throw new y("There is no suitable adapter to dispatch the request "+c,"ERR_NOT_SUPPORT")}return s}const ut={getAdapter:zn,adapters:Se};function pe(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new v(null,e)}function Je(e){return pe(e),e.headers=C.from(e.headers),e.data=de.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded",!1),ut.getAdapter(e.adapter||K.adapter,e)(e).then(function(r){return pe(e),r.data=de.call(e,e.transformResponse,r),r.headers=C.from(r.headers),r},function(r){return ot(r)||(pe(e),r&&r.response&&(r.response.data=de.call(e,e.transformResponse,r.response),r.response.headers=C.from(r.response.headers))),Promise.reject(r)})}const ft="1.13.6",ae={};["object","boolean","number","function","string","symbol"].forEach((e,t)=>{ae[e]=function(r){return typeof r===e||"a"+(t<1?"n ":" ")+e}});const Ve={};ae.transitional=function(t,n,r){function s(o,i){return"[Axios v"+ft+"] Transitional option '"+o+"'"+i+(r?". "+r:"")}return(o,i,c)=>{if(t===!1)throw new y(s(i," has been removed"+(n?" in "+n:"")),y.ERR_DEPRECATED);return n&&!Ve[i]&&(Ve[i]=!0,console.warn(s(i," has been deprecated since v"+n+" and will be removed in the near future"))),t?t(o,i,c):!0}};ae.spelling=function(t){return(n,r)=>(console.warn(`${r} is likely a misspelling of ${t}`),!0)};function Jn(e,t,n){if(typeof e!="object")throw new y("options must be an object",y.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let s=r.length;for(;s-- >0;){const o=r[s],i=t[o];if(i){const c=e[o],p=c===void 0||i(c,o,e);if(p!==!0)throw new y("option "+o+" must be "+p,y.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new y("Unknown option "+o,y.ERR_BAD_OPTION)}}const te={assertOptions:Jn,validators:ae},N=te.validators;let j=class{constructor(t){this.defaults=t||{},this.interceptors={request:new Le,response:new Le}}async request(t,n){try{return await this._request(t,n)}catch(r){if(r instanceof Error){let s={};Error.captureStackTrace?Error.captureStackTrace(s):s=new Error;const o=s.stack?s.stack.replace(/^.+\n/,""):"";try{r.stack?o&&!String(r.stack).endsWith(o.replace(/^.+\n.+\n/,""))&&(r.stack+=` +`+o):r.stack=o}catch{}}throw r}}_request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=q(this.defaults,n);const{transitional:r,paramsSerializer:s,headers:o}=n;r!==void 0&&te.assertOptions(r,{silentJSONParsing:N.transitional(N.boolean),forcedJSONParsing:N.transitional(N.boolean),clarifyTimeoutError:N.transitional(N.boolean),legacyInterceptorReqResOrdering:N.transitional(N.boolean)},!1),s!=null&&(a.isFunction(s)?n.paramsSerializer={serialize:s}:te.assertOptions(s,{encode:N.function,serialize:N.function},!0)),n.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?n.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:n.allowAbsoluteUrls=!0),te.assertOptions(n,{baseUrl:N.spelling("baseURL"),withXsrfToken:N.spelling("withXSRFToken")},!0),n.method=(n.method||this.defaults.method||"get").toLowerCase();let i=o&&a.merge(o.common,o[n.method]);o&&a.forEach(["delete","get","head","post","put","patch","common"],u=>{delete o[u]}),n.headers=C.concat(i,o);const c=[];let p=!0;this.interceptors.request.forEach(function(m){if(typeof m.runWhen=="function"&&m.runWhen(n)===!1)return;p=p&&m.synchronous;const d=n.transitional||Ee;d&&d.legacyInterceptorReqResOrdering?c.unshift(m.fulfilled,m.rejected):c.push(m.fulfilled,m.rejected)});const f=[];this.interceptors.response.forEach(function(m){f.push(m.fulfilled,m.rejected)});let l,h=0,b;if(!p){const u=[Je.bind(this),void 0];for(u.unshift(...c),u.push(...f),b=u.length,l=Promise.resolve(n);h{if(!r._listeners)return;let o=r._listeners.length;for(;o-- >0;)r._listeners[o](s);r._listeners=null}),this.promise.then=s=>{let o;const i=new Promise(c=>{r.subscribe(c),o=c}).then(s);return i.cancel=function(){r.unsubscribe(o)},i},t(function(o,i,c){r.reason||(r.reason=new v(o,i,c),n(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}toAbortSignal(){const t=new AbortController,n=r=>{t.abort(r)};return this.subscribe(n),t.signal.unsubscribe=()=>this.unsubscribe(n),t.signal}static source(){let t;return{token:new dt(function(s){t=s}),cancel:t}}};function Wn(e){return function(n){return e.apply(null,n)}}function Kn(e){return a.isObject(e)&&e.isAxiosError===!0}const be={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(be).forEach(([e,t])=>{be[t]=e});function pt(e){const t=new j(e),n=We(j.prototype.request,t);return a.extend(n,j.prototype,t,{allOwnKeys:!0}),a.extend(n,t,null,{allOwnKeys:!0}),n.create=function(s){return pt(q(e,s))},n}const R=pt(K);R.Axios=j;R.CanceledError=v;R.CancelToken=Vn;R.isCancel=ot;R.VERSION=ft;R.toFormData=ie;R.AxiosError=y;R.Cancel=R.CanceledError;R.all=function(t){return Promise.all(t)};R.spread=Wn;R.isAxiosError=Kn;R.mergeConfig=q;R.AxiosHeaders=C;R.formToJSON=e=>st(a.isHTMLForm(e)?new FormData(e):e);R.getAdapter=ut.getAdapter;R.HttpStatusCode=be;R.default=R;const{Axios:Qn,AxiosError:Zn,CanceledError:Yn,isCancel:er,CancelToken:tr,VERSION:nr,all:rr,Cancel:sr,isAxiosError:or,spread:ir,toFormData:ar,AxiosHeaders:cr,HttpStatusCode:lr,formToJSON:ur,getAdapter:fr,mergeConfig:dr}=R;export{R as a}; diff --git a/apps/admin/assets/vendor-B6xRL-fs.js b/apps/admin/assets/vendor-B6xRL-fs.js new file mode 100644 index 00000000..4195d241 --- /dev/null +++ b/apps/admin/assets/vendor-B6xRL-fs.js @@ -0,0 +1,29 @@ +/** +* @vue/shared v3.5.30 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Fs(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const oe={},jt=[],Xe=()=>{},ai=()=>!1,Bn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Vs=e=>e.startsWith("onUpdate:"),pe=Object.assign,Hs=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Yo=Object.prototype.hasOwnProperty,te=(e,t)=>Yo.call(e,t),H=Array.isArray,Bt=e=>_n(e)==="[object Map]",Un=e=>_n(e)==="[object Set]",lr=e=>_n(e)==="[object Date]",G=e=>typeof e=="function",ae=e=>typeof e=="string",Ze=e=>typeof e=="symbol",ne=e=>e!==null&&typeof e=="object",di=e=>(ne(e)||G(e))&&G(e.then)&&G(e.catch),hi=Object.prototype.toString,_n=e=>hi.call(e),Xo=e=>_n(e).slice(8,-1),pi=e=>_n(e)==="[object Object]",kn=e=>ae(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Xt=Fs(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Kn=e=>{const t=Object.create(null);return(n=>t[n]||(t[n]=e(n)))},Zo=/-\w/g,Ce=Kn(e=>e.replace(Zo,t=>t.slice(1).toUpperCase())),el=/\B([A-Z])/g,bt=Kn(e=>e.replace(el,"-$1").toLowerCase()),Gn=Kn(e=>e.charAt(0).toUpperCase()+e.slice(1)),ss=Kn(e=>e?`on${Gn(e)}`:""),Ye=(e,t)=>!Object.is(e,t),xn=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},js=e=>{const t=parseFloat(e);return isNaN(t)?e:t},tl=e=>{const t=ae(e)?Number(e):NaN;return isNaN(t)?e:t};let cr;const Wn=()=>cr||(cr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Bs(e){if(H(e)){const t={};for(let n=0;n{if(n){const s=n.split(sl);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function Us(e){let t="";if(ae(e))t=e;else if(H(e))for(let n=0;nvn(n,t))}const vi=e=>!!(e&&e.__v_isRef===!0),ul=e=>ae(e)?e:e==null?"":H(e)||ne(e)&&(e.toString===hi||!G(e.toString))?vi(e)?ul(e.value):JSON.stringify(e,yi,2):String(e),yi=(e,t)=>vi(t)?yi(e,t.value):Bt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r],i)=>(n[rs(s,i)+" =>"]=r,n),{})}:Un(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>rs(n))}:Ze(t)?rs(t):ne(t)&&!H(t)&&!pi(t)?String(t):t,rs=(e,t="")=>{var n;return Ze(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.5.30 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ge;class bi{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.__v_skip=!0,this.parent=ge,!t&&ge&&(this.index=(ge.scopes||(ge.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes)for(t=0,n=this.scopes.length;t0&&--this._on===0&&(ge=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(en){let t=en;for(en=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Zt;){let t=Zt;for(Zt=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function Ri(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function wi(e){let t,n=e.depsTail,s=n;for(;s;){const r=s.prevDep;s.version===-1?(s===n&&(n=r),Gs(s),al(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=r}e.deps=t,e.depsTail=n}function ys(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(Ti(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function Ti(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===un)||(e.globalVersion=un,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!ys(e))))return;e.flags|=2;const t=e.dep,n=ce,s=Ve;ce=e,Ve=!0;try{Ri(e);const r=e.fn(e._value);(t.version===0||Ye(r,e._value))&&(e.flags|=128,e._value=r,t.version++)}catch(r){throw t.version++,r}finally{ce=n,Ve=s,wi(e),e.flags&=-3}}function Gs(e,t=!1){const{dep:n,prevSub:s,nextSub:r}=e;if(s&&(s.nextSub=r,e.prevSub=void 0),r&&(r.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)Gs(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function al(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let Ve=!0;const Oi=[];function ut(){Oi.push(Ve),Ve=!1}function ft(){const e=Oi.pop();Ve=e===void 0?!0:e}function ur(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=ce;ce=void 0;try{t()}finally{ce=n}}}let un=0;class dl{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Ws{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!ce||!Ve||ce===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==ce)n=this.activeLink=new dl(ce,this),ce.deps?(n.prevDep=ce.depsTail,ce.depsTail.nextDep=n,ce.depsTail=n):ce.deps=ce.depsTail=n,Pi(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=ce.depsTail,n.nextDep=void 0,ce.depsTail.nextDep=n,ce.depsTail=n,ce.deps===n&&(ce.deps=s)}return n}trigger(t){this.version++,un++,this.notify(t)}notify(t){ks();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Ks()}}}function Pi(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)Pi(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const Pn=new WeakMap,Pt=Symbol(""),bs=Symbol(""),fn=Symbol("");function me(e,t,n){if(Ve&&ce){let s=Pn.get(e);s||Pn.set(e,s=new Map);let r=s.get(n);r||(s.set(n,r=new Ws),r.map=s,r.key=n),r.track()}}function ot(e,t,n,s,r,i){const o=Pn.get(e);if(!o){un++;return}const l=c=>{c&&c.trigger()};if(ks(),t==="clear")o.forEach(l);else{const c=H(e),a=c&&kn(n);if(c&&n==="length"){const u=Number(s);o.forEach((d,p)=>{(p==="length"||p===fn||!Ze(p)&&p>=u)&&l(d)})}else switch((n!==void 0||o.has(void 0))&&l(o.get(n)),a&&l(o.get(fn)),t){case"add":c?a&&l(o.get("length")):(l(o.get(Pt)),Bt(e)&&l(o.get(bs)));break;case"delete":c||(l(o.get(Pt)),Bt(e)&&l(o.get(bs)));break;case"set":Bt(e)&&l(o.get(Pt));break}}Ks()}function hl(e,t){const n=Pn.get(e);return n&&n.get(t)}function Lt(e){const t=X(e);return t===e?t:(me(t,"iterate",fn),Ne(e)?t:t.map(He))}function $n(e){return me(e=X(e),"iterate",fn),e}function ze(e,t){return at(e)?Kt(ct(e)?He(t):t):He(t)}const pl={__proto__:null,[Symbol.iterator](){return os(this,Symbol.iterator,e=>ze(this,e))},concat(...e){return Lt(this).concat(...e.map(t=>H(t)?Lt(t):t))},entries(){return os(this,"entries",e=>(e[1]=ze(this,e[1]),e))},every(e,t){return tt(this,"every",e,t,void 0,arguments)},filter(e,t){return tt(this,"filter",e,t,n=>n.map(s=>ze(this,s)),arguments)},find(e,t){return tt(this,"find",e,t,n=>ze(this,n),arguments)},findIndex(e,t){return tt(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return tt(this,"findLast",e,t,n=>ze(this,n),arguments)},findLastIndex(e,t){return tt(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return tt(this,"forEach",e,t,void 0,arguments)},includes(...e){return ls(this,"includes",e)},indexOf(...e){return ls(this,"indexOf",e)},join(e){return Lt(this).join(e)},lastIndexOf(...e){return ls(this,"lastIndexOf",e)},map(e,t){return tt(this,"map",e,t,void 0,arguments)},pop(){return qt(this,"pop")},push(...e){return qt(this,"push",e)},reduce(e,...t){return fr(this,"reduce",e,t)},reduceRight(e,...t){return fr(this,"reduceRight",e,t)},shift(){return qt(this,"shift")},some(e,t){return tt(this,"some",e,t,void 0,arguments)},splice(...e){return qt(this,"splice",e)},toReversed(){return Lt(this).toReversed()},toSorted(e){return Lt(this).toSorted(e)},toSpliced(...e){return Lt(this).toSpliced(...e)},unshift(...e){return qt(this,"unshift",e)},values(){return os(this,"values",e=>ze(this,e))}};function os(e,t,n){const s=$n(e),r=s[t]();return s!==e&&!Ne(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.done||(i.value=n(i.value)),i}),r}const gl=Array.prototype;function tt(e,t,n,s,r,i){const o=$n(e),l=o!==e&&!Ne(e),c=o[t];if(c!==gl[t]){const d=c.apply(e,i);return l?He(d):d}let a=n;o!==e&&(l?a=function(d,p){return n.call(this,ze(e,d),p,e)}:n.length>2&&(a=function(d,p){return n.call(this,d,p,e)}));const u=c.call(o,a,s);return l&&r?r(u):u}function fr(e,t,n,s){const r=$n(e),i=r!==e&&!Ne(e);let o=n,l=!1;r!==e&&(i?(l=s.length===0,o=function(a,u,d){return l&&(l=!1,a=ze(e,a)),n.call(this,a,ze(e,u),d,e)}):n.length>3&&(o=function(a,u,d){return n.call(this,a,u,d,e)}));const c=r[t](o,...s);return l?ze(e,c):c}function ls(e,t,n){const s=X(e);me(s,"iterate",fn);const r=s[t](...n);return(r===-1||r===!1)&&qn(n[0])?(n[0]=X(n[0]),s[t](...n)):r}function qt(e,t,n=[]){ut(),ks();const s=X(e)[t].apply(e,n);return Ks(),ft(),s}const ml=Fs("__proto__,__v_isRef,__isVue"),Ii=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Ze));function _l(e){Ze(e)||(e=String(e));const t=X(this);return me(t,"has",e),t.hasOwnProperty(e)}class Ni{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(r?i?wl:Fi:i?Li:Di).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const o=H(t);if(!r){let c;if(o&&(c=pl[n]))return c;if(n==="hasOwnProperty")return _l}const l=Reflect.get(t,n,fe(t)?t:s);if((Ze(n)?Ii.has(n):ml(n))||(r||me(t,"get",n),i))return l;if(fe(l)){const c=o&&kn(n)?l:l.value;return r&&ne(c)?Ss(c):c}return ne(l)?r?Ss(l):yn(l):l}}class Mi extends Ni{constructor(t=!1){super(!1,t)}set(t,n,s,r){let i=t[n];const o=H(t)&&kn(n);if(!this._isShallow){const a=at(i);if(!Ne(s)&&!at(s)&&(i=X(i),s=X(s)),!o&&fe(i)&&!fe(s))return a||(i.value=s),!0}const l=o?Number(n)e,Sn=e=>Reflect.getPrototypeOf(e);function Sl(e,t,n){return function(...s){const r=this.__v_raw,i=X(r),o=Bt(i),l=e==="entries"||e===Symbol.iterator&&o,c=e==="keys"&&o,a=r[e](...s),u=n?Es:t?Kt:He;return!t&&me(i,"iterate",c?bs:Pt),pe(Object.create(a),{next(){const{value:d,done:p}=a.next();return p?{value:d,done:p}:{value:l?[u(d[0]),u(d[1])]:u(d),done:p}}})}}function Cn(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Cl(e,t){const n={get(r){const i=this.__v_raw,o=X(i),l=X(r);e||(Ye(r,l)&&me(o,"get",r),me(o,"get",l));const{has:c}=Sn(o),a=t?Es:e?Kt:He;if(c.call(o,r))return a(i.get(r));if(c.call(o,l))return a(i.get(l));i!==o&&i.get(r)},get size(){const r=this.__v_raw;return!e&&me(X(r),"iterate",Pt),r.size},has(r){const i=this.__v_raw,o=X(i),l=X(r);return e||(Ye(r,l)&&me(o,"has",r),me(o,"has",l)),r===l?i.has(r):i.has(r)||i.has(l)},forEach(r,i){const o=this,l=o.__v_raw,c=X(l),a=t?Es:e?Kt:He;return!e&&me(c,"iterate",Pt),l.forEach((u,d)=>r.call(i,a(u),a(d),o))}};return pe(n,e?{add:Cn("add"),set:Cn("set"),delete:Cn("delete"),clear:Cn("clear")}:{add(r){const i=X(this),o=Sn(i),l=X(r),c=!t&&!Ne(r)&&!at(r)?l:r;return o.has.call(i,c)||Ye(r,c)&&o.has.call(i,r)||Ye(l,c)&&o.has.call(i,l)||(i.add(c),ot(i,"add",c,c)),this},set(r,i){!t&&!Ne(i)&&!at(i)&&(i=X(i));const o=X(this),{has:l,get:c}=Sn(o);let a=l.call(o,r);a||(r=X(r),a=l.call(o,r));const u=c.call(o,r);return o.set(r,i),a?Ye(i,u)&&ot(o,"set",r,i):ot(o,"add",r,i),this},delete(r){const i=X(this),{has:o,get:l}=Sn(i);let c=o.call(i,r);c||(r=X(r),c=o.call(i,r)),l&&l.call(i,r);const a=i.delete(r);return c&&ot(i,"delete",r,void 0),a},clear(){const r=X(this),i=r.size!==0,o=r.clear();return i&&ot(r,"clear",void 0,void 0),o}}),["keys","values","entries",Symbol.iterator].forEach(r=>{n[r]=Sl(r,e,t)}),n}function $s(e,t){const n=Cl(e,t);return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(te(n,r)&&r in s?n:s,r,i)}const Al={get:$s(!1,!1)},xl={get:$s(!1,!0)},Rl={get:$s(!0,!1)};const Di=new WeakMap,Li=new WeakMap,Fi=new WeakMap,wl=new WeakMap;function Tl(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Ol(e){return e.__v_skip||!Object.isExtensible(e)?0:Tl(Xo(e))}function yn(e){return at(e)?e:qs(e,!1,yl,Al,Di)}function Vi(e){return qs(e,!1,El,xl,Li)}function Ss(e){return qs(e,!0,bl,Rl,Fi)}function qs(e,t,n,s,r){if(!ne(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=Ol(e);if(i===0)return e;const o=r.get(e);if(o)return o;const l=new Proxy(e,i===2?s:n);return r.set(e,l),l}function ct(e){return at(e)?ct(e.__v_raw):!!(e&&e.__v_isReactive)}function at(e){return!!(e&&e.__v_isReadonly)}function Ne(e){return!!(e&&e.__v_isShallow)}function qn(e){return e?!!e.__v_raw:!1}function X(e){const t=e&&e.__v_raw;return t?X(t):e}function zs(e){return!te(e,"__v_skip")&&Object.isExtensible(e)&&gi(e,"__v_skip",!0),e}const He=e=>ne(e)?yn(e):e,Kt=e=>ne(e)?Ss(e):e;function fe(e){return e?e.__v_isRef===!0:!1}function Hi(e){return ji(e,!1)}function Pl(e){return ji(e,!0)}function ji(e,t){return fe(e)?e:new Il(e,t)}class Il{constructor(t,n){this.dep=new Ws,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:X(t),this._value=n?t:He(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||Ne(t)||at(t);t=s?t:X(t),Ye(t,n)&&(this._rawValue=t,this._value=s?t:He(t),this.dep.trigger())}}function It(e){return fe(e)?e.value:e}const Nl={get:(e,t,n)=>t==="__v_raw"?e:It(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return fe(r)&&!fe(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function Bi(e){return ct(e)?e:new Proxy(e,Nl)}function Ml(e){const t=H(e)?new Array(e.length):{};for(const n in e)t[n]=Ll(e,n);return t}class Dl{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0,this._value=void 0,this._raw=X(t);let r=!0,i=t;if(!H(t)||!kn(String(n)))do r=!qn(i)||Ne(i);while(r&&(i=i.__v_raw));this._shallow=r}get value(){let t=this._object[this._key];return this._shallow&&(t=It(t)),this._value=t===void 0?this._defaultValue:t}set value(t){if(this._shallow&&fe(this._raw[this._key])){const n=this._object[this._key];if(fe(n)){n.value=t;return}}this._object[this._key]=t}get dep(){return hl(this._raw,this._key)}}function Ll(e,t,n){return new Dl(e,t,n)}class Fl{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new Ws(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=un-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&ce!==this)return xi(this,!0),!0}get value(){const t=this.dep.track();return Ti(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function Vl(e,t,n=!1){let s,r;return G(e)?s=e:(s=e.get,r=e.set),new Fl(s,r,n)}const An={},In=new WeakMap;let Rt;function Hl(e,t=!1,n=Rt){if(n){let s=In.get(n);s||In.set(n,s=[]),s.push(e)}}function jl(e,t,n=oe){const{immediate:s,deep:r,once:i,scheduler:o,augmentJob:l,call:c}=n,a=N=>r?N:Ne(N)||r===!1||r===0?lt(N,1):lt(N);let u,d,p,m,A=!1,S=!1;if(fe(e)?(d=()=>e.value,A=Ne(e)):ct(e)?(d=()=>a(e),A=!0):H(e)?(S=!0,A=e.some(N=>ct(N)||Ne(N)),d=()=>e.map(N=>{if(fe(N))return N.value;if(ct(N))return a(N);if(G(N))return c?c(N,2):N()})):G(e)?t?d=c?()=>c(e,2):e:d=()=>{if(p){ut();try{p()}finally{ft()}}const N=Rt;Rt=u;try{return c?c(e,3,[m]):e(m)}finally{Rt=N}}:d=Xe,t&&r){const N=d,U=r===!0?1/0:r;d=()=>lt(N(),U)}const j=Si(),L=()=>{u.stop(),j&&j.active&&Hs(j.effects,u)};if(i&&t){const N=t;t=(...U)=>{N(...U),L()}}let w=S?new Array(e.length).fill(An):An;const D=N=>{if(!(!(u.flags&1)||!u.dirty&&!N))if(t){const U=u.run();if(r||A||(S?U.some((re,q)=>Ye(re,w[q])):Ye(U,w))){p&&p();const re=Rt;Rt=u;try{const q=[U,w===An?void 0:S&&w[0]===An?[]:w,m];w=U,c?c(t,3,q):t(...q)}finally{Rt=re}}}else u.run()};return l&&l(D),u=new Ci(d),u.scheduler=o?()=>o(D,!1):D,m=N=>Hl(N,!1,u),p=u.onStop=()=>{const N=In.get(u);if(N){if(c)c(N,4);else for(const U of N)U();In.delete(u)}},t?s?D(!0):w=u.run():o?o(D.bind(null,!0),!0):u.run(),L.pause=u.pause.bind(u),L.resume=u.resume.bind(u),L.stop=L,L}function lt(e,t=1/0,n){if(t<=0||!ne(e)||e.__v_skip||(n=n||new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,fe(e))lt(e.value,t,n);else if(H(e))for(let s=0;s{lt(s,t,n)});else if(pi(e)){for(const s in e)lt(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&<(e[s],t,n)}return e}/** +* @vue/runtime-core v3.5.30 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function bn(e,t,n,s){try{return s?e(...s):e()}catch(r){zn(r,t,n)}}function je(e,t,n,s){if(G(e)){const r=bn(e,t,n,s);return r&&di(r)&&r.catch(i=>{zn(i,t,n)}),r}if(H(e)){const r=[];for(let i=0;i>>1,r=Ee[s],i=an(r);i=an(n)?Ee.push(e):Ee.splice(Ul(t),0,e),e.flags|=1,ki()}}function ki(){Nn||(Nn=Ui.then(Gi))}function kl(e){H(e)?Ut.push(...e):_t&&e.id===-1?_t.splice(Vt+1,0,e):e.flags&1||(Ut.push(e),e.flags|=1),ki()}function ar(e,t,n=$e+1){for(;nan(n)-an(s));if(Ut.length=0,_t){_t.push(...t);return}for(_t=t,Vt=0;Vt<_t.length;Vt++){const n=_t[Vt];n.flags&4&&(n.flags&=-2),n.flags&8||n(),n.flags&=-2}_t=null,Vt=0}}const an=e=>e.id==null?e.flags&2?-1:1/0:e.id;function Gi(e){try{for($e=0;$e{s._d&&Fn(-1);const i=Mn(t);let o;try{o=e(...r)}finally{Mn(i),s._d&&Fn(1)}return o};return s._n=!0,s._c=!0,s._d=!0,s}function Uf(e,t){if(Pe===null)return e;const n=Zn(Pe),s=e.dirs||(e.dirs=[]);for(let r=0;r1)return n&&G(t)?t.call(s&&s.proxy):t}}function Gl(){return!!(er()||Nt)}const Wl=Symbol.for("v-scx"),$l=()=>Fe(Wl);function tn(e,t,n){return $i(e,t,n)}function $i(e,t,n=oe){const{immediate:s,deep:r,flush:i,once:o}=n,l=pe({},n),c=t&&s||!t&&i!=="post";let a;if(pn){if(i==="sync"){const m=$l();a=m.__watcherHandles||(m.__watcherHandles=[])}else if(!c){const m=()=>{};return m.stop=Xe,m.resume=Xe,m.pause=Xe,m}}const u=_e;l.call=(m,A,S)=>je(m,u,A,S);let d=!1;i==="post"?l.scheduler=m=>{we(m,u&&u.suspense)}:i!=="sync"&&(d=!0,l.scheduler=(m,A)=>{A?m():Qs(m)}),l.augmentJob=m=>{t&&(m.flags|=4),d&&(m.flags|=2,u&&(m.id=u.uid,m.i=u))};const p=jl(e,t,l);return pn&&(a?a.push(p):c&&p()),p}function ql(e,t,n){const s=this.proxy,r=ae(e)?e.includes(".")?qi(s,e):()=>s[e]:e.bind(s,s);let i;G(t)?i=t:(i=t.handler,n=t);const o=En(this),l=$i(r,i.bind(s),n);return o(),l}function qi(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;re.__isTeleport,qe=Symbol("_leaveCb"),zt=Symbol("_enterCb");function Jl(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return so(()=>{e.isMounted=!0}),ro(()=>{e.isUnmounting=!0}),e}const De=[Function,Array],Ji={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:De,onEnter:De,onAfterEnter:De,onEnterCancelled:De,onBeforeLeave:De,onLeave:De,onAfterLeave:De,onLeaveCancelled:De,onBeforeAppear:De,onAppear:De,onAfterAppear:De,onAppearCancelled:De},Qi=e=>{const t=e.subTree;return t.component?Qi(t.component):t},Ql={name:"BaseTransition",props:Ji,setup(e,{slots:t}){const n=er(),s=Jl();return()=>{const r=t.default&&Zi(t.default(),!0);if(!r||!r.length)return;const i=Yi(r),o=X(e),{mode:l}=o;if(s.isLeaving)return cs(i);const c=dr(i);if(!c)return cs(i);let a=Cs(c,o,s,n,d=>a=d);c.type!==Se&&dn(c,a);let u=n.subTree&&dr(n.subTree);if(u&&u.type!==Se&&!wt(u,c)&&Qi(n).type!==Se){let d=Cs(u,o,s,n);if(dn(u,d),l==="out-in"&&c.type!==Se)return s.isLeaving=!0,d.afterLeave=()=>{s.isLeaving=!1,n.job.flags&8||n.update(),delete d.afterLeave,u=void 0},cs(i);l==="in-out"&&c.type!==Se?d.delayLeave=(p,m,A)=>{const S=Xi(s,u);S[String(u.key)]=u,p[qe]=()=>{m(),p[qe]=void 0,delete a.delayedLeave,u=void 0},a.delayedLeave=()=>{A(),delete a.delayedLeave,u=void 0}}:u=void 0}else u&&(u=void 0);return i}}};function Yi(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==Se){t=n;break}}return t}const Yl=Ql;function Xi(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function Cs(e,t,n,s,r){const{appear:i,mode:o,persisted:l=!1,onBeforeEnter:c,onEnter:a,onAfterEnter:u,onEnterCancelled:d,onBeforeLeave:p,onLeave:m,onAfterLeave:A,onLeaveCancelled:S,onBeforeAppear:j,onAppear:L,onAfterAppear:w,onAppearCancelled:D}=t,N=String(e.key),U=Xi(n,e),re=(T,K)=>{T&&je(T,s,9,K)},q=(T,K)=>{const Y=K[1];re(T,K),H(T)?T.every(P=>P.length<=1)&&Y():T.length<=1&&Y()},W={mode:o,persisted:l,beforeEnter(T){let K=c;if(!n.isMounted)if(i)K=j||c;else return;T[qe]&&T[qe](!0);const Y=U[N];Y&&wt(e,Y)&&Y.el[qe]&&Y.el[qe](),re(K,[T])},enter(T){if(U[N]===e)return;let K=a,Y=u,P=d;if(!n.isMounted)if(i)K=L||a,Y=w||u,P=D||d;else return;let z=!1;T[zt]=ve=>{z||(z=!0,ve?re(P,[T]):re(Y,[T]),W.delayedLeave&&W.delayedLeave(),T[zt]=void 0)};const de=T[zt].bind(null,!1);K?q(K,[T,de]):de()},leave(T,K){const Y=String(e.key);if(T[zt]&&T[zt](!0),n.isUnmounting)return K();re(p,[T]);let P=!1;T[qe]=de=>{P||(P=!0,K(),de?re(S,[T]):re(A,[T]),T[qe]=void 0,U[Y]===e&&delete U[Y])};const z=T[qe].bind(null,!1);U[Y]=e,m?q(m,[T,z]):z()},clone(T){const K=Cs(T,t,n,s,r);return r&&r(K),K}};return W}function cs(e){if(Jn(e))return e=yt(e),e.children=null,e}function dr(e){if(!Jn(e))return zi(e.type)&&e.children?Yi(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&G(n.default))return n.default()}}function dn(e,t){e.shapeFlag&6&&e.component?(e.transition=t,dn(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Zi(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;inn(S,t&&(H(t)?t[j]:t),n,s,r));return}if(sn(s)&&!r){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&nn(e,t,n,s.component.subTree);return}const i=s.shapeFlag&4?Zn(s.component):s.el,o=r?null:i,{i:l,r:c}=e,a=t&&t.r,u=l.refs===oe?l.refs={}:l.refs,d=l.setupState,p=X(d),m=d===oe?ai:S=>hr(u,S)?!1:te(p,S),A=(S,j)=>!(j&&hr(u,j));if(a!=null&&a!==c){if(pr(t),ae(a))u[a]=null,m(a)&&(d[a]=null);else if(fe(a)){const S=t;A(a,S.k)&&(a.value=null),S.k&&(u[S.k]=null)}}if(G(c))bn(c,l,12,[o,u]);else{const S=ae(c),j=fe(c);if(S||j){const L=()=>{if(e.f){const w=S?m(c)?d[c]:u[c]:A()||!e.k?c.value:u[e.k];if(r)H(w)&&Hs(w,i);else if(H(w))w.includes(i)||w.push(i);else if(S)u[c]=[i],m(c)&&(d[c]=u[c]);else{const D=[i];A(c,e.k)&&(c.value=D),e.k&&(u[e.k]=D)}}else S?(u[c]=o,m(c)&&(d[c]=o)):j&&(A(c,e.k)&&(c.value=o),e.k&&(u[e.k]=o))};if(o){const w=()=>{L(),Dn.delete(e)};w.id=-1,Dn.set(e,w),we(w,n)}else pr(e),L()}}}function pr(e){const t=Dn.get(e);t&&(t.flags|=8,Dn.delete(e))}Wn().requestIdleCallback;Wn().cancelIdleCallback;const sn=e=>!!e.type.__asyncLoader,Jn=e=>e.type.__isKeepAlive;function Xl(e,t){no(e,"a",t)}function Zl(e,t){no(e,"da",t)}function no(e,t,n=_e){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(Qn(t,s,n),n){let r=n.parent;for(;r&&r.parent;)Jn(r.parent.vnode)&&ec(s,t,n,r),r=r.parent}}function ec(e,t,n,s){const r=Qn(t,e,s,!0);io(()=>{Hs(s[t],r)},n)}function Qn(e,t,n=_e,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...o)=>{ut();const l=En(n),c=je(t,n,e,o);return l(),ft(),c});return s?r.unshift(i):r.push(i),i}}const dt=e=>(t,n=_e)=>{(!pn||e==="sp")&&Qn(e,(...s)=>t(...s),n)},tc=dt("bm"),so=dt("m"),nc=dt("bu"),sc=dt("u"),ro=dt("bum"),io=dt("um"),rc=dt("sp"),ic=dt("rtg"),oc=dt("rtc");function lc(e,t=_e){Qn("ec",e,t)}const oo="components";function kf(e,t){return co(oo,e,!0,t)||e}const lo=Symbol.for("v-ndc");function Kf(e){return ae(e)?co(oo,e,!1)||e:e||lo}function co(e,t,n=!0,s=!1){const r=Pe||_e;if(r){const i=r.type;{const l=zc(i,!1);if(l&&(l===t||l===Ce(t)||l===Gn(Ce(t))))return i}const o=gr(r[e]||i[e],t)||gr(r.appContext[e],t);return!o&&s?i:o}}function gr(e,t){return e&&(e[t]||e[Ce(t)]||e[Gn(Ce(t))])}function Gf(e,t,n,s){let r;const i=n,o=H(e);if(o||ae(e)){const l=o&&ct(e);let c=!1,a=!1;l&&(c=!Ne(e),a=at(e),e=$n(e)),r=new Array(e.length);for(let u=0,d=e.length;ut(l,c,void 0,i));else{const l=Object.keys(e);r=new Array(l.length);for(let c=0,a=l.length;ce?Po(e)?Zn(e):As(e.parent):null,rn=pe(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>As(e.parent),$root:e=>As(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>fo(e),$forceUpdate:e=>e.f||(e.f=()=>{Qs(e.update)}),$nextTick:e=>e.n||(e.n=Js.bind(e.proxy)),$watch:e=>ql.bind(e)}),us=(e,t)=>e!==oe&&!e.__isScriptSetup&&te(e,t),cc={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:r,props:i,accessCache:o,type:l,appContext:c}=e;if(t[0]!=="$"){const p=o[t];if(p!==void 0)switch(p){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(us(s,t))return o[t]=1,s[t];if(r!==oe&&te(r,t))return o[t]=2,r[t];if(te(i,t))return o[t]=3,i[t];if(n!==oe&&te(n,t))return o[t]=4,n[t];xs&&(o[t]=0)}}const a=rn[t];let u,d;if(a)return t==="$attrs"&&me(e.attrs,"get",""),a(e);if((u=l.__cssModules)&&(u=u[t]))return u;if(n!==oe&&te(n,t))return o[t]=4,n[t];if(d=c.config.globalProperties,te(d,t))return d[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return us(r,t)?(r[t]=n,!0):s!==oe&&te(s,t)?(s[t]=n,!0):te(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,props:i,type:o}},l){let c;return!!(n[l]||e!==oe&&l[0]!=="$"&&te(e,l)||us(t,l)||te(i,l)||te(s,l)||te(rn,l)||te(r.config.globalProperties,l)||(c=o.__cssModules)&&c[l])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:te(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function mr(e){return H(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let xs=!0;function uc(e){const t=fo(e),n=e.proxy,s=e.ctx;xs=!1,t.beforeCreate&&_r(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:o,watch:l,provide:c,inject:a,created:u,beforeMount:d,mounted:p,beforeUpdate:m,updated:A,activated:S,deactivated:j,beforeDestroy:L,beforeUnmount:w,destroyed:D,unmounted:N,render:U,renderTracked:re,renderTriggered:q,errorCaptured:W,serverPrefetch:T,expose:K,inheritAttrs:Y,components:P,directives:z,filters:de}=t;if(a&&fc(a,s,null),o)for(const $ in o){const Z=o[$];G(Z)&&(s[$]=Z.bind(n))}if(r){const $=r.call(n,n);ne($)&&(e.data=yn($))}if(xs=!0,i)for(const $ in i){const Z=i[$],et=G(Z)?Z.bind(n,n):G(Z.get)?Z.get.bind(n,n):Xe,ht=!G(Z)&&G(Z.set)?Z.set.bind(n):Xe,Ue=Le({get:et,set:ht});Object.defineProperty(s,$,{enumerable:!0,configurable:!0,get:()=>Ue.value,set:Ae=>Ue.value=Ae})}if(l)for(const $ in l)uo(l[$],s,n,$);if(c){const $=G(c)?c.call(n):c;Reflect.ownKeys($).forEach(Z=>{Rn(Z,$[Z])})}u&&_r(u,e,"c");function ie($,Z){H(Z)?Z.forEach(et=>$(et.bind(n))):Z&&$(Z.bind(n))}if(ie(tc,d),ie(so,p),ie(nc,m),ie(sc,A),ie(Xl,S),ie(Zl,j),ie(lc,W),ie(oc,re),ie(ic,q),ie(ro,w),ie(io,N),ie(rc,T),H(K))if(K.length){const $=e.exposed||(e.exposed={});K.forEach(Z=>{Object.defineProperty($,Z,{get:()=>n[Z],set:et=>n[Z]=et,enumerable:!0})})}else e.exposed||(e.exposed={});U&&e.render===Xe&&(e.render=U),Y!=null&&(e.inheritAttrs=Y),P&&(e.components=P),z&&(e.directives=z),T&&to(e)}function fc(e,t,n=Xe){H(e)&&(e=Rs(e));for(const s in e){const r=e[s];let i;ne(r)?"default"in r?i=Fe(r.from||s,r.default,!0):i=Fe(r.from||s):i=Fe(r),fe(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:o=>i.value=o}):t[s]=i}}function _r(e,t,n){je(H(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function uo(e,t,n,s){let r=s.includes(".")?qi(n,s):()=>n[s];if(ae(e)){const i=t[e];G(i)&&tn(r,i)}else if(G(e))tn(r,e.bind(n));else if(ne(e))if(H(e))e.forEach(i=>uo(i,t,n,s));else{const i=G(e.handler)?e.handler.bind(n):t[e.handler];G(i)&&tn(r,i,e)}}function fo(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:o}}=e.appContext,l=i.get(t);let c;return l?c=l:!r.length&&!n&&!s?c=t:(c={},r.length&&r.forEach(a=>Ln(c,a,o,!0)),Ln(c,t,o)),ne(t)&&i.set(t,c),c}function Ln(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&Ln(e,i,n,!0),r&&r.forEach(o=>Ln(e,o,n,!0));for(const o in t)if(!(s&&o==="expose")){const l=ac[o]||n&&n[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const ac={data:vr,props:yr,emits:yr,methods:Yt,computed:Yt,beforeCreate:ye,created:ye,beforeMount:ye,mounted:ye,beforeUpdate:ye,updated:ye,beforeDestroy:ye,beforeUnmount:ye,destroyed:ye,unmounted:ye,activated:ye,deactivated:ye,errorCaptured:ye,serverPrefetch:ye,components:Yt,directives:Yt,watch:hc,provide:vr,inject:dc};function vr(e,t){return t?e?function(){return pe(G(e)?e.call(this,this):e,G(t)?t.call(this,this):t)}:t:e}function dc(e,t){return Yt(Rs(e),Rs(t))}function Rs(e){if(H(e)){const t={};for(let n=0;nt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Ce(t)}Modifiers`]||e[`${bt(t)}Modifiers`];function _c(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||oe;let r=n;const i=t.startsWith("update:"),o=i&&mc(s,t.slice(7));o&&(o.trim&&(r=n.map(u=>ae(u)?u.trim():u)),o.number&&(r=n.map(js)));let l,c=s[l=ss(t)]||s[l=ss(Ce(t))];!c&&i&&(c=s[l=ss(bt(t))]),c&&je(c,e,6,r);const a=s[l+"Once"];if(a){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,je(a,e,6,r)}}const vc=new WeakMap;function ho(e,t,n=!1){const s=n?vc:t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let o={},l=!1;if(!G(e)){const c=a=>{const u=ho(a,t,!0);u&&(l=!0,pe(o,u))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!l?(ne(e)&&s.set(e,null),null):(H(i)?i.forEach(c=>o[c]=null):pe(o,i),ne(e)&&s.set(e,o),o)}function Yn(e,t){return!e||!Bn(t)?!1:(t=t.slice(2).replace(/Once$/,""),te(e,t[0].toLowerCase()+t.slice(1))||te(e,bt(t))||te(e,t))}function br(e){const{type:t,vnode:n,proxy:s,withProxy:r,propsOptions:[i],slots:o,attrs:l,emit:c,render:a,renderCache:u,props:d,data:p,setupState:m,ctx:A,inheritAttrs:S}=e,j=Mn(e);let L,w;try{if(n.shapeFlag&4){const N=r||s,U=N;L=Qe(a.call(U,N,u,d,m,p,A)),w=l}else{const N=t;L=Qe(N.length>1?N(d,{attrs:l,slots:o,emit:c}):N(d,null)),w=t.props?l:yc(l)}}catch(N){on.length=0,zn(N,e,1),L=Te(Se)}let D=L;if(w&&S!==!1){const N=Object.keys(w),{shapeFlag:U}=D;N.length&&U&7&&(i&&N.some(Vs)&&(w=bc(w,i)),D=yt(D,w,!1,!0))}return n.dirs&&(D=yt(D,null,!1,!0),D.dirs=D.dirs?D.dirs.concat(n.dirs):n.dirs),n.transition&&dn(D,n.transition),L=D,Mn(j),L}const yc=e=>{let t;for(const n in e)(n==="class"||n==="style"||Bn(n))&&((t||(t={}))[n]=e[n]);return t},bc=(e,t)=>{const n={};for(const s in e)(!Vs(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function Ec(e,t,n){const{props:s,children:r,component:i}=e,{props:o,children:l,patchFlag:c}=t,a=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?Er(s,o,a):!!o;if(c&8){const u=t.dynamicProps;for(let d=0;dObject.create(go),_o=e=>Object.getPrototypeOf(e)===go;function Cc(e,t,n,s=!1){const r={},i=mo();e.propsDefaults=Object.create(null),vo(e,t,r,i);for(const o in e.propsOptions[0])o in r||(r[o]=void 0);n?e.props=s?r:Vi(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function Ac(e,t,n,s){const{props:r,attrs:i,vnode:{patchFlag:o}}=e,l=X(r),[c]=e.propsOptions;let a=!1;if((s||o>0)&&!(o&16)){if(o&8){const u=e.vnode.dynamicProps;for(let d=0;d{c=!0;const[p,m]=yo(d,t,!0);pe(o,p),m&&l.push(...m)};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}if(!i&&!c)return ne(e)&&s.set(e,jt),jt;if(H(i))for(let u=0;ue==="_"||e==="_ctx"||e==="$stable",Xs=e=>H(e)?e.map(Qe):[Qe(e)],Rc=(e,t,n)=>{if(t._n)return t;const s=Kl((...r)=>Xs(t(...r)),n);return s._c=!1,s},bo=(e,t,n)=>{const s=e._ctx;for(const r in e){if(Ys(r))continue;const i=e[r];if(G(i))t[r]=Rc(r,i,s);else if(i!=null){const o=Xs(i);t[r]=()=>o}}},Eo=(e,t)=>{const n=Xs(t);e.slots.default=()=>n},So=(e,t,n)=>{for(const s in t)(n||!Ys(s))&&(e[s]=t[s])},wc=(e,t,n)=>{const s=e.slots=mo();if(e.vnode.shapeFlag&32){const r=t._;r?(So(s,t,n),n&&gi(s,"_",r,!0)):bo(t,s)}else t&&Eo(e,t)},Tc=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,o=oe;if(s.shapeFlag&32){const l=t._;l?n&&l===1?i=!1:So(r,t,n):(i=!t.$stable,bo(t,r)),o=t}else t&&(Eo(e,t),o={default:1});if(i)for(const l in r)!Ys(l)&&o[l]==null&&delete r[l]},we=Mc;function Oc(e){return Pc(e)}function Pc(e,t){const n=Wn();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:c,setText:a,setElementText:u,parentNode:d,nextSibling:p,setScopeId:m=Xe,insertStaticContent:A}=e,S=(f,h,g,_=null,b=null,v=null,R=void 0,x=null,C=!!h.dynamicChildren)=>{if(f===h)return;f&&!wt(f,h)&&(_=y(f),Ae(f,b,v,!0),f=null),h.patchFlag===-2&&(C=!1,h.dynamicChildren=null);const{type:E,ref:B,shapeFlag:I}=h;switch(E){case Xn:j(f,h,g,_);break;case Se:L(f,h,g,_);break;case wn:f==null&&w(h,g,_,R);break;case Je:P(f,h,g,_,b,v,R,x,C);break;default:I&1?U(f,h,g,_,b,v,R,x,C):I&6?z(f,h,g,_,b,v,R,x,C):(I&64||I&128)&&E.process(f,h,g,_,b,v,R,x,C,F)}B!=null&&b?nn(B,f&&f.ref,v,h||f,!h):B==null&&f&&f.ref!=null&&nn(f.ref,null,v,f,!0)},j=(f,h,g,_)=>{if(f==null)s(h.el=l(h.children),g,_);else{const b=h.el=f.el;h.children!==f.children&&a(b,h.children)}},L=(f,h,g,_)=>{f==null?s(h.el=c(h.children||""),g,_):h.el=f.el},w=(f,h,g,_)=>{[f.el,f.anchor]=A(f.children,h,g,_,f.el,f.anchor)},D=({el:f,anchor:h},g,_)=>{let b;for(;f&&f!==h;)b=p(f),s(f,g,_),f=b;s(h,g,_)},N=({el:f,anchor:h})=>{let g;for(;f&&f!==h;)g=p(f),r(f),f=g;r(h)},U=(f,h,g,_,b,v,R,x,C)=>{if(h.type==="svg"?R="svg":h.type==="math"&&(R="mathml"),f==null)re(h,g,_,b,v,R,x,C);else{const E=f.el&&f.el._isVueCE?f.el:null;try{E&&E._beginPatch(),T(f,h,b,v,R,x,C)}finally{E&&E._endPatch()}}},re=(f,h,g,_,b,v,R,x)=>{let C,E;const{props:B,shapeFlag:I,transition:V,dirs:k}=f;if(C=f.el=o(f.type,v,B&&B.is,B),I&8?u(C,f.children):I&16&&W(f.children,C,null,_,b,fs(f,v),R,x),k&&St(f,null,_,"created"),q(C,f,f.scopeId,R,_),B){for(const le in B)le!=="value"&&!Xt(le)&&i(C,le,null,B[le],v,_);"value"in B&&i(C,"value",null,B.value,v),(E=B.onVnodeBeforeMount)&&We(E,_,f)}k&&St(f,null,_,"beforeMount");const Q=Ic(b,V);Q&&V.beforeEnter(C),s(C,h,g),((E=B&&B.onVnodeMounted)||Q||k)&&we(()=>{E&&We(E,_,f),Q&&V.enter(C),k&&St(f,null,_,"mounted")},b)},q=(f,h,g,_,b)=>{if(g&&m(f,g),_)for(let v=0;v<_.length;v++)m(f,_[v]);if(b){let v=b.subTree;if(h===v||Ro(v.type)&&(v.ssContent===h||v.ssFallback===h)){const R=b.vnode;q(f,R,R.scopeId,R.slotScopeIds,b.parent)}}},W=(f,h,g,_,b,v,R,x,C=0)=>{for(let E=C;E{const x=h.el=f.el;let{patchFlag:C,dynamicChildren:E,dirs:B}=h;C|=f.patchFlag&16;const I=f.props||oe,V=h.props||oe;let k;if(g&&Ct(g,!1),(k=V.onVnodeBeforeUpdate)&&We(k,g,h,f),B&&St(h,f,g,"beforeUpdate"),g&&Ct(g,!0),(I.innerHTML&&V.innerHTML==null||I.textContent&&V.textContent==null)&&u(x,""),E?K(f.dynamicChildren,E,x,g,_,fs(h,b),v):R||Z(f,h,x,null,g,_,fs(h,b),v,!1),C>0){if(C&16)Y(x,I,V,g,b);else if(C&2&&I.class!==V.class&&i(x,"class",null,V.class,b),C&4&&i(x,"style",I.style,V.style,b),C&8){const Q=h.dynamicProps;for(let le=0;le{k&&We(k,g,h,f),B&&St(h,f,g,"updated")},_)},K=(f,h,g,_,b,v,R)=>{for(let x=0;x{if(h!==g){if(h!==oe)for(const v in h)!Xt(v)&&!(v in g)&&i(f,v,h[v],null,b,_);for(const v in g){if(Xt(v))continue;const R=g[v],x=h[v];R!==x&&v!=="value"&&i(f,v,x,R,b,_)}"value"in g&&i(f,"value",h.value,g.value,b)}},P=(f,h,g,_,b,v,R,x,C)=>{const E=h.el=f?f.el:l(""),B=h.anchor=f?f.anchor:l("");let{patchFlag:I,dynamicChildren:V,slotScopeIds:k}=h;k&&(x=x?x.concat(k):k),f==null?(s(E,g,_),s(B,g,_),W(h.children||[],g,B,b,v,R,x,C)):I>0&&I&64&&V&&f.dynamicChildren&&f.dynamicChildren.length===V.length?(K(f.dynamicChildren,V,g,b,v,R,x),(h.key!=null||b&&h===b.subTree)&&Co(f,h,!0)):Z(f,h,g,B,b,v,R,x,C)},z=(f,h,g,_,b,v,R,x,C)=>{h.slotScopeIds=x,f==null?h.shapeFlag&512?b.ctx.activate(h,g,_,R,C):de(h,g,_,b,v,R,C):ve(f,h,C)},de=(f,h,g,_,b,v,R)=>{const x=f.component=Kc(f,_,b);if(Jn(f)&&(x.ctx.renderer=F),Gc(x,!1,R),x.asyncDep){if(b&&b.registerDep(x,ie,R),!f.el){const C=x.subTree=Te(Se);L(null,C,h,g),f.placeholder=C.el}}else ie(x,f,h,g,b,v,R)},ve=(f,h,g)=>{const _=h.component=f.component;if(Ec(f,h,g))if(_.asyncDep&&!_.asyncResolved){$(_,h,g);return}else _.next=h,_.update();else h.el=f.el,_.vnode=h},ie=(f,h,g,_,b,v,R)=>{const x=()=>{if(f.isMounted){let{next:I,bu:V,u:k,parent:Q,vnode:le}=f;{const Ke=Ao(f);if(Ke){I&&(I.el=le.el,$(f,I,R)),Ke.asyncDep.then(()=>{we(()=>{f.isUnmounted||E()},b)});return}}let se=I,xe;Ct(f,!1),I?(I.el=le.el,$(f,I,R)):I=le,V&&xn(V),(xe=I.props&&I.props.onVnodeBeforeUpdate)&&We(xe,Q,I,le),Ct(f,!0);const Re=br(f),ke=f.subTree;f.subTree=Re,S(ke,Re,d(ke.el),y(ke),f,b,v),I.el=Re.el,se===null&&Sc(f,Re.el),k&&we(k,b),(xe=I.props&&I.props.onVnodeUpdated)&&we(()=>We(xe,Q,I,le),b)}else{let I;const{el:V,props:k}=h,{bm:Q,m:le,parent:se,root:xe,type:Re}=f,ke=sn(h);Ct(f,!1),Q&&xn(Q),!ke&&(I=k&&k.onVnodeBeforeMount)&&We(I,se,h),Ct(f,!0);{xe.ce&&xe.ce._hasShadowRoot()&&xe.ce._injectChildStyle(Re,f.parent?f.parent.type:void 0);const Ke=f.subTree=br(f);S(null,Ke,g,_,f,b,v),h.el=Ke.el}if(le&&we(le,b),!ke&&(I=k&&k.onVnodeMounted)){const Ke=h;we(()=>We(I,se,Ke),b)}(h.shapeFlag&256||se&&sn(se.vnode)&&se.vnode.shapeFlag&256)&&f.a&&we(f.a,b),f.isMounted=!0,h=g=_=null}};f.scope.on();const C=f.effect=new Ci(x);f.scope.off();const E=f.update=C.run.bind(C),B=f.job=C.runIfDirty.bind(C);B.i=f,B.id=f.uid,C.scheduler=()=>Qs(B),Ct(f,!0),E()},$=(f,h,g)=>{h.component=f;const _=f.vnode.props;f.vnode=h,f.next=null,Ac(f,h.props,_,g),Tc(f,h.children,g),ut(),ar(f),ft()},Z=(f,h,g,_,b,v,R,x,C=!1)=>{const E=f&&f.children,B=f?f.shapeFlag:0,I=h.children,{patchFlag:V,shapeFlag:k}=h;if(V>0){if(V&128){ht(E,I,g,_,b,v,R,x,C);return}else if(V&256){et(E,I,g,_,b,v,R,x,C);return}}k&8?(B&16&&Me(E,b,v),I!==E&&u(g,I)):B&16?k&16?ht(E,I,g,_,b,v,R,x,C):Me(E,b,v,!0):(B&8&&u(g,""),k&16&&W(I,g,_,b,v,R,x,C))},et=(f,h,g,_,b,v,R,x,C)=>{f=f||jt,h=h||jt;const E=f.length,B=h.length,I=Math.min(E,B);let V;for(V=0;VB?Me(f,b,v,!0,!1,I):W(h,g,_,b,v,R,x,C,I)},ht=(f,h,g,_,b,v,R,x,C)=>{let E=0;const B=h.length;let I=f.length-1,V=B-1;for(;E<=I&&E<=V;){const k=f[E],Q=h[E]=C?it(h[E]):Qe(h[E]);if(wt(k,Q))S(k,Q,g,null,b,v,R,x,C);else break;E++}for(;E<=I&&E<=V;){const k=f[I],Q=h[V]=C?it(h[V]):Qe(h[V]);if(wt(k,Q))S(k,Q,g,null,b,v,R,x,C);else break;I--,V--}if(E>I){if(E<=V){const k=V+1,Q=kV)for(;E<=I;)Ae(f[E],b,v,!0),E++;else{const k=E,Q=E,le=new Map;for(E=Q;E<=V;E++){const Oe=h[E]=C?it(h[E]):Qe(h[E]);Oe.key!=null&&le.set(Oe.key,E)}let se,xe=0;const Re=V-Q+1;let ke=!1,Ke=0;const $t=new Array(Re);for(E=0;E=Re){Ae(Oe,b,v,!0);continue}let Ge;if(Oe.key!=null)Ge=le.get(Oe.key);else for(se=Q;se<=V;se++)if($t[se-Q]===0&&wt(Oe,h[se])){Ge=se;break}Ge===void 0?Ae(Oe,b,v,!0):($t[Ge-Q]=E+1,Ge>=Ke?Ke=Ge:ke=!0,S(Oe,h[Ge],g,null,b,v,R,x,C),xe++)}const rr=ke?Nc($t):jt;for(se=rr.length-1,E=Re-1;E>=0;E--){const Oe=Q+E,Ge=h[Oe],ir=h[Oe+1],or=Oe+1{const{el:v,type:R,transition:x,children:C,shapeFlag:E}=f;if(E&6){Ue(f.component.subTree,h,g,_);return}if(E&128){f.suspense.move(h,g,_);return}if(E&64){R.move(f,h,g,F);return}if(R===Je){s(v,h,g);for(let I=0;Ix.enter(v),b);else{const{leave:I,delayLeave:V,afterLeave:k}=x,Q=()=>{f.ctx.isUnmounted?r(v):s(v,h,g)},le=()=>{v._isLeaving&&v[qe](!0),I(v,()=>{Q(),k&&k()})};V?V(v,Q,le):le()}else s(v,h,g)},Ae=(f,h,g,_=!1,b=!1)=>{const{type:v,props:R,ref:x,children:C,dynamicChildren:E,shapeFlag:B,patchFlag:I,dirs:V,cacheIndex:k}=f;if(I===-2&&(b=!1),x!=null&&(ut(),nn(x,null,g,f,!0),ft()),k!=null&&(h.renderCache[k]=void 0),B&256){h.ctx.deactivate(f);return}const Q=B&1&&V,le=!sn(f);let se;if(le&&(se=R&&R.onVnodeBeforeUnmount)&&We(se,h,f),B&6)Et(f.component,g,_);else{if(B&128){f.suspense.unmount(g,_);return}Q&&St(f,null,h,"beforeUnmount"),B&64?f.type.remove(f,h,g,F,_):E&&!E.hasOnce&&(v!==Je||I>0&&I&64)?Me(E,h,g,!1,!0):(v===Je&&I&384||!b&&B&16)&&Me(C,h,g),_&&Mt(f)}(le&&(se=R&&R.onVnodeUnmounted)||Q)&&we(()=>{se&&We(se,h,f),Q&&St(f,null,h,"unmounted")},g)},Mt=f=>{const{type:h,el:g,anchor:_,transition:b}=f;if(h===Je){Dt(g,_);return}if(h===wn){N(f);return}const v=()=>{r(g),b&&!b.persisted&&b.afterLeave&&b.afterLeave()};if(f.shapeFlag&1&&b&&!b.persisted){const{leave:R,delayLeave:x}=b,C=()=>R(g,v);x?x(f.el,v,C):C()}else v()},Dt=(f,h)=>{let g;for(;f!==h;)g=p(f),r(f),f=g;r(h)},Et=(f,h,g)=>{const{bum:_,scope:b,job:v,subTree:R,um:x,m:C,a:E}=f;Cr(C),Cr(E),_&&xn(_),b.stop(),v&&(v.flags|=8,Ae(R,f,h,g)),x&&we(x,h),we(()=>{f.isUnmounted=!0},h)},Me=(f,h,g,_=!1,b=!1,v=0)=>{for(let R=v;R{if(f.shapeFlag&6)return y(f.component.subTree);if(f.shapeFlag&128)return f.suspense.next();const h=p(f.anchor||f.el),g=h&&h[zl];return g?p(g):h};let M=!1;const O=(f,h,g)=>{let _;f==null?h._vnode&&(Ae(h._vnode,null,null,!0),_=h._vnode.component):S(h._vnode||null,f,h,null,null,null,g),h._vnode=f,M||(M=!0,ar(_),Ki(),M=!1)},F={p:S,um:Ae,m:Ue,r:Mt,mt:de,mc:W,pc:Z,pbc:K,n:y,o:e};return{render:O,hydrate:void 0,createApp:gc(O)}}function fs({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Ct({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Ic(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Co(e,t,n=!1){const s=e.children,r=t.children;if(H(s)&&H(r))for(let i=0;i>1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}function Ao(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Ao(t)}function Cr(e){if(e)for(let t=0;te.__isSuspense;function Mc(e,t){t&&t.pendingBranch?H(e)?t.effects.push(...e):t.effects.push(e):kl(e)}const Je=Symbol.for("v-fgt"),Xn=Symbol.for("v-txt"),Se=Symbol.for("v-cmt"),wn=Symbol.for("v-stc"),on=[];let Ie=null;function Dc(e=!1){on.push(Ie=e?null:[])}function Lc(){on.pop(),Ie=on[on.length-1]||null}let hn=1;function Fn(e,t=!1){hn+=e,e<0&&Ie&&t&&(Ie.hasOnce=!0)}function wo(e){return e.dynamicChildren=hn>0?Ie||jt:null,Lc(),hn>0&&Ie&&Ie.push(e),e}function Wf(e,t,n,s,r,i){return wo(Oo(e,t,n,s,r,i,!0))}function Fc(e,t,n,s,r){return wo(Te(e,t,n,s,r,!0))}function Vn(e){return e?e.__v_isVNode===!0:!1}function wt(e,t){return e.type===t.type&&e.key===t.key}const To=({key:e})=>e??null,Tn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ae(e)||fe(e)||G(e)?{i:Pe,r:e,k:t,f:!!n}:e:null);function Oo(e,t=null,n=null,s=0,r=null,i=e===Je?0:1,o=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&To(t),ref:t&&Tn(t),scopeId:Wi,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:Pe};return l?(Zs(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=ae(n)?8:16),hn>0&&!o&&Ie&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&Ie.push(c),c}const Te=Vc;function Vc(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===lo)&&(e=Se),Vn(e)){const l=yt(e,t,!0);return n&&Zs(l,n),hn>0&&!i&&Ie&&(l.shapeFlag&6?Ie[Ie.indexOf(e)]=l:Ie.push(l)),l.patchFlag=-2,l}if(Jc(e)&&(e=e.__vccOpts),t){t=Hc(t);let{class:l,style:c}=t;l&&!ae(l)&&(t.class=Us(l)),ne(c)&&(qn(c)&&!H(c)&&(c=pe({},c)),t.style=Bs(c))}const o=ae(e)?1:Ro(e)?128:zi(e)?64:ne(e)?4:G(e)?2:0;return Oo(e,t,n,s,r,o,i,!0)}function Hc(e){return e?qn(e)||_o(e)?pe({},e):e:null}function yt(e,t,n=!1,s=!1){const{props:r,ref:i,patchFlag:o,children:l,transition:c}=e,a=t?Bc(r||{},t):r,u={__v_isVNode:!0,__v_skip:!0,type:e.type,props:a,key:a&&To(a),ref:t&&t.ref?n&&i?H(i)?i.concat(Tn(t)):[i,Tn(t)]:Tn(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Je?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&yt(e.ssContent),ssFallback:e.ssFallback&&yt(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&s&&dn(u,c.clone(u)),u}function jc(e=" ",t=0){return Te(Xn,null,e,t)}function $f(e,t){const n=Te(wn,null,e);return n.staticCount=t,n}function qf(e="",t=!1){return t?(Dc(),Fc(Se,null,e)):Te(Se,null,e)}function Qe(e){return e==null||typeof e=="boolean"?Te(Se):H(e)?Te(Je,null,e.slice()):Vn(e)?it(e):Te(Xn,null,String(e))}function it(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:yt(e)}function Zs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(H(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Zs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!_o(t)?t._ctx=Pe:r===3&&Pe&&(Pe.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else G(t)?(t={default:t,_ctx:Pe},n=32):(t=String(t),s&64?(n=16,t=[jc(t)]):n=8);e.children=t,e.shapeFlag|=n}function Bc(...e){const t={};for(let n=0;n_e||Pe;let Hn,Ts;{const e=Wn(),t=(n,s)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(s),i=>{r.length>1?r.forEach(o=>o(i)):r[0](i)}};Hn=t("__VUE_INSTANCE_SETTERS__",n=>_e=n),Ts=t("__VUE_SSR_SETTERS__",n=>pn=n)}const En=e=>{const t=_e;return Hn(e),e.scope.on(),()=>{e.scope.off(),Hn(t)}},Ar=()=>{_e&&_e.scope.off(),Hn(null)};function Po(e){return e.vnode.shapeFlag&4}let pn=!1;function Gc(e,t=!1,n=!1){t&&Ts(t);const{props:s,children:r}=e.vnode,i=Po(e);Cc(e,s,i,t),wc(e,r,n||t);const o=i?Wc(e,t):void 0;return t&&Ts(!1),o}function Wc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,cc);const{setup:s}=n;if(s){ut();const r=e.setupContext=s.length>1?qc(e):null,i=En(e),o=bn(s,e,0,[e.props,r]),l=di(o);if(ft(),i(),(l||e.sp)&&!sn(e)&&to(e),l){if(o.then(Ar,Ar),t)return o.then(c=>{xr(e,c)}).catch(c=>{zn(c,e,0)});e.asyncDep=o}else xr(e,o)}else Io(e)}function xr(e,t,n){G(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ne(t)&&(e.setupState=Bi(t)),Io(e)}function Io(e,t,n){const s=e.type;e.render||(e.render=s.render||Xe);{const r=En(e);ut();try{uc(e)}finally{ft(),r()}}}const $c={get(e,t){return me(e,"get",""),e[t]}};function qc(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,$c),slots:e.slots,emit:e.emit,expose:t}}function Zn(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Bi(zs(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in rn)return rn[n](e)},has(t,n){return n in t||n in rn}})):e.proxy}function zc(e,t=!0){return G(e)?e.displayName||e.name:e.name||t&&e.__name}function Jc(e){return G(e)&&"__vccOpts"in e}const Le=(e,t)=>Vl(e,t,pn);function tr(e,t,n){try{Fn(-1);const s=arguments.length;return s===2?ne(t)&&!H(t)?Vn(t)?Te(e,null,[t]):Te(e,t):Te(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&Vn(n)&&(n=[n]),Te(e,t,n))}finally{Fn(1)}}const Qc="3.5.30";/** +* @vue/runtime-dom v3.5.30 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Os;const Rr=typeof window<"u"&&window.trustedTypes;if(Rr)try{Os=Rr.createPolicy("vue",{createHTML:e=>e})}catch{}const No=Os?e=>Os.createHTML(e):e=>e,Yc="http://www.w3.org/2000/svg",Xc="http://www.w3.org/1998/Math/MathML",rt=typeof document<"u"?document:null,wr=rt&&rt.createElement("template"),Zc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?rt.createElementNS(Yc,e):t==="mathml"?rt.createElementNS(Xc,e):n?rt.createElement(e,{is:n}):rt.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>rt.createTextNode(e),createComment:e=>rt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>rt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{wr.innerHTML=No(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const l=wr.content;if(s==="svg"||s==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},pt="transition",Jt="animation",gn=Symbol("_vtc"),Mo={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},eu=pe({},Ji,Mo),tu=e=>(e.displayName="Transition",e.props=eu,e),zf=tu((e,{slots:t})=>tr(Yl,nu(e),t)),At=(e,t=[])=>{H(e)?e.forEach(n=>n(...t)):e&&e(...t)},Tr=e=>e?H(e)?e.some(t=>t.length>1):e.length>1:!1;function nu(e){const t={};for(const P in e)P in Mo||(t[P]=e[P]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:a=o,appearToClass:u=l,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:m=`${n}-leave-to`}=e,A=su(r),S=A&&A[0],j=A&&A[1],{onBeforeEnter:L,onEnter:w,onEnterCancelled:D,onLeave:N,onLeaveCancelled:U,onBeforeAppear:re=L,onAppear:q=w,onAppearCancelled:W=D}=t,T=(P,z,de,ve)=>{P._enterCancelled=ve,xt(P,z?u:l),xt(P,z?a:o),de&&de()},K=(P,z)=>{P._isLeaving=!1,xt(P,d),xt(P,m),xt(P,p),z&&z()},Y=P=>(z,de)=>{const ve=P?q:w,ie=()=>T(z,P,de);At(ve,[z,ie]),Or(()=>{xt(z,P?c:i),nt(z,P?u:l),Tr(ve)||Pr(z,s,S,ie)})};return pe(t,{onBeforeEnter(P){At(L,[P]),nt(P,i),nt(P,o)},onBeforeAppear(P){At(re,[P]),nt(P,c),nt(P,a)},onEnter:Y(!1),onAppear:Y(!0),onLeave(P,z){P._isLeaving=!0;const de=()=>K(P,z);nt(P,d),P._enterCancelled?(nt(P,p),Mr(P)):(Mr(P),nt(P,p)),Or(()=>{P._isLeaving&&(xt(P,d),nt(P,m),Tr(N)||Pr(P,s,j,de))}),At(N,[P,de])},onEnterCancelled(P){T(P,!1,void 0,!0),At(D,[P])},onAppearCancelled(P){T(P,!0,void 0,!0),At(W,[P])},onLeaveCancelled(P){K(P),At(U,[P])}})}function su(e){if(e==null)return null;if(ne(e))return[as(e.enter),as(e.leave)];{const t=as(e);return[t,t]}}function as(e){return tl(e)}function nt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[gn]||(e[gn]=new Set)).add(t)}function xt(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[gn];n&&(n.delete(t),n.size||(e[gn]=void 0))}function Or(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let ru=0;function Pr(e,t,n,s){const r=e._endId=++ru,i=()=>{r===e._endId&&s()};if(n!=null)return setTimeout(i,n);const{type:o,timeout:l,propCount:c}=iu(e,t);if(!o)return s();const a=o+"end";let u=0;const d=()=>{e.removeEventListener(a,p),i()},p=m=>{m.target===e&&++u>=c&&d()};setTimeout(()=>{u(n[A]||"").split(", "),r=s(`${pt}Delay`),i=s(`${pt}Duration`),o=Ir(r,i),l=s(`${Jt}Delay`),c=s(`${Jt}Duration`),a=Ir(l,c);let u=null,d=0,p=0;t===pt?o>0&&(u=pt,d=o,p=i.length):t===Jt?a>0&&(u=Jt,d=a,p=c.length):(d=Math.max(o,a),u=d>0?o>a?pt:Jt:null,p=u?u===pt?i.length:c.length:0);const m=u===pt&&/\b(?:transform|all)(?:,|$)/.test(s(`${pt}Property`).toString());return{type:u,timeout:d,propCount:p,hasTransform:m}}function Ir(e,t){for(;e.lengthNr(n)+Nr(e[s])))}function Nr(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Mr(e){return(e?e.ownerDocument:document).body.offsetHeight}function ou(e,t,n){const s=e[gn];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Dr=Symbol("_vod"),lu=Symbol("_vsh"),cu=Symbol(""),uu=/(?:^|;)\s*display\s*:/;function fu(e,t,n){const s=e.style,r=ae(n);let i=!1;if(n&&!r){if(t)if(ae(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();n[l]==null&&On(s,l,"")}else for(const o in t)n[o]==null&&On(s,o,"");for(const o in n)o==="display"&&(i=!0),On(s,o,n[o])}else if(r){if(t!==n){const o=s[cu];o&&(n+=";"+o),s.cssText=n,i=uu.test(n)}}else t&&e.removeAttribute("style");Dr in e&&(e[Dr]=i?s.display:"",e[lu]&&(s.display="none"))}const Lr=/\s*!important$/;function On(e,t,n){if(H(n))n.forEach(s=>On(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=au(e,t);Lr.test(n)?e.setProperty(bt(s),n.replace(Lr,""),"important"):e[s]=n}}const Fr=["Webkit","Moz","ms"],ds={};function au(e,t){const n=ds[t];if(n)return n;let s=Ce(t);if(s!=="filter"&&s in e)return ds[t]=s;s=Gn(s);for(let r=0;rhs||(gu.then(()=>hs=0),hs=Date.now());function _u(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;je(vu(s,n.value),t,5,[s])};return n.value=e,n.attached=mu(),n}function vu(e,t){if(H(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const kr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,yu=(e,t,n,s,r,i)=>{const o=r==="svg";t==="class"?ou(e,s,o):t==="style"?fu(e,n,s):Bn(t)?Vs(t)||hu(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):bu(e,t,s,o))?(jr(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Hr(e,t,s,o,i,t!=="value")):e._isVueCE&&(Eu(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!ae(s)))?jr(e,Ce(t),s,i,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Hr(e,t,s,o))};function bu(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&kr(t)&&G(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return kr(t)&&ae(n)?!1:t in e}function Eu(e,t){const n=e._def.props;if(!n)return!1;const s=Ce(t);return Array.isArray(n)?n.some(r=>Ce(r)===s):Object.keys(n).some(r=>Ce(r)===s)}const jn=e=>{const t=e.props["onUpdate:modelValue"]||!1;return H(t)?n=>xn(t,n):t};function Su(e){e.target.composing=!0}function Kr(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const kt=Symbol("_assign");function Gr(e,t,n){return t&&(e=e.trim()),n&&(e=js(e)),e}const Jf={created(e,{modifiers:{lazy:t,trim:n,number:s}},r){e[kt]=jn(r);const i=s||r.props&&r.props.type==="number";Tt(e,t?"change":"input",o=>{o.target.composing||e[kt](Gr(e.value,n,i))}),(n||i)&&Tt(e,"change",()=>{e.value=Gr(e.value,n,i)}),t||(Tt(e,"compositionstart",Su),Tt(e,"compositionend",Kr),Tt(e,"change",Kr))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:r,number:i}},o){if(e[kt]=jn(o),e.composing)return;const l=(i||e.type==="number")&&!/^0\d/.test(e.value)?js(e.value):e.value,c=t??"";l!==c&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||r&&e.value.trim()===c)||(e.value=c))}},Qf={deep:!0,created(e,t,n){e[kt]=jn(n),Tt(e,"change",()=>{const s=e._modelValue,r=Cu(e),i=e.checked,o=e[kt];if(H(s)){const l=_i(s,r),c=l!==-1;if(i&&!c)o(s.concat(r));else if(!i&&c){const a=[...s];a.splice(l,1),o(a)}}else if(Un(s)){const l=new Set(s);i?l.add(r):l.delete(r),o(l)}else o(Do(e,i))})},mounted:Wr,beforeUpdate(e,t,n){e[kt]=jn(n),Wr(e,t,n)}};function Wr(e,{value:t,oldValue:n},s){e._modelValue=t;let r;if(H(t))r=_i(t,s.props.value)>-1;else if(Un(t))r=t.has(s.props.value);else{if(t===n)return;r=vn(t,Do(e,!0))}e.checked!==r&&(e.checked=r)}function Cu(e){return"_value"in e?e._value:e.value}function Do(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const Au=["ctrl","shift","alt","meta"],xu={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Au.some(n=>e[`${n}Key`]&&!t.includes(n))},Yf=(e,t)=>{if(!e)return e;const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=((r,...i)=>{for(let o=0;o{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=(r=>{if(!("key"in r))return;const i=bt(r.key);if(t.some(o=>o===i||Ru[o]===i))return e(r)}))},wu=pe({patchProp:yu},Zc);let $r;function Tu(){return $r||($r=Oc(wu))}const Zf=((...e)=>{const t=Tu().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Pu(s);if(!r)return;const i=t._component;!G(i)&&!i.render&&!i.template&&(i.template=r.innerHTML),r.nodeType===1&&(r.textContent="");const o=n(r,!1,Ou(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),o},t});function Ou(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Pu(e){return ae(e)?document.querySelector(e):e}/*! + * pinia v2.3.1 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */let Lo;const es=e=>Lo=e,Fo=Symbol();function Ps(e){return e&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Object]"&&typeof e.toJSON!="function"}var ln;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})(ln||(ln={}));function ea(){const e=Ei(!0),t=e.run(()=>Hi({}));let n=[],s=[];const r=zs({install(i){es(r),r._a=i,i.provide(Fo,r),i.config.globalProperties.$pinia=r,s.forEach(o=>n.push(o)),s=[]},use(i){return this._a?n.push(i):s.push(i),this},_p:n,_a:null,_e:e,_s:new Map,state:t});return r}const Vo=()=>{};function qr(e,t,n,s=Vo){e.push(t);const r=()=>{const i=e.indexOf(t);i>-1&&(e.splice(i,1),s())};return!n&&Si()&&fl(r),r}function Ft(e,...t){e.slice().forEach(n=>{n(...t)})}const Iu=e=>e(),zr=Symbol(),ps=Symbol();function Is(e,t){e instanceof Map&&t instanceof Map?t.forEach((n,s)=>e.set(s,n)):e instanceof Set&&t instanceof Set&&t.forEach(e.add,e);for(const n in t){if(!t.hasOwnProperty(n))continue;const s=t[n],r=e[n];Ps(r)&&Ps(s)&&e.hasOwnProperty(n)&&!fe(s)&&!ct(s)?e[n]=Is(r,s):e[n]=s}return e}const Nu=Symbol();function Mu(e){return!Ps(e)||!e.hasOwnProperty(Nu)}const{assign:mt}=Object;function Du(e){return!!(fe(e)&&e.effect)}function Lu(e,t,n,s){const{state:r,actions:i,getters:o}=t,l=n.state.value[e];let c;function a(){l||(n.state.value[e]=r?r():{});const u=Ml(n.state.value[e]);return mt(u,i,Object.keys(o||{}).reduce((d,p)=>(d[p]=zs(Le(()=>{es(n);const m=n._s.get(e);return o[p].call(m,m)})),d),{}))}return c=Ho(e,a,t,n,s,!0),c}function Ho(e,t,n={},s,r,i){let o;const l=mt({actions:{}},n),c={deep:!0};let a,u,d=[],p=[],m;const A=s.state.value[e];!i&&!A&&(s.state.value[e]={});let S;function j(W){let T;a=u=!1,typeof W=="function"?(W(s.state.value[e]),T={type:ln.patchFunction,storeId:e,events:m}):(Is(s.state.value[e],W),T={type:ln.patchObject,payload:W,storeId:e,events:m});const K=S=Symbol();Js().then(()=>{S===K&&(a=!0)}),u=!0,Ft(d,T,s.state.value[e])}const L=i?function(){const{state:T}=n,K=T?T():{};this.$patch(Y=>{mt(Y,K)})}:Vo;function w(){o.stop(),d=[],p=[],s._s.delete(e)}const D=(W,T="")=>{if(zr in W)return W[ps]=T,W;const K=function(){es(s);const Y=Array.from(arguments),P=[],z=[];function de($){P.push($)}function ve($){z.push($)}Ft(p,{args:Y,name:K[ps],store:U,after:de,onError:ve});let ie;try{ie=W.apply(this&&this.$id===e?this:U,Y)}catch($){throw Ft(z,$),$}return ie instanceof Promise?ie.then($=>(Ft(P,$),$)).catch($=>(Ft(z,$),Promise.reject($))):(Ft(P,ie),ie)};return K[zr]=!0,K[ps]=T,K},N={_p:s,$id:e,$onAction:qr.bind(null,p),$patch:j,$reset:L,$subscribe(W,T={}){const K=qr(d,W,T.detached,()=>Y()),Y=o.run(()=>tn(()=>s.state.value[e],P=>{(T.flush==="sync"?u:a)&&W({storeId:e,type:ln.direct,events:m},P)},mt({},c,T)));return K},$dispose:w},U=yn(N);s._s.set(e,U);const q=(s._a&&s._a.runWithContext||Iu)(()=>s._e.run(()=>(o=Ei()).run(()=>t({action:D}))));for(const W in q){const T=q[W];if(fe(T)&&!Du(T)||ct(T))i||(A&&Mu(T)&&(fe(T)?T.value=A[W]:Is(T,A[W])),s.state.value[e][W]=T);else if(typeof T=="function"){const K=D(T,W);q[W]=K,l.actions[W]=T}}return mt(U,q),mt(X(U),q),Object.defineProperty(U,"$state",{get:()=>s.state.value[e],set:W=>{j(T=>{mt(T,W)})}}),s._p.forEach(W=>{mt(U,o.run(()=>W({store:U,app:s._a,pinia:s,options:l})))}),A&&i&&n.hydrate&&n.hydrate(U.$state,A),a=!0,u=!0,U}/*! #__NO_SIDE_EFFECTS__ */function ta(e,t,n){let s,r;const i=typeof t=="function";typeof e=="string"?(s=e,r=i?n:t):(r=e,s=e.id);function o(l,c){const a=Gl();return l=l||(a?Fe(Fo,null):null),l&&es(l),l=Lo,l._s.has(s)||(i?Ho(s,t,r,l):Lu(s,r,l)),l._s.get(s)}return o.$id=s,o}/*! + * vue-router v4.6.4 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */const Ht=typeof document<"u";function jo(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Fu(e){return e.__esModule||e[Symbol.toStringTag]==="Module"||e.default&&jo(e.default)}const ee=Object.assign;function gs(e,t){const n={};for(const s in t){const r=t[s];n[s]=Be(r)?r.map(e):e(r)}return n}const cn=()=>{},Be=Array.isArray;function Jr(e,t){const n={};for(const s in e)n[s]=s in t?t[s]:e[s];return n}const Bo=/#/g,Vu=/&/g,Hu=/\//g,ju=/=/g,Bu=/\?/g,Uo=/\+/g,Uu=/%5B/g,ku=/%5D/g,ko=/%5E/g,Ku=/%60/g,Ko=/%7B/g,Gu=/%7C/g,Go=/%7D/g,Wu=/%20/g;function nr(e){return e==null?"":encodeURI(""+e).replace(Gu,"|").replace(Uu,"[").replace(ku,"]")}function $u(e){return nr(e).replace(Ko,"{").replace(Go,"}").replace(ko,"^")}function Ns(e){return nr(e).replace(Uo,"%2B").replace(Wu,"+").replace(Bo,"%23").replace(Vu,"%26").replace(Ku,"`").replace(Ko,"{").replace(Go,"}").replace(ko,"^")}function qu(e){return Ns(e).replace(ju,"%3D")}function zu(e){return nr(e).replace(Bo,"%23").replace(Bu,"%3F")}function Ju(e){return zu(e).replace(Hu,"%2F")}function mn(e){if(e==null)return null;try{return decodeURIComponent(""+e)}catch{}return""+e}const Qu=/\/$/,Yu=e=>e.replace(Qu,"");function ms(e,t,n="/"){let s,r={},i="",o="";const l=t.indexOf("#");let c=t.indexOf("?");return c=l>=0&&c>l?-1:c,c>=0&&(s=t.slice(0,c),i=t.slice(c,l>0?l:t.length),r=e(i.slice(1))),l>=0&&(s=s||t.slice(0,l),o=t.slice(l,t.length)),s=tf(s??t,n),{fullPath:s+i+o,path:s,query:r,hash:mn(o)}}function Xu(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function Qr(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Zu(e,t,n){const s=t.matched.length-1,r=n.matched.length-1;return s>-1&&s===r&&Gt(t.matched[s],n.matched[r])&&Wo(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Gt(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function Wo(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n in e)if(!ef(e[n],t[n]))return!1;return!0}function ef(e,t){return Be(e)?Yr(e,t):Be(t)?Yr(t,e):(e==null?void 0:e.valueOf())===(t==null?void 0:t.valueOf())}function Yr(e,t){return Be(t)?e.length===t.length&&e.every((n,s)=>n===t[s]):e.length===1&&e[0]===t}function tf(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),s=e.split("/"),r=s[s.length-1];(r===".."||r===".")&&s.push("");let i=n.length-1,o,l;for(o=0;o1&&i--;else break;return n.slice(0,i).join("/")+"/"+s.slice(o).join("/")}const gt={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};let Ms=(function(e){return e.pop="pop",e.push="push",e})({}),_s=(function(e){return e.back="back",e.forward="forward",e.unknown="",e})({});function nf(e){if(!e)if(Ht){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),Yu(e)}const sf=/^[^#]+#/;function rf(e,t){return e.replace(sf,"#")+t}function of(e,t){const n=document.documentElement.getBoundingClientRect(),s=e.getBoundingClientRect();return{behavior:t.behavior,left:s.left-n.left-(t.left||0),top:s.top-n.top-(t.top||0)}}const ts=()=>({left:window.scrollX,top:window.scrollY});function lf(e){let t;if("el"in e){const n=e.el,s=typeof n=="string"&&n.startsWith("#"),r=typeof n=="string"?s?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!r)return;t=of(r,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function Xr(e,t){return(history.state?history.state.position-t:-1)+e}const Ds=new Map;function cf(e,t){Ds.set(e,t)}function uf(e){const t=Ds.get(e);return Ds.delete(e),t}function ff(e){return typeof e=="string"||e&&typeof e=="object"}function $o(e){return typeof e=="string"||typeof e=="symbol"}let ue=(function(e){return e[e.MATCHER_NOT_FOUND=1]="MATCHER_NOT_FOUND",e[e.NAVIGATION_GUARD_REDIRECT=2]="NAVIGATION_GUARD_REDIRECT",e[e.NAVIGATION_ABORTED=4]="NAVIGATION_ABORTED",e[e.NAVIGATION_CANCELLED=8]="NAVIGATION_CANCELLED",e[e.NAVIGATION_DUPLICATED=16]="NAVIGATION_DUPLICATED",e})({});const qo=Symbol("");ue.MATCHER_NOT_FOUND+"",ue.NAVIGATION_GUARD_REDIRECT+"",ue.NAVIGATION_ABORTED+"",ue.NAVIGATION_CANCELLED+"",ue.NAVIGATION_DUPLICATED+"";function Wt(e,t){return ee(new Error,{type:e,[qo]:!0},t)}function st(e,t){return e instanceof Error&&qo in e&&(t==null||!!(e.type&t))}const af=["params","query","hash"];function df(e){if(typeof e=="string")return e;if(e.path!=null)return e.path;const t={};for(const n of af)n in e&&(t[n]=e[n]);return JSON.stringify(t,null,2)}function hf(e){const t={};if(e===""||e==="?")return t;const n=(e[0]==="?"?e.slice(1):e).split("&");for(let s=0;sr&&Ns(r)):[s&&Ns(s)]).forEach(r=>{r!==void 0&&(t+=(t.length?"&":"")+n,r!=null&&(t+="="+r))})}return t}function pf(e){const t={};for(const n in e){const s=e[n];s!==void 0&&(t[n]=Be(s)?s.map(r=>r==null?null:""+r):s==null?s:""+s)}return t}const gf=Symbol(""),ei=Symbol(""),ns=Symbol(""),sr=Symbol(""),Ls=Symbol("");function Qt(){let e=[];function t(s){return e.push(s),()=>{const r=e.indexOf(s);r>-1&&e.splice(r,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function vt(e,t,n,s,r,i=o=>o()){const o=s&&(s.enterCallbacks[r]=s.enterCallbacks[r]||[]);return()=>new Promise((l,c)=>{const a=p=>{p===!1?c(Wt(ue.NAVIGATION_ABORTED,{from:n,to:t})):p instanceof Error?c(p):ff(p)?c(Wt(ue.NAVIGATION_GUARD_REDIRECT,{from:t,to:p})):(o&&s.enterCallbacks[r]===o&&typeof p=="function"&&o.push(p),l())},u=i(()=>e.call(s&&s.instances[r],t,n,a));let d=Promise.resolve(u);e.length<3&&(d=d.then(a)),d.catch(p=>c(p))})}function vs(e,t,n,s,r=i=>i()){const i=[];for(const o of e)for(const l in o.components){let c=o.components[l];if(!(t!=="beforeRouteEnter"&&!o.instances[l]))if(jo(c)){const a=(c.__vccOpts||c)[t];a&&i.push(vt(a,n,s,o,l,r))}else{let a=c();i.push(()=>a.then(u=>{if(!u)throw new Error(`Couldn't resolve component "${l}" at "${o.path}"`);const d=Fu(u)?u.default:u;o.mods[l]=u,o.components[l]=d;const p=(d.__vccOpts||d)[t];return p&&vt(p,n,s,o,l,r)()}))}}return i}function mf(e,t){const n=[],s=[],r=[],i=Math.max(t.matched.length,e.matched.length);for(let o=0;oGt(a,l))?s.push(l):n.push(l));const c=e.matched[o];c&&(t.matched.find(a=>Gt(a,c))||r.push(c))}return[n,s,r]}/*! + * vue-router v4.6.4 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */let _f=()=>location.protocol+"//"+location.host;function zo(e,t){const{pathname:n,search:s,hash:r}=t,i=e.indexOf("#");if(i>-1){let o=r.includes(e.slice(i))?e.slice(i).length:1,l=r.slice(o);return l[0]!=="/"&&(l="/"+l),Qr(l,"")}return Qr(n,e)+s+r}function vf(e,t,n,s){let r=[],i=[],o=null;const l=({state:p})=>{const m=zo(e,location),A=n.value,S=t.value;let j=0;if(p){if(n.value=m,t.value=p,o&&o===A){o=null;return}j=S?p.position-S.position:0}else s(m);r.forEach(L=>{L(n.value,A,{delta:j,type:Ms.pop,direction:j?j>0?_s.forward:_s.back:_s.unknown})})};function c(){o=n.value}function a(p){r.push(p);const m=()=>{const A=r.indexOf(p);A>-1&&r.splice(A,1)};return i.push(m),m}function u(){if(document.visibilityState==="hidden"){const{history:p}=window;if(!p.state)return;p.replaceState(ee({},p.state,{scroll:ts()}),"")}}function d(){for(const p of i)p();i=[],window.removeEventListener("popstate",l),window.removeEventListener("pagehide",u),document.removeEventListener("visibilitychange",u)}return window.addEventListener("popstate",l),window.addEventListener("pagehide",u),document.addEventListener("visibilitychange",u),{pauseListeners:c,listen:a,destroy:d}}function ti(e,t,n,s=!1,r=!1){return{back:e,current:t,forward:n,replaced:s,position:window.history.length,scroll:r?ts():null}}function yf(e){const{history:t,location:n}=window,s={value:zo(e,n)},r={value:t.state};r.value||i(s.value,{back:null,current:s.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(c,a,u){const d=e.indexOf("#"),p=d>-1?(n.host&&document.querySelector("base")?e:e.slice(d))+c:_f()+e+c;try{t[u?"replaceState":"pushState"](a,"",p),r.value=a}catch(m){console.error(m),n[u?"replace":"assign"](p)}}function o(c,a){i(c,ee({},t.state,ti(r.value.back,c,r.value.forward,!0),a,{position:r.value.position}),!0),s.value=c}function l(c,a){const u=ee({},r.value,t.state,{forward:c,scroll:ts()});i(u.current,u,!0),i(c,ee({},ti(s.value,c,null),{position:u.position+1},a),!1),s.value=c}return{location:s,state:r,push:l,replace:o}}function na(e){e=nf(e);const t=yf(e),n=vf(e,t.state,t.location,t.replace);function s(i,o=!0){o||n.pauseListeners(),history.go(i)}const r=ee({location:"",base:e,go:s,createHref:rf.bind(null,e)},t,n);return Object.defineProperty(r,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(r,"state",{enumerable:!0,get:()=>t.state.value}),r}let Ot=(function(e){return e[e.Static=0]="Static",e[e.Param=1]="Param",e[e.Group=2]="Group",e})({});var he=(function(e){return e[e.Static=0]="Static",e[e.Param=1]="Param",e[e.ParamRegExp=2]="ParamRegExp",e[e.ParamRegExpEnd=3]="ParamRegExpEnd",e[e.EscapeNext=4]="EscapeNext",e})(he||{});const bf={type:Ot.Static,value:""},Ef=/[a-zA-Z0-9_]/;function Sf(e){if(!e)return[[]];if(e==="/")return[[bf]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(m){throw new Error(`ERR (${n})/"${a}": ${m}`)}let n=he.Static,s=n;const r=[];let i;function o(){i&&r.push(i),i=[]}let l=0,c,a="",u="";function d(){a&&(n===he.Static?i.push({type:Ot.Static,value:a}):n===he.Param||n===he.ParamRegExp||n===he.ParamRegExpEnd?(i.length>1&&(c==="*"||c==="+")&&t(`A repeatable param (${a}) must be alone in its segment. eg: '/:ids+.`),i.push({type:Ot.Param,value:a,regexp:u,repeatable:c==="*"||c==="+",optional:c==="*"||c==="?"})):t("Invalid state to consume buffer"),a="")}function p(){a+=c}for(;lt.length?t.length===1&&t[0]===be.Static+be.Segment?1:-1:0}function Jo(e,t){let n=0;const s=e.score,r=t.score;for(;n0&&t[t.length-1]<0}const wf={strict:!1,end:!0,sensitive:!1};function Tf(e,t,n){const s=xf(Sf(e.path),n),r=ee(s,{record:e,parent:t,children:[],alias:[]});return t&&!r.record.aliasOf==!t.record.aliasOf&&t.children.push(r),r}function Of(e,t){const n=[],s=new Map;t=Jr(wf,t);function r(d){return s.get(d)}function i(d,p,m){const A=!m,S=ii(d);S.aliasOf=m&&m.record;const j=Jr(t,d),L=[S];if("alias"in d){const N=typeof d.alias=="string"?[d.alias]:d.alias;for(const U of N)L.push(ii(ee({},S,{components:m?m.record.components:S.components,path:U,aliasOf:m?m.record:S})))}let w,D;for(const N of L){const{path:U}=N;if(p&&U[0]!=="/"){const re=p.record.path,q=re[re.length-1]==="/"?"":"/";N.path=p.record.path+(U&&q+U)}if(w=Tf(N,p,j),m?m.alias.push(w):(D=D||w,D!==w&&D.alias.push(w),A&&d.name&&!oi(w)&&o(d.name)),Qo(w)&&c(w),S.children){const re=S.children;for(let q=0;q{o(D)}:cn}function o(d){if($o(d)){const p=s.get(d);p&&(s.delete(d),n.splice(n.indexOf(p),1),p.children.forEach(o),p.alias.forEach(o))}else{const p=n.indexOf(d);p>-1&&(n.splice(p,1),d.record.name&&s.delete(d.record.name),d.children.forEach(o),d.alias.forEach(o))}}function l(){return n}function c(d){const p=Nf(d,n);n.splice(p,0,d),d.record.name&&!oi(d)&&s.set(d.record.name,d)}function a(d,p){let m,A={},S,j;if("name"in d&&d.name){if(m=s.get(d.name),!m)throw Wt(ue.MATCHER_NOT_FOUND,{location:d});j=m.record.name,A=ee(ri(p.params,m.keys.filter(D=>!D.optional).concat(m.parent?m.parent.keys.filter(D=>D.optional):[]).map(D=>D.name)),d.params&&ri(d.params,m.keys.map(D=>D.name))),S=m.stringify(A)}else if(d.path!=null)S=d.path,m=n.find(D=>D.re.test(S)),m&&(A=m.parse(S),j=m.record.name);else{if(m=p.name?s.get(p.name):n.find(D=>D.re.test(p.path)),!m)throw Wt(ue.MATCHER_NOT_FOUND,{location:d,currentLocation:p});j=m.record.name,A=ee({},p.params,d.params),S=m.stringify(A)}const L=[];let w=m;for(;w;)L.unshift(w.record),w=w.parent;return{name:j,path:S,params:A,matched:L,meta:If(L)}}e.forEach(d=>i(d));function u(){n.length=0,s.clear()}return{addRoute:i,resolve:a,removeRoute:o,clearRoutes:u,getRoutes:l,getRecordMatcher:r}}function ri(e,t){const n={};for(const s of t)s in e&&(n[s]=e[s]);return n}function ii(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:Pf(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function Pf(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const s in e.components)t[s]=typeof n=="object"?n[s]:n;return t}function oi(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function If(e){return e.reduce((t,n)=>ee(t,n.meta),{})}function Nf(e,t){let n=0,s=t.length;for(;n!==s;){const i=n+s>>1;Jo(e,t[i])<0?s=i:n=i+1}const r=Mf(e);return r&&(s=t.lastIndexOf(r,s-1)),s}function Mf(e){let t=e;for(;t=t.parent;)if(Qo(t)&&Jo(e,t)===0)return t}function Qo({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function li(e){const t=Fe(ns),n=Fe(sr),s=Le(()=>{const c=It(e.to);return t.resolve(c)}),r=Le(()=>{const{matched:c}=s.value,{length:a}=c,u=c[a-1],d=n.matched;if(!u||!d.length)return-1;const p=d.findIndex(Gt.bind(null,u));if(p>-1)return p;const m=ci(c[a-2]);return a>1&&ci(u)===m&&d[d.length-1].path!==m?d.findIndex(Gt.bind(null,c[a-2])):p}),i=Le(()=>r.value>-1&&Hf(n.params,s.value.params)),o=Le(()=>r.value>-1&&r.value===n.matched.length-1&&Wo(n.params,s.value.params));function l(c={}){if(Vf(c)){const a=t[It(e.replace)?"replace":"push"](It(e.to)).catch(cn);return e.viewTransition&&typeof document<"u"&&"startViewTransition"in document&&document.startViewTransition(()=>a),a}return Promise.resolve()}return{route:s,href:Le(()=>s.value.href),isActive:i,isExactActive:o,navigate:l}}function Df(e){return e.length===1?e[0]:e}const Lf=eo({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"},viewTransition:Boolean},useLink:li,setup(e,{slots:t}){const n=yn(li(e)),{options:s}=Fe(ns),r=Le(()=>({[ui(e.activeClass,s.linkActiveClass,"router-link-active")]:n.isActive,[ui(e.exactActiveClass,s.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const i=t.default&&Df(t.default(n));return e.custom?i:tr("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:r.value},i)}}}),Ff=Lf;function Vf(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function Hf(e,t){for(const n in t){const s=t[n],r=e[n];if(typeof s=="string"){if(s!==r)return!1}else if(!Be(r)||r.length!==s.length||s.some((i,o)=>i.valueOf()!==r[o].valueOf()))return!1}return!0}function ci(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const ui=(e,t,n)=>e??t??n,jf=eo({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const s=Fe(Ls),r=Le(()=>e.route||s.value),i=Fe(ei,0),o=Le(()=>{let a=It(i);const{matched:u}=r.value;let d;for(;(d=u[a])&&!d.components;)a++;return a}),l=Le(()=>r.value.matched[o.value]);Rn(ei,Le(()=>o.value+1)),Rn(gf,l),Rn(Ls,r);const c=Hi();return tn(()=>[c.value,l.value,e.name],([a,u,d],[p,m,A])=>{u&&(u.instances[d]=a,m&&m!==u&&a&&a===p&&(u.leaveGuards.size||(u.leaveGuards=m.leaveGuards),u.updateGuards.size||(u.updateGuards=m.updateGuards))),a&&u&&(!m||!Gt(u,m)||!p)&&(u.enterCallbacks[d]||[]).forEach(S=>S(a))},{flush:"post"}),()=>{const a=r.value,u=e.name,d=l.value,p=d&&d.components[u];if(!p)return fi(n.default,{Component:p,route:a});const m=d.props[u],A=m?m===!0?a.params:typeof m=="function"?m(a):m:null,j=tr(p,ee({},A,t,{onVnodeUnmounted:L=>{L.component.isUnmounted&&(d.instances[u]=null)},ref:c}));return fi(n.default,{Component:j,route:a})||j}}});function fi(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const Bf=jf;function sa(e){const t=Of(e.routes,e),n=e.parseQuery||hf,s=e.stringifyQuery||Zr,r=e.history,i=Qt(),o=Qt(),l=Qt(),c=Pl(gt);let a=gt;Ht&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const u=gs.bind(null,y=>""+y),d=gs.bind(null,Ju),p=gs.bind(null,mn);function m(y,M){let O,F;return $o(y)?(O=t.getRecordMatcher(y),F=M):F=y,t.addRoute(F,O)}function A(y){const M=t.getRecordMatcher(y);M&&t.removeRoute(M)}function S(){return t.getRoutes().map(y=>y.record)}function j(y){return!!t.getRecordMatcher(y)}function L(y,M){if(M=ee({},M||c.value),typeof y=="string"){const g=ms(n,y,M.path),_=t.resolve({path:g.path},M),b=r.createHref(g.fullPath);return ee(g,_,{params:p(_.params),hash:mn(g.hash),redirectedFrom:void 0,href:b})}let O;if(y.path!=null)O=ee({},y,{path:ms(n,y.path,M.path).path});else{const g=ee({},y.params);for(const _ in g)g[_]==null&&delete g[_];O=ee({},y,{params:d(g)}),M.params=d(M.params)}const F=t.resolve(O,M),J=y.hash||"";F.params=u(p(F.params));const f=Xu(s,ee({},y,{hash:$u(J),path:F.path})),h=r.createHref(f);return ee({fullPath:f,hash:J,query:s===Zr?pf(y.query):y.query||{}},F,{redirectedFrom:void 0,href:h})}function w(y){return typeof y=="string"?ms(n,y,c.value.path):ee({},y)}function D(y,M){if(a!==y)return Wt(ue.NAVIGATION_CANCELLED,{from:M,to:y})}function N(y){return q(y)}function U(y){return N(ee(w(y),{replace:!0}))}function re(y,M){const O=y.matched[y.matched.length-1];if(O&&O.redirect){const{redirect:F}=O;let J=typeof F=="function"?F(y,M):F;return typeof J=="string"&&(J=J.includes("?")||J.includes("#")?J=w(J):{path:J},J.params={}),ee({query:y.query,hash:y.hash,params:J.path!=null?{}:y.params},J)}}function q(y,M){const O=a=L(y),F=c.value,J=y.state,f=y.force,h=y.replace===!0,g=re(O,F);if(g)return q(ee(w(g),{state:typeof g=="object"?ee({},J,g.state):J,force:f,replace:h}),M||O);const _=O;_.redirectedFrom=M;let b;return!f&&Zu(s,F,O)&&(b=Wt(ue.NAVIGATION_DUPLICATED,{to:_,from:F}),Ue(F,F,!0,!1)),(b?Promise.resolve(b):K(_,F)).catch(v=>st(v)?st(v,ue.NAVIGATION_GUARD_REDIRECT)?v:ht(v):Z(v,_,F)).then(v=>{if(v){if(st(v,ue.NAVIGATION_GUARD_REDIRECT))return q(ee({replace:h},w(v.to),{state:typeof v.to=="object"?ee({},J,v.to.state):J,force:f}),M||_)}else v=P(_,F,!0,h,J);return Y(_,F,v),v})}function W(y,M){const O=D(y,M);return O?Promise.reject(O):Promise.resolve()}function T(y){const M=Dt.values().next().value;return M&&typeof M.runWithContext=="function"?M.runWithContext(y):y()}function K(y,M){let O;const[F,J,f]=mf(y,M);O=vs(F.reverse(),"beforeRouteLeave",y,M);for(const g of F)g.leaveGuards.forEach(_=>{O.push(vt(_,y,M))});const h=W.bind(null,y,M);return O.push(h),Me(O).then(()=>{O=[];for(const g of i.list())O.push(vt(g,y,M));return O.push(h),Me(O)}).then(()=>{O=vs(J,"beforeRouteUpdate",y,M);for(const g of J)g.updateGuards.forEach(_=>{O.push(vt(_,y,M))});return O.push(h),Me(O)}).then(()=>{O=[];for(const g of f)if(g.beforeEnter)if(Be(g.beforeEnter))for(const _ of g.beforeEnter)O.push(vt(_,y,M));else O.push(vt(g.beforeEnter,y,M));return O.push(h),Me(O)}).then(()=>(y.matched.forEach(g=>g.enterCallbacks={}),O=vs(f,"beforeRouteEnter",y,M,T),O.push(h),Me(O))).then(()=>{O=[];for(const g of o.list())O.push(vt(g,y,M));return O.push(h),Me(O)}).catch(g=>st(g,ue.NAVIGATION_CANCELLED)?g:Promise.reject(g))}function Y(y,M,O){l.list().forEach(F=>T(()=>F(y,M,O)))}function P(y,M,O,F,J){const f=D(y,M);if(f)return f;const h=M===gt,g=Ht?history.state:{};O&&(F||h?r.replace(y.fullPath,ee({scroll:h&&g&&g.scroll},J)):r.push(y.fullPath,J)),c.value=y,Ue(y,M,O,h),ht()}let z;function de(){z||(z=r.listen((y,M,O)=>{if(!Et.listening)return;const F=L(y),J=re(F,Et.currentRoute.value);if(J){q(ee(J,{replace:!0,force:!0}),F).catch(cn);return}a=F;const f=c.value;Ht&&cf(Xr(f.fullPath,O.delta),ts()),K(F,f).catch(h=>st(h,ue.NAVIGATION_ABORTED|ue.NAVIGATION_CANCELLED)?h:st(h,ue.NAVIGATION_GUARD_REDIRECT)?(q(ee(w(h.to),{force:!0}),F).then(g=>{st(g,ue.NAVIGATION_ABORTED|ue.NAVIGATION_DUPLICATED)&&!O.delta&&O.type===Ms.pop&&r.go(-1,!1)}).catch(cn),Promise.reject()):(O.delta&&r.go(-O.delta,!1),Z(h,F,f))).then(h=>{h=h||P(F,f,!1),h&&(O.delta&&!st(h,ue.NAVIGATION_CANCELLED)?r.go(-O.delta,!1):O.type===Ms.pop&&st(h,ue.NAVIGATION_ABORTED|ue.NAVIGATION_DUPLICATED)&&r.go(-1,!1)),Y(F,f,h)}).catch(cn)}))}let ve=Qt(),ie=Qt(),$;function Z(y,M,O){ht(y);const F=ie.list();return F.length?F.forEach(J=>J(y,M,O)):console.error(y),Promise.reject(y)}function et(){return $&&c.value!==gt?Promise.resolve():new Promise((y,M)=>{ve.add([y,M])})}function ht(y){return $||($=!y,de(),ve.list().forEach(([M,O])=>y?O(y):M()),ve.reset()),y}function Ue(y,M,O,F){const{scrollBehavior:J}=e;if(!Ht||!J)return Promise.resolve();const f=!O&&uf(Xr(y.fullPath,0))||(F||!O)&&history.state&&history.state.scroll||null;return Js().then(()=>J(y,M,f)).then(h=>h&&lf(h)).catch(h=>Z(h,y,M))}const Ae=y=>r.go(y);let Mt;const Dt=new Set,Et={currentRoute:c,listening:!0,addRoute:m,removeRoute:A,clearRoutes:t.clearRoutes,hasRoute:j,getRoutes:S,resolve:L,options:e,push:N,replace:U,go:Ae,back:()=>Ae(-1),forward:()=>Ae(1),beforeEach:i.add,beforeResolve:o.add,afterEach:l.add,onError:ie.add,isReady:et,install(y){y.component("RouterLink",Ff),y.component("RouterView",Bf),y.config.globalProperties.$router=Et,Object.defineProperty(y.config.globalProperties,"$route",{enumerable:!0,get:()=>It(c)}),Ht&&!Mt&&c.value===gt&&(Mt=!0,N(r.location).catch(F=>{}));const M={};for(const F in gt)Object.defineProperty(M,F,{get:()=>c.value[F],enumerable:!0});y.provide(ns,Et),y.provide(sr,Vi(M)),y.provide(Ls,c);const O=y.unmount;Dt.add(y),y.unmount=function(){Dt.delete(y),Dt.size<1&&(a=gt,z&&z(),z=null,c.value=gt,Mt=!1,$=!1),O()}}};function Me(y){return y.reduce((M,O)=>M.then(()=>T(O)),Promise.resolve())}return Et}function ra(){return Fe(ns)}function ia(e){return Fe(sr)}export{Js as A,Zf as B,ea as C,kf as D,Uf as E,Je as F,Jf as G,ra as H,$f as I,Qf as J,Xf as K,Yf as L,Ff as R,zf as T,na as a,Wf as b,sa as c,ta as d,Oo as e,Gf as f,Te as g,Kl as h,It as i,jc as j,qf as k,Bf as l,Fc as m,Us as n,Dc as o,Kf as p,eo as q,Hi as r,tr as s,ul as t,ia as u,io as v,tn as w,Pl as x,Le as y,so as z}; diff --git a/apps/admin/drpys.png b/apps/admin/drpys.png new file mode 100644 index 00000000..dac857da Binary files /dev/null and b/apps/admin/drpys.png differ diff --git a/apps/admin/favicon.svg b/apps/admin/favicon.svg new file mode 100644 index 00000000..14f166b5 --- /dev/null +++ b/apps/admin/favicon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/index.html b/apps/admin/index.html new file mode 100644 index 00000000..0a3cdbe2 --- /dev/null +++ b/apps/admin/index.html @@ -0,0 +1,15 @@ + + + + + + DRPYS ADMIN + + + + + + +
+ + diff --git a/apps/source-checker/index.html b/apps/source-checker/index.html index d31f6267..284b0465 100644 --- a/apps/source-checker/index.html +++ b/apps/source-checker/index.html @@ -523,22 +523,36 @@

检测结果

// 2. 如果推荐接口异常,检测一级分类接口 let categorySuccess = false; if (homeResult.data && homeResult.data.class && homeResult.data.class.length > 0) { - const firstCategory = homeResult.data.class[0]; - if (firstCategory.type_id) { + // 尝试检测前两个分类(容错机制) + const categoriesToCheck = homeResult.data.class.slice(0, 2); + + for (let i = 0; i < categoriesToCheck.length; i++) { + const category = categoriesToCheck[i]; + if (!category.type_id) continue; + const cateResult = await this.testApi(source.api, { ac: 'list', - t: firstCategory.type_id, + t: category.type_id, pg: 1, extend }); - result.details.category = cateResult; + + // 记录结果:如果是第一个,直接记录;如果是后续且成功了,也记录覆盖 + if (i === 0 || (cateResult.success && this.isValidData(cateResult.data))) { + result.details.category = cateResult; + } categorySuccess = cateResult.success && this.isValidData(cateResult.data); if (categorySuccess) { result.status = 'success'; - result.message = '分类接口正常'; - this.log(`${source.name}: 分类接口正常`, 'success'); + result.message = `分类接口正常${i > 0 ? ' (容错:分类2)' : ''}`; + this.log(`${source.name}: 分类接口正常${i > 0 ? ' (容错:分类2)' : ''}`, 'success'); return; + } else { + // 如果是第一个失败且还有下一个,记录日志 + if (i === 0 && categoriesToCheck.length > 1) { + this.log(`${source.name}: 分类1无数据,尝试容错检测分类2...`, 'warning'); + } } } } diff --git a/config/map.txt b/config/map.txt index 5919fc23..5e8d2390 100644 --- a/config/map.txt +++ b/config/map.txt @@ -18,6 +18,7 @@ emby@@{"server":"http://139.9.106.196:2345","username":"kid","password":""}@@小 采集之王[合]@@?type=url¶ms=../json/采集[密]静态.json$1$@@采王成人[密] 采集之王[合]@@?type=url¶ms=../json/采集2024静态.json$1$@@采王2024 采集之王[合]@@?type=url¶ms=../json/采集2025静态.json$1$@@采王2025 +采集之王[合]@@?type=url¶ms=../json/采集2026静态.json$1$@@采王2026 UC分享@@?type=url¶ms=../json/UC分享.json@@UC分享[盘] 16wMV[听]@@?type=url¶ms=../json/十六万歌曲.txt 点歌欢唱[B]@@?type=url¶ms=../json/十六万歌曲.txt diff --git a/controllers/admin.js b/controllers/admin.js new file mode 100644 index 00000000..95c7782f --- /dev/null +++ b/controllers/admin.js @@ -0,0 +1,286 @@ +/** + * Admin Controller - 后台管理主控制器 + * 重构版:移除 MCP 依赖,直接实现业务逻辑 + */ + +import path from 'path'; +import fs from '../utils/fsWrapper.js'; +import { validateBasicAuth } from '../utils/api_validate.js'; + +// 导入子控制器 +import * as systemController from './admin/systemController.js'; +import * as logsController from './admin/logsController.js'; +import * as sourcesController from './admin/sourcesController.js'; +import * as filesController from './admin/filesController.js'; +import * as dbController from './admin/dbController.js'; +import * as subController from './admin/subController.js'; +import * as backupController from './admin/backupController.js'; + +// 配置常量 +const CONFIG_PATH = path.join(process.cwd(), 'config/env.json'); + +const FULL_ENV_TEMPLATE = { + "ali_token": "", + "ali_refresh_token": "", + "quark_cookie": "", + "quark_token_cookie": "", + "uc_cookie": "", + "uc_token_cookie": "", + "baidu_cookie": "", + "xun_username": "", + "xun_password": "", + "cloud_account": "", + "cloud_password": "", + "cloud_cookie": "", + "yun_account": "", + "yun_cookie": "", + "pan_passport": "", + "pan_password": "", + "pan_auth": "", + "pikpak_token": "", + "now_ai": "1", + "spark_ai_authKey": "", + "deepseek_apiKey": "", + "kimi_apiKey": "", + "sparkBotObject": {}, + "thread": "6", + "api_pwd": "", + "hide_adult": "1", + "enable_old_config": "0", + "show_curl": "0", + "show_req": "0", + "enable_rule_name": "0", + "enable_dr2": "1", + "enable_py": "1", + "enable_php": "1", + "enable_cat": "1", + "enable_self_jx": "0", + "enable_system_proxy": "1", + "play_proxy_mode": "1", + "play_local_proxy_type": "1", + "PROXY_AUTH": "drpys", + "enable_doh": "0", + "allow_forward": "0", + "allow_ftp_cache_clear": "0", + "allow_webdav_cache_clear": "0", + "link_url": "", + "enable_link_data": "0", + "enable_link_push": "0", + "enable_link_jar": "0", + "cat_sub_code": "all", + "must_sub_code": "0", + "bili_cookie": "", + "mg_hz": "4" +}; + +// 导出路由配置 +export default async function adminController(fastify, options) { + // 注册 Basic Auth 验证钩子 + fastify.addHook('preHandler', (request, reply, done) => { + // 只对 /api/admin/* 接口进行验证 + if (request.url.startsWith('/api/admin')) { + validateBasicAuth(request, reply, done); + } else { + done(); + } + }); + + // ==================== 系统管理 API ==================== + fastify.get('/api/admin/health', systemController.getHealth); + fastify.post('/api/admin/restart', systemController.restartService); + + // ==================== 日志 API ==================== + fastify.get('/api/admin/logs', logsController.getLogs); + + // ==================== 配置管理 API ==================== + fastify.get('/api/admin/config', getConfig); + fastify.post('/api/admin/config', updateConfig); + fastify.get('/api/admin/env', getEnv); + fastify.get('/api/admin/version', getVersion); + + // ==================== 源管理 API ==================== + fastify.get('/api/admin/sources', sourcesController.listSources); + fastify.post('/api/admin/sources/validate', sourcesController.validateSpider); + fastify.post('/api/admin/sources/syntax', sourcesController.checkSyntax); + fastify.get('/api/admin/sources/template', sourcesController.getTemplate); + fastify.get('/api/admin/sources/libs', sourcesController.getLibsInfo); + + // ==================== 文件管理 API ==================== + fastify.get('/api/admin/files/list', filesController.listDirectory); + fastify.get('/api/admin/files/read', filesController.readFile); + fastify.post('/api/admin/files/write', filesController.writeFile); + fastify.delete('/api/admin/files/delete', filesController.deleteFile); + + // ==================== 数据库 API ==================== + fastify.post('/api/admin/db/query', dbController.executeQuery); + fastify.get('/api/admin/db/tables', dbController.getTables); + fastify.get('/api/admin/db/tables/:table/schema', dbController.getTableSchema); + + // ==================== Sub文件管理 API ==================== + fastify.get('/api/admin/sub/files', subController.getSubFiles); + fastify.get('/api/admin/sub/file', subController.getSubFileContent); + fastify.post('/api/admin/sub/file', subController.saveSubFileContent); + + // ==================== 备份恢复 API ==================== + fastify.get('/api/admin/backup/config', backupController.getBackupConfig); + fastify.post('/api/admin/backup/config', backupController.updateBackupConfig); + fastify.post('/api/admin/backup/config/reset', backupController.resetBackupConfig); + fastify.post('/api/admin/backup/create', backupController.createBackup); + fastify.post('/api/admin/backup/restore', backupController.restoreBackup); + + // ==================== 路由信息 API ==================== + fastify.get('/api/admin/routes', getRoutesInfo); + fastify.get('/api/admin/docs', systemController.getApiDocs); + + // MCP 兼容层 + const ENABLE_MCP_COMPAT = process.env.ENABLE_MCP_COMPAT !== 'false'; + if (ENABLE_MCP_COMPAT) { + fastify.post('/admin/mcp', async (req, reply) => { + const { name, arguments: args } = req.body; + try { + // 仅作最低限度的兼容,或者提示用户升级 + return reply.code(400).send({ error: 'MCP API 已弃用,请更新 drpy-node-admin 到最新版本' }); + } catch (e) { + return reply.code(500).send({ error: e.message }); + } + }); + } +} + +// ==================== 辅助函数 ==================== + +async function getConfig(req, reply) { + try { + const { key } = req.query; + + let config = {}; + if (await fs.pathExists(CONFIG_PATH)) { + const configContent = await fs.readFile(CONFIG_PATH, 'utf-8'); + try { + config = JSON.parse(configContent); + } catch (e) { + // ignore parse error + } + } + + // Merge with template to ensure all keys exist + config = { ...FULL_ENV_TEMPLATE, ...config }; + + if (key) { + const keys = key.split('.'); + let value = config; + for (const k of keys) { + value = value?.[k]; + } + return reply.send(value !== undefined ? value : null); + } + + return reply.send(config); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} + +async function updateConfig(req, reply) { + try { + const { key, value } = req.body; + + if (!key) { + return reply.code(400).send({ error: 'Key is required' }); + } + + if (!await fs.pathExists(CONFIG_PATH)) { + return reply.code(404).send({ error: 'Config file not found' }); + } + + const configContent = await fs.readFile(CONFIG_PATH, 'utf-8'); + let config = JSON.parse(configContent); + + // 设置嵌套值 + const keys = key.split('.'); + let target = config; + for (let i = 0; i < keys.length - 1; i++) { + if (!target[keys[i]]) { + target[keys[i]] = {}; + } + target = target[keys[i]]; + } + + // 尝试解析为 JSON + let parsedValue = value; + try { + parsedValue = JSON.parse(value); + } catch { + // 保持字符串 + } + + target[keys[keys.length - 1]] = parsedValue; + + // 写回文件 + await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2)); + + return reply.send({ + success: true, + message: `配置项 ${key} 已更新` + }); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} + +async function getEnv(req, reply) { + try { + const envData = {}; + + // 从 process.env 读取关键配置 + const keys = [ + 'PORT', 'NODE_ENV', 'MAX_TEXT_SIZE', 'MAX_IMAGE_SIZE', + 'QUARK_COOKIE', 'ALI_TOKEN', 'bili_cookie' + ]; + + for (const key of keys) { + if (process.env[key]) { + envData[key] = process.env[key]; + } + } + + return reply.send(envData); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} + +async function getVersion(req, reply) { + try { + const packageJson = await fs.readJson(path.join(process.cwd(), 'package.json')); + return reply.send({ version: packageJson.version }); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} + +async function getRoutesInfo(req, reply) { + try { + const indexControllerPath = path.join(process.cwd(), 'controllers/index.js'); + + if (!await fs.pathExists(indexControllerPath)) { + return reply.send({ + file: 'controllers/index.js', + registered_controllers: [] + }); + } + + const content = await fs.readFile(indexControllerPath, 'utf-8'); + const lines = content.split('\n'); + const registered = lines + .filter(l => l.trim().startsWith('fastify.register(')) + .map(l => l.trim()); + + return reply.send({ + file: 'controllers/index.js', + registered_controllers: registered + }); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} diff --git a/controllers/admin/backupController.js b/controllers/admin/backupController.js new file mode 100644 index 00000000..9179b98c --- /dev/null +++ b/controllers/admin/backupController.js @@ -0,0 +1,196 @@ +import path from 'path'; +import fs from '../../utils/fsWrapper.js'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const projectRootDir = path.resolve(__dirname, '../../'); + +const BACKUP_PATHS = [ + '.env', + '.plugins.js', + 'config/env.json', + 'config/map.txt', + 'config/parses.conf', + 'config/player.json', + 'scripts/cron', + 'plugins' +]; + +const BACKINFO_FILENAME = '.backinfo'; + +const getBackupRootDir = () => { + return path.join(path.dirname(projectRootDir), path.basename(projectRootDir) + '-backup'); +}; + +const getBackinfoPath = (backupDir) => { + return path.join(backupDir, BACKINFO_FILENAME); +}; + +const loadBackinfo = (backupDir) => { + const infoPath = getBackinfoPath(backupDir); + if (!fs.existsSync(infoPath)) { + return null; + } + try { + const content = fs.readFileSync(infoPath, 'utf-8'); + return JSON.parse(content); + } catch (e) { + return null; + } +}; + +const saveBackinfo = (backupDir, data) => { + const infoPath = getBackinfoPath(backupDir); + fs.writeFileSync(infoPath, JSON.stringify(data, null, 2), 'utf-8'); +}; + +const getEffectiveBackupPaths = (backupDir) => { + const info = loadBackinfo(backupDir); + if (info && Array.isArray(info.paths) && info.paths.length > 0) { + return { paths: info.paths, info }; + } + return { paths: BACKUP_PATHS, info }; +}; + +export const getBackupConfig = async (request, reply) => { + const backupDir = getBackupRootDir(); + let paths; + let lastBackupAt = null; + let lastRestoreAt = null; + + if (!fs.existsSync(backupDir)) { + paths = BACKUP_PATHS; + } else { + const result = getEffectiveBackupPaths(backupDir); + paths = result.paths; + if (result.info) { + lastBackupAt = result.info.lastBackupAt || null; + lastRestoreAt = result.info.lastRestoreAt || null; + } + } + return reply.send({ success: true, paths, lastBackupAt, lastRestoreAt }); +}; + +export const updateBackupConfig = async (request, reply) => { + try { + const { paths } = request.body; + if (!Array.isArray(paths)) { + return reply.code(400).send({ success: false, message: 'paths must be an array' }); + } + + const backupDir = getBackupRootDir(); + await fs.ensureDir(backupDir); + + const info = loadBackinfo(backupDir) || {}; + const backinfoData = { + ...info, + paths + }; + saveBackinfo(backupDir, backinfoData); + + return reply.send({ success: true, message: 'Backup configuration updated successfully', paths }); + } catch (error) { + request.log.error(`Update backup config failed: ${error.message}`); + return reply.code(500).send({ success: false, message: 'Update backup config failed: ' + error.message }); + } +}; + +export const resetBackupConfig = async (request, reply) => { + try { + const backupDir = getBackupRootDir(); + await fs.ensureDir(backupDir); + + const info = loadBackinfo(backupDir) || {}; + const backinfoData = { + ...info, + paths: BACKUP_PATHS + }; + saveBackinfo(backupDir, backinfoData); + + return reply.send({ success: true, message: 'Backup configuration reset to defaults', paths: BACKUP_PATHS }); + } catch (error) { + request.log.error(`Reset backup config failed: ${error.message}`); + return reply.code(500).send({ success: false, message: 'Reset backup config failed: ' + error.message }); + } +}; + +export const createBackup = async (request, reply) => { + if (process.env.VERCEL) { + return reply.code(403).send({ success: false, message: 'Vercel environment does not support backup' }); + } + try { + const backupDir = getBackupRootDir(); + await fs.ensureDir(backupDir); + + const { paths, info } = getEffectiveBackupPaths(backupDir); + const details = []; + + for (const item of paths) { + const srcPath = path.join(projectRootDir, item); + const destPath = path.join(backupDir, item); + + if (fs.existsSync(srcPath)) { + await fs.copy(srcPath, destPath, { overwrite: true }); + details.push(`Backed up: ${item}`); + } else { + details.push(`Skipped (not found): ${item}`); + } + } + + const now = new Date().toISOString(); + const customPaths = info && Array.isArray(info.paths) && info.paths.length > 0 ? info.paths : []; + const backinfoData = { + paths: customPaths, + lastBackupAt: now, + lastRestoreAt: info && info.lastRestoreAt ? info.lastRestoreAt : null + }; + saveBackinfo(backupDir, backinfoData); + + return reply.send({ success: true, message: 'Backup completed successfully', backupDir, details }); + } catch (error) { + request.log.error(`Backup failed: ${error.message}`); + return reply.code(500).send({ success: false, message: 'Backup failed: ' + error.message }); + } +}; + +export const restoreBackup = async (request, reply) => { + if (process.env.VERCEL) { + return reply.code(403).send({ success: false, message: 'Vercel environment does not support restore' }); + } + try { + const backupDir = getBackupRootDir(); + if (!fs.existsSync(backupDir)) { + return reply.code(404).send({ success: false, message: 'Backup directory not found' }); + } + + const { paths, info } = getEffectiveBackupPaths(backupDir); + const details = []; + + for (const item of paths) { + const srcPath = path.join(backupDir, item); + const destPath = path.join(projectRootDir, item); + + if (fs.existsSync(srcPath)) { + await fs.copy(srcPath, destPath, { overwrite: true }); + details.push(`Restored: ${item}`); + } else { + details.push(`Skipped (not found in backup): ${item}`); + } + } + + const now = new Date().toISOString(); + const customPaths = info && Array.isArray(info.paths) && info.paths.length > 0 ? info.paths : []; + const backinfoData = { + paths: customPaths, + lastBackupAt: info && info.lastBackupAt ? info.lastBackupAt : null, + lastRestoreAt: now + }; + saveBackinfo(backupDir, backinfoData); + + return reply.send({ success: true, message: 'Restore completed successfully', backupDir, details }); + } catch (error) { + request.log.error(`Restore failed: ${error.message}`); + return reply.code(500).send({ success: false, message: 'Restore failed: ' + error.message }); + } +}; diff --git a/controllers/admin/dbController.js b/controllers/admin/dbController.js new file mode 100644 index 00000000..baee64cb --- /dev/null +++ b/controllers/admin/dbController.js @@ -0,0 +1,117 @@ +/** + * 数据库查询控制器 + * 提供安全的只读 SQL 查询功能 + */ + +import sqlite3pkg from 'node-sqlite3-wasm'; +const { Database } = sqlite3pkg; +import path from 'path'; + +// 执行查询 +export async function executeQuery(req, reply) { + try { + const { sql, params } = req.body; + + if (!sql || !sql.trim()) { + return reply.code(400).send({ + error: 'SQL 查询不能为空' + }); + } + + // 只允许 SELECT 查询 + const trimmedSql = sql.trim().toLowerCase(); + if (!trimmedSql.startsWith('select') && !trimmedSql.startsWith('pragma')) { + return reply.code(403).send({ + error: '只允许 SELECT 查询' + }); + } + + // 额外安全检查 + const dangerousKeywords = [ + 'drop', 'delete', 'insert', 'update', 'alter', 'create', 'truncate', + 'replace', 'grant', 'revoke', 'lock', 'unlock', 'reindex', 'vacuum' + ]; + + for (const keyword of dangerousKeywords) { + // Check for keyword surrounded by whitespace or non-word characters + // This prevents matching "update_time" but matches "update table" or "update\ntable" + const regex = new RegExp(`(^|[\\s\\W])${keyword}([\\s\\W]|$)`, 'i'); + if (regex.test(trimmedSql)) { + return reply.code(403).send({ + error: `不允许使用 ${keyword.toUpperCase()} 语句` + }); + } + } + + const dbPath = path.join(process.cwd(), 'database.db'); + const db = new Database(dbPath); + + try { + const rows = db.all(sql, params || []); + return reply.send({ + success: true, + data: rows, + rows: rows.length + }); + } finally { + db.close(); + } + } catch (e) { + reply.code(500).send({ + error: `SQL 错误: ${e.message}` + }); + } +} + +// 获取表结构 +export async function getTables(req, reply) { + try { + const dbPath = path.join(process.cwd(), 'database.db'); + const db = new Database(dbPath); + + try { + const tables = db.all("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"); + return reply.send({ + success: true, + tables: tables.map(t => t.name) + }); + } finally { + db.close(); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 获取表结构 +export async function getTableSchema(req, reply) { + try { + const { table } = req.params; + + if (!table) { + return reply.code(400).send({ + error: '表名不能为空' + }); + } + + const dbPath = path.join(process.cwd(), 'database.db'); + const db = new Database(dbPath); + + try { + const schema = db.all(`PRAGMA table_info(${table})`); + return reply.send({ + success: true, + table, + columns: schema + }); + } finally { + db.close(); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} diff --git a/controllers/admin/filesController.js b/controllers/admin/filesController.js new file mode 100644 index 00000000..ad966014 --- /dev/null +++ b/controllers/admin/filesController.js @@ -0,0 +1,206 @@ +/** + * 文件管理控制器 + * 提供文件列表、读取、写入、删除功能 + */ + +import fs from '../../utils/fsWrapper.js'; +import path from 'path'; +import mime from 'mime-types'; + +// 列出目录 +export async function listDirectory(req, reply) { + try { + const dirPath = req.query.path || '.'; + + if (!isSafePath(dirPath)) { + return reply.code(403).send({ + error: '访问被拒绝' + }); + } + + const fullPath = path.join(process.cwd(), dirPath); + const files = await fs.readdir(fullPath, { withFileTypes: true }); + + const result = files.map(f => { + const isDir = f.isDirectory(); + return { + name: f.name, + path: dirPath === '.' ? f.name : `${dirPath}/${f.name}`, + isDirectory: isDir, + size: isDir ? undefined : 0 // fs.stat is expensive to do for all files, so omit size here unless needed + }; + }); + + // 异步获取文件大小 + for (let i = 0; i < result.length; i++) { + if (!result[i].isDirectory) { + try { + const stat = await fs.stat(path.join(fullPath, result[i].name)); + result[i].size = stat.size; + } catch (e) { + // Ignore stat errors + } + } + } + + return reply.send({ files: result }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 读取文件 +export async function readFile(req, reply) { + try { + const { path: filePath } = req.query; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(403).send({ + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + + if (!await fs.pathExists(fullPath)) { + return reply.code(404).send({ + error: '文件不存在' + }); + } + + const ext = path.extname(filePath).toLowerCase(); + const imageExts = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.bmp', '.tiff', '.tif']; + + if (imageExts.includes(ext)) { + // 图片文件 - 返回 base64 + const buffer = await fs.readFile(fullPath); + const base64 = buffer.toString('base64'); + const mimeType = mime.lookup(fullPath) || 'image/png'; + + return reply.send({ + type: 'image', + mimeType, + dataUrl: `data:${mimeType};base64,${base64}` + }); + } + + // 文本文件 + let content = await fs.readFile(fullPath, 'utf-8'); + + // 如果是 JS 文件,尝试解码 + if (ext === '.js') { + try { + const { decodeDsSource } = await import('../../utils/dsHelper.js'); + content = await decodeDsSource(content); + } catch (e) { + // 保持原样 + } + } + + return reply.send({ + type: 'text', + content + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 写入文件 +export async function writeFile(req, reply) { + try { + const { path: filePath, content } = req.body; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(403).send({ + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + + // 确保目录存在 + await fs.ensureDir(path.dirname(fullPath)); + + // 写入文件 + await fs.writeFile(fullPath, content, 'utf-8'); + + return reply.send({ + success: true, + message: '文件保存成功' + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 删除文件 +export async function deleteFile(req, reply) { + try { + const { path: filePath } = req.query; // in fastify, DELETE params might be in query or we can use body depending on client + + const fp = filePath || (req.body && req.body.path); + + if (!fp || !isSafePath(fp)) { + return reply.code(403).send({ + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), fp); + + if (!await fs.pathExists(fullPath)) { + return reply.code(404).send({ + error: '文件不存在' + }); + } + + await fs.remove(fullPath); + + return reply.send({ + success: true, + message: '文件删除成功' + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +function isSafePath(filePath) { + if (!filePath || typeof filePath !== 'string') return false; + + // Prevent absolute paths from user input directly + if (path.isAbsolute(filePath)) return false; + + // Resolve full path and check if it is within CWD + const fullPath = path.resolve(process.cwd(), filePath); + const cwd = process.cwd(); + + // Ensure the resolved path is inside the current working directory + if (!fullPath.startsWith(cwd)) return false; + + // Blacklist check for sensitive files/directories + const blacklist = [ + 'node_modules', + 'database.db', + '.git', + '.env', + 'package-lock.json', + 'yarn.lock' + ]; + + // Check if any part of the relative path matches the blacklist + // We check against the relative path to avoid matching parts of CWD + const relativePath = path.relative(cwd, fullPath); + if (blacklist.some(item => relativePath.includes(item))) return false; + + return true; +} diff --git a/controllers/admin/logsController.js b/controllers/admin/logsController.js new file mode 100644 index 00000000..a96197bc --- /dev/null +++ b/controllers/admin/logsController.js @@ -0,0 +1,96 @@ +/** + * 日志管理控制器 + * 提供日志读取 + */ + +import fs from '../../utils/fsWrapper.js'; +import path from 'path'; + +// 读取日志 +export async function getLogs(req, reply) { + try { + const lines = parseInt(req.query.lines) || 50; + const logDir = path.join(process.cwd(), 'logs'); + + if (!await fs.pathExists(logDir)) { + return reply.send({ + file: null, + content: '日志目录不存在' + }); + } + + const files = await fs.readdir(logDir); + const logFiles = files + .filter(f => f.endsWith('.log.txt')) + .sort() + .reverse(); + + if (logFiles.length === 0) { + return reply.send({ + file: null, + content: '没有日志文件' + }); + } + + const latestLog = path.join(logDir, logFiles[0]); + const content = await fs.readFile(latestLog, 'utf-8'); + const allLines = content.trim().split('\n'); + const lastLines = allLines.slice(-lines); + + return reply.send({ + file: logFiles[0], + content: lastLines.join('\n') + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + + + +async function streamLogs(socket, lines) { + try { + const logDir = path.join(process.cwd(), 'logs'); + const files = await fs.readdir(logDir); + const logFiles = files + .filter(f => f.endsWith('.log.txt')) + .sort() + .reverse(); + + if (logFiles.length === 0) { + socket.send(JSON.stringify({ + type: 'error', + message: '没有日志文件' + })); + return; + } + + const latestLog = path.join(logDir, logFiles[0]); + const content = await fs.readFile(latestLog, 'utf-8'); + const allLines = content.trim().split('\n'); + const lastLines = allLines.slice(-lines); + + // 发送现有日志 + for (const line of lastLines) { + if (socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ + type: 'log', + timestamp: Date.now(), + content: line + })); + } + } + + socket.send(JSON.stringify({ + type: 'end', + message: `已读取 ${lastLines.length} 行日志` + })); + } catch (e) { + socket.send(JSON.stringify({ + type: 'error', + message: e.message + })); + } +} diff --git a/controllers/admin/sourcesController.js b/controllers/admin/sourcesController.js new file mode 100644 index 00000000..a2254948 --- /dev/null +++ b/controllers/admin/sourcesController.js @@ -0,0 +1,360 @@ +/** + * 源管理控制器 + * 提供源列表、验证、语法检查、模板获取等功能 + */ + +import fs from '../../utils/fsWrapper.js'; +import path from 'path'; +import vm from 'vm'; +import { execFile } from 'child_process'; +import util from 'util'; + +const execFileAsync = util.promisify(execFile); + +// 列出所有源 +export async function listSources(req, reply) { + try { + const jsPath = path.join(process.cwd(), 'spider/js'); + const catvodPath = path.join(process.cwd(), 'spider/catvod'); + const phpPath = path.join(process.cwd(), 'spider/php'); + const pyPath = path.join(process.cwd(), 'spider/py'); + + let jsSources = []; + let catvodSources = []; + let phpSources = []; + let pySources = []; + + if (await fs.pathExists(jsPath)) { + jsSources = (await fs.readdir(jsPath)) + .filter(f => f.endsWith('.js') && !f.startsWith('_')) + .sort(); + } + + if (await fs.pathExists(catvodPath)) { + catvodSources = (await fs.readdir(catvodPath)) + .filter(f => f.endsWith('.js') && !f.startsWith('_')) + .sort(); + } + + if (await fs.pathExists(phpPath)) { + phpSources = (await fs.readdir(phpPath)) + .filter(f => f.endsWith('.php') && !f.startsWith('_')) + .sort(); + } + + if (await fs.pathExists(pyPath)) { + pySources = (await fs.readdir(pyPath)) + .filter(f => f.endsWith('.py') && !f.startsWith('_')) + .sort(); + } + + return reply.send({ + js: jsSources, + catvod: catvodSources, + php: phpSources, + py: pySources + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 验证源文件 +export async function validateSpider(req, reply) { + try { + const { path: filePath } = req.body; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(400).send({ + isValid: false, + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + if (!await fs.pathExists(fullPath)) { + return reply.code(404).send({ + isValid: false, + error: '文件不存在' + }); + } + + let code = await fs.readFile(fullPath, 'utf-8'); + + // PHP 文件验证 + if (filePath.endsWith('.php')) { + try { + await execFileAsync('php', ['-l', fullPath]); + return reply.send({ + isValid: true, + message: 'PHP 语法检查通过 (结构验证暂不支持)' + }); + } catch (e) { + return reply.send({ + isValid: false, + error: `PHP 语法错误: ${e.message}` + }); + } + } + + // Python 文件验证 + if (filePath.endsWith('.py')) { + try { + await execFileAsync('python', ['-m', 'py_compile', fullPath]); + return reply.send({ + isValid: true, + message: 'Python 语法检查通过 (结构验证暂不支持)' + }); + } catch (e) { + return reply.send({ + isValid: false, + error: `Python 语法错误: ${e.message}` + }); + } + } + + // 如果是 JS 文件,尝试解码 + if (filePath.endsWith('.js')) { + try { + const { decodeDsSource } = await import('../../utils/dsHelper.js'); + code = await decodeDsSource(code); + } catch (e) { + // 解码失败,使用原始代码 + } + } + + // 创建沙箱执行 + const sandbox = { + console: { log: () => {} }, + require: () => {}, + rule: null + }; + + try { + vm.createContext(sandbox); + new vm.Script(code).runInContext(sandbox); + + if (!sandbox.rule) { + return reply.send({ + isValid: false, + error: '源文件中缺少 rule 对象' + }); + } + + // 基本验证 + const required = ['title', 'host', 'url']; + const missing = required.filter(k => !sandbox.rule[k]); + + if (missing.length > 0) { + return reply.send({ + isValid: false, + error: `rule 对象缺少必填字段: ${missing.join(', ')}` + }); + } + + return reply.send({ + isValid: true, + message: '验证通过' + }); + } catch (e) { + return reply.send({ + isValid: false, + error: `执行错误: ${e.message}` + }); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 检查语法 +export async function checkSyntax(req, reply) { + try { + const { path: filePath } = req.body; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(400).send({ + isValid: false, + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + + // PHP 语法检查 + if (filePath.endsWith('.php')) { + try { + await execFileAsync('php', ['-l', fullPath]); + return reply.send({ + isValid: true, + message: 'PHP 语法检查通过' + }); + } catch (e) { + return reply.code(400).send({ + isValid: false, + error: `PHP 语法错误: ${e.message}` + }); + } + } + + // Python 语法检查 + if (filePath.endsWith('.py')) { + try { + await execAsync(`python -m py_compile "${fullPath}"`); + return reply.send({ + isValid: true, + message: 'Python 语法检查通过' + }); + } catch (e) { + return reply.code(400).send({ + isValid: false, + error: `Python 语法错误: ${e.message}` + }); + } + } + + let code = await fs.readFile(fullPath, 'utf-8'); + + // 如果是 JS 文件,尝试解码 + if (filePath.endsWith('.js')) { + try { + const { decodeDsSource } = await import('../../utils/dsHelper.js'); + code = await decodeDsSource(code); + } catch (e) { + // 解码失败,使用原始代码 + } + } + + try { + new vm.Script(code); + return reply.send({ + isValid: true, + message: '语法检查通过' + }); + } catch (e) { + return reply.code(400).send({ + isValid: false, + error: `语法错误: ${e.message}` + }); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 获取模板 +export async function getTemplate(req, reply) { + const template = `/* +* @File : drpy-node spider template +* @Author : user +* @Date : ${new Date().toISOString().split('T')[0]} +* @Comments : +*/ + +var rule = { + // 影视|漫画|小说 + 类型: '影视', + // 源标题 + title: 'Site Name', + // 源主域名 + host: 'https://example.com', + // 源主页链接 + homeUrl: '/latest/', + // 源一级列表链接 + url: '/category/fyclass/page/fypage', + // 源搜索链接 + searchUrl: '/search?wd=**&pg=fypage', + // 允许搜索、允许快搜、允许筛选 + searchable: 2, + quickSearch: 0, + filterable: 1, + // 请求头 + headers: { + 'User-Agent': 'MOBILE_UA', + }, + // 超时时间 + timeout: 5000, + // 静态分类 + class_name: '电影&电视剧&综艺&动漫', + class_url: '1&2&3&4', + + // 是否需要调用免嗅 + play_parse: true, + // 免嗅lazy执行函数 + lazy: '', + // 首页推荐数量 + limit: 6, + // 是否双层列表 + double: true, + + // 推荐列表 + 推荐: '.recommend .item;a&&title;img&&src;.remarks&&Text;a&&href', + // 一级列表 + 一级: '.list .item;a&&title;img&&src;.remarks&&Text;a&&href', + // 二级详情 + 二级: { + "title": "h1&&Text", + "img": ".poster img&&src", + "desc": ".desc&&Text", + "content": ".content&&Text", + "tabs": ".tabs span", + "lists": ".playlists ul" + }, + // 搜索 + 搜索: '.search-result .item;a&&title;img&&src;.remarks&&Text;a&&href', +}`; + + return reply.send({ template }); +} + +export async function getLibsInfo(req, reply) { + const info = { + globalObjects: [ + "request(url, options) - HTTP Request", + "post(url, options) - HTTP POST Request", + "pdfa(html, rule) - Parse List", + "pdfh(html, rule) - Parse Single Node", + "pd(html, rule) - Parse URL", + "setItem(k, v) - Persistent storage", + "getItem(k) - Retrieve storage", + "clearItem(k) - Delete storage", + "urljoin(base, path) - Resolve URL" + ], + parsingRules: [ + "Format: selector;attr1;attr2...", + "pdfa (list): Returns array", + "pdfh (single): Returns string", + "pd (url): Returns resolved URL string", + "Special Attrs: Text, Html, href, src, style, data-*", + "Syntax: && (nested), || (backup), :eq(n) (index), * (all)" + ] + }; + return reply.send(info); +} + +function isSafePath(filePath) { + if (!filePath || typeof filePath !== 'string') return false; + + // Prevent absolute paths from user input directly + if (path.isAbsolute(filePath)) return false; + + // Resolve full path and check if it is within CWD + const fullPath = path.resolve(process.cwd(), filePath); + const cwd = process.cwd(); + + // Ensure the resolved path is inside the current working directory + if (!fullPath.startsWith(cwd)) return false; + + // Blacklist check + const blacklist = ['node_modules', 'database.db', '.git', '.env']; + const relativePath = path.relative(cwd, fullPath); + if (blacklist.some(item => relativePath.includes(item))) return false; + + return true; +} diff --git a/controllers/admin/subController.js b/controllers/admin/subController.js new file mode 100644 index 00000000..0eaca881 --- /dev/null +++ b/controllers/admin/subController.js @@ -0,0 +1,78 @@ +import path from 'path'; +import fs from '../../utils/fsWrapper.js'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const projectRootDir = path.resolve(__dirname, '../../'); +const subDir = path.join(projectRootDir, 'public/sub'); + +// Ensure sub directory exists +fs.ensureDirSync(subDir); + +export const getSubFiles = async (request, reply) => { + try { + const files = await fs.readdir(subDir); + const result = []; + for (const file of files) { + const filePath = path.join(subDir, file); + const stats = await fs.stat(filePath); + if (stats.isFile()) { + result.push({ + name: file, + size: stats.size, + mtime: stats.mtime + }); + } + } + return reply.send({ success: true, data: result }); + } catch (error) { + request.log.error(error); + return reply.code(500).send({ success: false, message: error.message }); + } +}; + +export const getSubFileContent = async (request, reply) => { + const { name } = request.query; + if (!name) { + return reply.code(400).send({ success: false, message: 'Filename is required' }); + } + + // Basic security check to prevent directory traversal + if (name.includes('..') || name.includes('/') || name.includes('\\')) { + return reply.code(400).send({ success: false, message: 'Invalid filename' }); + } + + const filePath = path.join(subDir, name); + try { + if (!await fs.pathExists(filePath)) { + return reply.code(404).send({ success: false, message: 'File not found' }); + } + const content = await fs.readFile(filePath, 'utf-8'); + return reply.send({ success: true, data: content }); + } catch (error) { + request.log.error(error); + return reply.code(500).send({ success: false, message: error.message }); + } +}; + +export const saveSubFileContent = async (request, reply) => { + const { name, content } = request.body; + if (!name) { + return reply.code(400).send({ success: false, message: 'Filename is required' }); + } + + // Basic security check + if (name.includes('..') || name.includes('/') || name.includes('\\')) { + return reply.code(400).send({ success: false, message: 'Invalid filename' }); + } + + const filePath = path.join(subDir, name); + try { + await fs.writeFile(filePath, content, 'utf-8'); + return reply.send({ success: true, message: 'File saved successfully' }); + } catch (error) { + request.log.error(error); + return reply.code(500).send({ success: false, message: error.message }); + } +}; diff --git a/controllers/admin/systemController.js b/controllers/admin/systemController.js new file mode 100644 index 00000000..a0768c3a --- /dev/null +++ b/controllers/admin/systemController.js @@ -0,0 +1,205 @@ +/** + * 系统管理控制器 + * 提供健康检查、服务重启等系统级功能 + */ + +import os from 'os'; +import { exec } from 'child_process'; +import util from 'util'; +import path from 'path'; +import fs from '../../utils/fsWrapper.js'; + +const execPromise = util.promisify(exec); + +// 健康检查 +export async function getHealth(req, reply) { + try { + const uptime = process.uptime(); + const memory = process.memoryUsage(); + const packageJson = await fs.readJson(path.join(process.cwd(), 'package.json')); + + return reply.send({ + status: 'ok', + uptime: Math.floor(uptime), + memory: { + used: Math.round(memory.heapUsed / 1024 / 1024), + total: Math.round(memory.heapTotal / 1024 / 1024), + rss: Math.round(memory.rss / 1024 / 1024) + }, + version: packageJson.version, + platform: { + arch: os.arch(), + platform: os.platform(), + nodeVersion: process.version + }, + timestamp: Date.now() + }); + } catch (e) { + reply.code(500).send({ + status: 'error', + error: e.message + }); + } +} + +// 服务重启 +export async function restartService(req, reply) { + try { + // 检查是否在 PM2 环境运行 + try { + await execPromise('pm2 restart drpys'); + return reply.send({ + success: true, + message: '服务已通过 PM2 重启' + }); + } catch (pm2Error) { + return reply.send({ + success: false, + message: '当前未使用 PM2 运行。请在终端中手动重启服务:\n1. 按 Ctrl+C 停止当前服务\n2. 运行 npm run dev 重新启动' + }); + } + } catch (e) { + reply.code(500).send({ + success: false, + error: e.message + }); + } +} + +// API 文档 +export async function getApiDocs(req, reply) { + const apiDocs = [ + { + category: "系统管理", + endpoints: [ + { + path: "/api/admin/health", + method: "GET", + description: "获取系统健康状态,包括内存使用、运行时间、版本等信息" + }, + { + path: "/api/admin/restart", + method: "POST", + description: "尝试重启服务(仅在 PM2 环境下有效)" + }, + { + path: "/api/admin/docs", + method: "GET", + description: "获取 API 文档列表" + } + ] + }, + { + category: "日志管理", + endpoints: [ + { + path: "/api/admin/logs", + method: "GET", + description: "获取最近的系统日志" + }, + { + path: "/ws", + method: "WS", + description: "WebSocket 实时日志流连接端点(全局)" + } + ] + }, + { + category: "配置管理", + endpoints: [ + { + path: "/api/admin/config", + method: "GET", + description: "获取系统配置,支持通过 key 参数获取特定配置项" + }, + { + path: "/api/admin/config", + method: "POST", + description: "更新系统配置" + }, + { + path: "/api/admin/env", + method: "GET", + description: "获取关键环境变量配置" + } + ] + }, + { + category: "源管理", + endpoints: [ + { + path: "/api/admin/sources", + method: "GET", + description: "获取所有 JS 和 CatVod 源列表" + }, + { + path: "/api/admin/sources/validate", + method: "POST", + description: "验证源文件的格式和必要字段" + }, + { + path: "/api/admin/sources/syntax", + method: "POST", + description: "检查源文件的语法正确性" + }, + { + path: "/api/admin/sources/template", + method: "GET", + description: "获取标准源文件模板" + }, + { + path: "/api/admin/sources/libs", + method: "GET", + description: "获取爬虫相关库函数和解析规则说明" + } + ] + }, + { + category: "文件管理", + endpoints: [ + { + path: "/api/admin/files/list", + method: "GET", + description: "列出指定目录下的文件和文件夹" + }, + { + path: "/api/admin/files/read", + method: "GET", + description: "读取指定文件的内容" + }, + { + path: "/api/admin/files/write", + method: "POST", + description: "写入内容到指定文件" + }, + { + path: "/api/admin/files/delete", + method: "DELETE", + description: "删除指定的文件" + } + ] + }, + { + category: "数据库管理", + endpoints: [ + { + path: "/api/admin/db/query", + method: "POST", + description: "执行 SQL 查询语句" + }, + { + path: "/api/admin/db/tables", + method: "GET", + description: "获取数据库所有表名" + }, + { + path: "/api/admin/db/tables/:table/schema", + method: "GET", + description: "获取指定表的结构定义" + } + ] + } + ]; + + return reply.send(apiDocs); +} diff --git a/controllers/docs.js b/controllers/docs.js index 723a2f13..62394779 100644 --- a/controllers/docs.js +++ b/controllers/docs.js @@ -6,8 +6,8 @@ import path from 'path'; import {existsSync, readFileSync} from 'fs'; import {getMimeType} from '../utils/mime-type.js'; -// import '../utils/marked.min.js'; // Markdown解析库 -import { marked } from "marked"; +import '../utils/marked.min.js'; // Markdown解析库 +// import { marked } from "marked"; import {validateBasicAuth} from "../utils/api_validate.js"; /** diff --git a/controllers/fastify-spa-routes.js b/controllers/fastify-spa-routes.js index 1ee3c681..01c175f6 100644 --- a/controllers/fastify-spa-routes.js +++ b/controllers/fastify-spa-routes.js @@ -13,7 +13,7 @@ async function addSPARoutes(fastify, options) { for (const appName of spaApps) { // 1. 处理根路径重定向 fastify.get(`/apps/${appName}`, async (request, reply) => { - return reply.redirect(301, `/apps/${appName}/`); + return reply.redirect(`/apps/${appName}/`, 301); }); // 2. 处理应用根路径 @@ -35,15 +35,16 @@ async function addSPARoutes(fastify, options) { // 3. 设置404处理器来处理SPA路由回退 fastify.setNotFoundHandler(async (request, reply) => { const url = request.url; + const pathname = url.split('?')[0]; // 检查是否是SPA应用的路由请求 for (const appName of spaApps) { const appPrefix = `/apps/${appName}/`; - if (url.startsWith(appPrefix)) { + if (pathname.startsWith(appPrefix)) { // 检查是否是静态资源请求(有文件扩展名) - const urlPath = url.replace(appPrefix, ''); - const hasExtension = /\.[a-zA-Z0-9]+(\?.*)?$/.test(urlPath); + const urlPath = pathname.replace(appPrefix, ''); + const hasExtension = /\.[a-zA-Z0-9]+$/.test(urlPath); if (!hasExtension) { // 没有扩展名,可能是Vue路由,返回index.html diff --git a/controllers/index.js b/controllers/index.js index aa6f2853..a3324bfa 100644 --- a/controllers/index.js +++ b/controllers/index.js @@ -24,6 +24,7 @@ import m3u8ProxyController from './m3u8-proxy.js'; import unifiedProxyController from './unified-proxy.js'; import githubController from './github.js'; import websocketServerController from "./websocketServer.js"; +import adminController from './admin.js'; export const registerRoutes = (fastify, options) => { fastify.register(formBody); @@ -52,6 +53,7 @@ export const registerRoutes = (fastify, options) => { fastify.register(m3u8ProxyController, options); fastify.register(unifiedProxyController, options); fastify.register(githubController, options); + fastify.register(adminController, options); }; export const registerWsRoutes = (wsApp, options) => { diff --git a/controllers/root.js b/controllers/root.js index 6194cd16..30526ff0 100644 --- a/controllers/root.js +++ b/controllers/root.js @@ -1,7 +1,7 @@ import path from 'path'; import {readdirSync, readFileSync, writeFileSync, existsSync, createReadStream} from 'fs'; -// import '../utils/marked.min.js'; -import { marked } from "marked"; +import '../utils/marked.min.js'; +// import { marked } from "marked"; import {computeHash} from '../utils/utils.js'; import {validateBasicAuth} from "../utils/api_validate.js"; import {daemon} from "../utils/daemonManager.js"; diff --git a/controllers/static.js b/controllers/static.js index 66493679..4a1a8cf9 100644 --- a/controllers/static.js +++ b/controllers/static.js @@ -46,7 +46,7 @@ export default (fastify, options, done) => { fastify.register(addSPARoutes, { appsDir: options.appsDir, - spaApps: ['drplayer'] // 只有drplayer需要SPA路由支持 + spaApps: ['drplayer', 'admin'] // 支持SPA路由的应用 }); // 注册JSON配置文件服务 - 用于存放各种JSON格式的配置文件 diff --git a/controllers/websocket.js b/controllers/websocket.js index e5be100c..35ae8570 100644 --- a/controllers/websocket.js +++ b/controllers/websocket.js @@ -10,6 +10,15 @@ import {toBeijingTime} from "../utils/datetime-format.js"; // WebSocket 客户端管理 const wsClients = new Set(); +// 导出客户端管理函数 +export function addClient(client) { + wsClients.add(client); +} + +export function removeClient(client) { + wsClients.delete(client); +} + // 需要拦截的console方法列表 const CONSOLE_METHODS = [ 'log', 'error', 'warn', 'info', 'debug', diff --git a/data/source-checker/report.json b/data/source-checker/report.json index 69685278..4f8aeb5a 100644 --- a/data/source-checker/report.json +++ b/data/source-checker/report.json @@ -1,10 +1,10 @@ { - "exportTime": "2026-03-13T12:37:39.210Z", + "exportTime": "2026-03-14T05:07:55.462Z", "configUrl": "http://localhost:5757/config/1?sub=all&healthy=0&pwd=dzyyds", "totalSources": 299, "summary": { - "success": 247, - "error": 52, + "success": 249, + "error": 50, "pending": 0 }, "sources": [ @@ -17,10 +17,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%AE%BE%E7%BD%AE%E4%B8%AD%E5%BF%83?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -32,10 +30,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A4%AE%E8%A7%86%E5%A4%A7%E5%85%A8[%E5%AE%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -47,57 +43,34 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%85%BE%E4%BA%91%E9%A9%BE%E9%9B%BE[%E5%AE%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_IPTV四川[官]", - "name": "IPTV四川[官](DS)", + "key": "drpyS_IPTV直播", + "name": "IPTV直播(DS)", "api": "http://localhost:5757/api/直播转点播[合]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9B%B4%E6%92%AD%E8%BD%AC%E7%82%B9%E6%92%AD[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTz8ksSzVKzi3WLU7WAwkAANFSeAoYAAAA" - }, - "checkTime": "2026-03-13T12:37:39.210Z", - "manuallyMarked": false - }, - { - "key": "drpyS_番茄小说[书]", - "name": "番茄小说[书](DS)", - "api": "http://localhost:5757/api/番茄小说[书]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_番茄小说 ᵈᶻ[书]", - "name": "番茄小说 ᵈᶻ[书](PHP)", - "api": "http://localhost:5757/api/番茄小说 ᵈᶻ[书]?do=php&pwd=dzyyds", + "key": "drpyS_人人影视[优]", + "name": "人人影视[优](DS)", + "api": "http://localhost:5757/api/人人影视[优]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E5%B0%8F%E8%AF%B4%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E5%B0%8F%E8%AF%B4%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -108,72 +81,35 @@ "searchable": 1, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9F%AD%E5%89%A7%E8%81%9A%E5%90%88[%E7%9F%AD]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%9F%AD%E5%89%A7%E8%81%9A%E5%90%88[%E7%9F%AD]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_IPTV直播", - "name": "IPTV直播(DS)", + "key": "drpyS_IPTV四川[官]", + "name": "IPTV四川[官](DS)", "api": "http://localhost:5757/api/直播转点播[合]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9B%B4%E6%92%AD%E8%BD%AC%E7%82%B9%E6%92%AD[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTz8ksSzVKzi3WA%2FEAuuBHLxUAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.210Z", - "manuallyMarked": false - }, - { - "key": "drpyS_Emby[优]", - "name": "Emby[优](DS)", - "api": "http://localhost:5757/api/Emby[优]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Emby[%E4%BC%98]?pwd=dzyyds&extend=H4sIAAAAAAAAAx3NQU7DMBCF4bt4Tdyxx4k9uUHXSOxn7HFrQZOqcZEAcXcS9t97%2F4%2B5rls3s7n2ft%2Fm00lv8mWFl8vz1mxm82Kemz7OZScJNE0uS60OA0plEC1ZOaZEo5DbbV%2FfdTmogLiJWaOmAJgFiyOaSJLPSOB3WvSzZf0%2FVvYxc40D8eiG4IEGcTwOGINUhOxrLfsifzRd%2Bps%2BtrYekWDJgsWje%2BeLvrZvNTPC7x9iYTnC1AAAAA%3D%3D" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_人人影视[优]", - "name": "人人影视[优](DS)", - "api": "http://localhost:5757/api/人人影视[优]?pwd=dzyyds", + "key": "drpyS_剧海影视[优]", + "name": "剧海影视[优](DS)", + "api": "http://localhost:5757/api/剧海影视[优]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%BA%BA%E4%BA%BA%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", - "manuallyMarked": false - }, - { - "key": "drpyS_木兮[优]", - "name": "木兮[优](DS)", - "api": "http://localhost:5757/api/木兮[优]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%9C%A8%E5%85%AE[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -185,25 +121,21 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%98%9F%E8%BE%B0%E5%BD%B1%E9%99%A2[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_剧海影视[优]", - "name": "剧海影视[优](DS)", - "api": "http://localhost:5757/api/剧海影视[优]?pwd=dzyyds", + "key": "drpyS_木兮[优]", + "name": "木兮[优](DS)", + "api": "http://localhost:5757/api/木兮[优]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%89%A7%E6%B5%B7%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -215,10 +147,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%AF%92%E8%88%8C%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -230,10 +160,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%B0%8F%E8%8B%B9%E6%9E%9C[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -245,57 +173,34 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%A8%B1%E8%8A%B1%E5%8A%A8%E6%BC%AB[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_TG频道[优]", - "name": "TG频道[优](DS)", - "api": "http://localhost:5757/api/TG频道?pwd=dzyyds", + "key": "drpyS_热播影视[优]", + "name": "热播影视[优](DS)", + "api": "http://localhost:5757/api/热播影视[优]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/TG%E9%A2%91%E9%81%93?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTD3F%2FuWjiy8bJL1t7n%2B9dpwcSAwBCcG9sGwAAAA%3D%3D", - "category": "http://localhost:5757/api/TG%E9%A2%91%E9%81%93?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTD3F%2FuWjiy8bJL1t7n%2B9dpwcSAwBCcG9sGwAAAA%3D%3D" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_短剧频道[优]", - "name": "短剧频道[优](DS)", - "api": "http://localhost:5757/api/TG频道?pwd=dzyyds", + "key": "drpyS_泥视频[优]", + "name": "泥视频[优](DS)", + "api": "http://localhost:5757/api/泥视频[优]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/TG%E9%A2%91%E9%81%93?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTD3F%2FPn%2Ft087lLxdNfNk4WQ8kBgDLqEoeGwAAAA%3D%3D", - "category": "http://localhost:5757/api/TG%E9%A2%91%E9%81%93?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTD3F%2FPn%2Ft087lLxdNfNk4WQ8kBgDLqEoeGwAAAA%3D%3D" - }, - "checkTime": "2026-03-13T12:37:39.210Z", - "manuallyMarked": false - }, - { - "key": "drpyS_七味[优]", - "name": "七味[优](DS)", - "api": "http://localhost:5757/api/七味[优]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%B8%83%E5%91%B3[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -307,25 +212,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8B%AC%E6%92%AD%E5%BA%93[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", - "manuallyMarked": false - }, - { - "key": "drpyS_耐看点播[优]", - "name": "耐看点播[优](DS)", - "api": "http://localhost:5757/api/耐看点播[优]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%80%90%E7%9C%8B%E7%82%B9%E6%92%AD[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -337,56 +225,47 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%B2%A4%E6%BC%AB%E4%B9%8B%E5%AE%B6[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_泥视频[优]", - "name": "泥视频[优](DS)", - "api": "http://localhost:5757/api/泥视频[优]?pwd=dzyyds", + "key": "drpyS_耐看点播[优]", + "name": "耐看点播[优](DS)", + "api": "http://localhost:5757/api/耐看点播[优]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%B3%A5%E8%A7%86%E9%A2%91[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_瓜子[优]", - "name": "瓜子[优](DS)", - "api": "http://localhost:5757/api/瓜子[优]?pwd=dzyyds", + "key": "drpyS_永乐视频[优]", + "name": "永乐视频[优](DS)", + "api": "http://localhost:5757/api/永乐视频[优]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%93%9C%E5%AD%90[%E4%BC%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%93%9C%E5%AD%90[%E4%BC%98]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_荐片[优]", - "name": "荐片[优](DS)", - "api": "http://localhost:5757/api/荐片[优]?pwd=dzyyds", + "key": "drpyS_麻雀视频[优]", + "name": "麻雀视频[优](DS)", + "api": "http://localhost:5757/api/麻雀视频[优]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%8D%90%E7%89%87[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -398,70 +277,60 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%A3%9E%E5%BF%ABTV[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_热播影视[优]", - "name": "热播影视[优](DS)", - "api": "http://localhost:5757/api/热播影视[优]?pwd=dzyyds", + "key": "drpyS_追新影视[优]", + "name": "追新影视[优](DS)", + "api": "http://localhost:5757/api/追新影视[优]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%83%AD%E6%92%AD%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_追新影视[优]", - "name": "追新影视[优](DS)", - "api": "http://localhost:5757/api/追新影视[优]?pwd=dzyyds", + "key": "drpyS_傻样[盘]", + "name": "傻样[盘](DS)", + "api": "http://localhost:5757/api/傻样[盘]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%BF%BD%E6%96%B0%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_永乐视频[优]", - "name": "永乐视频[优](DS)", - "api": "http://localhost:5757/api/永乐视频[优]?pwd=dzyyds", + "key": "drpyS_夸克社[盘]", + "name": "夸克社[盘](DS)", + "api": "http://localhost:5757/api/夸克社[盘]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%B0%B8%E4%B9%90%E8%A7%86%E9%A2%91[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_麻雀视频[优]", - "name": "麻雀视频[优](DS)", - "api": "http://localhost:5757/api/麻雀视频[优]?pwd=dzyyds", + "key": "drpyS_木偶[盘]", + "name": "木偶[盘](DS)", + "api": "http://localhost:5757/api/木偶[盘]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%BA%BB%E9%9B%80%E8%A7%86%E9%A2%91[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -473,381 +342,320 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A4%9A%E5%A4%9A[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_夸克影视[盘]", - "name": "夸克影视[盘](DS)", - "api": "http://localhost:5757/api/夸克影视[盘]?pwd=dzyyds", + "key": "drpyS_Emby[优]", + "name": "Emby[优](DS)", + "api": "http://localhost:5757/api/Emby[优]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A4%B8%E5%85%8B%E5%BD%B1%E8%A7%86[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_UC分享[盘]", - "name": "UC分享[盘](DS)", - "api": "http://localhost:5757/api/UC分享?pwd=dzyyds", + "key": "drpyS_爱看资源[盘]", + "name": "爱看资源[盘](DS)", + "api": "http://localhost:5757/api/爱看资源[盘]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "手动标记为正常", - "testUrls": { - "home": "http://localhost:5757/api/UC%E5%88%86%E4%BA%AB?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTD3V%2B2tH2ZNdqPRAPAKubOwMVAAAA", - "category": "http://localhost:5757/api/UC%E5%88%86%E4%BA%AB?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTD3V%2B2tH2ZNdqPRAPAKubOwMVAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": true - }, - { - "key": "drpyS_WebDav影视[盘]", - "name": "WebDav影视[盘](DS)", - "api": "http://localhost:5757/api/webdav影视[盘]?pwd=dzyyds", - "type": 4, - "searchable": 0, - "lang": "ds", - "status": "success", - "message": "手动标记为正常", - "testUrls": { - "home": "http://localhost:5757/api/webdav%E5%BD%B1%E8%A7%86[%E7%9B%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTL09NSkks0wOxASthelgTAAAA", - "category": "http://localhost:5757/api/webdav%E5%BD%B1%E8%A7%86[%E7%9B%98]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTL09NSkks0wOxASthelgTAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": true + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false }, { - "key": "drpyS_傻样[盘]", - "name": "傻样[盘](DS)", - "api": "http://localhost:5757/api/傻样[盘]?pwd=dzyyds", + "key": "drpyS_短剧网[盘]", + "name": "短剧网[盘](DS)", + "api": "http://localhost:5757/api/短剧网[盘]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%82%BB%E6%A0%B7[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_FTP[盘]", - "name": "FTP[盘](DS)", - "api": "http://localhost:5757/api/ftp[盘]?pwd=dzyyds", + "key": "drpyS_盘Ta[盘]", + "name": "盘Ta[盘](DS)", + "api": "http://localhost:5757/api/盘Ta[盘]?pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 1, "lang": "ds", "status": "success", - "message": "手动标记为正常", - "testUrls": { - "home": "http://localhost:5757/api/ftp[%E7%9B%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTTysp0AMxAIzjQSIQAAAA", - "category": "http://localhost:5757/api/ftp[%E7%9B%98]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTTysp0AMxAIzjQSIQAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": true + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false }, { - "key": "drpyS_WebDav[盘]", - "name": "WebDav[盘](DS)", - "api": "http://localhost:5757/api/webdav[盘]?pwd=dzyyds", + "key": "drpyS_立播[盘]", + "name": "立播[盘](DS)", + "api": "http://localhost:5757/api/立播[盘]?pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 1, "lang": "ds", "status": "success", - "message": "手动标记为正常", - "testUrls": { - "home": "http://localhost:5757/api/webdav[%E7%9B%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTL09NSkks0wOxASthelgTAAAA", - "category": "http://localhost:5757/api/webdav[%E7%9B%98]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTL09NSkks0wOxASthelgTAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": true + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false }, { - "key": "drpyS_WebDavZn[盘]", - "name": "WebDavZn[盘](DS)", - "api": "http://localhost:5757/api/webdav[盘]?pwd=dzyyds", + "key": "drpyS_欧哥[盘]", + "name": "欧哥[盘](DS)", + "api": "http://localhost:5757/api/欧哥[盘]?pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 1, "lang": "ds", "status": "success", - "message": "手动标记为正常", - "testUrls": { - "home": "http://localhost:5757/api/webdav[%E7%9B%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTL09NSkkse7p344vlbXogEQDz64JLGQAAAA%3D%3D", - "category": "http://localhost:5757/api/webdav[%E7%9B%98]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTL09NSkkse7p344vlbXogEQDz64JLGQAAAA%3D%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": true + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false }, { - "key": "drpyS_夸克社[盘]", - "name": "夸克社[盘](DS)", - "api": "http://localhost:5757/api/夸克社[盘]?pwd=dzyyds", + "key": "drpyS_番茄小说[书]", + "name": "番茄小说[书](DS)", + "api": "http://localhost:5757/api/番茄小说[书]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A4%B8%E5%85%8B%E7%A4%BE[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_木偶[盘]", - "name": "木偶[盘](DS)", - "api": "http://localhost:5757/api/木偶[盘]?pwd=dzyyds", + "key": "drpyS_荐片[优]", + "name": "荐片[优](DS)", + "api": "http://localhost:5757/api/荐片[优]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%9C%A8%E5%81%B6[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_短剧网[盘]", - "name": "短剧网[盘](DS)", - "api": "http://localhost:5757/api/短剧网[盘]?pwd=dzyyds", + "key": "php_番茄小说 ᵈᶻ[书]", + "name": "番茄小说 ᵈᶻ[书](PHP)", + "api": "http://localhost:5757/api/番茄小说 ᵈᶻ[书]?do=php&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "php", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9F%AD%E5%89%A7%E7%BD%91[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_盘Ta[盘]", - "name": "盘Ta[盘](DS)", - "api": "http://localhost:5757/api/盘Ta[盘]?pwd=dzyyds", + "key": "drpyS_TG频道[优]", + "name": "TG频道[优](DS)", + "api": "http://localhost:5757/api/TG频道?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9B%98Ta[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_爱看资源[盘]", - "name": "爱看资源[盘](DS)", - "api": "http://localhost:5757/api/爱看资源[盘]?pwd=dzyyds", + "key": "drpyS_瓜子[优]", + "name": "瓜子[优](DS)", + "api": "http://localhost:5757/api/瓜子[优]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E7%9C%8B%E8%B5%84%E6%BA%90[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_立播[盘]", - "name": "立播[盘](DS)", - "api": "http://localhost:5757/api/立播[盘]?pwd=dzyyds", + "key": "drpyS_短剧频道[优]", + "name": "短剧频道[优](DS)", + "api": "http://localhost:5757/api/TG频道?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%AB%8B%E6%92%AD[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_欧哥[盘]", - "name": "欧哥[盘](DS)", - "api": "http://localhost:5757/api/欧哥[盘]?pwd=dzyyds", + "key": "drpyS_蜡笔ᵐ[盘]", + "name": "蜡笔ᵐ[盘](DS)", + "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%AC%A7%E5%93%A5[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_蜡笔ᵐ[盘]", - "name": "蜡笔ᵐ[盘](DS)", - "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", + "key": "drpyS_夸克影视[盘]", + "name": "夸克影视[盘](DS)", + "api": "http://localhost:5757/api/夸克影视[盘]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5MWfh8zVTAI8Mua8gAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_虎斑ᵐ[盘]", - "name": "虎斑ᵐ[盘](DS)", - "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", + "key": "drpyS_UC分享[盘]", + "name": "UC分享[盘](DS)", + "api": "http://localhost:5757/api/UC分享?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5MbPv2bSJAFZ8CcsgAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "drpyS_至臻[盘]", - "name": "至臻[盘](DS)", - "api": "http://localhost:5757/api/至臻[盘]?pwd=dzyyds", + "key": "drpyS_WebDav影视[盘]", + "name": "WebDav影视[盘](DS)", + "api": "http://localhost:5757/api/webdav影视[盘]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 0, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%87%B3%E8%87%BB[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "drpyS_木偶ᵐ[盘]", - "name": "木偶ᵐ[盘](DS)", - "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", + "key": "drpyS_七味[优]", + "name": "七味[优](DS)", + "api": "http://localhost:5757/api/七味[优]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5NmfF08ZtABDtdR4gAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "3/4 接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_虎斑[盘]", - "name": "虎斑[盘](DS)", - "api": "http://localhost:5757/api/虎斑[盘]?pwd=dzyyds", + "key": "drpyS_WebDav[盘]", + "name": "WebDav[盘](DS)", + "api": "http://localhost:5757/api/webdav[盘]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 0, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%99%8E%E6%96%91[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "drpyS_至臻ᵐ[盘]", - "name": "至臻ᵐ[盘](DS)", - "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", + "key": "drpyS_WebDavZn[盘]", + "name": "WebDavZn[盘](DS)", + "api": "http://localhost:5757/api/webdav[盘]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 0, "lang": "ds", "status": "success", - "message": "3/4 接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF50b75RftuAAWyZJQgAAAA", - "category": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF50b75RftuAAWyZJQgAAAA", - "search": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF50b75RftuAAWyZJQgAAAA", - "detail": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=detail&ids=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF50b75RftuAAWyZJQgAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "drpyS_雷鲸小站[盘]", - "name": "雷鲸小站[盘](DS)", - "api": "http://localhost:5757/api/雷鲸小站[盘]?pwd=dzyyds", + "key": "drpyS_FTP[盘]", + "name": "FTP[盘](DS)", + "api": "http://localhost:5757/api/ftp[盘]?pwd=dzyyds", + "type": 4, + "searchable": 0, + "lang": "ds", + "status": "success", + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true + }, + { + "key": "drpyS_至臻[盘]", + "name": "至臻[盘](DS)", + "api": "http://localhost:5757/api/至臻[盘]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9B%B7%E9%B2%B8%E5%B0%8F%E7%AB%99[%E7%9B%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_多多ᵐ[盘]", - "name": "多多ᵐ[盘](DS)", - "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", + "key": "drpyS_虎斑[盘]", + "name": "虎斑[盘](DS)", + "api": "http://localhost:5757/api/虎斑[盘]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5umQWEAEA1%2BC5iSAAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_玩偶ᵐ[盘]", - "name": "玩偶ᵐ[盘](DS)", + "key": "drpyS_木偶ᵐ[盘]", + "name": "木偶ᵐ[盘](DS)", "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF53rfyaeM2FUMAXj8hgiIAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_欧歌ᵐ[盘]", - "name": "欧歌ᵐ[盘](DS)", + "key": "drpyS_多多ᵐ[盘]", + "name": "多多ᵐ[盘](DS)", "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", - "message": "4/4 接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5tmb5s7U9AIVJTBogAAAA", - "category": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5tmb5s7U9AIVJTBogAAAA", - "search": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5tmb5s7U9AIVJTBogAAAA", - "detail": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=detail&ids=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5tmb5s7U9AIVJTBogAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -859,10 +667,8 @@ "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/alist?do=cat&pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTT8zJLC7RAzEB657OqRIAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -874,73 +680,47 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%94%B5%E5%BD%B1%E6%B8%AF[%E7%A3%81]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_集百动漫[漫]", - "name": "集百动漫[漫](DS)", - "api": "http://localhost:5757/api/集百动漫[漫]?pwd=dzyyds", + "key": "drpyS_至臻ᵐ[盘]", + "name": "至臻ᵐ[盘](DS)", + "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9B%86%E7%99%BE%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_剧透社[盘]", - "name": "剧透社[盘](hipy)", - "api": "http://localhost:5757/api/剧透社[盘]?do=py&pwd=dzyyds", + "key": "drpyS_集百动漫[漫]", + "name": "集百动漫[漫](DS)", + "api": "http://localhost:5757/api/集百动漫[漫]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "hipy", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%89%A7%E9%80%8F%E7%A4%BE[%E7%9B%98]?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%89%A7%E9%80%8F%E7%A4%BE[%E7%9B%98]?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_樱漫[漫]", - "name": "樱漫[漫](DS)", - "api": "http://localhost:5757/api/樱漫[漫]?pwd=dzyyds", + "key": "php_星星短剧 ᵈᶻ[短]", + "name": "星星短剧 ᵈᶻ[短](PHP)", + "api": "http://localhost:5757/api/星星短剧 ᵈᶻ[短]?do=php&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%A8%B1%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%A8%B1%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false - }, - { - "key": "drpyS_爱动漫[漫]", - "name": "爱动漫[漫](DS)", - "api": "http://localhost:5757/api/爱动漫[漫]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", + "lang": "php", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%88%B1%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -952,73 +732,21 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8A%A8%E6%BC%AB%E8%B1%86[%E6%BC%AB]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false - }, - { - "key": "drpyS_西饭短剧[短]", - "name": "西饭短剧[短](DS)", - "api": "http://localhost:5757/api/西饭短剧[短]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%A5%BF%E9%A5%AD%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E8%A5%BF%E9%A5%AD%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_星芽短剧[短]", - "name": "星芽短剧[短](DS)", - "api": "http://localhost:5757/api/星芽短剧[短]?pwd=dzyyds", + "key": "drpyS_360影视[官]", + "name": "360影视[官](DS)", + "api": "http://localhost:5757/api/360影视[官]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%98%9F%E8%8A%BD%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%98%9F%E8%8A%BD%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false - }, - { - "key": "php_星星短剧 ᵈᶻ[短]", - "name": "星星短剧 ᵈᶻ[短](PHP)", - "api": "http://localhost:5757/api/星星短剧 ᵈᶻ[短]?do=php&pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "php", - "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%98%9F%E6%98%9F%E7%9F%AD%E5%89%A7%20%E1%B5%88%E1%B6%BB[%E7%9F%AD]?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false - }, - { - "key": "drpyS_牛牛短剧[短]", - "name": "牛牛短剧[短](DS)", - "api": "http://localhost:5757/api/牛牛短剧[短]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%89%9B%E7%89%9B%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%89%9B%E7%89%9B%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1030,57 +758,21 @@ "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%94%9C%E5%9C%88%E7%9F%AD%E5%89%A7[%E7%9F%AD]?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_七猫短剧[短]", - "name": "七猫短剧[短](DS)", - "api": "http://localhost:5757/api/七猫短剧[短]?pwd=dzyyds", + "key": "catvod_聚合短剧[短]", + "name": "聚合短剧[短](cat)", + "api": "http://localhost:5757/api/聚合短剧[短]?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false - }, - { - "key": "drpyS_软鸭短剧[短]", - "name": "软鸭短剧[短](DS)", - "api": "http://localhost:5757/api/软鸭短剧[短]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%BD%AF%E9%B8%AD%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E8%BD%AF%E9%B8%AD%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false - }, - { - "key": "drpyS_360影视[官]", - "name": "360影视[官](DS)", - "api": "http://localhost:5757/api/360影视[官]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", + "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/360%E5%BD%B1%E8%A7%86[%E5%AE%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1092,10 +784,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%88%91%E7%9A%84%E5%93%94%E5%93%A9[%E5%AE%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp5ytPJK5919D%2BbvUkPJAIADgS31hkAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1107,10 +797,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%88%91%E7%9A%84%E5%93%94%E5%93%A9[%E5%AE%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp5ytPJK59NnfmiaZMeSAQAgv7xPBkAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1122,10 +810,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%88%91%E7%9A%84%E5%93%94%E5%93%A9[%E5%AE%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp5ytPJK59umPi0Zb8eSAQAOsH08xkAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1137,60 +823,47 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%88%91%E7%9A%84%E5%93%94%E5%93%A9[%E5%AE%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp5ytPJK58uWf60dYUeSAQAZ2A%2BOBkAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_哔哩收藏[官]", - "name": "哔哩收藏[官](DS)", - "api": "http://localhost:5757/api/哔哩收藏[官]?pwd=dzyyds", + "key": "drpyS_哔哩大杂烩[官]", + "name": "哔哩大杂烩[官](DS)", + "api": "http://localhost:5757/api/我的哔哩[官]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%93%94%E5%93%A9%E6%94%B6%E8%97%8F[%E5%AE%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp5ytPJK59N2fZier8eSAQA1H95AxkAAAA%3D", - "category": "http://localhost:5757/api/%E5%93%94%E5%93%A9%E6%94%B6%E8%97%8F[%E5%AE%98]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp5ytPJK59N2fZier8eSAQA1H95AxkAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_优酷[官]", - "name": "优酷[官](DS)", - "api": "http://localhost:5757/api/优酷[官]?pwd=dzyyds", + "key": "drpyS_斗鱼直播弹幕[官]", + "name": "斗鱼直播弹幕[官](DS)", + "api": "http://localhost:5757/api/斗鱼直播弹幕[官]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%BC%98%E9%85%B7[%E5%AE%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E4%BC%98%E9%85%B7[%E5%AE%98]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_奇珍异兽[官]", - "name": "奇珍异兽[官](DS)", - "api": "http://localhost:5757/api/奇珍异兽[官]?pwd=dzyyds", + "key": "hipy_py_剧透社[盘]", + "name": "剧透社[盘](hipy)", + "api": "http://localhost:5757/api/剧透社[盘]?do=py&pwd=dzyyds", "type": 4, - "searchable": 2, - "lang": "ds", + "searchable": 1, + "lang": "hipy", "status": "success", - "message": "2/4 接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A5%87%E7%8F%8D%E5%BC%82%E5%85%BD[%E5%AE%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%A5%87%E7%8F%8D%E5%BC%82%E5%85%BD[%E5%AE%98]?pwd=dzyyds&ac=list&t=1&pg=1", - "search": "http://localhost:5757/api/%E5%A5%87%E7%8F%8D%E5%BC%82%E5%85%BD[%E5%AE%98]?pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95", - "detail": "http://localhost:5757/api/%E5%A5%87%E7%8F%8D%E5%BC%82%E5%85%BD[%E5%AE%98]?pwd=dzyyds&ac=detail&ids=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1202,166 +875,281 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%93%94%E5%93%A9%E5%BD%B1%E8%A7%86[%E5%AE%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_聚合短剧[短]", - "name": "聚合短剧[短](cat)", - "api": "http://localhost:5757/api/聚合短剧[短]?do=cat&pwd=dzyyds", + "key": "drpyS_玩偶ᵐ[盘]", + "name": "玩偶ᵐ[盘](DS)", + "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%81%9A%E5%90%88%E7%9F%AD%E5%89%A7[%E7%9F%AD]?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_哔哩大杂烩[官]", - "name": "哔哩大杂烩[官](DS)", - "api": "http://localhost:5757/api/我的哔哩[官]?pwd=dzyyds", + "key": "drpyS_虎斑ᵐ[盘]", + "name": "虎斑ᵐ[盘](DS)", + "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%88%91%E7%9A%84%E5%93%94%E5%93%A9[%E5%AE%98]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp5ytPJK58uWf5sbtPz5pV6IEEAolZcGBwAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_斗鱼直播弹幕[官]", - "name": "斗鱼直播弹幕[官](DS)", - "api": "http://localhost:5757/api/斗鱼直播弹幕[官]?pwd=dzyyds", + "key": "drpyS_樱漫[漫]", + "name": "樱漫[漫](DS)", + "api": "http://localhost:5757/api/樱漫[漫]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%96%97%E9%B1%BC%E7%9B%B4%E6%92%AD%E5%BC%B9%E5%B9%95[%E5%AE%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_哩哩[官]", - "name": "哩哩[官](cat)", - "api": "http://localhost:5757/api/哩哩[官]?do=cat&pwd=dzyyds", + "key": "drpyS_星芽短剧[短]", + "name": "星芽短剧[短](DS)", + "api": "http://localhost:5757/api/星芽短剧[短]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "cat", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%93%A9%E5%93%A9[%E5%AE%98]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%93%A9%E5%93%A9[%E5%AE%98]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_百忙无果[官]", - "name": "百忙无果[官](DS)", - "api": "http://localhost:5757/api/百忙无果[官]?pwd=dzyyds", + "key": "drpyS_七猫短剧[短]", + "name": "七猫短剧[短](DS)", + "api": "http://localhost:5757/api/七猫短剧[短]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%99%BE%E5%BF%99%E6%97%A0%E6%9E%9C[%E5%AE%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%99%BE%E5%BF%99%E6%97%A0%E6%9E%9C[%E5%AE%98]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_菜狗[官]", - "name": "菜狗[官](DS)", - "api": "http://localhost:5757/api/菜狗[官]?pwd=dzyyds", + "key": "drpyS_牛牛短剧[短]", + "name": "牛牛短剧[短](DS)", + "api": "http://localhost:5757/api/牛牛短剧[短]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%8F%9C%E7%8B%97[%E5%AE%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E8%8F%9C%E7%8B%97[%E5%AE%98]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_央央[官]", - "name": "央央[官](cat)", - "api": "http://localhost:5757/api/央央[官]?do=cat&pwd=dzyyds", + "key": "drpyS_爱动漫[漫]", + "name": "爱动漫[漫](DS)", + "api": "http://localhost:5757/api/爱动漫[漫]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "cat", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A4%AE%E5%A4%AE[%E5%AE%98]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%A4%AE%E5%A4%AE[%E5%AE%98]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_果果 ᵈᶻ[官]", - "name": "果果 ᵈᶻ[官](PHP)", - "api": "http://localhost:5757/api/果果 ᵈᶻ[官]?do=php&pwd=dzyyds", + "key": "drpyS_西饭短剧[短]", + "name": "西饭短剧[短](DS)", + "api": "http://localhost:5757/api/西饭短剧[短]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "php", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%9E%9C%E6%9E%9C%20%E1%B5%88%E1%B6%BB[%E5%AE%98]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%9E%9C%E6%9E%9C%20%E1%B5%88%E1%B6%BB[%E5%AE%98]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_腾腾 ᵈᶻ[官]", - "name": "腾腾 ᵈᶻ[官](PHP)", - "api": "http://localhost:5757/api/腾腾 ᵈᶻ[官]?do=php&pwd=dzyyds", + "key": "drpyS_哔哩收藏[官]", + "name": "哔哩收藏[官](DS)", + "api": "http://localhost:5757/api/哔哩收藏[官]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "php", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%85%BE%E8%85%BE%20%E1%B5%88%E1%B6%BB[%E5%AE%98]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E8%85%BE%E8%85%BE%20%E1%B5%88%E1%B6%BB[%E5%AE%98]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_16wMV[听]", - "name": "16wMV[听](DS)", - "api": "http://localhost:5757/api/16wMV[听]?pwd=dzyyds", + "key": "drpyS_优酷[官]", + "name": "优酷[官](DS)", + "api": "http://localhost:5757/api/优酷[官]?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_菜狗[官]", + "name": "菜狗[官](DS)", + "api": "http://localhost:5757/api/菜狗[官]?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "php_果果 ᵈᶻ[官]", + "name": "果果 ᵈᶻ[官](PHP)", + "api": "http://localhost:5757/api/果果 ᵈᶻ[官]?do=php&pwd=dzyyds", "type": 4, "searchable": 1, + "lang": "php", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_百忙无果[官]", + "name": "百忙无果[官](DS)", + "api": "http://localhost:5757/api/百忙无果[官]?pwd=dzyyds", + "type": 4, + "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/16wMV[%E5%90%AC]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTf9rb%2BLR17ZMd7c%2FW9jybvUmvpKIEABrNdgcbAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "catvod_哩哩[官]", + "name": "哩哩[官](cat)", + "api": "http://localhost:5757/api/哩哩[官]?do=cat&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "cat", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "catvod_央央[官]", + "name": "央央[官](cat)", + "api": "http://localhost:5757/api/央央[官]?do=cat&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "cat", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "php_腾腾 ᵈᶻ[官]", + "name": "腾腾 ᵈᶻ[官](PHP)", + "api": "http://localhost:5757/api/腾腾 ᵈᶻ[官]?do=php&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "php", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_软鸭短剧[短]", + "name": "软鸭短剧[短](DS)", + "api": "http://localhost:5757/api/软鸭短剧[短]?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_番茄短剧[短]", + "name": "番茄短剧[短](DS)", + "api": "http://localhost:5757/api/番茄短剧[短]?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "success", + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true + }, + { + "key": "catvod_奇奇[官]", + "name": "奇奇[官](cat)", + "api": "http://localhost:5757/api/奇奇[官]?do=cat&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "cat", + "status": "success", + "message": "分类接口正常 (容错:分类2)", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "php_奇奇 ᵈᶻ[官]", + "name": "奇奇 ᵈᶻ[官](PHP)", + "api": "http://localhost:5757/api/奇奇 ᵈᶻ[官]?do=php&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "php", + "status": "success", + "message": "分类接口正常 (容错:分类2)", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_奇珍异兽[官]", + "name": "奇珍异兽[官](DS)", + "api": "http://localhost:5757/api/奇珍异兽[官]?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "success", + "message": "分类接口正常 (容错:分类2)", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1373,10 +1161,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/DJ%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1388,184 +1174,216 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%85%AD%E6%9C%88%E5%90%AC%E4%B9%A6[%E5%90%AC]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_30wMV[听]", - "name": "30wMV[听](DS)", - "api": "http://localhost:5757/api/30wMV[听]?pwd=dzyyds", + "key": "drpyS_16wMV[听]", + "name": "16wMV[听](DS)", + "api": "http://localhost:5757/api/16wMV[听]?pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 1, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/30wMV[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/30wMV[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_凤凰FM[听]", - "name": "凤凰FM[听](DS)", - "api": "http://localhost:5757/api/凤凰FM[听]?pwd=dzyyds", + "key": "catvod_听了么[听]", + "name": "听了么[听](cat)", + "api": "http://localhost:5757/api/听了么[听]?do=cat&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "cat", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "catvod_网抑云[听]", + "name": "网抑云[听](cat)", + "api": "http://localhost:5757/api/网抑云[听]?do=cat&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "cat", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_爱推图[画]", + "name": "爱推图[画](DS)", + "api": "http://localhost:5757/api/爱推图[画]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%87%A4%E5%87%B0FM[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%87%A4%E5%87%B0FM[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_博看听书[听]", - "name": "博看听书[听](DS)", - "api": "http://localhost:5757/api/博看听书[听]?pwd=dzyyds", + "key": "drpyS_包子漫画[画]", + "name": "包子漫画[画](DS)", + "api": "http://localhost:5757/api/包子漫画[画]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8D%9A%E7%9C%8B%E5%90%AC%E4%B9%A6[%E5%90%AC]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_果果[官]", - "name": "果果[官](cat)", - "api": "http://localhost:5757/api/果果[官]?do=cat&pwd=dzyyds", + "key": "drpyS_酷爱漫画[画]", + "name": "酷爱漫画[画](DS)", + "api": "http://localhost:5757/api/酷爱漫画[画]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "cat", + "searchable": 2, + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%9E%9C%E6%9E%9C[%E5%AE%98]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%9E%9C%E6%9E%9C[%E5%AE%98]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_布谷音乐[听]", - "name": "布谷音乐[听](DS)", - "api": "http://localhost:5757/api/布谷音乐[听]?pwd=dzyyds", + "key": "drpyS_番茄漫画[画]", + "name": "番茄漫画[画](DS)", + "api": "http://localhost:5757/api/番茄漫画[画]?pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "ds", + "status": "success", + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true + }, + { + "key": "drpyS_光社漫画[画]", + "name": "光社漫画[画](DS)", + "api": "http://localhost:5757/api/光社漫画[画]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%B8%83%E8%B0%B7%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%B8%83%E8%B0%B7%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_爱玩音乐[听]", - "name": "爱玩音乐[听](DS)", - "api": "http://localhost:5757/api/爱玩音乐[听]?pwd=dzyyds", + "key": "php_酷爱漫画 ᵈᶻ[画]", + "name": "酷爱漫画 ᵈᶻ[画](PHP)", + "api": "http://localhost:5757/api/酷爱漫画 ᵈᶻ[画]?do=php&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "php", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "catvod_果果[官]", + "name": "果果[官](cat)", + "api": "http://localhost:5757/api/果果[官]?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, + "lang": "cat", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_30wMV[听]", + "name": "30wMV[听](DS)", + "api": "http://localhost:5757/api/30wMV[听]?pwd=dzyyds", + "type": 4, + "searchable": 0, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E7%8E%A9%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%88%B1%E7%8E%A9%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_狗狗音乐[听]", - "name": "狗狗音乐[听](DS)", - "api": "http://localhost:5757/api/狗狗音乐[听]?pwd=dzyyds", + "key": "drpyS_凤凰FM[听]", + "name": "凤凰FM[听](DS)", + "api": "http://localhost:5757/api/凤凰FM[听]?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8B%97%E7%8B%97%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_酷我听书[听]", - "name": "酷我听书[听](DS)", - "api": "http://localhost:5757/api/酷我听书[听]?pwd=dzyyds", + "key": "drpyS_爱玩音乐[听]", + "name": "爱玩音乐[听](DS)", + "api": "http://localhost:5757/api/爱玩音乐[听]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%85%B7%E6%88%91%E5%90%AC%E4%B9%A6[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%85%B7%E6%88%91%E5%90%AC%E4%B9%A6[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_米兔音乐[听]", - "name": "米兔音乐[听](DS)", - "api": "http://localhost:5757/api/米兔音乐[听]?pwd=dzyyds", + "key": "drpyS_博看听书[听]", + "name": "博看听书[听](DS)", + "api": "http://localhost:5757/api/博看听书[听]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%B1%B3%E5%85%94%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%B1%B3%E5%85%94%E9%9F%B3%E4%B9%90[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_爱听音乐[听]", - "name": "爱听音乐[听](hipy)", - "api": "http://localhost:5757/api/爱听音乐[听]?do=py&pwd=dzyyds", + "key": "drpyS_布谷音乐[听]", + "name": "布谷音乐[听](DS)", + "api": "http://localhost:5757/api/布谷音乐[听]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "hipy", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E5%90%AC%E9%9F%B3%E4%B9%90[%E5%90%AC]?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%88%B1%E5%90%AC%E9%9F%B3%E4%B9%90[%E5%90%AC]?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_音乐磁场[听]", - "name": "音乐磁场[听](DS)", - "api": "http://localhost:5757/api/音乐磁场[听]?pwd=dzyyds", + "key": "drpyS_狗狗音乐[听]", + "name": "狗狗音乐[听](DS)", + "api": "http://localhost:5757/api/狗狗音乐[听]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9F%B3%E4%B9%90%E7%A3%81%E5%9C%BA[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%9F%B3%E4%B9%90%E7%A3%81%E5%9C%BA[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1577,105 +1395,73 @@ "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%9C%BB%E8%9C%93FM[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E8%9C%BB%E8%9C%93FM[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false - }, - { - "key": "drpyS_番茄畅听[听]", - "name": "番茄畅听[听](DS)", - "api": "http://localhost:5757/api/番茄畅听[听]?pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E7%95%85%E5%90%AC[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E7%95%85%E5%90%AC[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_听了么[听]", - "name": "听了么[听](cat)", - "api": "http://localhost:5757/api/听了么[听]?do=cat&pwd=dzyyds", + "key": "catvod_青木倪壁纸[画]", + "name": "青木倪壁纸[画](cat)", + "api": "http://localhost:5757/api/青木倪壁纸[画]?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%90%AC%E4%BA%86%E4%B9%88[%E5%90%AC]?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_七猫小说[书]", - "name": "七猫小说[书](DS)", - "api": "http://localhost:5757/api/七猫小说[书]?pwd=dzyyds", + "key": "drpyS_酷我听书[听]", + "name": "酷我听书[听](DS)", + "api": "http://localhost:5757/api/酷我听书[听]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_网抑云[听]", - "name": "网抑云[听](cat)", - "api": "http://localhost:5757/api/网抑云[听]?do=cat&pwd=dzyyds", + "key": "php_包子漫画 ᵈᶻ[画]", + "name": "包子漫画 ᵈᶻ[画](PHP)", + "api": "http://localhost:5757/api/包子漫画 ᵈᶻ[画]?do=php&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "php", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E6%8A%91%E4%BA%91[%E5%90%AC]?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_阅读助手[书]", - "name": "阅读助手[书](DS)", - "api": "http://localhost:5757/api/阅读助手[书]?pwd=dzyyds", + "key": "drpyS_米兔音乐[听]", + "name": "米兔音乐[听](DS)", + "api": "http://localhost:5757/api/米兔音乐[听]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%98%85%E8%AF%BB%E5%8A%A9%E6%89%8B[%E4%B9%A6]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%98%85%E8%AF%BB%E5%8A%A9%E6%89%8B[%E4%B9%A6]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_爱玩音乐[听]", - "name": "爱玩音乐[听](hipy)", - "api": "http://localhost:5757/api/爱玩音乐[听]?do=py&pwd=dzyyds", + "key": "drpyS_七猫小说[书]", + "name": "七猫小说[书](DS)", + "api": "http://localhost:5757/api/七猫小说[书]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "hipy", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E7%8E%A9%E9%9F%B3%E4%B9%90[%E5%90%AC]?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%88%B1%E7%8E%A9%E9%9F%B3%E4%B9%90[%E5%90%AC]?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1687,108 +1473,99 @@ "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8A%AA%E5%8A%AA%E4%B9%A6%E5%9D%8A[%E4%B9%A6]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%8A%AA%E5%8A%AA%E4%B9%A6%E5%9D%8A[%E4%B9%A6]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_七猫小说 ᵈᶻ[书]", - "name": "七猫小说 ᵈᶻ[书](PHP)", - "api": "http://localhost:5757/api/七猫小说 ᵈᶻ[书]?do=php&pwd=dzyyds", + "key": "drpyS_去读书[书]", + "name": "去读书[书](DS)", + "api": "http://localhost:5757/api/去读书[书]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E5%B0%8F%E8%AF%B4%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E5%B0%8F%E8%AF%B4%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_七猫小说[书]", - "name": "七猫小说[书](hipy)", - "api": "http://localhost:5757/api/七猫小说[书]?do=py&pwd=dzyyds", + "key": "drpyS_阅读助手[书]", + "name": "阅读助手[书](DS)", + "api": "http://localhost:5757/api/阅读助手[书]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "hipy", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E4%B8%83%E7%8C%AB%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_去读书[书]", - "name": "去读书[书](DS)", - "api": "http://localhost:5757/api/去读书[书]?pwd=dzyyds", + "key": "hipy_py_爱玩音乐[听]", + "name": "爱玩音乐[听](hipy)", + "api": "http://localhost:5757/api/爱玩音乐[听]?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "hipy", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8E%BB%E8%AF%BB%E4%B9%A6[%E4%B9%A6]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%8E%BB%E8%AF%BB%E4%B9%A6[%E4%B9%A6]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_顶点小说[书]", - "name": "顶点小说[书](DS)", - "api": "http://localhost:5757/api/顶点小说[书]?pwd=dzyyds", + "key": "drpyS_音乐磁场[听]", + "name": "音乐磁场[听](DS)", + "api": "http://localhost:5757/api/音乐磁场[听]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "3/4 接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%A1%B6%E7%82%B9%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%A1%B6%E7%82%B9%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds&ac=list&t=1&pg=1", - "search": "http://localhost:5757/api/%E9%A1%B6%E7%82%B9%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95", - "detail": "http://localhost:5757/api/%E9%A1%B6%E7%82%B9%E5%B0%8F%E8%AF%B4[%E4%B9%A6]?pwd=dzyyds&ac=detail&ids=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_酷爱漫画[画]", - "name": "酷爱漫画[画](DS)", - "api": "http://localhost:5757/api/酷爱漫画[画]?pwd=dzyyds", + "key": "php_去读书 ᵈᶻ[书]", + "name": "去读书 ᵈᶻ[书](PHP)", + "api": "http://localhost:5757/api/去读书 ᵈᶻ[书]?do=php&pwd=dzyyds", "type": 4, - "searchable": 2, - "lang": "ds", + "searchable": 1, + "lang": "php", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%85%B7%E7%88%B1%E6%BC%AB%E7%94%BB[%E7%94%BB]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_漫画大全[画]", - "name": "漫画大全[画](DS)", - "api": "http://localhost:5757/api/漫画大全[画]?pwd=dzyyds", + "key": "php_七猫小说 ᵈᶻ[书]", + "name": "七猫小说 ᵈᶻ[书](PHP)", + "api": "http://localhost:5757/api/七猫小说 ᵈᶻ[书]?do=php&pwd=dzyyds", "type": 4, - "searchable": 2, - "lang": "ds", + "searchable": 1, + "lang": "php", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%BC%AB%E7%94%BB%E5%A4%A7%E5%85%A8[%E7%94%BB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%BC%AB%E7%94%BB%E5%A4%A7%E5%85%A8[%E7%94%BB]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "hipy_py_爱听音乐[听]", + "name": "爱听音乐[听](hipy)", + "api": "http://localhost:5757/api/爱听音乐[听]?do=py&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "hipy", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1800,57 +1577,47 @@ "lang": "php", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%98%85%E8%AF%BB%E5%8A%A9%E6%89%8B%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%98%85%E8%AF%BB%E5%8A%A9%E6%89%8B%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_包子漫画[画]", - "name": "包子漫画[画](DS)", - "api": "http://localhost:5757/api/包子漫画[画]?pwd=dzyyds", + "key": "drpyS_漫画大全[画]", + "name": "漫画大全[画](DS)", + "api": "http://localhost:5757/api/漫画大全[画]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8C%85%E5%AD%90%E6%BC%AB%E7%94%BB[%E7%94%BB]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_爱推图[画]", - "name": "爱推图[画](DS)", - "api": "http://localhost:5757/api/爱推图[画]?pwd=dzyyds", + "key": "php_74P福利图 ᵈᵇ[画]", + "name": "74P福利图 ᵈᵇ[画](PHP)", + "api": "http://localhost:5757/api/74P福利图 ᵈᵇ[画]?do=php&pwd=dzyyds", "type": 4, - "searchable": 2, - "lang": "ds", + "searchable": 1, + "lang": "php", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E6%8E%A8%E5%9B%BE[%E7%94%BB]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_去读书 ᵈᶻ[书]", - "name": "去读书 ᵈᶻ[书](PHP)", - "api": "http://localhost:5757/api/去读书 ᵈᶻ[书]?do=php&pwd=dzyyds", + "key": "drpyS_顶点小说[书]", + "name": "顶点小说[书](DS)", + "api": "http://localhost:5757/api/顶点小说[书]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "php", + "searchable": 2, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8E%BB%E8%AF%BB%E4%B9%A6%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%8E%BB%E8%AF%BB%E4%B9%A6%20%E1%B5%88%E1%B6%BB[%E4%B9%A6]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1862,11 +1629,8 @@ "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%BC%AB%E7%A5%9E[%E7%94%BB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%BC%AB%E7%A5%9E[%E7%94%BB]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1878,72 +1642,60 @@ "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8A%A8%E6%BC%AB%E5%95%A6[%E7%94%BB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%8A%A8%E6%BC%AB%E5%95%A6[%E7%94%BB]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_光社漫画[画]", - "name": "光社漫画[画](DS)", - "api": "http://localhost:5757/api/光社漫画[画]?pwd=dzyyds", + "key": "catvod_酷酷[官]", + "name": "酷酷[官](cat)", + "api": "http://localhost:5757/api/酷酷[官]?do=cat&pwd=dzyyds", "type": 4, - "searchable": 2, - "lang": "ds", + "searchable": 1, + "lang": "cat", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%85%89%E7%A4%BE%E6%BC%AB%E7%94%BB[%E7%94%BB]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "php_酷爱漫画 ᵈᶻ[画]", - "name": "酷爱漫画 ᵈᶻ[画](PHP)", - "api": "http://localhost:5757/api/酷爱漫画 ᵈᶻ[画]?do=php&pwd=dzyyds", + "key": "hipy_py_七猫小说[书]", + "name": "七猫小说[书](hipy)", + "api": "http://localhost:5757/api/七猫小说[书]?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "hipy", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%85%B7%E7%88%B1%E6%BC%AB%E7%94%BB%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_74P福利图 ᵈᵇ[画]", - "name": "74P福利图 ᵈᵇ[画](PHP)", - "api": "http://localhost:5757/api/74P福利图 ᵈᵇ[画]?do=php&pwd=dzyyds", + "key": "drpyS_音乐聚合[听]", + "name": "音乐聚合[听](DS)", + "api": "http://localhost:5757/api/音乐聚合[听]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/74P%E7%A6%8F%E5%88%A9%E5%9B%BE%20%E1%B5%88%E1%B5%87[%E7%94%BB]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/74P%E7%A6%8F%E5%88%A9%E5%9B%BE%20%E1%B5%88%E1%B5%87[%E7%94%BB]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "php_包子漫画 ᵈᶻ[画]", - "name": "包子漫画 ᵈᶻ[画](PHP)", - "api": "http://localhost:5757/api/包子漫画 ᵈᶻ[画]?do=php&pwd=dzyyds", + "key": "php_74P福利图 ᵈᶻ[画]", + "name": "74P福利图 ᵈᶻ[画](PHP)", + "api": "http://localhost:5757/api/74P福利图 ᵈᶻ[画]?do=php&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "php", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8C%85%E5%AD%90%E6%BC%AB%E7%94%BB%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -1955,60 +1707,48 @@ "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E8%93%9D%E9%B9%B0", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E8%93%9D%E9%B9%B0" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_74P福利图 ᵈᶻ[画]", - "name": "74P福利图 ᵈᶻ[画](PHP)", - "api": "http://localhost:5757/api/74P福利图 ᵈᶻ[画]?do=php&pwd=dzyyds", + "key": "php_动漫啦 ᵈᶻ[画]", + "name": "动漫啦 ᵈᶻ[画](PHP)", + "api": "http://localhost:5757/api/动漫啦 ᵈᶻ[画]?do=php&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "php", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/74P%E7%A6%8F%E5%88%A9%E5%9B%BE%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/74P%E7%A6%8F%E5%88%A9%E5%9B%BE%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_动漫啦 ᵈᶻ[画]", - "name": "动漫啦 ᵈᶻ[画](PHP)", - "api": "http://localhost:5757/api/动漫啦 ᵈᶻ[画]?do=php&pwd=dzyyds", + "key": "drpyS_番茄畅听[听]", + "name": "番茄畅听[听](DS)", + "api": "http://localhost:5757/api/番茄畅听[听]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8A%A8%E6%BC%AB%E5%95%A6%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%8A%A8%E6%BC%AB%E5%95%A6%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "catvod_青木倪壁纸[画]", - "name": "青木倪壁纸[画](cat)", - "api": "http://localhost:5757/api/青木倪壁纸[画]?do=cat&pwd=dzyyds", + "key": "drpyS_播客[听]", + "name": "播客[听](DS)", + "api": "http://localhost:5757/api/播客[听]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "cat", + "searchable": 0, + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9D%92%E6%9C%A8%E5%80%AA%E5%A3%81%E7%BA%B8[%E7%94%BB]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%9D%92%E6%9C%A8%E5%80%AA%E5%A3%81%E7%BA%B8[%E7%94%BB]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { "key": "php_番茄漫画 ᵈᶻ[画]", @@ -2019,263 +1759,242 @@ "lang": "php", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E6%BC%AB%E7%94%BB%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E6%BC%AB%E7%94%BB%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_影视_Appget", - "name": "影视[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_TG搜[搜]", + "name": "TG搜[搜](DS)", + "api": "http://localhost:5757/api/TG搜[搜]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "unknown", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%BD%B1%E8%A7%86", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%BD%B1%E8%A7%86" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_奇奇_Appget", - "name": "奇奇[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_TG盘搜[搜]", + "name": "TG盘搜[搜](DS)", + "api": "http://localhost:5757/api/TG盘搜[搜]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "unknown", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%A5%87%E5%A5%87", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%A5%87%E5%A5%87" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_优兔_Appget", - "name": "优兔[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_兄弟盘[搜]", + "name": "兄弟盘[搜](DS)", + "api": "http://localhost:5757/api/兄弟盘[搜]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "unknown", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BC%98%E5%85%94", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BC%98%E5%85%94" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_紫金_Appget", - "name": "紫金[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_百度盘[搜]", + "name": "百度盘[搜](DS)", + "api": "http://localhost:5757/api/百度盘[搜]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "unknown", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%B4%AB%E9%87%91", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%B4%AB%E9%87%91" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_小猪_Appget", - "name": "小猪[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_网盘资源[搜]", + "name": "网盘资源[搜](DS)", + "api": "http://localhost:5757/api/网盘资源[搜]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "unknown", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%B0%8F%E7%8C%AA", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%B0%8F%E7%8C%AA" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_五八_Appget", - "name": "五八[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_iptv", + "name": "iptv(DS)", + "api": "http://localhost:5757/api/iptv?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "unknown", + "searchable": 0, + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BA%94%E5%85%AB", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BA%94%E5%85%AB" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_爱盈_Appget", - "name": "爱盈[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "push_agent", + "name": "push_agent(DS)", + "api": "http://localhost:5757/api/push_agent?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "unknown", + "searchable": 0, + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%88%B1%E7%9B%88", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%88%B1%E7%9B%88" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_火狐_Appget", - "name": "火狐[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_动作交互", + "name": "动作交互(DS)", + "api": "http://localhost:5757/api/动作交互?pwd=dzyyds", + "type": 4, + "searchable": 0, + "lang": "ds", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_动作测试新定标准版", + "name": "动作测试新定标准版(DS)", + "api": "http://localhost:5757/api/动作测试新定标准版?pwd=dzyyds", + "type": 4, + "searchable": 0, + "lang": "ds", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_点歌欢唱[B]", + "name": "点歌欢唱[B](DS)", + "api": "http://localhost:5757/api/点歌欢唱[B]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "unknown", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%81%AB%E7%8B%90", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%81%AB%E7%8B%90" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_火锅_Appget", - "name": "火锅[M](GET)", - "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", + "key": "drpyS_梨园行[戏]", + "name": "梨园行[戏](DS)", + "api": "http://localhost:5757/api/梨园行[戏]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "unknown", + "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%81%AB%E9%94%85", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%81%AB%E9%94%85" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_数字_Appget", - "name": "数字[M](GET)", + "key": "drpyS_影视_Appget", + "name": "影视[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E6%95%B0%E5%AD%97", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E6%95%B0%E5%AD%97" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_金牌_Appget", - "name": "金牌[M](GET)", + "key": "drpyS_小猪_Appget", + "name": "小猪[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E9%87%91%E7%89%8C", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E9%87%91%E7%89%8C" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_TG搜[搜]", - "name": "TG搜[搜](DS)", - "api": "http://localhost:5757/api/TG搜[搜]?pwd=dzyyds", + "key": "drpyS_奇奇_Appget", + "name": "奇奇[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/TG%E6%90%9C[%E6%90%9C]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_TG盘搜[搜]", - "name": "TG盘搜[搜](DS)", - "api": "http://localhost:5757/api/TG盘搜[搜]?pwd=dzyyds", + "key": "drpyS_爱壹帆", + "name": "爱壹帆(DS)", + "api": "http://localhost:5757/api/爱壹帆?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/TG%E7%9B%98%E6%90%9C[%E6%90%9C]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_兄弟盘[搜]", - "name": "兄弟盘[搜](DS)", - "api": "http://localhost:5757/api/兄弟盘[搜]?pwd=dzyyds", + "key": "drpyS_优兔_Appget", + "name": "优兔[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%85%84%E5%BC%9F%E7%9B%98[%E6%90%9C]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_百度盘[搜]", - "name": "百度盘[搜](DS)", - "api": "http://localhost:5757/api/百度盘[搜]?pwd=dzyyds", + "key": "drpyS_紫金_Appget", + "name": "紫金[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%99%BE%E5%BA%A6%E7%9B%98[%E6%90%9C]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_元咲动漫_Appget", - "name": "元咲动漫[M](GET)", + "key": "drpyS_五八_Appget", + "name": "五八[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%85%83%E5%92%B2%E5%8A%A8%E6%BC%AB", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%85%83%E5%92%B2%E5%8A%A8%E6%BC%AB" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2287,151 +2006,112 @@ "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%B8%AB%E4%B8%AB%E5%8A%A8%E6%BC%AB", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%B8%AB%E4%B8%AB%E5%8A%A8%E6%BC%AB" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_方舟动漫_Appget", - "name": "方舟动漫[M](GET)", + "key": "drpyS_爱盈_Appget", + "name": "爱盈[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E6%96%B9%E8%88%9F%E5%8A%A8%E6%BC%AB", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E6%96%B9%E8%88%9F%E5%8A%A8%E6%BC%AB" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_番薯动漫_Appget", - "name": "番薯动漫[M](GET)", + "key": "drpyS_元咲动漫_Appget", + "name": "元咲动漫[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%95%AA%E8%96%AF%E5%8A%A8%E6%BC%AB", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%95%AA%E8%96%AF%E5%8A%A8%E6%BC%AB" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_咕咕动漫_Appget", - "name": "咕咕动漫[M](GET)", + "key": "drpyS_火狐_Appget", + "name": "火狐[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%92%95%E5%92%95%E5%8A%A8%E6%BC%AB", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%92%95%E5%92%95%E5%8A%A8%E6%BC%AB" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_网盘资源[搜]", - "name": "网盘资源[搜](DS)", - "api": "http://localhost:5757/api/网盘资源[搜]?pwd=dzyyds", + "key": "drpyS_数字_Appget", + "name": "数字[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98%E8%B5%84%E6%BA%90[%E6%90%9C]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_iptv", - "name": "iptv(DS)", - "api": "http://localhost:5757/api/iptv?pwd=dzyyds", + "key": "drpyS_APP模板配置", + "name": "APP模板配置(DS)", + "api": "http://localhost:5757/api/APP模板配置?pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 1, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/iptv?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "push_agent", - "name": "push_agent(DS)", - "api": "http://localhost:5757/api/push_agent?pwd=dzyyds", + "key": "drpyS_方舟动漫_Appget", + "name": "方舟动漫[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, - "searchable": 0, - "lang": "ds", + "searchable": 1, + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/push_agent?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_APP模板配置", - "name": "APP模板配置(DS)", - "api": "http://localhost:5757/api/APP模板配置?pwd=dzyyds", + "key": "drpyS_番薯动漫_Appget", + "name": "番薯动漫[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "unknown", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/APP%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE?pwd=dzyyds", - "category": "http://localhost:5757/api/APP%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_php测试", - "name": "php测试(DS)", - "api": "http://localhost:5757/api/php?pwd=dzyyds", + "key": "drpyS_金牌_Appget", + "name": "金牌[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "success", - "message": "手动标记为正常", - "testUrls": { - "home": "http://localhost:5757/api/php?pwd=dzyyds&extend=H4sIAAAAAAAAA6tWysgvLlGyUsooKSkottLXLy8v10tKzEwp1UvOz1WqBQCTzRcDIAAAAA%3D%3D", - "category": "http://localhost:5757/api/php?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA6tWysgvLlGyUsooKSkottLXLy8v10tKzEwp1UvOz1WqBQCTzRcDIAAAAA%3D%3D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": true - }, - { - "key": "drpyS_TVB云播", - "name": "TVB云播(DS)", - "api": "http://localhost:5757/api/TVB云播?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/TVB%E4%BA%91%E6%92%AD?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2443,102 +2123,73 @@ "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%85%94%E5%B0%8F%E8%B4%9D[%E5%84%BF]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%85%94%E5%B0%8F%E8%B4%9D[%E5%84%BF]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "drpyS_动作测试新定标准版", - "name": "动作测试新定标准版(DS)", - "api": "http://localhost:5757/api/动作测试新定标准版?pwd=dzyyds", - "type": 4, - "searchable": 0, - "lang": "ds", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8A%A8%E4%BD%9C%E6%B5%8B%E8%AF%95%E6%96%B0%E5%AE%9A%E6%A0%87%E5%87%86%E7%89%88?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_动作交互", - "name": "动作交互(DS)", - "api": "http://localhost:5757/api/动作交互?pwd=dzyyds", + "key": "drpyS_开眼", + "name": "开眼(DS)", + "api": "http://localhost:5757/api/开眼?pwd=dzyyds", "type": 4, "searchable": 0, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8A%A8%E4%BD%9C%E4%BA%A4%E4%BA%92?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_点歌欢唱[B]", - "name": "点歌欢唱[B](DS)", - "api": "http://localhost:5757/api/点歌欢唱[B]?pwd=dzyyds", + "key": "drpyS_咕咕动漫_Appget", + "name": "咕咕动漫[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%82%B9%E6%AD%8C%E6%AC%A2%E5%94%B1[B]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTf9rb%2BLR17ZMd7c%2FW9jybvUmvpKIEABrNdgcbAAAA" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_梨园行[戏]", - "name": "梨园行[戏](DS)", - "api": "http://localhost:5757/api/梨园行[戏]?pwd=dzyyds", + "key": "drpyS_凡客TV", + "name": "凡客TV(DS)", + "api": "http://localhost:5757/api/凡客TV?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%A2%A8%E5%9B%AD%E8%A1%8C[%E6%88%8F]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_开眼", - "name": "开眼(DS)", - "api": "http://localhost:5757/api/开眼?pwd=dzyyds", + "key": "drpyS_php测试", + "name": "php测试(DS)", + "api": "http://localhost:5757/api/php?pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 1, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%BC%80%E7%9C%BC?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%BC%80%E7%9C%BC?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false + "message": "手动标记为正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": true }, { - "key": "drpyS_爱壹帆", - "name": "爱壹帆(DS)", - "api": "http://localhost:5757/api/爱壹帆?pwd=dzyyds", + "key": "drpyS_王子_Appget", + "name": "王子[M](GET)", + "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, - "searchable": 2, - "lang": "ds", + "searchable": 1, + "lang": "unknown", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E5%A3%B9%E5%B8%86?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "2/4 接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2549,27 +2200,9 @@ "searchable": 2, "lang": "ds", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%9E%AB%E6%9E%97%E5%BD%B1%E8%A7%86?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "drpyS_凡客TV", - "name": "凡客TV(DS)", - "api": "http://localhost:5757/api/凡客TV?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%87%A1%E5%AE%A2TV?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%87%A1%E5%AE%A2TV?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "3/4 接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2580,12 +2213,9 @@ "searchable": 2, "lang": "ds", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E7%9C%8B%E6%9C%BA%E5%99%A8%E4%BA%BA[%E8%99%AB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%88%B1%E7%9C%8B%E6%9C%BA%E5%99%A8%E4%BA%BA[%E8%99%AB]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常 (容错:分类2)", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2597,10 +2227,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9B%B4%E6%92%AD%E8%BD%AC%E7%82%B9%E6%92%AD[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTz8ksSzVKzi3WzS3TAwkAAGomgm4YAAAA" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2612,10 +2240,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%B4%9D%E4%B9%90%E8%99%8E[%E5%84%BF]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2627,41 +2253,21 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8E%96%E6%9C%88%E5%BD%B1%E8%A7%86?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_采王道长[合]", - "name": "采王道长[合](DS)", + "key": "drpyS_采王zy[密]", + "name": "采王zy[密](DS)", "api": "http://localhost:5757/api/采集之王[合]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%87%87%E9%9B%86%E4%B9%8B%E7%8E%8B[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTf9ne%2FnJ228u5M581NOqBRFQMAcGPDNobAAAA" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "drpyS_美颜怪[擦]", - "name": "美颜怪[擦](DS)", - "api": "http://localhost:5757/api/美颜怪[擦]?pwd=dzyyds", - "type": 4, - "searchable": 0, - "lang": "ds", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BE%8E%E9%A2%9C%E6%80%AA[%E6%93%A6]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%BE%8E%E9%A2%9C%E6%80%AA[%E6%93%A6]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2673,133 +2279,73 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8E%8B%E5%AD%90TV?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "drpyS_采王zy[密]", - "name": "采王zy[密](DS)", - "api": "http://localhost:5757/api/采集之王[合]?pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "ds", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%87%87%E9%9B%86%E4%B9%8B%E7%8E%8B[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTf9ne%2FnJ2W3RVZezLuTOfNTTqgURVDAGu%2FMCKHwAAAA%3D%3D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "drpyS_短剧视频库", - "name": "短剧视频库(DS)", - "api": "http://localhost:5757/api/短剧视频库?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9F%AD%E5%89%A7%E8%A7%86%E9%A2%91%E5%BA%93?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "drpyS_爱看高清", - "name": "爱看高清(DS)", - "api": "http://localhost:5757/api/爱看高清?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "success", - "message": "3/4 接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E7%9C%8B%E9%AB%98%E6%B8%85?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%88%B1%E7%9C%8B%E9%AB%98%E6%B8%85?pwd=dzyyds&ac=list&t=1&pg=1", - "search": "http://localhost:5757/api/%E7%88%B1%E7%9C%8B%E9%AB%98%E6%B8%85?pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95", - "detail": "http://localhost:5757/api/%E7%88%B1%E7%9C%8B%E9%AB%98%E6%B8%85?pwd=dzyyds&ac=detail&ids=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_采王成人[密]", - "name": "采王成人[密](DS)", + "key": "drpyS_采王道长[合]", + "name": "采王道长[合](DS)", "api": "http://localhost:5757/api/采集之王[合]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%87%87%E9%9B%86%E4%B9%8B%E7%8E%8B[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTf9ne%2FnJ2W%2FTT9W2xL%2BfOfNbQqAcSVjFUAQAd5YgpIQAAAA%3D%3D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_麦田影院", - "name": "麦田影院(DS)", - "api": "http://localhost:5757/api/麦田影院?pwd=dzyyds", + "key": "drpyS_采王2024", + "name": "采王2024(DS)", + "api": "http://localhost:5757/api/采集之王[合]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%BA%A6%E7%94%B0%E5%BD%B1%E9%99%A2?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_飞牛影视", - "name": "飞牛影视(DS)", - "api": "http://localhost:5757/api/飞牛影视?pwd=dzyyds", + "key": "drpyS_采王成人[密]", + "name": "采王成人[密](DS)", + "api": "http://localhost:5757/api/采集之王[合]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%A3%9E%E7%89%9B%E5%BD%B1%E8%A7%86?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_鬼片之家", - "name": "鬼片之家(DS)", - "api": "http://localhost:5757/api/鬼片之家?pwd=dzyyds", + "key": "drpyS_飞牛影视", + "name": "飞牛影视(DS)", + "api": "http://localhost:5757/api/飞牛影视?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%AC%BC%E7%89%87%E4%B9%8B%E5%AE%B6?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_采王2024", - "name": "采王2024(DS)", - "api": "http://localhost:5757/api/采集之王[合]?pwd=dzyyds", + "key": "drpyS_麦田影院", + "name": "麦田影院(DS)", + "api": "http://localhost:5757/api/麦田影院?pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 2, "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%87%87%E9%9B%86%E4%B9%8B%E7%8E%8B[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTf9ne%2FnJ2m5GBkcnLuTOfNTTqgURVDFUAlKCu7yAAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2811,10 +2357,8 @@ "lang": "ds", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%87%87%E9%9B%86%E4%B9%8B%E7%8E%8B[%E5%90%88]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTf9ne%2FnJ2m5GBkenLuTOfNTTqgURVDFUAfHtVViAAAAA%3D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2826,10 +2370,34 @@ "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/mtv60w[%E5%B7%AE]?do=cat&pwd=dzyyds&extend=music.db" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_爱看高清", + "name": "爱看高清(DS)", + "api": "http://localhost:5757/api/爱看高清?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_鬼片之家", + "name": "鬼片之家(DS)", + "api": "http://localhost:5757/api/鬼片之家?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2841,10 +2409,8 @@ "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%B2%B3%E5%8D%97%E7%94%B5%E8%A7%86%E4%BB%A3%E7%90%86?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2856,73 +2422,60 @@ "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8C%AB%E6%B5%8B%E8%AF%95?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_yikm[游戏]", - "name": "yikm[游戏](cat)", - "api": "http://localhost:5757/api/yikm[游戏]?do=cat&pwd=dzyyds", + "key": "catvod_月光影视", + "name": "月光影视(cat)", + "api": "http://localhost:5757/api/月光影视?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "cat", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/yikm[%E6%B8%B8%E6%88%8F]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/yikm[%E6%B8%B8%E6%88%8F]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_喜刷刷", - "name": "喜刷刷(cat)", - "api": "http://localhost:5757/api/喜刷刷?do=cat&pwd=dzyyds", + "key": "hipy_py_4K影视", + "name": "4K影视(hipy)", + "api": "http://localhost:5757/api/4K影视?do=py&pwd=dzyyds", "type": 4, - "searchable": 0, - "lang": "cat", + "searchable": 1, + "lang": "hipy", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%96%9C%E5%88%B7%E5%88%B7?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%96%9C%E5%88%B7%E5%88%B7?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_爱玩音乐", - "name": "爱玩音乐(cat)", - "api": "http://localhost:5757/api/爱玩音乐?do=cat&pwd=dzyyds", + "key": "hipy_py_呀哩4K[AF]", + "name": "呀哩4K[AF](hipy)", + "api": "http://localhost:5757/api/AppFei?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "hipy", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E7%8E%A9%E9%9F%B3%E4%B9%90?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%88%B1%E7%8E%A9%E9%9F%B3%E4%B9%90?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_月光影视", - "name": "月光影视(cat)", - "api": "http://localhost:5757/api/月光影视?do=cat&pwd=dzyyds", + "key": "hipy_py_森林动漫[AF]", + "name": "森林动漫[AF](hipy)", + "api": "http://localhost:5757/api/AppFei?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%9C%88%E5%85%89%E5%BD%B1%E8%A7%86?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -2934,267 +2487,229 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/4KVM?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_荐片", - "name": "荐片(cat)", - "api": "http://localhost:5757/api/荐片?do=cat&pwd=dzyyds", + "key": "hipy_py_火猫影视[AFX]", + "name": "火猫影视[AFX](hipy)", + "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%8D%90%E7%89%87?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_海龟", - "name": "海龟(cat)", - "api": "http://localhost:5757/api/海龟?do=cat&pwd=dzyyds", + "key": "hipy_py_茉莉[AG¹]", + "name": "茉莉[AG¹](hipy)", + "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%B5%B7%E9%BE%9F?do=cat&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_4K影视", - "name": "4K影视(hipy)", - "api": "http://localhost:5757/api/4K影视?do=py&pwd=dzyyds", + "key": "hipy_py_魔方[AG¹]", + "name": "魔方[AG¹](hipy)", + "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/4K%E5%BD%B1%E8%A7%86?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_森林动漫[AF]", - "name": "森林动漫[AF](hipy)", - "api": "http://localhost:5757/api/AppFei?do=py&pwd=dzyyds", + "key": "hipy_py_五八[AG¹]", + "name": "五八[AG¹](hipy)", + "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppFei?do=py&pwd=dzyyds&extend=https%3A%2F%2Fysa.yy-fun.cc%2Ffeiapp" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_呀哩4K[AF]", - "name": "呀哩4K[AF](hipy)", - "api": "http://localhost:5757/api/AppFei?do=py&pwd=dzyyds", + "key": "hipy_py_丫丫动漫[AG¹]", + "name": "丫丫动漫[AG¹](hipy)", + "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppFei?do=py&pwd=dzyyds&extend=https%3A%2F%2Fysc.yy-fun.cc%2Ffeiapp" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_麒麟[AFX]", - "name": "麒麟[AFX](hipy)", - "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", + "key": "catvod_荐片", + "name": "荐片(cat)", + "api": "http://localhost:5757/api/荐片?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "hipy", + "lang": "cat", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&extend=https%3A%2F%2Fqh.70qh.top", - "category": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=https%3A%2F%2Fqh.70qh.top" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_TVB云播[AFX]", - "name": "TVB云播[AFX](hipy)", - "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", + "key": "hipy_py_OMOfun[AG¹]", + "name": "OMOfun[AG¹](hipy)", + "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&extend=http%3A%2F%2Fapp.hktvyb.cc" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_粉象[AFX]", - "name": "粉象[AFX](hipy)", - "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", + "key": "drpyS_美颜怪[擦]", + "name": "美颜怪[擦](DS)", + "api": "http://localhost:5757/api/美颜怪[擦]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "hipy", + "searchable": 0, + "lang": "ds", "status": "success", "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&extend=http%3A%2F%2Fhost1.sopython.top%2Fhost.json", - "category": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=http%3A%2F%2Fhost1.sopython.top%2Fhost.json" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_火猫影视[AFX]", - "name": "火猫影视[AFX](hipy)", - "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", + "key": "hipy_py_雪豹视频[Hs]", + "name": "雪豹视频[Hs](hipy)", + "api": "http://localhost:5757/api/AppHs?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fcunchu8.obs.cn-north-4.myhuaweicloud.com%2Fconfig.json%22%2C%22parse%22%3A%7B%22JL4K%22%3A%22http%3A%2F%2F194.147.100.155%3A7891%2F%3Furl%3D%22%7D%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_拾光视频[Hs]", - "name": "拾光视频[Hs](hipy)", - "api": "http://localhost:5757/api/AppHs?do=py&pwd=dzyyds", + "key": "hipy_py_即看影视[AS]", + "name": "即看影视[AS](hipy)", + "api": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppHs?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fdy.jmzp.net.cn%22%2C%22app_id%22%3A%22shiguang%22%2C%22deviceid%22%3A%22%22%2C%22versionCode%22%3A%2210000%22%2C%22UMENG_CHANNEL%22%3A%22guan%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_五八[AG¹]", - "name": "五八[AG¹](hipy)", - "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + "key": "catvod_喜刷刷", + "name": "喜刷刷(cat)", + "api": "http://localhost:5757/api/喜刷刷?do=cat&pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "hipy", + "searchable": 0, + "lang": "cat", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fdy.58ys.vip%22%2C%22key%22%3A%22JEWibY1AgWF0V1xx%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_丫丫动漫[AG¹]", - "name": "丫丫动漫[AG¹](hipy)", - "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + "key": "catvod_yikm[游戏]", + "name": "yikm[游戏](cat)", + "api": "http://localhost:5757/api/yikm[游戏]?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "hipy", + "lang": "cat", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22http%3A%2F%2Ftv.yy-fun.cc%22%2C%22key%22%3A%22qkxnwkfjwpcnwycl%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_OMOfun[AG¹]", - "name": "OMOfun[AG¹](hipy)", - "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + "key": "catvod_爱玩音乐", + "name": "爱玩音乐(cat)", + "api": "http://localhost:5757/api/爱玩音乐?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "hipy", + "lang": "cat", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fapp.omofun1.top%22%2C%22key%22%3A%2266dc309cbeeca454%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, - { - "key": "hipy_py_茉莉[AG¹]", - "name": "茉莉[AG¹](hipy)", - "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + { + "key": "hipy_py_麒麟[AFX]", + "name": "麒麟[AFX](hipy)", + "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fgitee.com%2Fwmmoliill%2Fwimg%2Fraw%2Fmaster%2Fimg%2Fbk%2F9.txt%22%2C%22key%22%3A%2288689667dce61725%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_雪豹视频[Hs]", - "name": "雪豹视频[Hs](hipy)", - "api": "http://localhost:5757/api/AppHs?do=py&pwd=dzyyds", + "key": "hipy_py_粉象[AFX]", + "name": "粉象[AFX](hipy)", + "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppHs?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fdy.jszdzs.com%22%2C%22app_id%22%3A%22xuebao%22%2C%22deviceid%22%3A%22%22%2C%22versionCode%22%3A%2221300%22%2C%22UMENG_CHANNEL%22%3A%22share%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_魔方[AG¹]", - "name": "魔方[AG¹](hipy)", - "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + "key": "catvod_海龟", + "name": "海龟(cat)", + "api": "http://localhost:5757/api/海龟?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "hipy", + "lang": "cat", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fsnysw.xyz%2Fmf4kzs327.txt%22%2C%22key%22%3A%221234567887654321%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_即看影视[AS]", - "name": "即看影视[AS](hipy)", - "api": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds", + "key": "hipy_py_拾光视频[Hs]", + "name": "拾光视频[Hs](hipy)", + "api": "http://localhost:5757/api/AppHs?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fskyappdata-1321528676.cos.accelerate.myqcloud.com%2F4kapp%2Fappipr.txt%22%2C%22key%22%3A%22ygcnbckhcuvygdyb%22%2C%22iv%22%3A%224023892775143708%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3206,40 +2721,34 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppToV5?do=py&pwd=dzyyds&extend=http%3A%2F%2F118.89.203.120%3A8762" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_紫云[AV¹]", - "name": "紫云[AV¹](hipy)", - "api": "http://localhost:5757/api/AppV1?do=py&pwd=dzyyds", + "key": "hipy_py_闪影[AV²]", + "name": "闪影[AV²](hipy)", + "api": "http://localhost:5757/api/AppV2²?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppV1?do=py&pwd=dzyyds&extend=http%3A%2F%2Fziyuncms.feifan12.xyz%2Fapi.php" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_皮皮虾[ATV⁵]", - "name": "皮皮虾[ATV⁵](hipy)", - "api": "http://localhost:5757/api/AppToV5?do=py&pwd=dzyyds", + "key": "hipy_py_紫云[AV¹]", + "name": "紫云[AV¹](hipy)", + "api": "http://localhost:5757/api/AppV1?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppToV5?do=py&pwd=dzyyds&extend=http%3A%2F%2F38.55.237.41%3A8762" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3251,10 +2760,8 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fkankelm.cn%3A2024%2Fappdomain.txt%22%2C%22key%22%3A%22ygcnbcvybqqckwqy%22%2C%22iv%22%3A%221583560747143708%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3266,115 +2773,99 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fdmsk.oss-rg-china-mainland.aliyuncs.com%2Fdmapp%2Fdmapi.txt%22%2C%22key%22%3A%22ygcnbcobcegtgigg%22%2C%22iv%22%3A%224058263969143708%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_闪影[AV²]", - "name": "闪影[AV²](hipy)", + "key": "hipy_py_剧下饭[AV²]", + "name": "剧下饭[AV²](hipy)", "api": "http://localhost:5757/api/AppV2²?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppV2%C2%B2?do=py&pwd=dzyyds&extend=http%3A%2F%2F38.47.213.61%3A41271" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_剧下饭[AV²]", - "name": "剧下饭[AV²](hipy)", - "api": "http://localhost:5757/api/AppV2²?do=py&pwd=dzyyds", + "key": "hipy_py_剧永久[AV⁶]", + "name": "剧永久[AV⁶](hipy)", + "api": "http://localhost:5757/api/AppV6?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppV2%C2%B2?do=py&pwd=dzyyds&extend=http%3A%2F%2Fjxfmax.juxiafan.com" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_剧永久[AV⁶]", - "name": "剧永久[AV⁶](hipy)", + "key": "hipy_py_剧下饭[AV⁶]", + "name": "剧下饭[AV⁶](hipy)", "api": "http://localhost:5757/api/AppV6?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppV6?do=py&pwd=dzyyds&extend=%7B%22api%22%3A%22http%3A%2F%2Fyjyi.juyongjiu.com%2Ficciu_api.php%2Fv1.vod%22%2C%22datasignkey%22%3A%226QQNUsP3PkD2ajJCPCY8%22%2C%22apisignkey%22%3A%22lvdoutv-1.0.0%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_Free影视[AS]", - "name": "Free影视[AS](hipy)", - "api": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds", + "key": "hipy_py_皮皮虾[ATV⁵]", + "name": "皮皮虾[ATV⁵](hipy)", + "api": "http://localhost:5757/api/AppToV5?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fsk.xiaoyaoys.top%2Fskkkkkkk.txt%22%2C%22key%22%3A%22ygcnbcczduwydmrs%22%2C%22iv%22%3A%224672921073143708%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_剧下饭[AV⁶]", - "name": "剧下饭[AV⁶](hipy)", - "api": "http://localhost:5757/api/AppV6?do=py&pwd=dzyyds", + "key": "hipy_py_依赖测试", + "name": "依赖测试(hipy)", + "api": "http://localhost:5757/api/依赖测试?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppV6?do=py&pwd=dzyyds&extend=http%3A%2F%2Fjxfmax.juxiafan.com%2Ficciu_api.php%2Fv1.vod" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_掌上追剧[AG³]", - "name": "掌上追剧[AG³](hipy)", - "api": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds", + "key": "hipy_py_动作代理测试", + "name": "动作代理测试(hipy)", + "api": "http://localhost:5757/api/动作代理测试?do=py&pwd=dzyyds", "type": 4, - "searchable": 1, + "searchable": 0, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22http%3A%2F%2Ftvb.yy-fun.cc%22%2C%22key%22%3A%22jcTz6Jda2aKrH8Tk%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_依赖测试", - "name": "依赖测试(hipy)", - "api": "http://localhost:5757/api/依赖测试?do=py&pwd=dzyyds", + "key": "hipy_py_掌上追剧[AG³]", + "name": "掌上追剧[AG³](hipy)", + "api": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%BE%9D%E8%B5%96%E6%B5%8B%E8%AF%95?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3386,10 +2877,8 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppYqk?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fgapi0320.3njzmrx1.com%2Fconfig.json%2Chttps%3A%2F%2Fgapi0320.lq0okex8.com%2Fconfig.json%2Chttps%3A%2F%2Fgapi0320.zabqs8xp.com%2Fconfig.json%2Chttps%3A%2F%2Fyappconfig-20250628-1318635097.cos.ap-shanghai.myqcloud.com%2Fconfig.json%2Chttps%3A%2F%2Fyconfig-20250628-1360051343.cos.ap-guangzhou.myqcloud.com%2Fconfig.json%22%2C%22appId%22%3A%22d6d520ea90904f1ba680ed6c9c9f9007%22%2C%22appkey%22%3A%2270af67d2b6cf47679b397ea4c1886877%22%2C%22udid%22%3A%22bfc18c00-c866-46cb-8d7b-121c39b942d4%22%2C%22bundlerId%22%3A%22com.flotimingo.ts%22%2C%22source%22%3A%221001_default%22%2C%22version%22%3A%221.3.10%22%2C%22versionCode%22%3A1104%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3401,40 +2890,34 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppYqk?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fgapi0725.5p8jcjc.com%2Fconfig.json%2Chttps%3A%2F%2Fgapi0725.olrv5gz.com%2Fconfig.json%2Chttps%3A%2F%2Fgapi0725.mvljeat.com%2Fconfig.json%2Chttps%3A%2F%2Fjzapp-1318635097.cos.ap-shanghai.myqcloud.com%2Fconfig.json%2Chttps%3A%2F%2Fjuzi-config-1360051343.cos.ap-shanghai.myqcloud.com%2Fconfig.json%22%2C%22appId%22%3A%22fea23e11fc1241409682880e15fb2851%22%2C%22appkey%22%3A%22f384b87cc9ef41e4842dda977bae2c7f%22%2C%22udid%22%3A%22bfc18c00-c866-46cb-8d7b-121c39b942d4%22%2C%22bundlerId%22%3A%22com.voraguzzee.ts%22%2C%22source%22%3A%221003_default%22%2C%22version%22%3A%221.0.1%22%2C%22versionCode%22%3A1000%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_动作代理测试", - "name": "动作代理测试(hipy)", - "api": "http://localhost:5757/api/动作代理测试?do=py&pwd=dzyyds", + "key": "hipy_py_懒懒视频", + "name": "懒懒视频(hipy)", + "api": "http://localhost:5757/api/懒懒视频?do=py&pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8A%A8%E4%BD%9C%E4%BB%A3%E7%90%86%E6%B5%8B%E8%AF%95?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_懒懒视频", - "name": "懒懒视频(hipy)", - "api": "http://localhost:5757/api/懒懒视频?do=py&pwd=dzyyds", + "key": "hipy_py_Free影视[AS]", + "name": "Free影视[AS](hipy)", + "api": "http://localhost:5757/api/AppSk?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%87%92%E6%87%92%E8%A7%86%E9%A2%91?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3445,26 +2928,22 @@ "searchable": 1, "lang": "hipy", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%93%94%E5%93%A9%E5%93%94%E5%93%A9?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "3/4 接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_新韩剧网", - "name": "新韩剧网(hipy)", - "api": "http://localhost:5757/api/新韩剧网?do=py&pwd=dzyyds", + "key": "hipy_py_热播APP", + "name": "热播APP(hipy)", + "api": "http://localhost:5757/api/热播APP?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%96%B0%E9%9F%A9%E5%89%A7%E7%BD%91?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3476,87 +2955,47 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%93%87%E5%93%87APP?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_欣欣影视", - "name": "欣欣影视(hipy)", - "api": "http://localhost:5757/api/欣欣影视?do=py&pwd=dzyyds", + "key": "hipy_py_新韩剧网", + "name": "新韩剧网(hipy)", + "api": "http://localhost:5757/api/新韩剧网?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%AC%A3%E6%AC%A3%E5%BD%B1%E8%A7%86?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "hipy_py_河马短剧", - "name": "河马短剧(hipy)", - "api": "http://localhost:5757/api/河马短剧?do=py&pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "hipy", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%B2%B3%E9%A9%AC%E7%9F%AD%E5%89%A7?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%B2%B3%E9%A9%AC%E7%9F%AD%E5%89%A7?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "hipy_py_兄弟影视", - "name": "兄弟影视(hipy)", - "api": "http://localhost:5757/api/兄弟影视?do=py&pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "hipy", - "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%85%84%E5%BC%9F%E5%BD%B1%E8%A7%86?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%85%84%E5%BC%9F%E5%BD%B1%E8%A7%86?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_热播APP", - "name": "热播APP(hipy)", - "api": "http://localhost:5757/api/热播APP?do=py&pwd=dzyyds", + "key": "hipy_py_欣欣影视", + "name": "欣欣影视(hipy)", + "api": "http://localhost:5757/api/欣欣影视?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%83%AD%E6%92%ADAPP?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_新浪资源", - "name": "新浪资源(hipy)", - "api": "http://localhost:5757/api/新浪资源?do=py&pwd=dzyyds", + "key": "hipy_py_看客TV", + "name": "看客TV(hipy)", + "api": "http://localhost:5757/api/看客TV?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%96%B0%E6%B5%AA%E8%B5%84%E6%BA%90?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3568,25 +3007,8 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8B%AC%E6%92%AD%E5%BA%93?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", - "manuallyMarked": false - }, - { - "key": "hipy_py_看客TV", - "name": "看客TV(hipy)", - "api": "http://localhost:5757/api/看客TV?do=py&pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "hipy", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%9C%8B%E5%AE%A2TV?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3598,147 +3020,86 @@ "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%AB%AF%E6%9C%A8?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, - { - "key": "hipy_py_资源管理", - "name": "资源管理(hipy)", - "api": "http://localhost:5757/api/资源管理?do=py&pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "hipy", - "status": "success", - "message": "手动标记为正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%B5%84%E6%BA%90%E7%AE%A1%E7%90%86?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E8%B5%84%E6%BA%90%E7%AE%A1%E7%90%86?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.213Z", - "manuallyMarked": true - }, { "key": "hipy_py_麻雀视频", - "name": "麻雀视频(hipy)", - "api": "http://localhost:5757/api/麻雀视频?do=py&pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "hipy", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%BA%BB%E9%9B%80%E8%A7%86%E9%A2%91?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", - "manuallyMarked": false - }, - { - "key": "hipy_py_麦田影院", - "name": "麦田影院(hipy)", - "api": "http://localhost:5757/api/麦田影院?do=py&pwd=dzyyds", - "type": 4, - "searchable": 1, - "lang": "hipy", - "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%BA%A6%E7%94%B0%E5%BD%B1%E9%99%A2?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", - "manuallyMarked": false - }, - { - "key": "hipy_py_猎手APP", - "name": "猎手APP(hipy)", - "api": "http://localhost:5757/api/猎手APP?do=py&pwd=dzyyds", + "name": "麻雀视频(hipy)", + "api": "http://localhost:5757/api/麻雀视频?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8C%8E%E6%89%8BAPP?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_瓜子", - "name": "瓜子(hipy)", - "api": "http://localhost:5757/api/瓜子?do=py&pwd=dzyyds", + "key": "php_坚果视频 ᵈᶻ", + "name": "坚果视频 ᵈᶻ(PHP)", + "api": "http://localhost:5757/api/坚果视频 ᵈᶻ?do=php&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "hipy", + "lang": "php", "status": "success", - "message": "分类接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%93%9C%E5%AD%90?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%93%9C%E5%AD%90?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_爱瓜APP", - "name": "爱瓜APP(hipy)", - "api": "http://localhost:5757/api/爱瓜APP?do=py&pwd=dzyyds", + "key": "hipy_py_麦田影院", + "name": "麦田影院(hipy)", + "api": "http://localhost:5757/api/麦田影院?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%88%B1%E7%93%9CAPP?do=py&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_人人影视 ᵈᶻ", - "name": "人人影视 ᵈᶻ(PHP)", - "api": "http://localhost:5757/api/人人影视 ᵈᶻ?do=php&pwd=dzyyds", + "key": "php_金牌 ᵈᶻ", + "name": "金牌 ᵈᶻ(PHP)", + "api": "http://localhost:5757/api/金牌 ᵈᶻ?do=php&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "php", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%BA%BA%E4%BA%BA%E5%BD%B1%E8%A7%86%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_坚果视频 ᵈᶻ", - "name": "坚果视频 ᵈᶻ(PHP)", - "api": "http://localhost:5757/api/坚果视频 ᵈᶻ?do=php&pwd=dzyyds", + "key": "php_人人影视 ᵈᶻ", + "name": "人人影视 ᵈᶻ(PHP)", + "api": "http://localhost:5757/api/人人影视 ᵈᶻ?do=php&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "php", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%9D%9A%E6%9E%9C%E8%A7%86%E9%A2%91%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_山有木兮 ᵈᶻ", - "name": "山有木兮 ᵈᶻ(PHP)", - "api": "http://localhost:5757/api/山有木兮 ᵈᶻ?do=php&pwd=dzyyds", + "key": "hipy_py_猎手APP", + "name": "猎手APP(hipy)", + "api": "http://localhost:5757/api/猎手APP?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "hipy", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%B1%B1%E6%9C%89%E6%9C%A8%E5%85%AE%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -3750,357 +3111,305 @@ "lang": "php", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%BA%BB%E9%9B%80%E8%A7%86%E9%A2%91%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_B站 ᵈᶻ", - "name": "B站 ᵈᶻ(PHP)", - "api": "http://localhost:5757/api/B站 ᵈᶻ?do=php&pwd=dzyyds", + "key": "php_山有木兮 ᵈᶻ", + "name": "山有木兮 ᵈᶻ(PHP)", + "api": "http://localhost:5757/api/山有木兮 ᵈᶻ?do=php&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "php", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/B%E7%AB%99%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_荐片影视 ᵈᶻ", - "name": "荐片影视 ᵈᶻ(PHP)", - "api": "http://localhost:5757/api/荐片影视 ᵈᶻ?do=php&pwd=dzyyds", + "key": "php_B站 ᵈᶻ", + "name": "B站 ᵈᶻ(PHP)", + "api": "http://localhost:5757/api/B站 ᵈᶻ?do=php&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "php", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%8D%90%E7%89%87%E5%BD%B1%E8%A7%86%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_金牌 ᵈᶻ", - "name": "金牌 ᵈᶻ(PHP)", - "api": "http://localhost:5757/api/金牌 ᵈᶻ?do=php&pwd=dzyyds", + "key": "php_哇哇影视 ᵈᶻ", + "name": "哇哇影视 ᵈᶻ(PHP)", + "api": "http://localhost:5757/api/哇哇影视 ᵈᶻ?do=php&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "php", "status": "success", "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%87%91%E7%89%8C%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_哇哇影视 ᵈᶻ", - "name": "哇哇影视 ᵈᶻ(PHP)", - "api": "http://localhost:5757/api/哇哇影视 ᵈᶻ?do=php&pwd=dzyyds", + "key": "hipy_py_河马短剧", + "name": "河马短剧(hipy)", + "api": "http://localhost:5757/api/河马短剧?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "hipy", "status": "success", - "message": "推荐接口正常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%93%87%E5%93%87%E5%BD%B1%E8%A7%86%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_3Q影视[优]", - "name": "3Q影视[优](DS)", - "api": "http://localhost:5757/api/3Q影视[优]?pwd=dzyyds", + "key": "hipy_py_兄弟影视", + "name": "兄弟影视(hipy)", + "api": "http://localhost:5757/api/兄弟影视?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "error", - "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/3Q%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.210Z", + "lang": "hipy", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_二小[盘]", - "name": "二小[盘](DS)", - "api": "http://localhost:5757/api/二小[盘]?pwd=dzyyds", + "key": "hipy_py_爱瓜APP", + "name": "爱瓜APP(hipy)", + "api": "http://localhost:5757/api/爱瓜APP?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "error", - "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E4%BA%8C%E5%B0%8F[%E7%9B%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E4%BA%8C%E5%B0%8F[%E7%9B%98]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "lang": "hipy", + "status": "success", + "message": "推荐接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_玩偶哥哥DM[盘]", - "name": "玩偶哥哥DM[盘](DS)", - "api": "http://localhost:5757/api/玩偶哥哥DM[盘]?pwd=dzyyds", + "key": "hipy_py_瓜子", + "name": "瓜子(hipy)", + "api": "http://localhost:5757/api/瓜子?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "error", - "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8E%A9%E5%81%B6%E5%93%A5%E5%93%A5DM[%E7%9B%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%8E%A9%E5%81%B6%E5%93%A5%E5%93%A5DM[%E7%9B%98]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "lang": "hipy", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_玩偶哥哥[盘]", - "name": "玩偶哥哥[盘](DS)", - "api": "http://localhost:5757/api/玩偶哥哥[盘]?pwd=dzyyds", + "key": "hipy_py_资源管理", + "name": "资源管理(hipy)", + "api": "http://localhost:5757/api/资源管理?do=py&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "error", - "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%8E%A9%E5%81%B6%E5%93%A5%E5%93%A5[%E7%9B%98]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%8E%A9%E5%81%B6%E5%93%A5%E5%93%A5[%E7%9B%98]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "lang": "hipy", + "status": "success", + "message": "分类接口正常 (容错:分类2)", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_二小ᵐ[盘]", - "name": "二小ᵐ[盘](DS)", - "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", + "key": "php_荐片影视 ᵈᶻ", + "name": "荐片影视 ᵈᶻ(PHP)", + "api": "http://localhost:5757/api/荐片影视 ᵈᶻ?do=php&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", - "status": "error", - "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5sqvn6YZ%2BAGwhNKsgAAAA", - "category": "http://localhost:5757/api/%E7%BD%91%E7%9B%98[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=H4sIAAAAAAAAA9PT088qzs%2FTfzp%2F%2FtMJvS9be5%2FvXacHElF5sqvn6YZ%2BAGwhNKsgAAAA" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "lang": "php", + "status": "success", + "message": "分类接口正常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_NT动漫[漫]", - "name": "NT动漫[漫](DS)", - "api": "http://localhost:5757/api/NT动漫[漫]?pwd=dzyyds", + "key": "drpyS_啊哈DJ[听]", + "name": "啊哈DJ[听](DS)", + "api": "http://localhost:5757/api/啊哈DJ[听]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", - "status": "error", - "message": "推荐和分类接口均异常", + "status": "success", + "message": "2/4 接口正常", "testUrls": { - "home": "http://localhost:5757/api/NT%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds", - "category": "http://localhost:5757/api/NT%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds&ac=list&t=1&pg=1" + "home": "http://localhost:5757/api/%E5%95%8A%E5%93%88DJ[%E5%90%AC]?pwd=dzyyds", + "category": "http://localhost:5757/api/%E5%95%8A%E5%93%88DJ[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1", + "search": "http://localhost:5757/api/%E5%95%8A%E5%93%88DJ[%E5%90%AC]?pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95", + "detail": "http://localhost:5757/api/%E5%95%8A%E5%93%88DJ[%E5%90%AC]?pwd=dzyyds&ac=detail&ids=1" }, - "checkTime": "2026-03-13T12:37:39.211Z", + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_嗷呜动漫[漫]", - "name": "嗷呜动漫[漫](DS)", - "api": "http://localhost:5757/api/嗷呜动漫[漫]?pwd=dzyyds", + "key": "drpyS_3Q影视[优]", + "name": "3Q影视[优](DS)", + "api": "http://localhost:5757/api/3Q影视[优]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", "testUrls": { - "home": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds&ac=list&t=1&pg=1" + "home": "http://localhost:5757/api/3Q%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds", + "category": "http://localhost:5757/api/3Q%E5%BD%B1%E8%A7%86[%E4%BC%98]?pwd=dzyyds&ac=list&t=1&pg=1" }, - "checkTime": "2026-03-13T12:37:39.211Z", + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_雪花电影[磁]", - "name": "雪花电影[磁](DS)", - "api": "http://localhost:5757/api/雪花电影[磁]?pwd=dzyyds", + "key": "drpyS_玩偶哥哥DM[盘]", + "name": "玩偶哥哥DM[盘](DS)", + "api": "http://localhost:5757/api/玩偶哥哥DM[盘]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9B%AA%E8%8A%B1%E7%94%B5%E5%BD%B1[%E7%A3%81]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%9B%AA%E8%8A%B1%E7%94%B5%E5%BD%B1[%E7%A3%81]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_番茄短剧[短]", - "name": "番茄短剧[短](DS)", - "api": "http://localhost:5757/api/番茄短剧[短]?pwd=dzyyds", + "key": "drpyS_玩偶哥哥[盘]", + "name": "玩偶哥哥[盘](DS)", + "api": "http://localhost:5757/api/玩偶哥哥[盘]?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 1, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E7%9F%AD%E5%89%A7[%E7%9F%AD]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_围观短剧 ᵈᶻ[短]", - "name": "围观短剧 ᵈᶻ[短](PHP)", - "api": "http://localhost:5757/api/围观短剧 ᵈᶻ[短]?do=php&pwd=dzyyds", + "key": "drpyS_二小[盘]", + "name": "二小[盘](DS)", + "api": "http://localhost:5757/api/二小[盘]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "php", + "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%9B%B4%E8%A7%82%E7%9F%AD%E5%89%A7%20%E1%B5%88%E1%B6%BB[%E7%9F%AD]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%9B%B4%E8%A7%82%E7%9F%AD%E5%89%A7%20%E1%B5%88%E1%B6%BB[%E7%9F%AD]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_嗷呜动漫[漫]", - "name": "嗷呜动漫[漫](cat)", - "api": "http://localhost:5757/api/嗷呜动漫[漫]?do=cat&pwd=dzyyds", + "key": "drpyS_二小ᵐ[盘]", + "name": "二小ᵐ[盘](DS)", + "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_奇奇[官]", - "name": "奇奇[官](cat)", - "api": "http://localhost:5757/api/奇奇[官]?do=cat&pwd=dzyyds", + "key": "drpyS_欧歌ᵐ[盘]", + "name": "欧歌ᵐ[盘](DS)", + "api": "http://localhost:5757/api/网盘[模板]?pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A5%87%E5%A5%87[%E5%AE%98]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%A5%87%E5%A5%87[%E5%AE%98]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "php_奇奇 ᵈᶻ[官]", - "name": "奇奇 ᵈᶻ[官](PHP)", - "api": "http://localhost:5757/api/奇奇 ᵈᶻ[官]?do=php&pwd=dzyyds", + "key": "drpyS_NT动漫[漫]", + "name": "NT动漫[漫](DS)", + "api": "http://localhost:5757/api/NT动漫[漫]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "php", + "searchable": 2, + "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%A5%87%E5%A5%87%20%E1%B5%88%E1%B6%BB[%E5%AE%98]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%A5%87%E5%A5%87%20%E1%B5%88%E1%B6%BB[%E5%AE%98]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "catvod_酷酷[官]", - "name": "酷酷[官](cat)", - "api": "http://localhost:5757/api/酷酷[官]?do=cat&pwd=dzyyds", + "key": "php_围观短剧 ᵈᶻ[短]", + "name": "围观短剧 ᵈᶻ[短](PHP)", + "api": "http://localhost:5757/api/围观短剧 ᵈᶻ[短]?do=php&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "cat", + "lang": "php", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%85%B7%E9%85%B7[%E5%AE%98]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%85%B7%E9%85%B7[%E5%AE%98]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_啊哈DJ[听]", - "name": "啊哈DJ[听](DS)", - "api": "http://localhost:5757/api/啊哈DJ[听]?pwd=dzyyds", + "key": "drpyS_嗷呜动漫[漫]", + "name": "嗷呜动漫[漫](DS)", + "api": "http://localhost:5757/api/嗷呜动漫[漫]?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", "testUrls": { - "home": "http://localhost:5757/api/%E5%95%8A%E5%93%88DJ[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%95%8A%E5%93%88DJ[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" + "home": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds", + "category": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB[%E6%BC%AB]?pwd=dzyyds&ac=list&t=1&pg=1" }, - "checkTime": "2026-03-13T12:37:39.211Z", + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_音乐聚合[听]", - "name": "音乐聚合[听](DS)", - "api": "http://localhost:5757/api/音乐聚合[听]?pwd=dzyyds", + "key": "catvod_嗷呜动漫[漫]", + "name": "嗷呜动漫[漫](cat)", + "api": "http://localhost:5757/api/嗷呜动漫[漫]?do=cat&pwd=dzyyds", "type": 4, "searchable": 1, - "lang": "ds", + "lang": "cat", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9F%B3%E4%B9%90%E8%81%9A%E5%90%88[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%9F%B3%E4%B9%90%E8%81%9A%E5%90%88[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_播客[听]", - "name": "播客[听](DS)", - "api": "http://localhost:5757/api/播客[听]?pwd=dzyyds", + "key": "drpyS_雪花电影[磁]", + "name": "雪花电影[磁](DS)", + "api": "http://localhost:5757/api/雪花电影[磁]?pwd=dzyyds", "type": 4, - "searchable": 0, + "searchable": 2, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E6%92%AD%E5%AE%A2[%E5%90%AC]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E6%92%AD%E5%AE%A2[%E5%90%AC]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_番茄漫画[画]", - "name": "番茄漫画[画](DS)", - "api": "http://localhost:5757/api/番茄漫画[画]?pwd=dzyyds", + "key": "drpyS_雷鲸小站[盘]", + "name": "雷鲸小站[盘](DS)", + "api": "http://localhost:5757/api/雷鲸小站[盘]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E6%BC%AB%E7%94%BB[%E7%94%BB]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E6%BC%AB%E7%94%BB[%E7%94%BB]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4112,11 +3421,8 @@ "lang": "php", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%BB%85%E5%A3%AB%E6%BC%AB%E7%94%BB%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%BB%85%E5%A3%AB%E6%BC%AB%E7%94%BB%20%E1%B5%88%E1%B6%BB[%E7%94%BB]?do=php&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4128,11 +3434,8 @@ "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E6%BC%AB%E7%94%BB[%E7%94%BB]?do=cat&pwd=dzyyds", - "category": "http://localhost:5757/api/%E7%95%AA%E8%8C%84%E6%BC%AB%E7%94%BB[%E7%94%BB]?do=cat&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4144,11 +3447,8 @@ "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BB%93%E9%BC%A0", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BB%93%E9%BC%A0" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4160,107 +3460,86 @@ "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%92%96%E5%95%A1", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%92%96%E5%95%A1" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_云云_Appget", - "name": "云云[M](GET)", + "key": "drpyS_鲸鱼_Appget", + "name": "鲸鱼[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BA%91%E4%BA%91", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E4%BA%91%E4%BA%91" - }, - "checkTime": "2026-03-13T12:37:39.211Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_鲸鱼_Appget", - "name": "鲸鱼[M](GET)", + "key": "drpyS_火锅_Appget", + "name": "火锅[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E9%B2%B8%E9%B1%BC", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E9%B2%B8%E9%B1%BC" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_王子_Appget", - "name": "王子[M](GET)", + "key": "drpyS_旗星_Appget", + "name": "旗星[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%8E%8B%E5%AD%90", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%8E%8B%E5%AD%90" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_旗星_Appget", - "name": "旗星[M](GET)", + "key": "drpyS_剧梦_Appget", + "name": "剧梦[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E6%97%97%E6%98%9F", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E6%97%97%E6%98%9F" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_剧梦_Appget", - "name": "剧梦[M](GET)", + "key": "drpyS_顾我_Appget", + "name": "顾我[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%89%A7%E6%A2%A6", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E5%89%A7%E6%A2%A6" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_顾我_Appget", - "name": "顾我[M](GET)", + "key": "drpyS_爆炸_Appget", + "name": "爆炸[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E9%A1%BE%E6%88%91", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E9%A1%BE%E6%88%91" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4272,27 +3551,34 @@ "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%81%B5%E8%99%8E", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%81%B5%E8%99%8E" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_爆炸_Appget", - "name": "爆炸[M](GET)", + "key": "drpyS_云云_Appget", + "name": "云云[M](GET)", "api": "http://localhost:5757/api/Appget[模板]?pwd=dzyyds", "type": 4, "searchable": 1, "lang": "unknown", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%88%86%E7%82%B8", - "category": "http://localhost:5757/api/Appget[%E6%A8%A1%E6%9D%BF]?pwd=dzyyds&ac=list&t=1&pg=1&extend=..%2Fjson%2FApp%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE.json%24%E7%88%86%E7%82%B8" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "drpyS_18av[密]", + "name": "18av[密](DS)", + "api": "http://localhost:5757/api/18av[密]?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "error", + "message": "推荐和分类接口均异常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4304,11 +3590,8 @@ "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/55%E5%BD%B1%E8%A7%86?pwd=dzyyds", - "category": "http://localhost:5757/api/55%E5%BD%B1%E8%A7%86?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4320,27 +3603,21 @@ "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/999%E7%89%87?pwd=dzyyds", - "category": "http://localhost:5757/api/999%E7%89%87?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_18av[密]", - "name": "18av[密](DS)", - "api": "http://localhost:5757/api/18av[密]?pwd=dzyyds", + "key": "drpyS_TVB云播", + "name": "TVB云播(DS)", + "api": "http://localhost:5757/api/TVB云播?pwd=dzyyds", "type": 4, "searchable": 2, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/18av[%E5%AF%86]?pwd=dzyyds", - "category": "http://localhost:5757/api/18av[%E5%AF%86]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4352,27 +3629,8 @@ "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E5%8D%AB%E6%98%9F%E5%BD%B1%E8%A7%86?pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%8D%AB%E6%98%9F%E5%BD%B1%E8%A7%86?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", - "manuallyMarked": false - }, - { - "key": "drpyS_草榴社区[密]", - "name": "草榴社区[密](DS)", - "api": "http://localhost:5757/api/草榴社区[密]?pwd=dzyyds", - "type": 4, - "searchable": 2, - "lang": "ds", - "status": "error", - "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E8%8D%89%E6%A6%B4%E7%A4%BE%E5%8C%BA[%E5%AF%86]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E8%8D%89%E6%A6%B4%E7%A4%BE%E5%8C%BA[%E5%AF%86]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4384,27 +3642,21 @@ "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9D%9E%E5%87%A1%E9%87%87%E9%9B%86[%E9%87%87]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%9D%9E%E5%87%A1%E9%87%87%E9%9B%86[%E9%87%87]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_麻豆社[密]", - "name": "麻豆社[密](DS)", - "api": "http://localhost:5757/api/麻豆社[密]?pwd=dzyyds", + "key": "drpyS_零度", + "name": "零度(DS)", + "api": "http://localhost:5757/api/零度?pwd=dzyyds", "type": 4, - "searchable": 2, + "searchable": 0, "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%BA%BB%E8%B1%86%E7%A4%BE[%E5%AF%86]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%BA%BB%E8%B1%86%E7%A4%BE[%E5%AF%86]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4416,43 +3668,47 @@ "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%BB%91%E6%96%99%E4%B8%8D%E6%89%93%E7%83%8A[%E5%AF%86]?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%BB%91%E6%96%99%E4%B8%8D%E6%89%93%E7%83%8A[%E5%AF%86]?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "drpyS_零度", - "name": "零度(DS)", - "api": "http://localhost:5757/api/零度?pwd=dzyyds", + "key": "hipy_py_花柳影视[AFX]", + "name": "花柳影视[AFX](hipy)", + "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", "type": 4, - "searchable": 0, - "lang": "ds", + "searchable": 1, + "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9B%B6%E5%BA%A6?pwd=dzyyds", - "category": "http://localhost:5757/api/%E9%9B%B6%E5%BA%A6?pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_花柳影视[AFX]", - "name": "花柳影视[AFX](hipy)", + "key": "hipy_py_旗星[AG¹]", + "name": "旗星[AG¹](hipy)", + "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "hipy", + "status": "error", + "message": "推荐和分类接口均异常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "hipy_py_TVB云播[AFX]", + "name": "TVB云播[AFX](hipy)", "api": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22http%3A%2F%2Fnico.oiio.fun%22%7D", - "category": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22host%22%3A%22http%3A%2F%2Fnico.oiio.fun%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4464,11 +3720,8 @@ "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22http%3A%2F%2Fwww.yezitv.top%2Fdtym.json%22%7D", - "category": "http://localhost:5757/api/AppFox?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22host%22%3A%22http%3A%2F%2Fwww.yezitv.top%2Fdtym.json%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4480,61 +3733,63 @@ "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/AppMuou?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/AppMuou?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_旗星[AG¹]", - "name": "旗星[AG¹](hipy)", - "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + "key": "drpyS_麻豆社[密]", + "name": "麻豆社[密](DS)", + "api": "http://localhost:5757/api/麻豆社[密]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "hipy", + "searchable": 2, + "lang": "ds", "status": "error", "message": "推荐和分类接口均异常", "testUrls": { - "home": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22http%3A%2F%2Fys.qist.top%22%2C%22key%22%3A%222SWSPFxugBLPPOKo%22%7D", - "category": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22host%22%3A%22http%3A%2F%2Fys.qist.top%22%2C%22key%22%3A%222SWSPFxugBLPPOKo%22%7D" + "home": "http://localhost:5757/api/%E9%BA%BB%E8%B1%86%E7%A4%BE[%E5%AF%86]?pwd=dzyyds", + "category": "http://localhost:5757/api/%E9%BA%BB%E8%B1%86%E7%A4%BE[%E5%AF%86]?pwd=dzyyds&ac=list&t=1&pg=1" }, - "checkTime": "2026-03-13T12:37:39.212Z", + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_玲珑[AG¹]", - "name": "玲珑[AG¹](hipy)", - "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", + "key": "drpyS_草榴社区[密]", + "name": "草榴社区[密](DS)", + "api": "http://localhost:5757/api/草榴社区[密]?pwd=dzyyds", "type": 4, - "searchable": 1, - "lang": "hipy", + "searchable": 2, + "lang": "ds", "status": "error", - "message": "仅 1/4 接口正常", - "testUrls": { - "home": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fmac.555618.xyz%22%2C%22key%22%3A%22%23getapp%40TMD%402025%22%7D", - "category": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22host%22%3A%22https%3A%2F%2Fmac.555618.xyz%22%2C%22key%22%3A%22%23getapp%40TMD%402025%22%7D", - "search": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95&extend=%7B%22host%22%3A%22https%3A%2F%2Fmac.555618.xyz%22%2C%22key%22%3A%22%23getapp%40TMD%402025%22%7D", - "detail": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds&ac=detail&ids=1&extend=%7B%22host%22%3A%22https%3A%2F%2Fmac.555618.xyz%22%2C%22key%22%3A%22%23getapp%40TMD%402025%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "message": "推荐和分类接口均异常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_好震惊[AV²]", - "name": "好震惊[AV²](hipy)", - "api": "http://localhost:5757/api/AppV2²?do=py&pwd=dzyyds", + "key": "drpyS_短剧视频库", + "name": "短剧视频库(DS)", + "api": "http://localhost:5757/api/短剧视频库?pwd=dzyyds", + "type": 4, + "searchable": 2, + "lang": "ds", + "status": "error", + "message": "Cannot set properties of null (setting 'textContent')", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "hipy_py_玲珑[AG¹]", + "name": "玲珑[AG¹](hipy)", + "api": "http://localhost:5757/api/AppGet?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/AppV2%C2%B2?do=py&pwd=dzyyds&extend=http%3A%2F%2Fv.lnhaozhenjin.cn", - "category": "http://localhost:5757/api/AppV2%C2%B2?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=http%3A%2F%2Fv.lnhaozhenjin.cn" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4546,11 +3801,8 @@ "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/AppV2%C2%B9?do=py&pwd=dzyyds", - "category": "http://localhost:5757/api/AppV2%C2%B9?do=py&pwd=dzyyds&ac=list&t=1&pg=1" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4562,27 +3814,21 @@ "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2F99.jl8.top%2F1.txt%22%2C%22key%22%3A%22xnybssspqtwotuwj%22%7D", - "category": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22host%22%3A%22https%3A%2F%2F99.jl8.top%2F1.txt%22%2C%22key%22%3A%22xnybssspqtwotuwj%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_云云[AG³]", - "name": "云云[AG³](hipy)", + "key": "hipy_py_鲸鱼影视[AG³]", + "name": "鲸鱼影视[AG³](hipy)", "api": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fstaraugust123456.oss-cn-hangzhou.aliyuncs.com%2F2.txt%22%2C%22datakey%22%3A%22staraugust123456%22%2C%22api%22%3A2%7D", - "category": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22host%22%3A%22https%3A%2F%2Fstaraugust123456.oss-cn-hangzhou.aliyuncs.com%2F2.txt%22%2C%22datakey%22%3A%22staraugust123456%22%2C%22api%22%3A2%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4594,27 +3840,34 @@ "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/emby?do=py&pwd=dzyyds&extend=%7B%22server%22%3A%22http%3A%2F%2F139.9.106.196%3A2345%22%2C%22username%22%3A%22kid%22%2C%22password%22%3A%22%22%7D", - "category": "http://localhost:5757/api/emby?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22server%22%3A%22http%3A%2F%2F139.9.106.196%3A2345%22%2C%22username%22%3A%22kid%22%2C%22password%22%3A%22%22%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { - "key": "hipy_py_鲸鱼影视[AG³]", - "name": "鲸鱼影视[AG³](hipy)", + "key": "hipy_py_好震惊[AV²]", + "name": "好震惊[AV²](hipy)", + "api": "http://localhost:5757/api/AppV2²?do=py&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "hipy", + "status": "error", + "message": "推荐和分类接口均异常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "hipy_py_云云[AG³]", + "name": "云云[AG³](hipy)", "api": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds", "type": 4, "searchable": 1, "lang": "hipy", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds&extend=%7B%22host%22%3A%22https%3A%2F%2Fjingyu4k-1312635929.cos.ap-nanjing.myqcloud.com%2F1.json%22%2C%22datakey%22%3A%22AAdgrdghjfgswerA%22%2C%22api%22%3A2%7D", - "category": "http://localhost:5757/api/getapp3.4.4?do=py&pwd=dzyyds&ac=list&t=1&pg=1&extend=%7B%22host%22%3A%22https%3A%2F%2Fjingyu4k-1312635929.cos.ap-nanjing.myqcloud.com%2F1.json%22%2C%22datakey%22%3A%22AAdgrdghjfgswerA%22%2C%22api%22%3A2%7D" - }, - "checkTime": "2026-03-13T12:37:39.212Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4626,11 +3879,26 @@ "lang": "php", "status": "error", "message": "推荐和分类接口均异常", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", + "manuallyMarked": false + }, + { + "key": "hipy_py_新浪资源", + "name": "新浪资源(hipy)", + "api": "http://localhost:5757/api/新浪资源?do=py&pwd=dzyyds", + "type": 4, + "searchable": 1, + "lang": "hipy", + "status": "error", + "message": "仅 1/4 接口正常", "testUrls": { - "home": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds", - "category": "http://localhost:5757/api/%E5%97%B7%E5%91%9C%E5%8A%A8%E6%BC%AB%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds&ac=list&t=1&pg=1" + "home": "http://localhost:5757/api/%E6%96%B0%E6%B5%AA%E8%B5%84%E6%BA%90?do=py&pwd=dzyyds", + "category": "http://localhost:5757/api/%E6%96%B0%E6%B5%AA%E8%B5%84%E6%BA%90?do=py&pwd=dzyyds&ac=list&t=1&pg=1", + "search": "http://localhost:5757/api/%E6%96%B0%E6%B5%AA%E8%B5%84%E6%BA%90?do=py&pwd=dzyyds&ac=list&wd=%E6%B5%8B%E8%AF%95", + "detail": "http://localhost:5757/api/%E6%96%B0%E6%B5%AA%E8%B5%84%E6%BA%90?do=py&pwd=dzyyds&ac=detail&ids=1" }, - "checkTime": "2026-03-13T12:37:39.213Z", + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false }, { @@ -4642,10 +3910,8 @@ "lang": "php", "status": "error", "message": "推荐和分类接口均异常", - "testUrls": { - "home": "http://localhost:5757/api/%E9%9B%B6%E5%BA%A6%E5%BD%B1%E8%A7%86%20%E1%B5%88%E1%B6%BB?do=php&pwd=dzyyds" - }, - "checkTime": "2026-03-13T12:37:39.213Z", + "testUrls": {}, + "checkTime": "2026-03-14T05:07:55.462Z", "manuallyMarked": false } ] diff --git a/docs/updateRecord.md b/docs/updateRecord.md index bc2c2bb7..533ce260 100644 --- a/docs/updateRecord.md +++ b/docs/updateRecord.md @@ -1,5 +1,40 @@ # drpyS更新记录 +### 20260320 + +更新至V1.4.1 + +1. 完善后台管理功能,精心打磨各个功能和页面 +2. 设置中心源增加快捷后台管理、DS仓库入口 +3. 修复node24以上运行代码出现的警告 + +注意事项(node24以上存在兼容性问题,不是没法运行,而是类似APP模板这种源无法正常使用,还是推荐大家使用node23及以下版本) + +### 20260319 + +更新至V1.3.31 + +1. 增加后台管理插件,移除dns库,优化marked库 +2. 推荐使用node23版本,24以上会有兼容性问题 + +### 20260317 + +更新至V1.3.30 + +1. 优化文件头处理工具,支持完美JSON5对象文件头识别,新增PHP文件头支持,提高文件头读写速度 +2. 修复夸克工具无限转存逻辑异常 +3. 新增源、并优化bundle打包逻辑 +4. 尝试处理了一些内存泄露问题 + +### 20260315 + +更新至V1.3.29 + +1. 彻底解决ds代码问题导致的阻止程序退出 +2. 完善全局require处理,支持cjs文件里引入 `axios` 等对象不报错 +3. 彻底优化本地bundle包 +4. 更新迅雷网盘解析支持,设置中心推送里可以推送播放迅雷链接 + ### 20260314 更新至V1.3.28 @@ -7,6 +42,8 @@ 1. 合并zy佬在mcp服务上做的一些更新 2. 优化 drpyS内存开销,杜绝无限内存增长,实测 pm2运行的ds经历多轮源可用性测试后仍旧可以 长期低于 400mb内存占用 3. 优化本地bundle包几乎完美 +4. 优化阿里和UC网盘解析 +5. 处理了一些失效的源 ### 20260301 diff --git a/drpy-node-admin/.env.example b/drpy-node-admin/.env.example new file mode 100644 index 00000000..c33d1953 --- /dev/null +++ b/drpy-node-admin/.env.example @@ -0,0 +1,9 @@ +# 后端服务器地址(可选) +# 开发环境通常留空,使用 Vite 代理 +# 生产环境如果前后端分离部署,需要配置后端地址 +# 例如: VITE_BACKEND_URL=http://localhost:5757 +VITE_BACKEND_URL= + +# WebSocket 服务器地址(可选) +# 如果与主服务器不同,可以单独配置 +# VITE_WS_URL=ws://localhost:5757 diff --git a/drpy-node-admin/.env.production.apps b/drpy-node-admin/.env.production.apps new file mode 100644 index 00000000..78f581ff --- /dev/null +++ b/drpy-node-admin/.env.production.apps @@ -0,0 +1,3 @@ +# .env.production.apps +# 子目录部署配置 - 部署到 /apps/admin/ 目录 +VITE_BASE_PATH=/apps/admin/ diff --git a/drpy-node-admin/.gitignore b/drpy-node-admin/.gitignore new file mode 100644 index 00000000..46eb96b8 --- /dev/null +++ b/drpy-node-admin/.gitignore @@ -0,0 +1,36 @@ +# Dependencies +node_modules/ +.pnp/ +.pnp.js + +# Build outputs +dist/ +dist-ssr/ +*.local + +# Editor directories and files +.vscode/ +.idea/ +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Environment variables +.env +.env.local +.env.*.local + +# Logs +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# OS files +.DS_Store +Thumbs.db diff --git a/drpy-node-admin/API.md b/drpy-node-admin/API.md new file mode 100644 index 00000000..a1723e49 --- /dev/null +++ b/drpy-node-admin/API.md @@ -0,0 +1,589 @@ +# drpy-node Admin API 文档 + +## 概述 + +drpy-node Admin API 是一套 RESTful API,用于后台管理面板与 drpy-node 服务之间的通信。 + +**Base URL**: `http://localhost:5757/api/admin` + +**认证方式**: Basic Auth(与 /apps/ 相同) + +--- + +## API 端点 + +### 1. 系统管理 + +#### 1.1 健康检查 + +获取服务运行状态和系统信息。 + +```http +GET /api/admin/health +``` + +**响应**: +```json +{ + "status": "ok", + "uptime": 123456, + "memory": { + "used": 128, + "total": 512, + "rss": 256 + }, + "version": "1.3.30", + "platform": { + "arch": "x64", + "platform": "win32", + "nodeVersion": "v18.17.0" + }, + "timestamp": 1710907200000 +} +``` + +#### 1.2 重启服务 + +尝试重启服务(需要 PM2 环境)。 + +```http +POST /api/admin/restart +``` + +**响应**: +```json +{ + "success": true, + "message": "服务已通过 PM2 重启" +} +``` + +或(非 PM2 环境): +```json +{ + "success": false, + "message": "当前未使用 PM2 运行。请在终端中手动重启服务:\n1. 按 Ctrl+C 停止当前服务\n2. 运行 npm run dev 重新启动" +} +``` + +--- + +### 2. 日志管理 + +#### 2.1 读取日志 + +获取最近的日志内容。 + +```http +GET /api/admin/logs?lines=50 +``` + +**查询参数**: +- `lines` (可选): 读取的行数,默认 50 + +**响应**: +```json +{ + "file": "drpy-node-20250318.log.txt", + "content": "[2025-03-18 10:30:00] Server started on port 5757\n..." +} +``` + +#### 2.2 实时日志流 (WebSocket) + +建立 WebSocket 连接以接收实时日志。 + +```http +WS /api/admin/logs/stream +``` + +**客户端发送**: +```json +{ + "action": "subscribe", + "lines": 50 +} +``` + +**服务端推送**: +```json +{ + "type": "log", + "timestamp": 1710907200000, + "content": "[INFO] Server started" +} +``` + +**消息类型**: +- `connected`: 连接成功 +- `log`: 日志内容 +- `error`: 错误信息 +- `end`: 日志读取完成 +- `cleared`: 日志已清空 +- `pong`: 心跳响应 + +--- + +### 3. 配置管理 + +#### 3.1 获取配置 + +获取配置值。 + +```http +GET /api/admin/config?key=section.key +``` + +**查询参数**: +- `key` (可选): 配置键路径,使用点分隔 + +**响应**: +```json +"配置值" +``` + +#### 3.2 更新配置 + +更新配置值。 + +```http +POST /api/admin/config +``` + +**请求体**: +```json +{ + "key": "section.key", + "value": "new value" +} +``` + +**响应**: +```json +{ + "success": true, + "message": "配置项 section.key 已更新" +} +``` + +#### 3.3 获取环境变量 + +获取当前环境变量。 + +```http +GET /api/admin/env +``` + +**响应**: +```json +{ + "PORT": "5757", + "NODE_ENV": "development", + "MAX_TEXT_SIZE": "102400", + "QUARK_COOKIE": "..." +} +``` + +--- + +### 4. 源管理 + +#### 4.1 列出所有源 + +获取所有可用的源文件列表。 + +```http +GET /api/admin/sources +``` + +**响应**: +```json +{ + "js": ["_test.js", "_qq.js", "_fq.js", ...], + "catvod": ["cat.js", ...] +} +``` + +#### 4.2 验证源 + +验证源文件的结构和必填字段。 + +```http +POST /api/admin/sources/validate +``` + +**请求体**: +```json +{ + "path": "spider/js/_test.js" +} +``` + +**响应**: +```json +{ + "isValid": true, + "message": "验证通过" +} +``` + +或(验证失败): +```json +{ + "isValid": false, + "error": "rule 对象缺少必填字段: host" +} +``` + +#### 4.3 检查语法 + +检查源文件的 JavaScript 语法。 + +```http +POST /api/admin/sources/syntax +``` + +**请求体**: +```json +{ + "path": "spider/js/_test.js" +} +``` + +**响应**: +```json +{ + "isValid": true, + "message": "语法检查通过" +} +``` + +或(语法错误): +```json +{ + "isValid": false, + "error": "Syntax Error: Unexpected token" +} +``` + +#### 4.4 获取源模板 + +获取空的源文件模板。 + +```http +GET /api/admin/sources/template +``` + +**响应**: +```json +{ + "template": "var rule = {\n 类型: '影视',\n ...\n}" +} +``` + +#### 4.5 获取 drpy 库信息 + +获取 drpy 全局对象和规则语法说明。 + +```http +GET /api/admin/sources/libs +``` + +**响应**: +```json +{ + "globalObjects": [ + "request(url, options) - HTTP Request", + "pdfa(html, rule) - Parse List", + ... + ], + "parsingRules": [ + "Format: selector;attr1;attr2...", + "pdfa (list): Returns array", + ... + ] +} +``` + +--- + +### 5. 文件管理 + +#### 5.1 列出目录 + +获取目录内容列表。 + +```http +GET /api/admin/files/list?path=spider/js +``` + +**查询参数**: +- `path`: 目录路径,默认为当前目录 '.' + +**响应**: +```json +{ + "files": [ + { + "name": "_test.js", + "path": "spider/js/_test.js", + "isDirectory": false, + "size": 2048 + }, + { + "name": "lib", + "path": "spider/js/lib", + "isDirectory": true + } + ] +} +``` + +#### 5.2 读取文件 + +读取文件内容。 + +```http +GET /api/admin/files/read?path=spider/js/_test.js +``` + +**查询参数**: +- `path`: 文件路径 + +**文本文件响应**: +```json +{ + "type": "text", + "content": "文件内容..." +} +``` + +**图片文件响应**: +```json +{ + "type": "image", + "mimeType": "image/png", + "dataUrl": "data:image/png;base64,iVBORw0KGgo..." +} +``` + +#### 5.3 写入文件 + +写入文件内容。 + +```http +POST /api/admin/files/write +``` + +**请求体**: +```json +{ + "path": "spider/js/new_source.js", + "content": "文件内容..." +} +``` + +**响应**: +```json +{ + "success": true, + "message": "文件保存成功" +} +``` + +#### 5.4 删除文件 + +删除文件。 + +```http +DELETE /api/admin/files/delete?path=spider/js/old.js +``` + +**查询参数**: +- `path`: 文件路径 + +**响应**: +```json +{ + "success": true, + "message": "文件删除成功" +} +``` + +--- + +### 6. 数据库查询 + +#### 6.1 执行查询 + +执行只读 SQL 查询。 + +```http +POST /api/admin/db/query +``` + +**请求体**: +```json +{ + "sql": "SELECT * FROM sqlite_master WHERE type='table'" +} +``` + +**响应**: +```json +{ + "success": true, + "data": [ + { "type": "table", "name": "sources", "tbl_name": "sources", ... } + ], + "rows": 10 +} +``` + +#### 6.2 获取所有表 + +获取数据库中所有表。 + +```http +GET /api/admin/db/tables +``` + +**响应**: +```json +{ + "success": true, + "tables": ["sources", "config", ...] +} +``` + +#### 6.3 获取表结构 + +获取表的字段信息。 + +```http +GET /api/admin/db/tables/{table}/schema +``` + +**响应**: +```json +{ + "success": true, + "table": "sources", + "columns": [ + { "cid": 0, "name": "id", "type": "INTEGER", "notnull": 1, "dflt_value": null }, + ... + ] +} +``` + +--- + +### 7. 路由信息 + +#### 7.1 获取路由列表 + +获取已注册的控制器列表。 + +```http +GET /api/admin/routes +``` + +**响应**: +```json +{ + "file": "controllers/index.js", + "registered_controllers": [ + "fastify.register(websocketController, options);", + "fastify.register(staticController, options);", + ... + ] +} +``` + +--- + +## 错误响应格式 + +所有 API 在发生错误时返回统一格式: + +```json +{ + "error": "错误描述信息" +} +``` + +HTTP 状态码: +- `200`: 成功 +- `400`: 请求参数错误 +- `403`: 访问被拒绝(路径不安全) +- `404`: 资源不存在 +- `500`: 服务器内部错误 + +--- + +## 安全限制 + +### 路径访问限制 + +允许访问的目录: +- `spider/js/` +- `spider/js_dr2/` +- `spider/catvod/` +- `spider/py/` +- `spider/xbpq/` +- `config/` +- `json/` +- `docs/` + +禁止访问: +- 包含 `..` 的路径(路径遍历) +- 包含 `~` 的路径 +- 绝对路径(以 `/` 开头) +- `node_modules/` 目录 +- `database.db` 文件 + +### SQL 查询限制 + +- 只允许 `SELECT` 查询 +- 禁止 `DROP`、`DELETE`、`INSERT`、`UPDATE`、`ALTER`、`CREATE`、`TRUNCATE` + +--- + +## WebSocket 心跳 + +为保持连接活跃,客户端应每 30 秒发送一次心跳: + +```javascript +// 客户端代码示例 +setInterval(() => { + if (ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'heartbeat' })); + } +}, 30000); +``` + +服务端会响应: +```json +{ "type": "pong" } +``` + +--- + +## 速率限制 + +为防止滥用,建议实施以下速率限制: + +- 日志读取: 10 次/分钟 +- 文件操作: 20 次/分钟 +- 配置更新: 5 次/分钟 +- 数据库查询: 30 次/分钟 + +--- + +## 版本历史 + +### v1.0.0 (2025-03-18) +- 初始版本 +- 实现所有核心 API +- WebSocket 实时日志支持 +- 移除 MCP 依赖 diff --git a/drpy-node-admin/IMPLEMENTATION.md b/drpy-node-admin/IMPLEMENTATION.md new file mode 100644 index 00000000..9e47051e --- /dev/null +++ b/drpy-node-admin/IMPLEMENTATION.md @@ -0,0 +1,1383 @@ +# drpy-node-admin 解耦实现细节 + +## 1. 控制器实现示例 + +### 1.1 systemController.js + +```javascript +/** + * 系统管理控制器 + * 提供健康检查、服务重启等系统级功能 + */ + +import os from 'os'; +import { exec } from 'child_process'; +import util from 'util'; +import path from 'path'; +import fs from 'fs-extra'; + +const execPromise = util.promisify(exec); + +// 健康检查 +export async function getHealth(req, reply) { + try { + const uptime = process.uptime(); + const memory = process.memoryUsage(); + const packageJson = await fs.readJson(path.join(process.cwd(), 'package.json')); + + return reply.send({ + status: 'ok', + uptime: Math.floor(uptime), + memory: { + used: Math.round(memory.heapUsed / 1024 / 1024), + total: Math.round(memory.heapTotal / 1024 / 1024), + rss: Math.round(memory.rss / 1024 / 1024) + }, + version: packageJson.version, + platform: { + arch: os.arch(), + platform: os.platform(), + nodeVersion: process.version + }, + timestamp: Date.now() + }); + } catch (e) { + reply.code(500).send({ + status: 'error', + error: e.message + }); + } +} + +// 服务重启 +export async function restartService(req, reply) { + try { + // 检查是否在 PM2 环境运行 + try { + await execPromise('pm2 restart drpys'); + return reply.send({ + success: true, + message: '服务已通过 PM2 重启' + }); + } catch (pm2Error) { + return reply.send({ + success: false, + message: '当前未使用 PM2 运行。请在终端中手动重启服务:\\n1. 按 Ctrl+C 停止当前服务\\n2. 运行 npm run dev 重新启动' + }); + } + } catch (e) { + reply.code(500).send({ + success: false, + error: e.message + }); + } +} +``` + +### 1.2 logsController.js + +```javascript +/** + * 日志管理控制器 + * 提供日志读取和 WebSocket 实时流式传输 + */ + +import fs from 'fs-extra'; +import path from 'path'; +import { WebSocket } from '@fastify/websocket'; +import { EventEmitter } from 'events'; + +const logEmitter = new EventEmitter(); +const activeLogConnections = new Set(); + +// 读取日志 +export async function getLogs(req, reply) { + try { + const lines = parseInt(req.query.lines) || 50; + const logDir = path.join(process.cwd(), 'logs'); + + if (!await fs.pathExists(logDir)) { + return reply.send({ + file: null, + content: '日志目录不存在' + }); + } + + const files = await fs.readdir(logDir); + const logFiles = files + .filter(f => f.endsWith('.log.txt')) + .sort() + .reverse(); + + if (logFiles.length === 0) { + return reply.send({ + file: null, + content: '没有日志文件' + }); + } + + const latestLog = path.join(logDir, logFiles[0]); + const content = await fs.readFile(latestLog, 'utf-8'); + const allLines = content.trim().split('\\n'); + const lastLines = allLines.slice(-lines); + + return reply.send({ + file: logFiles[0], + content: lastLines.join('\\n') + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// WebSocket 日志流处理 +export async function handleLogStream(connection, req) { + const socket = connection.socket; + activeLogConnections.add(socket); + + // 发送欢迎消息 + socket.send(JSON.stringify({ + type: 'connected', + message: '已连接到日志流' + })); + + // 心跳处理 + const heartbeatInterval = setInterval(() => { + if (socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ type: 'pong' })); + } else { + clearInterval(heartbeatInterval); + } + }, 30000); + + socket.on('message', async (message) => { + try { + const data = JSON.parse(message); + + if (data.action === 'subscribe') { + await streamLogs(socket, data.lines || 50); + } else if (data.action === 'clear') { + // 清空日志 + socket.send(JSON.stringify({ type: 'cleared' })); + } + } catch (e) { + socket.send(JSON.stringify({ + type: 'error', + message: e.message + })); + } + }); + + socket.on('close', () => { + clearInterval(heartbeatInterval); + activeLogConnections.delete(socket); + }); +} + +async function streamLogs(socket, lines) { + try { + const logDir = path.join(process.cwd(), 'logs'); + const files = await fs.readdir(logDir); + const logFiles = files + .filter(f => f.endsWith('.log.txt')) + .sort() + .reverse(); + + if (logFiles.length === 0) { + socket.send(JSON.stringify({ + type: 'error', + message: '没有日志文件' + })); + return; + } + + const latestLog = path.join(logDir, logFiles[0]); + const content = await fs.readFile(latestLog, 'utf-8'); + const allLines = content.trim().split('\\n'); + const lastLines = allLines.slice(-lines); + + // 发送现有日志 + for (const line of lastLines) { + if (socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ + type: 'log', + timestamp: Date.now(), + content: line + })); + } + } + + socket.send(JSON.stringify({ + type: 'end', + message: `已读取 ${lastLines.length} 行日志` + })); + } catch (e) { + socket.send(JSON.stringify({ + type: 'error', + message: e.message + })); + } +} +``` + +### 1.3 sourcesController.js + +```javascript +/** + * 源管理控制器 + * 提供源列表、验证、语法检查、模板获取等功能 + */ + +import fs from 'fs-extra'; +import path from 'path'; +import vm from 'vm'; +import { resolvePath } from '../../utils/pathHelper.js'; + +// 导入 drpy 工具 +let jsoup, req; +try { + const htmlParser = await import('../../libs_drpy/htmlParser.js'); + jsoup = htmlParser.jsoup; + const reqModule = await import('../../utils/req.js'); + req = reqModule.default; +} catch (e) { + console.warn('Failed to import project utils:', e.message); +} + +// 列出所有源 +export async function listSources(req, reply) { + try { + const jsPath = path.join(process.cwd(), 'spider/js'); + const catvodPath = path.join(process.cwd(), 'spider/catvod'); + + let jsSources = []; + let catvodSources = []; + + if (await fs.pathExists(jsPath)) { + jsSources = (await fs.readdir(jsPath)) + .filter(f => f.endsWith('.js')) + .sort(); + } + + if (await fs.pathExists(catvodPath)) { + catvodSources = (await fs.readdir(catvodPath)) + .filter(f => f.endsWith('.js')) + .sort(); + } + + return reply.send({ + js: jsSources, + catvod: catvodSources + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 验证源文件 +export async function validateSpider(req, reply) { + try { + const { path: filePath } = req.body; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(400).send({ + isValid: false, + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + if (!await fs.pathExists(fullPath)) { + return reply.code(404).send({ + isValid: false, + error: '文件不存在' + }); + } + + let code = await fs.readFile(fullPath, 'utf-8'); + + // 如果是 JS 文件,尝试解码 + if (filePath.endsWith('.js')) { + try { + const { decodeDsSource } = await import('../../utils/dsHelper.js'); + code = await decodeDsSource(code); + } catch (e) { + // 解码失败,使用原始代码 + } + } + + // 创建沙箱执行 + const sandbox = { + console: { log: () => {} }, + require: () => {}, + rule: null + }; + + try { + vm.createContext(sandbox); + new vm.Script(code).runInContext(sandbox); + + if (!sandbox.rule) { + return reply.send({ + isValid: false, + error: '源文件中缺少 rule 对象' + }); + } + + // 基本验证 + const required = ['title', 'host', 'url']; + const missing = required.filter(k => !sandbox.rule[k]); + + if (missing.length > 0) { + return reply.send({ + isValid: false, + error: `rule 对象缺少必填字段: ${missing.join(', ')}` + }); + } + + return reply.send({ + isValid: true, + message: '验证通过' + }); + } catch (e) { + return reply.send({ + isValid: false, + error: `执行错误: ${e.message}` + }); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 检查语法 +export async function checkSyntax(req, reply) { + try { + const { path: filePath } = req.body; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(400).send({ + isValid: false, + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + let code = await fs.readFile(fullPath, 'utf-8'); + + // 如果是 JS 文件,尝试解码 + if (filePath.endsWith('.js')) { + try { + const { decodeDsSource } = await import('../../utils/dsHelper.js'); + code = await decodeDsSource(code); + } catch (e) { + // 解码失败,使用原始代码 + } + } + + try { + new vm.Script(code); + return reply.send({ + isValid: true, + message: '语法检查通过' + }); + } catch (e) { + return reply.code(400).send({ + isValid: false, + error: `语法错误: ${e.message}` + }); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 获取模板 +export async function getTemplate(req, reply) { + const template = `/* +* @File : drpy-node spider template +* @Author : user +* @Date : ${new Date().toISOString().split('T')[0]} +* @Comments : +*/ + +var rule = { + // 影视|漫画|小说 + 类型: '影视', + // 源标题 + title: 'Site Name', + // 源主域名 + host: 'https://example.com', + // 源主页链接 + homeUrl: '/latest/', + // 源一级列表链接 + url: '/category/fyclass/page/fypage', + // 源搜索链接 + searchUrl: '/search?wd=**&pg=fypage', + // 允许搜索、允许快搜、允许筛选 + searchable: 2, + quickSearch: 0, + filterable: 1, + // 请求头 + headers: { + 'User-Agent': 'MOBILE_UA', + }, + // 超时时间 + timeout: 5000, + // 静态分类 + class_name: '电影&电视剧&综艺&动漫', + class_url: '1&2&3&4', + + // 是否需要调用免嗅 + play_parse: true, + // 免嗅lazy执行函数 + lazy: '', + // 首页推荐数量 + limit: 6, + // 是否双层列表 + double: true, + + // 推荐列表 + 推荐: '.recommend .item;a&&title;img&&src;.remarks&&Text;a&&href', + // 一级列表 + 一级: '.list .item;a&&title;img&&src;.remarks&&Text;a&&href', + // 二级详情 + 二级: { + "title": "h1&&Text", + "img": ".poster img&&src", + "desc": ".desc&&Text", + "content": ".content&&Text", + "tabs": ".tabs span", + "lists": ".playlists ul" + }, + // 搜索 + 搜索: '.search-result .item;a&&title;img&&src;.remarks&&Text;a&&href', +}`; + + return reply.send({ template }); +} + +function isSafePath(filePath) { + return !filePath.includes('..') && + !filePath.includes('~') && + !filePath.startsWith('/') && + !filePath.includes('node_modules'); +} +``` + +### 1.4 filesController.js + +```javascript +/** + * 文件管理控制器 + * 提供文件列表、读取、写入、删除功能 + */ + +import fs from 'fs-extra'; +import path from 'path'; +import mime from 'mime-types'; + +// 列出目录 +export async function listDirectory(req, reply) { + try { + const dirPath = req.query.path || '.'; + + if (!isSafePath(dirPath)) { + return reply.code(403).send({ + error: '访问被拒绝' + }); + } + + const fullPath = path.join(process.cwd(), dirPath); + const files = await fs.readdir(fullPath, { withFileTypes: true }); + + const result = files.map(f => ({ + name: f.name, + path: dirPath === '.' ? f.name : `${dirPath}/${f.name}`, + isDirectory: f.isDirectory(), + size: f.isDirectory() ? undefined : (await fs.stat(path.join(fullPath, f.name))).size + })); + + return reply.send({ files: result }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 读取文件 +export async function readFile(req, reply) { + try { + const { path: filePath } = req.query; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(403).send({ + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + + if (!await fs.pathExists(fullPath)) { + return reply.code(404).send({ + error: '文件不存在' + }); + } + + const ext = path.extname(filePath).toLowerCase(); + const imageExts = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.bmp']; + + if (imageExts.includes(ext)) { + // 图片文件 - 返回 base64 + const buffer = await fs.readFile(fullPath); + const base64 = buffer.toString('base64'); + const mimeType = mime.lookup(fullPath) || 'image/png'; + + return reply.send({ + type: 'image', + mimeType, + dataUrl: `data:${mimeType};base64,${base64}` + }); + } + + // 文本文件 + let content = await fs.readFile(fullPath, 'utf-8'); + + // 如果是 JS 文件,尝试解码 + if (ext === '.js') { + try { + const { decodeDsSource } = await import('../../utils/dsHelper.js'); + content = await decodeDsSource(content); + } catch (e) { + // 保持原样 + } + } + + return reply.send({ + type: 'text', + content + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 写入文件 +export async function writeFile(req, reply) { + try { + const { path: filePath, content } = req.body; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(403).send({ + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + + // 确保目录存在 + await fs.ensureDir(path.dirname(fullPath)); + + // 写入文件 + await fs.writeFile(fullPath, content, 'utf-8'); + + return reply.send({ + success: true, + message: '文件保存成功' + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 删除文件 +export async function deleteFile(req, reply) { + try { + const { path: filePath } = req.body; + + if (!filePath || !isSafePath(filePath)) { + return reply.code(403).send({ + error: '无效的文件路径' + }); + } + + const fullPath = path.join(process.cwd(), filePath); + + if (!await fs.pathExists(fullPath)) { + return reply.code(404).send({ + error: '文件不存在' + }); + } + + await fs.remove(fullPath); + + return reply.send({ + success: true, + message: '文件删除成功' + }); + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +function isSafePath(filePath) { + return !filePath.includes('..') && + !filePath.includes('~') && + !filePath.startsWith('/') && + !filePath.includes('node_modules') && + !filePath.includes('database.db'); +} +``` + +### 1.5 dbController.js + +```javascript +/** + * 数据库查询控制器 + * 提供安全的只读 SQL 查询功能 + */ + +import sqlite3pkg from 'node-sqlite3-wasm'; +const { Database } = sqlite3pkg; +import path from 'path'; + +// 执行查询 +export async function executeQuery(req, reply) { + try { + const { sql, params } = req.body; + + if (!sql || !sql.trim()) { + return reply.code(400).send({ + error: 'SQL 查询不能为空' + }); + } + + // 只允许 SELECT 查询 + const trimmedSql = sql.trim().toLowerCase(); + if (!trimmedSql.startsWith('select')) { + return reply.code(403).send({ + error: '只允许 SELECT 查询' + }); + } + + // 额外安全检查 + const dangerousKeywords = ['drop', 'delete', 'insert', 'update', 'alter', 'create', 'truncate']; + for (const keyword of dangerousKeywords) { + if (trimmedSql.includes(keyword)) { + return reply.code(403).send({ + error: `不允许使用 ${keyword.toUpperCase()} 语句` + }); + } + } + + const dbPath = path.join(process.cwd(), 'database.db'); + const db = new Database(dbPath); + + try { + const rows = db.all(sql, params || []); + return reply.send({ + success: true, + data: rows, + rows: rows.length + }); + } finally { + db.close(); + } + } catch (e) { + reply.code(500).send({ + error: `SQL 错误: ${e.message}` + }); + } +} + +// 获取表结构 +export async function getTables(req, reply) { + try { + const dbPath = path.join(process.cwd(), 'database.db'); + const db = new Database(dbPath); + + try { + const tables = db.all("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"); + return reply.send({ + success: true, + tables: tables.map(t => t.name) + }); + } finally { + db.close(); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} + +// 获取表结构 +export async function getTableSchema(req, reply) { + try { + const { table } = req.params; + + if (!table) { + return reply.code(400).send({ + error: '表名不能为空' + }); + } + + const dbPath = path.join(process.cwd(), 'database.db'); + const db = new Database(dbPath); + + try { + const schema = db.all(`PRAGMA table_info(${table})`); + return reply.send({ + success: true, + table, + columns: schema + }); + } finally { + db.close(); + } + } catch (e) { + reply.code(500).send({ + error: e.message + }); + } +} +``` + +## 2. admin.js 重构 + +```javascript +/** + * Admin Controller - 后台管理主控制器 + * 重构版:移除 MCP 依赖,直接实现业务逻辑 + */ + +import path from 'path'; +import fs from 'fs-extra'; +import fastifyStatic from '@fastify/static'; +import { websocketServerConnector } from '@fastify/websocket'; + +// 导入子控制器 +import * as systemController from './admin/systemController.js'; +import * as logsController from './admin/logsController.js'; +import * as sourcesController from './admin/sourcesController.js'; +import * as filesController from './admin/filesController.js'; +import * as dbController from './admin/dbController.js'; + +// 配置常量 +const CONFIG_PATH = path.join(process.cwd(), 'config/env.json'); + +// 导出路由配置 +export default async function adminController(fastify, options, done) { + // 注册 WebSocket 插件 + await fastify.register(websocketServerConnector); + + // ==================== 静态文件服务 ==================== + const adminDistPath = path.join(process.cwd(), 'apps/admin'); + + // 如果编译后的 admin 存在,提供静态文件服务 + if (await fs.pathExists(adminDistPath)) { + fastify.log.info('Serving admin panel from ' + adminDistPath); + + fastify.register(fastifyStatic, { + root: adminDistPath, + prefix: '/admin/', + decorateReply: false, + index: ['index.html'], + cacheControl: 3600, // 1 小时缓存 + etag: true + }); + } + + // ==================== 系统管理 API ==================== + fastify.get('/api/admin/health', systemController.getHealth); + fastify.post('/api/admin/restart', systemController.restartService); + + // ==================== 日志 API ==================== + fastify.get('/api/admin/logs', logsController.getLogs); + fastify.register(async function (fastify) { + fastify.get('/api/admin/logs/stream', { websocket: true }, logsController.handleLogStream); + }); + + // ==================== 配置管理 API ==================== + fastify.get('/api/admin/config', getConfig); + fastify.post('/api/admin/config', updateConfig); + fastify.get('/api/admin/env', getEnv); + + // ==================== 源管理 API ==================== + fastify.get('/api/admin/sources', sourcesController.listSources); + fastify.post('/api/admin/sources/validate', sourcesController.validateSpider); + fastify.post('/api/admin/sources/syntax', sourcesController.checkSyntax); + fastify.get('/api/admin/sources/template', sourcesController.getTemplate); + fastify.get('/api/admin/sources/libs', sourcesController.getLibsInfo); + + // ==================== 文件管理 API ==================== + fastify.get('/api/admin/files/list', filesController.listDirectory); + fastify.get('/api/admin/files/read', filesController.readFile); + fastify.post('/api/admin/files/write', filesController.writeFile); + fastify.delete('/api/admin/files/delete', filesController.deleteFile); + + // ==================== 数据库 API ==================== + fastify.post('/api/admin/db/query', dbController.executeQuery); + fastify.get('/api/admin/db/tables', dbController.getTables); + fastify.get('/api/admin/db/tables/:table/schema', dbController.getTableSchema); + + // ==================== 路由信息 API ==================== + fastify.get('/api/admin/routes', getRoutesInfo); + + done(); +} + +// ==================== 辅助函数 ==================== + +async function getConfig(req, reply) { + try { + const { key } = req.query; + + if (!await fs.pathExists(CONFIG_PATH)) { + return reply.send({}); + } + + const configContent = await fs.readFile(CONFIG_PATH, 'utf-8'); + const config = JSON.parse(configContent); + + if (key) { + const keys = key.split('.'); + let value = config; + for (const k of keys) { + value = value?.[k]; + } + return reply.send(value !== undefined ? value : null); + } + + return reply.send(config); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} + +async function updateConfig(req, reply) { + try { + const { key, value } = req.body; + + if (!key) { + return reply.code(400).send({ error: 'Key is required' }); + } + + if (!await fs.pathExists(CONFIG_PATH)) { + return reply.code(404).send({ error: 'Config file not found' }); + } + + const configContent = await fs.readFile(CONFIG_PATH, 'utf-8'); + let config = JSON.parse(configContent); + + // 设置嵌套值 + const keys = key.split('.'); + let target = config; + for (let i = 0; i < keys.length - 1; i++) { + if (!target[keys[i]]) { + target[keys[i]] = {}; + } + target = target[keys[i]]; + } + + // 尝试解析为 JSON + let parsedValue = value; + try { + parsedValue = JSON.parse(value); + } catch { + // 保持字符串 + } + + target[keys[keys.length - 1]] = parsedValue; + + // 写回文件 + await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2)); + + return reply.send({ + success: true, + message: `配置项 ${key} 已更新` + }); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} + +async function getEnv(req, reply) { + try { + const envData = {}; + + // 从 process.env 读取关键配置 + const keys = [ + 'PORT', 'NODE_ENV', 'MAX_TEXT_SIZE', 'MAX_IMAGE_SIZE', + 'QUARK_COOKIE', 'ALI_TOKEN', 'bili_cookie' + ]; + + for (const key of keys) { + if (process.env[key]) { + envData[key] = process.env[key]; + } + } + + return reply.send(envData); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} + +async function getRoutesInfo(req, reply) { + try { + const indexControllerPath = path.join(process.cwd(), 'controllers/index.js'); + + if (!await fs.pathExists(indexControllerPath)) { + return reply.send({ + file: 'controllers/index.js', + registered_controllers: [] + }); + } + + const content = await fs.readFile(indexControllerPath, 'utf-8'); + const lines = content.split('\n'); + const registered = lines + .filter(l => l.trim().startsWith('fastify.register(')) + .map(l => l.trim()); + + return reply.send({ + file: 'controllers/index.js', + registered_controllers: registered + }); + } catch (e) { + reply.code(500).send({ error: e.message }); + } +} +``` + +## 3. 前端 API 客户端 + +### 3.1 src/api/admin.js + +```javascript +/** + * Admin API 统一调用接口 + * 所有后台管理 API 都通过这个模块调用 + */ + +import client from './client'; + +export const adminApi = { + // ==================== 系统 ==================== + async getHealth() { + return client.get('/api/admin/health'); + }, + + async restartService() { + return client.post('/api/admin/restart'); + }, + + // ==================== 日志 ==================== + async getLogs(lines = 50) { + return client.get('/api/admin/logs', { params: { lines } }); + }, + + // WebSocket 连接在组件中直接使用 + + // ==================== 配置 ==================== + async getConfig(key) { + return client.get('/api/admin/config', { params: { key } }); + }, + + async updateConfig(key, value) { + return client.post('/api/admin/config', { key, value }); + }, + + async getEnv() { + return client.get('/api/admin/env'); + }, + + // ==================== 源管理 ==================== + async listSources() { + return client.get('/api/admin/sources'); + }, + + async validateSource(path) { + return client.post('/api/admin/sources/validate', { path }); + }, + + async checkSyntax(path) { + return client.post('/api/admin/sources/syntax', { path }); + }, + + async getTemplate() { + return client.get('/api/admin/sources/template'); + }, + + async getLibsInfo() { + return client.get('/api/admin/sources/libs'); + }, + + // ==================== 文件管理 ==================== + async listDirectory(path) { + return client.get('/api/admin/files/list', { params: { path } }); + }, + + async readFile(path) { + return client.get('/api/admin/files/read', { params: { path } }); + }, + + async writeFile(path, content) { + return client.post('/api/admin/files/write', { path, content }); + }, + + async deleteFile(path) { + return client.delete('/api/admin/files/delete', { params: { path } }); + }, + + // ==================== 数据库 ==================== + async executeQuery(sql) { + return client.post('/api/admin/db/query', { sql }); + }, + + async getTables() { + return client.get('/api/admin/db/tables'); + }, + + async getTableSchema(table) { + return client.get(`/api/admin/db/tables/${table}/schema`); + }, + + // ==================== 路由信息 ==================== + async getRoutes() { + return client.get('/api/admin/routes'); + } +}; +``` + +### 3.2 其他 API 文件重构 + +```javascript +// src/api/system.js - 重构 +import { adminApi } from './admin'; + +export const systemApi = { + async checkHealth() { + const result = await adminApi.getHealth(); + return result; + }, + + async restartService() { + const result = await adminApi.restartService(); + return result; + }, + + async fetchRoutes() { + const result = await adminApi.getRoutes(); + return result; + }, + + async fetchSources() { + const result = await adminApi.listSources(); + // 保持与原有格式兼容 + return result; + } +}; + +// src/api/spider.js - 重构 +import { adminApi } from './admin'; + +export const spiderApi = { + async listSources() { + const result = await adminApi.listSources(); + // 保持与原有格式兼容 + return { + js: result.js || [], + catvod: result.catvod || [] + }; + }, + + async validateSpider(path) { + const result = await adminApi.validateSource(path); + // 保持与原有格式兼容 + if (result.isValid) { + return { isError: false, content: [{ text: result.message || '验证通过' }] }; + } else { + return { isError: true, content: [{ text: result.error }] }; + } + }, + + async checkSyntax(path) { + const result = await adminApi.checkSyntax(path); + // 保持与原有格式兼容 + if (result.isValid) { + return { isError: false, content: [{ text: result.message || '语法正确' }] }; + } else { + return { isError: true, content: [{ text: result.error }] }; + } + }, + + async getTemplate() { + const result = await adminApi.getTemplate(); + return result.template; + }, + + async debugRule(params) { + // 如果需要调试功能,需要额外实现 + // 暂时返回不支持的提示 + return { + isError: true, + content: [{ text: '调试功能暂未实现' }] + }; + } +}; + +// src/api/file.js - 重构 +import { adminApi } from './admin'; + +export const fileApi = { + async listDirectory(path = '.') { + const result = await adminApi.listDirectory(path); + // 保持与原有格式兼容 + return result; + }, + + async readFile(path) { + const result = await adminApi.readFile(path); + return result; + }, + + async writeFile(path, content) { + const result = await adminApi.writeFile(path, content); + return result; + }, + + async deleteFile(path) { + const result = await adminApi.deleteFile(path); + return result; + } +}; + +// src/api/db.js - 新增 +import { adminApi } from './admin'; + +export const dbApi = { + async query(sql) { + const result = await adminApi.executeQuery(sql); + return result.data; + }, + + async getTables() { + const result = await adminApi.getTables(); + return result.tables; + }, + + async getTableSchema(table) { + const result = await adminApi.getTableSchema(table); + return result.columns; + } +}; +``` + +## 4. Vite 配置调整 + +### 4.1 vite.config.js + +```javascript +import { fileURLToPath } from 'url'; +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import path from 'path'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +export default defineConfig({ + plugins: [vue()], + + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + } + }, + + // 构建配置 + build: { + outDir: path.resolve(__dirname, '../apps/admin'), + emptyOutDir: true, + rollupOptions: { + output: { + manualChunks: { + 'vendor': ['vue', 'vue-router', 'pinia'], + 'ui': ['axios'] + } + } + }, + chunkSizeWarningLimit: 1000 + }, + + // 开发服务器配置 + server: { + port: 5174, + proxy: { + // 所有 API 请求代理到 drpy-node + '/api': { + target: 'http://localhost:5757', + changeOrigin: true + }, + // WebSocket 代理 + '/api/admin/logs/stream': { + target: 'ws://localhost:5757', + ws: true + } + } + }, + + // 基础路径 + base: '/admin/' +}); +``` + +## 5. 测试计划 + +### 5.1 API 测试用例 + +```javascript +// tests/api/admin.test.js +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import { build } from 'vite'; +import { fileURLToPath } from 'url'; +import { $fetch } from 'island-fetch'; + +describe('Admin API', () => { + let baseUrl; + + beforeAll(async () => { + // 启动测试服务器 + baseUrl = 'http://localhost:5757/api/admin'; + }); + + describe('GET /health', () => { + it('should return health status', async () => { + const response = await $fetch(`${baseUrl}/health`); + const data = await response.json(); + + expect(data.status).toBe('ok'); + expect(data.version).toBeDefined(); + }); + }); + + describe('GET /sources', () => { + it('should return list of sources', async () => { + const response = await $fetch(`${baseUrl}/sources`); + const data = await response.json(); + + expect(data.js).toBeInstanceOf(Array); + expect(data.catvod).toBeInstanceOf(Array); + }); + }); + + describe('POST /sources/syntax', () => { + it('should check syntax of spider file', async () => { + const response = await $fetch(`${baseUrl}/sources/syntax`, { + method: 'POST', + body: JSON.stringify({ + path: 'spider/js/_test.js' + }) + }); + const data = await response.json(); + + expect(data.isValid).toBeDefined(); + }); + }); + + // 更多测试用例... +}); +``` + +## 6. 部署脚本 + +### 6.1 构建脚本 + +```javascript +// scripts/build-admin.js +import { execSync } from 'child_process'; +import fs from 'fs-extra'; +import path from 'path'; + +console.log('🔨 开始构建 drpy-node-admin...'); + +// 1. 进入 admin 目录 +process.chdir(path.join(process.cwd(), 'drpy-node-admin')); + +// 2. 安装依赖(如果需要) +if (!fs.existsSync('node_modules')) { + console.log('📦 安装依赖...'); + execSync('npm install', { stdio: 'inherit' }); +} + +// 3. 构建 +console.log('🏗️ 构建生产版本...'); +execSync('npm run build', { stdio: 'inherit' }); + +// 4. 验证构建结果 +const adminDistPath = path.join(process.cwd(), '../apps/admin'); +if (!fs.existsSync(adminDistPath)) { + console.error('❌ 构建失败:未找到输出目录'); + process.exit(1); +} + +const indexHtml = path.join(adminDistPath, 'index.html'); +if (!fs.existsSync(indexHtml)) { + console.error('❌ 构建失败:未找到 index.html'); + process.exit(1); +} + +console.log('✅ 构建成功!'); +console.log(`📂 输出目录: ${adminDistPath}`); +console.log(''); +console.log('现在可以通过以下地址访问管理面板:'); +console.log(' http://localhost:5757/admin/'); +``` + +## 7. 兼容性过渡方案 + +### 7.1 MCP 兼容层(可选) + +```javascript +// 在 admin.js 中添加兼容层(可配置开关) +const ENABLE_MCP_COMPAT = process.env.ENABLE_MCP_COMPAT === 'true'; + +// 兼容 MCP 格式的接口 +if (ENABLE_MCP_COMPAT) { + fastify.post('/admin/mcp', async (req, reply) => { + const { name, arguments: args } = req.body; + + // 映射到新 API + const apiMapping = { + 'read_logs': () => logsController.getLogs(req, reply), + 'restart_service': () => systemController.restartService(req, reply), + 'list_sources': () => sourcesController.listSources(req, reply), + // ... 其他映射 + }; + + const handler = apiMapping[name]; + if (handler) { + return handler(); + } + + return reply.code(404).send({ error: 'Tool not found' }); + }); +} +``` diff --git a/drpy-node-admin/README.md b/drpy-node-admin/README.md new file mode 100644 index 00000000..3e3c6722 --- /dev/null +++ b/drpy-node-admin/README.md @@ -0,0 +1,197 @@ +# DRPY Node Admin + +drpy-node 后台管理界面 - 基于 Vue3 + Tailwind CSS 构建的现代化管理系统。 + +## 功能特性 + +- 🎨 现代化 UI 设计,支持亮色/暗色主题 +- 📱 完全响应式,适配 PC 和移动端 +- 🚀 基于 Vite 构建,快速开发体验 +- 🔧 环境变量可视化配置 +- 📦 源文件管理和验证 +- 📋 实时日志查看 +- 📚 API 文档查看 +- 📁 文件浏览和编辑 +- 🗄️ 数据库查询 + +## 开发 + +```bash +# 安装依赖 +npm install + +# 启动开发服务器 +npm run dev + +# 构建生产版本 +npm run build + +# 预览生产构建 +npm run preview +``` + +## 技术栈 + +- **Vue 3** - 渐进式 JavaScript 框架 +- **Vite** - 下一代前端构建工具 +- **Tailwind CSS** - 实用优先的 CSS 框架 +- **Vue Router** - 官方路由管理 +- **Pinia** - Vue 3 状态管理 +- **Axios** - HTTP 客户端 + +## 项目结构 + +``` +drpy-node-admin/ +├── src/ +│ ├── api/ # API 接口 +│ ├── components/ # 公共组件 +│ ├── router/ # 路由配置 +│ ├── stores/ # Pinia 状态管理 +│ ├── utils/ # 工具函数 +│ ├── views/ # 页面组件 +│ ├── App.vue # 根组件 +│ ├── main.js # 入口文件 +│ └── style.css # 全局样式 +├── public/ # 静态资源 +├── index.html # HTML 模板 +├── vite.config.js # Vite 配置 +├── tailwind.config.js # Tailwind 配置 +└── package.json # 项目配置 +``` + +## SPA 集成与部署 (重要) + +本项目被设计为 drpy-node 的一个子应用 (SPA 插件),默认部署在 `/apps/admin/` 路径下。为了确保单页面应用(SPA)在子目录下正常运行并解决刷新 404 问题,采用了与 `drplayer` 一致的配置模式。 + +### 1. 关键配置 + +#### 环境变量 (.env.production.apps) +用于指定生产构建时的基础路径: +```env +# 子目录部署配置 - 部署到 /apps/admin/ 目录 +VITE_BASE_PATH=/apps/admin/ +``` + +#### Vite 配置 (vite.config.js) +构建配置会自动读取环境变量中的 `VITE_BASE_PATH`: +```javascript +// 基础路径:优先使用环境变量 VITE_BASE_PATH,否则使用默认值 +base: mode.includes('production') ? (env.VITE_BASE_PATH || './') : '/' +``` + +#### 路由配置 (src/router/index.js) +Vue Router 必须使用与 `base` 一致的 History 模式,否则会导致路由跳转失效或刷新白屏: +```javascript +const router = createRouter({ + // 必须传入 base 路径 + history: createWebHistory(import.meta.env.VITE_BASE_PATH || import.meta.env.BASE_URL), + routes +}) +``` + +### 2. 后端集成 (drpy-node) + +后端通过 `controllers/static.js` 和 `controllers/fastify-spa-routes.js` 提供支持: + +1. **静态资源服务**:`fastify-static` 将 `apps` 目录映射到 `/apps/` 路由。 +2. **SPA 路由回退**:`addSPARoutes` 插件拦截 `/apps/admin/*` 的请求,当请求的资源不存在时(如刷新页面),自动返回 `/apps/admin/index.html`,由前端路由接管。 + +```javascript +// controllers/static.js +fastify.register(addSPARoutes, { + appsDir: options.appsDir, + spaApps: ['drplayer', 'admin'] // 注册为 SPA 应用 +}); +``` + +### 3. 构建与发布 + +**请务必使用以下命令进行构建,以确保加载正确的环境变量:** + +```bash +# 在 drpy-node-admin 目录下 +npm run build:apps + +# 或者在项目根目录下 +npm run admin:build +``` + +构建产物将输出到 `../apps/admin` 目录,可以直接被 drpy-node 服务加载。 + +## 与 drpy-node 集成 + +Admin 面板通过 drpy-node-mcp 与主项目通信,需要后端提供相应的 API 接口。 + +### 日志功能说明 + +日志查看页面使用 WebSocket 实时接收后端日志。确保: + +1. **开发环境**: + - 后端服务器运行在 `http://localhost:5757` + - Vite 开发服务器自动代理 `/ws` 请求到后端 + +2. **生产环境**: + - 确保后端的 `/ws` 端点可访问 + - 如果前后端分离部署,配置 `VITE_BACKEND_URL` 环境变量 + - 示例:`VITE_BACKEND_URL=http://your-backend:5757` + +### 部署说明 + +#### 开发环境 +```bash +# 终端 1: 启动后端 +npm run dev + +# 终端 2: 启动前端 +cd drpy-node-admin +npm run dev +``` + +#### 生产环境 +```bash +# 构建前端 +cd drpy-node-admin +npm run build + +# 将 dist 目录部署到静态服务器 +# 或配置反向代理将 /admin 请求指向 dist 目录 +``` + +#### Nginx 配置示例 +```nginx +server { + listen 80; + server_name your-domain.com; + + # 主服务 + location / { + proxy_pass http://localhost:5757; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + + # WebSocket 支持 + location /ws { + proxy_pass http://localhost:5757; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + + # Admin 面板 + location /admin { + alias /path/to/drpy-node-admin/dist; + try_files $uri $uri/ /admin/index.html; + } +} +``` + +## License + +MIT diff --git a/drpy-node-admin/ROADMAP.md b/drpy-node-admin/ROADMAP.md new file mode 100644 index 00000000..c42f1385 --- /dev/null +++ b/drpy-node-admin/ROADMAP.md @@ -0,0 +1,433 @@ +# drpy-node-admin 解耦重构规划文档 + +## 📋 文档目录 + +本目录包含 drpy-node-admin 解耦与 SPA 插件化重构的完整规划文档: + +1. **SPEC.md** - 总体规划与架构设计 +2. **IMPLEMENTATION.md** - 详细实现指南与代码示例 +3. **API.md** - REST API 接口完整文档 +4. **ROADMAP.md** - 本文件,实施路线图 + +--- + +## 🎯 重构目标 + +### 当前问题 + +``` +┌─────────────────────────────────────────────────────┐ +│ 当前架构 │ +├─────────────────────────────────────────────────────┤ +│ │ +│ drpy-node-admin │ +│ │ │ +│ ├──→ /admin/mcp (调用 MCP 工具) │ +│ │ │ +│ drpy-node │ +│ │ │ +│ └──→ import('../drpy-node-mcp/tools/*.js') ❌ │ +│ │ +│ drpy-node-mcp (独立项目) │ +│ │ │ +│ └──→ 依赖 drpy-node (仅用于开发调试) │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +**核心问题**: drpy-node 作为主服务,不应该依赖 drpy-node-mcp + +### 目标架构 + +``` +┌─────────────────────────────────────────────────────┐ +│ 目标架构 │ +├─────────────────────────────────────────────────────┤ +│ │ +│ drpy-node (主服务) │ +│ │ │ +│ ├──→ /api/admin/* (REST API) │ +│ │ │ +│ ├──→ /admin/* (静态文件) │ +│ │ │ +│ └──→ apps/admin/ (编译后的 SPA) ✓ │ +│ │ +│ drpy-node-admin (开发时) │ +│ │ │ +│ └──→ npm run dev (开发服务器) │ +│ │ +│ drpy-node-mcp (独立项目) │ +│ │ │ +│ └──→ 依赖 drpy-node 的 API (可选) │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +## 📊 变更概览 + +### drpy-node 变更 + +| 操作 | 文件路径 | 说明 | +|-----|---------|------| +| **重构** | `controllers/admin.js` | 移除 MCP 依赖,实现直接业务逻辑 | +| **新增** | `controllers/admin/*.js` | 6 个子控制器模块 | +| **新增** | `utils/admin/*.js` | 3 个工具模块 | +| **新增** | `apps/admin/` | 编译后的 SPA 静态文件 | + +### drpy-node-admin 变更 + +| 操作 | 文件路径 | 说明 | +|-----|---------|------| +| **重构** | `src/api/*.js` | 所有 API 调用改用 REST API | +| **新增** | `src/api/admin.js` | 统一 API 调用模块 | +| **修改** | `vite.config.js` | 输出目录改为 `../apps/admin` | +| **修改** | `src/stores/*.js` | 适配新的 API 响应格式 | + +--- + +## 🚀 实施路线图 + +### Phase 1: 后端 API 实现 (2-3 天) + +**目标**: 实现所有必需的 REST API 接口 + +#### 步骤 1.1: 创建子控制器 (1 天) +``` +✓ controllers/admin/systemController.js - 系统管理 +✓ controllers/admin/logsController.js - 日志管理 +✓ controllers/admin/sourcesController.js - 源管理 +✓ controllers/admin/filesController.js - 文件管理 +✓ controllers/admin/dbController.js - 数据库查询 +✓ controllers/admin/routesController.js - 路由信息 +``` + +#### 步骤 1.2: 重构 admin.js (0.5 天) +``` +✓ 移除 import('../drpy-node-mcp/...') 代码 +✓ 注册子控制器路由 +✓ 实现 WebSocket 日志流 +✓ 添加静态文件服务 +``` + +#### 步骤 1.3: 创建工具模块 (0.5 天) +``` +✓ utils/admin/logReader.js - 日志读取 +✓ utils/admin/configManager.js - 配置管理 +✓ utils/admin/fileValidator.js - 路径安全验证 +``` + +#### 步骤 1.4: 测试 API (0.5 天) +``` +✓ 使用 Postman/Thunder 测试所有 API +✓ 验证响应格式正确性 +✓ 测试 WebSocket 连接 +``` + +--- + +### Phase 2: 前端适配 (1-2 天) + +**目标**: 前端改用新的 REST API + +#### 步骤 2.1: 创建 admin API 模块 (0.5 天) +``` +✓ src/api/admin.js - 统一 API 调用 +``` + +#### 步骤 2.2: 重构现有 API 模块 (0.5 天) +``` +✓ src/api/system.js - 系统相关 +✓ src/api/spider.js - 源管理 +✓ src/api/file.js - 文件管理 +✓ src/api/db.js - 数据库查询 (新增) +``` + +#### 步骤 2.3: 调整 Vite 配置 (0.5 天) +``` +✓ 修改 build.outDir 为 ../apps/admin +✓ 修改 base 为 /admin/ +✓ 调整 proxy 配置 +``` + +#### 步骤 2.4: 前端测试 (0.5 天) +``` +✓ 开发模式测试所有功能 +✓ 验证 API 调用正常 +✓ 测试 WebSocket 日志流 +``` + +--- + +### Phase 3: 构建与集成 (1 天) + +**目标**: 完成 SPA 插件构建和集成 + +#### 步骤 3.1: 配置构建脚本 (0.3 天) +``` +✓ 添加 scripts/build-admin.js +✓ 更新 package.json 脚本 +``` + +#### 步骤 3.2: 构建并验证 (0.3 天) +``` +✓ npm run admin:build +✓ 验证 apps/admin/ 目录生成 +✓ 检查 index.html 和 assets +``` + +#### 步骤 3.3: 集成测试 (0.4 天) +``` +✓ 启动 drpy-node 服务 +✓ 访问 http://localhost:5757/admin/ +✓ 全面功能测试 +✓ 性能测试 +``` + +--- + +### Phase 4: 清理与优化 (可选,1 天) + +**目标**: 移除 MCP 依赖,优化代码 + +#### 步骤 4.1: 移除 MCP 兼容层 +``` +✓ 移除 /admin/mcp 端点 +✓ 清理相关注释 +``` + +#### 步骤 4.2: 代码优化 +``` +✓ 提取公共逻辑 +✓ 添加错误处理 +✓ 完善日志记录 +``` + +#### 步骤 4.3: 文档更新 +``` +✓ 更新 README.md +✓ 更新 API.md +✓ 添加部署文档 +``` + +--- + +## 📁 文件清单 + +### 新增文件 (drpy-node) + +``` +drpy-node/ +├── controllers/admin/ +│ ├── systemController.js ← 新增 +│ ├── logsController.js ← 新增 +│ ├── sourcesController.js ← 新增 +│ ├── filesController.js ← 新增 +│ ├── dbController.js ← 新增 +│ └── routesController.js ← 新增 +└── utils/admin/ + ├── logReader.js ← 新增 + ├── configManager.js ← 新增 + └── fileValidator.js ← 新增 +``` + +### 修改文件 (drpy-node) + +``` +drpy-node/ +└── controllers/ + └── admin.js ← 重构 +``` + +### 新增文件 (drpy-node-admin) + +``` +drpy-node-admin/ +└── src/api/ + └── admin.js ← 新增 +``` + +### 修改文件 (drpy-node-admin) + +``` +drpy-node-admin/ +├── src/api/ +│ ├── client.js ← 修改 baseURL +│ ├── system.js ← 重构 API 调用 +│ ├── spider.js ← 重构 API 调用 +│ └── file.js ← 重构 API 调用 +└── vite.config.js ← 修改构建配置 +``` + +--- + +## 🔄 数据流变化 + +### 之前(MCP 方式) + +``` +drpy-node-admin + │ + │ POST /admin/mcp + │ { "name": "list_sources", "arguments": {} } + ↓ +drpy-node (admin.js) + │ + │ import('../drpy-node-mcp/tools/spiderTools.js') + ↓ +drpy-node-mcp + │ + │ return { content: [{ type: "text", text: JSON.stringify(...) }] } + ↓ +drpy-node-admin + │ + │ JSON.parse(response.content[0].text) +``` + +### 之后(REST API 方式) + +``` +drpy-node-admin + │ + │ GET /api/admin/sources + ↓ +drpy-node (admin.js) + │ + │ 直接调用 sourcesController.listSources() + │ + │ return { js: [...], catvod: [...] } + ↓ +drpy-node-admin +``` + +--- + +## 🎨 前端开发体验 + +### 开发模式 + +```bash +# 终端 1: 启动 drpy-node +npm run dev + +# 终端 2: 启动 drpy-node-admin 开发服务器 +cd drpy-node-admin +npm run dev + +# 访问: http://localhost:5174/ +# API 请求自动代理到 http://localhost:5757 +``` + +### 构建生产版本 + +```bash +cd drpy-node-admin +npm run build + +# 输出到: ../apps/admin/ +# 包含: index.html, assets/*.js, assets/*.css +``` + +### 部署验证 + +```bash +# 启动 drpy-node +npm run dev + +# 访问: http://localhost:5757/admin/ +``` + +--- + +## 🔍 关键决策点 + +### 决策 1: WebSocket 实现 + +**选择**: 使用 @fastify/websocket + +**原因**: +- drpy-node 已使用 Fastify +- @fastify/websocket 官方插件 +- 与现有架构兼容 + +**替代方案**: +- Socket.io (需要额外依赖) +- 原生 WebSocket (需要手动处理) + +### 决策 2: 文件上传方式 + +**选择**: 使用 POST JSON body 传输内容 + +**限制**: +- 适合中小文件 +- 不支持大文件上传 + +**如果需要大文件支持**: +- 可考虑 multipart/form-data +- 或分片上传 + +### 决策 3: 路径安全 + +**策略**: +- 白名单方式(只允许特定目录) +- 禁止路径遍历(..) +- 禁止敏感文件 + +### 决策 4: SQL 安全 + +**策略**: +- 只允许 SELECT 查询 +- 关键词黑名单过滤 +- 参数化查询(如需要) + +--- + +## 📈 成功指标 + +### 功能完整性 +- [ ] 所有现有功能可正常使用 +- [ ] API 响应时间与之前相当 +- [ ] WebSocket 日志流稳定 + +### 代码质量 +- [ ] 无 MCP 依赖 +- [ ] 代码结构清晰 +- [ ] 有适当的错误处理 + +### 可维护性 +- [ ] API 文档完整 +- [ ] 代码注释充分 +- [ ] 易于扩展 + +--- + +## 🎯 下一步行动 + +1. **审查文档** + - 仔细阅读 SPEC.md + - 理解 IMPLEMENTATION.md 中的代码示例 + - 熟悉 API.md 中的接口规范 + +2. **确认计划** + - 评估时间估算是否合理 + - 确认技术方案可行 + - 提出调整建议(如有) + +3. **开始实施** + - 按照 Phase 1 → Phase 2 → Phase 3 顺序执行 + - 每个阶段完成后进行测试 + - 遇到问题及时调整 + +--- + +## 📞 联系与反馈 + +如有疑问或需要调整,请及时沟通。在开始实施前,请确保: + +1. ✅ 已完整阅读所有规划文档 +2. ✅ 理解技术方案和架构设计 +3. ✅ 确认实施计划和时间安排 +4. ✅ 了解风险和应对措施 + +**准备好后,请指示开始实施!** diff --git a/drpy-node-admin/SPEC.md b/drpy-node-admin/SPEC.md new file mode 100644 index 00000000..22ea3dec --- /dev/null +++ b/drpy-node-admin/SPEC.md @@ -0,0 +1,581 @@ +# drpy-node-admin 解耦与 SPA 插件化重构 SPEC + +## 1. 项目概述 + +### 1.1 当前状态 +- **drpy-node-admin**: 独立的 Vue 3 后台管理项目 +- **数据依赖**: 通过 MCP (Model Context Protocol) 工具调用 drpy-node 功能 +- **耦合问题**: admin.js 中动态导入 `drpy-node-mcp` 模块,违反依赖方向 + +### 1.2 目标架构 +``` +┌─────────────────────────────────────────────────────────────┐ +│ drpy-node │ +│ ┌──────────────┐ ┌───────────────┐ ┌──────────────┐ │ +│ │ Core APIs │ │ Controllers │ │ Static │ │ +│ │ │ │ │ │ Files │ │ +│ │ - /api/* │◄─┤ - admin.js │◄─┤ /apps/admin │ │ +│ │ - /admin/* │ │ - api.js │ │ │ │ +│ │ │ │ - config.js │ │ - index.html │ │ +│ │ │ │ - ... │ │ - assets/* │ │ +│ └──────────────┘ └───────────────┘ └──────────────┘ │ +│ ▲ ▲ │ +│ │ │ │ +│ └──────────────┬─────────────────────┘ │ +│ │ │ +│ ┌─────────────────────────────────────────────────────────┐│ +│ │ drpy-node-admin (SPA Plugin) ││ +│ │ ┌─────────┐ ┌──────────┐ ┌────────────┐ ││ +│ │ │ Views │ │ Stores │ │Components │ ││ +│ │ └────┬────┘ └────┬─────┘ └──────┬─────┘ ││ +│ │ │ │ │ ││ +│ │ └──────┬─────┴───────────────┴────┐ ││ +│ │ │ API Client (axios) │ ││ +│ │ └───────────┬─────────────┘ ││ +│ │ │ ││ +│ │ ┌───────────┴─────────────┐ ││ +│ │ │ REST API Interface │ ││ +│ │ │ /api/admin/* │ ││ +│ │ └──────────────────────────┘ ││ +│ └─────────────────────────────────────────────────────────┘│ +└─────────────────────────────────────────────────────────────┘ + + ▲ + │ + ┌───────────────┴───────────────┐ + │ drpy-node-mcp (Independent) │ + │ ┌────────────────────────┐ │ + │ │ MCP Tools │ │ + │ │ - systemTools.js │ │ + │ │ - spiderTools.js │ │ + │ │ - fsTools.js │ │ + │ │ - dbTools.js │ │ + │ │ - apiTools.js │ │ + │ └────────────────────────┘ │ + │ ▲ │ + │ │ (depends on) │ + │ └───────────────────┘ + └──────────────────────────────────┘ +``` + +## 2. 需要实现的 REST API + +### 2.1 系统管理 API + +#### 2.1.1 健康检查 +``` +GET /api/admin/health +Response: { + status: "ok" | "error", + uptime: number, + memory: { used: number, total: number }, + version: string +} +``` + +#### 2.1.2 服务重启 +``` +POST /api/admin/restart +Response: { + success: boolean, + message: string +} +``` + +### 2.2 日志 API + +#### 2.2.1 读取日志 +``` +GET /api/admin/logs?lines=50 +Response: { + file: string, + content: string +} +``` + +#### 2.2.2 WebSocket 实时日志 +``` +WS /api/admin/logs/stream +Message: { + type: "log" | "error" | "end", + content: string, + timestamp: number +} +``` + +### 2.3 配置管理 API + +#### 2.3.1 获取配置 +``` +GET /api/admin/config?key=section.key +Response: any (配置值) +``` + +#### 2.3.2 更新配置 +``` +POST /api/admin/config +Body: { + key: string, + value: any +} +Response: { + success: boolean, + message: string +} +``` + +### 2.4 源管理 API + +#### 2.4.1 列出所有源 +``` +GET /api/admin/sources +Response: { + js: string[], + catvod: string[] +} +``` + +#### 2.4.2 验证源 +``` +POST /api/admin/sources/validate +Body: { + path: string +} +Response: { + isValid: boolean, + message: string +} +``` + +#### 2.4.3 检查语法 +``` +POST /api/admin/sources/syntax +Body: { + path: string +} +Response: { + isValid: boolean, + error?: string +} +``` + +#### 2.4.4 获取模板 +``` +GET /api/admin/sources/template +Response: { + template: string +} +``` + +### 2.5 文件系统 API + +#### 2.5.1 列出目录 +``` +GET /api/admin/files/list?path=spider/js +Response: [{ + name: string, + path: string, + isDirectory: boolean, + size?: number +}] +``` + +#### 2.5.2 读取文件 +``` +GET /api/admin/files/read?path=spider/js/test.js +Response: { + type: "text" | "image", + content?: string, + mimeType?: string, + dataUrl?: string +} +``` + +#### 2.5.3 写入文件 +``` +POST /api/admin/files/write +Body: { + path: string, + content: string +} +Response: { + success: boolean, + message: string +} +``` + +#### 2.5.4 删除文件 +``` +DELETE /api/admin/files/delete?path=spider/js/test.js +Response: { + success: boolean, + message: string +} +``` + +### 2.6 数据库 API + +#### 2.6.1 执行查询 +``` +POST /api/admin/db/query +Body: { + sql: string +} +Response: [{ + // 查询结果行 +}] +``` + +### 2.7 路由信息 API + +#### 2.7.1 获取路由列表 +``` +GET /api/admin/routes +Response: { + registered_controllers: string[] +} +``` + +## 3. 文件结构规划 + +### 3.1 drpy-node 新增文件 +``` +drpy-node/ +├── controllers/ +│ ├── admin.js # 重构,移除 MCP 依赖 +│ └── admin/ +│ ├── systemController.js # 系统管理 +│ ├── logsController.js # 日志管理 +│ ├── sourcesController.js # 源管理 +│ ├── filesController.js # 文件管理 +│ ├── dbController.js # 数据库查询 +│ └── routesController.js # 路由信息 +├── utils/ +│ └── admin/ +│ ├── logReader.js # 日志读取工具 +│ ├── configManager.js # 配置管理工具 +│ └── fileValidator.js # 文件安全验证 +└── apps/ + └── admin/ # 新增:编译后的 admin SPA + ├── index.html + └── assets/ + ├── index-*.js + └── index-*.css +``` + +### 3.2 drpy-node-admin 文件调整 +``` +drpy-node-admin/ +├── src/ +│ ├── api/ +│ │ ├── client.js # 保持,调整 baseURL +│ │ ├── admin.js # 新增:统一的 admin API 调用 +│ │ ├── system.js # 重构:使用 /api/admin/system +│ │ ├── sources.js # 重构:使用 /api/admin/sources +│ │ ├── files.js # 重构:使用 /api/admin/files +│ │ └── db.js # 重构:使用 /api/admin/db +│ ├── views/ +│ │ └── ... (保持不变) +│ ├── stores/ +│ │ └── ... (保持不变) +│ └── components/ +│ └── ... (保持不变) +├── vite.config.js # 调整:output 指向 apps/admin +├── package.json +└── tailwind.config.js +``` + +## 4. 实施步骤 + +### Phase 1: API 层实现 (drpy-node) + +#### 步骤 1.1: 创建 admin 子控制器 +1. 创建 `controllers/admin/` 目录 +2. 实现 6 个子控制器模块 +3. 每个控制器实现对应的 API 接口 + +#### 步骤 1.2: 重构 admin.js +1. 移除 `import('../drpy-node-mcp/...')` 动态导入 +2. 实现独立的业务逻辑 +3. 注册子控制器路由 +4. 添加静态文件服务指向 `apps/admin/` + +#### 步骤 1.3: 实现工具函数 +1. `utils/admin/logReader.js` - 日志文件读取 +2. `utils/admin/configManager.js` - 配置文件管理 +3. `utils/admin/fileValidator.js` - 路径安全验证 + +### Phase 2: 前端适配 (drpy-node-admin) + +#### 步骤 2.1: API 客户端重构 +1. 调整 `baseURL` 为 `/api/admin` +2. 移除 MCP 响应解析逻辑 +3. 实现标准的 REST API 调用 + +#### 步骤 2.2: Vite 配置调整 +1. 修改 `build.outDir` 为 `../apps/admin` +2. 修改 `base` 为 `/admin/` +3. 添加构建优化配置 + +#### 步骤 2.3: 路由模式调整 +1. 使用 history 模式或 hash 模式 +2. 添加路由回退处理 + +### Phase 3: 构建与集成 + +#### 步骤 3.1: 本地测试 +1. 运行 `npm run admin:build` 构建 +2. 验证生成的文件在 `apps/admin/` 目录 +3. 测试所有功能正常工作 + +#### 步骤 3.2: 最终验证 +1. 清理 MCP 依赖 +2. 确认 drpy-node 可以独立运行 +3. 性能测试 + +## 5. API 详细规范 + +### 5.1 通用响应格式 +```typescript +// 成功响应 +{ + success: true, + data?: any, + message?: string +} + +// 错误响应 +{ + success: false, + error: string, + code?: string +} +``` + +### 5.2 错误码定义 +```javascript +const ErrorCodes = { + UNAUTHORIZED: 'UNAUTHORIZED', + FORBIDDEN: 'FORBIDDEN', + NOT_FOUND: 'NOT_FOUND', + INVALID_PATH: 'INVALID_PATH', + SYNTAX_ERROR: 'SYNTAX_ERROR', + VALIDATION_ERROR: 'VALIDATION_ERROR', + INTERNAL_ERROR: 'INTERNAL_ERROR' +} +``` + +### 5.3 认证与授权 +```javascript +// 使用与 /apps/ 相同的认证机制 +// 所有 /api/admin/* 接口需要 basic auth +``` + +## 6. WebSocket 实时日志规范 + +### 6.1 连接 +``` +WS /api/admin/logs/stream +``` + +### 6.2 消息格式 +```javascript +// 客户端 → 服务端 +{ + action: "subscribe" | "unsubscribe" | "clear", + lines?: number +} + +// 服务端 → 客户端 +{ + type: "log" | "error" | "end", + timestamp: number, + content: string +} +``` + +### 6.3 心跳机制 +```javascript +// 每 30 秒发送一次心跳 +// 客户端 +setInterval(() => { + ws.send(JSON.stringify({ type: 'heartbeat' })) +}, 30000) + +// 服务端响应 +{ type: 'pong' } +``` + +## 7. 安全考虑 + +### 7.1 路径验证 +```javascript +// 只允许访问特定目录 +const ALLOWED_PATHS = [ + 'spider/js', + 'spider/js_dr2', + 'spider/catvod', + 'spider/py', + 'spider/xbpq', + 'config', + 'json', + 'docs' +]; + +// 禁止路径遍历 +function validatePath(path) { + return !path.includes('..') && + !path.includes('~') && + !path.startsWith('/'); + +} +``` + +### 7.2 SQL 注入防护 +```javascript +// 只允许 SELECT 查询 +if (!query.trim().toLowerCase().startsWith('select')) { + throw new Error('Only SELECT queries allowed'); +} +``` + +### 7.3 文件操作限制 +```javascript +// 禁止写入关键文件 +const PROTECTED_FILES = [ + 'package.json', + 'index.js', + 'database.db' +]; +``` + +## 8. 性能优化 + +### 8.1 日志流式传输 +```javascript +// 使用流式传输大日志文件 +const stream = fs.createReadStream(logPath); +stream.on('data', (chunk) => { + ws.send({ type: 'log', content: chunk.toString() }); +}); +``` + +### 8.2 静态资源缓存 +```javascript +// admin 静态资源缓存策略 +fastify.register(fastifyStatic, { + root: adminDistPath, + prefix: '/admin/', + cacheControl: 3600, // 1 小时 + etag: true +}); +``` + +### 8.3 API 响应压缩 +```javascript +// 启用 gzip 压缩 +import fastifyCompress from '@fastify/compress'; +fastify.register(fastifyCompress); +``` + +## 9. 兼容性说明 + +### 9.1 向后兼容 +- 保留 `/admin/mcp` 接口作为临时兼容层(可配置开关) +- 给予过渡期,逐步迁移到新 API + +### 9.2 版本控制 +```javascript +// API 版本号 +const API_VERSION = 'v1'; +// 所有响应头包含版本 +reply.header('X-API-Version', API_VERSION); +``` + +## 10. 测试计划 + +### 10.1 单元测试 +- 每个控制器函数的单元测试 +- 工具函数的单元测试 +- API 响应格式验证 + +### 10.2 集成测试 +- API 端到端测试 +- WebSocket 连接测试 +- 文件上传下载测试 + +### 10.3 性能测试 +- 日志流式传输性能 +- 大文件读取性能 +- 并发请求处理 + +## 11. 交付物清单 + +### 11.1 drpy-node 修改 +- [ ] `controllers/admin.js` - 重构完成 +- [ ] `controllers/admin/systemController.js` - 新增 +- [ ] `controllers/admin/logsController.js` - 新增 +- [ ] `controllers/admin/sourcesController.js` - 新增 +- [ ] `controllers/admin/filesController.js` - 新增 +- [ ] `controllers/admin/dbController.js` - 新增 +- [ ] `controllers/admin/routesController.js` - 新增 +- [ ] `utils/admin/logReader.js` - 新增 +- [ ] `utils/admin/configManager.js` - 新增 +- [ ] `utils/admin/fileValidator.js` - 新增 + +### 11.2 drpy-node-admin 修改 +- [ ] `src/api/client.js` - baseURL 调整 +- [ ] `src/api/admin.js` - 统一 API 调用 +- [ ] `src/api/system.js` - API 重构 +- [ ] `src/api/spider.js` - API 重构 +- [ ] `src/api/file.js` - API 重构 +- [ ] `src/api/db.js` - API 重构 +- [ ] `vite.config.js` - 构建配置调整 +- [ ] `package.json` - 脚本更新 + +### 11.3 文档 +- [ ] API 接口文档 +- [ ] 部署指南 +- [ ] 开发指南更新 +- [ ] 变更日志 + +## 12. 时间估算 + +| 阶段 | 任务 | 预计时间 | +|-----|------|---------| +| Phase 1 | API 层实现 | 2-3 天 | +| Phase 2 | 前端适配 | 1-2 天 | +| Phase 3 | 构建与集成 | 1 天 | +| 测试与修复 | 全面测试 | 1-2 天 | +| **总计** | | **5-8 天** | + +## 13. 风险与应对 + +### 13.1 技术风险 +**风险**: 解耦后功能缺失 +**应对**: 详细的功能对比测试清单 + +### 13.2 兼容性风险 +**风险**: 现有部署环境适配问题 +**应对**: 保持 MCP 临时兼容层 + +### 13.3 性能风险 +**风险**: 新架构性能下降 +**应对**: 性能基准测试和优化 + +## 14. 后续优化方向 + +### 14.1 功能增强 +- 添加源市场功能 +- 添加源订阅功能 +- 添加统计分析功能 + +### 14.2 用户体验优化 +- 实现主题自定义 +- 添加快捷键支持 +- 优化移动端体验 + +### 14.3 运维功能 +- 添加系统监控图表 +- 实现日志分析功能 +- 添加性能指标展示 diff --git a/drpy-node-admin/index.html b/drpy-node-admin/index.html new file mode 100644 index 00000000..74275406 --- /dev/null +++ b/drpy-node-admin/index.html @@ -0,0 +1,13 @@ + + + + + + DRPYS ADMIN + + + +
+ + + diff --git a/drpy-node-admin/package-lock.json b/drpy-node-admin/package-lock.json new file mode 100644 index 00000000..6454686d --- /dev/null +++ b/drpy-node-admin/package-lock.json @@ -0,0 +1,2812 @@ +{ + "name": "drpy-node-admin", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "drpy-node-admin", + "version": "1.0.0", + "dependencies": { + "@guolao/vue-monaco-editor": "^1.6.0", + "axios": "^1.7.9", + "pinia": "^2.2.8", + "sortablejs": "^1.15.7", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.1", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.17", + "vite": "^6.0.11" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@guolao/vue-monaco-editor": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/@guolao/vue-monaco-editor/-/vue-monaco-editor-1.6.0.tgz", + "integrity": "sha512-w2IiJ6eJGGeuIgCK6EKZOAfhHTTUB5aZwslzwGbZ5e89Hb4avx6++GkLTW8p84Sng/arFMjLPPxSBI56cFudyQ==", + "license": "MIT", + "dependencies": { + "@monaco-editor/loader": "^1.6.1", + "vue-demi": "latest" + }, + "peerDependencies": { + "@vue/composition-api": "^1.7.2", + "monaco-editor": ">=0.43.0", + "vue": "^2.6.14 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@monaco-editor/loader": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/@monaco-editor/loader/-/loader-1.7.0.tgz", + "integrity": "sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==", + "license": "MIT", + "dependencies": { + "state-local": "^1.0.6" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.30.tgz", + "integrity": "sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/shared": "3.5.30", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.30.tgz", + "integrity": "sha512-eCFYESUEVYHhiMuK4SQTldO3RYxyMR/UQL4KdGD1Yrkfdx4m/HYuZ9jSfPdA+nWJY34VWndiYdW/wZXyiPEB9g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.30", + "@vue/shared": "3.5.30" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.30.tgz", + "integrity": "sha512-LqmFPDn89dtU9vI3wHJnwaV6GfTRD87AjWpTWpyrdVOObVtjIuSeZr181z5C4PmVx/V3j2p+0f7edFKGRMpQ5A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/compiler-core": "3.5.30", + "@vue/compiler-dom": "3.5.30", + "@vue/compiler-ssr": "3.5.30", + "@vue/shared": "3.5.30", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.8", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.30.tgz", + "integrity": "sha512-NsYK6OMTnx109PSL2IAyf62JP6EUdk4Dmj6AkWcJGBvN0dQoMYtVekAmdqgTtWQgEJo+Okstbf/1p7qZr5H+bA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.30", + "@vue/shared": "3.5.30" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.30.tgz", + "integrity": "sha512-179YNgKATuwj9gB+66snskRDOitDiuOZqkYia7mHKJaidOMo/WJxHKF8DuGc4V4XbYTJANlfEKb0yxTQotnx4Q==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.30" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.30.tgz", + "integrity": "sha512-e0Z+8PQsUTdwV8TtEsLzUM7SzC7lQwYKePydb7K2ZnmS6jjND+WJXkmmfh/swYzRyfP1EY3fpdesyYoymCzYfg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.30", + "@vue/shared": "3.5.30" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.30.tgz", + "integrity": "sha512-2UIGakjU4WSQ0T4iwDEW0W7vQj6n7AFn7taqZ9Cvm0Q/RA2FFOziLESrDL4GmtI1wV3jXg5nMoJSYO66egDUBw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.30", + "@vue/runtime-core": "3.5.30", + "@vue/shared": "3.5.30", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.30.tgz", + "integrity": "sha512-v+R34icapydRwbZRD0sXwtHqrQJv38JuMB4JxbOxd8NEpGLny7cncMp53W9UH/zo4j8eDHjQ1dEJXwzFQknjtQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.30", + "@vue/shared": "3.5.30" + }, + "peerDependencies": { + "vue": "3.5.30" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.30.tgz", + "integrity": "sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ==", + "license": "MIT" + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.27", + "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001774", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "1.13.6", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.8", + "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", + "integrity": "sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001780", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz", + "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/dompurify": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "peer": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.313", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz", + "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/marked": { + "version": "14.0.0", + "resolved": "https://registry.npmmirror.com/marked/-/marked-14.0.0.tgz", + "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "license": "MIT", + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/monaco-editor": { + "version": "0.55.1", + "resolved": "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.55.1.tgz", + "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", + "license": "MIT", + "peer": true, + "dependencies": { + "dompurify": "3.2.7", + "marked": "14.0.0" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinia": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz", + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmmirror.com/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/sortablejs": { + "version": "1.15.7", + "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.7.tgz", + "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "license": "MIT" + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmmirror.com/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmmirror.com/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmmirror.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vue": { + "version": "3.5.30", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.30.tgz", + "integrity": "sha512-hTHLc6VNZyzzEH/l7PFGjpcTvUgiaPK5mdLkbjrTeWSRcEfxFrv56g/XckIYlE9ckuobsdwqd5mk2g1sBkMewg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.30", + "@vue/compiler-sfc": "3.5.30", + "@vue/runtime-dom": "3.5.30", + "@vue/server-renderer": "3.5.30", + "@vue/shared": "3.5.30" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + } + } +} diff --git a/drpy-node-admin/package.json b/drpy-node-admin/package.json new file mode 100644 index 00000000..7535cd40 --- /dev/null +++ b/drpy-node-admin/package.json @@ -0,0 +1,26 @@ +{ + "name": "drpy-node-admin", + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "build:apps": "vite build --mode production.apps", + "preview": "vite preview" + }, + "dependencies": { + "@guolao/vue-monaco-editor": "^1.6.0", + "axios": "^1.7.9", + "pinia": "^2.2.8", + "sortablejs": "^1.15.7", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.1", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.17", + "vite": "^6.0.11" + } +} diff --git a/drpy-node-admin/postcss.config.js b/drpy-node-admin/postcss.config.js new file mode 100644 index 00000000..2e7af2b7 --- /dev/null +++ b/drpy-node-admin/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/drpy-node-admin/public/drpys.png b/drpy-node-admin/public/drpys.png new file mode 100644 index 00000000..dac857da Binary files /dev/null and b/drpy-node-admin/public/drpys.png differ diff --git a/drpy-node-admin/public/favicon.svg b/drpy-node-admin/public/favicon.svg new file mode 100644 index 00000000..14f166b5 --- /dev/null +++ b/drpy-node-admin/public/favicon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/drpy-node-admin/src/App.vue b/drpy-node-admin/src/App.vue new file mode 100644 index 00000000..cc925d92 --- /dev/null +++ b/drpy-node-admin/src/App.vue @@ -0,0 +1,104 @@ + + + + + diff --git a/drpy-node-admin/src/api/admin.js b/drpy-node-admin/src/api/admin.js new file mode 100644 index 00000000..72513932 --- /dev/null +++ b/drpy-node-admin/src/api/admin.js @@ -0,0 +1,131 @@ +/** + * Admin API 统一调用接口 + * 所有后台管理 API 都通过这个模块调用 + */ + +import client from './client'; + +export const adminApi = { + // ==================== 系统 ==================== + async getHealth() { + return client.get('/api/admin/health'); + }, + + async restartService() { + return client.post('/api/admin/restart'); + }, + + // ==================== 日志 ==================== + async getLogs(lines = 50) { + return client.get('/api/admin/logs', { params: { lines } }); + }, + + // WebSocket 连接在组件中直接使用 + + // ==================== 配置 ==================== + async getConfig(key) { + return client.get('/api/admin/config', { params: { key } }); + }, + + async updateConfig(key, value) { + return client.post('/api/admin/config', { key, value }); + }, + + async getEnv() { + return client.get('/api/admin/env'); + }, + + // ==================== 源管理 ==================== + async listSources() { + return client.get('/api/admin/sources'); + }, + + async validateSource(path) { + return client.post('/api/admin/sources/validate', { path }); + }, + + async checkSyntax(path) { + return client.post('/api/admin/sources/syntax', { path }); + }, + + async getTemplate() { + return client.get('/api/admin/sources/template'); + }, + + async getLibsInfo() { + return client.get('/api/admin/sources/libs'); + }, + + // ==================== 文件管理 ==================== + async listDirectory(path) { + return client.get('/api/admin/files/list', { params: { path } }); + }, + + async readFile(path) { + return client.get('/api/admin/files/read', { params: { path } }); + }, + + async writeFile(path, content) { + return client.post('/api/admin/files/write', { path, content }); + }, + + async deleteFile(path) { + return client.delete('/api/admin/files/delete', { params: { path } }); + }, + + // ==================== 数据库 ==================== + async executeQuery(sql) { + return client.post('/api/admin/db/query', { sql }); + }, + + async getTables() { + return client.get('/api/admin/db/tables'); + }, + + async getTableSchema(table) { + return client.get(`/api/admin/db/tables/${table}/schema`); + }, + + // ==================== 路由信息 ==================== + async getRoutes() { + return client.get('/api/admin/routes'); + }, + + async getApiDocs() { + return client.get('/api/admin/docs'); + }, + + // ==================== 订阅管理 ==================== + async getSubFiles() { + return client.get('/api/admin/sub/files'); + }, + + async getSubFile(name) { + return client.get('/api/admin/sub/file', { params: { name } }); + }, + + async saveSubFile(name, content) { + return client.post('/api/admin/sub/file', { name, content }); + }, + + // ==================== 备份恢复 ==================== + async getBackupConfig() { + return client.get('/api/admin/backup/config'); + }, + + async updateBackupConfig(paths) { + return client.post('/api/admin/backup/config', { paths }); + }, + + async resetBackupConfig() { + return client.post('/api/admin/backup/config/reset'); + }, + + async createBackup() { + return client.post('/api/admin/backup/create'); + }, + + async restoreBackup() { + return client.post('/api/admin/backup/restore'); + } +}; diff --git a/drpy-node-admin/src/api/client.js b/drpy-node-admin/src/api/client.js new file mode 100644 index 00000000..77a43855 --- /dev/null +++ b/drpy-node-admin/src/api/client.js @@ -0,0 +1,36 @@ +import axios from 'axios' + +const apiClient = axios.create({ + baseURL: '', + timeout: 30000, + headers: { + 'Content-Type': 'application/json' + } +}) + +// Request interceptor +apiClient.interceptors.request.use( + (config) => { + // Add auth if needed + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// Response interceptor +apiClient.interceptors.response.use( + (response) => { + // 打印响应以便调试 + // console.log('API Response:', response.data) + return response.data + }, + (error) => { + const message = error.response?.data?.message || error.response?.data?.error || error.message || '请求失败' + console.error('API Error:', message, error.response?.data) + return Promise.reject(new Error(message)) + } +) + +export default apiClient diff --git a/drpy-node-admin/src/api/config.js b/drpy-node-admin/src/api/config.js new file mode 100644 index 00000000..c2283d61 --- /dev/null +++ b/drpy-node-admin/src/api/config.js @@ -0,0 +1,15 @@ +import { adminApi } from './admin'; + +export const configApi = { + async getConfig() { + return await adminApi.getConfig(); + }, + + async updateConfig(key, value) { + return await adminApi.updateConfig(key, value); + }, + + async getConfigValue(key) { + return await adminApi.getConfig(key); + } +}; diff --git a/drpy-node-admin/src/api/db.js b/drpy-node-admin/src/api/db.js new file mode 100644 index 00000000..7694dae4 --- /dev/null +++ b/drpy-node-admin/src/api/db.js @@ -0,0 +1,18 @@ +import { adminApi } from './admin'; + +export const dbApi = { + async query(sql) { + const result = await adminApi.executeQuery(sql); + return result.data; + }, + + async getTables() { + const result = await adminApi.getTables(); + return result.tables; + }, + + async getTableSchema(table) { + const result = await adminApi.getTableSchema(table); + return result.columns; + } +}; diff --git a/drpy-node-admin/src/api/file.js b/drpy-node-admin/src/api/file.js new file mode 100644 index 00000000..847d21be --- /dev/null +++ b/drpy-node-admin/src/api/file.js @@ -0,0 +1,23 @@ +import { adminApi } from './admin'; + +export const fileApi = { + async listDirectory(path = '.') { + const result = await adminApi.listDirectory(path); + return result; + }, + + async readFile(path) { + const result = await adminApi.readFile(path); + return result; + }, + + async writeFile(path, content) { + const result = await adminApi.writeFile(path, content); + return result; + }, + + async deleteFile(path) { + const result = await adminApi.deleteFile(path); + return result; + } +}; diff --git a/drpy-node-admin/src/api/spider.js b/drpy-node-admin/src/api/spider.js new file mode 100644 index 00000000..5bd17a6d --- /dev/null +++ b/drpy-node-admin/src/api/spider.js @@ -0,0 +1,46 @@ +import { adminApi } from './admin'; + +export const spiderApi = { + async listSources() { + const result = await adminApi.listSources(); + return { + js: result.js || [], + catvod: result.catvod || [], + php: result.php || [], + py: result.py || [] + }; + }, + + async validateSpider(path) { + const result = await adminApi.validateSource(path); + // 保持与原有格式兼容 + if (result.isValid) { + return { isError: false, content: [{ text: result.message || '验证通过' }] }; + } else { + return { isError: true, content: [{ text: result.error }] }; + } + }, + + async checkSyntax(path) { + const result = await adminApi.checkSyntax(path); + // 保持与原有格式兼容 + if (result.isValid) { + return { isError: false, content: [{ text: result.message || '语法正确' }] }; + } else { + return { isError: true, content: [{ text: result.error }] }; + } + }, + + async getTemplate() { + const result = await adminApi.getTemplate(); + return result.template; + }, + + async debugRule(params) { + // 暂未实现 + return { + isError: true, + content: [{ text: '调试功能暂未实现' }] + }; + } +}; diff --git a/drpy-node-admin/src/api/system.js b/drpy-node-admin/src/api/system.js new file mode 100644 index 00000000..d75eb8cb --- /dev/null +++ b/drpy-node-admin/src/api/system.js @@ -0,0 +1,23 @@ +import { adminApi } from './admin'; + +export const systemApi = { + async getHealth() { + return await adminApi.getHealth(); + }, + + async restartService() { + return await adminApi.restartService(); + }, + + async getRoutes() { + return await adminApi.getRoutes(); + }, + + async getLogs(lines = 100) { + return await adminApi.getLogs(lines); + }, + + async getApiList() { + return await adminApi.getApiDocs(); + } +}; diff --git a/drpy-node-admin/src/components/Header.vue b/drpy-node-admin/src/components/Header.vue new file mode 100644 index 00000000..265d9e67 --- /dev/null +++ b/drpy-node-admin/src/components/Header.vue @@ -0,0 +1,57 @@ + + + diff --git a/drpy-node-admin/src/components/Sidebar.vue b/drpy-node-admin/src/components/Sidebar.vue new file mode 100644 index 00000000..a78e4517 --- /dev/null +++ b/drpy-node-admin/src/components/Sidebar.vue @@ -0,0 +1,72 @@ + + + diff --git a/drpy-node-admin/src/main.js b/drpy-node-admin/src/main.js new file mode 100644 index 00000000..f021ba49 --- /dev/null +++ b/drpy-node-admin/src/main.js @@ -0,0 +1,25 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import router from './router' +import App from './App.vue' +import './style.css' +import { install as VueMonacoEditorPlugin } from '@guolao/vue-monaco-editor' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.use(VueMonacoEditorPlugin, { + paths: { + // 使用 jsdelivr 的国内加速节点或者 unpkg + vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs' + }, + 'vs/nls': { + availableLanguages: { + '*': 'zh-cn' + } + } +}) + +app.mount('#app') diff --git a/drpy-node-admin/src/router/index.js b/drpy-node-admin/src/router/index.js new file mode 100644 index 00000000..e4b383f4 --- /dev/null +++ b/drpy-node-admin/src/router/index.js @@ -0,0 +1,98 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { useThemeStore } from '../stores/theme' + +const routes = [ + { + path: '/', + name: 'dashboard', + component: () => import('../views/Dashboard.vue'), + meta: { title: '仪表盘' } + }, + { + path: '/config', + name: 'config', + component: () => import('../views/Config.vue'), + meta: { title: '环境配置' } + }, + { + path: '/sources', + name: 'sources', + component: () => import('../views/Sources.vue'), + meta: { title: '源管理' } + }, + { + path: '/sources/editor', + name: 'source-editor', + component: () => import('../views/SourceEditor.vue'), + meta: { title: '源编辑器' } + }, + { + path: '/parses', + name: 'parses', + component: () => import('../views/Parses.vue'), + meta: { title: '解析管理' } + }, + { + path: '/map-manager', + name: 'map-manager', + component: () => import('../views/MapManager.vue'), + meta: { title: '站源映射' } + }, + { + path: '/logs', + name: 'logs', + component: () => import('../views/Logs.vue'), + meta: { title: '日志查看' } + }, + { + path: '/api-docs', + name: 'api', + component: () => import('../views/ApiDocs.vue'), + meta: { title: 'API 文档' } + }, + { + path: '/files', + name: 'files', + component: () => import('../views/Files.vue'), + meta: { title: '文件管理' } + }, + { + path: '/database', + name: 'database', + component: () => import('../views/Database.vue'), + meta: { title: '数据库' } + }, + { + path: '/subscription', + name: 'subscription', + component: () => import('../views/Subscription.vue'), + meta: { title: '订阅管理' } + }, + { + path: '/backup', + name: 'backup', + component: () => import('../views/Backup.vue'), + meta: { title: '系统备份' } + } +] + +const router = createRouter({ + history: createWebHistory(import.meta.env.VITE_BASE_PATH || import.meta.env.BASE_URL), + routes +}) + +// Navigation guard +router.beforeEach((to, from, next) => { + const themeStore = useThemeStore() + // Close sidebar on mobile when navigating + if (window.innerWidth < 1024) { + themeStore.closeSidebar() + } + + // Update document title + document.title = to.meta.title ? `${to.meta.title} - DRPYS ADMIN` : 'DRPYS ADMIN' + + next() +}) + +export default router diff --git a/drpy-node-admin/src/stores/config.js b/drpy-node-admin/src/stores/config.js new file mode 100644 index 00000000..2cf5c080 --- /dev/null +++ b/drpy-node-admin/src/stores/config.js @@ -0,0 +1,45 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { configApi } from '../api/config' + +export const useConfigStore = defineStore('config', () => { + const config = ref(null) + const loading = ref(false) + const error = ref(null) + + const fetchConfig = async () => { + loading.value = true + error.value = null + try { + config.value = await configApi.getConfig() + } catch (e) { + error.value = e.message + console.error('Failed to fetch config:', e) + } finally { + loading.value = false + } + } + + const updateConfig = async (key, value) => { + loading.value = true + error.value = null + try { + await configApi.updateConfig(key, value) + await fetchConfig() + } catch (e) { + error.value = e.message + console.error('Failed to update config:', e) + throw e + } finally { + loading.value = false + } + } + + return { + config, + loading, + error, + fetchConfig, + updateConfig + } +}) diff --git a/drpy-node-admin/src/stores/system.js b/drpy-node-admin/src/stores/system.js new file mode 100644 index 00000000..f94a0300 --- /dev/null +++ b/drpy-node-admin/src/stores/system.js @@ -0,0 +1,84 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { systemApi } from '../api/system' +import { spiderApi } from '../api/spider' + +export const useSystemStore = defineStore('system', () => { + const health = ref({ status: 'unknown' }) + const logs = ref([]) + const routes = ref([]) + const sources = ref({ js: [], catvod: [], php: [], py: [] }) + const loading = ref(false) + const error = ref(null) + + const checkHealth = async () => { + try { + health.value = await systemApi.getHealth() + } catch (e) { + health.value = { status: 'error', message: e.message } + } + } + + const fetchLogs = async (lines = 100) => { + loading.value = true + error.value = null + try { + logs.value = await systemApi.getLogs(lines) + } catch (e) { + error.value = e.message + console.error('Failed to fetch logs:', e) + } finally { + loading.value = false + } + } + + const fetchRoutes = async () => { + try { + routes.value = await systemApi.getRoutes() + } catch (e) { + error.value = e.message + console.error('Failed to fetch routes:', e) + } + } + + const fetchSources = async () => { + loading.value = true + error.value = null + try { + sources.value = await spiderApi.listSources() + } catch (e) { + error.value = e.message + console.error('Failed to fetch sources:', e) + } finally { + loading.value = false + } + } + + const restartService = async () => { + loading.value = true + error.value = null + try { + await systemApi.restartService() + } catch (e) { + error.value = e.message + console.error('Failed to restart service:', e) + throw e + } finally { + loading.value = false + } + } + + return { + health, + logs, + routes, + sources, + loading, + error, + checkHealth, + fetchLogs, + fetchRoutes, + fetchSources, + restartService + } +}) diff --git a/drpy-node-admin/src/stores/theme.js b/drpy-node-admin/src/stores/theme.js new file mode 100644 index 00000000..3a68fd2a --- /dev/null +++ b/drpy-node-admin/src/stores/theme.js @@ -0,0 +1,53 @@ +import { defineStore } from 'pinia' +import { ref, watch } from 'vue' + +export const useThemeStore = defineStore('theme', () => { + const isDark = ref(false) + const sidebarOpen = ref(false) + + // Initialize theme from localStorage or system preference + const initTheme = () => { + const saved = localStorage.getItem('theme') + if (saved) { + isDark.value = saved === 'dark' + } else { + isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches + } + updateTheme() + } + + const updateTheme = () => { + if (isDark.value) { + document.documentElement.classList.add('dark') + } else { + document.documentElement.classList.remove('dark') + } + } + + const toggleTheme = () => { + isDark.value = !isDark.value + } + + const closeSidebar = () => { + sidebarOpen.value = false + } + + const toggleSidebar = () => { + sidebarOpen.value = !sidebarOpen.value + } + + // Watch for changes and save to localStorage + watch(isDark, () => { + localStorage.setItem('theme', isDark.value ? 'dark' : 'light') + updateTheme() + }) + + return { + isDark, + sidebarOpen, + initTheme, + toggleTheme, + closeSidebar, + toggleSidebar + } +}) diff --git a/drpy-node-admin/src/style.css b/drpy-node-admin/src/style.css new file mode 100644 index 00000000..5f4e9522 --- /dev/null +++ b/drpy-node-admin/src/style.css @@ -0,0 +1,82 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + body { + @apply bg-gray-50 text-gray-900 dark:bg-gray-900 dark:text-gray-100; + font-feature-settings: "rlig" 1, "calt" 1; + } +} + +@layer components { + .btn { + @apply inline-flex items-center justify-center rounded-lg px-4 py-2 text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none; + } + + .btn-primary { + @apply btn bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500; + } + + .btn-secondary { + @apply btn bg-gray-200 text-gray-900 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600 focus:ring-gray-500; + } + + .btn-danger { + @apply btn bg-red-600 text-white hover:bg-red-700 focus:ring-red-500; + } + + .btn-success { + @apply btn bg-green-600 text-white hover:bg-green-700 focus:ring-green-500; + } + + .card { + @apply bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700; + } + + .input { + @apply w-full h-[38px] px-3 py-2 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-gray-100 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-colors; + } + + textarea.input { + @apply h-auto; + } + + .badge { + @apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium; + } + + .badge-success { + @apply badge bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200; + } + + .badge-warning { + @apply badge bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200; + } + + .badge-error { + @apply badge bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200; + } + + .badge-info { + @apply badge bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200; + } +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + @apply bg-gray-100 dark:bg-gray-800; +} + +::-webkit-scrollbar-thumb { + @apply bg-gray-300 dark:bg-gray-600 rounded-full; +} + +::-webkit-scrollbar-thumb:hover { + @apply bg-gray-400 dark:bg-gray-500; +} diff --git a/drpy-node-admin/src/views/ApiDocs.vue b/drpy-node-admin/src/views/ApiDocs.vue new file mode 100644 index 00000000..f66b82c7 --- /dev/null +++ b/drpy-node-admin/src/views/ApiDocs.vue @@ -0,0 +1,210 @@ + + + + + diff --git a/drpy-node-admin/src/views/Backup.vue b/drpy-node-admin/src/views/Backup.vue new file mode 100644 index 00000000..d2c52d91 --- /dev/null +++ b/drpy-node-admin/src/views/Backup.vue @@ -0,0 +1,378 @@ + + + + + diff --git a/drpy-node-admin/src/views/Config.vue b/drpy-node-admin/src/views/Config.vue new file mode 100644 index 00000000..dfa364b2 --- /dev/null +++ b/drpy-node-admin/src/views/Config.vue @@ -0,0 +1,403 @@ + + + + + \ No newline at end of file diff --git a/drpy-node-admin/src/views/Parses.vue b/drpy-node-admin/src/views/Parses.vue new file mode 100644 index 00000000..8af6f559 --- /dev/null +++ b/drpy-node-admin/src/views/Parses.vue @@ -0,0 +1,158 @@ + + + + + \ No newline at end of file diff --git a/drpy-node-admin/src/views/SourceEditor.vue b/drpy-node-admin/src/views/SourceEditor.vue new file mode 100644 index 00000000..e3262e76 --- /dev/null +++ b/drpy-node-admin/src/views/SourceEditor.vue @@ -0,0 +1,286 @@ + + + + + diff --git a/drpy-node-admin/src/views/Sources.vue b/drpy-node-admin/src/views/Sources.vue new file mode 100644 index 00000000..bd78e8bc --- /dev/null +++ b/drpy-node-admin/src/views/Sources.vue @@ -0,0 +1,284 @@ + + + + + diff --git a/drpy-node-admin/src/views/Subscription.vue b/drpy-node-admin/src/views/Subscription.vue new file mode 100644 index 00000000..0c6a59a9 --- /dev/null +++ b/drpy-node-admin/src/views/Subscription.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/drpy-node-admin/tailwind.config.js b/drpy-node-admin/tailwind.config.js new file mode 100644 index 00000000..5fdd6b9a --- /dev/null +++ b/drpy-node-admin/tailwind.config.js @@ -0,0 +1,31 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{vue,js,ts,jsx,tsx}", + ], + darkMode: 'class', + theme: { + extend: { + colors: { + primary: { + 50: '#f0f9ff', + 100: '#e0f2fe', + 200: '#bae6fd', + 300: '#7dd3fc', + 400: '#38bdf8', + 500: '#0ea5e9', + 600: '#0284c7', + 700: '#0369a1', + 800: '#075985', + 900: '#0c4a6e', + }, + }, + animation: { + 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite', + 'spin-slow': 'spin 3s linear infinite', + } + }, + }, + plugins: [], +} diff --git a/drpy-node-admin/vite.config.js b/drpy-node-admin/vite.config.js new file mode 100644 index 00000000..1ede903e --- /dev/null +++ b/drpy-node-admin/vite.config.js @@ -0,0 +1,56 @@ +import { fileURLToPath } from 'url'; +import { defineConfig, loadEnv } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import path from 'path'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +export default defineConfig(({ command, mode }) => { + // 加载环境变量 + const env = loadEnv(mode, process.cwd(), ''); + + return { + plugins: [vue()], + + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + } + }, + + // 构建配置 + build: { + outDir: path.resolve(__dirname, '../apps/admin'), + emptyOutDir: true, + rollupOptions: { + output: { + manualChunks: { + 'vendor': ['vue', 'vue-router', 'pinia'], + 'ui': ['axios'] + } + } + }, + chunkSizeWarningLimit: 1000 + }, + + // 开发服务器配置 + server: { + port: 5174, + proxy: { + // 所有 API 请求代理到 drpy-node + '/api': { + target: 'http://localhost:5757', + changeOrigin: true + }, + // WebSocket 代理 + '/ws': { + target: 'ws://localhost:5757', + ws: true + } + } + }, + + // 基础路径 + base: mode.includes('production') ? (env.VITE_BASE_PATH || './') : '/' + }; +}); diff --git "a/drpy-node-bundle/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" "b/drpy-node-bundle/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" new file mode 100644 index 00000000..eb9a2801 --- /dev/null +++ "b/drpy-node-bundle/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" @@ -0,0 +1,253 @@ +{ + "Appget": { + "示例": { + "muban": "模板类型(AppGet,AppQiji)", + "host": "host和hosturl二填一", + "hosturl": "域名地址", + "key": "数据加解密秘钥", + "iv": "一般同上", + "verify": "是否启用搜索验证,字符串true或false", + "username": "APP账号用户名", + "password": "APP账号密码", + "会员时长": "会员函数(gzip压缩)", + "lazyheader": "视频播放请求头,JSON格式" + }, + "蓝鹰": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://lanyinghz.oss-cn-hangzhou.aliyuncs.com/lanyingxmy.txt", + "key": "ca94b06ca359d80e", + "iv": "ca94b06ca359d80e", + "verify": "true", + "username": "", + "password": "", + "会员时长": "", + "lazyheader": {} + }, + "仓鼠": { + "muban": "AppQiji", + "host": "https://hk440cms.cs4k.top", + "hosturl": "", + "key": "fL7sY4zN4kB3pG4p", + "iv": "fL7sY4zN4kB3pG4p", + "verify": "true" + }, + "云云": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://staraugust123456.oss-cn-hangzhou.aliyuncs.com/2.txt", + "key": "staraugust123456", + "iv": "staraugust123456", + "verify": "true" + }, + "奇奇": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://yun-1316442804.cos.ap-guangzhou.myqcloud.com/a.txt", + "key": "123456789abcdefg", + "iv": "123456789abcdefg", + "verify": "true" + }, + "鲸鱼": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://jingyu4k-1312635929.cos.ap-nanjing.myqcloud.com/1.json", + "key": "AAdgrdghjfgswerA", + "iv": "AAdgrdghjfgswerA", + "verify": "true" + }, + "咖啡": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://daen-1256234123.cos.ap-shanghai.myqcloud.com/MuQi/mqxh.txt", + "key": "37kj83zs1q16jk6t", + "iv": "37kj83zs1q16jk6t", + "verify": "true" + }, + "小猪": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://tiantangyoulu.oss-cn-beijing.aliyuncs.com/tengxunyun.txt", + "key": "seb5tq9mykp2w9ry", + "iv": "seb5tq9mykp2w9ry", + "verify": "true" + }, + "影视": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://aysappto.oss-cn-chengdu.aliyuncs.com/qj2.txt", + "key": "sada21321sdq231d", + "iv": "sada21321sdq231d", + "verify": "true" + }, + "优兔": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://uututv-1319209748.cos.ap-shanghai.myqcloud.com/uutuv4.txt", + "key": "UrWKPnmQWJA8AQzd", + "iv": "UrWKPnmQWJA8AQzd", + "verify": "true" + }, + "王子": { + "muban": "AppGet", + "host": "https://app.95112475.xyz", + "hosturl": "", + "key": "5a9w6x58dsq6z3a6", + "iv": "5a9w6x58dsq6z3a6", + "verify": "true" + }, + "紫金": { + "muban": "AppGet", + "host": "", + "hosturl": "https://snysw.xyz/mf4kzs327.txt", + "key": "1234567887654321", + "iv": "1234567887654321", + "verify": "true" + }, + "数字": { + "muban": "AppGet", + "host": "http://app1-0-0.87333.cc", + "hosturl": "", + "key": "VwsHxkCViDXEExWa", + "iv": "VwsHxkCViDXEExWa", + "verify": "true" + }, + "火锅": { + "muban": "AppGet", + "host": "https://ios.hgyx.vip", + "hosturl": "", + "key": "062dec75d039980e", + "iv": "062dec75d039980e", + "verify": "true" + }, + "五八": { + "muban": "AppGet", + "host": "https://dy.58ys.vip", + "hosturl": "", + "key": "JEWibY1AgWF0V1xx", + "iv": "JEWibY1AgWF0V1xx", + "verify": "true" + }, + "旗星": { + "muban": "AppGet", + "host": "http://ys.qist.top", + "hosturl": "", + "key": "2SWSPFxugBLPPOKo", + "iv": "2SWSPFxugBLPPOKo", + "verify": "true" + }, + "灵虎": { + "muban": "AppGet", + "host": "", + "hosturl": "https://bind.315999.xyz/89.txt", + "key": "#getapp@TMD@2025", + "iv": "#getapp@TMD@2025", + "verify": "true" + }, + "剧梦": { + "muban": "AppGet", + "host": "https://www.jumengwu.com", + "hosturl": "", + "key": "1f0a873caf2550a5", + "iv": "1f0a873caf2550a5", + "verify": "true" + }, + "火狐": { + "muban": "AppGet", + "host": "http://huohu.yihn.cc", + "hosturl": "", + "key": "huohushipingetap", + "iv": "huohushipingetap", + "verify": "true" + }, + "金牌": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://dtqj.ggtvb.cc/dtjp.txt", + "key": "eecbio48dsq131ee", + "iv": "eecbio48dsq131ee", + "verify": "true" + }, + "爱盈": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://aysappto.oss-cn-chengdu.aliyuncs.com/qj3.txt", + "key": "sda1231sasddad21", + "iv": "sda1231sasddad21", + "verify": "true" + }, + "顾我": { + "muban": "AppQiji", + "host": "http://117.50.204.35:520", + "hosturl": "", + "key": "ca94b06ca3c7d80e", + "iv": "ca94b06ca3c7d80e", + "verify": "true" + }, + "爆炸": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://daen-1256234123.cos.ap-shanghai.myqcloud.com/MuQi/mqxh.txt", + "key": "37kj83zs1q16jk6t", + "iv": "37kj83zs1q16jk6t", + "verify": "true" + }, + "丫丫动漫": { + "muban": "AppGet", + "host": "http://tv.yy-fun.cc", + "hosturl": "", + "key": "qkxnwkfjwpcnwycl", + "iv": "qkxnwkfjwpcnwycl", + "verify": "true" + }, + "番薯动漫": { + "muban": "AppGet", + "host": "https://new.app.bytegooty.com", + "hosturl": "", + "key": "N4yj7l7xKxHF4*gz", + "iv": "N4yj7l7xKxHF4*gz", + "verify": "true" + }, + "咕咕动漫": { + "muban": "AppGet", + "host": "https://www.gugu3.com", + "hosturl": "", + "key": "nKfZ8KX6JTNWRzTD", + "iv": "nKfZ8KX6JTNWRzTD", + "verify": "true" + }, + "元咲动漫": { + "muban": "AppGet", + "host": "http://cic.aicg.fun", + "hosturl": "", + "key": "2c4h36abd96se10u", + "iv": "2c4h36abd96se10u", + "verify": "true" + }, + "方舟动漫": { + "muban": "AppGet", + "host": "https://www.cyfz.vip", + "hosturl": "", + "key": "e72cdfd629e8895d", + "iv": "e72cdfd629e8895d", + "verify": "true" + } + }, + "Appmuou": { + "示例": { + "host": "", + "hosturl": "", + "version": "" + } + }, + "AppShark": { + "示例": { + "host": "", + "hosturl": "", + "key": "", + "key1": "", + "key2": "", + "version": "" + } + } +} \ No newline at end of file diff --git a/drpy-node-bundle/libs/localDsCore.bundled.js b/drpy-node-bundle/libs/localDsCore.bundled.js index 9d3acab6..2ce724c9 100644 --- a/drpy-node-bundle/libs/localDsCore.bundled.js +++ b/drpy-node-bundle/libs/localDsCore.bundled.js @@ -28,11 +28,8 @@ import { EventEmitter as EventEmitter$1 } from "node:events"; import Stream, { Transform, Writable as Writable$1, finished } from "node:stream"; import { StringDecoder } from "node:string_decoder"; import util, { TextDecoder as TextDecoder$1, promisify } from "util"; -import process$1 from "node:process"; -import os from "node:os"; -import tty from "node:tty"; -import util$1 from "node:util"; -import { createRequire as createRequire$1 } from "module"; +import http2 from "http2"; +import Module, { createRequire as createRequire$1 } from "module"; import { setTimeout as setTimeout$1 } from "timers"; import { pipeline } from "stream/promises"; import diagnosticsChannel from "diagnostics_channel"; @@ -8204,10 +8201,7 @@ var require_node_rsa = /* @__PURE__ */ __commonJSMin(((exports, module) => { function f(t) { var e = a, r = t || {}; n.ok(e), n.equal(typeof e, "object"), n.ok(r), n.equal(typeof r, "object"), Object.getOwnPropertyNames(e).forEach((function(t) { - if (!r[t]) { - var n = Object.getOwnPropertyDescriptor(e, t); - Object.defineProperty(r, t, n); - } + if (!r[t]) Object.defineProperty(r, t, Object.getOwnPropertyDescriptor(e, t)); })), t = r, this._buf = i.alloc(t.size || 1024), this._size = this._buf.length, this._offset = 0, this._options = t, this._seq = []; } Object.defineProperty(f.prototype, "buffer", { get: function() { @@ -14367,7 +14361,7 @@ let debounceTimers = /* @__PURE__ */ new Map(); function startJsonWatcher(ENGINES, jsonDir) { if (process.env.NODE_ENV !== "development") return; try { - watch(jsonDir, { recursive: true }, (eventType, filename) => { + jsonWatcher = watch(jsonDir, { recursive: true }, (eventType, filename) => { if (filename && filename.endsWith(".json")) { if (debounceTimers.has(filename)) clearTimeout(debounceTimers.get(filename)); const timer = setTimeout(() => { @@ -14375,9 +14369,11 @@ function startJsonWatcher(ENGINES, jsonDir) { ENGINES.drpyS.clearAllCache(); debounceTimers.delete(filename); }, 100); + if (timer.unref) timer.unref(); debounceTimers.set(filename, timer); } }); + if (jsonWatcher.unref) jsonWatcher.unref(); } catch (error) { console.error("start json file listening failed with error:", error); } @@ -14834,6 +14830,7 @@ var require_constants$7 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (hasBlob) BINARY_TYPES.push("blob"); module.exports = { BINARY_TYPES, + CLOSE_TIMEOUT: 3e4, EMPTY_BUFFER: Buffer.alloc(0), GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", hasBlob, @@ -16820,23 +16817,22 @@ var require_extension = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/ws/lib/websocket.js var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const EventEmitter$10 = __require("events"); + const EventEmitter$11 = __require("events"); const https$6 = __require("https"); const http$12 = __require("http"); - const net$6 = __require("net"); + const net$8 = __require("net"); const tls$2 = __require("tls"); const { randomBytes, createHash: createHash$2 } = __require("crypto"); const { Duplex: Duplex$3, Readable: Readable$9 } = __require("stream"); - const { URL: URL$2 } = __require("url"); + const { URL: URL$3 } = __require("url"); const PerMessageDeflate = require_permessage_deflate$1(); const Receiver = require_receiver$1(); const Sender = require_sender$1(); const { isBlob } = require_validation$2(); - const { BINARY_TYPES, EMPTY_BUFFER, GUID, kForOnEventAttribute, kListener, kStatusCode, kWebSocket, NOOP } = require_constants$7(); + const { BINARY_TYPES, CLOSE_TIMEOUT, EMPTY_BUFFER, GUID, kForOnEventAttribute, kListener, kStatusCode, kWebSocket, NOOP } = require_constants$7(); const { EventTarget: { addEventListener, removeEventListener } } = require_event_target(); const { format, parse } = require_extension(); const { toBuffer } = require_buffer_util(); - const closeTimeout = 30 * 1e3; const kAborted = Symbol("kAborted"); const protocolVersions = [8, 13]; const readyStates = [ @@ -16851,7 +16847,7 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * * @extends EventEmitter */ - var WebSocket = class WebSocket extends EventEmitter$10 { + var WebSocket = class WebSocket extends EventEmitter$11 { /** * Create a new `WebSocket`. * @@ -16887,6 +16883,7 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { initAsClient(this, address, protocols, options); } else { this._autoPong = options.autoPong; + this._closeTimeout = options.closeTimeout; this._isServer = true; } } @@ -17307,6 +17304,8 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * times in the same tick * @param {Boolean} [options.autoPong=true] Specifies whether or not to * automatically send a pong in response to a ping + * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait + * for the closing handshake to finish after `websocket.close()` is called * @param {Function} [options.finishRequest] A function which can be used to * customize the headers of each http request before it is sent * @param {Boolean} [options.followRedirects=false] Whether or not to follow @@ -17333,6 +17332,7 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { const opts = { allowSynchronousEvents: true, autoPong: true, + closeTimeout: CLOSE_TIMEOUT, protocolVersion: protocolVersions[1], maxPayload: 100 * 1024 * 1024, skipUTF8Validation: false, @@ -17350,11 +17350,12 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { port: void 0 }; websocket._autoPong = opts.autoPong; + websocket._closeTimeout = opts.closeTimeout; if (!protocolVersions.includes(opts.protocolVersion)) throw new RangeError(`Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})`); let parsedUrl; - if (address instanceof URL$2) parsedUrl = address; + if (address instanceof URL$3) parsedUrl = address; else try { - parsedUrl = new URL$2(address); + parsedUrl = new URL$3(address); } catch (e) { throw new SyntaxError(`Invalid URL: ${address}`); } @@ -17456,7 +17457,7 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { req.abort(); let addr; try { - addr = new URL$2(location, address); + addr = new URL$3(location, address); } catch (e) { emitErrorAndClose(websocket, /* @__PURE__ */ new SyntaxError(`Invalid URL: ${location}`)); return; @@ -17547,7 +17548,7 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { */ function netConnect(options) { options.path = options.socketPath; - return net$6.connect(options); + return net$8.connect(options); } /** * Create a `tls.TLSSocket` and initiate a connection. @@ -17558,7 +17559,7 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { */ function tlsConnect(options) { options.path = void 0; - if (!options.servername && options.servername !== "") options.servername = net$6.isIP(options.host) ? "" : options.host; + if (!options.servername && options.servername !== "") options.servername = net$8.isIP(options.host) ? "" : options.host; return tls$2.connect(options); } /** @@ -17723,7 +17724,7 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * @private */ function setCloseTimer(websocket) { - websocket._closeTimer = setTimeout(websocket._socket.destroy.bind(websocket._socket), closeTimeout); + websocket._closeTimer = setTimeout(websocket._socket.destroy.bind(websocket._socket), websocket._closeTimeout); } /** * The listener of the socket `'close'` event. @@ -17736,8 +17737,10 @@ var require_websocket$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { this.removeListener("data", socketOnData); this.removeListener("end", socketOnEnd); websocket._readyState = WebSocket.CLOSING; - let chunk; - if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && (chunk = websocket._socket.read()) !== null) websocket._receiver.write(chunk); + if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && this._readableState.length !== 0) { + const chunk = this.read(this._readableState.length); + websocket._receiver.write(chunk); + } websocket._receiver.end(); this[kWebSocket] = void 0; clearTimeout(websocket._closeTimer); @@ -17940,7 +17943,7 @@ var require_subprotocol = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/ws/lib/websocket-server.js var require_websocket_server = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const EventEmitter$9 = __require("events"); + const EventEmitter$10 = __require("events"); const http$11 = __require("http"); const { Duplex: Duplex$1 } = __require("stream"); const { createHash: createHash$1 } = __require("crypto"); @@ -17948,7 +17951,7 @@ var require_websocket_server = /* @__PURE__ */ __commonJSMin(((exports, module) const PerMessageDeflate = require_permessage_deflate$1(); const subprotocol = require_subprotocol(); const WebSocket = require_websocket$1(); - const { GUID, kWebSocket } = require_constants$7(); + const { CLOSE_TIMEOUT, GUID, kWebSocket } = require_constants$7(); const keyRegex = /^[+/0-9A-Za-z]{22}==$/; const RUNNING = 0; const CLOSING = 1; @@ -17958,7 +17961,7 @@ var require_websocket_server = /* @__PURE__ */ __commonJSMin(((exports, module) * * @extends EventEmitter */ - var WebSocketServer = class extends EventEmitter$9 { + var WebSocketServer = class extends EventEmitter$10 { /** * Create a `WebSocketServer` instance. * @@ -17972,6 +17975,9 @@ var require_websocket_server = /* @__PURE__ */ __commonJSMin(((exports, module) * pending connections * @param {Boolean} [options.clientTracking=true] Specifies whether or not to * track clients + * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to + * wait for the closing handshake to finish after `websocket.close()` is + * called * @param {Function} [options.handleProtocols] A hook to handle protocols * @param {String} [options.host] The hostname where to bind the server * @param {Number} [options.maxPayload=104857600] The maximum allowed message @@ -18000,6 +18006,7 @@ var require_websocket_server = /* @__PURE__ */ __commonJSMin(((exports, module) perMessageDeflate: false, handleProtocols: null, clientTracking: true, + closeTimeout: CLOSE_TIMEOUT, verifyClient: null, noServer: false, backlog: null, @@ -20483,7 +20490,7 @@ var require_util$8 = /* @__PURE__ */ __commonJSMin(((exports, module) => { return this; }; /** - * Shortens this buffer by triming bytes off of the end of this buffer. + * Shortens this buffer by trimming bytes off of the end of this buffer. * * @param count the number of bytes to trim off. * @@ -21038,7 +21045,7 @@ var require_util$8 = /* @__PURE__ */ __commonJSMin(((exports, module) => { return this; }; /** - * Shortens this buffer by triming bytes off of the end of this buffer. + * Shortens this buffer by trimming bytes off of the end of this buffer. * * @param count the number of bytes to trim off. * @@ -23145,7 +23152,7 @@ var require_aes$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * The word [a0, a1, a2, a3] is a polynomial a3x^3 + a2x^2 + a1x + a0. * * Addition is performed by XOR'ing like powers of x. Multiplication - * is performed in two steps, the first is an algebriac expansion as + * is performed in two steps, the first is an algebraic expansion as * you would do normally (where addition is XOR). But the result is * a polynomial larger than 3 degrees and thus it cannot fit in a word. So * next the result is modularly reduced by an AES-specific polynomial of @@ -23779,6 +23786,10 @@ var require_asn1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { BMPSTRING: 30 }; /** + * Sets the default maximum recursion depth when parsing ASN.1 structures. + */ + asn1.maxDepth = 256; + /** * Creates a new asn1 object. * * @param tagClass the tag class for the object. @@ -23937,6 +23948,8 @@ var require_asn1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * erroneously decode values that happen to be valid ASN.1. This * flag will be deprecated or removed as soon as schema support is * available. (default: true) + * [maxDepth] override asn1.maxDepth recursion limit + * (default: asn1.maxDepth) * * @throws Will throw an error for various malformed input conditions. * @@ -23956,6 +23969,7 @@ var require_asn1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (!("strict" in options)) options.strict = true; if (!("parseAllBytes" in options)) options.parseAllBytes = true; if (!("decodeBitStrings" in options)) options.decodeBitStrings = true; + if (!("maxDepth" in options)) options.maxDepth = asn1.maxDepth; if (typeof bytes === "string") bytes = forge.util.createBuffer(bytes); var byteCount = bytes.length(); var value = _fromDer(bytes, bytes.length(), 0, options); @@ -23978,6 +23992,7 @@ var require_asn1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * @return the parsed asn1 object. */ function _fromDer(bytes, remaining, depth, options) { + if (depth >= options.maxDepth) throw new Error("ASN.1 parsing error: Max depth exceeded."); var start; _checkBufferLength(bytes, remaining, 2); var b1 = bytes.getByte(); @@ -24123,6 +24138,7 @@ var require_asn1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { last = true; valueBytes = []; value = parseInt(values[i], 10); + if (value > 4294967295) throw new Error("OID value too large; max is 32-bits."); do { b = value & 127; value = value >>> 7; @@ -24150,8 +24166,9 @@ var require_asn1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { oid = Math.floor(b / 40) + "." + b % 40; var value = 0; while (bytes.length() > 0) { + if (value > 70368744177663) throw new Error("OID value too large; max is 53-bits."); b = bytes.getByte(); - value = value << 7; + value = value * 128; if (b & 128) value += b & 127; else { oid += "." + (value + b); @@ -24356,13 +24373,32 @@ var require_asn1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (v.value && forge.util.isArray(v.value)) { var j = 0; for (var i = 0; rval && i < v.value.length; ++i) { - rval = v.value[i].optional || false; - if (obj.value[j]) { - rval = asn1.validate(obj.value[j], v.value[i], capture, errors); - if (rval) ++j; - else if (v.value[i].optional) rval = true; + var schemaItem = v.value[i]; + rval = !!schemaItem.optional; + var objChild = obj.value[j]; + if (!objChild) { + if (!schemaItem.optional) { + rval = false; + if (errors) errors.push("[" + v.name + "] Missing required element. Expected tag class \"" + schemaItem.tagClass + "\", type \"" + schemaItem.type + "\""); + } + continue; + } + if (typeof schemaItem.tagClass !== "undefined" && typeof schemaItem.type !== "undefined" && (objChild.tagClass !== schemaItem.tagClass || objChild.type !== schemaItem.type)) if (schemaItem.optional) { + rval = true; + continue; + } else { + rval = false; + if (errors) errors.push("[" + v.name + "] Tag mismatch. Expected (" + schemaItem.tagClass + "," + schemaItem.type + "), got (" + objChild.tagClass + "," + objChild.type + ")"); + break; + } + if (asn1.validate(objChild, schemaItem, capture, errors)) { + ++j; + rval = true; + } else if (schemaItem.optional) rval = true; + else { + rval = false; + break; } - if (!rval && errors) errors.push("[" + v.name + "] Tag class \"" + v.tagClass + "\", type \"" + v.type + "\" expected value length \"" + v.value.length + "\", got \"" + obj.value.length + "\""); } } if (rval && capture) { @@ -29799,7 +29835,7 @@ var require_rsa = /* @__PURE__ */ __commonJSMin(((exports, module) => { * * @param md the message digest object with the hash to sign. * - * @return the encoded message (ready for RSA encrytion) + * @return the encoded message (ready for RSA encryption) */ var emsaPkcs1v15encode = function(md) { var oid; @@ -29854,7 +29890,7 @@ var require_rsa = /* @__PURE__ */ __commonJSMin(((exports, module) => { * * The parameter bt controls whether to put padding bytes before the * message passed in. Set bt to either true or false to disable padding - * completely (in order to handle e.g. EMSA-PSS encoding seperately before), + * completely (in order to handle e.g. EMSA-PSS encoding separately before), * signaling whether the encryption operation is a public key operation * (i.e. encrypting data) or not, i.e. private key operation (data signing). * @@ -30339,7 +30375,7 @@ var require_rsa = /* @__PURE__ */ __commonJSMin(((exports, module) => { throw error; } if (oid === forge.oids.md2 || oid === forge.oids.md5) { - if (!("parameters" in capture)) throw new Error("ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 DigestInfo value. Missing algorithm identifer NULL parameters."); + if (!("parameters" in capture)) throw new Error("ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 DigestInfo value. Missing algorithm identifier NULL parameters."); } return digest === capture.digest; } }; @@ -33903,7 +33939,7 @@ var require_x509 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * Convert signature parameters object to ASN.1 * * @param {String} oid Signature algorithm OID - * @param params The signature parametrs object + * @param params The signature parameters object * @return ASN.1 object representing signature parameters */ function _signatureParametersToAsn1(oid, params) { @@ -34499,6 +34535,7 @@ var require_pkcs12 = /* @__PURE__ */ __commonJSMin(((exports, module) => { capture: "macAlgorithm" }, { name: "PFX.macData.mac.digestAlgorithm.parameters", + optional: true, tagClass: asn1.Class.UNIVERSAL, captureAsn1: "macAlgorithmParameters" }] @@ -34713,7 +34750,7 @@ var require_pkcs12 = /* @__PURE__ */ __commonJSMin(((exports, module) => { mac.start(md, macKey); mac.update(data.value); if (mac.getMac().getBytes() !== capture.macDigest) throw new Error("PKCS#12 MAC could not be verified. Invalid password?"); - } + } else if (Array.isArray(obj.value) && obj.value.length > 2) throw new Error("Invalid PKCS#12. macData field present but MAC was not validated."); _decodeAuthenticatedSafe(pfx, data.value, strict, password); return pfx; }; @@ -41798,7 +41835,7 @@ var PipeProxyErrors = class extends Pipe { } constructor(src, dest, opts) { super(src, dest, opts); - this.proxyErrors = (er) => dest.emit("error", er); + this.proxyErrors = (er) => this.dest.emit("error", er); src.on("error", this.proxyErrors); } }; @@ -42437,7 +42474,8 @@ while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) && this[BUFFER].length); return: stop, [Symbol.asyncIterator]() { return this; - } + }, + [Symbol.asyncDispose]: async () => {} }; } /** @@ -42477,7 +42515,8 @@ while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) && this[BUFFER].length); return: stop, [Symbol.iterator]() { return this; - } + }, + [Symbol.dispose]: () => {} }; } /** @@ -43944,7 +43983,7 @@ var require_lodash = /* @__PURE__ */ __commonJSMin(((exports, module) => { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; /** Used as the semantic version number. */ - var VERSION = "4.17.21"; + var VERSION = "4.17.23"; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** Error message constants. */ @@ -47293,8 +47332,20 @@ var require_lodash = /* @__PURE__ */ __commonJSMin(((exports, module) => { */ function baseUnset(object, path) { path = castPath(path, object); - object = parent(object, path); - return object == null || delete object[toKey(last(path))]; + var index = -1, length = path.length; + if (!length) return true; + var isRootPrimitive = object == null || typeof object !== "object" && typeof object !== "function"; + while (++index < length) { + var key = path[index]; + if (typeof key !== "string") continue; + if (key === "__proto__" && !hasOwnProperty.call(object, "__proto__")) return false; + if (key === "constructor" && index + 1 < length && typeof path[index + 1] === "string" && path[index + 1] === "prototype") { + if (isRootPrimitive && index === 0) continue; + return false; + } + } + var obj = parent(object, path); + return obj == null || delete obj[toKey(last(path))]; } /** * The base implementation of `_.update`. @@ -59491,6 +59542,13 @@ const COOKIE = { }; //#endregion //#region ../node_modules/axios/lib/helpers/bind.js +/** +* Create a bound version of a function with a specified `this` context +* +* @param {Function} fn - The function to bind +* @param {*} thisArg - The value to be passed as the `this` parameter +* @returns {Function} A new function that will call the original function with the specified `this` context +*/ function bind$1(fn, thisArg) { return function wrap() { return fn.apply(thisArg, arguments); @@ -59511,7 +59569,7 @@ const kindOfTest = (type) => { }; const typeOfTest = (type) => (thing) => typeof thing === type; /** -* Determine if a value is an Array +* Determine if a value is a non-null object * * @param {Object} val The value to test * @@ -59639,6 +59697,29 @@ const isDate$1 = kindOfTest("Date"); */ const isFile = kindOfTest("File"); /** +* Determine if a value is a React Native Blob +* React Native "blob": an object with a `uri` attribute. Optionally, it can +* also have a `name` and `type` attribute to specify filename and content type +* +* @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71 +* +* @param {*} value The value to test +* +* @returns {boolean} True if value is a React Native Blob, otherwise false +*/ +const isReactNativeBlob = (value) => { + return !!(value && typeof value.uri !== "undefined"); +}; +/** +* Determine if environment is React Native +* ReactNative `FormData` has a non-standard `getParts()` method +* +* @param {*} formData The formData to test +* +* @returns {boolean} True if environment is React Native, otherwise false +*/ +const isReactNative = (formData) => formData && typeof formData.getParts !== "undefined"; +/** * Determine if a value is a Blob * * @param {*} val The value to test @@ -59669,9 +59750,18 @@ const isStream = (val) => isObject$1(val) && isFunction$3(val.pipe); * * @returns {boolean} True if value is an FormData, otherwise false */ +function getGlobal() { + if (typeof globalThis !== "undefined") return globalThis; + if (typeof self !== "undefined") return self; + if (typeof window !== "undefined") return window; + if (typeof global !== "undefined") return global; + return {}; +} +const G$1 = getGlobal(); +const FormDataCtor = typeof G$1.FormData !== "undefined" ? G$1.FormData : void 0; const isFormData = (thing) => { let kind; - return thing && (typeof FormData === "function" && thing instanceof FormData || isFunction$3(thing.append) && ((kind = kindOf(thing)) === "formdata" || kind === "object" && isFunction$3(thing.toString) && thing.toString() === "[object FormData]")); + return thing && (FormDataCtor && thing instanceof FormDataCtor || isFunction$3(thing.append) && ((kind = kindOf(thing)) === "formdata" || kind === "object" && isFunction$3(thing.toString) && thing.toString() === "[object FormData]")); }; /** * Determine if a value is a URLSearchParams object @@ -59694,7 +59784,9 @@ const [isReadableStream, isRequest, isResponse, isHeaders] = [ * * @returns {String} The String freed of excess whitespace */ -const trim = (str) => str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""); +const trim = (str) => { + return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""); +}; /** * Iterate over an Array or an Object invoking a function for each item. * @@ -59704,10 +59796,11 @@ const trim = (str) => str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\ * If 'obj' is an Object callback will be called passing * the value, key, and complete object for each property. * -* @param {Object|Array} obj The object to iterate +* @param {Object|Array} obj The object to iterate * @param {Function} fn The callback to invoke for each item * -* @param {Boolean} [allOwnKeys = false] +* @param {Object} [options] +* @param {Boolean} [options.allOwnKeys = false] * @returns {any} */ function forEach(obj, fn, { allOwnKeys = false } = {}) { @@ -59727,6 +59820,14 @@ function forEach(obj, fn, { allOwnKeys = false } = {}) { } } } +/** +* Finds a key in an object, case-insensitive, returning the actual key name. +* Returns null if the object is a Buffer or if no match is found. +* +* @param {Object} obj - The object to search. +* @param {string} key - The key to find (case-insensitive). +* @returns {?string} The actual key name if found, otherwise null. +*/ function findKey$1(obj, key) { if (isBuffer(obj)) return null; key = key.toLowerCase(); @@ -59754,7 +59855,7 @@ const isContextDefined = (context) => !isUndefined$1(context) && context !== _gl * Example: * * ```js -* var result = merge({foo: 123}, {foo: 456}); +* const result = merge({foo: 123}, {foo: 456}); * console.log(result.foo); // outputs 456 * ``` * @@ -59766,6 +59867,7 @@ function merge$1() { const { caseless, skipUndefined } = isContextDefined(this) && this || {}; const result = {}; const assignValue = (val, key) => { + if (key === "__proto__" || key === "constructor" || key === "prototype") return; const targetKey = caseless && findKey$1(result, key) || key; if (isPlainObject(result[targetKey]) && isPlainObject(val)) result[targetKey] = merge$1(result[targetKey], val); else if (isPlainObject(val)) result[targetKey] = merge$1({}, val); @@ -59782,13 +59884,24 @@ function merge$1() { * @param {Object} b The object to copy properties from * @param {Object} thisArg The object to bind function to * -* @param {Boolean} [allOwnKeys] +* @param {Object} [options] +* @param {Boolean} [options.allOwnKeys] * @returns {Object} The resulting value of object a */ const extend$1 = (a, b, thisArg, { allOwnKeys } = {}) => { forEach(b, (val, key) => { - if (thisArg && isFunction$3(val)) a[key] = bind$1(val, thisArg); - else a[key] = val; + if (thisArg && isFunction$3(val)) Object.defineProperty(a, key, { + value: bind$1(val, thisArg), + writable: true, + enumerable: true, + configurable: true + }); + else Object.defineProperty(a, key, { + value: val, + writable: true, + enumerable: true, + configurable: true + }); }, { allOwnKeys }); return a; }; @@ -59814,7 +59927,12 @@ const stripBOM = (content) => { */ const inherits$3 = (constructor, superConstructor, props, descriptors) => { constructor.prototype = Object.create(superConstructor.prototype, descriptors); - constructor.prototype.constructor = constructor; + Object.defineProperty(constructor.prototype, "constructor", { + value: constructor, + writable: true, + enumerable: false, + configurable: true + }); Object.defineProperty(constructor, "super", { value: superConstructor.prototype }); props && Object.assign(constructor.prototype, props); }; @@ -59970,6 +60088,14 @@ const freezeMethods = (obj) => { }; }); }; +/** +* Converts an array or a delimited string into an object set with values as keys and true as values. +* Useful for fast membership checks. +* +* @param {Array|string} arrayOrString - The array or string to convert. +* @param {string} delimiter - The delimiter to use if input is a string. +* @returns {Object} An object with keys from the array or string, values set to true. +*/ const toObjectSet = (arrayOrString, delimiter) => { const obj = {}; const define = (arr) => { @@ -59994,6 +60120,12 @@ const toFiniteNumber = (value, defaultValue) => { function isSpecCompliantForm(thing) { return !!(thing && isFunction$3(thing.append) && thing[toStringTag] === "FormData" && thing[iterator]); } +/** +* Recursively converts an object to a JSON-compatible object, handling circular references and Buffers. +* +* @param {Object} obj - The object to convert. +* @returns {Object} The JSON-compatible object. +*/ const toJSONObject = (obj) => { const stack = new Array(10); const visit = (source, i) => { @@ -60015,8 +60147,28 @@ const toJSONObject = (obj) => { }; return visit(obj, 0); }; +/** +* Determines if a value is an async function. +* +* @param {*} thing - The value to test. +* @returns {boolean} True if value is an async function, otherwise false. +*/ const isAsyncFn = kindOfTest("AsyncFunction"); +/** +* Determines if a value is thenable (has then and catch methods). +* +* @param {*} thing - The value to test. +* @returns {boolean} True if value is thenable, otherwise false. +*/ const isThenable = (thing) => thing && (isObject$1(thing) || isFunction$3(thing)) && isFunction$3(thing.then) && isFunction$3(thing.catch); +/** +* Provides a cross-platform setImmediate implementation. +* Uses native setImmediate if available, otherwise falls back to postMessage or setTimeout. +* +* @param {boolean} setImmediateSupported - Whether setImmediate is supported. +* @param {boolean} postMessageSupported - Whether postMessage is supported. +* @returns {Function} A function to schedule a callback asynchronously. +*/ const _setImmediate = ((setImmediateSupported, postMessageSupported) => { if (setImmediateSupported) return setImmediate; return postMessageSupported ? ((token, callbacks) => { @@ -60029,6 +60181,12 @@ const _setImmediate = ((setImmediateSupported, postMessageSupported) => { }; })(`axios@${Math.random()}`, []) : (cb) => setTimeout(cb); })(typeof setImmediate === "function", isFunction$3(_global.postMessage)); +/** +* Schedules a microtask or asynchronous callback as soon as possible. +* Uses queueMicrotask if available, otherwise falls back to process.nextTick or _setImmediate. +* +* @type {Function} +*/ const asap = typeof queueMicrotask !== "undefined" ? queueMicrotask.bind(_global) : typeof process !== "undefined" && process.nextTick || _setImmediate; const isIterable = (thing) => thing != null && isFunction$3(thing[iterator]); var utils_default = { @@ -60050,6 +60208,8 @@ var utils_default = { isUndefined: isUndefined$1, isDate: isDate$1, isFile, + isReactNativeBlob, + isReactNative, isBlob, isRegExp: isRegExp$1, isFunction: isFunction$3, @@ -60092,89 +60252,77 @@ var utils_default = { }; //#endregion //#region ../node_modules/axios/lib/core/AxiosError.js -/** -* Create an Error with the specified message, config, error code, request and response. -* -* @param {string} message The error message. -* @param {string} [code] The error code (for example, 'ECONNABORTED'). -* @param {Object} [config] The config. -* @param {Object} [request] The request. -* @param {Object} [response] The response. -* -* @returns {Error} The created error. -*/ -function AxiosError$1(message, code, config, request, response) { - Error.call(this); - if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); - else this.stack = (/* @__PURE__ */ new Error()).stack; - this.message = message; - this.name = "AxiosError"; - code && (this.code = code); - config && (this.config = config); - request && (this.request = request); - if (response) { - this.response = response; - this.status = response.status ? response.status : null; +var AxiosError$1 = class AxiosError$1 extends Error { + static from(error, code, config, request, response, customProps) { + const axiosError = new AxiosError$1(error.message, code || error.code, config, request, response); + axiosError.cause = error; + axiosError.name = error.name; + if (error.status != null && axiosError.status == null) axiosError.status = error.status; + customProps && Object.assign(axiosError, customProps); + return axiosError; + } + /** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [config] The config. + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * + * @returns {Error} The created error. + */ + constructor(message, code, config, request, response) { + super(message); + Object.defineProperty(this, "message", { + value: message, + enumerable: true, + writable: true, + configurable: true + }); + this.name = "AxiosError"; + this.isAxiosError = true; + code && (this.code = code); + config && (this.config = config); + request && (this.request = request); + if (response) { + this.response = response; + this.status = response.status; + } + } + toJSON() { + return { + message: this.message, + name: this.name, + description: this.description, + number: this.number, + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + config: utils_default.toJSONObject(this.config), + code: this.code, + status: this.status + }; } -} -utils_default.inherits(AxiosError$1, Error, { toJSON: function toJSON() { - return { - message: this.message, - name: this.name, - description: this.description, - number: this.number, - fileName: this.fileName, - lineNumber: this.lineNumber, - columnNumber: this.columnNumber, - stack: this.stack, - config: utils_default.toJSONObject(this.config), - code: this.code, - status: this.status - }; -} }); -const prototype$1 = AxiosError$1.prototype; -const descriptors = {}; -[ - "ERR_BAD_OPTION_VALUE", - "ERR_BAD_OPTION", - "ECONNABORTED", - "ETIMEDOUT", - "ERR_NETWORK", - "ERR_FR_TOO_MANY_REDIRECTS", - "ERR_DEPRECATED", - "ERR_BAD_RESPONSE", - "ERR_BAD_REQUEST", - "ERR_CANCELED", - "ERR_NOT_SUPPORT", - "ERR_INVALID_URL" -].forEach((code) => { - descriptors[code] = { value: code }; -}); -Object.defineProperties(AxiosError$1, descriptors); -Object.defineProperty(prototype$1, "isAxiosError", { value: true }); -AxiosError$1.from = (error, code, config, request, response, customProps) => { - const axiosError = Object.create(prototype$1); - utils_default.toFlatObject(error, axiosError, function filter(obj) { - return obj !== Error.prototype; - }, (prop) => { - return prop !== "isAxiosError"; - }); - const msg = error && error.message ? error.message : "Error"; - const errCode = code == null && error ? error.code : code; - AxiosError$1.call(axiosError, msg, errCode, config, request, response); - if (error && axiosError.cause == null) Object.defineProperty(axiosError, "cause", { - value: error, - configurable: true - }); - axiosError.name = error && error.name || "Error"; - customProps && Object.assign(axiosError, customProps); - return axiosError; }; +AxiosError$1.ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE"; +AxiosError$1.ERR_BAD_OPTION = "ERR_BAD_OPTION"; +AxiosError$1.ECONNABORTED = "ECONNABORTED"; +AxiosError$1.ETIMEDOUT = "ETIMEDOUT"; +AxiosError$1.ERR_NETWORK = "ERR_NETWORK"; +AxiosError$1.ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS"; +AxiosError$1.ERR_DEPRECATED = "ERR_DEPRECATED"; +AxiosError$1.ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE"; +AxiosError$1.ERR_BAD_REQUEST = "ERR_BAD_REQUEST"; +AxiosError$1.ERR_CANCELED = "ERR_CANCELED"; +AxiosError$1.ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT"; +AxiosError$1.ERR_INVALID_URL = "ERR_INVALID_URL"; //#endregion //#region ../node_modules/delayed-stream/lib/delayed_stream.js var require_delayed_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => { var Stream$4 = __require("stream").Stream; - var util$12 = __require("util"); + var util$11 = __require("util"); module.exports = DelayedStream; function DelayedStream() { this.source = null; @@ -60185,7 +60333,7 @@ var require_delayed_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => this._released = false; this._bufferedEvents = []; } - util$12.inherits(DelayedStream, Stream$4); + util$11.inherits(DelayedStream, Stream$4); DelayedStream.create = function(source, options) { var delayedStream = new this(); options = options || {}; @@ -60251,7 +60399,7 @@ var require_delayed_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => //#endregion //#region ../node_modules/combined-stream/lib/combined_stream.js var require_combined_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => { - var util$11 = __require("util"); + var util$10 = __require("util"); var Stream$3 = __require("stream").Stream; var DelayedStream = require_delayed_stream(); module.exports = CombinedStream; @@ -60267,7 +60415,7 @@ var require_combined_stream = /* @__PURE__ */ __commonJSMin(((exports, module) = this._insideLoop = false; this._pendingNext = false; } - util$11.inherits(CombinedStream, Stream$3); + util$10.inherits(CombinedStream, Stream$3); CombinedStream.create = function(options) { var combinedStream = new this(); options = options || {}; @@ -68534,8 +68682,8 @@ var require_populate = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/form-data/lib/form_data.js var require_form_data$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { var CombinedStream = require_combined_stream(); - var util$10 = __require("util"); - var path$6 = __require("path"); + var util$9 = __require("util"); + var path$5 = __require("path"); var http$10 = __require("http"); var https$5 = __require("https"); var parseUrl$1 = __require("url").parse; @@ -68564,7 +68712,7 @@ var require_form_data$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { options = options || {}; for (var option in options) this[option] = options[option]; } - util$10.inherits(FormData, CombinedStream); + util$9.inherits(FormData, CombinedStream); FormData.LINE_BREAK = "\r\n"; FormData.DEFAULT_CONTENT_TYPE = "application/octet-stream"; FormData.prototype.append = function(field, value, options) { @@ -68632,9 +68780,9 @@ var require_form_data$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { }; FormData.prototype._getContentDisposition = function(value, options) { var filename; - if (typeof options.filepath === "string") filename = path$6.normalize(options.filepath).replace(/\\/g, "/"); - else if (options.filename || value && (value.name || value.path)) filename = path$6.basename(options.filename || value && (value.name || value.path)); - else if (value && value.readable && hasOwn(value, "httpVersion")) filename = path$6.basename(value.client._httpMessage.path || ""); + if (typeof options.filepath === "string") filename = path$5.normalize(options.filepath).replace(/\\/g, "/"); + else if (options.filename || value && (value.name || value.path)) filename = path$5.basename(options.filename || value && (value.name || value.path)); + else if (value && value.readable && hasOwn(value, "httpVersion")) filename = path$5.basename(value.client._httpMessage.path || ""); if (filename) return "filename=\"" + filename + "\""; }; FormData.prototype._getContentType = function(value, options) { @@ -68762,7 +68910,7 @@ var require_form_data$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { FormData.prototype.toString = function() { return "[object FormData]"; }; - setToStringTag(FormData, "FormData"); + setToStringTag(FormData.prototype, "FormData"); module.exports = FormData; })); //#endregion @@ -68878,6 +69026,10 @@ function toFormData$1(obj, formData, options) { */ function defaultVisitor(value, key, path) { let arr = value; + if (utils_default.isReactNative(formData) && utils_default.isReactNativeBlob(value)) { + formData.append(renderKey(path, key, dots), convertValue(value)); + return false; + } if (value && !path && typeof value === "object") { if (utils_default.endsWith(key, "{}")) { key = metaTokens ? key : key.slice(0, -2); @@ -68986,11 +69138,11 @@ function encode$1(val) { function buildURL(url, params, options) { if (!params) return url; const _encode = options && options.encode || encode$1; - if (utils_default.isFunction(options)) options = { serialize: options }; - const serializeFn = options && options.serialize; + const _options = utils_default.isFunction(options) ? { serialize: options } : options; + const serializeFn = _options && _options.serialize; let serializedParams; - if (serializeFn) serializedParams = serializeFn(params, options); - else serializedParams = utils_default.isURLSearchParams(params) ? params.toString() : new AxiosURLSearchParams(params, options).toString(_encode); + if (serializeFn) serializedParams = serializeFn(params, _options); + else serializedParams = utils_default.isURLSearchParams(params) ? params.toString() : new AxiosURLSearchParams(params, _options).toString(_encode); if (serializedParams) { const hashmarkIndex = url.indexOf("#"); if (hashmarkIndex !== -1) url = url.slice(0, hashmarkIndex); @@ -69009,6 +69161,7 @@ var InterceptorManager = class { * * @param {Function} fulfilled The function to handle `then` for a `Promise` * @param {Function} rejected The function to handle `reject` for a `Promise` + * @param {Object} options The options for the interceptor, synchronous and runWhen * * @return {Number} An ID used to remove interceptor later */ @@ -69026,7 +69179,7 @@ var InterceptorManager = class { * * @param {Number} id The ID that was returned by `use` * - * @returns {Boolean} `true` if the interceptor was removed, `false` otherwise + * @returns {void} */ eject(id) { if (this.handlers[id]) this.handlers[id] = null; @@ -69060,7 +69213,8 @@ var InterceptorManager = class { var transitional_default = { silentJSONParsing: true, forcedJSONParsing: true, - clarifyTimeoutError: false + clarifyTimeoutError: false, + legacyInterceptorReqResOrdering: true }; //#endregion //#region ../node_modules/axios/lib/platform/node/classes/URLSearchParams.js @@ -69082,7 +69236,7 @@ const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => { for (let i = 0; i < size; i++) str += alphabet[randomValues[i] % length]; return str; }; -var node_default$1 = { +var node_default = { isNode: true, classes: { URLSearchParams: URLSearchParams_default, @@ -69146,7 +69300,7 @@ const origin = hasBrowserEnv && window.location.href || "http://localhost"; //#region ../node_modules/axios/lib/platform/index.js var platform_default = { ...utils_exports, - ...node_default$1 + ...node_default }; //#endregion //#region ../node_modules/axios/lib/helpers/toURLEncodedForm.js @@ -69312,7 +69466,7 @@ const defaults$1 = { return status >= 200 && status < 300; }, headers: { common: { - "Accept": "application/json, text/plain, */*", + Accept: "application/json, text/plain, */*", "Content-Type": void 0 } } }; @@ -69606,20 +69760,22 @@ function isCancel$1(value) { } //#endregion //#region ../node_modules/axios/lib/cancel/CanceledError.js -/** -* A `CanceledError` is an object that is thrown when an operation is canceled. -* -* @param {string=} message The message. -* @param {Object=} config The config. -* @param {Object=} request The request. -* -* @returns {CanceledError} The created error. -*/ -function CanceledError$1(message, config, request) { - AxiosError$1.call(this, message == null ? "canceled" : message, AxiosError$1.ERR_CANCELED, config, request); - this.name = "CanceledError"; -} -utils_default.inherits(CanceledError$1, AxiosError$1, { __CANCEL__: true }); +var CanceledError$1 = class extends AxiosError$1 { + /** + * A `CanceledError` is an object that is thrown when an operation is canceled. + * + * @param {string=} message The message. + * @param {Object=} config The config. + * @param {Object=} request The request. + * + * @returns {CanceledError} The created error. + */ + constructor(message, config, request) { + super(message == null ? "canceled" : message, AxiosError$1.ERR_CANCELED, config, request); + this.name = "CanceledError"; + this.__CANCEL__ = true; + } +}; //#endregion //#region ../node_modules/axios/lib/core/settle.js /** @@ -69646,6 +69802,7 @@ function settle(resolve, reject, response) { * @returns {boolean} True if the specified URL is absolute, otherwise false */ function isAbsoluteURL(url) { + if (typeof url !== "string") return false; return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); } //#endregion @@ -70264,114 +70421,13 @@ var require_browser = /* @__PURE__ */ __commonJSMin(((exports, module) => { }; })); //#endregion -//#region ../node_modules/supports-color/index.js -var supports_color_exports = /* @__PURE__ */ __exportAll({ - createSupportsColor: () => createSupportsColor, - default: () => supportsColor -}); -function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process$1.argv) { - const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--"; - const position = argv.indexOf(prefix + flag); - const terminatorPosition = argv.indexOf("--"); - return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); -} -function envForceColor() { - if (!("FORCE_COLOR" in env)) return; - if (env.FORCE_COLOR === "true") return 1; - if (env.FORCE_COLOR === "false") return 0; - if (env.FORCE_COLOR.length === 0) return 1; - const level = Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3); - if (![ - 0, - 1, - 2, - 3 - ].includes(level)) return; - return level; -} -function translateLevel(level) { - if (level === 0) return false; - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; -} -function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) { - const noFlagForceColor = envForceColor(); - if (noFlagForceColor !== void 0) flagForceColor = noFlagForceColor; - const forceColor = sniffFlags ? flagForceColor : noFlagForceColor; - if (forceColor === 0) return 0; - if (sniffFlags) { - if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) return 3; - if (hasFlag("color=256")) return 2; - } - if ("TF_BUILD" in env && "AGENT_NAME" in env) return 1; - if (haveStream && !streamIsTTY && forceColor === void 0) return 0; - const min = forceColor || 0; - if (env.TERM === "dumb") return min; - if (process$1.platform === "win32") { - const osRelease = os.release().split("."); - if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2; - return 1; - } - if ("CI" in env) { - if ([ - "GITHUB_ACTIONS", - "GITEA_ACTIONS", - "CIRCLECI" - ].some((key) => key in env)) return 3; - if ([ - "TRAVIS", - "APPVEYOR", - "GITLAB_CI", - "BUILDKITE", - "DRONE" - ].some((sign) => sign in env) || env.CI_NAME === "codeship") return 1; - return min; - } - if ("TEAMCITY_VERSION" in env) return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; - if (env.COLORTERM === "truecolor") return 3; - if (env.TERM === "xterm-kitty") return 3; - if (env.TERM === "xterm-ghostty") return 3; - if (env.TERM === "wezterm") return 3; - if ("TERM_PROGRAM" in env) { - const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10); - switch (env.TERM_PROGRAM) { - case "iTerm.app": return version >= 3 ? 3 : 2; - case "Apple_Terminal": return 2; - } - } - if (/-256(color)?$/i.test(env.TERM)) return 2; - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) return 1; - if ("COLORTERM" in env) return 1; - return min; -} -function createSupportsColor(stream, options = {}) { - return translateLevel(_supportsColor(stream, { - streamIsTTY: stream && stream.isTTY, - ...options - })); -} -var env, flagForceColor, supportsColor; -var init_supports_color = __esmMin((() => { - ({env} = process$1); - if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) flagForceColor = 0; - else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) flagForceColor = 1; - supportsColor = { - stdout: createSupportsColor({ isTTY: tty.isatty(1) }), - stderr: createSupportsColor({ isTTY: tty.isatty(2) }) - }; -})); -//#endregion //#region ../node_modules/debug/src/node.js var require_node$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { /** * Module dependencies. */ - const tty$1 = __require("tty"); - const util$9 = __require("util"); + const tty = __require("tty"); + const util$8 = __require("util"); /** * This is the Node.js implementation of `debug()`. */ @@ -70381,7 +70437,7 @@ var require_node$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { exports.save = save; exports.load = load; exports.useColors = useColors; - exports.destroy = util$9.deprecate(() => {}, "Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); + exports.destroy = util$8.deprecate(() => {}, "Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); /** * Colors. */ @@ -70394,7 +70450,7 @@ var require_node$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { 1 ]; try { - const supportsColor = (init_supports_color(), __toCommonJS(supports_color_exports)); + const supportsColor = __require("supports-color"); if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) exports.colors = [ 20, 21, @@ -70497,7 +70553,7 @@ var require_node$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * Is stdout a TTY? Colored output is enabled when `true`. */ function useColors() { - return "colors" in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty$1.isatty(process.stderr.fd); + return "colors" in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd); } /** * Adds ANSI color escape codes if enabled. @@ -70522,7 +70578,7 @@ var require_node$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr. */ function log(...args) { - return process.stderr.write(util$9.formatWithOptions(exports.inspectOpts, ...args) + "\n"); + return process.stderr.write(util$8.formatWithOptions(exports.inspectOpts, ...args) + "\n"); } /** * Save `namespaces`. @@ -70561,14 +70617,14 @@ var require_node$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { */ formatters.o = function(v) { this.inspectOpts.colors = this.useColors; - return util$9.inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" "); + return util$8.inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" "); }; /** * Map %O to `util.inspect()`, allowing multiple lines if needed. */ formatters.O = function(v) { this.inspectOpts.colors = this.useColors; - return util$9.inspect(v, this.inspectOpts); + return util$8.inspect(v, this.inspectOpts); }; })); //#endregion @@ -71031,7 +71087,7 @@ var require_follow_redirects = /* @__PURE__ */ __commonJSMin(((exports, module) //#region ../node_modules/axios/lib/env/data.js var import_follow_redirects = /* @__PURE__ */ __toESM(require_follow_redirects(), 1); var import_proxy_from_env = /* @__PURE__ */ __toESM(require_proxy_from_env(), 1); -const VERSION$2 = "1.12.2"; +const VERSION$2 = "1.13.6"; //#endregion //#region ../node_modules/axios/lib/helpers/parseProtocol.js function parseProtocol(url) { @@ -71444,6 +71500,60 @@ const flushOnFinish = (stream, [throttled, flush]) => { stream.on("end", flush).on("error", flush); return throttled; }; +var Http2Sessions = class { + constructor() { + this.sessions = Object.create(null); + } + getSession(authority, options) { + options = Object.assign({ sessionTimeout: 1e3 }, options); + let authoritySessions = this.sessions[authority]; + if (authoritySessions) { + let len = authoritySessions.length; + for (let i = 0; i < len; i++) { + const [sessionHandle, sessionOptions] = authoritySessions[i]; + if (!sessionHandle.destroyed && !sessionHandle.closed && util.isDeepStrictEqual(sessionOptions, options)) return sessionHandle; + } + } + const session = http2.connect(authority, options); + let removed; + const removeSession = () => { + if (removed) return; + removed = true; + let entries = authoritySessions, len = entries.length, i = len; + while (i--) if (entries[i][0] === session) { + if (len === 1) delete this.sessions[authority]; + else entries.splice(i, 1); + return; + } + }; + const originalRequestFn = session.request; + const { sessionTimeout } = options; + if (sessionTimeout != null) { + let timer; + let streamsCount = 0; + session.request = function() { + const stream = originalRequestFn.apply(this, arguments); + streamsCount++; + if (timer) { + clearTimeout(timer); + timer = null; + } + stream.once("close", () => { + if (!--streamsCount) timer = setTimeout(() => { + timer = null; + removeSession(); + }, sessionTimeout); + }); + return stream; + }; + } + session.once("close", removeSession); + let entry = [session, options]; + authoritySessions ? authoritySessions.push(entry) : authoritySessions = this.sessions[authority] = [entry]; + return session; + } +}; +const http2Sessions = new Http2Sessions(); /** * If the proxy or config beforeRedirects functions are defined, call them with the options * object. @@ -71474,7 +71584,8 @@ function setProxy(options, configProxy, location) { if (proxy) { if (proxy.username) proxy.auth = (proxy.username || "") + ":" + (proxy.password || ""); if (proxy.auth) { - if (proxy.auth.username || proxy.auth.password) proxy.auth = (proxy.auth.username || "") + ":" + (proxy.auth.password || ""); + if (Boolean(proxy.auth.username || proxy.auth.password)) proxy.auth = (proxy.auth.username || "") + ":" + (proxy.auth.password || ""); + else if (typeof proxy.auth === "object") throw new AxiosError$1("Invalid proxy authorization", AxiosError$1.ERR_BAD_OPTION, { proxy }); const base64 = Buffer.from(proxy.auth, "utf8").toString("base64"); options.headers["Proxy-Authorization"] = "Basic " + base64; } @@ -71522,14 +71633,43 @@ const buildAddressEntry = (address, family) => resolveFamily(utils_default.isObj address, family }); +const http2Transport = { request(options, cb) { + const authority = options.protocol + "//" + options.hostname + ":" + (options.port || (options.protocol === "https:" ? 443 : 80)); + const { http2Options, headers } = options; + const session = http2Sessions.getSession(authority, http2Options); + const { HTTP2_HEADER_SCHEME, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS } = http2.constants; + const http2Headers = { + [HTTP2_HEADER_SCHEME]: options.protocol.replace(":", ""), + [HTTP2_HEADER_METHOD]: options.method, + [HTTP2_HEADER_PATH]: options.path + }; + utils_default.forEach(headers, (header, name) => { + name.charAt(0) !== ":" && (http2Headers[name] = header); + }); + const req = session.request(http2Headers); + req.once("response", (responseHeaders) => { + const response = req; + responseHeaders = Object.assign({}, responseHeaders); + const status = responseHeaders[HTTP2_HEADER_STATUS]; + delete responseHeaders[HTTP2_HEADER_STATUS]; + response.headers = responseHeaders; + response.statusCode = +status; + cb(response); + }); + return req; +} }; var http_default = isHttpAdapterSupported && function httpAdapter(config) { return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) { - let { data, lookup, family } = config; + let { data, lookup, family, httpVersion = 1, http2Options } = config; const { responseType, responseEncoding } = config; const method = config.method.toUpperCase(); let isDone; let rejected = false; let req; + httpVersion = +httpVersion; + if (Number.isNaN(httpVersion)) throw TypeError(`Invalid protocol version: '${config.httpVersion}' is not a number`); + if (httpVersion !== 1 && httpVersion !== 2) throw TypeError(`Unsupported protocol version '${httpVersion}'`); + const isHttp2 = httpVersion === 2; if (lookup) { const _lookup = callbackify(lookup, (value) => utils_default.isArray(value) ? value : [value]); lookup = (hostname, opt, cb) => { @@ -71540,27 +71680,39 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { }); }; } - const emitter = new EventEmitter(); + const abortEmitter = new EventEmitter(); + function abort(reason) { + try { + abortEmitter.emit("abort", !reason || reason.type ? new CanceledError$1(null, config, req) : reason); + } catch (err) { + console.warn("emit error", err); + } + } + abortEmitter.once("abort", reject); const onFinished = () => { if (config.cancelToken) config.cancelToken.unsubscribe(abort); if (config.signal) config.signal.removeEventListener("abort", abort); - emitter.removeAllListeners(); + abortEmitter.removeAllListeners(); }; - onDone((value, isRejected) => { + if (config.cancelToken || config.signal) { + config.cancelToken && config.cancelToken.subscribe(abort); + if (config.signal) config.signal.aborted ? abort() : config.signal.addEventListener("abort", abort); + } + onDone((response, isRejected) => { isDone = true; if (isRejected) { rejected = true; onFinished(); + return; } + const { data } = response; + if (data instanceof stream.Readable || data instanceof stream.Duplex) { + const offListeners = stream.finished(data, () => { + offListeners(); + onFinished(); + }); + } else onFinished(); }); - function abort(reason) { - emitter.emit("abort", !reason || reason.type ? new CanceledError$1(null, config, req) : reason); - } - emitter.once("abort", reject); - if (config.cancelToken || config.signal) { - config.cancelToken && config.cancelToken.subscribe(abort); - if (config.signal) config.signal.aborted ? abort() : config.signal.addEventListener("abort", abort); - } const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls); const parsed = new URL(fullPath, platform_default.hasBrowserEnv ? platform_default.origin : void 0); const protocol = parsed.protocol || supportedProtocols[0]; @@ -71594,7 +71746,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { } if (supportedProtocols.indexOf(protocol) === -1) return reject(new AxiosError$1("Unsupported protocol " + protocol, AxiosError$1.ERR_BAD_REQUEST, config)); const headers = AxiosHeaders$1.from(config.headers).normalize(); - headers.set("User-Agent", "axios/1.12.2", false); + headers.set("User-Agent", "axios/1.13.6", false); const { onUploadProgress, onDownloadProgress } = config; const maxRate = config.maxRate; let maxUploadRate = void 0; @@ -71604,7 +71756,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { data = formDataToStream(data, (formHeaders) => { headers.set(formHeaders); }, { - tag: `axios-1.12.2-boundary`, + tag: `axios-1.13.6-boundary`, boundary: userBoundary && userBoundary[1] || void 0 }); } else if (utils_default.isFormData(data) && utils_default.isFunction(data.getHeaders)) { @@ -71669,7 +71821,8 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { protocol, family, beforeRedirect: dispatchBeforeRedirect, - beforeRedirects: {} + beforeRedirects: {}, + http2Options }; !utils_default.isUndefined(lookup) && (options.lookup = lookup); if (config.socketPath) options.socketPath = config.socketPath; @@ -71681,7 +71834,8 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { let transport; const isHttpsRequest = isHttps.test(options.protocol); options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent; - if (config.transport) transport = config.transport; + if (isHttp2) transport = http2Transport; + else if (config.transport) transport = config.transport; else if (config.maxRedirects === 0) transport = isHttpsRequest ? https : http; else { if (config.maxRedirects) options.maxRedirects = config.maxRedirects; @@ -71694,7 +71848,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { req = transport.request(options, function handleResponse(res) { if (req.destroyed) return; const streams = [res]; - const responseLength = +res.headers["content-length"]; + const responseLength = utils_default.toFiniteNumber(res.headers["content-length"]); if (onDownloadProgress || maxDownloadRate) { const transformStream = new AxiosTransformStream({ maxRate: utils_default.toFiniteNumber(maxDownloadRate) }); onDownloadProgress && transformStream.on("progress", flushOnFinish(transformStream, progressEventDecorator(responseLength, progressEventReducer(asyncDecorator(onDownloadProgress), true, 3)))); @@ -71724,10 +71878,6 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { } } responseStream = streams.length > 1 ? stream.pipeline(streams, utils_default.noop) : streams[0]; - const offListeners = stream.finished(responseStream, () => { - offListeners(); - onFinished(); - }); const response = { status: res.statusCode, statusText: res.statusMessage, @@ -71747,7 +71897,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) { rejected = true; responseStream.destroy(); - reject(new AxiosError$1("maxContentLength size of " + config.maxContentLength + " exceeded", AxiosError$1.ERR_BAD_RESPONSE, config, lastRequest)); + abort(new AxiosError$1("maxContentLength size of " + config.maxContentLength + " exceeded", AxiosError$1.ERR_BAD_RESPONSE, config, lastRequest)); } }); responseStream.on("aborted", function handlerStreamAborted() { @@ -71774,16 +71924,16 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { settle(resolve, reject, response); }); } - emitter.once("abort", (err) => { + abortEmitter.once("abort", (err) => { if (!responseStream.destroyed) { responseStream.emit("error", err); responseStream.destroy(); } }); }); - emitter.once("abort", (err) => { - reject(err); - req.destroy(err); + abortEmitter.once("abort", (err) => { + if (req.close) req.close(); + else req.destroy(err); }); req.on("error", function handleRequestError(err) { reject(AxiosError$1.from(err, null, config, req)); @@ -71794,7 +71944,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { if (config.timeout) { const timeout = parseInt(config.timeout, 10); if (Number.isNaN(timeout)) { - reject(new AxiosError$1("error trying to parse `config.timeout` to int", AxiosError$1.ERR_BAD_OPTION_VALUE, config, req)); + abort(new AxiosError$1("error trying to parse `config.timeout` to int", AxiosError$1.ERR_BAD_OPTION_VALUE, config, req)); return; } req.setTimeout(timeout, function handleRequestTimeout() { @@ -71802,10 +71952,9 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { let timeoutErrorMessage = config.timeout ? "timeout of " + config.timeout + "ms exceeded" : "timeout exceeded"; const transitional = config.transitional || transitional_default; if (config.timeoutErrorMessage) timeoutErrorMessage = config.timeoutErrorMessage; - reject(new AxiosError$1(timeoutErrorMessage, transitional.clarifyTimeoutError ? AxiosError$1.ETIMEDOUT : AxiosError$1.ECONNABORTED, config, req)); - abort(); + abort(new AxiosError$1(timeoutErrorMessage, transitional.clarifyTimeoutError ? AxiosError$1.ETIMEDOUT : AxiosError$1.ECONNABORTED, config, req)); }); - } + } else req.setTimeout(0); if (utils_default.isStream(data)) { let ended = false; let errored = false; @@ -71820,7 +71969,10 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) { if (!ended && !errored) abort(new CanceledError$1("Request stream has been aborted", config, req)); }); data.pipe(req); - } else req.end(data); + } else { + data && req.write(data); + req.end(); + } }); }; const __setProxy = setProxy; @@ -71833,20 +71985,23 @@ var isURLSameOrigin_default = platform_default.hasStandardBrowserEnv ? ((origin, //#endregion //#region ../node_modules/axios/lib/helpers/cookies.js var cookies_default = platform_default.hasStandardBrowserEnv ? { - write(name, value, expires, path, domain, secure) { - const cookie = [name + "=" + encodeURIComponent(value)]; - utils_default.isNumber(expires) && cookie.push("expires=" + new Date(expires).toGMTString()); - utils_default.isString(path) && cookie.push("path=" + path); - utils_default.isString(domain) && cookie.push("domain=" + domain); - secure === true && cookie.push("secure"); + write(name, value, expires, path, domain, secure, sameSite) { + if (typeof document === "undefined") return; + const cookie = [`${name}=${encodeURIComponent(value)}`]; + if (utils_default.isNumber(expires)) cookie.push(`expires=${new Date(expires).toUTCString()}`); + if (utils_default.isString(path)) cookie.push(`path=${path}`); + if (utils_default.isString(domain)) cookie.push(`domain=${domain}`); + if (secure === true) cookie.push("secure"); + if (utils_default.isString(sameSite)) cookie.push(`SameSite=${sameSite}`); document.cookie = cookie.join("; "); }, read(name) { - const match = document.cookie.match(new RegExp("(^|;\\s*)(" + name + ")=([^;]*)")); - return match ? decodeURIComponent(match[3]) : null; + if (typeof document === "undefined") return null; + const match = document.cookie.match(new RegExp("(?:^|; )" + name + "=([^;]*)")); + return match ? decodeURIComponent(match[1]) : null; }, remove(name) { - this.write(name, "", Date.now() - 864e5); + this.write(name, "", Date.now() - 864e5, "/"); } } : { write() {}, @@ -71926,7 +72081,8 @@ function mergeConfig$1(config1, config2) { ...config1, ...config2 }), function computeConfigValue(prop) { - const merge = mergeMap[prop] || mergeDeepProperties; + if (prop === "__proto__" || prop === "constructor" || prop === "prototype") return; + const merge = utils_default.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties; const configValue = merge(config1[prop], config2[prop], prop); utils_default.isUndefined(configValue) && merge !== mergeDirectKeys || (config[prop] = configValue); }); @@ -72073,7 +72229,7 @@ const composeSignals = (signals, timeout) => { }; let timer = timeout && setTimeout(() => { timer = null; - onabort(new AxiosError$1(`timeout ${timeout} of ms exceeded`, AxiosError$1.ETIMEDOUT)); + onabort(new AxiosError$1(`timeout of ${timeout}ms exceeded`, AxiosError$1.ETIMEDOUT)); }, timeout); const unsubscribe = () => { if (signals) { @@ -72167,7 +72323,7 @@ const globalFetchAPI = (({ Request, Response }) => ({ Request, Response }))(utils_default.global); -const { ReadableStream: ReadableStream$1, TextEncoder: TextEncoder$2 } = utils_default.global; +const { ReadableStream: ReadableStream$1, TextEncoder: TextEncoder$1 } = utils_default.global; const test = (fn, ...args) => { try { return !!fn(...args); @@ -72183,7 +72339,7 @@ const factory = (env) => { const isResponseSupported = isFunction$2(Response); if (!isFetchSupported) return false; const isReadableStreamSupported = isFetchSupported && isFunction$2(ReadableStream$1); - const encodeText = isFetchSupported && (typeof TextEncoder$2 === "function" ? ((encoder) => (str) => encoder.encode(str))(new TextEncoder$2()) : async (str) => new Uint8Array(await new Request(str).arrayBuffer())); + const encodeText = isFetchSupported && (typeof TextEncoder$1 === "function" ? ((encoder) => (str) => encoder.encode(str))(new TextEncoder$1()) : async (str) => new Uint8Array(await new Request(str).arrayBuffer())); const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => { let duplexAccessed = false; const hasContentType = new Request(platform_default.origin, { @@ -72295,14 +72451,14 @@ const factory = (env) => { }); } catch (err) { unsubscribe && unsubscribe(); - if (err && err.name === "TypeError" && /Load failed|fetch/i.test(err.message)) throw Object.assign(new AxiosError$1("Network Error", AxiosError$1.ERR_NETWORK, config, request), { cause: err.cause || err }); - throw AxiosError$1.from(err, err && err.code, config, request); + if (err && err.name === "TypeError" && /Load failed|fetch/i.test(err.message)) throw Object.assign(new AxiosError$1("Network Error", AxiosError$1.ERR_NETWORK, config, request, err && err.response), { cause: err.cause || err }); + throw AxiosError$1.from(err, err && err.code, config, request, err && err.response); } }; }; const seedCache = /* @__PURE__ */ new Map(); const getFetch = (config) => { - let env = config ? config.env : {}; + let env = config && config.env || {}; const { fetch, Request, Response } = env; const seeds = [ Request, @@ -72321,6 +72477,15 @@ const getFetch = (config) => { const adapter$1 = getFetch(); //#endregion //#region ../node_modules/axios/lib/adapters/adapters.js +/** +* Known adapters mapping. +* Provides environment-specific adapters for Axios: +* - `http` for Node.js +* - `xhr` for browsers +* - `fetch` for fetch API-based requests +* +* @type {Object} +*/ const knownAdapters = { http: http_default, xhr: xhr_default, @@ -72334,32 +72499,58 @@ utils_default.forEach(knownAdapters, (fn, value) => { Object.defineProperty(fn, "adapterName", { value }); } }); +/** +* Render a rejection reason string for unknown or unsupported adapters +* +* @param {string} reason +* @returns {string} +*/ const renderReason = (reason) => `- ${reason}`; +/** +* Check if the adapter is resolved (function, null, or false) +* +* @param {Function|null|false} adapter +* @returns {boolean} +*/ const isResolvedHandle = (adapter) => utils_default.isFunction(adapter) || adapter === null || adapter === false; +/** +* Get the first suitable adapter from the provided list. +* Tries each adapter in order until a supported one is found. +* Throws an AxiosError if no adapter is suitable. +* +* @param {Array|string|Function} adapters - Adapter(s) by name or function. +* @param {Object} config - Axios request configuration +* @throws {AxiosError} If no suitable adapter is available +* @returns {Function} The resolved adapter function +*/ +function getAdapter$1(adapters, config) { + adapters = utils_default.isArray(adapters) ? adapters : [adapters]; + const { length } = adapters; + let nameOrAdapter; + let adapter; + const rejectedReasons = {}; + for (let i = 0; i < length; i++) { + nameOrAdapter = adapters[i]; + let id; + adapter = nameOrAdapter; + if (!isResolvedHandle(nameOrAdapter)) { + adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; + if (adapter === void 0) throw new AxiosError$1(`Unknown adapter '${id}'`); + } + if (adapter && (utils_default.isFunction(adapter) || (adapter = adapter.get(config)))) break; + rejectedReasons[id || "#" + i] = adapter; + } + if (!adapter) { + const reasons = Object.entries(rejectedReasons).map(([id, state]) => `adapter ${id} ` + (state === false ? "is not supported by the environment" : "is not available in the build")); + throw new AxiosError$1(`There is no suitable adapter to dispatch the request ` + (length ? reasons.length > 1 ? "since :\n" + reasons.map(renderReason).join("\n") : " " + renderReason(reasons[0]) : "as no adapter specified"), "ERR_NOT_SUPPORT"); + } + return adapter; +} +/** +* Exports Axios adapters and utility to resolve an adapter +*/ var adapters_default = { - getAdapter: (adapters, config) => { - adapters = utils_default.isArray(adapters) ? adapters : [adapters]; - const { length } = adapters; - let nameOrAdapter; - let adapter; - const rejectedReasons = {}; - for (let i = 0; i < length; i++) { - nameOrAdapter = adapters[i]; - let id; - adapter = nameOrAdapter; - if (!isResolvedHandle(nameOrAdapter)) { - adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; - if (adapter === void 0) throw new AxiosError$1(`Unknown adapter '${id}'`); - } - if (adapter && (utils_default.isFunction(adapter) || (adapter = adapter.get(config)))) break; - rejectedReasons[id || "#" + i] = adapter; - } - if (!adapter) { - const reasons = Object.entries(rejectedReasons).map(([id, state]) => `adapter ${id} ` + (state === false ? "is not supported by the environment" : "is not available in the build")); - throw new AxiosError$1(`There is no suitable adapter to dispatch the request ` + (length ? reasons.length > 1 ? "since :\n" + reasons.map(renderReason).join("\n") : " " + renderReason(reasons[0]) : "as no adapter specified"), "ERR_NOT_SUPPORT"); - } - return adapter; - }, + getAdapter: getAdapter$1, adapters: knownAdapters }; //#endregion @@ -72532,7 +72723,8 @@ var Axios$1 = class { if (transitional !== void 0) validator_default.assertOptions(transitional, { silentJSONParsing: validators.transitional(validators.boolean), forcedJSONParsing: validators.transitional(validators.boolean), - clarifyTimeoutError: validators.transitional(validators.boolean) + clarifyTimeoutError: validators.transitional(validators.boolean), + legacyInterceptorReqResOrdering: validators.transitional(validators.boolean) }, false); if (paramsSerializer != null) if (utils_default.isFunction(paramsSerializer)) config.paramsSerializer = { serialize: paramsSerializer }; else validator_default.assertOptions(paramsSerializer, { @@ -72564,7 +72756,9 @@ var Axios$1 = class { this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config) === false) return; synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; - requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); + const transitional = config.transitional || transitional_default; + if (transitional && transitional.legacyInterceptorReqResOrdering) requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); + else requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); }); const responseInterceptorChain = []; this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { @@ -72738,7 +72932,7 @@ var CancelToken$1 = class CancelToken$1 { * * ```js * function f(x, y, z) {} -* var args = [1, 2, 3]; +* const args = [1, 2, 3]; * f.apply(null, args); * ``` * @@ -72834,7 +73028,13 @@ const HttpStatusCode$1 = { InsufficientStorage: 507, LoopDetected: 508, NotExtended: 510, - NetworkAuthenticationRequired: 511 + NetworkAuthenticationRequired: 511, + WebServerIsDown: 521, + ConnectionTimedOut: 522, + OriginIsUnreachable: 523, + TimeoutOccurred: 524, + SslHandshakeFailed: 525, + InvalidSslCertificate: 526 }; Object.entries(HttpStatusCode$1).forEach(([key, value]) => { HttpStatusCode$1[value] = key; @@ -73637,881 +73837,6 @@ var require_dayjs_min = /* @__PURE__ */ __commonJSMin(((exports, module) => { })); })); //#endregion -//#region ../node_modules/quick-lru/index.js -var import_dayjs_min = /* @__PURE__ */ __toESM(require_dayjs_min(), 1); -var QuickLRU = class extends Map { - #size = 0; - #cache = /* @__PURE__ */ new Map(); - #oldCache = /* @__PURE__ */ new Map(); - #maxSize; - #maxAge; - #onEviction; - constructor(options = {}) { - super(); - if (!(options.maxSize && options.maxSize > 0)) throw new TypeError("`maxSize` must be a number greater than 0"); - if (typeof options.maxAge === "number" && options.maxAge === 0) throw new TypeError("`maxAge` must be a number greater than 0"); - this.#maxSize = options.maxSize; - this.#maxAge = options.maxAge || Number.POSITIVE_INFINITY; - this.#onEviction = options.onEviction; - } - get __oldCache() { - return this.#oldCache; - } - #emitEvictions(cache) { - if (typeof this.#onEviction !== "function") return; - for (const [key, item] of cache) this.#onEviction(key, item.value); - } - #deleteIfExpired(key, item) { - if (typeof item.expiry === "number" && item.expiry <= Date.now()) { - if (typeof this.#onEviction === "function") this.#onEviction(key, item.value); - return this.delete(key); - } - return false; - } - #getOrDeleteIfExpired(key, item) { - if (this.#deleteIfExpired(key, item) === false) return item.value; - } - #getItemValue(key, item) { - return item.expiry ? this.#getOrDeleteIfExpired(key, item) : item.value; - } - #peek(key, cache) { - const item = cache.get(key); - return this.#getItemValue(key, item); - } - #set(key, value) { - this.#cache.set(key, value); - this.#size++; - if (this.#size >= this.#maxSize) { - this.#size = 0; - this.#emitEvictions(this.#oldCache); - this.#oldCache = this.#cache; - this.#cache = /* @__PURE__ */ new Map(); - } - } - #moveToRecent(key, item) { - this.#oldCache.delete(key); - this.#set(key, item); - } - *#entriesAscending() { - for (const item of this.#oldCache) { - const [key, value] = item; - if (!this.#cache.has(key)) { - if (this.#deleteIfExpired(key, value) === false) yield item; - } - } - for (const item of this.#cache) { - const [key, value] = item; - if (this.#deleteIfExpired(key, value) === false) yield item; - } - } - get(key) { - if (this.#cache.has(key)) { - const item = this.#cache.get(key); - return this.#getItemValue(key, item); - } - if (this.#oldCache.has(key)) { - const item = this.#oldCache.get(key); - if (this.#deleteIfExpired(key, item) === false) { - this.#moveToRecent(key, item); - return item.value; - } - } - } - set(key, value, { maxAge = this.#maxAge } = {}) { - const expiry = typeof maxAge === "number" && maxAge !== Number.POSITIVE_INFINITY ? Date.now() + maxAge : void 0; - if (this.#cache.has(key)) this.#cache.set(key, { - value, - expiry - }); - else this.#set(key, { - value, - expiry - }); - return this; - } - has(key) { - if (this.#cache.has(key)) return !this.#deleteIfExpired(key, this.#cache.get(key)); - if (this.#oldCache.has(key)) return !this.#deleteIfExpired(key, this.#oldCache.get(key)); - return false; - } - peek(key) { - if (this.#cache.has(key)) return this.#peek(key, this.#cache); - if (this.#oldCache.has(key)) return this.#peek(key, this.#oldCache); - } - expiresIn(key) { - const item = this.#cache.get(key) ?? this.#oldCache.get(key); - if (item) return item.expiry ? item.expiry - Date.now() : Number.POSITIVE_INFINITY; - } - delete(key) { - const deleted = this.#cache.delete(key); - if (deleted) this.#size--; - return this.#oldCache.delete(key) || deleted; - } - clear() { - this.#cache.clear(); - this.#oldCache.clear(); - this.#size = 0; - } - resize(newSize) { - if (!(newSize && newSize > 0)) throw new TypeError("`maxSize` must be a number greater than 0"); - const items = [...this.#entriesAscending()]; - const removeCount = items.length - newSize; - if (removeCount < 0) { - this.#cache = new Map(items); - this.#oldCache = /* @__PURE__ */ new Map(); - this.#size = items.length; - } else { - if (removeCount > 0) this.#emitEvictions(items.slice(0, removeCount)); - this.#oldCache = new Map(items.slice(removeCount)); - this.#cache = /* @__PURE__ */ new Map(); - this.#size = 0; - } - this.#maxSize = newSize; - } - evict(count = 1) { - const requested = Number(count); - if (!requested || requested <= 0) return; - const items = [...this.#entriesAscending()]; - const evictCount = Math.trunc(Math.min(requested, Math.max(items.length - 1, 0))); - if (evictCount <= 0) return; - this.#emitEvictions(items.slice(0, evictCount)); - this.#oldCache = new Map(items.slice(evictCount)); - this.#cache = /* @__PURE__ */ new Map(); - this.#size = 0; - } - *keys() { - for (const [key] of this) yield key; - } - *values() { - for (const [, value] of this) yield value; - } - *[Symbol.iterator]() { - for (const item of this.#cache) { - const [key, value] = item; - if (this.#deleteIfExpired(key, value) === false) yield [key, value.value]; - } - for (const item of this.#oldCache) { - const [key, value] = item; - if (!this.#cache.has(key)) { - if (this.#deleteIfExpired(key, value) === false) yield [key, value.value]; - } - } - } - *entriesDescending() { - let items = [...this.#cache]; - for (let i = items.length - 1; i >= 0; --i) { - const [key, value] = items[i]; - if (this.#deleteIfExpired(key, value) === false) yield [key, value.value]; - } - items = [...this.#oldCache]; - for (let i = items.length - 1; i >= 0; --i) { - const [key, value] = items[i]; - if (!this.#cache.has(key)) { - if (this.#deleteIfExpired(key, value) === false) yield [key, value.value]; - } - } - } - *entriesAscending() { - for (const [key, value] of this.#entriesAscending()) yield [key, value.value]; - } - get size() { - if (!this.#size) return this.#oldCache.size; - let oldCacheSize = 0; - for (const key of this.#oldCache.keys()) if (!this.#cache.has(key)) oldCacheSize++; - return Math.min(this.#size + oldCacheSize, this.#maxSize); - } - get maxSize() { - return this.#maxSize; - } - get maxAge() { - return this.#maxAge; - } - entries() { - return this.entriesAscending(); - } - forEach(callbackFunction, thisArgument = this) { - for (const [key, value] of this.entriesAscending()) callbackFunction.call(thisArgument, value, key, this); - } - get [Symbol.toStringTag]() { - return "QuickLRU"; - } - toString() { - return `QuickLRU(${this.size}/${this.maxSize})`; - } - [Symbol.for("nodejs.util.inspect.custom")]() { - return this.toString(); - } -}; -//#endregion -//#region ../node_modules/weald/node_modules/ms/dist/index.js -const e$2 = 1e3, t$2 = e$2 * 60, n$1 = t$2 * 60, r$1 = n$1 * 24, i$1 = r$1 * 7, a$1 = r$1 * 365.25, o$1 = a$1 / 12; -function s$1(e, t) { - if (typeof e == `string`) return l$1(e); - if (typeof e == `number`) return p$1(e, t); - throw Error(`Value provided to ms() must be a string or number. value=${JSON.stringify(e)}`); -} -var c$1 = s$1; -function l$1(s) { - if (typeof s != `string` || s.length === 0 || s.length > 100) throw Error(`Value provided to ms.parse() must be a string with length between 1 and 99. value=${JSON.stringify(s)}`); - let c = /^(?-?\d*\.?\d+) *(?milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|months?|mo|years?|yrs?|y)?$/i.exec(s); - if (!c?.groups) return NaN; - let { value: l, unit: u = `ms` } = c.groups, d = parseFloat(l), f = u.toLowerCase(); - switch (f) { - case `years`: - case `year`: - case `yrs`: - case `yr`: - case `y`: return d * a$1; - case `months`: - case `month`: - case `mo`: return d * o$1; - case `weeks`: - case `week`: - case `w`: return d * i$1; - case `days`: - case `day`: - case `d`: return d * r$1; - case `hours`: - case `hour`: - case `hrs`: - case `hr`: - case `h`: return d * n$1; - case `minutes`: - case `minute`: - case `mins`: - case `min`: - case `m`: return d * t$2; - case `seconds`: - case `second`: - case `secs`: - case `sec`: - case `s`: return d * e$2; - case `milliseconds`: - case `millisecond`: - case `msecs`: - case `msec`: - case `ms`: return d; - default: throw Error(`Unknown unit "${f}" provided to ms.parse(). value=${JSON.stringify(s)}`); - } -} -function u$1(e) { - return l$1(e); -} -function d$1(s) { - let c = Math.abs(s); - return c >= a$1 ? `${Math.round(s / a$1)}y` : c >= o$1 ? `${Math.round(s / o$1)}mo` : c >= i$1 ? `${Math.round(s / i$1)}w` : c >= r$1 ? `${Math.round(s / r$1)}d` : c >= n$1 ? `${Math.round(s / n$1)}h` : c >= t$2 ? `${Math.round(s / t$2)}m` : c >= e$2 ? `${Math.round(s / e$2)}s` : `${s}ms`; -} -function f$1(s) { - let c = Math.abs(s); - return c >= a$1 ? m$1(s, c, a$1, `year`) : c >= o$1 ? m$1(s, c, o$1, `month`) : c >= i$1 ? m$1(s, c, i$1, `week`) : c >= r$1 ? m$1(s, c, r$1, `day`) : c >= n$1 ? m$1(s, c, n$1, `hour`) : c >= t$2 ? m$1(s, c, t$2, `minute`) : c >= e$2 ? m$1(s, c, e$2, `second`) : `${s} ms`; -} -function p$1(e, t) { - if (typeof e != `number` || !Number.isFinite(e)) throw Error(`Value provided to ms.format() must be of type number.`); - return t?.long ? f$1(e) : d$1(e); -} -function m$1(e, t, n, r) { - let i = t >= n * 1.5; - return `${Math.round(e / n)} ${r}${i ? `s` : ``}`; -} -//#endregion -//#region ../node_modules/weald/dist/src/common.js -init_supports_color(); -/** -* This is the common logic for both the Node.js and web browser -* implementations of `debug()`. -*/ -function setup(env) { - createDebug.debug = createDebug; - createDebug.default = createDebug; - createDebug.coerce = coerce; - createDebug.disable = disable; - createDebug.enable = enable; - createDebug.enabled = enabled; - createDebug.humanize = c$1; - createDebug.destroy = destroy; - Object.keys(env).forEach((key) => { - createDebug[key] = env[key]; - }); - /** - * The currently active debug mode names, and names to skip. - */ - createDebug.names = []; - createDebug.skips = []; - /** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - createDebug.formatters = {}; - /** - * Selects a color for a debug namespace - * - * @param {string} namespace - The namespace string for the debug instance to be colored - * @returns {number | string} An ANSI color code for the given namespace - */ - function selectColor(namespace) { - let hash = 0; - for (let i = 0; i < namespace.length; i++) { - hash = (hash << 5) - hash + namespace.charCodeAt(i); - hash |= 0; - } - return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; - } - createDebug.selectColor = selectColor; - /** - * Create a debugger with the given `namespace`. - * - * @param {string} namespace - * @returns {Function} - */ - function createDebug(namespace, options) { - let prevTime; - let enableOverride = null; - let namespacesCache; - let enabledCache; - function debug(...args) { - if (!debug.enabled) return; - const self = debug; - const curr = Number(/* @__PURE__ */ new Date()); - self.diff = curr - (prevTime || curr); - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - args[0] = createDebug.coerce(args[0]); - if (typeof args[0] !== "string") args.unshift("%O"); - let index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { - if (match === "%%") return "%"; - index++; - const formatter = createDebug.formatters[format]; - if (typeof formatter === "function") { - const val = args[index]; - match = formatter.call(self, val); - args.splice(index, 1); - index--; - } - return match; - }); - createDebug.formatArgs.call(self, args); - if (options?.onLog != null) options.onLog(...args); - (self.log || createDebug.log).apply(self, args); - } - debug.namespace = namespace; - debug.useColors = createDebug.useColors(); - debug.color = createDebug.selectColor(namespace); - debug.extend = extend; - debug.destroy = createDebug.destroy; - Object.defineProperty(debug, "enabled", { - enumerable: true, - configurable: false, - get: () => { - if (enableOverride !== null) return enableOverride; - if (namespacesCache !== createDebug.namespaces) { - namespacesCache = createDebug.namespaces; - enabledCache = createDebug.enabled(namespace); - } - return enabledCache; - }, - set: (v) => { - enableOverride = v; - } - }); - if (typeof createDebug.init === "function") createDebug.init(debug); - return debug; - } - function extend(namespace, delimiter) { - const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace); - newDebug.log = this.log; - return newDebug; - } - /** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {string} namespaces - */ - function enable(namespaces) { - createDebug.save(namespaces); - createDebug.namespaces = namespaces; - createDebug.names = []; - createDebug.skips = []; - let i; - const split = (typeof namespaces === "string" ? namespaces : "").split(/[\s,]+/); - const len = split.length; - for (i = 0; i < len; i++) { - if (!split[i]) continue; - namespaces = split[i].replace(/\*/g, ".*?"); - if (namespaces[0] === "-") createDebug.skips.push(new RegExp("^" + namespaces.substr(1) + "$")); - else createDebug.names.push(new RegExp("^" + namespaces + "$")); - } - } - /** - * Disable debug output. - * - * @returns {string} namespaces - */ - function disable() { - const namespaces = [...createDebug.names.map(toNamespace), ...createDebug.skips.map(toNamespace).map((namespace) => "-" + namespace)].join(","); - createDebug.enable(""); - return namespaces; - } - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {string} name - * @returns {boolean} - */ - function enabled(name) { - if (name[name.length - 1] === "*") return true; - let i; - let len; - for (i = 0, len = createDebug.skips.length; i < len; i++) if (createDebug.skips[i].test(name)) return false; - for (i = 0, len = createDebug.names.length; i < len; i++) if (createDebug.names[i].test(name)) return true; - return false; - } - /** - * Convert regexp to namespace - */ - function toNamespace(regexp) { - return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\.\*\?$/, "*"); - } - /** - * Coerce `val`. - */ - function coerce(val) { - if (val instanceof Error) return val.stack ?? val.message; - return val; - } - /** - * XXX DO NOT USE. This is a temporary stub function. - * XXX It WILL be removed in the next major release. - */ - function destroy() { - console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); - } - createDebug.setupFormatters(createDebug.formatters); - createDebug.enable(createDebug.load()); - return createDebug; -} -//#endregion -//#region ../node_modules/weald/dist/src/node.js -/** -* @packageDocumentation -* -* This module is a fork of the [debug](https://www.npmjs.com/package/debug) module. It has been converted to TypeScript and the output is ESM. -* -* It is API compatible with no extra features or bug fixes, it should only be used if you want a 100% ESM application. -* -* ESM should be arriving in `debug@5.x.x` so this module can be retired after that. -* -* Please see [debug](https://www.npmjs.com/package/debug) for API details. -*/ -/** -* Module dependencies. -*/ -/** -* This is the Node.js implementation of `debug()`. -*/ -/** -* Colors. -*/ -let colors = [ - 6, - 2, - 3, - 4, - 5, - 1 -]; -if (supportsColor.stderr !== false && (supportsColor.stderr ?? supportsColor).level >= 2) colors = [ - 20, - 21, - 26, - 27, - 32, - 33, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 56, - 57, - 62, - 63, - 68, - 69, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 92, - 93, - 98, - 99, - 112, - 113, - 128, - 129, - 134, - 135, - 148, - 149, - 160, - 161, - 162, - 163, - 164, - 165, - 166, - 167, - 168, - 169, - 170, - 171, - 172, - 173, - 178, - 179, - 184, - 185, - 196, - 197, - 198, - 199, - 200, - 201, - 202, - 203, - 204, - 205, - 206, - 207, - 208, - 209, - 214, - 215, - 220, - 221 -]; -/** -* Build up the default `inspectOpts` object from the environment variables. -* -* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js -*/ -const inspectOpts = Object.keys(process.env).filter((key) => { - return /^debug_/i.test(key); -}).reduce((obj, key) => { - const prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, (_, k) => { - return k.toUpperCase(); - }); - let val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) val = true; - else if (/^(no|off|false|disabled)$/i.test(val)) val = false; - else if (val === "null") val = null; - else val = Number(val); - obj[prop] = val; - return obj; -}, {}); -/** -* Is stdout a TTY? Colored output is enabled when `true`. -*/ -function useColors() { - return "colors" in inspectOpts ? Boolean(inspectOpts.colors) : tty.isatty(process.stderr.fd); -} -/** -* Adds ANSI color escape codes if enabled. -*/ -function formatArgs(args) { - const { namespace: name, useColors } = this; - if (useColors === true) { - const c = this.color; - const colorCode = "\x1B[3" + (c < 8 ? c : "8;5;" + c); - const prefix = ` ${colorCode};1m${name} \u001B[0m`; - args[0] = prefix + args[0].split("\n").join("\n" + prefix); - args.push(colorCode + "m+" + c$1(this.diff) + "\x1B[0m"); - } else args[0] = getDate() + name + " " + args[0]; -} -function getDate() { - if (inspectOpts.hideDate != null) return ""; - return (/* @__PURE__ */ new Date()).toISOString() + " "; -} -/** -* Invokes `util.format()` with the specified arguments and writes to stderr. -*/ -function log$2(...args) { - return process.stderr.write(util$1.format(...args) + "\n"); -} -/** -* Save `namespaces`. -* -* @param {string} namespaces -*/ -function save(namespaces) { - if (namespaces != null) process.env.DEBUG = namespaces; - else delete process.env.DEBUG; -} -/** -* Load `namespaces`. -* -* @returns {string} returns the previously persisted debug modes -*/ -function load$1() { - return process.env.DEBUG; -} -/** -* Init logic for `debug` instances. -* -* Create a new `inspectOpts` object in case `useColors` is set -* differently for a particular `debug` instance. -*/ -function init$3(debug) { - debug.inspectOpts = {}; - const keys = Object.keys(inspectOpts); - for (let i = 0; i < keys.length; i++) debug.inspectOpts[keys[i]] = inspectOpts[keys[i]]; -} -function setupFormatters(formatters) { - /** - * Map %o to `util.inspect()`, all on a single line. - */ - formatters.o = function(v) { - this.inspectOpts.colors = this.useColors; - return util$1.inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" "); - }; - /** - * Map %O to `util.inspect()`, allowing multiple lines if needed. - */ - formatters.O = function(v) { - this.inspectOpts.colors = this.useColors; - return util$1.inspect(v, this.inspectOpts); - }; -} -var node_default = setup({ - init: init$3, - log: log$2, - formatArgs, - save, - load: load$1, - useColors, - setupFormatters, - colors, - inspectOpts -}); -//#endregion -//#region ../node_modules/weald/dist/src/index.js -/** -* @packageDocumentation -* -* This module is a fork of the [debug](https://www.npmjs.com/package/debug) module. It has been converted to TypeScript and the output is ESM. -* -* It is API compatible with no extra features or bug fixes, it should only be used if you want a 100% ESM application. -* -* ESM should be arriving in `debug@5.x.x` so this module can be retired after that. -* -* Please see [debug](https://www.npmjs.com/package/debug) for API details. -*/ -/** -* Module dependencies. -*/ -var src_default = node_default; -//#endregion -//#region ../node_modules/dns-over-http-resolver/dist/src/utils.js -/** -* Build fetch resource for request -*/ -function buildResource(serverResolver, hostname, recordType) { - return `${serverResolver}?name=${hostname}&type=${recordType}`; -} -/** -* Use fetch to find the record -*/ -async function request$2(resource, signal) { - return await (await fetch(resource, { - headers: new Headers({ accept: "application/dns-json" }), - signal - })).json(); -} -/** -* Creates cache key composed by recordType and hostname -* -* @param {string} hostname -* @param {string} recordType -*/ -function getCacheKey(hostname, recordType) { - return `${recordType}_${hostname}`; -} -//#endregion -//#region ../node_modules/dns-over-http-resolver/dist/src/index.js -const log$1 = Object.assign(src_default("dns-over-http-resolver"), { error: src_default("dns-over-http-resolver:error") }); -/** -* DNS over HTTP resolver. -* Uses a list of servers to resolve DNS records with HTTP requests. -*/ -var Resolver = class { - _cache; - _TXTcache; - _servers; - _request; - _abortControllers; - /** - * @class - * @param {object} [options] - * @param {number} [options.maxCache = 100] - maximum number of cached dns records - * @param {Request} [options.request] - function to return DNSJSON - */ - constructor(options = {}) { - this._cache = new QuickLRU({ maxSize: options?.maxCache ?? 100 }); - this._TXTcache = new QuickLRU({ maxSize: options?.maxCache ?? 100 }); - this._servers = ["https://cloudflare-dns.com/dns-query", "https://dns.google/resolve"]; - this._request = options.request ?? request$2; - this._abortControllers = []; - } - /** - * Cancel all outstanding DNS queries made by this resolver. Any outstanding - * requests will be aborted and promises rejected. - */ - cancel() { - this._abortControllers.forEach((controller) => { - controller.abort(); - }); - } - /** - * Get an array of the IP addresses currently configured for DNS resolution. - * These addresses are formatted according to RFC 5952. It can include a custom port. - */ - getServers() { - return this._servers; - } - /** - * Get a shuffled array of the IP addresses currently configured for DNS resolution. - * These addresses are formatted according to RFC 5952. It can include a custom port. - */ - _getShuffledServers() { - const newServers = [...this._servers]; - for (let i = newServers.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * i); - const temp = newServers[i]; - newServers[i] = newServers[j]; - newServers[j] = temp; - } - return newServers; - } - /** - * Sets the IP address and port of servers to be used when performing DNS resolution. - * - * @param {string[]} servers - array of RFC 5952 formatted addresses. - */ - setServers(servers) { - this._servers = servers; - } - async resolve(hostname, rrType = "A") { - switch (rrType) { - case "A": return this.resolve4(hostname); - case "AAAA": return this.resolve6(hostname); - case "TXT": return this.resolveTxt(hostname); - default: throw new Error(`${rrType} is not supported`); - } - } - /** - * Uses the DNS protocol to resolve the given host name into IPv4 addresses - * - * @param {string} hostname - host name to resolve - */ - async resolve4(hostname) { - const recordType = "A"; - const cached = this._cache.get(getCacheKey(hostname, recordType)); - if (cached != null) return cached; - let aborted = false; - for (const server of this._getShuffledServers()) { - const controller = new AbortController(); - this._abortControllers.push(controller); - try { - const response = await this._request(buildResource(server, hostname, recordType), controller.signal); - const data = response.Answer.map((a) => a.data); - const ttl = Math.min(...response.Answer.map((a) => a.TTL)); - this._cache.set(getCacheKey(hostname, recordType), data, { maxAge: ttl }); - return data; - } catch (err) { - if (controller.signal.aborted) aborted = true; - log$1.error(`${server} could not resolve ${hostname} record ${recordType}`); - } finally { - this._abortControllers = this._abortControllers.filter((c) => c !== controller); - } - } - if (aborted) throw Object.assign(/* @__PURE__ */ new Error("queryA ECANCELLED"), { code: "ECANCELLED" }); - throw new Error(`Could not resolve ${hostname} record ${recordType}`); - } - /** - * Uses the DNS protocol to resolve the given host name into IPv6 addresses - * - * @param {string} hostname - host name to resolve - */ - async resolve6(hostname) { - const recordType = "AAAA"; - const cached = this._cache.get(getCacheKey(hostname, recordType)); - if (cached != null) return cached; - let aborted = false; - for (const server of this._getShuffledServers()) { - const controller = new AbortController(); - this._abortControllers.push(controller); - try { - const response = await this._request(buildResource(server, hostname, recordType), controller.signal); - const data = response.Answer.map((a) => a.data); - const ttl = Math.min(...response.Answer.map((a) => a.TTL)); - this._cache.set(getCacheKey(hostname, recordType), data, { maxAge: ttl }); - return data; - } catch (err) { - if (controller.signal.aborted) aborted = true; - log$1.error(`${server} could not resolve ${hostname} record ${recordType}`); - } finally { - this._abortControllers = this._abortControllers.filter((c) => c !== controller); - } - } - if (aborted) throw Object.assign(/* @__PURE__ */ new Error("queryAaaa ECANCELLED"), { code: "ECANCELLED" }); - throw new Error(`Could not resolve ${hostname} record ${recordType}`); - } - /** - * Uses the DNS protocol to resolve the given host name into a Text record - * - * @param {string} hostname - host name to resolve - */ - async resolveTxt(hostname) { - const recordType = "TXT"; - const cached = this._TXTcache.get(getCacheKey(hostname, recordType)); - if (cached != null) return cached; - let aborted = false; - for (const server of this._getShuffledServers()) { - const controller = new AbortController(); - this._abortControllers.push(controller); - try { - const response = await this._request(buildResource(server, hostname, recordType), controller.signal); - const data = response.Answer.map((a) => [a.data.replace(/['"]+/g, "")]); - const ttl = Math.min(...response.Answer.map((a) => a.TTL)); - this._TXTcache.set(getCacheKey(hostname, recordType), data, { maxAge: ttl }); - return data; - } catch (err) { - if (controller.signal.aborted) aborted = true; - log$1.error(`${server} could not resolve ${hostname} record ${recordType}`); - } finally { - this._abortControllers = this._abortControllers.filter((c) => c !== controller); - } - } - if (aborted) throw Object.assign(/* @__PURE__ */ new Error("queryTxt ECANCELLED"), { code: "ECANCELLED" }); - throw new Error(`Could not resolve ${hostname} record ${recordType}`); - } - clearCache() { - this._cache.clear(); - this._TXTcache.clear(); - } -}; -//#endregion //#region ../node_modules/agent-base/dist/helpers.js var require_helpers = /* @__PURE__ */ __commonJSMin(((exports) => { var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) { @@ -74619,7 +73944,7 @@ var require_dist$5 = /* @__PURE__ */ __commonJSMin(((exports) => { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Agent = void 0; - const net$5 = __importStar(__require("net")); + const net$7 = __importStar(__require("net")); const http$7 = __importStar(__require("http")); const https_1 = __require("https"); __exportStar(require_helpers(), exports); @@ -74644,7 +73969,7 @@ var require_dist$5 = /* @__PURE__ */ __commonJSMin(((exports) => { incrementSockets(name) { if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) return null; if (!this.sockets[name]) this.sockets[name] = []; - const fakeSocket = new net$5.Socket({ writable: false }); + const fakeSocket = new net$7.Socket({ writable: false }); this.sockets[name].push(fakeSocket); this.totalSocketCount++; return fakeSocket; @@ -74829,7 +74154,7 @@ var require_dist$4 = /* @__PURE__ */ __commonJSMin(((exports) => { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HttpsProxyAgent = void 0; - const net$4 = __importStar(__require("net")); + const net$6 = __importStar(__require("net")); const tls$1 = __importStar(__require("tls")); const assert_1 = __importDefault(__require("assert")); const debug_1 = __importDefault(require_src()); @@ -74838,7 +74163,7 @@ var require_dist$4 = /* @__PURE__ */ __commonJSMin(((exports) => { const parse_proxy_response_1 = require_parse_proxy_response(); const debug = (0, debug_1.default)("https-proxy-agent"); const setServernameFromNonIpHost = (options) => { - if (options.servername === void 0 && options.host && !net$4.isIP(options.host)) return { + if (options.servername === void 0 && options.host && !net$6.isIP(options.host)) return { ...options, servername: options.host }; @@ -74885,10 +74210,10 @@ var require_dist$4 = /* @__PURE__ */ __commonJSMin(((exports) => { socket = tls$1.connect(setServernameFromNonIpHost(this.connectOpts)); } else { debug("Creating `net.Socket`: %o", this.connectOpts); - socket = net$4.connect(this.connectOpts); + socket = net$6.connect(this.connectOpts); } const headers = typeof this.proxyHeaders === "function" ? this.proxyHeaders() : { ...this.proxyHeaders }; - const host = net$4.isIPv6(opts.host) ? `[${opts.host}]` : opts.host; + const host = net$6.isIPv6(opts.host) ? `[${opts.host}]` : opts.host; let payload = `CONNECT ${host}:${opts.port} HTTP/1.1\r\n`; if (proxy.username || proxy.password) { const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`; @@ -74914,7 +74239,7 @@ var require_dist$4 = /* @__PURE__ */ __commonJSMin(((exports) => { return socket; } socket.destroy(); - const fakeSocket = new net$4.Socket({ writable: false }); + const fakeSocket = new net$6.Socket({ writable: false }); fakeSocket.readable = true; req.once("socket", (s) => { debug("Replaying proxy buffer for failed request"); @@ -75873,9 +75198,9 @@ var require_atomic_sleep = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/sonic-boom/index.js var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { const fs$4 = __require("fs"); - const EventEmitter$8 = __require("events"); + const EventEmitter$9 = __require("events"); const inherits$2 = __require("util").inherits; - const path$5 = __require("path"); + const path$4 = __require("path"); const sleep = require_atomic_sleep(); const assert$43 = __require("assert"); const BUSY_WRITE_TIMEOUT = 100; @@ -75915,13 +75240,13 @@ var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { const flags = sonic.append ? "a" : "w"; const mode = sonic.mode; if (sonic.sync) try { - if (sonic.mkdir) fs$4.mkdirSync(path$5.dirname(file), { recursive: true }); + if (sonic.mkdir) fs$4.mkdirSync(path$4.dirname(file), { recursive: true }); fileOpened(null, fs$4.openSync(file, flags, mode)); } catch (err) { fileOpened(err); throw err; } - else if (sonic.mkdir) fs$4.mkdir(path$5.dirname(file), { recursive: true }, (err) => { + else if (sonic.mkdir) fs$4.mkdir(path$4.dirname(file), { recursive: true }, (err) => { if (err) return fileOpened(err); fs$4.open(file, flags, mode, fileOpened); }); @@ -75971,8 +75296,14 @@ var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { this.flush = flush; this.flushSync = flushSync; this._actualWrite = actualWrite; - fsWriteSync = () => fs$4.writeSync(this.fd, this._writingBuf, "utf8"); - fsWrite = () => fs$4.write(this.fd, this._writingBuf, "utf8", this.release); + fsWriteSync = () => { + if (Buffer.isBuffer(this._writingBuf)) return fs$4.writeSync(this.fd, this._writingBuf); + return fs$4.writeSync(this.fd, this._writingBuf, "utf8"); + }; + fsWrite = () => { + if (Buffer.isBuffer(this._writingBuf)) return fs$4.write(this.fd, this._writingBuf, this.release); + return fs$4.write(this.fd, this._writingBuf, "utf8", this.release); + }; } else throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`); if (typeof fd === "number") { this.fd = fd; @@ -76054,9 +75385,9 @@ var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { * @returns {{writingBuf: string | Buffer, len: number}} released writingBuf and length */ function releaseWritingBuf(writingBuf, len, n) { - if (typeof writingBuf === "string" && Buffer.byteLength(writingBuf) !== n) n = Buffer.from(writingBuf).subarray(0, n).toString().length; + if (typeof writingBuf === "string") writingBuf = Buffer.from(writingBuf); len = Math.max(len - n, 0); - writingBuf = writingBuf.slice(n); + writingBuf = writingBuf.subarray(n); return { writingBuf, len @@ -76067,7 +75398,7 @@ var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { sonic._asyncDrainScheduled = false; sonic.emit("drain"); } - inherits$2(SonicBoom, EventEmitter$8); + inherits$2(SonicBoom, EventEmitter$9); function mergeBuf(bufs, len) { if (bufs.length === 0) return kEmptyBuffer; if (bufs.length === 1) return bufs[0]; @@ -76075,13 +75406,15 @@ var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { } function write(data) { if (this.destroyed) throw new Error("SonicBoom destroyed"); - const len = this._len + data.length; + data = "" + data; + const dataLen = Buffer.byteLength(data); + const len = this._len + dataLen; const bufs = this._bufs; if (this.maxLength && len > this.maxLength) { this.emit("drop", data); return this._len < this._hwm; } - if (bufs.length === 0 || bufs[bufs.length - 1].length + data.length > this.maxWrite) bufs.push("" + data); + if (bufs.length === 0 || Buffer.byteLength(bufs[bufs.length - 1]) + dataLen > this.maxWrite) bufs.push(data); else bufs[bufs.length - 1] += data; this._len = len; if (!this._writing && this._len >= this.minLength) this._actualWrite(); @@ -76216,10 +75549,10 @@ var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { this._writingBuf = ""; } let buf = ""; - while (this._bufs.length || buf) { + while (this._bufs.length || buf.length) { if (buf.length <= 0) buf = this._bufs[0]; try { - const n = fs$4.writeSync(this.fd, buf, "utf8"); + const n = Buffer.isBuffer(buf) ? fs$4.writeSync(this.fd, buf) : fs$4.writeSync(this.fd, buf, "utf8"); const releasedBufObj = releaseWritingBuf(buf, this._len, n); buf = releasedBufObj.writingBuf; this._len = releasedBufObj.len; @@ -76264,13 +75597,13 @@ var require_sonic_boom = /* @__PURE__ */ __commonJSMin(((exports, module) => { function actualWrite() { const release = this.release; this._writing = true; - this._writingBuf = this._writingBuf || this._bufs.shift() || ""; + this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || ""; if (this.sync) try { - release(null, fs$4.writeSync(this.fd, this._writingBuf, "utf8")); + release(null, Buffer.isBuffer(this._writingBuf) ? fs$4.writeSync(this.fd, this._writingBuf) : fs$4.writeSync(this.fd, this._writingBuf, "utf8")); } catch (err) { release(err); } - else fs$4.write(this.fd, this._writingBuf, "utf8", release); + else fs$4.write(this.fd, this._writingBuf, release); } function actualWriteBuffer() { const release = this.release; @@ -76514,7 +75847,7 @@ var require_indexes = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/thread-stream/index.js var require_thread_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { version } = require_package$1(); - const { EventEmitter: EventEmitter$7 } = __require("events"); + const { EventEmitter: EventEmitter$8 } = __require("events"); const { Worker: Worker$1 } = __require("worker_threads"); const { join: join$2 } = __require("path"); const { pathToFileURL: pathToFileURL$1 } = __require("url"); @@ -76642,7 +75975,7 @@ var require_thread_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => stream.worker.off("exit", onWorkerExit); destroy(stream, code !== 0 ? /* @__PURE__ */ new Error("the worker thread exited") : null); } - var ThreadStream = class extends EventEmitter$7 { + var ThreadStream = class extends EventEmitter$8 { constructor(opts = {}) { super(); if (opts.bufferSize < 4) throw new Error("bufferSize must at least fit a 4-byte utf-8 char"); @@ -77457,7 +76790,7 @@ var require_meta = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/pino/lib/proto.js var require_proto = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const { EventEmitter: EventEmitter$6 } = __require("node:events"); + const { EventEmitter: EventEmitter$7 } = __require("node:events"); const { lsCacheSym, levelValSym, setLevelSym, getLevelSym, chindingsSym, parsedChindingsSym, mixinSym, asJsonSym, writeSym, mixinMergeStrategySym, timeSym, timeSliceIndexSym, streamSym, serializersSym, formattersSym, errorKeySym, messageKeySym, useOnlyCustomLevelsSym, needsMetadataGsym, redactFmtSym, stringifySym, formatOptsSym, stringifiersSym, msgPrefixSym, hooksSym } = require_symbols$3(); const { getLevel, setLevel, isLevelEnabled, mappings, initialLsCache, genLsCache, assertNoLevelCollisions } = require_levels(); const { asChindings, asJson, buildFormatters, stringify, noop } = require_tools(); @@ -77495,7 +76828,7 @@ var require_proto = /* @__PURE__ */ __commonJSMin(((exports, module) => { [getLevelSym]: getLevel, [setLevelSym]: setLevel }; - Object.setPrototypeOf(prototype, EventEmitter$6.prototype); + Object.setPrototypeOf(prototype, EventEmitter$7.prototype); module.exports = function() { return Object.create(prototype); }; @@ -78155,7 +77488,7 @@ var require_multistream = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/pino/pino.js var require_pino = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const os$2 = __require("node:os"); + const os$1 = __require("node:os"); const stdSerializers = require_pino_std_serializers(); const caller = require_caller(); const redaction = require_redaction(); @@ -78170,7 +77503,7 @@ var require_pino = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { chindingsSym, redactFmtSym, serializersSym, timeSym, timeSliceIndexSym, streamSym, stringifySym, stringifySafeSym, stringifiersSym, setLevelSym, endSym, formatOptsSym, messageKeySym, errorKeySym, nestedKeySym, mixinSym, levelCompSym, useOnlyCustomLevelsSym, formattersSym, hooksSym, nestedKeyStrSym, mixinMergeStrategySym, msgPrefixSym } = symbols; const { epochTime, nullTime } = time; const { pid } = process; - const hostname = os$2.hostname(); + const hostname = os$1.hostname(); const defaultErrorSerializer = stdSerializers.err; const normalize = createArgsNormalizer({ level: "info", @@ -78369,7 +77702,8 @@ var require_queue = /* @__PURE__ */ __commonJSMin(((exports, module) => { empty: noop, kill, killAndDrain, - error + error, + abort }; return self; function running() { @@ -78475,6 +77809,26 @@ var require_queue = /* @__PURE__ */ __commonJSMin(((exports, module) => { self.drain(); self.drain = noop; } + function abort() { + var current = queueHead; + queueHead = null; + queueTail = null; + while (current) { + var next = current.next; + var callback = current.callback; + var errorHandler = current.errorHandler; + var val = current.value; + var context = current.context; + current.value = null; + current.callback = noop; + current.errorHandler = null; + if (errorHandler) errorHandler(/* @__PURE__ */ new Error("abort"), val); + callback.call(context, /* @__PURE__ */ new Error("abort")); + current.release(current); + current = next; + } + self.drain = noop; + } function error(handler) { errorHandler = handler; } @@ -78794,8 +78148,8 @@ var require_time_tree = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/avvio/lib/debug.js var require_debug$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const { debuglog } = __require("node:util"); - module.exports = { debug: debuglog("avvio") }; + const { debuglog: debuglog$2 } = __require("node:util"); + module.exports = { debug: debuglog$2("avvio") }; })); //#endregion //#region ../node_modules/avvio/lib/create-promise.js @@ -78869,7 +78223,7 @@ var require_is_promise_like = /* @__PURE__ */ __commonJSMin(((exports, module) = //#endregion //#region ../node_modules/avvio/lib/plugin.js var require_plugin = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const { EventEmitter: EventEmitter$5 } = __require("node:events"); + const { EventEmitter: EventEmitter$6 } = __require("node:events"); const { inherits: inherits$1 } = __require("node:util"); const { debug } = require_debug$1(); const { createPromise } = require_create_promise(); @@ -78915,7 +78269,7 @@ var require_plugin = /* @__PURE__ */ __commonJSMin(((exports, module) => { this._promise = null; this.startTime = null; } - inherits$1(Plugin, EventEmitter$5); + inherits$1(Plugin, EventEmitter$6); /** * @callback ExecCallback * @param {Error|null} execErr @@ -80459,8 +79813,8 @@ var require_server = /* @__PURE__ */ __commonJSMin(((exports, module) => { const httpsOptions = options.https === true ? {} : options.https; if (options.serverFactory) server = options.serverFactory(httpHandler, options); else if (options.http2) { - if (typeof httpsOptions === "object") server = http2().createSecureServer(httpsOptions, httpHandler); - else server = http2().createServer(httpHandler); + if (typeof httpsOptions === "object") server = http2$1().createSecureServer(httpsOptions, httpHandler); + else server = http2$1().createServer(httpHandler); server.on("session", sessionTimeout(options.http2SessionTimeout)); } else { if (httpsOptions) server = https$2.createServer(httpsOptions, httpHandler); @@ -80507,7 +79861,7 @@ var require_server = /* @__PURE__ */ __commonJSMin(((exports, module) => { this.log.info(serverListeningText); return address; } - function http2() { + function http2$1() { try { return __require("node:http2"); } catch (err) { @@ -90234,6 +89588,7 @@ var require_limitLength = /* @__PURE__ */ __commonJSMin(((exports) => { var require_pattern = /* @__PURE__ */ __commonJSMin(((exports) => { Object.defineProperty(exports, "__esModule", { value: true }); const code_1 = require_code(); + const util_1 = require_util$7(); const codegen_1 = require_codegen(); exports.default = { keyword: "pattern", @@ -90245,10 +89600,18 @@ var require_pattern = /* @__PURE__ */ __commonJSMin(((exports) => { params: ({ schemaCode }) => (0, codegen_1._)`{pattern: ${schemaCode}}` }, code(cxt) { - const { data, $data, schema, schemaCode, it } = cxt; + const { gen, data, $data, schema, schemaCode, it } = cxt; const u = it.opts.unicodeRegExp ? "u" : ""; - const regExp = $data ? (0, codegen_1._)`(new RegExp(${schemaCode}, ${u}))` : (0, code_1.usePattern)(cxt, schema); - cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`); + if ($data) { + const { regExp } = it.opts.code; + const regExpCode = regExp.code === "new RegExp" ? (0, codegen_1._)`new RegExp` : (0, util_1.useFunc)(gen, regExp); + const valid = gen.let("valid"); + gen.try(() => gen.assign(valid, (0, codegen_1._)`${regExpCode}(${schemaCode}, ${u}).test(${data})`), () => gen.assign(valid, false)); + cxt.fail$data((0, codegen_1._)`!${valid}`); + } else { + const regExp = (0, code_1.usePattern)(cxt, schema); + cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`); + } } }; })); @@ -96245,8 +95608,10 @@ var require_serialize = /* @__PURE__ */ __commonJSMin(((exports) => { function serializeString({ gen, data }) { gen.add(names_1.default.json, (0, codegen_1._)`${(0, util_1.useFunc)(gen, quote_1.default)}(${data})`); } - function serializeNumber({ gen, data }) { - gen.add(names_1.default.json, (0, codegen_1._)`"" + ${data}`); + function serializeNumber({ gen, data, self }) { + const condition = (0, codegen_1._)`${data} === Infinity || ${data} === -Infinity || ${data} !== ${data}`; + if (self.opts.specialNumbers === void 0 || self.opts.specialNumbers === "fast") gen.add(names_1.default.json, (0, codegen_1._)`"" + ${data}`); + else gen.if(condition, () => gen.add(names_1.default.json, (0, codegen_1._)`null`), () => gen.add(names_1.default.json, (0, codegen_1._)`"" + ${data}`)); } function serializeRef(cxt) { const { gen, self, data, definitions, schema, schemaEnv } = cxt; @@ -102404,7 +101769,7 @@ var require_cookie = /* @__PURE__ */ __commonJSMin(((exports) => { //#endregion //#region ../node_modules/light-my-request/lib/parse-url.js var require_parse_url = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const { URL: URL$1 } = __require("node:url"); + const { URL: URL$2 } = __require("node:url"); const BASE_URL = "http://localhost"; /** * Parse URL @@ -102415,7 +101780,7 @@ var require_parse_url = /* @__PURE__ */ __commonJSMin(((exports, module) => { */ module.exports = function parseURL(url, query) { if ((typeof url === "string" || Object.prototype.toString.call(url) === "[object String]") && url.startsWith("//")) url = BASE_URL + url; - const result = typeof url === "object" ? Object.assign(new URL$1(BASE_URL), url) : new URL$1(url, BASE_URL); + const result = typeof url === "object" ? Object.assign(new URL$2(BASE_URL), url) : new URL$2(url, BASE_URL); if (typeof query === "string") { query = new URLSearchParams(query); for (const key of query.keys()) { @@ -102482,13 +101847,13 @@ var require_form_data = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/light-my-request/lib/request.js var require_request$3 = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { Readable: Readable$6, addAbortSignal } = __require("node:stream"); - const util$8 = __require("node:util"); + const util$7 = __require("node:util"); const cookie = require_cookie(); const assert$36 = __require("node:assert"); const { createDeprecation } = require_process_warning(); const parseURL = require_parse_url(); const { isFormDataLike, formDataToStream } = require_form_data(); - const { EventEmitter: EventEmitter$4 } = __require("node:events"); + const { EventEmitter: EventEmitter$5 } = __require("node:events"); const FST_LIGHTMYREQUEST_DEP01 = createDeprecation({ name: "FastifyDeprecationLightMyRequest", code: "FST_LIGHTMYREQUEST_DEP01", @@ -102509,7 +101874,7 @@ var require_request$3 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * @constructor * @param {String} remoteAddress the fake address to show consumers of the socket */ - var MockSocket = class extends EventEmitter$4 { + var MockSocket = class extends EventEmitter$5 { constructor(remoteAddress) { super(); this.remoteAddress = remoteAddress; @@ -102538,7 +101903,7 @@ var require_request$3 = /* @__PURE__ */ __commonJSMin(((exports, module) => { }); Object.assign(this, obj); for (const fn of Object.keys(Request.prototype)) this.constructor.prototype[fn] = Request.prototype[fn]; - util$8.inherits(this.constructor, options.Request); + util$7.inherits(this.constructor, options.Request); return this; } } @@ -102617,8 +101982,8 @@ var require_request$3 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (signal) addAbortSignal(signal, this); return this; } - util$8.inherits(Request, Readable$6); - util$8.inherits(CustomRequest, Request); + util$7.inherits(Request, Readable$6); + util$7.inherits(CustomRequest, Request); Request.prototype.prepare = function(next) { const payload = this._lightMyRequest.payload; if (!payload || typeof payload.resume !== "function") return next(); @@ -102669,6 +102034,12 @@ var require_set_cookie = /* @__PURE__ */ __commonJSMin(((exports, module) => { map: false, silent: false }; + function isForbiddenKey(key) { + return typeof key !== "string" || key in {}; + } + function createNullObj() { + return Object.create(null); + } function isNonEmptyString(str) { return typeof str === "string" && !!str.trim(); } @@ -102678,26 +102049,29 @@ var require_set_cookie = /* @__PURE__ */ __commonJSMin(((exports, module) => { var name = parsed.name; var value = parsed.value; options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; + if (isForbiddenKey(name)) return null; try { value = options.decodeValues ? decodeURIComponent(value) : value; } catch (e) { - console.error("set-cookie-parser encountered an error while decoding a cookie with value '" + value + "'. Set options.decodeValues to false to disable this feature.", e); + console.error("set-cookie-parser: failed to decode cookie value. Set options.decodeValues=false to disable decoding.", e); } - var cookie = { - name, - value - }; + var cookie = createNullObj(); + cookie.name = name; + cookie.value = value; parts.forEach(function(part) { var sides = part.split("="); var key = sides.shift().trimLeft().toLowerCase(); + if (isForbiddenKey(key)) return; var value = sides.join("="); if (key === "expires") cookie.expires = new Date(value); - else if (key === "max-age") cookie.maxAge = parseInt(value, 10); - else if (key === "secure") cookie.secure = true; + else if (key === "max-age") { + var n = parseInt(value, 10); + if (!Number.isNaN(n)) cookie.maxAge = n; + } else if (key === "secure") cookie.secure = true; else if (key === "httponly") cookie.httpOnly = true; else if (key === "samesite") cookie.sameSite = value; else if (key === "partitioned") cookie.partitioned = true; - else cookie[key] = value; + else if (key) cookie[key] = value; }); return cookie; } @@ -102717,7 +102091,7 @@ var require_set_cookie = /* @__PURE__ */ __commonJSMin(((exports, module) => { function parse(input, options) { options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; if (!input) if (!options.map) return []; - else return {}; + else return createNullObj(); if (input.headers) if (typeof input.headers.getSetCookie === "function") input = input.headers.getSetCookie(); else if (input.headers["set-cookie"]) input = input.headers["set-cookie"]; else { @@ -102730,12 +102104,15 @@ var require_set_cookie = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (!Array.isArray(input)) input = [input]; if (!options.map) return input.filter(isNonEmptyString).map(function(str) { return parseString(str, options); - }); - else return input.filter(isNonEmptyString).reduce(function(cookies, str) { - var cookie = parseString(str, options); - cookies[cookie.name] = cookie; - return cookies; - }, {}); + }).filter(Boolean); + else { + var cookies = createNullObj(); + return input.filter(isNonEmptyString).reduce(function(cookies, str) { + var cookie = parseString(str, options); + if (cookie && !isForbiddenKey(cookie.name)) cookies[cookie.name] = cookie; + return cookies; + }, cookies); + } } function splitCookiesString(cookiesString) { if (Array.isArray(cookiesString)) return cookiesString; @@ -102788,7 +102165,7 @@ var require_set_cookie = /* @__PURE__ */ __commonJSMin(((exports, module) => { var require_response$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { const http$5 = __require("node:http"); const { Writable: Writable$5, Readable: Readable$5 } = __require("node:stream"); - const util$7 = __require("node:util"); + const util$6 = __require("node:util"); const setCookie = require_set_cookie(); function Response(req, onEnd, reject) { http$5.ServerResponse.call(this, req); @@ -102822,7 +102199,7 @@ var require_response$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { this.once("error", onEndFailure); this.once("close", onEndFailure); } - util$7.inherits(Response, http$5.ServerResponse); + util$6.inherits(Response, http$5.ServerResponse); Response.prototype.setTimeout = function(msecs, callback) { this.timeoutHandle = setTimeout(() => { this.emit("timeout"); @@ -104579,6 +103956,7 @@ var require_fastify = /* @__PURE__ */ __commonJSMin(((exports, module) => { var import_fastify = /* @__PURE__ */ __toESM(require_fastify(), 1); var import_pino = /* @__PURE__ */ __toESM(require_pino(), 1); var import_dist$1 = require_dist$4(); +var import_dayjs_min = /* @__PURE__ */ __toESM(require_dayjs_min(), 1); async function exists(filename) { return new Promise((resolve) => access(filename, constants.F_OK, (error) => resolve(!error))); } @@ -104860,13 +104238,17 @@ var RotatingFileStream = class extends Writable { const inp = this.fsCreateReadStream(this.filename, {}); const out = this.fsCreateWriteStream(filename, options); const zip = this.createGzip(); - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { inp.once("error", reject); out.once("error", reject); zip.once("error", reject); out.once("finish", resolve); inp.pipe(zip).pipe(out); }); + await Promise.all([new Promise((resolve) => zip.close(resolve)), new Promise((resolve) => out.close((err) => { + if (err) this.emit("warning", err); + resolve(); + }))]); } async rotated(filename) { const { maxFiles, maxSize } = this.options; @@ -105154,8 +104536,8 @@ var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/dotenv/lib/main.js var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => { const fs$3 = __require("fs"); - const path$4 = __require("path"); - const os$1 = __require("os"); + const path$3 = __require("path"); + const os = __require("os"); const crypto$5 = __require("crypto"); const version = require_package().version; const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm; @@ -105255,12 +104637,12 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (options && options.path && options.path.length > 0) if (Array.isArray(options.path)) { for (const filepath of options.path) if (fs$3.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`; } else possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`; - else possibleVaultPath = path$4.resolve(process.cwd(), ".env.vault"); + else possibleVaultPath = path$3.resolve(process.cwd(), ".env.vault"); if (fs$3.existsSync(possibleVaultPath)) return possibleVaultPath; return null; } function _resolveHome(envPath) { - return envPath[0] === "~" ? path$4.join(os$1.homedir(), envPath.slice(1)) : envPath; + return envPath[0] === "~" ? path$3.join(os.homedir(), envPath.slice(1)) : envPath; } function _configVault(options) { const debug = Boolean(options && options.debug); @@ -105273,7 +104655,7 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => { return { parsed }; } function configDotenv(options) { - const dotenvPath = path$4.resolve(process.cwd(), ".env"); + const dotenvPath = path$3.resolve(process.cwd(), ".env"); let encoding = "utf8"; const debug = Boolean(options && options.debug); const quiet = options && "quiet" in options ? options.quiet : true; @@ -105301,7 +104683,7 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => { const keysCount = Object.keys(parsedAll).length; const shortPaths = []; for (const filePath of optionPaths) try { - const relative = path$4.relative(process.cwd(), filePath); + const relative = path$3.relative(process.cwd(), filePath); shortPaths.push(relative); } catch (e) { if (debug) _debug(`Failed to load ${filePath} ${e.message}`); @@ -105567,18 +104949,17 @@ const ENV = { /** * DNS over HTTPS (DOH) Utility Module * -* Uses 'dns-over-http-resolver' package for robust DOH resolution. +* Uses direct HTTP requests for robust DOH resolution. * Reads configuration from config/player.json. * Automatically detects system proxy (Env vars or Windows Registry) to bypass local DNS pollution. */ const execAsync = util.promisify(exec); const __dirname$7 = path.dirname(fileURLToPath(import.meta.url)); let dohServers = null; -let resolver = null; const configPath = path.resolve(__dirname$7, "../config/player.json"); -function getResolver() { - if (!(ENV.get("enable_doh", "0") === "1" || ENV.get("enable_doh") === "true")) return null; - if (resolver) return resolver; +function getDohServers() { + if (!(ENV.get("enable_doh", "0") === "1" || ENV.get("enable_doh") === "true")) return []; + if (dohServers) return dohServers; try { if (!dohServers) try { if (fs.existsSync(configPath)) { @@ -105591,16 +104972,11 @@ function getResolver() { } catch (e) { console.error("[DOH] Failed to load DOH config:", e.message); } - resolver = new Resolver({ - maxCache: 1e3, - request: customRequest - }); - if (dohServers && dohServers.length > 0) resolver.setServers(dohServers); } catch (e) { console.error("[DOH] Init failed:", e.message); - return null; + return []; } - return resolver; + return dohServers || []; } let cachedProxy = null; let lastCheckTime = 0; @@ -105673,12 +105049,11 @@ function getSystemProxy() { })(); return checkPromise; } -const customRequest = async (resource, signal) => { +const customRequest = async (resource) => { try { const proxy = await getSystemProxy(); const config = { headers: { "Accept": "application/dns-json" }, - signal, timeout: 5e3 }; if (proxy) { @@ -105699,10 +105074,19 @@ async function resolveDoh(domain) { if (!domain || /^(\d{1,3}\.){3}\d{1,3}$|^\[[\da-fA-F:]+\]$/.test(domain)) return domain; if (domain === "localhost" || domain === "127.0.0.1") return domain; try { - const resolver = getResolver(); - if (!resolver) return null; - const ips = await resolver.resolve(domain, "A"); - if (ips && ips.length > 0) return ips[0]; + const servers = getDohServers(); + if (!servers || servers.length === 0) return null; + for (const server of servers) try { + const url = new URL(server); + url.searchParams.set("name", domain); + url.searchParams.set("type", "A"); + const data = await customRequest(url.toString()); + if (data && data.Status === 0 && data.Answer) { + for (const ans of data.Answer) if (ans.type === 1) return ans.data; + } + } catch (e) { + continue; + } } catch (e) {} return null; } @@ -105778,39 +105162,6 @@ req$1.interceptors.request.use(async (config) => { * - 自动继承系统代理 */ const reqs = new axios$1.create({ httpsAgent: new https.Agent({ rejectUnauthorized: false }) }); -reqs.interceptors.request.use(async (config) => { - if (!config.url) return config; - try { - const proxy = await getSystemProxy(); - if (proxy) { - config.httpsAgent = new import_dist$1.HttpsProxyAgent(proxy); - config.proxy = false; - return config; - } - let fullUrl = config.url; - if (config.baseURL && !/^https?:\/\//i.test(fullUrl)) try { - fullUrl = new URL(fullUrl, config.baseURL).toString(); - } catch (e) {} - const urlObj = new URL(fullUrl); - const hostname = urlObj.hostname; - if (!hostname || /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === "localhost") return config; - const ip = await resolveDoh(hostname); - if (ip && ip !== hostname) { - if (!config.headers) config.headers = {}; - let hasHost = false; - const keys = Object.keys(config.headers); - for (const k of keys) if (k.toLowerCase() === "host") { - hasHost = true; - break; - } - if (!hasHost) config.headers.Host = hostname; - urlObj.hostname = ip; - config.url = urlObj.toString(); - if (config.baseURL) delete config.baseURL; - } - } catch (e) {} - return config; -}); //#endregion //#region ../utils/pan/ali.js const apiUrl = "https://api.aliyundrive.com"; @@ -113018,11 +112369,26 @@ var require_formats = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/qs/lib/utils.js var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { var formats = require_formats(); + var getSideChannel = require_side_channel(); var has = Object.prototype.hasOwnProperty; var isArray = Array.isArray; + var overflowChannel = getSideChannel(); + var markOverflow = function markOverflow(obj, maxIndex) { + overflowChannel.set(obj, maxIndex); + return obj; + }; + var isOverflow = function isOverflow(obj) { + return overflowChannel.has(obj); + }; + var getMaxIndex = function getMaxIndex(obj) { + return overflowChannel.get(obj); + }; + var setMaxIndex = function setMaxIndex(obj, maxIndex) { + overflowChannel.set(obj, maxIndex); + }; var hexTable = function() { var array = []; - for (var i = 0; i < 256; ++i) array.push("%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase()); + for (var i = 0; i < 256; ++i) array[array.length] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase(); return array; }(); var compactQueue = function compactQueue(queue) { @@ -113031,7 +112397,7 @@ var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { var obj = item.obj[item.prop]; if (isArray(obj)) { var compacted = []; - for (var j = 0; j < obj.length; ++j) if (typeof obj[j] !== "undefined") compacted.push(obj[j]); + for (var j = 0; j < obj.length; ++j) if (typeof obj[j] !== "undefined") compacted[compacted.length] = obj[j]; item.obj[item.prop] = compacted; } } @@ -113044,13 +112410,37 @@ var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { var merge = function merge(target, source, options) { if (!source) return target; if (typeof source !== "object" && typeof source !== "function") { - if (isArray(target)) target.push(source); - else if (target && typeof target === "object") { - if (options && (options.plainObjects || options.allowPrototypes) || !has.call(Object.prototype, source)) target[source] = true; + if (isArray(target)) { + var nextIndex = target.length; + if (options && typeof options.arrayLimit === "number" && nextIndex > options.arrayLimit) return markOverflow(arrayToObject(target.concat(source), options), nextIndex); + target[nextIndex] = source; + } else if (target && typeof target === "object") { + if (isOverflow(target)) { + var newIndex = getMaxIndex(target) + 1; + target[newIndex] = source; + setMaxIndex(target, newIndex); + } else if (options && options.strictMerge) return [target, source]; + else if (options && (options.plainObjects || options.allowPrototypes) || !has.call(Object.prototype, source)) target[source] = true; } else return [target, source]; return target; } - if (!target || typeof target !== "object") return [target].concat(source); + if (!target || typeof target !== "object") { + if (isOverflow(source)) { + var sourceKeys = Object.keys(source); + var result = options && options.plainObjects ? { + __proto__: null, + 0: target + } : { 0: target }; + for (var m = 0; m < sourceKeys.length; m++) { + var oldKey = parseInt(sourceKeys[m], 10); + result[oldKey + 1] = source[sourceKeys[m]]; + } + return markOverflow(result, getMaxIndex(source) + 1); + } + var combined = [target].concat(source); + if (options && typeof options.arrayLimit === "number" && combined.length > options.arrayLimit) return markOverflow(arrayToObject(combined, options), combined.length - 1); + return combined; + } var mergeTarget = target; if (isArray(target) && !isArray(source)) mergeTarget = arrayToObject(target, options); if (isArray(target) && isArray(source)) { @@ -113058,7 +112448,7 @@ var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (has.call(target, i)) { var targetItem = target[i]; if (targetItem && typeof targetItem === "object" && item && typeof item === "object") target[i] = merge(targetItem, item, options); - else target.push(item); + else target[target.length] = item; } else target[i] = item; }); return target; @@ -113067,6 +112457,11 @@ var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { var value = source[key]; if (has.call(acc, key)) acc[key] = merge(acc[key], value, options); else acc[key] = value; + if (isOverflow(source) && !isOverflow(acc)) markOverflow(acc, getMaxIndex(source)); + if (isOverflow(acc)) { + var keyNum = parseInt(key, 10); + if (String(keyNum) === key && keyNum >= 0 && keyNum > getMaxIndex(acc)) setMaxIndex(acc, keyNum); + } return acc; }, mergeTarget); }; @@ -113089,8 +112484,16 @@ var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { module.exports = { arrayToObject, assign, - combine: function combine(a, b) { - return [].concat(a, b); + combine: function combine(a, b, arrayLimit, plainObjects) { + if (isOverflow(a)) { + var newIndex = getMaxIndex(a) + 1; + a[newIndex] = b; + setMaxIndex(a, newIndex); + return a; + } + var result = [].concat(a, b); + if (result.length > arrayLimit) return markOverflow(arrayToObject(result, { plainObjects }), result.length - 1); + return result; }, compact: function compact(value) { var queue = [{ @@ -113106,11 +112509,11 @@ var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { var key = keys[j]; var val = obj[key]; if (typeof val === "object" && val !== null && refs.indexOf(val) === -1) { - queue.push({ + queue[queue.length] = { obj, prop: key - }); - refs.push(val); + }; + refs[refs.length] = val; } } } @@ -113160,13 +112563,15 @@ var require_utils$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (!obj || typeof obj !== "object") return false; return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); }, + isOverflow, isRegExp: function isRegExp(obj) { return Object.prototype.toString.call(obj) === "[object RegExp]"; }, + markOverflow, maybeMap: function maybeMap(val, fn) { if (isArray(val)) { var mapped = []; - for (var i = 0; i < val.length; i += 1) mapped.push(fn(val[i])); + for (var i = 0; i < val.length; i += 1) mapped[mapped.length] = fn(val[i]); return mapped; } return fn(val); @@ -113381,6 +112786,7 @@ var require_parse$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { parseArrays: true, plainObjects: false, strictDepth: false, + strictMerge: true, strictNullHandling: false, throwOnLimitExceeded: false }; @@ -113426,15 +112832,21 @@ var require_parse$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { val = options.strictNullHandling ? null : ""; } else { key = options.decoder(part.slice(0, pos), defaults.decoder, charset, "key"); - val = utils.maybeMap(parseArrayValue(part.slice(pos + 1), options, isArray(obj[key]) ? obj[key].length : 0), function(encodedVal) { + if (key !== null) val = utils.maybeMap(parseArrayValue(part.slice(pos + 1), options, isArray(obj[key]) ? obj[key].length : 0), function(encodedVal) { return options.decoder(encodedVal, defaults.decoder, charset, "value"); }); } if (val && options.interpretNumericEntities && charset === "iso-8859-1") val = interpretNumericEntities(String(val)); if (part.indexOf("[]=") > -1) val = isArray(val) ? [val] : val; - var existing = has.call(obj, key); - if (existing && options.duplicates === "combine") obj[key] = utils.combine(obj[key], val); - else if (!existing || options.duplicates === "last") obj[key] = val; + if (options.comma && isArray(val) && val.length > options.arrayLimit) { + if (options.throwOnLimitExceeded) throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + val = utils.combine([], val, options.arrayLimit, options.plainObjects); + } + if (key !== null) { + var existing = has.call(obj, key); + if (existing && (options.duplicates === "combine" || part.indexOf("[]=") > -1)) obj[key] = utils.combine(obj[key], val, options.arrayLimit, options.plainObjects); + else if (!existing || options.duplicates === "last") obj[key] = val; + } } return obj; }; @@ -113448,48 +112860,66 @@ var require_parse$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { for (var i = chain.length - 1; i >= 0; --i) { var obj; var root = chain[i]; - if (root === "[]" && options.parseArrays) obj = options.allowEmptyArrays && (leaf === "" || options.strictNullHandling && leaf === null) ? [] : utils.combine([], leaf); + if (root === "[]" && options.parseArrays) if (utils.isOverflow(leaf)) obj = leaf; + else obj = options.allowEmptyArrays && (leaf === "" || options.strictNullHandling && leaf === null) ? [] : utils.combine([], leaf, options.arrayLimit, options.plainObjects); else { obj = options.plainObjects ? { __proto__: null } : {}; var cleanRoot = root.charAt(0) === "[" && root.charAt(root.length - 1) === "]" ? root.slice(1, -1) : root; var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, ".") : cleanRoot; var index = parseInt(decodedRoot, 10); + var isValidArrayIndex = !isNaN(index) && root !== decodedRoot && String(index) === decodedRoot && index >= 0 && options.parseArrays; if (!options.parseArrays && decodedRoot === "") obj = { 0: leaf }; - else if (!isNaN(index) && root !== decodedRoot && String(index) === decodedRoot && index >= 0 && options.parseArrays && index <= options.arrayLimit) { + else if (isValidArrayIndex && index < options.arrayLimit) { obj = []; obj[index] = leaf; + } else if (isValidArrayIndex && options.throwOnLimitExceeded) throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + else if (isValidArrayIndex) { + obj[index] = leaf; + utils.markOverflow(obj, index); } else if (decodedRoot !== "__proto__") obj[decodedRoot] = leaf; } leaf = obj; } return leaf; }; - var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) { - if (!givenKey) return; + var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) { var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, "[$1]") : givenKey; + if (options.depth <= 0) { + if (!options.plainObjects && has.call(Object.prototype, key)) { + if (!options.allowPrototypes) return; + } + return [key]; + } var brackets = /(\[[^[\]]*])/; var child = /(\[[^[\]]*])/g; - var segment = options.depth > 0 && brackets.exec(key); + var segment = brackets.exec(key); var parent = segment ? key.slice(0, segment.index) : key; var keys = []; if (parent) { if (!options.plainObjects && has.call(Object.prototype, parent)) { if (!options.allowPrototypes) return; } - keys.push(parent); + keys[keys.length] = parent; } var i = 0; - while (options.depth > 0 && (segment = child.exec(key)) !== null && i < options.depth) { + while ((segment = child.exec(key)) !== null && i < options.depth) { i += 1; - if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) { + var segmentContent = segment[1].slice(1, -1); + if (!options.plainObjects && has.call(Object.prototype, segmentContent)) { if (!options.allowPrototypes) return; } - keys.push(segment[1]); + keys[keys.length] = segment[1]; } if (segment) { if (options.strictDepth === true) throw new RangeError("Input depth exceeded depth option of " + options.depth + " and strictDepth is true"); - keys.push("[" + key.slice(segment.index) + "]"); + keys[keys.length] = "[" + key.slice(segment.index) + "]"; } + return keys; + }; + var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) { + if (!givenKey) return; + var keys = splitKeyIntoSegments(givenKey, options); + if (!keys) return; return parseObject(keys, val, options, valuesParsed); }; var normalizeParseOptions = function normalizeParseOptions(opts) { @@ -113522,6 +112952,7 @@ var require_parse$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { parseArrays: opts.parseArrays !== false, plainObjects: typeof opts.plainObjects === "boolean" ? opts.plainObjects : defaults.plainObjects, strictDepth: typeof opts.strictDepth === "boolean" ? !!opts.strictDepth : defaults.strictDepth, + strictMerge: typeof opts.strictMerge === "boolean" ? !!opts.strictMerge : defaults.strictMerge, strictNullHandling: typeof opts.strictNullHandling === "boolean" ? opts.strictNullHandling : defaults.strictNullHandling, throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === "boolean" ? opts.throwOnLimitExceeded : false }; @@ -113595,6 +113026,28 @@ var BaiduDrive = class { this.channel = "chunlei"; } /** + * 格式化文件大小 + * @param {number} bytes - 文件字节数 + * @returns {string} 格式化后的大小字符串 + */ + formatFileSize(bytes) { + if (!bytes || bytes === 0) return "0 B"; + const units = [ + "B", + "KB", + "MB", + "GB", + "TB" + ]; + let i = 0; + let size = bytes; + while (size >= 1024 && i < units.length - 1) { + size /= 1024; + i++; + } + return size.toFixed(2) + " " + units[i]; + } + /** * 初始化方法,加载本地配置 * @returns {Promise} */ @@ -113684,12 +113137,18 @@ var BaiduDrive = class { if (item.category === "6" || item.category === 6) dirs.push(item.path); if (item.category === "1" || item.category === 1) { const fileName = item.server_filename || item.path.split("/").pop(); + let thumbnail = ""; + if (item.thumbs) thumbnail = item.thumbs.url || item.thumbs.icon || ""; + else if (item.icon) thumbnail = item.icon; videos.push({ name: fileName, path: item.path.replaceAll("#", "\0"), uk: this.uk, shareid: this.shareid, - fsid: item.fs_id || item.fsid + fsid: item.fs_id || item.fsid, + size: item.size, + formatted_size: this.formatFileSize(item.size), + thumbnail }); } }); @@ -113723,12 +113182,18 @@ var BaiduDrive = class { if (item.category === "6" || item.category === 6) dirs.push(item.path); if (item.category === "1" || item.category === 1) { const fileName = item.server_filename || item.path.split("/").pop(); + let thumbnail = ""; + if (item.thumbs) thumbnail = item.thumbs.url || item.thumbs.icon || ""; + else if (item.icon) thumbnail = item.icon; videos.push({ name: fileName, path: item.path.replaceAll("#", "\0"), uk: this.uk, shareid: this.shareid, - fsid: item.fs_id || item.fsid + fsid: item.fs_id || item.fsid, + size: item.size, + formatted_size: this.formatFileSize(item.size), + thumbnail }); } }); @@ -114530,15 +113995,6 @@ var QuarkHandler = class { * @returns {Promise} */ async initQuark() { - if (this.token) { - let exp = JSON.parse(import_crypto_js.default.enc.Base64.parse(this.token.split(".")[1]).toString(import_crypto_js.default.enc.Utf8)); - let now = Math.floor(Date.now() / 1e3); - if (exp.exp < now) console.log("登录状态已过期,重新登录,请及时更换Token"); - else { - console.log("登录成功,继续使用,可使用时间截止到:" + (/* @__PURE__ */ new Date(exp.exp * 1e3)).toLocaleString()); - console.log("QuarkTV token获取成功:" + this.token); - } - } if (this.cookie) console.log("cookie 获取成功"); else console.log("cookie 获取失败"); } @@ -114676,13 +114132,13 @@ var QuarkHandler = class { Object.assign(headers, { Cookie: cookie }); method = method || "post"; let link = `${this.apiUrl}/${url}`; - const resp = method === "get" ? await req$1.get(link, { headers }).catch((err) => { + const resp = method === "get" ? await reqs.get(link, { headers }).catch((err) => { console.error(err.message); return err.response || { status: 500, data: {} }; - }) : await req$1.post(link, data, { headers }).catch((err) => { + }) : await reqs.post(link, data, { headers }).catch((err) => { console.error(err.message); return err.response || { status: 500, @@ -114976,40 +114432,6 @@ var QuarkHandler = class { const data = method + "&" + pathname + "&" + timestamp + "&" + key; return import_crypto_js.default.SHA256(data).toString(); } - async refreshToken() { - let data = JSON.stringify({ - "req_id": reqId, - "app_ver": this.conf.appVer, - "device_id": deviceID, - "device_brand": "OPPO", - "platform": "tv", - "device_name": "PCRT00", - "device_model": "PCRT00", - "build_device": "aosp", - "build_product": "PCRT00", - "device_gpu": "Adreno%20(TM)%20640", - "activity_rect": "%7B%7D", - "channel": this.conf.channel, - "refresh_token": this.token - }); - let config = { - method: "POST", - url: "http://api.extscreen.com/quarkdrive", - headers: { - "User-Agent": "Mozilla/5.0 (Linux; U; Android 7.1.2; zh-cn; PCRT00 Build/N2G47O) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1", - "Connection": "Keep-Alive", - "Accept-Encoding": "gzip", - "Content-Type": "application/json", - "Cookie": "sl-session=VIaxTAKF8mdJBhU2uda0zA==" - }, - data - }; - let req = await axios.request(config); - if (req.status === 200) { - ENV.set("uc_token_cookie", req.data.data.refresh_token); - return await this.getDownload(shareId, stoken, fileId, fileToken, clean); - } - } async getDownload(shareId, stoken, fileId, fileToken, clean) { await this.initQuark(); if (!this.saveFileIdCaches[fileId]) { @@ -115109,8 +114531,72 @@ var QuarkHandler = class { } return null; } + async getToken() { + let t = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3); + let data = JSON.stringify({ + "conversation_id": "300000" + t, + "conversation_type": 3, + "msg_id": t + "000" + }); + let config = { + method: "POST", + url: "https://drive-social-api.quark.cn/1/clouddrive/chat/conv/file/acquire_dl_token?pr=ucpro&fr=pc&sys=darwin&ve=3.19", + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/3.23.2 Chrome/112.0.5615.165 Electron/24.1.3.8 Safari/537.36 Channel/pckk_other_ch", + "Connection": "keep-alive", + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json", + "accept-language": "zh-CN", + "origin": "https://pan.quark.cn", + "sec-fetch-dest": "empty", + "sec-fetch-mode": "cors", + "sec-fetch-site": "cross-site", + "sec-ch-ua": "\"Not:A-Brand\";v=\"99\", \"Chromium\";v=\"112\"", + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": "\"Windows\"", + "referer": "https://pan.quark.cn/", + "Cookie": this.cookie + }, + data + }; + let html = await axios.request(config); + if (html.status === 200) return html.data.data.token; + } + async getUrl(shareId, stoken, fileId, fileToken) { + await this.initQuark(); + let token = await this.getToken(); + let data = JSON.stringify({ + "fids": [fileId], + "fids_token": [fileToken], + "pwd_id": shareId, + "stoken": stoken, + "speedup_session": "", + "token": token + }); + let config = { + method: "POST", + url: "https://drive-pc.quark.cn/1/clouddrive/file/download?pr=ucpro&fr=pc", + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/3.20.0 Chrome/112.0.5615.165 Electron/24.1.3.8 Safari/537.36 Channel/pckk_other_ch", + "Connection": "keep-alive", + "Accept": "*/*,application/json;charset=utf-8", + "Accept-Encoding": "gzip, deflate, br, zstd", + "Content-Type": "application/json", + "Cookie": this.cookie + }, + data + }; + let html = await axios.request(config).catch((e) => e); + if (html.status === 200) return html.data.data.map((it) => { + return { + name: it.video_max_resolution, + url: it.download_url + }; + }); + } async testSupport(url, headers) { - const resp = await req$1.get(url, { + const resp = await reqs.get(url, { responseType: "stream", headers }).catch((err) => { @@ -115220,7 +114706,7 @@ var QuarkHandler = class { const start = chunkIdx * chunkSize; const end = Math.min(contentLength - 1, (chunkIdx + 1) * chunkSize - 1); console.log(inReq.id, chunkIdx); - const dlResp = await req$1.get(url, { + const dlResp = await reqs.get(url, { responseType: "stream", timeout, headers: Object.assign({ Range: `bytes=${start}-${end}` }, headers) @@ -115621,6 +115107,7 @@ var UCHandler = class { const subDir = []; for (const item of items) if (item.dir === true) subDir.push(item); else if (item.file === true && item.obj_category === "video") { + let text = /[#|'"\[\]&<>]/g; if (item.size < 1024 * 1024 * 5) continue; item.stoken = this.shareTokenCache[shareData.shareId].stoken; item.file_name = text.test(item.file_name) ? item.file_name.replace(text, "") : item.file_name; @@ -116434,6 +115921,683 @@ var YunDrive = class { }; const Yun$1 = new YunDrive(); //#endregion +//#region ../utils/pan/xun.js +var XunDriver = class { + constructor() { + this.regex = /https:\/\/pan.xunlei.com\/s\/(.*)\?.*?pwd=([^&]+)/; + this.headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Connection": "keep-alive", + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6" + }; + this.api = "https://xluser-ssl.xunlei.com/"; + this.xun_api = "https://api-pan.xunlei.com/"; + this.captcha_token = ""; + this.parent_id = ""; + this.share_id = ""; + this.pass_code = ""; + this.pass_code_token = ""; + this.filename = "ds"; + this.fileId = ""; + this.vodID = ""; + this.client_id = "XW5SkOhLDjnOZP7J"; + this.x_client_id = "XW-G4v1H72tgfJym"; + this.device_id = "652c6bb3cacdb4b80e852dfc3cb3cca4"; + this.i = 0; + } + async init() { + if (this.auth) if (JSON.parse(import_crypto_js.default.enc.Base64.parse(this.auth.split(".")[1]).toString(import_crypto_js.default.enc.Utf8)).exp > Math.floor(Date.now() / 1e3)) console.log("登录成功"); + else console.log("登录过期,重新登录"); + else await this.getAuth(); + } + get username() { + return ENV.get("xun_username"); + } + get password() { + return ENV.get("xun_password"); + } + get auth() { + return ENV.get("xun_auth"); + } + get app_auth() { + return ENV.get("xun_app_auth"); + } + get refresh_token() { + return ENV.get("xun_refresh_token"); + } + get userId() { + return ENV.get("xun_user_id"); + } + /** + * 延时函数 + * + * 创建一个Promise,在指定毫秒数后resolve,用于控制请求频率。 + * + * @param {number} ms - 延时毫秒数 + * @returns {Promise} 延时Promise + * + * @example + * await delay(1000); // 延时1秒 + */ + delay(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + async execUrl(url) { + this.link = url; + const matches = this.regex.exec(url); + if (matches && matches[1]) { + this.share_id = matches[1]; + this.pass_code = matches[2] || ""; + } + } + async login() { + let data = JSON.stringify({ + "protocolVersion": "301", + "sequenceNo": "1000001", + "platformVersion": "10", + "isCompressed": "0", + "appid": "40", + "clientVersion": "8.03.0.9067", + "peerID": "c9b076a446517969dff638cd37fa9ff1", + "appName": "ANDROID-com.xunlei.downloadprovider", + "sdkVersion": "231500", + "devicesign": "div101.b71a923eb0e2239842599a3c016b4098612f6cf6d6e9fd1925845ec59285716c", + "netWorkType": "2G", + "providerName": "NONE", + "deviceModel": "22021211RC", + "deviceName": "Xiaomi_22021211Rc", + "OSVersion": "12", + "creditkey": "", + "hl": "zh-CN", + "userName": this.username, + "passWord": this.password, + "verifyKey": "", + "verifyCode": "", + "isMd5Pwd": "0" + }); + let config = { + method: "POST", + url: `${this.api}xluser.core.login/v3/login`, + headers: { "Content-Type": "application/json" }, + data + }; + let login_data = await axios$1.request(config); + if (login_data.status === 200) { + console.log("登录成功"); + return login_data.data.sessionID; + } + } + async getSignCaptcha() { + let data = JSON.stringify({ + "client_id": this.x_client_id, + "action": "POST:/v1/auth/signin", + "device_id": this.device_id, + "captcha_token": "", + "meta": { "phone_number": `+86 ${this.username}` } + }); + let config = { + method: "POST", + url: `${this.api}v1/shield/captcha/init`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json" + }, + data + }; + let signin = await axios$1.request(config); + if (signin.status === 200) return signin.data.captcha_token; + } + async getAuth() { + let need_auth = 1; + if (this.auth) { + if (JSON.parse(import_crypto_js.default.enc.Base64.parse(this.auth.split(".")[1]).toString(import_crypto_js.default.enc.Utf8)).exp > Math.floor(Date.now() / 1e3)) { + console.log("登录成功"); + need_auth = 0; + } + } + if (need_auth) { + console.log("登录过期,重新登录"); + let captcha_token = await this.getSignCaptcha(); + let data = JSON.stringify({ + "username": `+86 ${this.username}`, + "password": this.password, + "client_id": this.x_client_id + }); + let config = { + method: "POST", + url: `${this.api}v1/auth/signin`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json", + "accept-language": "zh-cn", + "x-captcha-token": captcha_token, + "x-client-id": this.x_client_id, + "x-device-id": this.device_id + }, + data + }; + let auth_data = await axios$1.request(config); + if (auth_data.status === 200) { + ENV.set("xun_auth", auth_data.data.token_type + " " + auth_data.data.access_token); + ENV.set("xun_user_id", auth_data.data.user_id); + } + await this.safecaptcha(); + } + } + async safecaptcha() { + let data = JSON.stringify({ + "client_id": this.x_client_id, + "action": "get:/drive/v1/privilege/USER_SECURITY_TOKEN", + "device_id": this.device_id, + "captcha_token": "", + "meta": { + "username": "", + "phone_number": "", + "email": "", + "package_name": "pan.xunlei.com", + "client_version": "1.92.9", + "captcha_sign": "1.98cda33124387df2c03dea12799af2af", + "timestamp": "1757397551603", + "user_id": this.userId + } + }); + let config = { + method: "POST", + url: "https://xluser-ssl.xunlei.com/v1/shield/captcha/init", + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "content-type": "text/plain;charset=UTF-8" + }, + data + }; + let captcha_token = (await axios$1.request(config)).data.captcha_token; + let safe_data = (await axios$1({ + method: "GET", + url: "https://api-pan.xunlei.com/drive/v1/privilege/USER_SECURITY_TOKEN", + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": this.auth, + "content-type": "application/json", + "x-captcha-token": captcha_token, + "x-client-id": this.x_client_id, + "x-device-id": this.device_id + } + })).data; + } + async getCaptcha_token(path, mth) { + let action = `${mth}:${path}`; + let data = JSON.stringify({ + "client_id": "Xqp0kJBXWhwaTpB6", + "action": action, + "device_id": "1bf91caf40093318e8040916eb7ad16a", + "captcha_token": "", + "meta": { + "username": "", + "phone_number": "", + "email": "", + "package_name": "pan.xunlei.com", + "client_version": "1.92.9", + "captcha_sign": "1.cbc20fd633c54023baab5b816228bf90", + "timestamp": "1757383155459", + "user_id": this.userId + } + }); + let config = { + method: "POST", + url: `${this.api}v1/shield/captcha/init`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json" + }, + data + }; + let captcha_data = await axios$1.request(config); + if (captcha_data.status === 200) return captcha_data.data.captcha_token; + } + async getAppCaptcha_token(path, mth) { + let action = `${mth}:${path}`; + let data = JSON.stringify({ + "client_id": "XW-G4v1H72tgfJym", + "action": action, + "device_id": "652c6bb3cacdb4b80e852dfc3cb3cca4", + "captcha_token": "", + "meta": { + "package_name": "ThunderPanPlugin", + "client_version": "3.1.5", + "captcha_sign": "1.ee2cef5f061a7cdf4374df81b370d2ec", + "timestamp": "1773293019719", + "user_id": this.userId + } + }); + let config = { + method: "POST", + url: `${this.api}v1/shield/captcha/init`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json" + }, + data + }; + let captcha_data = await axios$1.request(config); + if (captcha_data.status === 200) return captcha_data.data.captcha_token; + } + sign() { + let x = [ + "QG3/GhopO+5+T", + "1Sv94+ANND3lDmmw", + "q2eTxRva8b3B5d", + "m2", + "VIc5CZRBMU71ENfbOh0+RgWIuzLy", + "66M8Wpw6nkBEekOtL6e", + "N0rucK7S8W/vrRkfPto5urIJJS8dVY0S", + "oLAR7pdUVUAp9xcuHWzrU057aUhdCJrt", + "6lxcykBSsfI//GR9", + "r50cz+1I4gbU/fk8", + "tdwzrTc4SNFC4marNGTgf05flC85A", + "qvNVUDFjfsOMqvdi2gB8gCvtaJAIqxXs" + ]; + const c = { + ClientID: "Xqp0kJBXWhwaTpB6", + ClientVersion: "1.92.9", + PackageName: "pan.xunlei.com", + DeviceID: "1bf91caf40093318e8040916eb7ad16a" + }; + const timestamp = Date.now(); + let w = c.ClientID + c.ClientVersion + c.PackageName + c.DeviceID + "1757338961011"; + for (let i = 0; i < x.length; i++) w = import_crypto_js.default.MD5(w + x[i]).toString(); + return "1." + w; + } + async getShareList() { + let captcha_data = await this.getCaptcha_token("/drive/v1/share", "get"); + let config = { + method: "GET", + url: `${this.xun_api}drive/v1/share?share_id=${this.share_id}&pass_code=${this.pass_code}&limit=100&page_token=&thumbnail_size=SIZE_SMALL`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": "", + "x-captcha-token": captcha_data, + "x-client-id": "Xqp0kJBXWhwaTpB6", + "x-device-id": "1bf91caf40093318e8040916eb7ad16a" + } + }; + let sharelist = await axios$1.request(config); + if (sharelist.status === 200) { + let file = {}; + let dirs = []; + let videos = []; + this.pass_code_token = sharelist.data.pass_code_token; + sharelist.data.files.map((it) => { + if (it.mime_type === "") dirs.push(it.id); + else { + let text = /[#|'"\[\]&<>]/g; + let name = text.test(it.name) ? it.name.replace(text, "") : it.name; + videos.push({ + name, + fileId: it.id, + share_id: this.share_id, + parent_id: it.parent_id, + pass_code_token: encodeURIComponent(this.pass_code_token) + }); + } + }); + if (!(sharelist.data.title in file) && sharelist.data.title !== void 0) file[sharelist.data.title] = []; + if (videos.length > 0 && sharelist.data.title !== void 0) file[sharelist.data.title] = [...videos]; + let result = await Promise.all(dirs.map(async (id) => this.getShareDetail(id))); + result = result.filter((item) => item !== void 0 && item !== null).flat(); + if (result.length >= 0) file[sharelist.data.title].push(...result); + return file; + } + } + async getShareDetail(id) { + let captcha_data = await this.getCaptcha_token("/drive/v1/share", "get"); + let config = { + method: "GET", + url: `${this.xun_api}drive/v1/share/detail?share_id=${this.share_id}&parent_id=${id}&pass_code_token=${encodeURIComponent(this.pass_code_token)}&limit=100&page_token=&thumbnail_size=SIZE_SMALL`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": "", + "content-type": "application/json", + "x-captcha-token": captcha_data, + "x-client-id": "Xqp0kJBXWhwaTpB6", + "x-device-id": "1bf91caf40093318e8040916eb7ad16a" + } + }; + let detail_data = await axios$1.request(config); + if (detail_data.status === 200) { + let dirs = []; + let videos = []; + detail_data.data.files.map((it) => { + if (it.mime_type === "") dirs.push(it.id); + else { + let text = /[#|'"\[\]&<>]/g; + let name = text.test(it.name) ? it.name.replace(text, "") : it.name; + videos.push({ + name, + fileId: it.id, + share_id: this.share_id, + parent_id: it.parent_id, + pass_code_token: encodeURIComponent(this.pass_code_token) + }); + } + }); + let result = await Promise.all(dirs.map(async (id) => this.getShareDetail(id))); + result = result.filter((item) => item !== void 0 && item !== null); + return [...videos, ...result.flat()]; + } + } + async getShareUrl(fileId, share_id, pass_code_token) { + let captcha_data = await this.getCaptcha_token("/drive/v1/share", "get"); + let config = { + method: "GET", + url: `${this.xun_api}drive/v1/share/file_info?pass_code_token=${encodeURIComponent(pass_code_token)}&space=&file_id=${fileId}&share_id=${share_id}&&pass_code=${this.pass_code}`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": "", + "cache-control": "no-cache", + "content-type": "application/json", + "x-captcha-token": captcha_data, + "x-client-id": "Xqp0kJBXWhwaTpB6", + "x-device-id": "1bf91caf40093318e8040916eb7ad16a" + } + }; + let url_list = await axios$1.request(config); + if (url_list.status === 200) { + let urls = []; + url_list.data.file_info.medias.map((it) => { + if (it.link !== null) { + urls.push(it.media_name, it.link.url + "#isVideo=true##fastPlayMode##threads=20#"); + urls.push("猫画" + it.media_name, `http://127.0.0.1:5575/proxy?thread=${ENV.get("thread") || 6}&chunkSize=256&url=` + encodeURIComponent(it.link.url)); + } + }); + return urls; + } + } + async getShareData(url) { + if (url.startsWith("https://")) { + await this.execUrl(url); + return await this.getShareList(); + } + } + async saveResult(fileId, share_id, pass_code_token) { + let captcha_data = await this.getAppCaptcha_token("drive/v1/files", "get"); + let data = JSON.stringify({ + "parent_id": this.fileId, + "share_id": share_id, + "pass_code_token": decodeURIComponent(pass_code_token), + "ancestor_ids": [], + "file_ids": [fileId], + "specify_parent_id": true + }); + let config = { + method: "POST", + url: `${this.xun_api}drive/v1/share/restore`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": this.auth, + "x-captcha-token": captcha_data, + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + }, + data + }; + let file_data = await axios$1.request(config).catch((e) => e.response); + if (file_data.status === 200) console.log("转存文件成功"); + if (file_data.status === 404) { + this.i++; + if (this.i < 3) await this.saveResult(fileId, share_id, pass_code_token); + else { + this.i = 0; + console.log("转存失败:" + file_data.data); + } + } + } + async saveFile(fileId, share_id, pass_code_token) { + await this.createFile(); + if (this.fileId !== "" && this.fileId !== void 0) { + await this.delay(5e3); + await this.saveResult(fileId, share_id, pass_code_token); + } + } + async getFile() { + if (this.auth === void 0 || this.auth === "") await this.getAuth(); + let captcha_data = await this.getAppCaptcha_token("drive/v1/files", "get"); + let config = { + method: "GET", + url: `${this.xun_api}drive/v1/files?parent_id=&filters=%7B%22phase%22%3A%7B%22eq%22%3A%22PHASE_TYPE_COMPLETE%22%7D%2C%22trashed%22%3A%7B%22eq%22%3Afalse%7D%7D&with_audit=true&thumbnail_size=SIZE_SMALL&limit=50`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": this.auth, + "content-type": "application/json", + "x-captcha-token": captcha_data, + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + } + }; + let file_data = await axios$1.request(config); + if (file_data.status === 200) file_data.data.files.map((it) => { + if (it.name === this.filename) this.fileId = it.id; + }); + } + async createFile() { + await this.getFile(); + let captcha_data = await this.getAppCaptcha_token("drive/v1/files", "get"); + let data = JSON.stringify({ + "parent_id": "", + "name": this.filename, + "kind": "drive#folder", + "space": "" + }); + let config = { + method: "POST", + url: `${this.xun_api}drive/v1/files`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": this.auth, + "x-captcha-token": captcha_data, + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + }, + data + }; + let file_data = await axios$1.request(config).catch((e) => e.response); + if (file_data.status === 200) this.fileId = file_data.data.file.id; + } + async getVodId() { + let captcha_data = await this.getAppCaptcha_token("drive/v1/files", "get"); + let config = { + method: "GET", + url: `${this.xun_api}drive/v1/files?parent_id=${this.fileId}&filters=%7B%22phase%22%3A%7B%22eq%22%3A%22PHASE_TYPE_COMPLETE%22%7D%2C%22trashed%22%3A%7B%22eq%22%3Afalse%7D%7D&with_audit=true&thumbnail_size=SIZE_SMALL&limit=50`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": this.auth, + "content-type": "application/json", + "x-captcha-token": captcha_data, + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + } + }; + let file_data = await axios$1.request(config); + if (file_data.status === 200) file_data.data.files.map((it) => { + this.vodID = it.id; + }); + return this.vodID; + } + async deleteFile() { + await this.getFile(); + if (this.fileId !== "" && this.fileId !== void 0) { + let captcha_data = await this.getAppCaptcha_token("drive/v1/files", "get"); + let data = JSON.stringify({ + "ids": [this.fileId], + "space": "" + }); + let config = { + method: "POST", + url: `${this.xun_api}drive/v1/files:batchDelete`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json", + "accept-language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6", + "authorization": this.auth, + "x-captcha-token": captcha_data, + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + }, + data + }; + let delete_data = await axios$1.request(config).catch((e) => e.response); + if (delete_data.status === 200) console.log("删除文件成功"); + else if (delete_data.status === 404) console.log("文件未找到,删除失败"); + } + } + async getDownload_CAPTCHA_TOKEN() { + let data = { + "client_id": "XW-G4v1H72tgfJym", + "action": "GET:CAPTCHA_TOKEN", + "device_id": "652c6bb3cacdb4b80e852dfc3cb3cca4", + "captcha_token": "", + "meta": { + "package_name": "ThunderPanPlugin", + "client_version": "3.1.1", + "captcha_sign": "1.0eada0deeeaac52a6376f2e167fa9f29", + "timestamp": "1757378771289", + "user_id": this.userId + } + }; + let config = { + method: "POST", + url: `${this.api}v1/shield/captcha/init`, + headers: { + "User-Agent": "thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + data + }; + let captcha_data = await axios$1.request(config); + if (captcha_data.status === 200) return captcha_data.data.captcha_token; + } + async getAppCaptcha() { + let data = JSON.stringify({ + "client_id": "Xqp0kJBXWhwaTpB6", + "action": "POST:/v1/auth/signin", + "device_id": "652c6bb3cacdb4b80e852dfc3cb3cca4", + "captcha_token": "", + "meta": { "phone_number": `+86 ${this.username}` } + }); + let config = { + method: "POST", + url: `${this.api}v1/shield/captcha/init`, + headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Content-Type": "application/json" + }, + data + }; + let signin = await axios$1.request(config); + if (signin.status === 200) return signin.data.captcha_token; + } + async AppAuth() { + if (this.app_auth) if (JSON.parse(import_crypto_js.default.enc.Base64.parse(this.app_auth.split(".")[1]).toString(import_crypto_js.default.enc.Utf8)).exp > Math.floor(Date.now() / 1e3)) console.log("登录成功"); + else { + console.log("登录过期,重新登录"); + let captcha_token = await this.getAppCaptcha(); + let data = JSON.stringify({ + "username": `+86 ${this.username}`, + "password": this.password, + "client_id": "XW-G4v1H72tgfJym" + }); + let config = { + method: "POST", + url: `${this.api}v1/auth/signin`, + headers: { + "User-Agent": "thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36", + "Content-Type": "application/json", + "x-captcha-token": captcha_token, + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + }, + data + }; + let auth_data = await axios$1.request(config); + if (auth_data.status === 200) { + ENV.set("xun_refresh_token", auth_data.data.refresh_token); + ENV.set("xun_app_auth", auth_data.data.token_type + " " + auth_data.data.access_token); + } + } + } + async getDownload_auth() { + await this.AppAuth(); + let data = JSON.stringify({ + "client_id": "XW-G4v1H72tgfJym", + "client_secret": "Qbaferw2knfQKqxa25EYJGtZ2_6755CMwzXBN3ctW54", + "grant_type": "refresh_token", + "refresh_token": this.refresh_token + }); + let dwon_data = await axios$1({ + method: "POST", + url: "https://xluser-ssl.xunlei.com/v1/auth/token", + headers: { + "User-Agent": "thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36", + "Content-Type": "application/json", + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + }, + data + }).catch((e) => e.response); + if (dwon_data.status === 200) { + ENV.set("xun_retoken", dwon_data.data.refresh_token); + ENV.set("xun_App_auth", dwon_data.data.token_type + " " + dwon_data.data.access_token); + } + } + async getDownloadUrl(fileId, share_id, pass_code_token) { + try { + await this.getDownload_auth(); + await this.deleteFile(); + await this.delay(1e3); + await this.saveFile(fileId, share_id, pass_code_token); + let vodID = await this.getVodId(); + let x_captcha_token = await this.getDownload_CAPTCHA_TOKEN(); + let config = { + method: "GET", + url: `${this.xun_api}drive/v1/files/${vodID}?space=&with[0]=public_share_tag&usage=FETCH`, + headers: { + "User-Agent": "thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36", + "Connection": "keep-alive", + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "x-captcha-token": x_captcha_token, + "authorization": this.app_auth, + "content-type": "application/json", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + } + }; + let file_data = await axios$1.request(config); + if (file_data.status === 200) { + console.log("下载地址:" + file_data.data.links["application/octet-stream"].url || file_data.data["web_content_link"]); + return file_data.data.links["application/octet-stream"].url || file_data.data["web_content_link"]; + } + } catch (e) { + console.log(e); + return ""; + } + } +}; +const Xun$1 = new XunDriver(); +//#endregion //#region ../utils/pans.js /** * 网盘服务模块集合 @@ -116462,7 +116626,8 @@ var pans_default = { Pan: Pan$1, Quark: Quark$1, UC: UC$1, - Yun: Yun$1 + Yun: Yun$1, + Xun: Xun$1 }; //#endregion //#region ../node_modules/cheerio/dist/esm/options.js @@ -120499,7 +120664,7 @@ var static_exports = /* @__PURE__ */ __exportAll({ merge: () => merge, parseHTML: () => parseHTML, root: () => root$1, - text: () => text$2, + text: () => text$1, xml: () => xml }); /** @@ -120557,7 +120722,7 @@ function xml(dom) { * @param elements - Elements to render. * @returns The rendered document. */ -function text$2(elements) { +function text$1(elements) { const elems = elements !== null && elements !== void 0 ? elements : this ? this.root() : []; let ret = ""; for (let i = 0; i < elems.length; i++) ret += textContent(elems[i]); @@ -122430,7 +122595,7 @@ function getAttr(elem, name, xmlMode) { (_a = elem.attribs) !== null && _a !== void 0 || (elem.attribs = {}); if (!name) return elem.attribs; if (hasOwn(elem.attribs, name)) return !xmlMode && rboolean.test(name) ? name : elem.attribs[name]; - if (elem.name === "option" && name === "value") return text$2(elem.children); + if (elem.name === "option" && name === "value") return text$1(elem.children); if (elem.name === "input" && (elem.attribs["type"] === "radio" || elem.attribs["type"] === "checkbox") && name === "value") return "on"; } /** @@ -122640,7 +122805,7 @@ function val(value) { for (const val of values) this.find(`option[value="${val}"]`).attr("selected", ""); return this; } - return this.attr("multiple") ? option.toArray().map((el) => text$2(el.children)) : option.attr("value"); + return this.attr("multiple") ? option.toArray().map((el) => text$1(el.children)) : option.attr("value"); } case "button": case "input": @@ -125399,7 +125564,7 @@ var manipulation_exports = /* @__PURE__ */ __exportAll({ prependTo: () => prependTo, remove: () => remove, replaceWith: () => replaceWith, - text: () => text$1, + text: () => text, toString: () => toString$2, unwrap: () => unwrap, wrap: () => wrap$1, @@ -126069,9 +126234,9 @@ function html(str) { function toString$2() { return this._render(this); } -function text$1(str) { - if (str === void 0) return text$2(this); - if (typeof str === "function") return domEach(this, (el, i) => this._make(el).text(str.call(el, i, text$2([el])))); +function text(str) { + if (str === void 0) return text$1(this); + if (typeof str === "function") return domEach(this, (el, i) => this._make(el).text(str.call(el, i, text$1([el])))); return domEach(this, (el) => { if (!hasChildren(el)) return; for (const child of el.children) child.next = child.prev = child.parent = null; @@ -143588,7 +143753,8 @@ var require_symbols = /* @__PURE__ */ __commonJSMin(((exports, module) => { kPingInterval: Symbol("ping interval"), kNoProxyAgent: Symbol("no proxy agent"), kHttpProxyAgent: Symbol("http proxy agent"), - kHttpsProxyAgent: Symbol("https proxy agent") + kHttpsProxyAgent: Symbol("https proxy agent"), + kSocks5ProxyAgent: Symbol("socks5 proxy agent") }; })); //#endregion @@ -144230,6 +144396,29 @@ var require_errors = /* @__PURE__ */ __commonJSMin(((exports, module) => { return true; } }; + var Socks5ProxyError = class extends UndiciError { + constructor(message, code) { + super(message); + this.name = "Socks5ProxyError"; + this.message = message || "SOCKS5 proxy error"; + this.code = code || "UND_ERR_SOCKS5"; + } + }; + const kMessageSizeExceededError = Symbol.for("undici.error.UND_ERR_WS_MESSAGE_SIZE_EXCEEDED"); + var MessageSizeExceededError = class extends UndiciError { + constructor(message) { + super(message); + this.name = "MessageSizeExceededError"; + this.message = message || "Max decompressed message size exceeded"; + this.code = "UND_ERR_WS_MESSAGE_SIZE_EXCEEDED"; + } + static [Symbol.hasInstance](instance) { + return instance && instance[kMessageSizeExceededError] === true; + } + get [kMessageSizeExceededError]() { + return true; + } + }; module.exports = { AbortError, HTTPParserError, @@ -144253,7 +144442,9 @@ var require_errors = /* @__PURE__ */ __commonJSMin(((exports, module) => { RequestRetryError, ResponseError, SecureProxyConnectionError, - MaxOriginsReachedError + MaxOriginsReachedError, + Socks5ProxyError, + MessageSizeExceededError }; })); //#endregion @@ -144512,7 +144703,7 @@ var require_util$5 = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { kDestroyed, kBodyUsed, kListeners, kBody } = require_symbols(); const { IncomingMessage } = __require("node:http"); const stream$1 = __require("node:stream"); - const net$3 = __require("node:net"); + const net$5 = __require("node:net"); const { stringify: stringify$2 } = __require("node:querystring"); const { EventEmitter: EE$2 } = __require("node:events"); const timers = require_timers(); @@ -144673,7 +144864,7 @@ var require_util$5 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (!host) return null; assert$34(typeof host === "string"); const servername = getHostname(host); - if (net$3.isIP(servername)) return ""; + if (net$5.isIP(servername)) return ""; return servername; } /** @@ -144700,6 +144891,18 @@ var require_util$5 = /* @__PURE__ */ __commonJSMin(((exports, module) => { return !!(obj != null && (typeof obj[Symbol.iterator] === "function" || typeof obj[Symbol.asyncIterator] === "function")); } /** + * Checks whether an object has a safe Symbol.iterator — i.e. one that is + * either own or inherited from a non-Object.prototype chain. This prevents + * prototype-pollution attacks from injecting a fake iterator on + * Object.prototype. + * @param {object} obj + * @returns {boolean} + */ + function hasSafeIterator(obj) { + const prototype = Object.getPrototypeOf(obj); + return Object.prototype.hasOwnProperty.call(obj, Symbol.iterator) || prototype != null && prototype !== Object.prototype && typeof obj[Symbol.iterator] === "function"; + } + /** * @param {Blob|Buffer|import ('stream').Stream} body * @returns {number|null} */ @@ -145371,6 +145574,7 @@ var require_util$5 = /* @__PURE__ */ __commonJSMin(((exports, module) => { getServerName, isStream, isIterable, + hasSafeIterator, isAsyncIterable, isDestroyed, headerNameToString, @@ -145445,10 +145649,10 @@ var require_stats = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/undici/lib/core/diagnostics.js var require_diagnostics = /* @__PURE__ */ __commonJSMin(((exports, module) => { const diagnosticsChannel$2 = __require("node:diagnostics_channel"); - const util$6 = __require("node:util"); - const undiciDebugLog = util$6.debuglog("undici"); - const fetchDebuglog = util$6.debuglog("fetch"); - const websocketDebuglog = util$6.debuglog("websocket"); + const util$5 = __require("node:util"); + const undiciDebugLog = util$5.debuglog("undici"); + const fetchDebuglog = util$5.debuglog("fetch"); + const websocketDebuglog = util$5.debuglog("websocket"); const channels = { beforeConnect: diagnosticsChannel$2.channel("undici:client:beforeConnect"), connected: diagnosticsChannel$2.channel("undici:client:connected"), @@ -145555,28 +145759,31 @@ var require_diagnostics = /* @__PURE__ */ __commonJSMin(((exports, module) => { var require_request$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { InvalidArgumentError, NotSupportedError } = require_errors(); const assert$33 = __require("node:assert"); - const { isValidHTTPToken, isValidHeaderValue, isStream, destroy, isBuffer, isFormDataLike, isIterable, isBlobLike, serializePathWithQuery, assertRequestHandler, getServerName, normalizedMethodRecords, getProtocolFromUrlString } = require_util$5(); + const { isValidHTTPToken, isValidHeaderValue, isStream, destroy, isBuffer, isFormDataLike, isIterable, hasSafeIterator, isBlobLike, serializePathWithQuery, assertRequestHandler, getServerName, normalizedMethodRecords, getProtocolFromUrlString } = require_util$5(); const { channels } = require_diagnostics(); const { headerNameLowerCasedRecord } = require_constants$4(); const invalidPathRegex = /[^\u0021-\u00ff]/; const kHandler = Symbol("handler"); var Request = class { - constructor(origin, { path, method, body, headers, query, idempotent, blocking, upgrade, headersTimeout, bodyTimeout, reset, expectContinue, servername, throwOnError, maxRedirections }, handler) { + constructor(origin, { path, method, body, headers, query, idempotent, blocking, upgrade, headersTimeout, bodyTimeout, reset, expectContinue, servername, throwOnError, maxRedirections, typeOfService }, handler) { if (typeof path !== "string") throw new InvalidArgumentError("path must be a string"); else if (path[0] !== "/" && !(path.startsWith("http://") || path.startsWith("https://")) && method !== "CONNECT") throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); else if (invalidPathRegex.test(path)) throw new InvalidArgumentError("invalid request path"); if (typeof method !== "string") throw new InvalidArgumentError("method must be a string"); else if (normalizedMethodRecords[method] === void 0 && !isValidHTTPToken(method)) throw new InvalidArgumentError("invalid request method"); if (upgrade && typeof upgrade !== "string") throw new InvalidArgumentError("upgrade must be a string"); + if (upgrade && !isValidHeaderValue(upgrade)) throw new InvalidArgumentError("invalid upgrade header"); if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) throw new InvalidArgumentError("invalid headersTimeout"); if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) throw new InvalidArgumentError("invalid bodyTimeout"); if (reset != null && typeof reset !== "boolean") throw new InvalidArgumentError("invalid reset"); if (expectContinue != null && typeof expectContinue !== "boolean") throw new InvalidArgumentError("invalid expectContinue"); if (throwOnError != null) throw new InvalidArgumentError("invalid throwOnError"); if (maxRedirections != null && maxRedirections !== 0) throw new InvalidArgumentError("maxRedirections is not supported, use the redirect interceptor"); + if (typeOfService != null && (!Number.isInteger(typeOfService) || typeOfService < 0 || typeOfService > 255)) throw new InvalidArgumentError("typeOfService must be an integer between 0 and 255"); this.headersTimeout = headersTimeout; this.bodyTimeout = bodyTimeout; this.method = method; + this.typeOfService = typeOfService ?? 0; this.abort = null; if (body == null) this.body = null; else if (isStream(body)) { @@ -145616,7 +145823,7 @@ var require_request$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (Array.isArray(headers)) { if (headers.length % 2 !== 0) throw new InvalidArgumentError("headers array must be even"); for (let i = 0; i < headers.length; i += 2) processHeader(this, headers[i], headers[i + 1]); - } else if (headers && typeof headers === "object") if (headers[Symbol.iterator]) for (const header of headers) { + } else if (headers && typeof headers === "object") if (hasSafeIterator(headers)) for (const header of headers) { if (!Array.isArray(header) || header.length !== 2) throw new InvalidArgumentError("headers must be in key-value pair format"); processHeader(this, header[0], header[1]); } @@ -145758,10 +145965,12 @@ var require_request$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (!isValidHeaderValue(val)) throw new InvalidArgumentError(`invalid ${key} header`); } else if (val === null) val = ""; else val = `${val}`; - if (request.host === null && headerName === "host") { + if (headerName === "host") { + if (request.host !== null) throw new InvalidArgumentError("duplicate host header"); if (typeof val !== "string") throw new InvalidArgumentError("invalid host header"); request.host = val; - } else if (request.contentLength === null && headerName === "content-length") { + } else if (headerName === "content-length") { + if (request.contentLength !== null) throw new InvalidArgumentError("duplicate content-length header"); request.contentLength = parseInt(val, 10); if (!Number.isFinite(request.contentLength)) throw new InvalidArgumentError("invalid content-length header"); } else if (request.contentType === null && headerName === "content-type") { @@ -145792,6 +146001,9 @@ var require_wrap_handler = /* @__PURE__ */ __commonJSMin(((exports, module) => { onConnect(abort, context) { return this.#handler.onConnect?.(abort, context); } + onResponseStarted() { + return this.#handler.onResponseStarted?.(); + } onHeaders(statusCode, rawHeaders, resume, statusMessage) { return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage); } @@ -145813,12 +146025,12 @@ var require_wrap_handler = /* @__PURE__ */ __commonJSMin(((exports, module) => { } onRequestUpgrade(controller, statusCode, headers, socket) { const rawHeaders = []; - for (const [key, val] of Object.entries(headers)) rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map((v) => Buffer.from(v)) : Buffer.from(val)); + for (const [key, val] of Object.entries(headers)) rawHeaders.push(Buffer.from(key, "latin1"), toRawHeaderValue(val)); this.#handler.onUpgrade?.(statusCode, rawHeaders, socket); } onResponseStart(controller, statusCode, headers, statusMessage) { const rawHeaders = []; - for (const [key, val] of Object.entries(headers)) rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map((v) => Buffer.from(v)) : Buffer.from(val)); + for (const [key, val] of Object.entries(headers)) rawHeaders.push(Buffer.from(key, "latin1"), toRawHeaderValue(val)); if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) controller.pause(); } onResponseData(controller, data) { @@ -145826,7 +146038,7 @@ var require_wrap_handler = /* @__PURE__ */ __commonJSMin(((exports, module) => { } onResponseEnd(controller, trailers) { const rawTrailers = []; - for (const [key, val] of Object.entries(trailers)) rawTrailers.push(Buffer.from(key), Array.isArray(val) ? val.map((v) => Buffer.from(v)) : Buffer.from(val)); + for (const [key, val] of Object.entries(trailers)) rawTrailers.push(Buffer.from(key, "latin1"), toRawHeaderValue(val)); this.#handler.onComplete?.(rawTrailers); } onResponseError(controller, err) { @@ -145834,14 +146046,17 @@ var require_wrap_handler = /* @__PURE__ */ __commonJSMin(((exports, module) => { this.#handler.onError?.(err); } }; + function toRawHeaderValue(value) { + return Array.isArray(value) ? value.map((item) => Buffer.from(item, "latin1")) : Buffer.from(value, "latin1"); + } })); //#endregion //#region ../node_modules/undici/lib/dispatcher/dispatcher.js var require_dispatcher = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const EventEmitter$3 = __require("node:events"); + const EventEmitter$4 = __require("node:events"); const WrapHandler = require_wrap_handler(); const wrapInterceptor = (dispatch) => (opts, handler) => dispatch(opts, WrapHandler.wrap(handler)); - var Dispatcher = class extends EventEmitter$3 { + var Dispatcher = class extends EventEmitter$4 { dispatch() { throw new Error("not implemented"); } @@ -145920,6 +146135,9 @@ var require_unwrap_handler = /* @__PURE__ */ __commonJSMin(((exports, module) => this.#controller = new UnwrapController(abort); this.#handler.onRequestStart?.(this.#controller, context); } + onResponseStarted() { + return this.#handler.onResponseStarted?.(); + } onUpgrade(statusCode, rawHeaders, socket) { this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket); } @@ -146041,7 +146259,7 @@ var require_dispatcher_base = /* @__PURE__ */ __commonJSMin(((exports, module) = //#endregion //#region ../node_modules/undici/lib/core/connect.js var require_connect = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const net$2 = __require("node:net"); + const net$4 = __require("node:net"); const assert$32 = __require("node:assert"); const util = require_util$5(); const { InvalidArgumentError } = require_errors(); @@ -146101,7 +146319,7 @@ var require_connect = /* @__PURE__ */ __commonJSMin(((exports, module) => { } else { assert$32(!httpSocket, "httpSocket can only be sent on TLS update"); port = port || 80; - socket = net$2.connect({ + socket = net$4.connect({ highWaterMark: 64 * 1024, ...options, localAddress, @@ -146741,21 +146959,21 @@ var require_constants$3 = /* @__PURE__ */ __commonJSMin(((exports) => { //#endregion //#region ../node_modules/undici/lib/llhttp/llhttp-wasm.js var require_llhttp_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const { Buffer: Buffer$3 } = __require("node:buffer"); + const { Buffer: Buffer$5 } = __require("node:buffer"); const wasmBase64 = "AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgL5YUCAgd/A34gASACaiEEAkAgACIDKAIMIgANACADKAIEBEAgAyABNgIECyMAQRBrIgkkAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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C0HjAQwHC0HXAQwGC0HYAQwFC0HZAQwEC0HaAQwDC0HbAQwCC0HdAQwBC0HcAQshAgNAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCADAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQAJ/AkACQAJAAn8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAg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ogKiAqICogKiAqICogKiAqICogKiAqICogIAogILIAQgAUEBaiIBRw0AC0HJACECDOwCCyABQQFqIQEgA0Evai0AAEEBcQ2lAiADQQA2AhwgAyABNgIUIANBlxA2AhAgA0EKNgIMQQAhAgzrAgsgASAERwRAA0AgAS0AAEEgRw0VIAQgAUEBaiIBRw0AC0H4ACECDOsCC0H4ACECDOoCCyADQQI6ACgMOAtBACECIANBADYCHCADQb8LNgIQIANBAjYCDCADIAFBAWo2AhQM6AILQQAhAgzOAgtBDSECDM0CC0ETIQIMzAILQRUhAgzLAgtBFiECDMoCC0EYIQIMyQILQRkhAgzIAgtBGiECDMcCC0EbIQIMxgILQRwhAgzFAgtBHSECDMQCC0EeIQIMwwILQR8hAgzCAgtBICECDMECC0EiIQIMwAILQSMhAgy/AgtBJSECDL4CC0HlACECDL0CCyADQT02AhwgAyABNgIUIAMgADYCDEEAIQIM1QILIANBGzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDNQCCyADQSA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzTAgsgA0ETNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0gILIANBCzYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNECCyADQRA2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzQAgsgA0EgNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzwILIANBCzYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM4CCyADQQw2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzNAgtBACECIANBADYCHCADIAE2AhQgA0HdDjYCECADQRI2AgwMzAILAkADQAJAIAEtAABBCmsOBAACAgACCyAEIAFBAWoiAUcNAAtB/QEhAgzMAgsCQAJAIAMtADZBAUcNAEEAIQACQCADKAI4IgJFDQAgAigCYCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUcNASADQfwBNgIcIAMgATYCFCADQdwZNgIQIANBFTYCDEEAIQIMzQILQdwBIQIMswILIANBADYCHCADIAE2AhQgA0H5CzYCECADQR82AgxBACECDMsCCwJAAkAgAy0AKEEBaw4CBAEAC0HbASECDLICC0HUASECDLECCyADQQI6ADFBACEAAkAgAygCOCICRQ0AIAIoAgAiAkUNACADIAIRAAAhAAsgAEUEQEHdASECDLECCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQbQMNgIQIANBEDYCDEEAIQIMygILIANB+wE2AhwgAyABNgIUIANBgRo2AhAgA0EVNgIMQQAhAgzJAgsgASAERgRAQfoBIQIMyQILIAEtAABByABGDQEgA0EBOgAoC0HAASECDK4CC0HaASECDK0CCyABIARHBEAgA0EMNgIIIAMgATYCBEHZASECDK0CC0H5ASECDMUCCyABIARGBEBB+AEhAgzFAgsgAS0AAEHIAEcNBCABQQFqIQFB2AEhAgyrAgsgASAERgRAQfcBIQIMxAILAkACQCABLQAAQcUAaw4QAAUFBQUFBQUFBQUFBQUFAQULIAFBAWohAUHWASECDKsCCyABQQFqIQFB1wEhAgyqAgtB9gEhAiABIARGDcICIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbrVAGotAABHDQMgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMMCCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIARQRAQeMBIQIMqgILIANB9QE2AhwgAyABNgIUIAMgADYCDEEAIQIMwgILQfQBIQIgASAERg3BAiADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEG41QBqLQAARw0CIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzCAgsgA0GBBDsBKCADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQLiIADQMMAgsgA0EANgIAC0EAIQIgA0EANgIcIAMgATYCFCADQeUfNgIQIANBCDYCDAy/AgtB1QEhAgylAgsgA0HzATYCHCADIAE2AhQgAyAANgIMQQAhAgy9AgtBACEAAkAgAygCOCICRQ0AIAIoAkAiAkUNACADIAIRAAAhAAsgAEUNbiAAQRVHBEAgA0EANgIcIAMgATYCFCADQYIPNgIQIANBIDYCDEEAIQIMvQILIANBjwE2AhwgAyABNgIUIANB7Bs2AhAgA0EVNgIMQQAhAgy8AgsgASAERwRAIANBDTYCCCADIAE2AgRB0wEhAgyjAgtB8gEhAgy7AgsgASAERgRAQfEBIQIMuwILAkACQAJAIAEtAABByABrDgsAAQgICAgICAgIAggLIAFBAWohAUHQASECDKMCCyABQQFqIQFB0QEhAgyiAgsgAUEBaiEBQdIBIQIMoQILQfABIQIgASAERg25AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBtdUAai0AAEcNBCAAQQJGDQMgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuQILQe8BIQIgASAERg24AiADKAIAIgAgBCABa2ohBiABIABrQQFqIQUDQCABLQAAIABBs9UAai0AAEcNAyAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMuAILQe4BIQIgASAERg23AiADKAIAIgAgBCABa2ohBiABIABrQQJqIQUDQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAY2AgAMtwILIAMoAgQhACADQgA3AwAgAyAAIAVBAWoiARArIgBFDQIgA0HsATYCHCADIAE2AhQgAyAANgIMQQAhAgy2AgsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNnAIgA0HtATYCHCADIAE2AhQgAyAANgIMQQAhAgy0AgtBzwEhAgyaAgtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDLQCC0HOASECDJoCCyADQesBNgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMsgILIAEgBEYEQEHrASECDLICCyABLQAAQS9GBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GyODYCECADQQg2AgxBACECDLECC0HNASECDJcCCyABIARHBEAgA0EONgIIIAMgATYCBEHMASECDJcCC0HqASECDK8CCyABIARGBEBB6QEhAgyvAgsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFBywEhAgyWAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZcCIANB6AE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAEgBEYEQEHnASECDK4CCwJAIAEtAABBLkYEQCABQQFqIQEMAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5gE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILQcoBIQIMlAILIAEgBEYEQEHlASECDK0CC0EAIQBBASEFQQEhB0EAIQICQAJAAkACQAJAAn8CQAJAAkACQAJAAkACQCABLQAAQTBrDgoKCQABAgMEBQYICwtBAgwGC0EDDAULQQQMBAtBBQwDC0EGDAILQQcMAQtBCAshAkEAIQVBACEHDAILQQkhAkEBIQBBACEFQQAhBwwBC0EAIQVBASECCyADIAI6ACsgAUEBaiEBAkACQCADLQAuQRBxDQACQAJAAkAgAy0AKg4DAQACBAsgB0UNAwwCCyAADQEMAgsgBUUNAQsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDQIgA0HiATYCHCADIAE2AhQgAyAANgIMQQAhAgyvAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZoCIANB4wE2AhwgAyABNgIUIAMgADYCDEEAIQIMrgILIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ2YAiADQeQBNgIcIAMgATYCFCADIAA2AgwMrQILQckBIQIMkwILQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANBpA02AhAgA0EhNgIMQQAhAgytAgtByAEhAgyTAgsgA0HhATYCHCADIAE2AhQgA0HQGjYCECADQRU2AgxBACECDKsCCyABIARGBEBB4QEhAgyrAgsCQCABLQAAQSBGBEAgA0EAOwE0IAFBAWohAQwBCyADQQA2AhwgAyABNgIUIANBmRE2AhAgA0EJNgIMQQAhAgyrAgtBxwEhAgyRAgsgASAERgRAQeABIQIMqgILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyrAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqgILQcYBIQIMkAILIAEgBEYEQEHfASECDKkCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqgILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKkCC0HFASECDI8CCyABIARGBEBB3gEhAgyoAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKkCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyoAgtBxAEhAgyOAgsgASAERgRAQd0BIQIMpwILAkACQAJAAkAgAS0AAEEKaw4XAgMDAAMDAwMDAwMDAwMDAwMDAwMDAwEDCyABQQFqDAULIAFBAWohAUHDASECDI8CCyABQQFqIQEgA0Evai0AAEEBcQ0IIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKcCCyADQQA2AhwgAyABNgIUIANBjQs2AhAgA0ENNgIMQQAhAgymAgsgASAERwRAIANBDzYCCCADIAE2AgRBASECDI0CC0HcASECDKUCCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtB2wEhAgymAgsgAygCBCEAIANBADYCBCADIAAgARAtIgBFBEAgAUEBaiEBDAQLIANB2gE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMpQILIAMoAgQhACADQQA2AgQgAyAAIAEQLSIADQEgAUEBagshAUHBASECDIoCCyADQdkBNgIcIAMgADYCDCADIAFBAWo2AhRBACECDKICC0HCASECDIgCCyADQS9qLQAAQQFxDQEgA0EANgIcIAMgATYCFCADQeQcNgIQIANBGTYCDEEAIQIMoAILIAEgBEYEQEHZASEC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IAFBAWohAUGeASECDOQBCyABQQFqIQFBnwEhAgzjAQtBtwEhAiABIARGDfsBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQezUAGotAABHDSggAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPwBCyADQQA2AgAgBkEBaiEBQQ0MKAtBtgEhAiABIARGDfoBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDScgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPsBCyADQQA2AgAgBkEBaiEBQQwMJwtBtQEhAiABIARGDfkBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQerUAGotAABHDSYgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPoBCyADQQA2AgAgBkEBaiEBQQMMJgtBtAEhAiABIARGDfgBIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQejUAGotAABHDSUgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADPkBCyADQQA2AgAgBkEBaiEBQSYMJQsgASAERgRAQbMBIQIM+AELAkACQCABLQAAQdQAaw4CAAEnCyABQQFqIQFBmQEhAgzfAQsgAUEBaiEBQZoBIQIM3gELQbIBIQIgASAERg32ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHm1ABqLQAARw0jIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz3AQsgA0EANgIAIAZBAWohAUEnDCMLQbEBIQIgASAERg31ASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHk1ABqLQAARw0iIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz2AQsgA0EANgIAIAZBAWohAUEcDCILQbABIQIgASAERg30ASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHe1ABqLQAARw0hIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz1AQsgA0EANgIAIAZBAWohAUEGDCELQa8BIQIgASAERg3zASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEHZ1ABqLQAARw0gIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAz0AQsgA0EANgIAIAZBAWohAUEZDCALIAEgBEYEQEGuASECDPMBCwJAAkACQAJAIAEtAABBLWsOIwAkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJAEkJCQkJAIkJCQDJAsgAUEBaiEBQY4BIQIM3AELIAFBAWohAUGPASECDNsBCyABQQFqIQFBlAEhAgzaAQsgAUEBaiEBQZUBIQIM2QELQa0BIQIgASAERg3xASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEHX1ABqLQAARw0eIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzyAQsgA0EANgIAIAZBAWohAUELDB4LIAEgBEYEQEGsASECDPEBCwJAAkAgAS0AAEHBAGsOAwAgASALIAFBAWohAUGQASECDNgBCyABQQFqIQFBkwEhAgzXAQsgASAERgRAQasBIQIM8AELAkACQCABLQAAQcEAaw4PAB8fHx8fHx8fHx8fHx8BHwsgAUEBaiEBQZEBIQIM1wELIAFBAWohAUGSASECDNYBCyABIARGBEBBqgEhAgzvAQsgAS0AAEHMAEcNHCABQQFqIQFBCgwbC0GpASECIAEgBEYN7QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABB0dQAai0AAEcNGiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7gELIANBADYCACAGQQFqIQFBHgwaC0GoASECIAEgBEYN7AEgAygCACIAIAQgAWtqIQUgASAAa0EGaiEGAkADQCABLQAAIABBytQAai0AAEcNGSAAQQZGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7QELIANBADYCACAGQQFqIQFBFQwZC0GnASECIAEgBEYN6wEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBx9QAai0AAEcNGCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM7AELIANBADYCACAGQQFqIQFBFwwYC0GmASECIAEgBEYN6gEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBwdQAai0AAEcNFyAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6wELIANBADYCACAGQQFqIQFBGAwXCyABIARGBEBBpQEhAgzqAQsCQAJAIAEtAABByQBrDgcAGRkZGRkBGQsgAUEBaiEBQYsBIQIM0QELIAFBAWohAUGMASECDNABC0GkASECIAEgBEYN6AEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBptUAai0AAEcNFSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6QELIANBADYCACAGQQFqIQFBCQwVC0GjASECIAEgBEYN5wEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBpNUAai0AAEcNFCAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM6AELIANBADYCACAGQQFqIQFBHwwUC0GiASECIAEgBEYN5gEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBvtQAai0AAEcNEyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5wELIANBADYCACAGQQFqIQFBAgwTC0GhASECIAEgBEYN5QEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGA0AgAS0AACAAQbzUAGotAABHDREgAEEBRg0CIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADOUBCyABIARGBEBBoAEhAgzlAQtBASABLQAAQd8ARw0RGiABQQFqIQFBhwEhAgzLAQsgA0EANgIAIAZBAWohAUGIASECDMoBC0GfASECIAEgBEYN4gEgAygCACIAIAQgAWtqIQUgASAAa0EIaiEGAkADQCABLQAAIABBhNUAai0AAEcNDyAAQQhGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4wELIANBADYCACAGQQFqIQFBKQwPC0GeASECIAEgBEYN4QEgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBuNQAai0AAEcNDiAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM4gELIANBADYCACAGQQFqIQFBLQwOCyABIARGBEBBnQEhAgzhAQsgAS0AAEHFAEcNDiABQQFqIQFBhAEhAgzHAQsgASAERgRAQZwBIQIM4AELAkACQCABLQAAQcwAaw4IAA8PDw8PDwEPCyABQQFqIQFBggEhAgzHAQsgAUEBaiEBQYMBIQIMxgELQZsBIQIgASAERg3eASADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANAIAEtAAAgAEGz1ABqLQAARw0LIABBBEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzfAQsgA0EANgIAIAZBAWohAUEjDAsLQZoBIQIgASAERg3dASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGw1ABqLQAARw0KIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzeAQsgA0EANgIAIAZBAWohAUEADAoLIAEgBEYEQEGZASECDN0BCwJAAkAgAS0AAEHIAGsOCAAMDAwMDAwBDAsgAUEBaiEBQf0AIQIMxAELIAFBAWohAUGAASECDMMBCyABIARGBEBBmAEhAgzcAQsCQAJAIAEtAABBzgBrDgMACwELCyABQQFqIQFB/gAhAgzDAQsgAUEBaiEBQf8AIQIMwgELIAEgBEYEQEGXASECDNsBCyABLQAAQdkARw0IIAFBAWohAUEIDAcLQZYBIQIgASAERg3ZASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEGs1ABqLQAARw0GIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzaAQsgA0EANgIAIAZBAWohAUEFDAYLQZUBIQIgASAERg3YASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEGm1ABqLQAARw0FIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzZAQsgA0EANgIAIAZBAWohAUEWDAULQZQBIQIgASAERg3XASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGh1QBqLQAARw0EIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzYAQsgA0EANgIAIAZBAWohAUEQDAQLIAEgBEYEQEGTASECDNcBCwJAAkAgAS0AAEHDAGsODAAGBgYGBgYGBgYGAQYLIAFBAWohAUH5ACECDL4BCyABQQFqIQFB+gAhAgy9AQtBkgEhAiABIARGDdUBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQaDUAGotAABHDQIgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNYBCyADQQA2AgAgBkEBaiEBQSQMAgsgA0EANgIADAILIAEgBEYEQEGRASECDNQBCyABLQAAQcwARw0BIAFBAWohAUETCzoAKSADKAIEIQAgA0EANgIEIAMgACABEC4iAA0CDAELQQAhAiADQQA2AhwgAyABNgIUIANB/h82AhAgA0EGNgIMDNEBC0H4ACECDLcBCyADQZABNgIcIAMgATYCFCADIAA2AgxBACECDM8BC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ0AIABBFUYNASADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgzOAQtB9wAhAgy0AQsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDMwBCyABIARGBEBBjwEhAgzMAQsCQCABLQAAQSBGBEAgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GbHzYCECADQQY2AgxBACECDMwBC0ECIQIMsgELA0AgAS0AAEEgRw0CIAQgAUEBaiIBRw0AC0GOASECDMoBCyABIARGBEBBjQEhAgzKAQsCQCABLQAAQQlrDgRKAABKAAtB9QAhAgywAQsgAy0AKUEFRgRAQfYAIQIMsAELQfQAIQIMrwELIAEgBEYEQEGMASECDMgBCyADQRA2AgggAyABNgIEDAoLIAEgBEYEQEGLASECDMcBCwJAIAEtAABBCWsOBEcAAEcAC0HzACECDK0BCyABIARHBEAgA0EQNgIIIAMgATYCBEHxACECDK0BC0GKASECDMUBCwJAIAEgBEcEQANAIAEtAABBoNAAai0AACIAQQNHBEACQCAAQQFrDgJJAAQLQfAAIQIMrwELIAQgAUEBaiIBRw0AC0GIASEC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BCABQQFqIgFHDQALQfsAIQIMpwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMpgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMpQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0DIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMpAELIANBADYCHCADIAE2AhQgA0G8CjYCECADQQc2AgxBACECDKMBC0HPACECDIkBC0HRACECDIgBC0HnACECDIcBCyABIARGBEBB+gAhAgygAQsCQCABLQAAQQlrDgQgAAAgAAsgAUEBaiEBQeYAIQIMhgELIAEgBEYEQEH5ACECDJ8BCwJAIAEtAABBCWsOBB8AAB8AC0EAIQACQCADKAI4IgJFDQAgAigCOCICRQ0AIAMgAhEAACEACyAARQRAQeIBIQIMhgELIABBFUcEQCADQQA2AhwgAyABNgIUIANByQ02AhAgA0EaNgIMQQAhAgyfAQsgA0H4ADYCHCADIAE2AhQgA0HqGjYCECADQRU2AgxBACECDJ4BCyABIARHBEAgA0ENNgIIIAMgATYCBEHkACECDIUBC0H3ACECDJ0BCyABIARGBEBB9gAhAgydAQsCQAJAAkAgAS0AAEHIAGsOCwABCwsLCwsLCwsCCwsgAUEBaiEBQd0AIQIMhQELIAFBAWohAUHgACECDIQBCyABQQFqIQFB4wAhAgyDAQtB9QAhAiABIARGDZsBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbXVAGotAABHDQggAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJwBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIABEAgA0H0ADYCHCADIAE2AhQgAyAANgIMQQAhAgycAQtB4gAhAgyCAQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJwBC0HhACECDIIBCyADQfMANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMmgELIAMtACkiAEEja0ELSQ0JAkAgAEEGSw0AQQEgAHRBygBxRQ0ADAoLQQAhAiADQQA2AhwgAyABNgIUIANB7Qk2AhAgA0EINgIMDJkBC0HyACECIAEgBEYNmAEgAygCACIAIAQgAWtqIQUgASAAa0EBaiEGAkADQCABLQAAIABBs9UAai0AAEcNBSAAQQFGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMmQELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfEANgIcIAMgATYCFCADIAA2AgxBACECDJkBC0HfACECDH8LQQAhAAJAIAMoAjgiAkUNACACKAI0IgJFDQAgAyACEQAAIQALAkAgAARAIABBFUYNASADQQA2AhwgAyABNgIUIANB6g02AhAgA0EmNgIMQQAhAgyZAQtB3gAhAgx/CyADQfAANgIcIAMgATYCFCADQYAbNgIQIANBFTYCDEEAIQIMlwELIAMtAClBIUYNBiADQQA2AhwgAyABNgIUIANBkQo2AhAgA0EINgIMQQAhAgyWAQtB7wAhAiABIARGDZUBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDVAGotAABHDQIgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADJYBCyADKAIEIQAgA0IANwMAIAMgACAGQQFqIgEQKyIARQ0CIANB7QA2AhwgAyABNgIUIAMgADYCDEEAIQIMlQELIANBADYCAAsgAygCBCEAIANBADYCBCADIAAgARArIgBFDYABIANB7gA2AhwgAyABNgIUIAMgADYCDEEAIQIMkwELQdwAIQIMeQtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJMBC0HbACECDHkLIANB7AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyRAQsgAy0AKSIAQSNJDQAgAEEuRg0AIANBADYCHCADIAE2AhQgA0HJCTYCECADQQg2AgxBACECDJABC0HaACECDHYLIAEgBEYEQEHrACECDI8BCwJAIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMjwELQdkAIQIMdQsgASAERwRAIANBDjYCCCADIAE2AgRB2AAhAgx1C0HqACECDI0BCyABIARGBEBB6QAhAgyNAQsgAS0AAEEwayIAQf8BcUEKSQRAIAMgADoAKiABQQFqIQFB1wAhAgx0CyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeiADQegANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyABIARGBEBB5wAhAgyMAQsCQCABLQAAQS5GBEAgAUEBaiEBDAELIAMoAgQhACADQQA2AgQgAyAAIAEQLyIARQ17IANB5gA2AhwgAyABNgIUIAMgADYCDEEAIQIMjAELQdYAIQIMcgsgASAERgRAQeUAIQIMiwELQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIANgIcIAMgATYCFCADIAA2AgxBACECDI0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNfSADQeMANgIcIAMgATYCFCADIAA2AgxBACECDIwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNeyADQeQANgIcIAMgATYCFCADIAA2AgwMiwELQdQAIQIMcQsgAy0AKUEiRg2GAUHTACECDHALQQAhAAJAIAMoAjgiAkUNACACKAJEIgJFDQAgAyACEQAAIQALIABFBEBB1QAhAgxwCyAAQRVHBEAgA0EANgIcIAMgATYCFCADQaQNNgIQIANBITYCDEEAIQIMiQELIANB4QA2AhwgAyABNgIUIANB0Bo2AhAgA0EVNgIMQQAhAgyIAQsgASAERgRAQeAAIQIMiAELAkACQAJAAkACQCABLQAAQQprDgQBBAQABAsgAUEBaiEBDAELIAFBAWohASADQS9qLQAAQQFxRQ0BC0HSACECDHALIANBADYCHCADIAE2AhQgA0G2ETYCECADQQk2AgxBACECDIgBCyADQQA2AhwgAyABNgIUIANBthE2AhAgA0EJNgIMQQAhAgyHAQsgASAERgRAQd8AIQIMhwELIAEtAABBCkYEQCABQQFqIQEMCQsgAy0ALkHAAHENCCADQQA2AhwgAyABNgIUIANBthE2AhAgA0ECNgIMQQAhAgyGAQsgASAERgRAQd0AIQIMhgELIAEtAAAiAkENRgRAIAFBAWohAUHQACECDG0LIAEhACACQQlrDgQFAQEFAQsgBCABIgBGBEBB3AAhAgyFAQsgAC0AAEEKRw0AIABBAWoMAgtBACECIANBADYCHCADIAA2AhQgA0HKLTYCECADQQc2AgwMgwELIAEgBEYEQEHbACECDIMBCwJAIAEtAABBCWsOBAMAAAMACyABQQFqCyEBQc4AIQIMaAsgASAERgRAQdoAIQIMgQELIAEtAABBCWsOBAABAQABC0EAIQIgA0EANgIcIANBmhI2AhAgA0EHNgIMIAMgAUEBajYCFAx/CyADQYASOwEqQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB2QA2AhwgAyABNgIUIANB6ho2AhAgA0EVNgIMQQAhAgx+C0HNACECDGQLIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDHwLIAEgBEYEQEHZACECDHwLIAEtAABBIEcNPSABQQFqIQEgAy0ALkEBcQ09IANBADYCHCADIAE2AhQgA0HCHDYCECADQR42AgxBACECDHsLIAEgBEYEQEHYACECDHsLAkACQAJAAkACQCABLQAAIgBBCmsOBAIDAwABCyABQQFqIQFBLCECDGULIABBOkcNASADQQA2AhwgAyABNgIUIANB5xE2AhAgA0EKNgIMQQAhAgx9CyABQQFqIQEgA0Evai0AAEEBcUUNcyADLQAyQYABcUUEQCADQTJqIQIgAxA1QQAhAAJAIAMoAjgiBkUNACAGKAIoIgZFDQAgAyAGEQAAIQALAkACQCAADhZNTEsBAQEBAQEBAQEBAQEBAQEBAQEAAQsgA0EpNgIcIAMgATYCFCADQawZNgIQIANBFTYCDEEAIQIMfgsg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c3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw=="; let wasmBuffer; Object.defineProperty(module, "exports", { get: () => { - return wasmBuffer ? wasmBuffer : wasmBuffer = Buffer$3.from(wasmBase64, "base64"); + return wasmBuffer ? wasmBuffer : wasmBuffer = Buffer$5.from(wasmBase64, "base64"); } }); })); //#endregion //#region ../node_modules/undici/lib/llhttp/llhttp_simd-wasm.js var require_llhttp_simd_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const { Buffer: Buffer$2 } = __require("node:buffer"); + const { Buffer: Buffer$4 } = __require("node:buffer"); const wasmBase64 = "AGFzbQEAAAABJwdgAX8Bf2ADf39/AX9gAn9/AGABfwBgBH9/f38Bf2AAAGADf39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQAEA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAAzU0BQYAAAMAAAAAAAADAQMAAwMDAAACAAAAAAICAgICAgICAgIBAQEBAQEBAQEBAwAAAwAAAAQFAXABExMFAwEAAgYIAX8BQcDZBAsHxQcoBm1lbW9yeQIAC19pbml0aWFsaXplAAgZX19pbmRpcmVjdF9mdW5jdGlvbl90YWJsZQEAC2xsaHR0cF9pbml0AAkYbGxodHRwX3Nob3VsZF9rZWVwX2FsaXZlADcMbGxodHRwX2FsbG9jAAsGbWFsbG9jADkLbGxodHRwX2ZyZWUADARmcmVlAAwPbGxodHRwX2dldF90eXBlAA0VbGxodHRwX2dldF9odHRwX21ham9yAA4VbGxodHRwX2dldF9odHRwX21pbm9yAA8RbGxodHRwX2dldF9tZXRob2QAEBZsbGh0dHBfZ2V0X3N0YXR1c19jb2RlABESbGxodHRwX2dldF91cGdyYWRlABIMbGxodHRwX3Jlc2V0ABMObGxodHRwX2V4ZWN1dGUAFBRsbGh0dHBfc2V0dGluZ3NfaW5pdAAVDWxsaHR0cF9maW5pc2gAFgxsbGh0dHBfcGF1c2UAFw1sbGh0dHBfcmVzdW1lABgbbGxodHRwX3Jlc3VtZV9hZnRlcl91cGdyYWRlABkQbGxodHRwX2dldF9lcnJubwAaF2xsaHR0cF9nZXRfZXJyb3JfcmVhc29uABsXbGxodHRwX3NldF9lcnJvcl9yZWFzb24AHBRsbGh0dHBfZ2V0X2Vycm9yX3BvcwAdEWxsaHR0cF9lcnJub19uYW1lAB4SbGxodHRwX21ldGhvZF9uYW1lAB8SbGxodHRwX3N0YXR1c19uYW1lACAabGxodHRw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AXRrQT5qIQILIAEgAjYCHCABQgA3AhAgAkECdEH01wBqIQACQEHI1QAoAgAiA0EBIAJ0IgdxRQRAIAAgATYCAEHI1QAgAyAHcjYCACABIAA2AhggASABNgIIIAEgATYCDAwBCyAEQRkgAkEBdmtBACACQR9HG3QhAiAAKAIAIQACQANAIAAiAygCBEF4cSAERg0BIAJBHXYhACACQQF0IQIgAyAAQQRxakEQaiIHKAIAIgANAAsgByABNgIAIAEgAzYCGCABIAE2AgwgASABNgIIDAELIAMoAggiACABNgIMIAMgATYCCCABQQA2AhggASADNgIMIAEgADYCCAtB5NUAQeTVACgCAEEBayIAQX8gABs2AgALCwcAIAAtACgLBwAgAC0AKgsHACAALQArCwcAIAAtACkLBwAgAC8BNAsHACAALQAwC0ABBH8gACgCGCEBIAAvAS4hAiAALQAoIQMgACgCOCEEIAAQOCAAIAQ2AjggACADOgAoIAAgAjsBLiAAIAE2AhgLhocCAwd/A34BeyABIAJqIQQCQCAAIgMoAgwiAA0AIAMoAgQEQCADIAE2AgQLIwBBEGsiCSQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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DAgLQeMBDAcLQdcBDAYLQdgBDAULQdkBDAQLQdoBDAMLQdsBDAILQd0BDAELQdwBCyECA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAMCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAAn8CQAJAAkACfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAwJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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A0EXNgIcIAMgADYCDCADIAFBAWo2AhQM+AILIABBFUYNI0EAIQIgA0EANgIcIAMgATYCFCADQdYMNgIQIANBIzYCDAz3AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQwdCyADQRk2AhwgAyAANgIMIAMgAUEBajYCFAz2AgsgAygCBCEAQQAhAiADQQA2AgQgAyAAIAEQNCIARQRAIAFBAWohAQzvAgsgA0EaNgIcIAMgADYCDCADIAFBAWo2AhQM9QILIABBFUYNH0EAIQIgA0EANgIcIAMgATYCFCADQdAPNgIQIANBIjYCDAz0AgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDBsLIANBHDYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgzzAgsgAygCBCEAIANBADYCBCADIAAgARAzIgBFBEAgAUEBaiEBDOsCCyADQR02AhwgAyAANgIMIAMgAUEBajYCFEEAIQIM8gILIABBO0cNASABQQFqIQELQSYhAgzXAgtBACECIANBADYCHCADIAE2AhQgA0GfFTYCECADQQw2AgwM7wILIAEgBEcEQANAIAEtAABBIEcNhAIgBCABQQFqIgFHDQALQSwhAgzvAgtBLCECDO4CCyABIARGBEBBNCECDO4CCwJAAkADQAJAIAEtAABBCmsOBAIAAAMACyAEIAFBAWoiAUcNAAtBNCECDO8CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUNnwIgA0EyNgIcIAMgATYCFCADIAA2AgxBACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABEDEiAEUEQCABQQFqIQEMnwILIANBMjYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgztAgsgASAERwRAAkADQCABLQAAQTBrIgBB/wFxQQpPBEBBOiECDNcCCyADKQMgIgtCmbPmzJmz5swZVg0BIAMgC0IKfiIKNwMgIAogAK1C/wGDIgtCf4VWDQEgAyAKIAt8NwMgIAQgAUEBaiIBRw0AC0HAACECDO4CCyADKAIEIQAgA0EANgIEIAMgACABQQFqIgEQMSIADRcM4gILQcAAIQIM7AILIAEgBEYEQEHJACECDOwCCwJAA0ACQCABLQAAQQlrDhgAAqICogKpAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAgCiAgsgBCABQQFqIgFHDQALQckAIQIM7AILIAFBAWohASADQS9qLQAAQQFxDaUCIANBADYCHCADIAE2AhQgA0GXEDYCECADQQo2AgxBACECDOsCCyABIARHBEADQCABLQAAQSBHDRUgBCABQQFqIgFHDQALQfgAIQIM6wILQfgAIQIM6gILIANBAjoAKAw4C0EAIQIgA0EANgIcIANBvws2AhAgA0ECNgIMIAMgAUEBajYCFAzoAgtBACECDM4CC0ENIQIMzQILQRMhAgzMAgtBFSECDMsCC0EWIQIMygILQRghAgzJAgtBGSECDMgCC0EaIQIMxwILQRshAgzGAgtBHCECDMUCC0EdIQIMxAILQR4hAgzDAgtBHyECDMICC0EgIQIMwQILQSIhAgzAAgtBIyECDL8CC0ElIQIMvgILQeUAIQIMvQILIANBPTYCHCADIAE2AhQgAyAANgIMQQAhAgzVAgsgA0EbNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIM1AILIANBIDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNMCCyADQRM2AhwgAyABNgIUIANBmBo2AhAgA0EVNgIMQQAhAgzSAgsgA0ELNgIcIAMgATYCFCADQZgaNgIQIANBFTYCDEEAIQIM0QILIANBEDYCHCADIAE2AhQgA0GYGjYCECADQRU2AgxBACECDNACCyADQSA2AhwgAyABNgIUIANBpBw2AhAgA0EVNgIMQQAhAgzPAgsgA0ELNgIcIAMgATYCFCADQaQcNgIQIANBFTYCDEEAIQIMzgILIANBDDYCHCADIAE2AhQgA0GkHDYCECADQRU2AgxBACECDM0CC0EAIQIgA0EANgIcIAMgATYCFCADQd0ONgIQIANBEjYCDAzMAgsCQANAAkAgAS0AAEEKaw4EAAICAAILIAQgAUEBaiIBRw0AC0H9ASECDMwCCwJAAkAgAy0ANkEBRw0AQQAhAAJAIAMoAjgiAkUNACACKAJgIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRw0BIANB/AE2AhwgAyABNgIUIANB3Bk2AhAgA0EVNgIMQQAhAgzNAgtB3AEhAgyzAgsgA0EANgIcIAMgATYCFCADQfkLNgIQIANBHzYCDEEAIQIMywILAkACQCADLQAoQQFrDgIEAQALQdsBIQIMsgILQdQBIQIMsQILIANBAjoAMUEAIQACQCADKAI4IgJFDQAgAigCACICRQ0AIAMgAhEAACEACyAARQRAQd0BIQIMsQILIABBFUcEQCADQQA2AhwgAyABNgIUIANBtAw2AhAgA0EQNgIMQQAhAgzKAgsgA0H7ATYCHCADIAE2AhQgA0GBGjYCECADQRU2AgxBACECDMkCCyABIARGBEBB+gEhAgzJAgsgAS0AAEHIAEYNASADQQE6ACgLQcABIQIMrgILQdoBIQIMrQILIAEgBEcEQCADQQw2AgggAyABNgIEQdkBIQIMrQILQfkBIQIMxQILIAEgBEYEQEH4ASECDMUCCyABLQAAQcgARw0EIAFBAWohAUHYASECDKsCCyABIARGBEBB9wEhAgzEAgsCQAJAIAEtAABBxQBrDhAABQUFBQUFBQUFBQUFBQUBBQsgAUEBaiEBQdYBIQIMqwILIAFBAWohAUHXASECDKoCC0H2ASECIAEgBEYNwgIgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABButUAai0AAEcNAyAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMwwILIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgBFBEBB4wEhAgyqAgsgA0H1ATYCHCADIAE2AhQgAyAANgIMQQAhAgzCAgtB9AEhAiABIARGDcECIAMoAgAiACAEIAFraiEFIAEgAGtBAWohBgJAA0AgAS0AACAAQbjVAGotAABHDQIgAEEBRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADMICCyADQYEEOwEoIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARAuIgANAwwCCyADQQA2AgALQQAhAiADQQA2AhwgAyABNgIUIANB5R82AhAgA0EINgIMDL8CC0HVASECDKUCCyADQfMBNgIcIAMgATYCFCADIAA2AgxBACECDL0CC0EAIQACQCADKAI4IgJFDQAgAigCQCICRQ0AIAMgAhEAACEACyAARQ1uIABBFUcEQCADQQA2AhwgAyABNgIUIANBgg82AhAgA0EgNgIMQQAhAgy9AgsgA0GPATYCHCADIAE2AhQgA0HsGzYCECADQRU2AgxBACECDLwCCyABIARHBEAgA0ENNgIIIAMgATYCBEHTASECDKMCC0HyASECDLsCCyABIARGBEBB8QEhAgy7AgsCQAJAAkAgAS0AAEHIAGsOCwABCAgICAgICAgCCAsgAUEBaiEBQdABIQIMowILIAFBAWohAUHRASECDKICCyABQQFqIQFB0gEhAgyhAgtB8AEhAiABIARGDbkCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEG11QBqLQAARw0EIABBAkYNAyAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy5AgtB7wEhAiABIARGDbgCIAMoAgAiACAEIAFraiEGIAEgAGtBAWohBQNAIAEtAAAgAEGz1QBqLQAARw0DIABBAUYNAiAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy4AgtB7gEhAiABIARGDbcCIAMoAgAiACAEIAFraiEGIAEgAGtBAmohBQNAIAEtAAAgAEGw1QBqLQAARw0CIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBjYCAAy3AgsgAygCBCEAIANCADcDACADIAAgBUEBaiIBECsiAEUNAiADQewBNgIcIAMgATYCFCADIAA2AgxBACECDLYCCyADQQA2AgALIAMoAgQhACADQQA2AgQgAyAAIAEQKyIARQ2cAiADQe0BNgIcIAMgATYCFCADIAA2AgxBACECDLQCC0HPASECDJoCC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMtAILQc4BIQIMmgILIANB6wE2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyyAgsgASAERgRAQesBIQIMsgILIAEtAABBL0YEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQbI4NgIQIANBCDYCDEEAIQIMsQILQc0BIQIMlwILIAEgBEcEQCADQQ42AgggAyABNgIEQcwBIQIMlwILQeoBIQIMrwILIAEgBEYEQEHpASECDK8CCyABLQAAQTBrIgBB/wFxQQpJBEAgAyAAOgAqIAFBAWohAUHLASECDJYCCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNlwIgA0HoATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgASAERgRAQecBIQIMrgILAkAgAS0AAEEuRgRAIAFBAWohAQwBCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmAIgA0HmATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgtBygEhAgyUAgsgASAERgRAQeUBIQIMrQILQQAhAEEBIQVBASEHQQAhAgJAAkACQAJAAkACfwJAAkACQAJAAkACQAJAIAEtAABBMGsOCgoJAAECAwQFBggLC0ECDAYLQQMMBQtBBAwEC0EFDAMLQQYMAgtBBwwBC0EICyECQQAhBUEAIQcMAgtBCSECQQEhAEEAIQVBACEHDAELQQAhBUEBIQILIAMgAjoAKyABQQFqIQECQAJAIAMtAC5BEHENAAJAAkACQCADLQAqDgMBAAIECyAHRQ0DDAILIAANAQwCCyAFRQ0BCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNAiADQeIBNgIcIAMgATYCFCADIAA2AgxBACECDK8CCyADKAIEIQAgA0EANgIEIAMgACABEC8iAEUNmgIgA0HjATYCHCADIAE2AhQgAyAANgIMQQAhAgyuAgsgAygCBCEAIANBADYCBCADIAAgARAvIgBFDZgCIANB5AE2AhwgAyABNgIUIAMgADYCDAytAgtByQEhAgyTAgtBACEAAkAgAygCOCICRQ0AIAIoAkQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GkDTYCECADQSE2AgxBACECDK0CC0HIASECDJMCCyADQeEBNgIcIAMgATYCFCADQdAaNgIQIANBFTYCDEEAIQIMqwILIAEgBEYEQEHhASECDKsCCwJAIAEtAABBIEYEQCADQQA7ATQgAUEBaiEBDAELIANBADYCHCADIAE2AhQgA0GZETYCECADQQk2AgxBACECDKsCC0HHASECDJECCyABIARGBEBB4AEhAgyqAgsCQCABLQAAQTBrQf8BcSICQQpJBEAgAUEBaiEBAkAgAy8BNCIAQZkzSw0AIAMgAEEKbCIAOwE0IABB/v8DcSACQf//A3NLDQAgAyAAIAJqOwE0DAILQQAhAiADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMDKsCCyADQQA2AhwgAyABNgIUIANBlR42AhAgA0ENNgIMQQAhAgyqAgtBxgEhAgyQAgsgASAERgRAQd8BIQIMqQILAkAgAS0AAEEwa0H/AXEiAkEKSQRAIAFBAWohAQJAIAMvATQiAEGZM0sNACADIABBCmwiADsBNCAAQf7/A3EgAkH//wNzSw0AIAMgACACajsBNAwCC0EAIQIgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDAyqAgsgA0EANgIcIAMgATYCFCADQZUeNgIQIANBDTYCDEEAIQIMqQILQcUBIQIMjwILIAEgBEYEQEHeASECDKgCCwJAIAEtAABBMGtB/wFxIgJBCkkEQCABQQFqIQECQCADLwE0IgBBmTNLDQAgAyAAQQpsIgA7ATQgAEH+/wNxIAJB//8Dc0sNACADIAAgAmo7ATQMAgtBACECIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgwMqQILIANBADYCHCADIAE2AhQgA0GVHjYCECADQQ02AgxBACECDKgCC0HEASECDI4CCyABIARGBEBB3QEhAgynAgsCQAJAAkACQCABLQAAQQprDhcCAwMAAwMDAwMDAwMDAwMDAwMDAwMDAQMLIAFBAWoMBQsgAUEBaiEBQcMBIQIMjwILIAFBAWohASADQS9qLQAAQQFxDQggA0EANgIcIAMgATYCFCADQY0LNgIQIANBDTYCDEEAIQIMpwILIANBADYCHCADIAE2AhQgA0GNCzYCECADQQ02AgxBACECDKYCCyABIARHBEAgA0EPNgIIIAMgATYCBEEBIQIMjQILQdwBIQIMpQILAkACQANAAkAgAS0AAEEKaw4EAgAAAwALIAQgAUEBaiIBRw0AC0HbASECDKYCCyADKAIEIQAgA0EANgIEIAMgACABEC0iAEUEQCABQQFqIQEMBAsgA0HaATYCHCADIAA2AgwgAyABQQFqNgIUQQAhAgylAgsgAygCBCEAIANBADYCBCADIAAgARAtIgANASABQQFqCyEBQcEBIQIMigILIANB2QE2AhwgAyAANgIMIAMgAUEBajYCFEEAIQIMogILQcIBIQIMiAILIANBL2otAABBAXENASADQQA2AhwgAyABNgIUIANB5Bw2AhAgA0EZNgIMQQAhAgygAgsgASAERgRAQdkB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CyADIAU2AgAMkAILIANBADYCACAGQQFqIQFBGgw8C0HKASECIAEgBEYNjgIgAygCACIAIAQgAWtqIQUgASAAa0EDaiEGAkADQCABLQAAIABBjdUAai0AAEcNOyAAQQNGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMjwILIANBADYCACAGQQFqIQFBIQw7CyABIARGBEBByQEhAgyOAgsCQAJAIAEtAABBwQBrDhQAPT09PT09PT09PT09PT09PT09AT0LIAFBAWohAUGtASECDPUBCyABQQFqIQFBsAEhAgz0AQsgASAERgRAQcgBIQIMjQILAkACQCABLQAAQdUAaw4LADw8PDw8PDw8PAE8CyABQQFqIQFBrgEhAgz0AQsgAUEBaiEBQa8BIQIM8wELQccBIQIgASAERg2LAiADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw04IABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyMAgsgA0EANgIAIAZBAWohAUEqDDgLIAEgBEYEQEHGASECDIsCCyABLQAAQdAARw04IAFBAWohAUElDDcLQcUBIQIgASAERg2JAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEGB1QBqLQAARw02IABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyKAgsgA0EANgIAIAZBAWohAUEODDYLIAEgBEYEQEHEASECDIkCCyABLQAAQcUARw02IAFBAWohAUGrASECDO8BCyABIARGBEBBwwEhAgyIAgsCQAJAAkACQCABLQAAQcIAaw4PAAECOTk5OTk5OTk5OTkDOQsgAUEBaiEBQacBIQIM8QELIAFBAWohAUGoASECDPABCyABQQFqIQFBqQEhAgzvAQsgAUEBaiEBQaoBIQIM7gELQcIBIQIgASAERg2GAiADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEH+1ABqLQAARw0zIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyHAgsgA0EANgIAIAZBAWohAUEUDDMLQcEBIQIgASAERg2FAiADKAIAIgAgBCABa2ohBSABIABrQQRqIQYCQANA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BTYCAAzsAQsgA0EANgIAIAZBAWohAUEXDBgLQaYBIQIgASAERg3qASADKAIAIgAgBCABa2ohBSABIABrQQVqIQYCQANAIAEtAAAgAEHB1ABqLQAARw0XIABBBUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzrAQsgA0EANgIAIAZBAWohAUEYDBcLIAEgBEYEQEGlASECDOoBCwJAAkAgAS0AAEHJAGsOBwAZGRkZGQEZCyABQQFqIQFBiwEhAgzRAQsgAUEBaiEBQYwBIQIM0AELQaQBIQIgASAERg3oASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGm1QBqLQAARw0VIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzpAQsgA0EANgIAIAZBAWohAUEJDBULQaMBIQIgASAERg3nASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGk1QBqLQAARw0UIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzoAQsgA0EANgIAIAZBAWohAUEfDBQLQaIBIQIgASAERg3mASADKAIAIgAgBCABa2ohBSABIABrQQJqIQYCQANAIAEtAAAgAEG+1ABqLQAARw0TIABBAkYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAznAQsgA0EANgIAIAZBAWohAUECDBMLQaEBIQIgASAERg3lASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYDQCABLQAAIABBvNQAai0AAEcNESAAQQFGDQIgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM5QELIAEgBEYEQEGgASECDOUBC0EBIAEtAABB3wBHDREaIAFBAWohAUGHASECDMsBCyADQQA2AgAgBkEBaiEBQYgBIQIMygELQZ8BIQIgASAERg3iASADKAIAIgAgBCABa2ohBSABIABrQQhqIQYCQANAIAEtAAAgAEGE1QBqLQAARw0PIABBCEYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAzjAQsgA0EANgIAIAZBAWohAUEpDA8LQZ4BIQIgASAERg3hASADKAIAIgAgBCABa2ohBSABIABrQQNqIQYCQANAIAEtAAAgAEG41ABqLQAARw0OIABBA0YNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAziAQsgA0EANgIAIAZBAWohAUEtDA4LIAEgBEYEQEGdASECDOEBCyABLQAAQcUARw0OIAFBAWohAUGEASECDMcBCyABIARGBEBBnAEhAgzgAQsCQAJAIAEtAABBzABrDggADw8PDw8PAQ8LIAFBAWohAUGCASECDMcBCyABQQFqIQFBgwEhAgzGAQtBmwEhAiABIARGDd4BIAMoAgAiACAEIAFraiEFIAEgAGtBBGohBgJAA0AgAS0AACAAQbPUAGotAABHDQsgAEEERg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN8BCyADQQA2AgAgBkEBaiEBQSMMCwtBmgEhAiABIARGDd0BIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQbDUAGotAABHDQogAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADN4BCyADQQA2AgAgBkEBaiEBQQAMCgsgASAERgRAQZkBIQIM3QELAkACQCABLQAAQcgAaw4IAAwMDAwMDAEMCyABQQFqIQFB/QAhAgzEAQsgAUEBaiEBQYABIQIMwwELIAEgBEYEQEGYASECDNwBCwJAAkAgAS0AAEHOAGsOAwALAQsLIAFBAWohAUH+ACECDMMBCyABQQFqIQFB/wAhAgzCAQsgASAERgRAQZcBIQIM2wELIAEtAABB2QBHDQggAUEBaiEBQQgMBwtBlgEhAiABIARGDdkBIAMoAgAiACAEIAFraiEFIAEgAGtBA2ohBgJAA0AgAS0AACAAQazUAGotAABHDQYgAEEDRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNoBCyADQQA2AgAgBkEBaiEBQQUMBgtBlQEhAiABIARGDdgBIAMoAgAiACAEIAFraiEFIAEgAGtBBWohBgJAA0AgAS0AACAAQabUAGotAABHDQUgAEEFRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNkBCyADQQA2AgAgBkEBaiEBQRYMBQtBlAEhAiABIARGDdcBIAMoAgAiACAEIAFraiEFIAEgAGtBAmohBgJAA0AgAS0AACAAQaHVAGotAABHDQQgAEECRg0BIABBAWohACAEIAFBAWoiAUcNAAsgAyAFNgIADNgBCyADQQA2AgAgBkEBaiEBQRAMBAsgASAERgRAQZMBIQIM1wELAkACQCABLQAAQcMAaw4MAAYGBgYGBgYGBgYBBgsgAUEBaiEBQfkAIQIMvgELIAFBAWohAUH6ACECDL0BC0GSASECIAEgBEYN1QEgAygCACIAIAQgAWtqIQUgASAAa0EFaiEGAkADQCABLQAAIABBoNQAai0AAEcNAiAAQQVGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAM1gELIANBADYCACAGQQFqIQFBJAwCCyADQQA2AgAMAgsgASAERgRAQZEBIQIM1AELIAEtAABBzABHDQEgAUEBaiEBQRMLOgApIAMoAgQhACADQQA2AgQgAyAAIAEQLiIADQIMAQtBACECIANBADYCHCADIAE2AhQgA0H+HzYCECADQQY2AgwM0QELQfgAIQIMtwELIANBkAE2AhwgAyABNgIUIAMgADYCDEEAIQIMzwELQQAhAAJAIAMoAjgiAkUNACACKAJAIgJFDQAgAyACEQAAIQALIABFDQAgAEEVRg0BIANBADYCHCADIAE2AhQgA0GCDzYCECADQSA2AgxBACECDM4BC0H3ACECDLQBCyADQY8BNgIcIAMgATYCFCADQewbNgIQIANBFTYCDEEAIQIMzAELIAEgBEYEQEGPASECDMwBCwJAIAEtAABBIEYEQCABQQFqIQEMAQsgA0EANgIcIAMgATYCFCADQZsfNgIQIANBBjYCDEEAIQIMzAELQQIhAgyyAQsDQCABLQAAQSBHDQIgBCABQQFqIgFHDQALQY4BIQIMygELIAEgBEYEQEGNASECDMoBCwJAIAEtAABBCWsOBEoAAEoAC0H1ACECDLABCyADLQApQQVGBEBB9gAhAgywAQtB9AAhAgyvAQsgASAERgRAQYwBIQIMyAELIANBEDYCCCADIAE2AgQMCgsgASAERgRAQYsBIQIMxwELAkAgAS0AAEEJaw4ERwAARwALQfMAIQIMrQELIAEgBEcEQCADQRA2AgggAyABNgIEQfEAIQIMrQELQYoBIQIMxQELAkAgASAERwRAA0AgAS0AAEGg0ABqLQAAIgBBA0cEQAJAIABBAWsOAkkABAtB8AAhAgyvAQsgBCABQQFqIgFHDQALQYgBIQIMxgELQYgBIQIMxQELIANBADYCHCADIAE2AhQgA0HbIDYCECADQQc2AgxBACECDMQBCyABIARGBEBBiQEhAgzEAQsCQAJAAkAgAS0AAEGg0gBqLQAAQQFrDgNGAgABC0HyACECDKwBCyADQQA2AhwgAyABNgIUIANBtBI2AhAgA0EHNgIMQQAhAgzEAQtB6gAhAgyqAQsgASAERwRAIAFBAWohAUHvACECDKoBC0GHASECDMIBCyAEIAEiAEYEQEGGASECDMIBCyAALQAAIgFBL0YEQCAAQQFqIQFB7gAhAgypAQsgAUEJayICQRdLDQEgACEBQQEgAnRBm4CABHENQQwBCyAEIAEiAEYEQEGFASECDMEBCyAALQAAQS9HDQAgAEEBaiEBDAMLQQAhAiADQQA2AhwgAyAANgIUIANB2yA2AhAgA0EHNgIMDL8BCwJAAkACQAJAAkADQCABLQAAQaDOAGotAAAiAEEFRwRAAkACQCAAQQFrDghHBQYHCAAEAQgLQesAIQIMrQELIAFBAWohAUHtACECDKwBCyAEIAFBAWoiAUcNAAtBhAEhAgzDAQsgAUEBagwUCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDMEBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDMABCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNHiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDL8BCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy+AQsgASAERgRAQYMBIQIMvgELAkAgAS0AAEGgzgBqLQAAQQFrDgg+BAUGAAgCAwcLIAFBAWohAQtBAyECDKMBCyABQQFqDA0LQQAhAiADQQA2AhwgA0HREjYCECADQQc2AgwgAyABQQFqNgIUDLoBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQdsANgIcIAMgATYCFCADIAA2AgxBACECDLkBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQd0ANgIcIAMgATYCFCADIAA2AgxBACECDLgBCyADKAIEIQAgA0EANgIEIAMgACABECwiAEUNFiADQfoANgIcIAMgATYCFCADIAA2AgxBACECDLcBCyADQQA2AhwgAyABNgIUIANB+Q82AhAgA0EHNgIMQQAhAgy2AQtB7AAhAgycAQsgASAERgRAQYIBIQIMtQELIAFBAWoMAgsgASAERgRAQYEBIQIMtAELIAFBAWoMAQsgASAERg0BIAFBAWoLIQFBBCECDJgBC0GAASECDLABCwNAIAEtAABBoMwAai0AACIAQQJHBEAgAEEBRwRAQekAIQIMmQELDDELIAQgAUEBaiIBRw0AC0H/ACECDK8BCyABIARGBEBB/gAhAgyvAQsCQCABLQAAQQlrDjcvAwYvBAYGBgYGBgYGBgYGBgYGBgYGBgUGBgIGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYABgsgAUEBagshAUEFIQIMlAELIAFBAWoMBgsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgyrAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgyqAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQggA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgypAQsgA0EANgIcIAMgATYCFCADQY0UNgIQIANBBzYCDEEAIQIMqAELAkACQAJAAkADQCABLQAAQaDKAGotAAAiAEEFRwRAAkAgAEEBaw4GLgMEBQYABgtB6AAhAgyUAQsgBCABQQFqIgFHDQALQf0AIQIMqwELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB2wA2AhwgAyABNgIUIAMgADYCDEEAIQIMqgELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB3QA2AhwgAyABNgIUIAMgADYCDEEAIQIMqQELIAMoAgQhACADQQA2AgQgAyAAIAEQLCIARQ0HIANB+gA2AhwgAyABNgIUIAMgADYCDEEAIQIMqAELIANBADYCHCADIAE2AhQgA0HkCDYCECADQQc2AgxBACECDKcBCyABIARGDQEgAUEBagshAUEGIQIMjAELQfwAIQIMpAELAkACQAJAAkADQCABLQAAQaDIAGotAAAiAEEFRwRAIABBAWsOBCkCAwQFCyAEIAFBAWoiAUcNAAtB+wAhAgynAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HbADYCHCADIAE2AhQgAyAANgIMQQAhAgymAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0HdADYCHCADIAE2AhQgAyAANgIMQQAhAgylAQsgAygCBCEAIANBADYCBCADIAAgARAsIgBFDQMgA0H6ADYCHCADIAE2AhQgAyAANgIMQQAhAgykAQsgA0EANgIcIAMgATYCFCADQbwKNgIQIANBBzYCDEEAIQIMowELQc8AIQIMiQELQdEAIQIMiAELQecAIQIMhwELIAEgBEYEQEH6ACECDKABCwJAIAEtAABBCWsOBCAAACAACyABQQFqIQFB5gAhAgyGAQsgASAERgRAQfkAIQIMnwELAkAgAS0AAEEJaw4EHwAAHwALQQAhAAJAIAMoAjgiAkUNACACKAI4IgJFDQAgAyACEQAAIQALIABFBEBB4gEhAgyGAQsgAEEVRwRAIANBADYCHCADIAE2AhQgA0HJDTYCECADQRo2AgxBACECDJ8BCyADQfgANgIcIAMgATYCFCADQeoaNgIQIANBFTYCDEEAIQIMngELIAEgBEcEQCADQQ02AgggAyABNgIEQeQAIQIMhQELQfcAIQIMnQELIAEgBEYEQEH2ACECDJ0BCwJAAkACQCABLQAAQcgAaw4LAAELCwsLCwsLCwILCyABQQFqIQFB3QAhAgyFAQsgAUEBaiEBQeAAIQIMhAELIAFBAWohAUHjACECDIMBC0H1ACECIAEgBEYNmwEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBtdUAai0AAEcNCCAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMnAELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgAEQCADQfQANgIcIAMgATYCFCADIAA2AgxBACECDJwBC0HiACECDIIBC0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMnAELQeEAIQIMggELIANB8wA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyaAQsgAy0AKSIAQSNrQQtJDQkCQCAAQQZLDQBBASAAdEHKAHFFDQAMCgtBACECIANBADYCHCADIAE2AhQgA0HtCTYCECADQQg2AgwMmQELQfIAIQIgASAERg2YASADKAIAIgAgBCABa2ohBSABIABrQQFqIQYCQANAIAEtAAAgAEGz1QBqLQAARw0FIABBAUYNASAAQQFqIQAgBCABQQFqIgFHDQALIAMgBTYCAAyZAQsgAygCBCEAIANCADcDACADIAAgBkEBaiIBECsiAARAIANB8QA2AhwgAyABNgIUIAMgADYCDEEAIQIMmQELQd8AIQIMfwtBACEAAkAgAygCOCICRQ0AIAIoAjQiAkUNACADIAIRAAAhAAsCQCAABEAgAEEVRg0BIANBADYCHCADIAE2AhQgA0HqDTYCECADQSY2AgxBACECDJkBC0HeACECDH8LIANB8AA2AhwgAyABNgIUIANBgBs2AhAgA0EVNgIMQQAhAgyXAQsgAy0AKUEhRg0GIANBADYCHCADIAE2AhQgA0GRCjYCECADQQg2AgxBACECDJYBC0HvACECIAEgBEYNlQEgAygCACIAIAQgAWtqIQUgASAAa0ECaiEGAkADQCABLQAAIABBsNUAai0AAEcNAiAAQQJGDQEgAEEBaiEAIAQgAUEBaiIBRw0ACyADIAU2AgAMlgELIAMoAgQhACADQgA3AwAgAyAAIAZBAWoiARArIgBFDQIgA0HtADYCHCADIAE2AhQgAyAANgIMQQAhAgyVAQsgA0EANgIACyADKAIEIQAgA0EANgIEIAMgACABECsiAEUNgAEgA0HuADYCHCADIAE2AhQgAyAANgIMQQAhAgyTAQtB3AAhAgx5C0EAIQACQCADKAI4IgJFDQAgAigCNCICRQ0AIAMgAhEAACEACwJAIAAEQCAAQRVGDQEgA0EANgIcIAMgATYCFCADQeoNNgIQIANBJjYCDEEAIQIMkwELQdsAIQIMeQsgA0HsADYCHCADIAE2AhQgA0GAGzYCECADQRU2AgxBACECDJEBCyADLQApIgBBI0kNACAAQS5GDQAgA0EANgIcIAMgATYCFCADQckJNgIQIANBCDYCDEEAIQIMkAELQdoAIQIMdgsgASAERgRAQesAIQIMjwELAkAgAS0AAEEvRgRAIAFBAWohAQwBCyAD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ciBIVFRQL3gueCByZXF1ZXN0AEludmFsaWQgbWV0aG9kIGZvciBSVFNQL3gueCByZXF1ZXN0AEV4cGVjdGVkIFNPVVJDRSBtZXRob2QgZm9yIElDRS94LnggcmVxdWVzdABJbnZhbGlkIGNoYXIgaW4gdXJsIGZyYWdtZW50IHN0YXJ0AEV4cGVjdGVkIGRvdABTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3N0YXR1cwBJbnZhbGlkIHJlc3BvbnNlIHN0YXR1cwBFeHBlY3RlZCBMRiBhZnRlciBoZWFkZXJzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3Byb3RvY29sX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fcHJvdG9jb2wARW1wdHkgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyYWN0ZXIgaW4gQ29udGVudC1MZW5ndGgAVHJhbnNmZXItRW5jb2RpbmcgY2FuJ3QgYmUgcHJlc2VudCB3aXRoIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgc2l6ZQBFeHBlY3RlZCBMRiBhZnRlciBjaHVuayBzaXplAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBVbmV4cGVjdGVkIHdoaXRlc3BhY2UgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgaGVhZGVyIHZhbHVlAE1pc3NpbmcgZXhwZWN0ZWQgTEYgYWZ0ZXIgaGVhZGVyIHZhbHVlAEludmFsaWQgYFRyYW5zZmVyLUVuY29kaW5nYCBoZWFkZXIgdmFsdWUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciBjaHVuayBleHRlbnNpb24gdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZSB2YWx1ZQBJbnZhbGlkIHF1b3RlZC1wYWlyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fcHJvdG9jb2xfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUATWlzc2luZyBleHBlY3RlZCBDUiBhZnRlciByZXNwb25zZSBsaW5lAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX25hbWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBuYW1lAE1pc3NpbmcgZXhwZWN0ZWQgQ1IgYWZ0ZXIgY2h1bmsgZXh0ZW5zaW9uIG5hbWUASW52YWxpZCBzdGF0dXMgY29kZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABNaXNzaW5nIGV4cGVjdGVkIENSIGFmdGVyIGNodW5rIGRhdGEARXhwZWN0ZWQgTEYgYWZ0ZXIgY2h1bmsgZGF0YQBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AARGF0YSBhZnRlciBgQ29ubmVjdGlvbjogY2xvc2VgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBRVUVSWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAEV4cGVjdGVkIExGIGFmdGVyIENSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX1BST1RPQ09MX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19DT01QTEVURQBIUEVfQ0JfSEVBREVSX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9OQU1FX0NPTVBMRVRFAEhQRV9DQl9NRVNTQUdFX0NPTVBMRVRFAEhQRV9DQl9NRVRIT0RfQ09NUExFVEUASFBFX0NCX0hFQURFUl9GSUVMRF9DT01QTEVURQBERUxFVEUASFBFX0lOVkFMSURfRU9GX1NUQVRFAElOVkFMSURfU1NMX0NFUlRJRklDQVRFAFBBVVNFAE5PX1JFU1BPTlNFAFVOU1VQUE9SVEVEX01FRElBX1RZUEUAR09ORQBOT1RfQUNDRVBUQUJMRQBTRVJWSUNFX1VOQVZBSUxBQkxFAFJBTkdFX05PVF9TQVRJU0ZJQUJMRQBPUklHSU5fSVNfVU5SRUFDSEFCTEUAUkVTUE9OU0VfSVNfU1RBTEUAUFVSR0UATUVSR0UAUkVRVUVTVF9IRUFERVJfRklFTERTX1RPT19MQVJHRQBSRVFVRVNUX0hFQURFUl9UT09fTEFSR0UAUEFZTE9BRF9UT09fTEFSR0UASU5TVUZGSUNJRU5UX1NUT1JBR0UASFBFX1BBVVNFRF9VUEdSQURFAEhQRV9QQVVTRURfSDJfVVBHUkFERQBTT1VSQ0UAQU5OT1VOQ0UAVFJBQ0UASFBFX1VORVhQRUNURURfU1BBQ0UAREVTQ1JJQkUAVU5TVUJTQ1JJQkUAUkVDT1JEAEhQRV9JTlZBTElEX01FVEhPRABOT1RfRk9VTkQAUFJPUEZJTkQAVU5CSU5EAFJFQklORABVTkFVVEhPUklaRUQATUVUSE9EX05PVF9BTExPV0VEAEhUVFBfVkVSU0lPTl9OT1RfU1VQUE9SVEVEAEFMUkVBRFlfUkVQT1JURUQAQUNDRVBURUQATk9UX0lNUExFTUVOVEVEAExPT1BfREVURUNURUQASFBFX0NSX0VYUEVDVEVEAEhQRV9MRl9FWFBFQ1RFRABDUkVBVEVEAElNX1VTRUQASFBFX1BBVVNFRABUSU1FT1VUX09DQ1VSRUQAUEFZTUVOVF9SRVFVSVJFRABQUkVDT05ESVRJT05fUkVRVUlSRUQAUFJPWFlfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATkVUV09SS19BVVRIRU5USUNBVElPTl9SRVFVSVJFRABMRU5HVEhfUkVRVUlSRUQAU1NMX0NFUlRJRklDQVRFX1JFUVVJUkVEAFVQR1JBREVfUkVRVUlSRUQAUEFHRV9FWFBJUkVEAFBSRUNPTkRJVElPTl9GQUlMRUQARVhQRUNUQVRJT05fRkFJTEVEAFJFVkFMSURBVElPTl9GQUlMRUQAU1NMX0hBTkRTSEFLRV9GQUlMRUQATE9DS0VEAFRSQU5TRk9STUFUSU9OX0FQUExJRUQATk9UX01PRElGSUVEAE5PVF9FWFRFTkRFRABCQU5EV0lEVEhfTElNSVRfRVhDRUVERUQAU0lURV9JU19PVkVSTE9BREVEAEhFQUQARXhwZWN0ZWQgSFRUUC8sIFJUU1AvIG9yIElDRS8A5xUAAK8VAACkEgAAkhoAACYWAACeFAAA2xkAAHkVAAB+EgAA/hQAADYVAAALFgAA2BYAAPMSAABCGAAArBYAABIVAAAUFwAA7xcAAEgUAABxFwAAshoAAGsZAAB+GQAANRQAAIIaAABEFwAA/RYAAB4YAACHFwAAqhkAAJMSAAAHGAAALBcAAMoXAACkFwAA5xUAAOcVAABYFwAAOxgAAKASAAAtHAAAwxEAAEgRAADeEgAAQhMAAKQZAAD9EAAA9xUAAKUVAADvFgAA+BkAAEoWAABWFgAA9RUAAAoaAAAIGgAAARoAAKsVAABCEgAA1xAAAEwRAAAFGQAAVBYAAB4RAADKGQAAyBkAAE4WAAD/GAAAcRQAAPAVAADuFQAAlBkAAPwVAAC/GQAAmxkAAHwUAABDEQAAcBgAAJUUAAAnFAAAGRQAANUSAADUGQAARBYAAPcQAEG5OwsBAQBB0DsL4AEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBuj0LBAEAAAIAQdE9C14DBAMDAwMDAAADAwADAwADAwMDAwMDAwMDAAUAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAwADAEG6PwsEAQAAAgBB0T8LXgMAAwMDAwMAAAMDAAMDAAMDAwMDAwMDAwMABAAFAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMAQbDBAAsNbG9zZWVlcC1hbGl2ZQBBycEACwEBAEHgwQAL4AEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBBycMACwEBAEHgwwAL5wEBAQEBAQEBAQEBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAWNodW5rZWQAQfHFAAteAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQBB0McACyFlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AQYDIAAsgcmFuc2Zlci1lbmNvZGluZ3BncmFkZQ0KDQpTTQ0KDQoAQanIAAsFAQIAAQMAQcDIAAtfBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanKAAsFAQIAAQMAQcDKAAtfBAUFBgUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAQanMAAsEAQAAAQBBwcwAC14CAgACAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGpzgALBQECAAEDAEHAzgALXwQFAAAFBQUFBQUFBQUFBQYFBQUFBQUFBQUFBQUABQAHCAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQAFAAUABQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUAAAAFAEGp0AALBQEBAAEBAEHA0AALAQEAQdrQAAtBAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQanSAAsFAQEAAQEAQcDSAAsBAQBBytIACwYCAAAAAAIAQeHSAAs6AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBBoNQAC50BTk9VTkNFRUNLT1VUTkVDVEVURUNSSUJFTFVTSEVURUFEU0VBUkNIUkdFQ1RJVklUWUxFTkRBUlZFT1RJRllQVElPTlNDSFNFQVlTVEFUQ0hHRVVFUllPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFVFRQQ0VUU1BBRFRQLw=="; let wasmBuffer; Object.defineProperty(module, "exports", { get: () => { - return wasmBuffer ? wasmBuffer : wasmBuffer = Buffer$2.from(wasmBase64, "base64"); + return wasmBuffer ? wasmBuffer : wasmBuffer = Buffer$4.from(wasmBase64, "base64"); } }); })); //#endregion @@ -147775,6 +147993,7 @@ var require_webidl = /* @__PURE__ */ __commonJSMin(((exports, module) => { }; }; webidl.dictionaryConverter = function(converters) { + converters.sort((a, b) => (a.key > b.key) - (a.key < b.key)); return (dictionary, prefix, argument) => { const dict = {}; if (dictionary != null && webidl.util.Type(dictionary) !== OBJECT) throw webidl.errors.exception({ @@ -148738,7 +148957,7 @@ var require_util$4 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * @param {URL} url */ function includesCredentials(url) { - return !!(url.username && url.password); + return !!(url.username || url.password); } /** * @see https://html.spec.whatwg.org/multipage/document-sequences.html#traversable-navigable @@ -150095,6 +150314,7 @@ var require_client_h1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (reset != null) socket[kReset] = reset; if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) socket[kReset] = true; if (blocking) socket[kBlocking] = true; + if (socket.setTypeOfService) socket.setTypeOfService(request.typeOfService); let header = `${method} ${path} HTTP/1.1\r\n`; if (typeof host === "string") header += `host: ${host}\r\n`; else header += client[kHostHeader]; @@ -150791,6 +151011,7 @@ var require_client_h2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), "") === false) stream.pause(); }); stream.on("data", (chunk) => { + if (request.aborted || request.completed) return; if (request.onData(chunk) === false) stream.pause(); }); stream.once("end", () => { @@ -150831,6 +151052,7 @@ var require_client_h2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { }); stream.once("trailers", (trailers) => { if (request.aborted || request.completed) return; + stream.removeAllListeners("data"); request.onComplete(trailers); }); return true; @@ -150935,7 +151157,7 @@ var require_client_h2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/undici/lib/dispatcher/client.js var require_client = /* @__PURE__ */ __commonJSMin(((exports, module) => { const assert$23 = __require("node:assert"); - const net$1 = __require("node:net"); + const net$3 = __require("node:net"); const http$3 = __require("node:http"); const util = require_util$5(); const { ClientStats } = require_stats(); @@ -150982,7 +151204,7 @@ var require_client = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) throw new InvalidArgumentError("bodyTimeout must be a positive integer or zero"); if (connect != null && typeof connect !== "function" && typeof connect !== "object") throw new InvalidArgumentError("connect must be a function or an object"); if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) throw new InvalidArgumentError("maxRequestsPerClient must be a positive number"); - if (localAddress != null && (typeof localAddress !== "string" || net$1.isIP(localAddress) === 0)) throw new InvalidArgumentError("localAddress must be valid string IP address"); + if (localAddress != null && (typeof localAddress !== "string" || net$3.isIP(localAddress) === 0)) throw new InvalidArgumentError("localAddress must be valid string IP address"); if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) throw new InvalidArgumentError("maxResponseSize must be a positive number"); if (autoSelectFamilyAttemptTimeout != null && (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1)) throw new InvalidArgumentError("autoSelectFamilyAttemptTimeout must be a positive number"); if (allowH2 != null && typeof allowH2 !== "boolean") throw new InvalidArgumentError("allowH2 must be a valid boolean value"); @@ -151005,6 +151227,13 @@ var require_client = /* @__PURE__ */ __commonJSMin(((exports, module) => { } : void 0, ...connect }); + else if (socketPath != null) { + const customConnect = connect; + connect = (opts, callback) => customConnect({ + ...opts, + socketPath + }, callback); + } this[kUrl] = util.parseOrigin(url); this[kConnector] = connect; this[kPipelining] = pipelining != null ? pipelining : 1; @@ -151125,7 +151354,7 @@ var require_client = /* @__PURE__ */ __commonJSMin(((exports, module) => { const idx = hostname.indexOf("]"); assert$23(idx !== -1); const ip = hostname.substring(1, idx); - assert$23(net$1.isIPv6(ip)); + assert$23(net$3.isIPv6(ip)); hostname = ip; } client[kConnecting] = true; @@ -151263,6 +151492,7 @@ var require_client = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (client[kPending] === 0) return; if (client[kRunning] >= (getPipelining(client) || 1)) return; const request = client[kQueue][client[kPendingIdx]]; + if (request === null) return; if (client[kUrl].protocol === "https:" && client[kServerName] !== request.servername) { if (client[kRunning] > 0) return; client[kServerName] = request.servername; @@ -151543,7 +151773,8 @@ var require_pool = /* @__PURE__ */ __commonJSMin(((exports, module) => { ...util.deepClone(options), connect, allowH2, - clientTtl + clientTtl, + socketPath }; this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; this[kFactory] = factory; @@ -151724,7 +151955,8 @@ var require_round_robin_pool = /* @__PURE__ */ __commonJSMin(((exports, module) ...util.deepClone(options), connect, allowH2, - clientTtl + clientTtl, + socketPath }; this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; this[kFactory] = factory; @@ -151879,6 +152111,597 @@ var require_agent = /* @__PURE__ */ __commonJSMin(((exports, module) => { module.exports = Agent; })); //#endregion +//#region ../node_modules/undici/lib/core/socks5-utils.js +var require_socks5_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => { + const { Buffer: Buffer$3 } = __require("node:buffer"); + const net$2 = __require("node:net"); + const { InvalidArgumentError } = require_errors(); + /** + * Parse an address and determine its type + * @param {string} address - The address to parse + * @returns {{type: number, buffer: Buffer}} Address type and buffer + */ + function parseAddress(address) { + if (net$2.isIPv4(address)) { + const parts = address.split(".").map(Number); + return { + type: 1, + buffer: Buffer$3.from(parts) + }; + } + if (net$2.isIPv6(address)) return { + type: 4, + buffer: parseIPv6(address) + }; + const domainBuffer = Buffer$3.from(address, "utf8"); + if (domainBuffer.length > 255) throw new InvalidArgumentError("Domain name too long (max 255 bytes)"); + return { + type: 3, + buffer: Buffer$3.concat([Buffer$3.from([domainBuffer.length]), domainBuffer]) + }; + } + /** + * Parse IPv6 address to buffer + * @param {string} address - IPv6 address string + * @returns {Buffer} 16-byte buffer + */ + function parseIPv6(address) { + const buffer = Buffer$3.alloc(16); + const parts = address.split(":"); + let partIndex = 0; + let bufferIndex = 0; + const doubleColonIndex = address.indexOf("::"); + if (doubleColonIndex !== -1) { + const skipParts = 8 - parts.filter((p) => p.length > 0).length; + for (let i = 0; i < parts.length; i++) if (parts[i] === "" && i === doubleColonIndex / 3) bufferIndex += skipParts * 2; + else if (parts[i] !== "") { + const value = parseInt(parts[i], 16); + buffer.writeUInt16BE(value, bufferIndex); + bufferIndex += 2; + } + } else for (const part of parts) { + if (part === "") continue; + const value = parseInt(part, 16); + buffer.writeUInt16BE(value, partIndex * 2); + partIndex++; + } + return buffer; + } + /** + * Build a SOCKS5 address buffer + * @param {number} type - Address type (1=IPv4, 3=Domain, 4=IPv6) + * @param {Buffer} addressBuffer - The address data + * @param {number} port - Port number + * @returns {Buffer} Complete address buffer including type, address, and port + */ + function buildAddressBuffer(type, addressBuffer, port) { + const portBuffer = Buffer$3.allocUnsafe(2); + portBuffer.writeUInt16BE(port, 0); + return Buffer$3.concat([ + Buffer$3.from([type]), + addressBuffer, + portBuffer + ]); + } + /** + * Parse address from SOCKS5 response + * @param {Buffer} buffer - Buffer containing the address + * @param {number} offset - Starting offset in buffer + * @returns {{address: string, port: number, bytesRead: number}} + */ + function parseResponseAddress(buffer, offset = 0) { + if (buffer.length < offset + 1) throw new InvalidArgumentError("Buffer too small to contain address type"); + const addressType = buffer[offset]; + let address; + let currentOffset = offset + 1; + switch (addressType) { + case 1: + if (buffer.length < currentOffset + 6) throw new InvalidArgumentError("Buffer too small for IPv4 address"); + address = Array.from(buffer.subarray(currentOffset, currentOffset + 4)).join("."); + currentOffset += 4; + break; + case 3: { + if (buffer.length < currentOffset + 1) throw new InvalidArgumentError("Buffer too small for domain length"); + const domainLength = buffer[currentOffset]; + currentOffset += 1; + if (buffer.length < currentOffset + domainLength + 2) throw new InvalidArgumentError("Buffer too small for domain address"); + address = buffer.subarray(currentOffset, currentOffset + domainLength).toString("utf8"); + currentOffset += domainLength; + break; + } + case 4: { + if (buffer.length < currentOffset + 18) throw new InvalidArgumentError("Buffer too small for IPv6 address"); + const parts = []; + for (let i = 0; i < 8; i++) { + const value = buffer.readUInt16BE(currentOffset + i * 2); + parts.push(value.toString(16)); + } + address = parts.join(":"); + currentOffset += 16; + break; + } + default: throw new InvalidArgumentError(`Invalid address type: ${addressType}`); + } + if (buffer.length < currentOffset + 2) throw new InvalidArgumentError("Buffer too small for port"); + const port = buffer.readUInt16BE(currentOffset); + currentOffset += 2; + return { + address, + port, + bytesRead: currentOffset - offset + }; + } + /** + * Create error for SOCKS5 reply code + * @param {number} replyCode - SOCKS5 reply code + * @returns {Error} Appropriate error object + */ + function createReplyError(replyCode) { + const message = { + 1: "General SOCKS server failure", + 2: "Connection not allowed by ruleset", + 3: "Network unreachable", + 4: "Host unreachable", + 5: "Connection refused", + 6: "TTL expired", + 7: "Command not supported", + 8: "Address type not supported" + }[replyCode] || `Unknown SOCKS5 error code: ${replyCode}`; + const error = new Error(message); + error.code = `SOCKS5_${replyCode}`; + return error; + } + module.exports = { + parseAddress, + parseIPv6, + buildAddressBuffer, + parseResponseAddress, + createReplyError + }; +})); +//#endregion +//#region ../node_modules/undici/lib/core/socks5-client.js +var require_socks5_client = /* @__PURE__ */ __commonJSMin(((exports, module) => { + const { EventEmitter: EventEmitter$3 } = __require("node:events"); + const { Buffer: Buffer$2 } = __require("node:buffer"); + const { InvalidArgumentError, Socks5ProxyError } = require_errors(); + const { debuglog: debuglog$1 } = __require("node:util"); + const { parseAddress } = require_socks5_utils(); + const debug = debuglog$1("undici:socks5"); + const SOCKS_VERSION = 5; + const AUTH_METHODS = { + NO_AUTH: 0, + GSSAPI: 1, + USERNAME_PASSWORD: 2, + NO_ACCEPTABLE: 255 + }; + const COMMANDS = { + CONNECT: 1, + BIND: 2, + UDP_ASSOCIATE: 3 + }; + const ADDRESS_TYPES = { + IPV4: 1, + DOMAIN: 3, + IPV6: 4 + }; + const REPLY_CODES = { + SUCCEEDED: 0, + GENERAL_FAILURE: 1, + CONNECTION_NOT_ALLOWED: 2, + NETWORK_UNREACHABLE: 3, + HOST_UNREACHABLE: 4, + CONNECTION_REFUSED: 5, + TTL_EXPIRED: 6, + COMMAND_NOT_SUPPORTED: 7, + ADDRESS_TYPE_NOT_SUPPORTED: 8 + }; + const STATES = { + INITIAL: "initial", + HANDSHAKING: "handshaking", + AUTHENTICATING: "authenticating", + CONNECTING: "connecting", + CONNECTED: "connected", + ERROR: "error", + CLOSED: "closed" + }; + /** + * SOCKS5 client implementation + * Handles SOCKS5 protocol negotiation and connection establishment + */ + var Socks5Client = class extends EventEmitter$3 { + constructor(socket, options = {}) { + super(); + if (!socket) throw new InvalidArgumentError("socket is required"); + this.socket = socket; + this.options = options; + this.state = STATES.INITIAL; + this.buffer = Buffer$2.alloc(0); + this.authMethods = []; + if (options.username && options.password) this.authMethods.push(AUTH_METHODS.USERNAME_PASSWORD); + this.authMethods.push(AUTH_METHODS.NO_AUTH); + this.socket.on("data", this.onData.bind(this)); + this.socket.on("error", this.onError.bind(this)); + this.socket.on("close", this.onClose.bind(this)); + } + /** + * Handle incoming data from the socket + */ + onData(data) { + debug("received data", data.length, "bytes in state", this.state); + this.buffer = Buffer$2.concat([this.buffer, data]); + try { + switch (this.state) { + case STATES.HANDSHAKING: + this.handleHandshakeResponse(); + break; + case STATES.AUTHENTICATING: + this.handleAuthResponse(); + break; + case STATES.CONNECTING: + this.handleConnectResponse(); + break; + } + } catch (err) { + this.onError(err); + } + } + /** + * Handle socket errors + */ + onError(err) { + debug("socket error", err); + this.state = STATES.ERROR; + this.emit("error", err); + this.destroy(); + } + /** + * Handle socket close + */ + onClose() { + debug("socket closed"); + this.state = STATES.CLOSED; + this.emit("close"); + } + /** + * Destroy the client and underlying socket + */ + destroy() { + if (this.socket && !this.socket.destroyed) this.socket.destroy(); + } + /** + * Start the SOCKS5 handshake + */ + handshake() { + if (this.state !== STATES.INITIAL) throw new InvalidArgumentError("Handshake already started"); + debug("starting handshake with", this.authMethods.length, "auth methods"); + this.state = STATES.HANDSHAKING; + const request = Buffer$2.alloc(2 + this.authMethods.length); + request[0] = SOCKS_VERSION; + request[1] = this.authMethods.length; + this.authMethods.forEach((method, i) => { + request[2 + i] = method; + }); + this.socket.write(request); + } + /** + * Handle handshake response from server + */ + handleHandshakeResponse() { + if (this.buffer.length < 2) return; + const version = this.buffer[0]; + const method = this.buffer[1]; + if (version !== SOCKS_VERSION) throw new Socks5ProxyError(`Invalid SOCKS version: ${version}`, "UND_ERR_SOCKS5_VERSION"); + if (method === AUTH_METHODS.NO_ACCEPTABLE) throw new Socks5ProxyError("No acceptable authentication method", "UND_ERR_SOCKS5_AUTH_REJECTED"); + this.buffer = this.buffer.subarray(2); + debug("server selected auth method", method); + if (method === AUTH_METHODS.NO_AUTH) this.emit("authenticated"); + else if (method === AUTH_METHODS.USERNAME_PASSWORD) { + this.state = STATES.AUTHENTICATING; + this.sendAuthRequest(); + } else throw new Socks5ProxyError(`Unsupported authentication method: ${method}`, "UND_ERR_SOCKS5_AUTH_METHOD"); + } + /** + * Send username/password authentication request + */ + sendAuthRequest() { + const { username, password } = this.options; + if (!username || !password) throw new InvalidArgumentError("Username and password required for authentication"); + debug("sending username/password auth"); + const usernameBuffer = Buffer$2.from(username); + const passwordBuffer = Buffer$2.from(password); + if (usernameBuffer.length > 255 || passwordBuffer.length > 255) throw new InvalidArgumentError("Username or password too long"); + const request = Buffer$2.alloc(3 + usernameBuffer.length + passwordBuffer.length); + request[0] = 1; + request[1] = usernameBuffer.length; + usernameBuffer.copy(request, 2); + request[2 + usernameBuffer.length] = passwordBuffer.length; + passwordBuffer.copy(request, 3 + usernameBuffer.length); + this.socket.write(request); + } + /** + * Handle authentication response + */ + handleAuthResponse() { + if (this.buffer.length < 2) return; + const version = this.buffer[0]; + const status = this.buffer[1]; + if (version !== 1) throw new Socks5ProxyError(`Invalid auth sub-negotiation version: ${version}`, "UND_ERR_SOCKS5_AUTH_VERSION"); + if (status !== 0) throw new Socks5ProxyError("Authentication failed", "UND_ERR_SOCKS5_AUTH_FAILED"); + this.buffer = this.buffer.subarray(2); + debug("authentication successful"); + this.emit("authenticated"); + } + /** + * Send CONNECT command + * @param {string} address - Target address (IP or domain) + * @param {number} port - Target port + */ + connect(address, port) { + if (this.state === STATES.CONNECTED) throw new InvalidArgumentError("Already connected"); + debug("connecting to", address, port); + this.state = STATES.CONNECTING; + const request = this.buildConnectRequest(COMMANDS.CONNECT, address, port); + this.socket.write(request); + } + /** + * Build a SOCKS5 request + */ + buildConnectRequest(command, address, port) { + const { type: addressType, buffer: addressBuffer } = parseAddress(address); + const request = Buffer$2.alloc(4 + addressBuffer.length + 2); + request[0] = SOCKS_VERSION; + request[1] = command; + request[2] = 0; + request[3] = addressType; + addressBuffer.copy(request, 4); + request.writeUInt16BE(port, 4 + addressBuffer.length); + return request; + } + /** + * Handle CONNECT response + */ + handleConnectResponse() { + if (this.buffer.length < 4) return; + const version = this.buffer[0]; + const reply = this.buffer[1]; + const addressType = this.buffer[3]; + if (version !== SOCKS_VERSION) throw new Socks5ProxyError(`Invalid SOCKS version in reply: ${version}`, "UND_ERR_SOCKS5_REPLY_VERSION"); + let responseLength = 4; + if (addressType === ADDRESS_TYPES.IPV4) responseLength += 6; + else if (addressType === ADDRESS_TYPES.DOMAIN) { + if (this.buffer.length < 5) return; + responseLength += 1 + this.buffer[4] + 2; + } else if (addressType === ADDRESS_TYPES.IPV6) responseLength += 18; + else throw new Socks5ProxyError(`Invalid address type in reply: ${addressType}`, "UND_ERR_SOCKS5_ADDR_TYPE"); + if (this.buffer.length < responseLength) return; + if (reply !== REPLY_CODES.SUCCEEDED) throw new Socks5ProxyError(`SOCKS5 connection failed: ${this.getReplyErrorMessage(reply)}`, `UND_ERR_SOCKS5_REPLY_${reply}`); + let boundAddress; + let offset = 4; + if (addressType === ADDRESS_TYPES.IPV4) { + boundAddress = Array.from(this.buffer.subarray(offset, offset + 4)).join("."); + offset += 4; + } else if (addressType === ADDRESS_TYPES.DOMAIN) { + const domainLength = this.buffer[offset]; + offset += 1; + boundAddress = this.buffer.subarray(offset, offset + domainLength).toString(); + offset += domainLength; + } else if (addressType === ADDRESS_TYPES.IPV6) { + const parts = []; + for (let i = 0; i < 8; i++) { + const value = this.buffer.readUInt16BE(offset + i * 2); + parts.push(value.toString(16)); + } + boundAddress = parts.join(":"); + offset += 16; + } + const boundPort = this.buffer.readUInt16BE(offset); + this.buffer = this.buffer.subarray(responseLength); + this.state = STATES.CONNECTED; + debug("connected, bound address:", boundAddress, "port:", boundPort); + this.emit("connected", { + address: boundAddress, + port: boundPort + }); + } + /** + * Get human-readable error message for reply code + */ + getReplyErrorMessage(reply) { + switch (reply) { + case REPLY_CODES.GENERAL_FAILURE: return "General SOCKS server failure"; + case REPLY_CODES.CONNECTION_NOT_ALLOWED: return "Connection not allowed by ruleset"; + case REPLY_CODES.NETWORK_UNREACHABLE: return "Network unreachable"; + case REPLY_CODES.HOST_UNREACHABLE: return "Host unreachable"; + case REPLY_CODES.CONNECTION_REFUSED: return "Connection refused"; + case REPLY_CODES.TTL_EXPIRED: return "TTL expired"; + case REPLY_CODES.COMMAND_NOT_SUPPORTED: return "Command not supported"; + case REPLY_CODES.ADDRESS_TYPE_NOT_SUPPORTED: return "Address type not supported"; + default: return `Unknown error code: ${reply}`; + } + } + }; + module.exports = { + Socks5Client, + AUTH_METHODS, + COMMANDS, + ADDRESS_TYPES, + REPLY_CODES, + STATES + }; +})); +//#endregion +//#region ../node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +var require_socks5_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, module) => { + const net$1 = __require("node:net"); + const { URL: URL$1 } = __require("node:url"); + let tls; + const DispatcherBase = require_dispatcher_base(); + const { InvalidArgumentError } = require_errors(); + const { Socks5Client } = require_socks5_client(); + const { kDispatch, kClose, kDestroy } = require_symbols(); + const Pool = require_pool(); + const buildConnector = require_connect(); + const { debuglog } = __require("node:util"); + const debug = debuglog("undici:socks5-proxy"); + const kProxyUrl = Symbol("proxy url"); + const kProxyHeaders = Symbol("proxy headers"); + const kProxyAuth = Symbol("proxy auth"); + const kPool = Symbol("pool"); + const kConnector = Symbol("connector"); + let experimentalWarningEmitted = false; + /** + * SOCKS5 proxy agent for dispatching requests through a SOCKS5 proxy + */ + var Socks5ProxyAgent = class extends DispatcherBase { + constructor(proxyUrl, options = {}) { + super(); + if (!experimentalWarningEmitted) { + process.emitWarning("SOCKS5 proxy support is experimental and subject to change", "ExperimentalWarning"); + experimentalWarningEmitted = true; + } + if (!proxyUrl) throw new InvalidArgumentError("Proxy URL is mandatory"); + const url = typeof proxyUrl === "string" ? new URL$1(proxyUrl) : proxyUrl; + if (url.protocol !== "socks5:" && url.protocol !== "socks:") throw new InvalidArgumentError("Proxy URL must use socks5:// or socks:// protocol"); + this[kProxyUrl] = url; + this[kProxyHeaders] = options.headers || {}; + this[kProxyAuth] = { + username: options.username || (url.username ? decodeURIComponent(url.username) : null), + password: options.password || (url.password ? decodeURIComponent(url.password) : null) + }; + this[kConnector] = options.connect || buildConnector({ + ...options.proxyTls, + servername: options.proxyTls?.servername || url.hostname + }); + this[kPool] = null; + } + /** + * Create a SOCKS5 connection to the proxy + */ + async createSocks5Connection(targetHost, targetPort) { + const proxyHost = this[kProxyUrl].hostname; + const proxyPort = parseInt(this[kProxyUrl].port) || 1080; + debug("creating SOCKS5 connection to", proxyHost, proxyPort); + const socket = await new Promise((resolve, reject) => { + const onConnect = () => { + socket.removeListener("error", onError); + resolve(socket); + }; + const onError = (err) => { + socket.removeListener("connect", onConnect); + reject(err); + }; + const socket = net$1.connect({ + host: proxyHost, + port: proxyPort + }); + socket.once("connect", onConnect); + socket.once("error", onError); + }); + const socks5Client = new Socks5Client(socket, this[kProxyAuth]); + socks5Client.on("error", (err) => { + debug("SOCKS5 error:", err); + socket.destroy(); + }); + await socks5Client.handshake(); + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + reject(/* @__PURE__ */ new Error("SOCKS5 authentication timeout")); + }, 5e3); + const onAuthenticated = () => { + clearTimeout(timeout); + socks5Client.removeListener("error", onError); + resolve(); + }; + const onError = (err) => { + clearTimeout(timeout); + socks5Client.removeListener("authenticated", onAuthenticated); + reject(err); + }; + if (socks5Client.state === "authenticated") { + clearTimeout(timeout); + resolve(); + } else { + socks5Client.once("authenticated", onAuthenticated); + socks5Client.once("error", onError); + } + }); + await socks5Client.connect(targetHost, targetPort); + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + reject(/* @__PURE__ */ new Error("SOCKS5 connection timeout")); + }, 5e3); + const onConnected = (info) => { + debug("SOCKS5 tunnel established to", targetHost, targetPort, "via", info); + clearTimeout(timeout); + socks5Client.removeListener("error", onError); + resolve(); + }; + const onError = (err) => { + clearTimeout(timeout); + socks5Client.removeListener("connected", onConnected); + reject(err); + }; + socks5Client.once("connected", onConnected); + socks5Client.once("error", onError); + }); + return socket; + } + /** + * Dispatch a request through the SOCKS5 proxy + */ + async [kDispatch](opts, handler) { + const { origin } = opts; + debug("dispatching request to", origin, "via SOCKS5"); + try { + if (!this[kPool] || this[kPool].destroyed || this[kPool].closed) this[kPool] = new Pool(origin, { + pipelining: opts.pipelining, + connections: opts.connections, + connect: async (connectOpts, callback) => { + try { + const url = new URL$1(origin); + const targetHost = url.hostname; + const targetPort = parseInt(url.port) || (url.protocol === "https:" ? 443 : 80); + debug("establishing SOCKS5 connection to", targetHost, targetPort); + const socket = await this.createSocks5Connection(targetHost, targetPort); + let finalSocket = socket; + if (url.protocol === "https:") { + if (!tls) tls = __require("node:tls"); + debug("upgrading to TLS"); + finalSocket = tls.connect({ + socket, + servername: targetHost, + ...connectOpts.tls || {} + }); + await new Promise((resolve, reject) => { + finalSocket.once("secureConnect", resolve); + finalSocket.once("error", reject); + }); + } + callback(null, finalSocket); + } catch (err) { + debug("SOCKS5 connection error:", err); + callback(err); + } + } + }); + return this[kPool][kDispatch](opts, handler); + } catch (err) { + debug("dispatch error:", err); + if (typeof handler.onError === "function") handler.onError(err); + else throw err; + } + } + async [kClose]() { + if (this[kPool]) await this[kPool].close(); + } + async [kDestroy](err) { + if (this[kPool]) await this[kPool].destroy(err); + } + }; + module.exports = Socks5ProxyAgent; +})); +//#endregion //#region ../node_modules/undici/lib/dispatcher/proxy-agent.js var require_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { kProxy, kClose, kDestroy, kDispatch } = require_symbols(); @@ -151889,6 +152712,7 @@ var require_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, module) => { const buildConnector = require_connect(); const Client = require_client(); const { channels } = require_diagnostics(); + const Socks5ProxyAgent = require_socks5_proxy_agent(); const kAgent = Symbol("proxy agent"); const kClient = Symbol("proxy client"); const kProxyHeaders = Symbol("proxy headers"); @@ -151970,6 +152794,14 @@ var require_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, module) => { const agentFactory = opts.factory || defaultAgentFactory; const factory = (origin, options) => { const { protocol } = new URL(origin); + if (this[kProxy].protocol === "socks5:" || this[kProxy].protocol === "socks:") return new Socks5ProxyAgent(this[kProxy].uri, { + headers: this[kProxyHeaders], + connect, + factory: agentFactory, + username: opts.username || username, + password: opts.password || password, + proxyTls: opts.proxyTls + }); if (!this[kTunnelProxy] && protocol === "http:" && this[kProxy].protocol === "http:") return new Http1ProxyWrapper(this[kProxy].uri, { headers: this[kProxyHeaders], connect, @@ -151977,11 +152809,16 @@ var require_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, module) => { }); return agentFactory(origin, options); }; - this[kClient] = clientFactory(url, { connect }); + if (protocol === "socks5:" || protocol === "socks:") this[kClient] = null; + else this[kClient] = clientFactory(url, { connect }); this[kAgent] = new Agent({ ...opts, factory, connect: async (opts, callback) => { + if (!this[kClient]) { + callback(new InvalidArgumentError("Cannot establish tunnel connection without a proxy client")); + return; + } let requestedPath = opts.host; if (!opts.port) requestedPath += `:${defaultProtocolPort(opts.protocol)}`; try { @@ -152048,10 +152885,14 @@ var require_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, module) => { else return new URL(opts.uri); } [kClose]() { - return Promise.all([this[kAgent].close(), this[kClient].close()]); + const promises = [this[kAgent].close()]; + if (this[kClient]) promises.push(this[kClient].close()); + return Promise.all(promises); } [kDestroy]() { - return Promise.all([this[kAgent].destroy(), this[kClient].destroy()]); + const promises = [this[kAgent].destroy()]; + if (this[kClient]) promises.push(this[kClient].destroy()); + return Promise.all(promises); } }; /** @@ -152147,9 +152988,8 @@ var require_env_http_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, modu for (let i = 0; i < this.#noProxyEntries.length; i++) { const entry = this.#noProxyEntries[i]; if (entry.port && entry.port !== port) continue; - if (!/^[.*]/.test(entry.hostname)) { - if (hostname === entry.hostname) return false; - } else if (hostname.endsWith(entry.hostname.replace(/^\*/, ""))) return false; + if (hostname === entry.hostname) return false; + if (hostname.slice(-(entry.hostname.length + 1)) === `.${entry.hostname}`) return false; } return true; } @@ -152162,7 +153002,7 @@ var require_env_http_proxy_agent = /* @__PURE__ */ __commonJSMin(((exports, modu if (!entry) continue; const parsed = entry.match(/^(.+):(\d+)$/); noProxyEntries.push({ - hostname: (parsed ? parsed[1] : entry).toLowerCase(), + hostname: (parsed ? parsed[1] : entry).replace(/^\*?\./, "").toLowerCase(), port: parsed ? Number.parseInt(parsed[2], 10) : 0 }); } @@ -155469,7 +156309,7 @@ var require_redirect_handler = /* @__PURE__ */ __commonJSMin(((exports, module) if (Array.isArray(headers)) { for (let i = 0; i < headers.length; i += 2) if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) ret.push(headers[i], headers[i + 1]); } else if (headers && typeof headers === "object") { - const entries = typeof headers[Symbol.iterator] === "function" ? headers : Object.entries(headers); + const entries = util.hasSafeIterator(headers) ? headers : Object.entries(headers); for (const [key, value] of entries) if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) ret.push(key, value); } else assert$14(headers == null, "headers must be an object or an array"); return ret; @@ -155657,6 +156497,56 @@ var require_dns = /* @__PURE__ */ __commonJSMin(((exports, module) => { const DecoratorHandler = require_decorator_handler(); const { InvalidArgumentError, InformationalError } = require_errors(); const maxInt = Math.pow(2, 31) - 1; + function hasSafeIterator(headers) { + const prototype = Object.getPrototypeOf(headers); + return Object.prototype.hasOwnProperty.call(headers, Symbol.iterator) || prototype != null && prototype !== Object.prototype && typeof headers[Symbol.iterator] === "function"; + } + function isHostHeader(key) { + return typeof key === "string" && key.toLowerCase() === "host"; + } + function normalizeHeaders(headers) { + if (headers == null) return null; + if (Array.isArray(headers)) { + if (headers.length === 0 || !Array.isArray(headers[0])) return headers; + const normalized = []; + for (const header of headers) if (Array.isArray(header) && header.length === 2) normalized.push(header[0], header[1]); + else normalized.push(header); + return normalized; + } + if (typeof headers === "object" && hasSafeIterator(headers)) { + const normalized = []; + for (const header of headers) if (Array.isArray(header) && header.length === 2) normalized.push(header[0], header[1]); + else normalized.push(header); + return normalized; + } + return headers; + } + function hasHostHeader(headers) { + if (headers == null) return false; + if (Array.isArray(headers)) { + if (headers.length === 0) return false; + for (let i = 0; i < headers.length; i += 2) if (isHostHeader(headers[i])) return true; + return false; + } + if (typeof headers === "object") { + for (const key in headers) if (isHostHeader(key)) return true; + } + return false; + } + function withHostHeader(host, headers) { + const normalizedHeaders = normalizeHeaders(headers); + if (hasHostHeader(normalizedHeaders)) return normalizedHeaders; + if (Array.isArray(normalizedHeaders)) return [ + "host", + host, + ...normalizedHeaders + ]; + if (normalizedHeaders && typeof normalizedHeaders === "object") return { + host, + ...normalizedHeaders + }; + return { host }; + } var DNSStorage = class { #maxItems = 0; #records = /* @__PURE__ */ new Map(); @@ -155855,7 +156745,8 @@ var require_dns = /* @__PURE__ */ __commonJSMin(((exports, module) => { else port = ""; const dispatchOpts = { ...this.#opts, - origin: `${this.#origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}` + origin: `${this.#origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}`, + headers: withHostHeader(this.#origin.host, this.#opts.headers) }; this.#dispatch(dispatchOpts, this); return; @@ -155903,10 +156794,7 @@ var require_dns = /* @__PURE__ */ __commonJSMin(((exports, module) => { ...origDispatchOpts, servername: origin.hostname, origin: newOrigin.origin, - headers: { - host: origin.host, - ...origDispatchOpts.headers - } + headers: withHostHeader(origin.host, origDispatchOpts.headers) }, instance.getHandler({ origin, dispatch, @@ -155922,7 +156810,7 @@ var require_dns = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/undici/lib/util/cache.js var require_cache$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const { safeHTTPMethods, pathHasQueryOrFragment } = require_util$5(); + const { safeHTTPMethods, pathHasQueryOrFragment, hasSafeIterator } = require_util$5(); const { serializePathWithQuery } = require_util$5(); /** * @param {import('../../types/dispatcher.d.ts').default.DispatchOptions} opts @@ -155945,17 +156833,15 @@ var require_cache$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => { function normalizeHeaders(opts) { let headers; if (opts.headers == null) headers = {}; - else if (typeof opts.headers[Symbol.iterator] === "function") { + else if (typeof opts.headers === "object") { headers = {}; - for (const x of opts.headers) { + if (hasSafeIterator(opts.headers)) for (const x of opts.headers) { if (!Array.isArray(x)) throw new Error("opts.headers is not a valid header map"); const [key, val] = x; if (typeof key !== "string" || typeof val !== "string") throw new Error("opts.headers is not a valid header map"); headers[key.toLowerCase()] = val; } - } else if (typeof opts.headers === "object") { - headers = {}; - for (const key of Object.keys(opts.headers)) headers[key.toLowerCase()] = opts.headers[key]; + else for (const key of Object.keys(opts.headers)) headers[key.toLowerCase()] = opts.headers[key]; } else throw new Error("opts.headers is not an object"); return headers; } @@ -156597,38 +157483,60 @@ var require_cache_handler = /* @__PURE__ */ __commonJSMin(((exports, module) => deleteAt }; if (statusCode === 304) { + const handle304 = (cachedValue) => { + if (!cachedValue) return downstreamOnHeaders(); + value.statusCode = cachedValue.statusCode; + value.statusMessage = cachedValue.statusMessage; + value.etag = cachedValue.etag; + value.headers = { + ...cachedValue.headers, + ...strippedHeaders + }; + downstreamOnHeaders(); + this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); + if (!this.#writeStream || !cachedValue?.body) return; + if (typeof cachedValue.body.values === "function") { + const bodyIterator = cachedValue.body.values(); + const streamCachedBody = () => { + for (const chunk of bodyIterator) { + const full = this.#writeStream.write(chunk) === false; + this.#handler.onResponseData?.(controller, chunk); + if (full) break; + } + }; + this.#writeStream.on("error", function() { + handler.#writeStream = void 0; + handler.#store.delete(handler.#cacheKey); + }).on("drain", () => { + streamCachedBody(); + }).on("close", function() { + if (handler.#writeStream === this) handler.#writeStream = void 0; + }); + streamCachedBody(); + } else if (typeof cachedValue.body.on === "function") { + cachedValue.body.on("data", (chunk) => { + this.#writeStream.write(chunk); + this.#handler.onResponseData?.(controller, chunk); + }).on("end", () => { + this.#writeStream.end(); + }).on("error", () => { + this.#writeStream = void 0; + this.#store.delete(this.#cacheKey); + }); + this.#writeStream.on("error", function() { + handler.#writeStream = void 0; + handler.#store.delete(handler.#cacheKey); + }).on("close", function() { + if (handler.#writeStream === this) handler.#writeStream = void 0; + }); + } + }; /** * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue} */ - const cachedValue = this.#store.get(this.#cacheKey); - if (!cachedValue) return downstreamOnHeaders(); - value.statusCode = cachedValue.statusCode; - value.statusMessage = cachedValue.statusMessage; - value.etag = cachedValue.etag; - value.headers = { - ...cachedValue.headers, - ...strippedHeaders - }; - downstreamOnHeaders(); - this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); - if (!this.#writeStream || !cachedValue?.body) return; - const bodyIterator = cachedValue.body.values(); - const streamCachedBody = () => { - for (const chunk of bodyIterator) { - const full = this.#writeStream.write(chunk) === false; - this.#handler.onResponseData?.(controller, chunk); - if (full) break; - } - }; - this.#writeStream.on("error", function() { - handler.#writeStream = void 0; - handler.#store.delete(handler.#cacheKey); - }).on("drain", () => { - streamCachedBody(); - }).on("close", function() { - if (handler.#writeStream === this) handler.#writeStream = void 0; - }); - streamCachedBody(); + const result = this.#store.get(this.#cacheKey); + if (result && typeof result.then === "function") result.then(handle304); + else handle304(result); } else { if (typeof resHeaders.etag === "string" && isEtagUsable(resHeaders.etag)) value.etag = resHeaders.etag; this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); @@ -157186,15 +158094,14 @@ var require_cache$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (!revalidate && withinStaleWhileRevalidateWindow(result)) { sendCachedValue(handler, opts, result, age, null, true); queueMicrotask(() => { - let headers = { + const headers = { ...opts.headers, "if-modified-since": new Date(result.cachedAt).toUTCString() }; if (result.etag) headers["if-none-match"] = result.etag; - if (result.vary) headers = { - ...headers, - ...result.vary - }; + if (result.vary) { + for (const key in result.vary) if (result.vary[key] != null) headers[key] = result.vary[key]; + } dispatch({ ...opts, headers @@ -157212,15 +158119,14 @@ var require_cache$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { let withinStaleIfErrorThreshold = false; const staleIfErrorExpiry = result.cacheControlDirectives["stale-if-error"] ?? reqCacheControl?.["stale-if-error"]; if (staleIfErrorExpiry) withinStaleIfErrorThreshold = now < result.staleAt + staleIfErrorExpiry * 1e3; - let headers = { + const headers = { ...opts.headers, "if-modified-since": new Date(result.cachedAt).toUTCString() }; if (result.etag) headers["if-none-match"] = result.etag; - if (result.vary) headers = { - ...headers, - ...result.vary - }; + if (result.vary) { + for (const key in result.vary) if (result.vary[key] != null) headers[key] = result.vary[key]; + } return dispatch({ ...opts, headers @@ -157493,11 +158399,22 @@ var require_decompress = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/undici/lib/handler/deduplication-handler.js var require_deduplication_handler = /* @__PURE__ */ __commonJSMin(((exports, module) => { + const { RequestAbortedError } = require_errors(); /** * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler */ + const DEFAULT_MAX_BUFFER_SIZE = 5 * 1024 * 1024; + /** + * @typedef {Object} WaitingHandler + * @property {DispatchHandler} handler + * @property {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @property {Buffer[]} bufferedChunks + * @property {number} bufferedBytes + * @property {object | null} pendingTrailers + * @property {boolean} done + */ /** - * Handler that buffers response data and notifies multiple waiting handlers. + * Handler that forwards response events to multiple waiting handlers. * Used for request deduplication. * * @implements {DispatchHandler} @@ -157508,13 +158425,13 @@ var require_deduplication_handler = /* @__PURE__ */ __commonJSMin(((exports, mod */ #primaryHandler; /** - * @type {DispatchHandler[]} + * @type {WaitingHandler[]} */ #waitingHandlers = []; /** - * @type {Buffer[]} + * @type {number} */ - #chunks = []; + #maxBufferSize = DEFAULT_MAX_BUFFER_SIZE; /** * @type {number} */ @@ -157532,6 +158449,18 @@ var require_deduplication_handler = /* @__PURE__ */ __commonJSMin(((exports, mod */ #aborted = false; /** + * @type {boolean} + */ + #responseStarted = false; + /** + * @type {boolean} + */ + #responseDataStarted = false; + /** + * @type {boolean} + */ + #completed = false; + /** * @type {import('../../types/dispatcher.d.ts').default.DispatchController | null} */ #controller = null; @@ -157542,20 +158471,40 @@ var require_deduplication_handler = /* @__PURE__ */ __commonJSMin(((exports, mod /** * @param {DispatchHandler} primaryHandler The primary handler * @param {() => void} onComplete Callback when request completes + * @param {number} [maxBufferSize] Maximum paused buffer size per waiting handler */ - constructor(primaryHandler, onComplete) { + constructor(primaryHandler, onComplete, maxBufferSize = DEFAULT_MAX_BUFFER_SIZE) { this.#primaryHandler = primaryHandler; this.#onComplete = onComplete; + this.#maxBufferSize = maxBufferSize; } /** - * Add a waiting handler that will receive the buffered response + * Add a waiting handler that will receive response events. + * Returns false if deduplication can no longer safely attach this handler. + * * @param {DispatchHandler} handler + * @returns {boolean} */ addWaitingHandler(handler) { - this.#waitingHandlers.push(handler); + if (this.#completed || this.#responseDataStarted) return false; + const waitingHandler = this.#createWaitingHandler(handler); + const waitingController = waitingHandler.controller; + try { + handler.onRequestStart?.(waitingController, null); + if (waitingController.aborted) { + waitingHandler.done = true; + return true; + } + if (this.#responseStarted) handler.onResponseStart?.(waitingController, this.#statusCode, this.#headers, this.#statusMessage); + } catch { + waitingHandler.done = true; + return true; + } + if (!waitingController.aborted) this.#waitingHandlers.push(waitingHandler); + return true; } /** - * @param {() => void} abort + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller * @param {any} context */ onRequestStart(controller, context) { @@ -157578,26 +158527,81 @@ var require_deduplication_handler = /* @__PURE__ */ __commonJSMin(((exports, mod * @param {string} statusMessage */ onResponseStart(controller, statusCode, headers, statusMessage) { + this.#responseStarted = true; this.#statusCode = statusCode; this.#headers = headers; this.#statusMessage = statusMessage; this.#primaryHandler.onResponseStart?.(controller, statusCode, headers, statusMessage); + for (const waitingHandler of this.#waitingHandlers) { + const { handler, controller: waitingController } = waitingHandler; + if (waitingHandler.done || waitingController.aborted) { + waitingHandler.done = true; + continue; + } + try { + handler.onResponseStart?.(waitingController, statusCode, headers, statusMessage); + } catch {} + if (waitingController.aborted) waitingHandler.done = true; + } + this.#pruneDoneWaitingHandlers(); } /** * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller * @param {Buffer} chunk */ onResponseData(controller, chunk) { - this.#chunks.push(Buffer.from(chunk)); + if (this.#aborted || this.#completed) return; + this.#responseDataStarted = true; this.#primaryHandler.onResponseData?.(controller, chunk); + for (const waitingHandler of this.#waitingHandlers) { + const { handler, controller: waitingController } = waitingHandler; + if (waitingHandler.done || waitingController.aborted) { + waitingHandler.done = true; + continue; + } + if (waitingController.paused) { + this.#bufferWaitingChunk(waitingHandler, chunk); + continue; + } + try { + handler.onResponseData?.(waitingController, chunk); + } catch {} + if (waitingController.aborted) { + waitingHandler.done = true; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + } + } + this.#pruneDoneWaitingHandlers(); } /** * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller * @param {object} trailers */ onResponseEnd(controller, trailers) { + if (this.#aborted || this.#completed) return; + this.#completed = true; this.#primaryHandler.onResponseEnd?.(controller, trailers); - this.#notifyWaitingHandlers(); + for (const waitingHandler of this.#waitingHandlers) { + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + continue; + } + this.#flushWaitingHandler(waitingHandler); + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + continue; + } + if (waitingHandler.controller.paused && waitingHandler.bufferedChunks.length > 0) { + waitingHandler.pendingTrailers = trailers; + continue; + } + try { + waitingHandler.handler.onResponseEnd?.(waitingHandler.controller, trailers); + } catch {} + waitingHandler.done = true; + } + this.#pruneDoneWaitingHandlers(); this.#onComplete?.(); } /** @@ -157605,70 +158609,126 @@ var require_deduplication_handler = /* @__PURE__ */ __commonJSMin(((exports, mod * @param {Error} err */ onResponseError(controller, err) { + if (this.#completed) return; this.#aborted = true; + this.#completed = true; this.#primaryHandler.onResponseError?.(controller, err); - this.#notifyWaitingHandlersError(err); + for (const waitingHandler of this.#waitingHandlers) this.#errorWaitingHandler(waitingHandler, err); + this.#waitingHandlers = []; this.#onComplete?.(); } /** - * Notify all waiting handlers with the buffered response + * @param {DispatchHandler} handler + * @returns {WaitingHandler} */ - #notifyWaitingHandlers() { - const body = Buffer.concat(this.#chunks); - for (const handler of this.#waitingHandlers) { - const waitingController = { - resume() {}, - pause() {}, - get paused() { - return false; - }, - get aborted() { - return false; - }, - get reason() { - return null; - }, - abort() {} - }; - try { - handler.onRequestStart?.(waitingController, null); - if (waitingController.aborted) continue; - handler.onResponseStart?.(waitingController, this.#statusCode, this.#headers, this.#statusMessage); - if (waitingController.aborted) continue; - if (body.length > 0) handler.onResponseData?.(waitingController, body); - handler.onResponseEnd?.(waitingController, {}); - } catch {} + #createWaitingHandler(handler) { + /** @type {WaitingHandler} */ + const waitingHandler = { + handler, + controller: null, + bufferedChunks: [], + bufferedBytes: 0, + pendingTrailers: null, + done: false + }; + const state = { + aborted: false, + paused: false, + reason: null + }; + waitingHandler.controller = { + resume: () => { + if (state.aborted) return; + state.paused = false; + this.#flushWaitingHandler(waitingHandler); + if (this.#completed && waitingHandler.pendingTrailers && waitingHandler.bufferedChunks.length === 0 && !state.paused && !state.aborted) { + try { + waitingHandler.handler.onResponseEnd?.(waitingHandler.controller, waitingHandler.pendingTrailers); + } catch {} + waitingHandler.pendingTrailers = null; + waitingHandler.done = true; + } + this.#pruneDoneWaitingHandlers(); + }, + pause: () => { + if (!state.aborted) state.paused = true; + }, + get paused() { + return state.paused; + }, + get aborted() { + return state.aborted; + }, + get reason() { + return state.reason; + }, + abort: (reason) => { + state.aborted = true; + state.reason = reason ?? null; + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + } + }; + return waitingHandler; + } + /** + * @param {WaitingHandler} waitingHandler + * @param {Buffer} chunk + */ + #bufferWaitingChunk(waitingHandler, chunk) { + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + return; + } + const bufferedChunk = Buffer.from(chunk); + waitingHandler.bufferedChunks.push(bufferedChunk); + waitingHandler.bufferedBytes += bufferedChunk.length; + if (waitingHandler.bufferedBytes > this.#maxBufferSize) { + const err = new RequestAbortedError(`Deduplicated waiting handler exceeded maxBufferSize (${this.#maxBufferSize} bytes) while paused`); + this.#errorWaitingHandler(waitingHandler, err); } - this.#waitingHandlers = []; - this.#chunks = []; } /** - * Notify all waiting handlers of an error - * @param {Error} err + * @param {WaitingHandler} waitingHandler */ - #notifyWaitingHandlersError(err) { - for (const handler of this.#waitingHandlers) { - const waitingController = { - resume() {}, - pause() {}, - get paused() { - return false; - }, - get aborted() { - return true; - }, - get reason() { - return err; - }, - abort() {} - }; + #flushWaitingHandler(waitingHandler) { + const { handler, controller } = waitingHandler; + while (!waitingHandler.done && !controller.aborted && !controller.paused && waitingHandler.bufferedChunks.length > 0) { + const bufferedChunk = waitingHandler.bufferedChunks.shift(); + waitingHandler.bufferedBytes -= bufferedChunk.length; try { - handler.onRequestStart?.(waitingController, null); - handler.onResponseError?.(waitingController, err); + handler.onResponseData?.(controller, bufferedChunk); } catch {} + if (controller.aborted) { + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + break; + } } - this.#waitingHandlers = []; - this.#chunks = []; + } + /** + * @param {WaitingHandler} waitingHandler + * @param {Error} err + */ + #errorWaitingHandler(waitingHandler, err) { + if (waitingHandler.done) return; + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + try { + waitingHandler.controller.abort(err); + waitingHandler.handler.onResponseError?.(waitingHandler.controller, err); + } catch {} + } + #pruneDoneWaitingHandlers() { + this.#waitingHandlers = this.#waitingHandlers.filter((waitingHandler) => waitingHandler.done === false); } }; module.exports = DeduplicationHandler; @@ -157686,15 +158746,15 @@ var require_deduplicate = /* @__PURE__ */ __commonJSMin(((exports, module) => { * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor} */ module.exports = (opts = {}) => { - const { methods = ["GET"], skipHeaderNames = [], excludeHeaderNames = [] } = opts; + const { methods = ["GET"], skipHeaderNames = [], excludeHeaderNames = [], maxBufferSize = 5 * 1024 * 1024 } = opts; if (typeof opts !== "object" || opts === null) throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? "null" : typeof opts}`); if (!Array.isArray(methods)) throw new TypeError(`expected opts.methods to be an array, got ${typeof methods}`); for (const method of methods) if (!util.safeHTTPMethods.includes(method)) throw new TypeError(`expected opts.methods to only contain safe HTTP methods, got ${method}`); if (!Array.isArray(skipHeaderNames)) throw new TypeError(`expected opts.skipHeaderNames to be an array, got ${typeof skipHeaderNames}`); if (!Array.isArray(excludeHeaderNames)) throw new TypeError(`expected opts.excludeHeaderNames to be an array, got ${typeof excludeHeaderNames}`); + if (!Number.isFinite(maxBufferSize) || maxBufferSize <= 0) throw new TypeError(`expected opts.maxBufferSize to be a positive finite number, got ${maxBufferSize}`); const skipHeaderNamesSet = new Set(skipHeaderNames.map((name) => name.toLowerCase())); const excludeHeaderNamesSet = new Set(excludeHeaderNames.map((name) => name.toLowerCase())); - const safeMethodsToNotDeduplicate = util.safeHTTPMethods.filter((method) => methods.includes(method) === false); /** * Map of pending requests for deduplication * @type {Map} @@ -157702,7 +158762,7 @@ var require_deduplicate = /* @__PURE__ */ __commonJSMin(((exports, module) => { const pendingRequests = /* @__PURE__ */ new Map(); return (dispatch) => { return (opts, handler) => { - if (!opts.origin || safeMethodsToNotDeduplicate.includes(opts.method)) return dispatch(opts, handler); + if (!opts.origin || methods.includes(opts.method) === false) return dispatch(opts, handler); opts = { ...opts, headers: normalizeHeaders(opts) @@ -157713,8 +158773,8 @@ var require_deduplicate = /* @__PURE__ */ __commonJSMin(((exports, module) => { const dedupeKey = makeDeduplicationKey(makeCacheKey(opts), excludeHeaderNamesSet); const pendingHandler = pendingRequests.get(dedupeKey); if (pendingHandler) { - pendingHandler.addWaitingHandler(handler); - return true; + if (pendingHandler.addWaitingHandler(handler)) return true; + return dispatch(opts, handler); } const deduplicationHandler = new DeduplicationHandler(handler, () => { pendingRequests.delete(dedupeKey); @@ -157723,7 +158783,7 @@ var require_deduplicate = /* @__PURE__ */ __commonJSMin(((exports, module) => { key: dedupeKey, type: "removed" }); - }); + }, maxBufferSize); pendingRequests.set(dedupeKey, deduplicationHandler); if (pendingRequestsChannel.hasSubscribers) pendingRequestsChannel.publish({ size: pendingRequests.size, @@ -158062,7 +159122,7 @@ var require_headers$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { iteratorMixin, isValidHeaderName, isValidHeaderValue } = require_util$4(); const { webidl } = require_webidl(); const assert$11 = __require("node:assert"); - const util$5 = __require("node:util"); + const util$4 = __require("node:util"); /** * @param {number} code * @returns {code is (0x0a | 0x0d | 0x09 | 0x20)} @@ -158378,9 +159438,9 @@ var require_headers$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (list) return [...list]; return []; } - [util$5.inspect.custom](depth, options) { + [util$4.inspect.custom](depth, options) { options.depth ??= depth; - return `Headers ${util$5.formatWithOptions(options, this.#headersList.entries)}`; + return `Headers ${util$4.formatWithOptions(options, this.#headersList.entries)}`; } static getHeadersGuard(o) { return o.#guard; @@ -158419,12 +159479,12 @@ var require_headers$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { value: "Headers", configurable: true }, - [util$5.inspect.custom]: { enumerable: false } + [util$4.inspect.custom]: { enumerable: false } }); webidl.converters.HeadersInit = function(V, prefix, argument) { if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { const iterator = Reflect.get(V, Symbol.iterator); - if (!util$5.types.isProxy(V) && iterator === Headers.prototype.entries) try { + if (!util$4.types.isProxy(V) && iterator === Headers.prototype.entries) try { return getHeadersList(V).entriesList; } catch {} if (typeof iterator === "function") return webidl.converters["sequence>"](V, prefix, argument, iterator.bind(V)); @@ -159644,7 +160704,8 @@ var require_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => { request, processResponseEndOfBody: handleFetchDone, processResponse, - dispatcher: getRequestDispatcher(requestObject) + dispatcher: getRequestDispatcher(requestObject), + requestObject }); return p.promise; } @@ -159675,7 +160736,7 @@ var require_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => { const response = getResponseState(responseObject); if (response.body?.stream != null && isReadable(response.body.stream)) controller.error(error); } - function fetching({ request, processRequestBodyChunkLength, processRequestEndOfBody, processResponse, processResponseEndOfBody, processResponseConsumeBody, useParallelQueue = false, dispatcher = getGlobalDispatcher() }) { + function fetching({ request, processRequestBodyChunkLength, processRequestEndOfBody, processResponse, processResponseEndOfBody, processResponseConsumeBody, useParallelQueue = false, dispatcher = getGlobalDispatcher(), requestObject = null }) { assert$7(dispatcher); let taskDestination = null; let crossOriginIsolatedCapability = false; @@ -159694,7 +160755,8 @@ var require_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => { processResponseConsumeBody, processResponseEndOfBody, taskDestination, - crossOriginIsolatedCapability + crossOriginIsolatedCapability, + requestObject }; assert$7(!request.body || request.body.stream); if (request.window === "client") request.window = request.client?.globalObject?.constructor?.name === "Window" ? request.client : "no-window"; @@ -160156,7 +161218,7 @@ var require_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => { /** @type {import('../../..').Agent} */ const agent = fetchParams.controller.dispatcher; return new Promise((resolve, reject) => agent.dispatch({ - path: url.pathname + url.search, + path: url.href.slice(url.origin.length, url.hash.length ? -url.hash.length : void 0), origin: url.origin, method: request.method, body: agent.isMockActive ? request.body && (request.body.source || request.body.stream) : body, @@ -160248,6 +161310,23 @@ var require_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => { fetchParams.controller.terminate(error); reject(error); }, + onRequestUpgrade(_controller, status, headers, socket) { + if (socket.session != null && status !== 200 || socket.session == null && status !== 101) return false; + const headersList = new HeadersList(); + for (const [name, value] of Object.entries(headers)) { + if (value == null) continue; + const headerName = name.toLowerCase(); + if (Array.isArray(value)) for (const entry of value) headersList.append(headerName, String(entry), true); + else headersList.append(headerName, String(value), true); + } + resolve({ + status, + statusText: STATUS_CODES[status], + headersList, + socket + }); + return true; + }, onUpgrade(status, rawHeaders, socket) { if (socket.session != null && status !== 200 || socket.session == null && status !== 101) return false; const headersList = new HeadersList(); @@ -161758,11 +162837,13 @@ var require_util$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => { * @returns {boolean} */ function isValidClientWindowBits(value) { + if (value.length === 0) return false; for (let i = 0; i < value.length; i++) { const byte = value.charCodeAt(i); if (byte < 48 || byte > 57) return false; } - return true; + const num = Number.parseInt(value, 10); + return num >= 8 && num <= 15; } /** * @see https://whatpr.org/websockets/48/7b748d3...d5570f3.html#get-a-url-record @@ -162076,6 +163157,7 @@ var require_connection = /* @__PURE__ */ __commonJSMin(((exports, module) => { var require_permessage_deflate = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __require("node:zlib"); const { isValidClientWindowBits } = require_util$1(); + const { MessageSizeExceededError } = require_errors(); const tail = Buffer.from([ 0, 0, @@ -162084,15 +163166,31 @@ var require_permessage_deflate = /* @__PURE__ */ __commonJSMin(((exports, module ]); const kBuffer = Symbol("kBuffer"); const kLength = Symbol("kLength"); + const kDefaultMaxDecompressedSize = 4 * 1024 * 1024; var PerMessageDeflate = class { /** @type {import('node:zlib').InflateRaw} */ #inflate; #options = {}; - constructor(extensions) { + /** @type {number} */ + #maxDecompressedSize; + /** @type {boolean} */ + #aborted = false; + /** @type {Function|null} */ + #currentCallback = null; + /** + * @param {Map} extensions + * @param {{ maxDecompressedMessageSize?: number }} [options] + */ + constructor(extensions, options = {}) { this.#options.serverNoContextTakeover = extensions.has("server_no_context_takeover"); this.#options.serverMaxWindowBits = extensions.get("server_max_window_bits"); + this.#maxDecompressedSize = options.maxDecompressedMessageSize ?? kDefaultMaxDecompressedSize; } decompress(chunk, fin, callback) { + if (this.#aborted) { + callback(new MessageSizeExceededError()); + return; + } if (!this.#inflate) { let windowBits = Z_DEFAULT_WINDOWBITS; if (this.#options.serverMaxWindowBits) { @@ -162102,24 +163200,45 @@ var require_permessage_deflate = /* @__PURE__ */ __commonJSMin(((exports, module } windowBits = Number.parseInt(this.#options.serverMaxWindowBits); } - this.#inflate = createInflateRaw({ windowBits }); + try { + this.#inflate = createInflateRaw({ windowBits }); + } catch (err) { + callback(err); + return; + } this.#inflate[kBuffer] = []; this.#inflate[kLength] = 0; this.#inflate.on("data", (data) => { - this.#inflate[kBuffer].push(data); + if (this.#aborted) return; this.#inflate[kLength] += data.length; + if (this.#inflate[kLength] > this.#maxDecompressedSize) { + this.#aborted = true; + this.#inflate.removeAllListeners(); + this.#inflate.destroy(); + this.#inflate = null; + if (this.#currentCallback) { + const cb = this.#currentCallback; + this.#currentCallback = null; + cb(new MessageSizeExceededError()); + } + return; + } + this.#inflate[kBuffer].push(data); }); this.#inflate.on("error", (err) => { this.#inflate = null; callback(err); }); } + this.#currentCallback = callback; this.#inflate.write(chunk); if (fin) this.#inflate.write(tail); this.#inflate.flush(() => { + if (this.#aborted || !this.#inflate) return; const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]); this.#inflate[kBuffer].length = 0; this.#inflate[kLength] = 0; + this.#currentCallback = null; callback(null, full); }); } @@ -162136,6 +163255,7 @@ var require_receiver = /* @__PURE__ */ __commonJSMin(((exports, module) => { const { failWebsocketConnection } = require_connection(); const { WebsocketFrameSend } = require_frame(); const { PerMessageDeflate } = require_permessage_deflate(); + const { MessageSizeExceededError } = require_errors(); var ByteParser = class extends Writable$2 { #buffers = []; #fragmentsBytes = 0; @@ -162148,11 +163268,19 @@ var require_receiver = /* @__PURE__ */ __commonJSMin(((exports, module) => { #extensions; /** @type {import('./websocket').Handler} */ #handler; - constructor(handler, extensions) { + /** @type {{ maxDecompressedMessageSize?: number }} */ + #options; + /** + * @param {import('./websocket').Handler} handler + * @param {Map|null} extensions + * @param {{ maxDecompressedMessageSize?: number }} [options] + */ + constructor(handler, extensions, options = {}) { super(); this.#handler = handler; this.#extensions = extensions == null ? /* @__PURE__ */ new Map() : extensions; - if (this.#extensions.has("permessage-deflate")) this.#extensions.set("permessage-deflate", new PerMessageDeflate(extensions)); + this.#options = options; + if (this.#extensions.has("permessage-deflate")) this.#extensions.set("permessage-deflate", new PerMessageDeflate(extensions, options)); } /** * @param {Buffer} chunk @@ -162239,12 +163367,12 @@ var require_receiver = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (this.#byteOffset < 8) return callback(); const buffer = this.consume(8); const upper = buffer.readUInt32BE(0); - if (upper > 2 ** 31 - 1) { + const lower = buffer.readUInt32BE(4); + if (upper !== 0 || lower > 2 ** 31 - 1) { failWebsocketConnection(this.#handler, 1009, "Received payload length > 2^31 bytes."); return; } - const lower = buffer.readUInt32BE(4); - this.#info.payloadLength = (upper << 8) + lower; + this.#info.payloadLength = lower; this.#state = parserStates.READ_DATA; } else if (this.#state === parserStates.READ_DATA) { if (this.#byteOffset < this.#info.payloadLength) return callback(); @@ -162259,7 +163387,8 @@ var require_receiver = /* @__PURE__ */ __commonJSMin(((exports, module) => { } else { this.#extensions.get("permessage-deflate").decompress(body, this.#info.fin, (error, data) => { if (error) { - failWebsocketConnection(this.#handler, 1007, error.message); + const code = error instanceof MessageSizeExceededError ? 1009 : 1007; + failWebsocketConnection(this.#handler, code, error.message); return; } this.writeFragments(data); @@ -162575,6 +163704,8 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => { #binaryType; /** @type {import('./receiver').ByteParser} */ #parser; + /** @type {{ maxDecompressedMessageSize?: number }} */ + #options; /** * @param {string} url * @param {string|string[]} protocols @@ -162593,6 +163724,7 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => { if (protocols.length !== new Set(protocols.map((p) => p.toLowerCase())).size) throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); if (protocols.length > 0 && !protocols.every((p) => isValidSubprotocol(p))) throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); this.#url = new URL(urlRecord.href); + this.#options = { maxDecompressedMessageSize: options.maxDecompressedMessageSize }; const client = environmentSettingsObject.settingsObject; this.#handler.controller = establishWebSocketConnection(urlRecord, protocols, client, this.#handler, options); this.#handler.readyState = WebSocket.CONNECTING; @@ -162732,7 +163864,7 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => { */ #onConnectionEstablished(response, parsedExtensions) { this.#handler.socket = response.socket; - const parser = new ByteParser(this.#handler, parsedExtensions); + const parser = new ByteParser(this.#handler, parsedExtensions, this.#options); parser.on("drain", () => this.#handler.onParserDrain()); parser.on("error", (err) => this.#handler.onParserError(err)); this.#parser = parser; @@ -162876,6 +164008,17 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => { { key: "headers", converter: webidl.nullableConverter(webidl.converters.HeadersInit) + }, + { + key: "maxDecompressedMessageSize", + converter: webidl.nullableConverter((V) => { + V = webidl.converters["unsigned long long"](V); + if (V <= 0) throw webidl.errors.exception({ + header: "WebSocket constructor", + message: "maxDecompressedMessageSize must be greater than 0" + }); + return V; + }) } ]); webidl.converters["DOMString or sequence or WebSocketInit"] = function(V) { @@ -163807,6 +164950,7 @@ var require_undici = /* @__PURE__ */ __commonJSMin(((exports, module) => { const RoundRobinPool = require_round_robin_pool(); const Agent = require_agent(); const ProxyAgent = require_proxy_agent(); + const Socks5ProxyAgent = require_socks5_proxy_agent(); const EnvHttpProxyAgent = require_env_http_proxy_agent(); const RetryAgent = require_retry_agent(); const H2CClient = require_h2c_client(); @@ -163833,6 +164977,7 @@ var require_undici = /* @__PURE__ */ __commonJSMin(((exports, module) => { module.exports.RoundRobinPool = RoundRobinPool; module.exports.Agent = Agent; module.exports.ProxyAgent = ProxyAgent; + module.exports.Socks5ProxyAgent = Socks5ProxyAgent; module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent; module.exports.RetryAgent = RetryAgent; module.exports.H2CClient = H2CClient; @@ -165003,7 +166148,11 @@ function createWebDAVClient(config) { //#region ../node_modules/basic-ftp/dist/parseControlResponse.js var require_parseControlResponse = /* @__PURE__ */ __commonJSMin(((exports) => { Object.defineProperty(exports, "__esModule", { value: true }); - exports.positiveIntermediate = exports.positiveCompletion = exports.isMultiline = exports.isSingleLine = exports.parseControlResponse = void 0; + exports.parseControlResponse = parseControlResponse; + exports.isSingleLine = isSingleLine; + exports.isMultiline = isMultiline; + exports.positiveCompletion = positiveCompletion; + exports.positiveIntermediate = positiveIntermediate; const LF = "\n"; /** * Parse an FTP control response as a collection of messages. A message is a complete @@ -165035,29 +166184,24 @@ var require_parseControlResponse = /* @__PURE__ */ __commonJSMin(((exports) => { rest: tokenRegex ? lines.slice(startAt).join(LF) + LF : "" }; } - exports.parseControlResponse = parseControlResponse; function isSingleLine(line) { return /^\d\d\d(?:$| )/.test(line); } - exports.isSingleLine = isSingleLine; function isMultiline(line) { return /^\d\d\d-/.test(line); } - exports.isMultiline = isMultiline; /** * Return true if an FTP return code describes a positive completion. */ function positiveCompletion(code) { return code >= 200 && code < 300; } - exports.positiveCompletion = positiveCompletion; /** * Return true if an FTP return code describes a positive intermediate response. */ function positiveIntermediate(code) { return code >= 300 && code < 400; } - exports.positiveIntermediate = positiveIntermediate; function isNotBlank(str) { return str.trim() !== ""; } @@ -165468,7 +166612,9 @@ var require_FileInfo = /* @__PURE__ */ __commonJSMin(((exports) => { //#region ../node_modules/basic-ftp/dist/parseListDOS.js var require_parseListDOS = /* @__PURE__ */ __commonJSMin(((exports) => { Object.defineProperty(exports, "__esModule", { value: true }); - exports.transformList = exports.parseLine = exports.testLine = void 0; + exports.testLine = testLine; + exports.parseLine = parseLine; + exports.transformList = transformList; const FileInfo_1 = require_FileInfo(); /** * This parser is based on the FTP client library source code in Apache Commons Net provided @@ -165485,7 +166631,6 @@ var require_parseListDOS = /* @__PURE__ */ __commonJSMin(((exports) => { function testLine(line) { return /^\d{2}/.test(line) && RE_LINE.test(line); } - exports.testLine = testLine; /** * Parse a single line of a DOS-style directory listing. */ @@ -165505,17 +166650,17 @@ var require_parseListDOS = /* @__PURE__ */ __commonJSMin(((exports) => { file.rawModifiedAt = groups[1] + " " + groups[2]; return file; } - exports.parseLine = parseLine; function transformList(files) { return files; } - exports.transformList = transformList; })); //#endregion //#region ../node_modules/basic-ftp/dist/parseListUnix.js var require_parseListUnix = /* @__PURE__ */ __commonJSMin(((exports) => { Object.defineProperty(exports, "__esModule", { value: true }); - exports.transformList = exports.parseLine = exports.testLine = void 0; + exports.testLine = testLine; + exports.parseLine = parseLine; + exports.transformList = transformList; const FileInfo_1 = require_FileInfo(); const JA_MONTH = "月"; const JA_DAY = "日"; @@ -165559,7 +166704,6 @@ var require_parseListUnix = /* @__PURE__ */ __commonJSMin(((exports) => { function testLine(line) { return RE_LINE.test(line); } - exports.testLine = testLine; /** * Parse a single line of a Unix-style directory listing. */ @@ -165608,11 +166752,9 @@ var require_parseListUnix = /* @__PURE__ */ __commonJSMin(((exports) => { } return file; } - exports.parseLine = parseLine; function transformList(files) { return files; } - exports.transformList = transformList; function parseMode(r, w, x) { let value = 0; if (r !== "-") value += FileInfo_1.FileInfo.UnixPermission.Read; @@ -165626,7 +166768,10 @@ var require_parseListUnix = /* @__PURE__ */ __commonJSMin(((exports) => { //#region ../node_modules/basic-ftp/dist/parseListMLSD.js var require_parseListMLSD = /* @__PURE__ */ __commonJSMin(((exports) => { Object.defineProperty(exports, "__esModule", { value: true }); - exports.parseMLSxDate = exports.transformList = exports.parseLine = exports.testLine = void 0; + exports.testLine = testLine; + exports.parseLine = parseLine; + exports.transformList = transformList; + exports.parseMLSxDate = parseMLSxDate; const FileInfo_1 = require_FileInfo(); function parseSize(value, info) { info.size = parseInt(value, 10); @@ -165710,7 +166855,6 @@ var require_parseListMLSD = /* @__PURE__ */ __commonJSMin(((exports) => { function testLine(line) { return /^\S+=\S+;/.test(line) || line.startsWith(" "); } - exports.testLine = testLine; /** * Parse single line as MLSD listing, see specification at https://tools.ietf.org/html/rfc3659#section-7. */ @@ -165728,7 +166872,6 @@ var require_parseListMLSD = /* @__PURE__ */ __commonJSMin(((exports) => { } return info; } - exports.parseLine = parseLine; function transformList(files) { const nonLinksByID = /* @__PURE__ */ new Map(); for (const file of files) if (!file.isSymbolicLink && file.uniqueID !== void 0) nonLinksByID.set(file.uniqueID, file); @@ -165742,7 +166885,6 @@ var require_parseListMLSD = /* @__PURE__ */ __commonJSMin(((exports) => { } return resolvedFiles; } - exports.transformList = transformList; /** * Parse date as specified in https://tools.ietf.org/html/rfc3659#section-2.3. * @@ -165752,7 +166894,6 @@ var require_parseListMLSD = /* @__PURE__ */ __commonJSMin(((exports) => { function parseMLSxDate(fact) { return new Date(Date.UTC(+fact.slice(0, 4), +fact.slice(4, 6) - 1, +fact.slice(6, 8), +fact.slice(8, 10), +fact.slice(10, 12), +fact.slice(12, 14), +fact.slice(15, 18))); } - exports.parseMLSxDate = parseMLSxDate; })); //#endregion //#region ../node_modules/basic-ftp/dist/parseList.js @@ -165779,17 +166920,27 @@ var require_parseList = /* @__PURE__ */ __commonJSMin(((exports) => { }) : function(o, v) { o["default"] = v; }); - var __importStar = exports && exports.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; + var __importStar = exports && exports.__importStar || (function() { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function(o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + } + __setModuleDefault(result, mod); + return result; + }; + })(); Object.defineProperty(exports, "__esModule", { value: true }); - exports.parseList = void 0; + exports.parseList = parseList; /** * Available directory listing parsers. These are candidates that will be tested * in the order presented. The first candidate will be used to parse the whole list. @@ -165821,7 +166972,6 @@ var require_parseList = /* @__PURE__ */ __commonJSMin(((exports) => { const files = lines.map(parser.parseLine).filter((info) => info !== void 0); return parser.transformList(files); } - exports.parseList = parseList; })); //#endregion //#region ../node_modules/basic-ftp/dist/ProgressTracker.js @@ -165922,7 +167072,10 @@ var require_StringWriter = /* @__PURE__ */ __commonJSMin(((exports) => { //#region ../node_modules/basic-ftp/dist/netUtils.js var require_netUtils = /* @__PURE__ */ __commonJSMin(((exports) => { Object.defineProperty(exports, "__esModule", { value: true }); - exports.ipIsPrivateV4Address = exports.upgradeSocket = exports.describeAddress = exports.describeTLS = void 0; + exports.describeTLS = describeTLS; + exports.describeAddress = describeAddress; + exports.upgradeSocket = upgradeSocket; + exports.ipIsPrivateV4Address = ipIsPrivateV4Address; const tls_1$2 = __require("tls"); /** * Returns a string describing the encryption on a given socket instance. @@ -165934,7 +167087,6 @@ var require_netUtils = /* @__PURE__ */ __commonJSMin(((exports) => { } return "No encryption"; } - exports.describeTLS = describeTLS; /** * Returns a string describing the remote address of a socket. */ @@ -165942,7 +167094,6 @@ var require_netUtils = /* @__PURE__ */ __commonJSMin(((exports) => { if (socket.remoteFamily === "IPv6") return `[${socket.remoteAddress}]:${socket.remotePort}`; return `${socket.remoteAddress}:${socket.remotePort}`; } - exports.describeAddress = describeAddress; /** * Upgrade a socket connection with TLS. */ @@ -165960,7 +167111,6 @@ var require_netUtils = /* @__PURE__ */ __commonJSMin(((exports) => { }); }); } - exports.upgradeSocket = upgradeSocket; /** * Returns true if an IP is a private address according to https://tools.ietf.org/html/rfc1918#section-3. * This will handle IPv4-mapped IPv6 addresses correctly but return false for all other IPv6 addresses. @@ -165972,13 +167122,19 @@ var require_netUtils = /* @__PURE__ */ __commonJSMin(((exports) => { const octets = ip.split(".").map((o) => parseInt(o, 10)); return octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168 || ip === "127.0.0.1"; } - exports.ipIsPrivateV4Address = ipIsPrivateV4Address; })); //#endregion //#region ../node_modules/basic-ftp/dist/transfer.js var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { Object.defineProperty(exports, "__esModule", { value: true }); - exports.downloadTo = exports.uploadFrom = exports.connectForPassiveTransfer = exports.parsePasvResponse = exports.enterPassiveModeIPv4 = exports.parseEpsvResponse = exports.enterPassiveModeIPv6 = void 0; + exports.enterPassiveModeIPv6 = enterPassiveModeIPv6; + exports.parseEpsvResponse = parseEpsvResponse; + exports.enterPassiveModeIPv4 = enterPassiveModeIPv4; + exports.enterPassiveModeIPv4_forceControlHostIP = enterPassiveModeIPv4_forceControlHostIP; + exports.parsePasvResponse = parsePasvResponse; + exports.connectForPassiveTransfer = connectForPassiveTransfer; + exports.uploadFrom = uploadFrom; + exports.downloadTo = downloadTo; const netUtils_1 = require_netUtils(); const stream_1 = __require("stream"); const tls_1$1 = __require("tls"); @@ -165995,7 +167151,6 @@ var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { await connectForPassiveTransfer(controlHost, port, ftp); return res; } - exports.enterPassiveModeIPv6 = enterPassiveModeIPv6; /** * Parse an EPSV response. Returns only the port as in EPSV the host of the control connection is used. */ @@ -166006,7 +167161,6 @@ var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { if (Number.isNaN(port)) throw new Error(`Can't parse response to 'EPSV', port is not a number: ${message}`); return port; } - exports.parseEpsvResponse = parseEpsvResponse; /** * Prepare a data socket using passive mode over IPv4. */ @@ -166019,7 +167173,20 @@ var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { await connectForPassiveTransfer(target.host, target.port, ftp); return res; } - exports.enterPassiveModeIPv4 = enterPassiveModeIPv4; + /** + * Prepare a data socket using passive mode over IPv4. Ignore the IP provided by the PASV response, + * and use the control host IP. This is the same behaviour as with the more modern variant EPSV. Use + * this to fix issues around NAT or provide more security by preventing FTP bounce attacks. + */ + async function enterPassiveModeIPv4_forceControlHostIP(ftp) { + const res = await ftp.request("PASV"); + const target = parsePasvResponse(res.message); + if (!target) throw new Error("Can't parse PASV response: " + res.message); + const controlHost = ftp.socket.remoteAddress; + if (controlHost === void 0) throw new Error("Control socket is disconnected, can't get remote address."); + await connectForPassiveTransfer(controlHost, target.port, ftp); + return res; + } /** * Parse a PASV response. */ @@ -166031,7 +167198,6 @@ var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { port: (parseInt(groups[2], 10) & 255) * 256 + (parseInt(groups[3], 10) & 255) }; } - exports.parsePasvResponse = parsePasvResponse; function connectForPassiveTransfer(host, port, ftp) { return new Promise((resolve, reject) => { let socket = ftp._newSocket(); @@ -166062,7 +167228,6 @@ var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { }); }); } - exports.connectForPassiveTransfer = connectForPassiveTransfer; /** * Helps resolving/rejecting transfers. * @@ -166158,7 +167323,6 @@ var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { else if ((0, parseControlResponse_1.positiveIntermediate)(res.code)) resolver.onUnexpectedRequest(res); }); } - exports.uploadFrom = uploadFrom; function downloadTo(destination, config) { if (!config.ftp.dataSocket) throw new Error("Download will be initiated but no data connection is available."); const resolver = new TransferResolver(config.ftp, config.tracker); @@ -166181,7 +167345,6 @@ var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => { else if ((0, parseControlResponse_1.positiveIntermediate)(res.code)) resolver.onUnexpectedRequest(res); }); } - exports.downloadTo = downloadTo; /** * Calls a function immediately if a condition is met or subscribes to an event and calls * it once the event is emitted. @@ -166219,6 +167382,7 @@ var require_Client = /* @__PURE__ */ __commonJSMin(((exports) => { const fsOpen = (0, util_1.promisify)(fs_1.open); const fsClose = (0, util_1.promisify)(fs_1.close); const fsUnlink = (0, util_1.promisify)(fs_1.unlink); + const defaultClientOptions = { allowSeparateTransferHost: true }; const LIST_COMMANDS_DEFAULT = () => ["LIST -a", "LIST"]; const LIST_COMMANDS_MLSD = () => [ "MLSD", @@ -166234,10 +167398,10 @@ var require_Client = /* @__PURE__ */ __commonJSMin(((exports) => { * * @param timeout Timeout in milliseconds, use 0 for no timeout. Optional, default is 30 seconds. */ - constructor(timeout = 3e4) { + constructor(timeout = 3e4, options = defaultClientOptions) { this.availableListCommands = LIST_COMMANDS_DEFAULT(); this.ftp = new FtpContext_1.FTPContext(timeout); - this.prepareTransfer = this._enterFirstCompatibleMode([transfer_1.enterPassiveModeIPv6, transfer_1.enterPassiveModeIPv4]); + this.prepareTransfer = this._enterFirstCompatibleMode([transfer_1.enterPassiveModeIPv6, options.allowSeparateTransferHost ? transfer_1.enterPassiveModeIPv4 : transfer_1.enterPassiveModeIPv4_forceControlHostIP]); this.parseList = parseList_1.parseList; this._progressTracker = new ProgressTracker_1.ProgressTracker(); } @@ -166733,6 +167897,11 @@ var require_Client = /* @__PURE__ */ __commonJSMin(((exports) => { async _downloadFromWorkingDir(localDirPath) { await ensureLocalDirectory(localDirPath); for (const file of await this.list()) { + if (!file.name || (0, path_1.basename)(file.name) !== file.name) { + const safeName = JSON.stringify(file.name); + this.ftp.log(`Invalid filename from server listing, will skip file. (${safeName})`); + continue; + } const localPath = (0, path_1.join)(localDirPath, file.name); if (file.isDirectory) { await this.cd(file.name); @@ -166849,14 +168018,14 @@ var require_Client = /* @__PURE__ */ __commonJSMin(((exports) => { async function ensureLocalDirectory(path) { try { await fsStat(path); - } catch (err) { + } catch (_a) { await fsMkDir(path, { recursive: true }); } } async function ignoreError(func) { try { return await func(); - } catch (err) { + } catch (_a) { return; } } @@ -374601,7 +375770,7 @@ var require_body = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/sync-fetch/src/request.js var require_request = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const util$4 = __require("util"); + const util$3 = __require("util"); const { Body, checkBody, parseBody, createStream, _state } = require_body(); const { SyncHeaders } = require_headers(); var SyncRequest = class SyncRequest { @@ -374705,7 +375874,7 @@ var require_request = /* @__PURE__ */ __commonJSMin(((exports, module) => { checkBody(this); return new SyncRequest(this.url, this[_state]); } - [util$4.inspect.custom](depth, options) { + [util$3.inspect.custom](depth, options) { if (options.depth === null) options.depth = 2; options.colors ??= true; const properties = { @@ -374714,7 +375883,7 @@ var require_request = /* @__PURE__ */ __commonJSMin(((exports, module) => { signal: this.signal, url: this.url }; - return `Response ${util$4.formatWithOptions(options, properties)}`; + return `Response ${util$3.formatWithOptions(options, properties)}`; } }; Body.mixin(SyncRequest.prototype); @@ -374762,7 +375931,7 @@ var require_request = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#endregion //#region ../node_modules/sync-fetch/src/response.js var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => { - const util$3 = __require("util"); + const util$2 = __require("util"); const { Body, checkBody, parseBody, createStream, _state } = require_body(); const { deserializeError } = require_error(); const { SyncHeaders, initializeHeaders } = require_headers(); @@ -374827,7 +375996,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => { url: this.url }); } - [util$3.inspect.custom](depth, options) { + [util$2.inspect.custom](depth, options) { if (options.depth === null) options.depth = 2; options.colors ??= true; const properties = { @@ -374841,7 +376010,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => { type: this.type, url: this.url }; - return `Response ${util$3.formatWithOptions(options, properties)}`; + return `Response ${util$2.formatWithOptions(options, properties)}`; } }; Body.mixin(SyncResponse.prototype); @@ -374899,7 +376068,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => { //#region ../node_modules/sync-fetch/index.js var require_sync_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => { const exec$1 = __require("child_process").execFileSync; - const path$3 = __require("path"); + const path$2 = __require("path"); const { SyncHeaders } = require_headers(); const { FetchError, deserializeError } = require_error(); const { SyncRequest, serializeRequest } = require_request(); @@ -374911,7 +376080,7 @@ var require_sync_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => { else throw deserializeError(...response[0]); } function sendMessage(message) { - return exec$1(process.execPath, [path$3.join(__dirname, "worker.js")], { + return exec$1(process.execPath, [path$2.join(__dirname, "worker.js")], { windowsHide: true, maxBuffer: Infinity, input: JSON.stringify(message), @@ -374931,6 +376100,20 @@ const __dirname$4 = path.dirname(fileURLToPath(import.meta.url)); const ROOT_DIR = path.resolve(__dirname$4, "../"); const LIB_ROOT = path.join(ROOT_DIR, "spider/js"); const customRequire = createRequire$1(import.meta.url); +/** +* Patch Module.prototype.require to handle bundled modules in CJS context +* This allows native CJS modules (like those loaded via require('./lib.js')) to find +* bundled dependencies (axios, iconv-lite, etc.) which are exposed on globalThis. +*/ +const originalRequire = Module.prototype.require; +Module.prototype.require = function(id) { + if (id === "iconv-lite" && globalThis.iconv) return globalThis.iconv; + if (id === "axios" && globalThis.axios) return globalThis.axios; + if (id === "cheerio" && globalThis.cheerio) return globalThis.cheerio; + if (id === "qs" && globalThis.qs) return globalThis.qs; + if (id === "crypto-js" && globalThis.CryptoJS) return globalThis.CryptoJS; + return originalRequire.apply(this, arguments); +}; const rootRequire = (modulePath) => { if (modulePath === "iconv-lite") return globalThis.iconv; if (modulePath === "axios") return globalThis.axios; @@ -378530,7 +379713,7 @@ var require_tunnel$1 = /* @__PURE__ */ __commonJSMin(((exports) => { var https$1 = __require("https"); var events = __require("events"); var assert$1 = __require("assert"); - var util$2 = __require("util"); + var util$1 = __require("util"); exports.httpOverHttp = httpOverHttp; exports.httpsOverHttp = httpsOverHttp; exports.httpOverHttps = httpOverHttps; @@ -378580,7 +379763,7 @@ var require_tunnel$1 = /* @__PURE__ */ __commonJSMin(((exports) => { self.removeSocket(socket); }); } - util$2.inherits(TunnelingAgent, events.EventEmitter); + util$1.inherits(TunnelingAgent, events.EventEmitter); TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { var self = this; var options = mergeOptions({ request: req }, self.options, toOptions(host, port, localAddress)); @@ -378728,8 +379911,8 @@ var require_tunnel = /* @__PURE__ */ __commonJSMin(((exports, module) => { module.exports = require_tunnel$1(); })); //#endregion -//#region ../libs_drpy/jsonpathplus.min.js -var require_jsonpathplus_min = /* @__PURE__ */ __commonJSMin(((exports, module) => { +//#region shim/original-jsonpath.js +var require_original_jsonpath = /* @__PURE__ */ __commonJSMin(((exports, module) => { (function(e, t) { "object" == typeof exports && "undefined" != typeof module ? t(exports) : "function" == typeof define && define.amd ? define(["exports"], t) : t((e = "undefined" != typeof globalThis ? globalThis : e || self).JSONPath = {}); })(exports, function(e) { @@ -379975,13 +381158,21 @@ var require_jsonpathplus_min = /* @__PURE__ */ __commonJSMin(((exports, module) }); })); //#endregion -//#region ../libs_drpy/htmlParser.js +//#region shim/jsonpath-shim.js var import_tunnel = /* @__PURE__ */ __toESM(require_tunnel(), 1); +var import_original_jsonpath = /* @__PURE__ */ __toESM(require_original_jsonpath(), 1); +const JP = import_original_jsonpath.JSONPath || import_original_jsonpath.default?.JSONPath || import_original_jsonpath.default; +if (typeof globalThis !== "undefined") { + if (!globalThis.JSONPath) globalThis.JSONPath = {}; + if (typeof JP === "function") globalThis.JSONPath.JSONPath = JP; + else if (JP && JP.JSONPath) globalThis.JSONPath = JP; +} +//#endregion +//#region ../libs_drpy/htmlParser.js /** * HTML解析器工具 * 基于cheerio提供HTML和JSON解析功能,支持类似海阔视界的解析语法 */ -var import_jsonpathplus_min = require_jsonpathplus_min(); /** * JSONPath查询工具 */ @@ -382935,22 +384126,87 @@ var FileHeaderManager = class { headerRegex: /@header\(([\s\S]*?)\)/, createComment: (content) => `"""\n${content}\n"""`, topCommentsRegex: /^(\s*(#[^\n]*\n|'''[\s\S]*?'''|"""[\s\S]*?""")\s*)+/ + }, + ".php": { + start: "/*", + end: "*/", + regex: /(<\?php\s*)?(\s*\/\*[\s\S]*?\*\/)/, + headerRegex: /@header\(([\s\S]*?)\)/, + createComment: (content) => `/*\n${content}\n*/`, + topCommentsRegex: /(<\?php\s*)?(\s*(\/\/[^\n]*\n|\/\*[\s\S]*?\*\/)\s*)+/ + } + }; + /** + * Find the @header(...) block in the comment text + * Optimized state machine for parsing nested structures + * @param {string} text Comment text + * @param {string} ext File extension (.js or .py) + * @returns {Object|null} { start, end, content } + */ + static findHeaderBlock(text, ext) { + const startIndex = text.indexOf("@header("); + if (startIndex === -1) return null; + let index = startIndex + 8; + let balance = 1; + const len = text.length; + while (index < len) { + const char = text[index]; + if (char === "\"" || char === "'") { + const quote = char; + index++; + while (index < len) { + const c = text[index]; + if (c === "\\") index += 2; + else if (c === quote) { + index++; + break; + } else index++; + } + continue; + } else if (char === "(") balance++; + else if (char === ")") { + balance--; + if (balance === 0) return { + start: startIndex, + end: index + 1, + content: text.substring(startIndex + 8, index) + }; + } else if (char === "/") { + const next = text[index + 1]; + if (next === "/") { + index += 2; + const newline = text.indexOf("\n", index); + index = newline === -1 ? len : newline; + continue; + } else if (next === "*") { + index += 2; + const endComment = text.indexOf("*/", index); + if (endComment === -1) index = len; + else index = endComment + 2; + continue; + } + } else if (ext === ".py" && char === "#") { + const newline = text.indexOf("\n", index + 1); + index = newline === -1 ? len : newline; + continue; + } + index++; } - }; + return null; + } /** - * 解析JavaScript对象字面量(支持无引号属性名) + * 解析对象字符串 * @param {string} str 对象字符串 * @returns {Object} 解析后的对象 */ static parseObjectLiteral(str) { - const normalized = str.replace(/([{,]\s*)([a-zA-Z_$][\w$]*)(\s*:)/g, "$1\"$2\"$3").replace(/'([^']+)'/g, "\"$1\""); try { - return JSON.parse(normalized); + return JSON5.parse(str); } catch (e) { try { return new Function(`return ${str}`)(); - } catch { - throw new Error(`Invalid header object: ${str}`); + } catch (evalError) { + throw new Error(`Invalid header object: ${str}. Error: ${evalError.message}`); } } } @@ -382966,10 +384222,10 @@ var FileHeaderManager = class { if (!config) throw new Error(`Unsupported file type: ${ext}`); const match = content.match(config.regex); if (!match) return null; - const headerMatch = match[0].match(config.headerRegex); - if (!headerMatch) return null; + const headerBlock = this.findHeaderBlock(match[0], ext); + if (!headerBlock) return null; try { - return this.parseObjectLiteral(headerMatch[1].trim()); + return this.parseObjectLiteral(headerBlock.content.trim()); } catch { return null; } @@ -383014,43 +384270,56 @@ var FileHeaderManager = class { const { createBackup = false } = options; if (!filePath || typeof filePath !== "string") throw new Error("Invalid file path"); if (!headerObj || typeof headerObj !== "object") throw new Error("Invalid header object"); + const ext = path.extname(filePath); + const config = this.COMMENT_CONFIG[ext]; + if (!config) throw new Error(`Unsupported file type: ${ext}`); + const headerStr = `@header(${JSON5.stringify(headerObj, null, 2)})`; + if (await this._replaceHeaderBuffer(filePath, headerStr, config, ext)) return; let content; try { content = await fs$1.readFile(filePath, "utf8"); } catch (error) { throw new Error(`Failed to read file: ${error.message}`); } - const originalContent = content; - const ext = path.extname(filePath); - const config = this.COMMENT_CONFIG[ext]; - if (!config) throw new Error(`Unsupported file type: ${ext}`); - const headerStr = `@header(${JSON.stringify(headerObj, null, 2).replace(/"([a-zA-Z_$][\w$]*)":/g, "$1:").replace(/"/g, "'")})`; const match = content.match(config.regex); let newContent; if (match) { const [fullComment] = match; const commentStartIndex = content.indexOf(fullComment); const commentEndIndex = commentStartIndex + fullComment.length; - if (content.substring(0, commentStartIndex).trim() !== "") newContent = config.createComment(headerStr) + "\n\n" + content; - else if (config.headerRegex.test(fullComment)) { - const updatedComment = fullComment.replace(config.headerRegex, headerStr); - newContent = content.substring(0, commentStartIndex) + updatedComment + content.substring(commentEndIndex); + const beforeComment = content.substring(0, commentStartIndex); + if (!(beforeComment.trim() === "" || ext === ".php" && beforeComment.trim() === " { - const trimmed = line.trim(); - return trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !trimmed.startsWith("*") && !trimmed.startsWith("*/") && !trimmed.startsWith("#") && !trimmed.startsWith("\"\"\"") && !trimmed.startsWith("'''"); - }); - const newCodeLines = newContent.split("\n").filter((line) => { - const trimmed = line.trim(); - return trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !trimmed.startsWith("*") && !trimmed.startsWith("*/") && !trimmed.startsWith("#") && !trimmed.startsWith("\"\"\"") && !trimmed.startsWith("'''") && !trimmed.includes("@header("); - }); - if (originalCodeLines.length > 5 && newCodeLines.length < originalCodeLines.length * .8) throw new Error("Content integrity check failed: significant code loss detected, operation aborted"); + const diffRatio = Math.abs(newContent.length - content.length) / content.length; + if (content.length > 100 && diffRatio > .5 && newContent.length < content.length) throw new Error("Content integrity check failed: significant size reduction detected, operation aborted"); let backupPath = null; if (createBackup) try { backupPath = await this.createBackup(filePath); @@ -383075,6 +384344,58 @@ var FileHeaderManager = class { } } /** + * 使用 Buffer 高效地替换文件头,避免大文件 String 转换开销 + * @private + */ + static async _replaceHeaderBuffer(filePath, headerStr, config, ext) { + let handle; + try { + handle = await fs$1.open(filePath, "r"); + const stats = await handle.stat(); + const scanSize = Math.min(stats.size, 64 * 1024); + const buffer = Buffer.alloc(scanSize); + await handle.read(buffer, 0, scanSize, 0); + await handle.close(); + handle = null; + const match = buffer.toString("utf8").match(config.regex); + if (match) { + const [fullComment] = match; + const headerBlock = this.findHeaderBlock(fullComment, ext); + if (headerBlock) { + const commentStartOffset = buffer.indexOf(fullComment); + if (commentStartOffset === -1) return false; + const preHeaderStr = fullComment.substring(0, headerBlock.start); + const preHeaderLen = Buffer.byteLength(preHeaderStr); + const postHeaderStr = fullComment.substring(headerBlock.end); + const newHeaderBuf = Buffer.from(headerStr); + const replaceStart = commentStartOffset + preHeaderLen; + const oldHeaderContentStr = headerBlock.content; + const oldHeaderFullStr = fullComment.substring(headerBlock.start, headerBlock.end); + const oldHeaderByteLen = Buffer.byteLength(oldHeaderFullStr); + if (newHeaderBuf.length === oldHeaderByteLen) { + const writeHandle = await fs$1.open(filePath, "r+"); + await writeHandle.write(newHeaderBuf, 0, newHeaderBuf.length, replaceStart); + await writeHandle.close(); + return true; + } else { + const fullFileBuf = await fs$1.readFile(filePath); + const finalBuf = Buffer.concat([ + fullFileBuf.subarray(0, replaceStart), + newHeaderBuf, + fullFileBuf.subarray(replaceStart + oldHeaderByteLen) + ]); + await fs$1.writeFile(filePath, finalBuf); + return true; + } + } + } + return false; + } catch (e) { + if (handle) await handle.close(); + return false; + } + } + /** * 移除头信息区域 * @param {string} input 文件路径或文件内容 * @param {Object} [options] 配置选项 @@ -383105,14 +384426,21 @@ var FileHeaderManager = class { } const match = content.match(config.regex); if (!match) return content.trim(); - let [fullComment, innerContent] = match; - if (config.headerRegex.test(innerContent)) { - innerContent = innerContent.replace(config.headerRegex, ""); - const cleanedInner = innerContent.split("\n").filter((line) => line.trim().length > 0).join("\n"); - if (!cleanedInner.trim()) content = content.replace(fullComment, ""); + let [fullComment] = match; + const headerBlock = this.findHeaderBlock(fullComment, ext); + if (headerBlock) { + let beforeHeader = fullComment.substring(0, headerBlock.start); + let afterHeader = fullComment.substring(headerBlock.end); + beforeHeader = beforeHeader.replace(config.start, ""); + afterHeader = afterHeader.replace(config.end, ""); + if (ext === ".php") beforeHeader = beforeHeader.replace(/<\?php\s*/, ""); + let cleanedInner = (beforeHeader + "\n" + afterHeader).split("\n").map((line) => line.trim()).filter((line) => line.length > 0).join("\n"); + if (!cleanedInner) if (ext === ".php" && fullComment.trim().startsWith(" newComment); } } return content.trim(); @@ -385149,8 +386477,7 @@ async function commonSearchListParse(moduleObject, method, injectVars, args) { let params = rurls.length > 1 ? rurls[1] : ""; log(`[commonSearchListParse] post=》rurl:${rurl},params:${params}`); let _fetch_params = deepCopy$1(rule_fetch_params); - let postData = { body: params }; - Object.assign(_fetch_params, postData); + Object.assign(_fetch_params, { body: params }); html = await post(rurl, _fetch_params); } else if (req_method === "postjson") { let rurls = MY_URL.split(";")[0].split("#"); @@ -385163,8 +386490,7 @@ async function commonSearchListParse(moduleObject, method, injectVars, args) { params = "{}"; } let _fetch_params = deepCopy$1(rule_fetch_params); - let postData = { body: params }; - Object.assign(_fetch_params, postData); + Object.assign(_fetch_params, { body: params }); html = await post(rurl, _fetch_params); } else html = await executeSandboxFunction("getHtml", [sandboxString(MY_URL)], moduleObject.context, "获取HTML异常", ""); if (html) { @@ -391212,47 +392538,66 @@ var require_crypto_js_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) => })); //#endregion //#region ../node_modules/simplecc-wasm/pkg/nodejs/simplecc_wasm.js -var require_simplecc_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) => { - let imports = {}; - imports["__wbindgen_placeholder__"] = module.exports; - let wasm; - const { TextDecoder: TextDecoder$2, TextEncoder: TextEncoder$1 } = __require("util"); - let cachedTextDecoder = new TextDecoder$2("utf-8", { - ignoreBOM: true, - fatal: true - }); - cachedTextDecoder.decode(); - let cachedUint8ArrayMemory0 = null; - function getUint8ArrayMemory0() { - if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); - return cachedUint8ArrayMemory0; +var require_simplecc_wasm = /* @__PURE__ */ __commonJSMin(((exports) => { + /** + * @param {string} text + * @param {string} name + * @returns {string} + */ + function simplecc(text, name) { + let deferred4_0; + let deferred4_1; + try { + const ptr0 = passStringToWasm0(text, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.simplecc(ptr0, len0, ptr1, len1); + var ptr3 = ret[0]; + var len3 = ret[1]; + if (ret[3]) { + ptr3 = 0; + len3 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } + } + exports.simplecc = simplecc; + function __wbg_get_imports() { + const import0 = { + __proto__: null, + __wbindgen_cast_0000000000000001: function(arg0, arg1) { + return getStringFromWasm0(arg0, arg1); + }, + __wbindgen_init_externref_table: function() { + const table = wasm.__wbindgen_externrefs; + const offset = table.grow(4); + table.set(0, void 0); + table.set(offset + 0, void 0); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + } + }; + return { + __proto__: null, + "./simplecc_wasm_bg.js": import0 + }; } function getStringFromWasm0(ptr, len) { ptr = ptr >>> 0; - return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); + return decodeText(ptr, len); } - const heap = new Array(128).fill(void 0); - heap.push(void 0, null, true, false); - let heap_next = heap.length; - function addHeapObject(obj) { - if (heap_next === heap.length) heap.push(heap.length + 1); - const idx = heap_next; - heap_next = heap[idx]; - heap[idx] = obj; - return idx; + let cachedUint8ArrayMemory0 = null; + function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + return cachedUint8ArrayMemory0; } - let WASM_VECTOR_LEN = 0; - let cachedTextEncoder = new TextEncoder$1("utf-8"); - const encodeString = typeof cachedTextEncoder.encodeInto === "function" ? function(arg, view) { - return cachedTextEncoder.encodeInto(arg, view); - } : function(arg, view) { - const buf = cachedTextEncoder.encode(arg); - view.set(buf); - return { - read: arg.length, - written: buf.length - }; - }; function passStringToWasm0(arg, malloc, realloc) { if (realloc === void 0) { const buf = cachedTextEncoder.encode(arg); @@ -391274,73 +392619,41 @@ var require_simplecc_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) => if (offset !== 0) arg = arg.slice(offset); ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); - const ret = encodeString(arg, view); + const ret = cachedTextEncoder.encodeInto(arg, view); offset += ret.written; ptr = realloc(ptr, len, offset, 1) >>> 0; } WASM_VECTOR_LEN = offset; return ptr; } - let cachedDataViewMemory0 = null; - function getDataViewMemory0() { - if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || cachedDataViewMemory0.buffer.detached === void 0 && cachedDataViewMemory0.buffer !== wasm.memory.buffer) cachedDataViewMemory0 = new DataView(wasm.memory.buffer); - return cachedDataViewMemory0; - } - function getObject(idx) { - return heap[idx]; - } - function dropObject(idx) { - if (idx < 132) return; - heap[idx] = heap_next; - heap_next = idx; + function takeFromExternrefTable0(idx) { + const value = wasm.__wbindgen_externrefs.get(idx); + wasm.__externref_table_dealloc(idx); + return value; } - function takeObject(idx) { - const ret = getObject(idx); - dropObject(idx); - return ret; + let cachedTextDecoder = new TextDecoder("utf-8", { + ignoreBOM: true, + fatal: true + }); + cachedTextDecoder.decode(); + function decodeText(ptr, len) { + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); } - /** - * @param {string} text - * @param {string} name - * @returns {string} - */ - module.exports.simplecc = function(text, name) { - let deferred4_0; - let deferred4_1; - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(text, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - const ptr1 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - wasm.simplecc(retptr, ptr0, len0, ptr1, len1); - var r0 = getDataViewMemory0().getInt32(retptr + 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4, true); - var r2 = getDataViewMemory0().getInt32(retptr + 8, true); - var r3 = getDataViewMemory0().getInt32(retptr + 12, true); - var ptr3 = r0; - var len3 = r1; - if (r3) { - ptr3 = 0; - len3 = 0; - throw takeObject(r2); - } - deferred4_0 = ptr3; - deferred4_1 = len3; - return getStringFromWasm0(ptr3, len3); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); - } - }; - module.exports.__wbindgen_string_new = function(arg0, arg1) { - return addHeapObject(getStringFromWasm0(arg0, arg1)); + const cachedTextEncoder = new TextEncoder(); + if (!("encodeInto" in cachedTextEncoder)) cachedTextEncoder.encodeInto = function(arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; }; - const path$2 = __require("path").join(__dirname, "simplecc_wasm_bg.wasm"); - const bytes = __require("fs").readFileSync(path$2); - const wasmModule = new WebAssembly.Module(bytes); - wasm = new WebAssembly.Instance(wasmModule, imports).exports; - module.exports.__wasm = wasm; + let WASM_VECTOR_LEN = 0; + const wasmPath = `${__dirname}/simplecc_wasm_bg.wasm`; + const wasmBytes = __require("fs").readFileSync(wasmPath); + const wasmModule = new WebAssembly.Module(wasmBytes); + const wasm = new WebAssembly.Instance(wasmModule, __wbg_get_imports()).exports; + wasm.__wbindgen_start(); })); //#endregion //#region ../node_modules/node-sqlite3-wasm/dist/node-sqlite3-wasm.js @@ -391822,7 +393135,7 @@ var require_node_sqlite3_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) } var readAsync, readBinary; if (ENVIRONMENT_IS_NODE) { - var fs$2 = __require("fs"); + var fs$2 = __require("node:fs"); scriptDirectory = __dirname + "/"; readBinary = (filename) => { filename = isFileURI(filename) ? new URL(filename) : filename; @@ -392067,10 +393380,11 @@ var require_node_sqlite3_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) var callUserCallback = (func) => { if (ABORT) return; try { - func(); - maybeExit(); + return func(); } catch (e) { handleException(e); + } finally { + maybeExit(); } }; var _emscripten_get_now = () => performance.now(); @@ -392508,7 +393822,7 @@ var require_node_sqlite3_wasm = /* @__PURE__ */ __commonJSMin(((exports, module) Module["cwrap"] = cwrap; Module["addFunction"] = addFunction; Module["removeFunction"] = removeFunction; - var _sqlite3_finalize, _sqlite3_reset, _sqlite3_clear_bindings, _sqlite3_value_blob, _sqlite3_value_text, _sqlite3_value_bytes, _sqlite3_value_double, _sqlite3_value_int64, _sqlite3_value_type, _sqlite3_result_blob, _sqlite3_result_blob64, _sqlite3_result_double, _sqlite3_result_error, _sqlite3_result_int, _sqlite3_result_int64, _sqlite3_result_null, _sqlite3_result_text, _sqlite3_step, _sqlite3_column_count, _sqlite3_column_blob, _sqlite3_column_bytes, _sqlite3_column_double, _sqlite3_column_int64, _sqlite3_column_text, _sqlite3_column_type, _sqlite3_column_name, _sqlite3_column_table_name, _sqlite3_bind_blob, _sqlite3_bind_blob64, _sqlite3_bind_double, _sqlite3_bind_int, _sqlite3_bind_int64, _sqlite3_bind_null, _sqlite3_bind_text, _sqlite3_bind_parameter_index, _sqlite3_exec, _sqlite3_prepare_v2, _sqlite3_errmsg, _sqlite3_last_insert_rowid, _sqlite3_changes, _sqlite3_close_v2, _sqlite3_create_function_v2, _sqlite3_open_v2, _sqlite3_get_autocommit, _malloc, _free, __emscripten_timeout, __emscripten_stack_restore, __emscripten_stack_alloc, _emscripten_stack_get_current, wasmMemory, wasmTable; + var _sqlite3_finalize, _sqlite3_reset, _sqlite3_clear_bindings, _sqlite3_value_blob, _sqlite3_value_text, _sqlite3_value_bytes, _sqlite3_value_double, _sqlite3_value_int64, _sqlite3_value_type, _sqlite3_result_blob, _sqlite3_result_blob64, _sqlite3_result_double, _sqlite3_result_error, _sqlite3_result_int, _sqlite3_result_int64, _sqlite3_result_null, _sqlite3_result_text, _sqlite3_step, _sqlite3_column_count, _sqlite3_column_blob, _sqlite3_column_bytes, _sqlite3_column_double, _sqlite3_column_int64, _sqlite3_column_text, _sqlite3_column_type, _sqlite3_column_name, _sqlite3_column_table_name, _sqlite3_bind_blob, _sqlite3_bind_blob64, _sqlite3_bind_double, _sqlite3_bind_int, _sqlite3_bind_int64, _sqlite3_bind_null, _sqlite3_bind_text, _sqlite3_bind_parameter_index, _sqlite3_exec, _sqlite3_prepare_v2, _sqlite3_errmsg, _sqlite3_last_insert_rowid, _sqlite3_changes, _sqlite3_close_v2, _sqlite3_create_function_v2, _sqlite3_open_v2, _sqlite3_get_autocommit, _malloc, _free, __emscripten_timeout, __emscripten_stack_restore, __emscripten_stack_alloc, _emscripten_stack_get_current, memory, __indirect_function_table, wasmMemory, wasmTable; function assignWasmExports(wasmExports) { Module["_sqlite3_finalize"] = wasmExports["A"]; Module["_sqlite3_reset"] = wasmExports["B"]; @@ -392694,7 +394008,7 @@ globalThis._fetch = fetch; globalThis.JsonBig = (0, import_json_bigint.default)({ storeAsString: true }); globalThis.require = rootRequire; initializeGlobalDollar(); -const { Ali, Baidu, Baidu2, Cloud, Pan, Quark, UC, Yun } = pans_default; +const { Ali, Baidu, Baidu2, Cloud, Pan, Quark, UC, Yun, Xun } = pans_default; const { sleep, sleepSync, getNowTime, computeHash, deepCopy, urljoin: urljoin$1, urljoin2, joinUrl, keysToLowerCase, naturalSort, $js, createBasicAuthHeaders, get_size } = utils_exports$1; const CACHE_OPTIONS = { max: 100, @@ -392894,6 +394208,7 @@ const STATIC_LIBS_SANDBOX = { Cloud, Yun, Pan, + Xun, createWebDAVClient, createFTPClient, require: rootRequire, @@ -393090,9 +394405,6 @@ async function init$2(filePath, env = {}, refresh) { const moduleObject = rule; moduleObject.cost = t2 - t1; moduleObject.context = context; - delete sandbox._asyncGetRule; - delete sandbox.module; - delete sandbox.exports; moduleCache$2.set(hashMd5, { moduleObject, hash: fileHash @@ -393129,9 +394441,6 @@ async function getRuleObject(filePath, env, refresh) { ruleObject.filterable = ruleObject.hasOwnProperty("filterable") ? Number(ruleObject.filterable) : 0; ruleObject.quickSearch = ruleObject.hasOwnProperty("quickSearch") ? Number(ruleObject.quickSearch) : 0; ruleObject.cost = t2 - t1; - delete sandbox._asyncGetRule; - delete sandbox.module; - delete sandbox.exports; ruleObjectCache$1.set(filePath, { ruleObject, hash: fileHash @@ -393172,9 +394481,6 @@ async function initJx(filePath, env, refresh) { }; const cost = t2 - t1; log(`[initJx] 加载解析:${filePath} 耗时 ${cost}毫秒`); - delete sandbox._asyncGetLazy; - delete sandbox.module; - delete sandbox.exports; jxCache.set(hashMd5, { jxObj, hash: fileHash @@ -393954,6 +395260,11 @@ var catvod_default = { }; //#endregion //#region localDsCore.js +const ENGINES = { + drpyS: drpyS_exports, + php: php_default, + catvod: catvod_default +}; const __dirname$1 = path.dirname(fileURLToPath(import.meta.url)); const isBundled = __dirname$1.endsWith("dist") || __dirname$1.endsWith("libs") || __dirname$1.endsWith("dist" + path.sep) || __dirname$1.endsWith("libs" + path.sep); const possibleRoots = [ @@ -393982,15 +395293,7 @@ const options = { catDir, catLibDir }; -/** -* 支持的引擎映射表 -* 包含drpyS、php、catvod -*/ -const ENGINES = { - drpyS: drpyS_exports, - php: php_default, - catvod: catvod_default -}; +startJsonWatcher(ENGINES, jsonDir); /** * 创建带超时的Promise包装函数 * 为API操作添加超时控制,防止长时间阻塞 @@ -394007,9 +395310,10 @@ function withTimeout(promise, timeoutMs = null, operation = "API操作", invokeM else defaultTimeout = 20 * 1e3; const actualTimeout = timeoutMs || defaultTimeout; return Promise.race([promise, new Promise((_, reject) => { - setTimeout(() => { + const timer = setTimeout(() => { reject(/* @__PURE__ */ new Error(`${operation}超时 (${actualTimeout}ms)`)); }, actualTimeout); + if (timer.unref) timer.unref(); })]); } async function getEngine(moduleName, query, inject_env) { diff --git a/drpy-node-bundle/localDsCore.js b/drpy-node-bundle/localDsCore.js index d0b6053e..db53f075 100644 --- a/drpy-node-bundle/localDsCore.js +++ b/drpy-node-bundle/localDsCore.js @@ -7,6 +7,13 @@ import * as drpyS from '../libs/drpyS.js'; import php from '../libs/php.js'; import catvod from '../libs/catvod.js'; +// 初始化API引擎集合 +const ENGINES = { + drpyS, + php, + catvod, +}; + const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Determine if we are running from the dist/libs directory (bundled) or source @@ -42,15 +49,9 @@ const options = { catDir, catLibDir, }; -/** - * 支持的引擎映射表 - * 包含drpyS、php、catvod - */ -const ENGINES = { - drpyS, - php, - catvod, -}; + +// 启动JSON文件监听器 (仅在开发环境下生效) +startJsonWatcher(ENGINES, jsonDir); //const query = { // do: 'ds', // pg: 1, @@ -83,9 +84,10 @@ function withTimeout(promise, timeoutMs = null, operation = 'API操作', invokeM return Promise.race([ promise, new Promise((_, reject) => { - setTimeout(() => { + const timer = setTimeout(() => { reject(new Error(`${operation}超时 (${actualTimeout}ms)`)); }, actualTimeout); + if (timer.unref) timer.unref(); }) ]); } diff --git a/drpy-node-bundle/localDsCoreTest.js b/drpy-node-bundle/localDsCoreTest.js index 5e6e6240..5e9de76c 100644 --- a/drpy-node-bundle/localDsCoreTest.js +++ b/drpy-node-bundle/localDsCoreTest.js @@ -1,7 +1,8 @@ // import * as localtDsCore from './localDsCore.js'; -const start = performance.now(); import * as localtDsCore from './libs/localDsCore.bundled.js'; +const start = performance.now(); + console.log(getEngine) // const a = await getEngine('爱推图[画]', {}, {proxyUrl: "xx"}) // console.log(a) @@ -21,4 +22,20 @@ const e = await getEngine('30wMV[听]', { // console.log(e) const end = performance.now(); -console.log(`耗时: ${end - start} ms`); \ No newline at end of file +console.log(`耗时: ${end - start} ms`); +// process.exit(0); + +const f = await getEngine('央视大全[官]', { + do: 'ds', + proxy: 1, + url: '', +}, { + requestHost: 'http://127.0.0.1:5757', + proxyPath: 'https://dh5wswx02.v.cntv.cn/asp/h5e/hls/2000/0303000a/3/default/b90af013c16e44de9e4f1f56dab91f63/1.ts' +}) + +const [statuCode, contentType, buffer, headers] = f; +console.log('resutl: header:', headers, 'buffer length:', buffer.length); + +const g = await getEngine('360影视[官]', {do: 'ds', ac: 'list', t: '2', ext: 'eyLnsbvlnosiOiLoqIDmg4UifQ=='}) +console.log(g) \ No newline at end of file diff --git a/drpy-node-bundle/rolldown.config.js b/drpy-node-bundle/rolldown.config.js index a9521b92..9cad7e15 100644 --- a/drpy-node-bundle/rolldown.config.js +++ b/drpy-node-bundle/rolldown.config.js @@ -45,7 +45,8 @@ const require = (moduleName) => { conditionNames: ['node', 'import'], alias: { 'pako': path.resolve(__dirname, '../libs_drpy/pako.min.js'), - 'puppeteer': path.resolve(__dirname, 'puppeteer-mock.js') + 'puppeteer': path.resolve(__dirname, 'puppeteer-mock.js'), + [path.resolve(__dirname, '../libs_drpy/jsonpathplus.min.js')]: path.resolve(__dirname, 'shim/jsonpath-shim.js') } }, external: (id) => { diff --git a/drpy-node-bundle/shim/jsonpath-shim.js b/drpy-node-bundle/shim/jsonpath-shim.js new file mode 100644 index 00000000..cdbd89f9 --- /dev/null +++ b/drpy-node-bundle/shim/jsonpath-shim.js @@ -0,0 +1,29 @@ +import * as lib from './original-jsonpath.js'; + +// 获取对象 +// Rolldown/ESM interop 可能会把 export 放在 default 或 namespace +const JP = lib.JSONPath || lib.default?.JSONPath || lib.default; + +// 确保全局挂载 +if (typeof globalThis !== 'undefined') { + if (!globalThis.JSONPath) { + globalThis.JSONPath = {}; // 初始化容器 + } + // min.js 的逻辑是 globalThis.JSONPath.JSONPath = F + // 如果 JP 是 F (构造函数) + if (typeof JP === 'function') { + globalThis.JSONPath.JSONPath = JP; + } else if (JP && JP.JSONPath) { + // 如果 JP 已经是 { JSONPath: F } + globalThis.JSONPath = JP; + } + + // 如果 htmlParser.js 直接使用 JSONPath 变量而不是 globalThis.JSONPath + // 在 Bundle 环境下这是不可能的,除非它是全局变量。 + // 但是在 Node 环境下,全局变量可以直接访问。 + // 我们这里只能保证 globalThis.JSONPath 存在。 +} + +// 导出,虽然 htmlParser.js 没用到,但为了模块完整性 +export { JP as JSONPath }; +export default JP; diff --git a/drpy-node-bundle/shim/original-jsonpath.js b/drpy-node-bundle/shim/original-jsonpath.js new file mode 100644 index 00000000..bc5ffbbb --- /dev/null +++ b/drpy-node-bundle/shim/original-jsonpath.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).JSONPath={})}(this,function(e){"use strict";function n(e,t,r){return t=l(t),function(e,t){{if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined")}return function(e){if(void 0!==e)return e;throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}(e)}(e,i()?Reflect.construct(t,r||[],l(e).constructor):t.apply(e,r))}function o(e,t,r){if(i())return Reflect.construct.apply(null,arguments);var n=[null];n.push.apply(n,t);n=new(e.bind.apply(e,n));return r&&h(n,r.prototype),n}function i(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(i=function(){return!!e})()}function t(t,e){var r,n=Object.keys(t);return Object.getOwnPropertySymbols&&(r=Object.getOwnPropertySymbols(t),e&&(r=r.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,r)),n}function r(n){for(var e=1;ee.length)&&(t=e.length);for(var r=0,n=new Array(t);ru.prec:r<=u.prec);)o=n.pop(),t=n.pop().value,c=n.pop(),e={type:l.BINARY_EXP,operator:t,left:c,right:o},n.push(e);(e=this.gobbleToken())||this.throwError("Expected expression after "+s),n.push(i,e)}for(e=n[a=n.length-1];1=t.length&&this.throwError("Unexpected token "+String.fromCharCode(e));break}if(i===l.COMMA_CODE){if(this.index++,++n!==t.length)if(e===l.CPAREN_CODE)this.throwError("Unexpected token ,");else if(e===l.CBRACK_CODE)for(var o=t.length;o":7,"<=":7,">=":7,"<<":8,">>":8,">>>":8,"+":9,"-":9,"*":10,"/":10,"%":10},right_associative:new Set,additional_identifier_chars:new Set(["$","_"]),literals:{true:!0,false:!1,null:null},this_str:"this"}),v.max_unop_len=v.getMaxKeyLen(v.unary_ops),v.max_binop_len=v.getMaxKeyLen(v.binary_ops);var E=function(e){return new v(e).parse()};Object.getOwnPropertyNames(v).forEach(function(e){void 0===E[e]&&"prototype"!==e&&(E[e]=v[e])}),E.Jsep=v;b={name:"ternary",init:function(o){o.hooks.add("after-expression",function(e){if(e.node&&this.code===o.QUMARK_CODE){this.index++;var t=e.node,r=this.gobbleExpression();if(r||this.throwError("Expected expression"),this.gobbleSpaces(),this.code===o.COLON_CODE){this.index++;var n=this.gobbleExpression();if(n||this.throwError("Expected expression"),e.node={type:"ConditionalExpression",test:t,consequent:r,alternate:n},t.operator&&o.binary_ops[t.operator]<=.9){for(var i=t;i.right.operator&&o.binary_ops[i.right.operator]<=.9;)i=i.right;e.node.test=i.right,i.right=e.node,e.node=t}}else this.throwError("Expected :")}})}};E.plugins.register(b);var b={name:"regex",init:function(s){s.hooks.add("gobble-token",function(e){if(47===this.code){for(var t=++this.index,r=!1;this.index>=",">>>=","&=","^=","|="]),updateOperators:[43,45],assignmentPrecedence:.9,init:function(t){var n=[t.IDENTIFIER,t.MEMBER_EXP];g.assignmentOperators.forEach(function(e){return t.addBinaryOp(e,g.assignmentPrecedence,!0)}),t.hooks.add("gobble-token",function(e){var t=this,r=this.code;g.updateOperators.some(function(e){return e===r&&e===t.expr.charCodeAt(t.index+1)})&&(this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:this.gobbleTokenProperty(this.gobbleIdentifier()),prefix:!0},e.node.argument&&n.includes(e.node.argument.type)||this.throwError("Unexpected ".concat(e.node.operator)))}),t.hooks.add("after-token",function(e){var t,r=this;e.node&&(t=this.code,g.updateOperators.some(function(e){return e===t&&e===r.expr.charCodeAt(r.index+1)})&&(n.includes(e.node.type)||this.throwError("Unexpected ".concat(e.node.operator)),this.index+=2,e.node={type:"UpdateExpression",operator:43===t?"++":"--",argument:e.node,prefix:!1}))}),t.hooks.add("after-expression",function(e){e.node&&!function t(e){g.assignmentOperators.has(e.operator)?(e.type="AssignmentExpression",t(e.left),t(e.right)):e.operator||Object.values(e).forEach(function(e){e&&"object"===C(e)&&t(e)})}(e.node)})}},A=Object.prototype.hasOwnProperty;function w(e,t){return(e=e.slice()).push(t),e}function k(e,t){return(t=t.slice()).unshift(e),t}var x=function(){function r(e){var t;return s(this,r),(t=n(this,r,['JSONPath should not be called with "new" (it prevents return of (unwrapped) scalar values)'])).avoidNew=!0,t.value=e,t.name="NewError",t}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&h(e,t)}(r,p(Error)),c(r)}();function F(e,t,r,n,i){if(!(this instanceof F))try{return new F(e,t,r,n,i)}catch(e){if(!e.avoidNew)throw e;return e.value}"string"==typeof e&&(i=n,n=r,r=t,t=e,e=null);var o=e&&"object"===C(e);if(e=e||{},this.json=e.json||r,this.path=e.path||t,this.resultType=e.resultType||"value",this.flatten=e.flatten||!1,this.wrap=!A.call(e,"wrap")||e.wrap,this.sandbox=e.sandbox||{},this.eval=void 0===e.eval?"safe":e.eval,this.ignoreEvalErrors=void 0!==e.ignoreEvalErrors&&e.ignoreEvalErrors,this.parent=e.parent||null,this.parentProperty=e.parentProperty||null,this.callback=e.callback||n||null,this.otherTypeCallback=e.otherTypeCallback||i||function(){throw new TypeError("You must supply an otherTypeCallback callback option with the @other() operator.")},!1!==e.autostart){var a={path:o?e.path:t};o?"json"in e&&(a.json=e.json):a.json=r;a=this.evaluate(a);if(!a||"object"!==C(a))throw new x(a);return a}}F.prototype.evaluate=function(e,t,r,n){var i=this,o=this.parent,a=this.parentProperty,s=this.flatten,u=this.wrap;if(this.currResultType=this.resultType,this.currEval=this.eval,this.currSandbox=this.sandbox,r=r||this.callback,this.currOtherTypeCallback=n||this.otherTypeCallback,t=t||this.json,(e=e||this.path)&&"object"===C(e)&&!Array.isArray(e)){if(!e.path&&""!==e.path)throw new TypeError('You must supply a "path" property when providing an object argument to JSONPath.evaluate().');if(!A.call(e,"json"))throw new TypeError('You must supply a "json" property when providing an object argument to JSONPath.evaluate().');t=e.json,s=A.call(e,"flatten")?e.flatten:s,this.currResultType=A.call(e,"resultType")?e.resultType:this.currResultType,this.currSandbox=A.call(e,"sandbox")?e.sandbox:this.currSandbox,u=A.call(e,"wrap")?e.wrap:u,this.currEval=A.call(e,"eval")?e.eval:this.currEval,r=A.call(e,"callback")?e.callback:r,this.currOtherTypeCallback=A.call(e,"otherTypeCallback")?e.otherTypeCallback:this.currOtherTypeCallback,o=A.call(e,"parent")?e.parent:o,a=A.call(e,"parentProperty")?e.parentProperty:a,e=e.path}if(o=o||null,a=a||null,Array.isArray(e)&&(e=F.toPathString(e)),(e||""===e)&&t){e=F.toPathArray(e);"$"===e[0]&&1@-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)['\[](\??\((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*?\))(?!(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])\)\])['\]]/g.exec(f);d?this._walk(n,function(e){var t=[d[2]],r=d[1]?n[e][d[1]]:n[e];0=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:t}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,a=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return o=e.done,e},e:function(e){a=!0,i=e},f:function(){try{o||null==r.return||r.return()}finally{if(a)throw i}}}}(c.split(","));try{for(E.s();!(g=E.n()).done;){var g=g.value;p(this._trace(k(g,l),n,i,o,a,s,!0))}}catch(e){E.e(e)}finally{E.f()}}else!r&&n&&A.call(n,c)&&p(this._trace(l,n[c],w(i,c),n,c,s,e,!0))}if(this._hasParentSelector)for(var x=0;x":function(e,t){return e>t()},"<=":function(e,t){return e<=t()},">=":function(e,t){return e>=t()},"<<":function(e,t){return e<>":function(e,t){return e>>t()},">>>":function(e,t){return e>>>t()},"+":function(e,t){return e+t()},"-":function(e,t){return e-t()},"*":function(e,t){return e*t()},"/":function(e,t){return e/t()},"%":function(e,t){return e%t()}}[e.operator](D.evalAst(e.left,t),function(){return D.evalAst(e.right,t)})},evalCompound:function(e,t){for(var r=0;r 0) { + playList = vodItems.join("#") + } + if (playList.length < 1) { + continue; + } + vod_play[site] = playList + } + let tabs = Object.keys(vod_play); + let playUrls = []; + for (let id in tabs) { + // print("id:" + id); + playUrls.push(vod_play[tabs[id]]) + } + if (tabs.length > 0) { + let vod_play_from = tabs.join("$$$"); + let vod_play_url = playUrls.join("$$$"); + base_vod.vod_play_from = vod_play_from; + base_vod.vod_play_url = vod_play_url + } + return base_vod; + }, + 搜索: 'json:data.longData.rows;titleTxt||titlealias;cover;cat_name;cat_id+en_id;description', +} \ No newline at end of file diff --git "a/drpy-node-bundle/spider/js/APP\346\250\241\346\235\277\351\205\215\347\275\256.js" "b/drpy-node-bundle/spider/js/APP\346\250\241\346\235\277\351\205\215\347\275\256.js" new file mode 100644 index 00000000..fbfc9ccd --- /dev/null +++ "b/drpy-node-bundle/spider/js/APP\346\250\241\346\235\277\351\205\215\347\275\256.js" @@ -0,0 +1,20 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: 'APP模板配置', + more: { + sourceTag: '设置,动作', + actions: [ + { + name: 'APP模板|配置相关', + action: '{\'actionId\':\'单选菜单\',\'type\':\'menu\',\'title\':\'Action菜单\',\'width\':500,\'column\':1,\'option\':[\'导入分享配置$menu1\',\'分享APP配置$menu2\'],\'selectedIndex\':0}' + } + ] + }, + lang: 'ds' +}) +*/ + +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 \ No newline at end of file diff --git "a/drpy-node-bundle/spider/js/AppShark[\346\250\241\346\235\277].js" "b/drpy-node-bundle/spider/js/AppShark[\346\250\241\346\235\277].js" new file mode 100644 index 00000000..0f3a3852 --- /dev/null +++ "b/drpy-node-bundle/spider/js/AppShark[\346\250\241\346\235\277].js" @@ -0,0 +1,11 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: 'AppShark模板', + lang: 'ds' +}) +*/ + +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 \ No newline at end of file diff --git "a/drpy-node-bundle/spider/js/Appget[\346\250\241\346\235\277].js" "b/drpy-node-bundle/spider/js/Appget[\346\250\241\346\235\277].js" new file mode 100644 index 00000000..3b4a753a --- /dev/null +++ "b/drpy-node-bundle/spider/js/Appget[\346\250\241\346\235\277].js" @@ -0,0 +1,11 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: 'Appget[模板]', + lang: 'ds' +}) +*/ + +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 \ No newline at end of file diff --git "a/drpy-node-bundle/spider/js/Appmuou[\346\250\241\346\235\277].js" "b/drpy-node-bundle/spider/js/Appmuou[\346\250\241\346\235\277].js" new file mode 100644 index 00000000..56df3dc1 --- /dev/null +++ "b/drpy-node-bundle/spider/js/Appmuou[\346\250\241\346\235\277].js" @@ -0,0 +1,11 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: 'Appmuou模板', + lang: 'ds' +}) +*/ + +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 \ No newline at end of file diff --git a/drpy-node-bundle/spider/js/_lib.cntv-urlparse.cjs b/drpy-node-bundle/spider/js/_lib.cntv-urlparse.cjs new file mode 100644 index 00000000..a3a76855 --- /dev/null +++ b/drpy-node-bundle/spider/js/_lib.cntv-urlparse.cjs @@ -0,0 +1,282 @@ +#!/usr/bin/env node +/** + * CCTV Video URL Parser + * 解析央视视频URL,获取视频下载链接 + * + * 使用方法: + * node parse_url.js "https://tv.cctv.com/2026/03/13/VIDE1I89jcwxtmOiZUd6zsLR260313.shtml" + * node parse_url.js "330318aa5ca745d286b8d6c57e971a39" + * echo "..." | node parse_url.js - + */ + +const crypto = require('crypto'); +const fs = require('fs'); + +// 固定参数 +const CCTV_API_URL = 'https://vdn.apps.cntv.cn/api/getHttpVideoInfo.do'; +const SECRET_KEY = '47899B86370B879139C08EA3B5E88267'; +const UID = '826D8646DEBBFD97A82D23CAE45A55BE'; + +// 提取视频ID的正则规则 +const PID_RULES = [ + /var\s+guid\s*=\s*["']([\da-fA-F]+)["']/, + /videoCenterId(?:["']\s*,|:)\s*["']([\da-fA-F]+)["']/, + /changePlayer\s*\(\s*["']([\da-fA-F]+)["']\)/, + /load[Vv]ideo\s*\(\s*["']([\da-fA-F]+)["']\)/, + /var\s+initMyAray\s*=\s*["']([\da-fA-F]+)["']/, + /var\s+ids\s*=\s*\[["']([\da-fA-F]+)["']\]/ +]; + +// PID格式:32位十六进制字符串 +const PID_PATTERN = /^[\da-fA-F]{32}$/; + +/** + * MD5哈希函数 + */ +function md5(value) { + return crypto.createHash('md5').update(value, 'utf-8').digest('hex'); +} + +/** + * HTTP GET请求(使用fetch) + */ +async function httpGet(url) { + try { + const response = await fetch(url, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' + } + }); + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + return await response.text(); + } catch (error) { + throw error; + } +} + +/** + * 判断输入类型 + * @param {string} input - 用户输入 + * @returns {string} - 'url' | 'pid' | 'html' | 'stdin' + */ +function detectInputType(input) { + if (input === '-') { + return 'stdin'; + } + // 优先检测URL + if (input.match(/^https?:\/\//i)) { + return 'url'; + } + // 检测HTML/JavaScript内容(包含HTML标签或JavaScript变量声明) + if (input.includes(' bestBandwidth) { + bestBandwidth = bandwidth; + bestUri = uriLine; + } + break; + } + } + } + } + } + + // 如果没有找到多码率流,直接返回第一个非空行(单码率情况) + if (!bestUri) { + for (const line of lines) { + const trimmed = line.trim(); + if (trimmed && !trimmed.startsWith('#')) { + bestUri = trimmed; + break; + } + } + } + + // 处理路径 + if (bestUri && !bestUri.startsWith('http')) { + const urlObj = new URL(m3u8BaseUrl); + // 如果是绝对路径(以/开头) + if (bestUri.startsWith('/')) { + bestUri = `${urlObj.protocol}//${urlObj.host}${bestUri}`; + } else { + // 相对路径 + const basePath = urlObj.pathname.substring(0, urlObj.pathname.lastIndexOf('/') + 1); + bestUri = `${urlObj.protocol}//${urlObj.host}${basePath}${bestUri}`; + } + } + + return bestUri; +} + +/** + * 根据PID获取视频信息 + * @param {string} pid - 视频ID + * @returns {Promise} 视频信息对象 + */ +async function getVideoInfoByPid(pid) { + console.log(`使用视频ID: ${pid}`); + + // 构建API请求参数 + console.log('步骤1: 构建API请求...'); + const tsp = Math.floor(Date.now() / 1000); + const vn = '2049'; + const vc = md5(tsp + vn + SECRET_KEY + UID); + + const apiParams = new URLSearchParams({ + pid: pid, + client: 'flash', + im: '0', + tsp: tsp.toString(), + vn: vn, + vc: vc, + uid: UID, + wlan: '' + }); + + const apiUrl = `${CCTV_API_URL}?${apiParams.toString()}`; + console.log(`API URL: ${apiUrl}`); + + // 调用API获取视频信息 + console.log('步骤2: 获取视频信息...'); + const apiResponse = await httpGet(apiUrl); + const videoData = JSON.parse(apiResponse); + + console.log('视频信息:', { + title: videoData.title, + pgtv: videoData.pgtv + }); + + // 获取m3u8下载链接 + console.log('步骤3: 解析下载链接...'); + const manifest = videoData.manifest || {}; + let hlsUrl = manifest.hls_h5e_url || manifest.hls_url || videoData.hls_h5e_url || videoData.hls_url; + + if (!hlsUrl) { + throw new Error('无法获取HLS下载链接'); + } + console.log(`HLS URL: ${hlsUrl}`); + + // 解析m3u8获取最高质量的流 + console.log('步骤4: 解析M3U8获取最佳质量...'); + const m3u8Content = await httpGet(hlsUrl); + const downloadUrl = parseM3U8ForBestQuality(m3u8Content, hlsUrl); + + if (!downloadUrl) { + throw new Error('无法解析M3U8内容'); + } + + console.log(`最终下载链接: ${downloadUrl}`); + + return { + success: true, + title: videoData.title, + pid: pid, + pgtv: videoData.pgtv, + hls_key: manifest.hls_h5e_url ? 'hls_h5e_url' : 'hls_url', + download_url: downloadUrl, + m3u8_url: hlsUrl, + cover_url: videoData.image + }; +} + +/** + * 主函数:解析CCTV视频URL + * @param {string} input - 输入(URL、PID或HTML内容) + * @returns {Promise} 视频信息对象 + */ +async function parseCCTVUrl(input) { + try { + const inputType = detectInputType(input); + console.log(`检测到输入类型: ${inputType}`); + + // 如果是PID,直接调用API + if (inputType === 'pid') { + return await getVideoInfoByPid(input); + } + + // 如果是URL,获取页面内容并提取PID + if (inputType === 'url') { + console.log(`正在解析URL: ${input}`); + console.log('步骤1: 获取页面内容...'); + const html = await httpGet(input); + const pid = extractPid(html); + + if (!pid) { + throw new Error('无法从页面中提取视频ID'); + } + console.log(`找到视频ID: ${pid}`); + + return await getVideoInfoByPid(pid); + } + + // 如果是HTML内容,直接提取PID + if (inputType === 'html') { + console.log('检测到HTML内容,直接提取视频ID...'); + const pid = extractPid(input); + + if (!pid) { + throw new Error('无法从HTML内容中提取视频ID'); + } + console.log(`找到视频ID: ${pid}`); + + return await getVideoInfoByPid(pid); + } + + throw new Error(`不支持的输入类型: ${inputType}`); + + } catch (error) { + console.error('解析失败:', error.message); + return { + success: false, + error: error.message + }; + } +} + +// 导出函数供其他模块使用 +module.exports = {parseCCTVUrl, detectInputType, getVideoInfoByPid}; \ No newline at end of file diff --git a/drpy-node-bundle/spider/js/_lib.cntv-wasm.cjs b/drpy-node-bundle/spider/js/_lib.cntv-wasm.cjs new file mode 100644 index 00000000..942a789c --- /dev/null +++ b/drpy-node-bundle/spider/js/_lib.cntv-wasm.cjs @@ -0,0 +1,5 @@ +var CNTVModule=function(){var _scriptDir="undefined"!=typeof document&&document.currentScript?document.currentScript.src:void 0;return function(CNTVModule){CNTVModule=CNTVModule||{};var Module=void 0!==CNTVModule?CNTVModule:{},moduleOverrides={},key;for(key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var arguments_=[],thisProgram="./this.program",quit_=function(A,e){throw e},ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_HAS_NODE=!1,ENVIRONMENT_IS_SHELL=!1,ENVIRONMENT_IS_WEB="object"==typeof window,ENVIRONMENT_IS_WORKER="function"==typeof importScripts,ENVIRONMENT_HAS_NODE="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER,scriptDirectory="",read_,readAsync,readBinary,setWindowTitle;function locateFile(A){return Module.locateFile?Module.locateFile(A,scriptDirectory):scriptDirectory+A}(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&(ENVIRONMENT_IS_WORKER?scriptDirectory=self.location.href:document.currentScript&&(scriptDirectory=document.currentScript.src),_scriptDir&&(scriptDirectory=_scriptDir),scriptDirectory=0!==scriptDirectory.indexOf("blob:")?scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1):"",read_=function(e){try{var t=new XMLHttpRequest;return t.open("GET",e,!1),t.send(null),t.responseText}catch(A){t=tryParseAsDataURI(e);if(t)return intArrayToString(t);throw A}},ENVIRONMENT_IS_WORKER&&(readBinary=function(e){try{var t=new XMLHttpRequest;return t.open("GET",e,!1),t.responseType="arraybuffer",t.send(null),new Uint8Array(t.response)}catch(A){t=tryParseAsDataURI(e);if(t)return t;throw A}}),readAsync=function(e,t,g){var r=new XMLHttpRequest;r.open("GET",e,!0),r.responseType="arraybuffer",r.onload=function(){var A;200==r.status||0==r.status&&r.response?t(r.response):(A=tryParseAsDataURI(e))?t(A.buffer):g()},r.onerror=g,r.send(null)},setWindowTitle=function(A){document.title=A});var out=Module.print||console.log.bind(console),err=Module.printErr||console.warn.bind(console);for(key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);function dynamicAlloc(A){var e=HEAP32[DYNAMICTOP_PTR>>2],A=e+A+15&-16;return A>_emscripten_get_heap_size()&&abort(),HEAP32[DYNAMICTOP_PTR>>2]=A,e}function getNativeTypeSize(A){switch(A){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:var e;return"*"===A[A.length-1]?4:"i"===A[0]?(assert((e=parseInt(A.substr(1)))%8==0,"getNativeTypeSize invalid bits "+e+", type "+A),e/8):0}}function warnOnce(A){warnOnce.shown||(warnOnce.shown={}),warnOnce.shown[A]||(warnOnce.shown[A]=1,err(A))}moduleOverrides=null,Module.arguments&&(arguments_=Module.arguments),Module.thisProgram&&(thisProgram=Module.thisProgram),Module.quit&&(quit_=Module.quit);var asm2wasmImports={"f64-rem":function(A,e){return A%e},debugger:function(){}},jsCallStartIndex=1,functionPointers=new Array(14);function addFunction(A,e){for(var t=0;t<14;t++)if(!functionPointers[t])return functionPointers[t]=A,jsCallStartIndex+t;throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}function makeBigInt(A,e,t){return t?(A>>>0)+4294967296*(e>>>0):(A>>>0)+4294967296*(0|e)}var tempRet0=0,setTempRet0=function(A){tempRet0=A},getTempRet0=function(){return tempRet0},wasmBinary,wasmMemory,wasmTable;function setValue(A,e,t,g){switch(t="*"===(t=t||"i8").charAt(t.length-1)?"i32":t){case"i1":case"i8":HEAP8[A>>0]=e;break;case"i16":HEAP16[A>>1]=e;break;case"i32":HEAP32[A>>2]=e;break;case"i64":tempI64=[e>>>0,1<=+Math_abs(tempDouble=e)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0],HEAP32[A>>2]=tempI64[0],HEAP32[A+4>>2]=tempI64[1];break;case"float":HEAPF32[A>>2]=e;break;case"double":HEAPF64[A>>3]=e;break;default:abort("invalid type for setValue: "+t)}}Module.wasmBinary&&(wasmBinary=Module.wasmBinary),"object"!=typeof WebAssembly&&err("no native wasm support detected");var ABORT=!1,EXITSTATUS=0;function assert(A,e){A||abort("Assertion failed: "+e)}var ALLOC_NONE=3;function allocate(A,e,t,g){var r,B,n="number"==typeof A?(r=!0,A):(r=!1,A.length),E="string"==typeof e?e:null,C=t==ALLOC_NONE?g:[_malloc,stackAlloc,dynamicAlloc][t](Math.max(n,E?1:e.length));if(r){for(assert(0==(3&(g=C))),B=C+(-4&n);g>2]=0;for(B=C+n;g>0]=0}else if("i8"===E)A.subarray||A.slice?HEAPU8.set(A,C):HEAPU8.set(new Uint8Array(A),C);else for(var o,I,Q=0;Q>10,56320|1023&E)))):B+=String.fromCharCode(C)}return B}function UTF8ToString(A,e){return A?UTF8ArrayToString(HEAPU8,A,e):""}function stringToUTF8Array(A,e,t,g){if(!(0>6}else{if(E<=65535){if(B<=t+2)break;e[t++]=224|E>>12}else{if(B<=t+3)break;e[t++]=240|E>>18,e[t++]=128|E>>12&63}e[t++]=128|E>>6&63}e[t++]=128|63&E}}return e[t]=0,t-r}function stringToUTF8(A,e,t){return stringToUTF8Array(A,HEAPU8,e,t)}function lengthBytesUTF8(A){for(var e=0,t=0;t>2]=DYNAMIC_BASE;var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for("function"==typeof Module.preRun&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=!0,Module.noFSInit||FS.init.initialized||FS.init(),TTY.init(),callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=!1,callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=!0}function postRun(){if(Module.postRun)for("function"==typeof Module.postRun&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(A){__ATPRERUN__.unshift(A)}function addOnPostRun(A){__ATPOSTRUN__.unshift(A)}function unSign(A,e,t){return 0<=A?A:e<=32?2*Math.abs(1<>2]=HEAPU32[eb+A[e]>>2]+eb});var ___exception_infos={},___exception_caught=[];function ___exception_addRef(A){A&&___exception_infos[A].refcount++}function ___exception_deAdjust(A){if(A&&!___exception_infos[A])for(var e in ___exception_infos)for(var t=+e,g=___exception_infos[t].adjusted,r=g.length,B=0;B>2]=A),A}var PATH_FS={resolve:function(){for(var A="",e=!1,t=arguments.length-1;-1<=t&&!e;t--){var g=0<=t?arguments[t]:FS.cwd();if("string"!=typeof g)throw new TypeError("Arguments to path.resolve must be strings");if(!g)return"";A=g+"/"+A,e="/"===g.charAt(0)}return(e?"/":"")+(A=PATH.normalizeArray(A.split("/").filter(function(A){return!!A}),!e).join("/"))||"."},relative:function(A,e){function t(A){for(var e=0;ee)A.contents.length=e;else for(;A.contents.length=A.node.usedBytes)return 0;var n=Math.min(A.node.usedBytes-r,g);if(8t.timestamp)&&(n.push(A),B++)}),[]);if(Object.keys(r.entries).forEach(function(A){r.entries[A];g.entries[A]||(t.push(A),B++)}),!B)return e(null);var E=!1,A=("remote"===g.type?g:r).db.transaction([IDBFS.DB_STORE_NAME],"readwrite"),C=A.objectStore(IDBFS.DB_STORE_NAME);function o(A){if(A&&!E)return E=!0,e(A)}A.onerror=function(A){o(this.error),A.preventDefault()},A.oncomplete=function(A){E||e(null)},n.sort().forEach(function(t){"local"===r.type?IDBFS.loadRemoteEntry(C,t,function(A,e){if(A)return o(A);IDBFS.storeLocalEntry(t,e,o)}):IDBFS.loadLocalEntry(t,function(A,e){if(A)return o(A);IDBFS.storeRemoteEntry(C,t,e,o)})}),t.sort().reverse().forEach(function(A){"local"===r.type?IDBFS.removeLocalEntry(A,o):IDBFS.removeRemoteEntry(C,A,o)})}},WORKERFS={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:function(A){assert(ENVIRONMENT_IS_WORKER),WORKERFS.reader||(WORKERFS.reader=new FileReaderSync);var B=WORKERFS.createNode(null,"/",WORKERFS.DIR_MODE,0),n={};function g(A){for(var e=A.split("/"),t=B,g=0;g=A.node.size?0:(A=A.node.contents.slice(r,r+g),r=WORKERFS.reader.readAsArrayBuffer(A),e.set(new Uint8Array(r),t),A.size)},write:function(A,e,t,g,r){throw new FS.ErrnoError(5)},llseek:function(A,e,t){if(1===t?e+=A.position:2===t&&FS.isFile(A.node.mode)&&(e+=A.node.size),e<0)throw new FS.ErrnoError(22);return e}}},FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:!1,ignorePermissions:!0,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(A){if(A instanceof FS.ErrnoError)return ___setErrNo(A.errno);throw A+" : "+stackTrace()},lookupPath:function(A,e){if(e=e||{},!(A=PATH_FS.resolve(FS.cwd(),A)))return{path:"",node:null};var t,g={follow_mount:!0,recurse_count:0};for(t in g)void 0===e[t]&&(e[t]=g[t]);if(8>>0)%FS.nameTable.length},hashAddNode:function(A){var e=FS.hashName(A.parent.id,A.name);A.name_next=FS.nameTable[e],FS.nameTable[e]=A},hashRemoveNode:function(A){var e=FS.hashName(A.parent.id,A.name);if(FS.nameTable[e]===A)FS.nameTable[e]=A.name_next;else for(var t=FS.nameTable[e];t;){if(t.name_next===A){t.name_next=A.name_next;break}t=t.name_next}},lookupNode:function(A,e){var t=FS.mayLookup(A);if(t)throw new FS.ErrnoError(t,A);for(var t=FS.hashName(A.id,e),g=FS.nameTable[t];g;g=g.name_next){var r=g.name;if(g.parent.id===A.id&&r===e)return g}return FS.lookup(A,e)},createNode:function(A,e,t,g){FS.FSNode||(FS.FSNode=function(A,e,t,g){this.parent=A=A||this,this.mount=A.mount,this.mounted=null,this.id=FS.nextInode++,this.name=e,this.mode=t,this.node_ops={},this.stream_ops={},this.rdev=g},FS.FSNode.prototype={},Object.defineProperties(FS.FSNode.prototype,{read:{get:function(){return 365==(365&this.mode)},set:function(A){A?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146==(146&this.mode)},set:function(A){A?this.mode|=146:this.mode&=-147}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}}));A=new FS.FSNode(A,e,t,g);return FS.hashAddNode(A),A},destroyNode:function(A){FS.hashRemoveNode(A)},isRoot:function(A){return A===A.parent},isMountpoint:function(A){return!!A.mounted},isFile:function(A){return 32768==(61440&A)},isDir:function(A){return 16384==(61440&A)},isLink:function(A){return 40960==(61440&A)},isChrdev:function(A){return 8192==(61440&A)},isBlkdev:function(A){return 24576==(61440&A)},isFIFO:function(A){return 4096==(61440&A)},isSocket:function(A){return 49152==(49152&A)},flagModes:{r:0,rs:1052672,"r+":2,w:577,wx:705,xw:705,"w+":578,"wx+":706,"xw+":706,a:1089,ax:1217,xa:1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(A){var e=FS.flagModes[A];if(void 0===e)throw new Error("Unknown file open mode: "+A);return e},flagsToPermissionString:function(A){var e=["r","w","rw"][3&A];return 512&A&&(e+="w"),e},nodePermissions:function(A,e){return FS.ignorePermissions||(-1===e.indexOf("r")||292&A.mode)&&(-1===e.indexOf("w")||146&A.mode)&&(-1===e.indexOf("x")||73&A.mode)?0:13},mayLookup:function(A){var e=FS.nodePermissions(A,"x");return e||(A.node_ops.lookup?0:13)},mayCreate:function(A,e){try{FS.lookupNode(A,e);return 17}catch(A){}return FS.nodePermissions(A,"wx")},mayDelete:function(A,e,t){var g;try{g=FS.lookupNode(A,e)}catch(A){return A.errno}e=FS.nodePermissions(A,"wx");if(e)return e;if(t){if(!FS.isDir(g.mode))return 20;if(FS.isRoot(g)||FS.getPath(g)===FS.cwd())return 16}else if(FS.isDir(g.mode))return 21;return 0},mayOpen:function(A,e){return A?FS.isLink(A.mode)?40:FS.isDir(A.mode)&&("r"!==FS.flagsToPermissionString(e)||512&e)?21:FS.nodePermissions(A,FS.flagsToPermissionString(e)):2},MAX_OPEN_FDS:4096,nextfd:function(A,e){e=e||FS.MAX_OPEN_FDS;for(var t=A=A||0;t<=e;t++)if(!FS.streams[t])return t;throw new FS.ErrnoError(24)},getStream:function(A){return FS.streams[A]},createStream:function(A,e,t){FS.FSStream||(FS.FSStream=function(){},FS.FSStream.prototype={},Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(A){this.node=A}},isRead:{get:function(){return 1!=(2097155&this.flags)}},isWrite:{get:function(){return 0!=(2097155&this.flags)}},isAppend:{get:function(){return 1024&this.flags}}}));var g,r=new FS.FSStream;for(g in A)r[g]=A[g];A=r;e=FS.nextfd(e,t);return A.fd=e,FS.streams[e]=A},closeStream:function(A){FS.streams[A]=null},chrdev_stream_ops:{open:function(A){var e=FS.getDevice(A.node.rdev);A.stream_ops=e.stream_ops,A.stream_ops.open&&A.stream_ops.open(A)},llseek:function(){throw new FS.ErrnoError(29)}},major:function(A){return A>>8},minor:function(A){return 255&A},makedev:function(A,e){return A<<8|e},registerDevice:function(A,e){FS.devices[A]={stream_ops:e}},getDevice:function(A){return FS.devices[A]},getMounts:function(A){for(var e=[],t=[A];t.length;){var g=t.pop();e.push(g),t.push.apply(t,g.mounts)}return e},syncfs:function(e,t){"function"==typeof e&&(t=e,e=!1),FS.syncFSRequests++,1=g.length&&B(null)}g.forEach(function(A){if(!A.type.syncfs)return n(null);A.type.syncfs(A,e,n)})},mount:function(A,e,t){var g,r="/"===t,B=!t;if(r&&FS.root)throw new FS.ErrnoError(16);if(!r&&!B){B=FS.lookupPath(t,{follow_mount:!1});if(t=B.path,g=B.node,FS.isMountpoint(g))throw new FS.ErrnoError(16);if(!FS.isDir(g.mode))throw new FS.ErrnoError(20)}B={type:A,opts:e,mountpoint:t,mounts:[]},e=A.mount(B);return(e.mount=B).root=e,r?FS.root=e:g&&(g.mounted=B,g.mount)&&g.mount.mounts.push(B),e},unmount:function(A){A=FS.lookupPath(A,{follow_mount:!1});if(!FS.isMountpoint(A.node))throw new FS.ErrnoError(22);var A=A.node,e=A.mounted,g=FS.getMounts(e),e=(Object.keys(FS.nameTable).forEach(function(A){for(var e=FS.nameTable[A];e;){var t=e.name_next;-1!==g.indexOf(e.mount)&&FS.destroyNode(e),e=t}}),A.mounted=null,A.mount.mounts.indexOf(e));A.mount.mounts.splice(e,1)},lookup:function(A,e){return A.node_ops.lookup(A,e)},mknod:function(A,e,t){var g=FS.lookupPath(A,{parent:!0}).node,A=PATH.basename(A);if(!A||"."===A||".."===A)throw new FS.ErrnoError(22);var r=FS.mayCreate(g,A);if(r)throw new FS.ErrnoError(r);if(g.node_ops.mknod)return g.node_ops.mknod(g,A,e,t);throw new FS.ErrnoError(1)},create:function(A,e){return FS.mknod(A,e=(e=void 0!==e?e:438)&4095|32768,0)},mkdir:function(A,e){return FS.mknod(A,e=(e=void 0!==e?e:511)&1023|16384,0)},mkdirTree:function(A,e){for(var t=A.split("/"),g="",r=0;rthis.length-1||A<0))return e=A%this.chunkSize,A=A/this.chunkSize|0,this.getter(A)[e]},r.prototype.setDataGetter=function(A){this.getter=A},r.prototype.cacheLength=function(){var A=new XMLHttpRequest;if(A.open("HEAD",n,!1),A.send(null),!(200<=A.status&&A.status<300||304===A.status))throw new Error("Couldn't load "+n+". Status: "+A.status);var e,g=Number(A.getResponseHeader("Content-length")),t=(e=A.getResponseHeader("Accept-Ranges"))&&"bytes"===e,A=(e=A.getResponseHeader("Content-Encoding"))&&"gzip"===e,r=1048576,B=(t||(r=g),this);B.setDataGetter(function(A){var e=A*r,t=(A+1)*r-1,t=Math.min(t,g-1);if(void 0===B.chunks[A]&&(B.chunks[A]=function(A,e){if(e=B.length)return 0;var n=Math.min(B.length-r,g);if(B.slice)for(var E=0;E>2]=g.dev,HEAP32[t+4>>2]=0,HEAP32[t+8>>2]=g.ino,HEAP32[t+12>>2]=g.mode,HEAP32[t+16>>2]=g.nlink,HEAP32[t+20>>2]=g.uid,HEAP32[t+24>>2]=g.gid,HEAP32[t+28>>2]=g.rdev,HEAP32[t+32>>2]=0,tempI64=[g.size>>>0,(tempDouble=g.size,1<=+Math_abs(tempDouble)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[t+40>>2]=tempI64[0],HEAP32[t+44>>2]=tempI64[1],HEAP32[t+48>>2]=4096,HEAP32[t+52>>2]=g.blocks,HEAP32[t+56>>2]=g.atime.getTime()/1e3|0,HEAP32[t+60>>2]=0,HEAP32[t+64>>2]=g.mtime.getTime()/1e3|0,HEAP32[t+68>>2]=0,HEAP32[t+72>>2]=g.ctime.getTime()/1e3|0,HEAP32[t+76>>2]=0,tempI64=[g.ino>>>0,(tempDouble=g.ino,1<=+Math_abs(tempDouble)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[t+80>>2]=tempI64[0],HEAP32[t+84>>2]=tempI64[1],0},doMsync:function(A,e,t,g){A=new Uint8Array(HEAPU8.subarray(A,A+t));FS.msync(e,A,0,t,g)},doMkdir:function(A,e){return"/"===(A=PATH.normalize(A))[A.length-1]&&(A=A.substr(0,A.length-1)),FS.mkdir(A,e,0),0},doMknod:function(A,e,t){switch(61440&e){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-22}return FS.mknod(A,e,t),0},doReadlink:function(A,e,t){var g,r;return t<=0?-22:(A=FS.readlink(A),g=Math.min(t,lengthBytesUTF8(A)),r=HEAP8[e+g],stringToUTF8(A,e,t+1),HEAP8[e+g]=r,g)},doAccess:function(A,e){var t;return-8&e?-22:(A=FS.lookupPath(A,{follow:!0}).node)?(t="",4&e&&(t+="r"),2&e&&(t+="w"),1&e&&(t+="x"),t&&FS.nodePermissions(A,t)?-13:0):-2},doDup:function(A,e,t){var g=FS.getStream(t);return g&&FS.close(g),FS.open(A,e,0,t,t).fd},doReadv:function(A,e,t,g){for(var r=0,B=0;B>2],E=HEAP32[e+(8*B+4)>>2],n=FS.read(A,HEAP8,n,E,g);if(n<0)return-1;if(r+=n,n>2],E=HEAP32[e+(8*B+4)>>2],n=FS.write(A,HEAP8,n,E,g);if(n<0)return-1;r+=n}return r},varargs:0,get:function(A){return SYSCALLS.varargs+=4,HEAP32[SYSCALLS.varargs-4>>2]},getStr:function(){return UTF8ToString(SYSCALLS.get())},getStreamFromFD:function(){var A=FS.getStream(SYSCALLS.get());if(A)return A;throw new FS.ErrnoError(9)},get64:function(){var A=SYSCALLS.get();SYSCALLS.get();return A},getZero:function(){SYSCALLS.get()}};function ___syscall140(A,e){SYSCALLS.varargs=e;try{var t=SYSCALLS.getStreamFromFD(),g=SYSCALLS.get(),r=SYSCALLS.get(),B=SYSCALLS.get(),n=SYSCALLS.get(),E=4294967296*g+(r>>>0),C=9007199254740992;return E<=-C||C<=E?-75:(FS.llseek(t,E,n),tempI64=[t.position>>>0,(tempDouble=t.position,1<=+Math_abs(tempDouble)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[B>>2]=tempI64[0],HEAP32[B+4>>2]=tempI64[1],t.getdents&&0==E&&0===n&&(t.getdents=null),0)}catch(A){return void 0!==FS&&A instanceof FS.ErrnoError||abort(A),-A.errno}}function ___syscall146(A,e){SYSCALLS.varargs=e;try{var t=SYSCALLS.getStreamFromFD(),g=SYSCALLS.get(),r=SYSCALLS.get();return SYSCALLS.doWritev(t,g,r)}catch(A){return void 0!==FS&&A instanceof FS.ErrnoError||abort(A),-A.errno}}function ___syscall6(A,e){SYSCALLS.varargs=e;try{var t=SYSCALLS.getStreamFromFD();return FS.close(t),0}catch(A){return void 0!==FS&&A instanceof FS.ErrnoError||abort(A),-A.errno}}function getShiftFromSize(A){switch(A){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+A)}}function embind_init_charCodes(){for(var A=new Array(256),e=0;e<256;++e)A[e]=String.fromCharCode(e);embind_charCodes=A}var embind_charCodes=void 0;function readLatin1String(A){for(var e="",t=A;HEAPU8[t];)e+=embind_charCodes[HEAPU8[t++]];return e}var awaitingDependencies={},registeredTypes={},typeDependencies={},char_0=48,char_9=57;function makeLegalFunctionName(A){var e;return void 0===A?"_unknown":(e=(A=A.replace(/[^a-zA-Z0-9_]/g,"$")).charCodeAt(0),char_0<=e&&e<=char_9?"_"+A:A)}function createNamedFunction(A,e){return A=makeLegalFunctionName(A),new Function("body","return function "+A+'() {\n "use strict"; return body.apply(this, arguments);\n};\n')(e)}function extendError(A,e){var t=createNamedFunction(e,function(A){this.name=e,this.message=A;A=new Error(A).stack;void 0!==A&&(this.stack=this.toString()+"\n"+A.replace(/^Error(:[^\n]*)?\n/,""))});return t.prototype=Object.create(A.prototype),(t.prototype.constructor=t).prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message},t}var BindingError=void 0;function throwBindingError(A){throw new BindingError(A)}var InternalError=void 0;function registerType(A,e,t){if(t=t||{},!("argPackAdvance"in e))throw new TypeError("registerType registeredInstance requires argPackAdvance");var g=e.name;if(A||throwBindingError('type "'+g+'" must have a positive integer typeid pointer'),registeredTypes.hasOwnProperty(A)){if(t.ignoreDuplicateRegistrations)return;throwBindingError("Cannot register type '"+g+"' twice")}registeredTypes[A]=e,delete typeDependencies[A],awaitingDependencies.hasOwnProperty(A)&&(t=awaitingDependencies[A],delete awaitingDependencies[A],t.forEach(function(A){A()}))}function __embind_register_bool(A,t,g,r,B){var n=getShiftFromSize(g);registerType(A,{name:t=readLatin1String(t),fromWireType:function(A){return!!A},toWireType:function(A,e){return e?r:B},argPackAdvance:8,readValueFromPointer:function(A){var e;if(1===g)e=HEAP8;else if(2===g)e=HEAP16;else{if(4!==g)throw new TypeError("Unknown boolean type size: "+t);e=HEAP32}return this.fromWireType(e[A>>n])},destructorFunction:null})}var emval_free_list=[],emval_handle_array=[{},{value:{href:"blob:https://tv.cctv.com/a2a31e32-7705-4db1-b190-1bd401598188"}},{value:null},{value:!0},{value:!1}];function __emval_decref(A){4>2])}function __embind_register_emval(A,e){registerType(A,{name:e=readLatin1String(e),fromWireType:function(A){var e=emval_handle_array[A].value;return __emval_decref(A),e},toWireType:function(A,e){return __emval_register(e)},argPackAdvance:8,readValueFromPointer:simpleReadValueFromPointer,destructorFunction:null})}function _embind_repr(A){var e;return null===A?"null":"object"==(e=typeof A)||"array"==e||"function"==e?A.toString():""+A}function floatReadValueFromPointer(A,e){switch(e){case 2:return function(A){return this.fromWireType(HEAPF32[A>>2])};case 3:return function(A){return this.fromWireType(HEAPF64[A>>3])};default:throw new TypeError("Unknown float type: "+A)}}function __embind_register_float(A,e,t){t=getShiftFromSize(t);registerType(A,{name:e=readLatin1String(e),fromWireType:function(A){return A},toWireType:function(A,e){if("number"!=typeof e&&"boolean"!=typeof e)throw new TypeError('Cannot convert "'+_embind_repr(e)+'" to '+this.name);return e},argPackAdvance:8,readValueFromPointer:floatReadValueFromPointer(e,t),destructorFunction:null})}function integerReadValueFromPointer(A,e,t){switch(e){case 0:return t?function(A){return HEAP8[A]}:function(A){return HEAPU8[A]};case 1:return t?function(A){return HEAP16[A>>1]}:function(A){return HEAPU16[A>>1]};case 2:return t?function(A){return HEAP32[A>>2]}:function(A){return HEAPU32[A>>2]};default:throw new TypeError("Unknown integer type: "+A)}}function __embind_register_integer(A,t,e,g,r){t=readLatin1String(t),-1===r&&(r=4294967295);var B,n=getShiftFromSize(e),E=function(A){return A},C=(0===g&&(B=32-8*e,E=function(A){return A<>>B}),-1!=t.indexOf("unsigned"));registerType(A,{name:t,fromWireType:E,toWireType:function(A,e){if("number"!=typeof e&&"boolean"!=typeof e)throw new TypeError('Cannot convert "'+_embind_repr(e)+'" to '+this.name);if(e>>0:0|e},argPackAdvance:8,readValueFromPointer:integerReadValueFromPointer(t,n,0!==g),destructorFunction:null})}function __embind_register_memory_view(A,e,t){var g=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][e];function r(A){var e=HEAPU32,t=e[A>>=2],A=e[A+1];return new g(e.buffer,A,t)}registerType(A,{name:t=readLatin1String(t),fromWireType:r,argPackAdvance:8,readValueFromPointer:r},{ignoreDuplicateRegistrations:!0})}function __embind_register_std_string(A,e){var I="std::string"===(e=readLatin1String(e));registerType(A,{name:e,fromWireType:function(A){var e=HEAPU32[A>>2];if(I){for(var t=HEAPU8[A+4+e],g=0,r=(0!=t&&(g=t,HEAPU8[A+4+e]=0),A+4),B=0;B<=e;++B){var n,E,C=A+4+B;0==HEAPU8[C]&&(n=UTF8ToString(r),E=void 0===E?n:E+String.fromCharCode(0)+n,r=C+1)}0!=g&&(HEAPU8[A+4+e]=g)}else{for(var o=new Array(e),B=0;B>2]=g,I&&t)stringToUTF8(e,r+4,g+1);else if(t)for(var B=0;B>2],g=new Array(t),r=A+4>>o,B=0;B>2]=g,r+4>>o),n=0;n>2]=r,e.toWireType(g,A)}var emval_symbols={};function getStringOrSymbol(A){var e=emval_symbols[A];return void 0===e?readLatin1String(A):e}function emval_get_global(){return"object"==typeof globalThis?globalThis:Function("return this")()}function __emval_get_global(A){return 0===A?__emval_register(emval_get_global()):(A=getStringOrSymbol(A),__emval_register(emval_get_global()[A]))}function __emval_get_property(A,e){return __emval_register((A=requireHandle(A))[e=requireHandle(e)])}function runDestructors(A){for(;A.length;){var e=A.pop();A.pop()(e)}}function __emval_run_destructors(A){runDestructors(emval_handle_array[A].value),__emval_decref(A)}function __emval_take_value(A,e){return __emval_register((A=requireRegisteredType(A,"_emval_take_value")).readValueFromPointer(e))}function _abort(){Module.abort()}function _emscripten_date_now(){return Date.now()}function __emscripten_traverse_stack(A){if(!A||!A.callee||!A.callee.name)return[null,"",""];A.callee.toString();var e,t=A.callee.name,g="(",r=!0;for(e in A){var B=A[e];r||(g+=", "),r=!1,g+="number"==typeof B||"string"==typeof B?B:"("+typeof B+")"}g+=")";var n=A.callee.caller;return[A=n?n.arguments:[],t,g=r?"":g]}function _emscripten_get_callstack_js(A){var e=(g=jsStackTrace()).lastIndexOf("_emscripten_log"),t=g.lastIndexOf("_emscripten_get_callstack"),e=g.indexOf("\n",Math.max(e,t))+1,g=g.slice(e),r=(8&A&&"undefined"==typeof emscripten_source_map&&(warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.'),A=8^A|16),null);if(128&A)for(r=__emscripten_traverse_stack(arguments);0<=r[1].indexOf("_emscripten_");)r=__emscripten_traverse_stack(r[0]);var B,n=g.split("\n"),E=(g="",new RegExp("\\s*(.*?)@(.*?):([0-9]+):([0-9]+)")),C=new RegExp("\\s*(.*?)@(.*):(.*)(:(.*))?"),o=new RegExp("\\s*at (.*?) \\((.*):(.*):(.*)\\)");for(B in n){var I=n[B],Q="",i="",a=0,s=0,l=o.exec(I);if(l&&5==l.length)Q=l[1],i=l[2],a=l[3],s=l[4];else{if(!((l=(l=E.exec(I))||C.exec(I))&&4<=l.length)){g+=I+"\n";continue}Q=l[1],i=l[2],a=l[3],s=0|l[4]}var c,I=(I=32&A?demangle(Q):Q)||Q,l=!1;8&A&&(l=(c=emscripten_source_map.originalPositionFor({line:a,column:s}))&&c.source)&&(64&A&&(c.source=c.source.substring(c.source.replace(/\\/g,"/").lastIndexOf("/")+1)),g+=" at "+I+" ("+c.source+":"+c.line+":"+c.column+")\n"),(16&A||!l)&&(g+=(l?" = "+Q:" at "+I)+" ("+(i=64&A?i.substring(i.replace(/\\/g,"/").lastIndexOf("/")+1):i)+":"+a+":"+s+")\n"),128&A&&r[0]&&(r[1]==Q&&0>3],r+=8):"i64"==A?(e=[HEAP32[r>>2],HEAP32[r+4>>2]],r+=8):(assert(0==(3&r)),A="i32",e=HEAP32[r>>2],r+=4),e}for(var B,n=[];;){var E,C=t;if(0===(E=HEAP8[t>>0]))break;if(B=HEAP8[t+1>>0],37==E){var o=!1,I=!1,Q=!1,i=!1,a=!1;A:for(;;){switch(B){case 43:o=!0;break;case 45:I=!0;break;case 35:Q=!0;break;case 48:if(i)break A;i=!0;break;case 32:a=!0;break;default:break A}B=HEAP8[++t+1>>0]}var s=0;if(42==B)s=g("i32"),B=HEAP8[++t+1>>0];else for(;48<=B&&B<=57;)s=10*s+(B-48),B=HEAP8[++t+1>>0];var l=!1,c=-1;if(46==B){if(l=!(c=0),42==(B=HEAP8[++t+1>>0]))c=g("i32"),t++;else for(;;){var w=HEAP8[t+1>>0];if(w<48||57>0]}switch(c<0&&(l=!(c=6)),String.fromCharCode(B)){case"h":var u=104==HEAP8[t+2>>0]?(t++,1):2;break;case"l":u=108==HEAP8[t+2>>0]?(t++,8):4;break;case"L":case"q":case"j":u=8;break;case"z":case"t":case"I":u=4;break;default:u=null}switch(u&&t++,B=HEAP8[t+1>>0],String.fromCharCode(B)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":var M,d,F=100==B||105==B,F=(d=g("i"+8*(u=u||4)),8==u&&(d=makeBigInt(d[0],d[1],117==B)),u<=4&&(d=(F?reSign:unSign)(d&Math.pow(256,u)-1,8*u)),Math.abs(d)),f="";if(100==B||105==B)M=reSign(d,8*u,1).toString(10);else if(117==B)M=unSign(d,8*u,1).toString(10),d=Math.abs(d);else if(111==B)M=(Q?"0":"")+F.toString(8);else if(120==B||88==B){if(f=Q&&0!=d?"0x":"",d<0){d=-d,M=(F-1).toString(16);for(var Y=[],D=0;Dh++;)R[0]+="0";M=R[0]+(1>0]);else n=n.concat(intArrayFromString("(null)".substr(0,y),!0));if(I)for(;y>2]=n.length;break;case"%":n.push(E);break;default:for(D=C;D>0])}t+=2}else n.push(E),t+=1}return n}function _emscripten_log_js(A,e){24&A&&(e=e.replace(/\s+$/,""),e+=(0>2],g=(e+=4,"");if(t)for(var r=__formatString(t,e),B=0;B>2]=e,HEAPU32[A+4>>2]=e/4294967296|0},openDatabase:function(A,e,t,g){try{var r=indexedDB.open(A,e)}catch(A){return g(A)}r.onupgradeneeded=function(A){A=A.target.result;A.objectStoreNames.contains("FILES")&&A.deleteObjectStore("FILES"),A.createObjectStore("FILES")},r.onsuccess=function(A){t(A.target.result)},r.onerror=function(A){g(A)}},staticInit:function(){var e="undefined"==typeof ENVIRONMENT_IS_FETCH_WORKER;Fetch.openDatabase("emscripten_filesystem",1,function(A){Fetch.dbInstance=A,e&&removeRunDependency("library_fetch_init")},function(){Fetch.dbInstance=!1,e&&removeRunDependency("library_fetch_init")}),"undefined"!=typeof ENVIRONMENT_IS_FETCH_WORKER&&ENVIRONMENT_IS_FETCH_WORKER||addRunDependency("library_fetch_init")}};function __emscripten_fetch_xhr(r,B,n,g,e){var A=HEAPU32[r+8>>2];if(A){var A=UTF8ToString(A),t=r+112,E=(E=UTF8ToString(t))||"GET",C=(HEAPU32[t+32>>2],HEAPU32[t+52>>2]),o=HEAPU32[t+56>>2],I=!!HEAPU32[t+60>>2],Q=(HEAPU32[t+64>>2],HEAPU32[t+68>>2]),i=HEAPU32[t+72>>2],a=HEAPU32[t+76>>2],s=HEAPU32[t+80>>2],l=HEAPU32[t+84>>2],t=HEAPU32[t+88>>2],c=!!(1&C),w=!!(2&C),C=!!(64&C),Q=Q?UTF8ToString(Q):void 0,i=i?UTF8ToString(i):void 0,u=s?UTF8ToString(s):void 0,M=new XMLHttpRequest;if(M.withCredentials=I,M.open(E,A,!C,Q,i),C||(M.timeout=o),M.url_=A,assert(!w,"streaming uses moz-chunked-arraybuffer which is no longer supported; TODO: rewrite using fetch()"),M.responseType="arraybuffer",s&&M.overrideMimeType(u),a)for(;;){var d=HEAPU32[a>>2];if(!d)break;var F=HEAPU32[a+4>>2];if(!F)break;a+=8;d=UTF8ToString(d),F=UTF8ToString(F);M.setRequestHeader(d,F)}Fetch.xhrs.push(M);I=Fetch.xhrs.length,E=(HEAPU32[r+0>>2]=I,l&&t?HEAPU8.slice(l,l+t):null);M.onload=function(A){var e=M.response?M.response.byteLength:0,t=0,g=0;c&&!w&&(t=_malloc(g=e),HEAPU8.set(new Uint8Array(M.response),t)),HEAPU32[r+12>>2]=t,Fetch.setu64(r+16,g),Fetch.setu64(r+24,0),e&&Fetch.setu64(r+32,e),HEAPU16[r+40>>1]=M.readyState,4===M.readyState&&0===M.status&&(M.status=0>1]=M.status,M.statusText&&stringToUTF8(M.statusText,r+44,64),200<=M.status&&M.status<300?B&&B(r,M,A):n&&n(r,M,A)},M.onerror=function(A){var e=M.status;4===M.readyState&&0===e&&(e=404),HEAPU32[r+12>>2]=0,Fetch.setu64(r+16,0),Fetch.setu64(r+24,0),Fetch.setu64(r+32,0),HEAPU16[r+40>>1]=M.readyState,HEAPU16[r+42>>1]=e,n&&n(r,M,A)},M.ontimeout=function(A){n&&n(r,M,A)},M.onprogress=function(A){var e=c&&w&&M.response?M.response.byteLength:0,t=0;c&&w&&(t=_malloc(e),HEAPU8.set(new Uint8Array(M.response),t)),HEAPU32[r+12>>2]=t,Fetch.setu64(r+16,e),Fetch.setu64(r+24,A.loaded-e),Fetch.setu64(r+32,A.total),HEAPU16[r+40>>1]=M.readyState,3<=M.readyState&&0===M.status&&0>1]=M.status,M.statusText&&stringToUTF8(M.statusText,r+44,64),g&&g(r,M,A)},M.onreadystatechange=function(A){HEAPU16[r+40>>1]=M.readyState,2<=M.readyState&&(HEAPU16[r+42>>1]=M.status),e&&e(r,M,A)};try{M.send(E)}catch(A){n&&n(r,M,A)}}else n(r,0,"no url specified!")}function __emscripten_fetch_cache_data(A,e,t,g,r){if(A){var B=UTF8ToString(HEAPU32[e+112+64>>2]||HEAPU32[e+8>>2]);try{var n=A.transaction(["FILES"],"readwrite").objectStore("FILES").put(t,B);n.onsuccess=function(A){HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=200,stringToUTF8("OK",e+44,64),g(e,0,B)},n.onerror=function(A){HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=413,stringToUTF8("Payload Too Large",e+44,64),r(e,0,A)}}catch(A){r(e,0,A)}}else r(e,0,"IndexedDB not available!")}function __emscripten_fetch_load_cached_data(A,g,r,B){if(A){var e=UTF8ToString(HEAPU32[g+112+64>>2]||HEAPU32[g+8>>2]);try{var t=A.transaction(["FILES"],"readonly").objectStore("FILES").get(e);t.onsuccess=function(A){var e,t;A.target.result?(e=(A=A.target.result).byteLength||A.length,t=_malloc(e),HEAPU8.set(new Uint8Array(A),t),HEAPU32[g+12>>2]=t,Fetch.setu64(g+16,e),Fetch.setu64(g+24,0),Fetch.setu64(g+32,e),HEAPU16[g+40>>1]=4,HEAPU16[g+42>>1]=200,stringToUTF8("OK",g+44,64),r(g,0,A)):(HEAPU16[g+40>>1]=4,HEAPU16[g+42>>1]=404,stringToUTF8("Not Found",g+44,64),B(g,0,"no data"))},t.onerror=function(A){HEAPU16[g+40>>1]=4,HEAPU16[g+42>>1]=404,stringToUTF8("Not Found",g+44,64),B(g,0,A)}}catch(A){B(g,0,A)}}else B(g,0,"IndexedDB not available!")}function __emscripten_fetch_delete_cached_data(A,e,t,g){if(A){var r=UTF8ToString(HEAPU32[e+112+64>>2]||HEAPU32[e+8>>2]);try{var B=A.transaction(["FILES"],"readwrite").objectStore("FILES").delete(r);B.onsuccess=function(A){A=A.target.result;HEAPU32[e+12>>2]=0,Fetch.setu64(e+16,0),Fetch.setu64(e+24,0),Fetch.setu64(e+32,0),HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=200,stringToUTF8("OK",e+44,64),t(e,0,A)},B.onerror=function(A){HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=404,stringToUTF8("Not Found",e+44,64),g(e,0,A)}}catch(A){g(e,0,A)}}else g(e,0,"IndexedDB not available!")}function _emscripten_start_fetch(A,g,r,B,n){void 0!==Module&&(Module.noExitRuntime=!0);function E(A,e,t){i?dynCall_vi(i,A):g&&g(A)}function C(A,e,t){s?dynCall_vi(s,A):B&&B(A)}function o(A,e,t){a?dynCall_vi(a,A):r&&r(A)}function I(A,e,t){l?dynCall_vi(l,A):n&&n(A)}function Q(A,e,t){__emscripten_fetch_cache_data(Fetch.dbInstance,A,e.response,function(A,e,t){i?dynCall_vi(i,A):g&&g(A)},function(A,e,t){i?dynCall_vi(i,A):g&&g(A)})}var e=A+112,t=UTF8ToString(e),i=HEAPU32[e+36>>2],a=HEAPU32[e+40>>2],s=HEAPU32[e+44>>2],l=HEAPU32[e+48>>2],c=HEAPU32[e+52>>2],w=!!(4&c),u=!!(32&c),c=!!(16&c);if((!c||"EM_IDB_STORE"===t||"EM_IDB_DELETE"===t)&&!Fetch.dbInstance)return o(A),0;if("EM_IDB_STORE"===t){var M=HEAPU32[e+84>>2];__emscripten_fetch_cache_data(Fetch.dbInstance,A,HEAPU8.slice(M,M+HEAPU32[e+88>>2]),E,o)}else if("EM_IDB_DELETE"===t)__emscripten_fetch_delete_cached_data(Fetch.dbInstance,A,E,o);else if(c){if(u)return 0;__emscripten_fetch_xhr(A,w?Q:E,o,C,I)}else __emscripten_fetch_load_cached_data(Fetch.dbInstance,A,E,u?o:w?function(A,e,t){__emscripten_fetch_xhr(A,Q,o,C,I)}:function(A,e,t){__emscripten_fetch_xhr(A,E,o,C,I)});return A}function _gettimeofday(A){var e=Date.now();return HEAP32[A>>2]=e/1e3|0,HEAP32[A+4>>2]=e%1e3*1e3|0,0}function _llvm_trap(){abort("trap!")}function _emscripten_memcpy_big(A,e,t){HEAPU8.set(HEAPU8.subarray(e,e+t),A)}function abortOnCannotGrowMemory(A){abort("OOM")}function emscripten_realloc_buffer(A){A=alignUp(A,65536);var e=buffer.byteLength;try{return-1!==wasmMemory.grow((A-e)/65536)?(buffer=wasmMemory.buffer,1):void 0}catch(A){}}function _emscripten_resize_heap(A){var e=_emscripten_get_heap_size(),t=2147418112;if(t>2,t=(3&B)<<6|(n=E.indexOf(A.charAt(o++))),C+=String.fromCharCode(g<<2|r>>4),64!==B&&(C+=String.fromCharCode(e)),64!==n&&(C+=String.fromCharCode(t)),o>2]=allocateUTF8OnStack(thisProgram);for(var g=1;g>2)+g]=allocateUTF8OnStack(A[g-1]);HEAP32[(t>>2)+e]=0;var r,B=Module.emtStackSave();try{var n=Module._main(e,t);Module.noExitRuntime||exit(n,!0)}catch(A){A instanceof ExitStatus||("SimulateInfiniteLoop"==A?(Module.noExitRuntime=!0,Module.emtStackRestore(B)):((r=A)&&"object"==typeof A&&A.stack&&(r=[A,A.stack]),err("exception thrown: "+r),quit_(1,A)))}finally{calledMain=!0}}function run(A){function e(){calledRun||(calledRun=!0,Module.calledRun=!0,ABORT)||(initRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),shouldRunNow&&callMain(A),postRun())}A=A||arguments_,0 { + if (typeof CNTVModuleFactory !== 'function') { + console.error('ERROR: CNTVModuleFactory is not a function:', CNTVModuleFactory); + // Try to handle if it's wrapped in default export + if (CNTVModuleFactory && typeof CNTVModuleFactory.default === 'function') { + CNTVH5PlayerModule = CNTVModuleFactory.default(); + } else if (CNTVModuleFactory && typeof CNTVModuleFactory.CNTVModule === 'function') { + CNTVH5PlayerModule = CNTVModuleFactory.CNTVModule(); + } else { + throw new Error('CNTVModuleFactory is not a function'); + } + } else { + CNTVH5PlayerModule = CNTVModuleFactory(); + } + + await new Promise((resolve) => { + if (CNTVH5PlayerModule.calledRun) resolve(); + else CNTVH5PlayerModule.onRuntimeInitialized = resolve; + }); + })(); + await wasmInitPromise; +} + +// ==================== 从网络地址获取二进制数据 ==================== +async function getBinaryFromUrl(url) { + try { + const response = await axios.get(url, { + responseType: 'arraybuffer', + timeout: 60000, + headers: {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'} + }); + if (response.status !== 200) { + throw new Error(`Failed to fetch binary: ${response.status} ${response.statusText}`); + } + return new Uint8Array(response.data); + } catch (error) { + throw new Error(`Request failed: ${error.message}`); + } +} + +// ==================== NAL单元处理 ==================== +function findNALUnits(buffer) { + const nalUnits = []; + let i = 0; + while (i < buffer.length - 3) { + if (buffer[i] === 0x00 && buffer[i + 1] === 0x00) { + let nalStart = -1; + if (buffer[i + 2] === 0x01 && i + 3 < buffer.length) { + nalStart = i + 3; + } else if (buffer[i + 2] === 0x00 && buffer[i + 3] === 0x01 && i + 4 < buffer.length) { + nalStart = i + 4; + } + if (nalStart >= 0) { + let nextStart = buffer.length; + for (let j = nalStart; j < buffer.length - 2; j++) { + if (buffer[j] === 0x00 && buffer[j + 1] === 0x00) { + if (buffer[j + 2] === 0x01 || (buffer[j + 2] === 0x00 && j + 3 < buffer.length && buffer[j + 3] === 0x01)) { + nextStart = j; + break; + } + } + } + const nalData = buffer.subarray(i, nextStart); + if (nalData.length >= 2) { + const header = nalData[nalStart - i]; + const data = nalData.subarray(nalStart - i + 1); + const nal = {header, data, nalUnitType: header & 0x1F}; + nalUnits.push(nal); + } + i = nextStart; + continue; + } + } + i++; + } + return nalUnits; +} + +// ==================== H.264解密核心 ==================== +// 解密H.264数据,保持原始数据结构不变,直接在原buffer上修改 +// 优化内存使用:避免创建不必要的buffer副本和对象 +async function decryptH264InPlace(h264Data) { + let curDate = Date.now().toString(); + const MemoryExtend = 2048; + let vmpTag = ''; + + // 预分配临时解密buffer(复用) + const maxDecryptBufSize = 1024 * 1024; // 1MB上限,足够处理单个NAL + const tempDecryptBuf = Buffer.allocUnsafe(maxDecryptBufSize); + + function _common(o) { + const memory = CNTVH5PlayerModule._jsmalloc(curDate.length + MemoryExtend); + CNTVH5PlayerModule.HEAP8.fill(0, memory, memory + curDate.length + MemoryExtend); + CNTVH5PlayerModule.HEAP8.set(Array.from(curDate, e => e.charCodeAt(0)), memory); + let ret; + switch (o) { + case "InitPlayer": + ret = CNTVH5PlayerModule._CNTV_InitPlayer(memory); + break; + case "UnInitPlayer": + ret = CNTVH5PlayerModule._CNTV_UnInitPlayer(memory); + break; + case "UpdatePlayer": + vmpTag = CNTVH5PlayerModule._CNTV_UpdatePlayer(memory).toString(16); + vmpTag = ['0'.repeat(8 - vmpTag.length), vmpTag].join(''); + ret = 0; + break; + } + CNTVH5PlayerModule._jsfree(memory); + return ret; + } + + function InitPlayer() { + return _common("InitPlayer"); + } + + function UnInitPlayer() { + return _common("UnInitPlayer"); + } + + function UpdatePlayer() { + return _common("UpdatePlayer"); + } + + // 解密到预分配的buffer,返回实际解密长度 + function decryptToBuf(srcBuf, destBuf) { + const pageHost = "https://tv.cctv.com"; + const addr = CNTVH5PlayerModule._jsmalloc(srcBuf.length + MemoryExtend); + const StaticCallModuleVod = { + H264NalSet: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD7(t, i, n, r); + }, + H265NalData: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD6(t, i, n, r); + }, + AVS1AudioKey: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD5(t, i, n, r); + }, + HEVC2AAC: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD4(t, i, n, r); + }, + HASHMap: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD3(t, i, n, r); + }, + BASE64Dec: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD2(t, i, n, r); + }, + MediaSession: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD1(t, i, n, r); + }, + Mp4fragment: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD0(t, i, n, r); + }, + MpegAudio: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD8(t, i, n, r); + }, + AACDemuxer: function (e, t, i, n, r) { + return e._jsdecVOD(i, n, r); + } + }; + + function StaticCallModuleVodAPI(e, t, i, n, r, a) { + return StaticCallModuleVod[a](e, t, i, n, r); + } + + CNTVH5PlayerModule.HEAP8.set(srcBuf, addr); + CNTVH5PlayerModule.HEAP8.set(Array.from(pageHost, e => e.charCodeAt(0)), addr + srcBuf.length); + const addr2 = CNTVH5PlayerModule._jsmalloc(curDate.length); + CNTVH5PlayerModule.HEAP8.set(Array.from(curDate, e => e.charCodeAt(0)), addr2); + + for (const i in vmpTag) + if ("0123456".includes(vmpTag[i])) + StaticCallModuleVodAPI(CNTVH5PlayerModule, addr2, addr, srcBuf.length, pageHost.length, Object.keys(StaticCallModuleVod)[i]); + + const decRet = StaticCallModuleVodAPI(CNTVH5PlayerModule, addr2, addr, srcBuf.length, pageHost.length, Object.keys(StaticCallModuleVod)[8]); + + // 复制到预分配的buffer (HEAP8是Uint8Array,使用set方法) + const copyLen = Math.min(decRet, destBuf.length); + destBuf.set(CNTVH5PlayerModule.HEAP8.subarray(addr, addr + copyLen)); + + CNTVH5PlayerModule._jsfree(addr); + CNTVH5PlayerModule._jsfree(addr2); + return decRet; + } + + // 找到所有NAL单元的位置信息(只存储必要的位置信息,不存储数据引用) + const nalUnits = []; // { dataPos, dataEnd, header, nalUnitType } + let i = 0; + while (i < h264Data.length - 3) { + if (h264Data[i] === 0x00 && h264Data[i + 1] === 0x00) { + let startCodeLen = 0; + let nalStart = -1; + + // 查找起始码 + if (h264Data[i + 2] === 0x01 && i + 3 < h264Data.length) { + startCodeLen = 3; + nalStart = i + 3; + } else if (h264Data[i + 2] === 0x00 && h264Data[i + 3] === 0x01 && i + 4 < h264Data.length) { + startCodeLen = 4; + nalStart = i + 4; + } + + if (nalStart >= 0) { + // 找到下一个起始码位置 + let nextStart = h264Data.length; + for (let j = nalStart; j < h264Data.length - 2; j++) { + if (h264Data[j] === 0x00 && h264Data[j + 1] === 0x00) { + if (h264Data[j + 2] === 0x01 || (h264Data[j + 2] === 0x00 && j + 3 < h264Data.length && h264Data[j + 3] === 0x01)) { + nextStart = j; + break; + } + } + } + + const header = h264Data[nalStart]; + const dataStart = nalStart + 1; + const dataEnd = nextStart; + const nalUnitType = header & 0x1F; + + // 只存储位置信息,不存储subarray引用 + nalUnits.push({ + dataPos: dataStart, + dataEnd: dataEnd, + header: header, + dataLen: dataEnd - dataStart, + nalUnitType: nalUnitType + }); + + i = nextStart; + continue; + } + } + i++; + } + + // 解密并替换原始buffer中的数据(原地修改) + let shouldDecrypt = false; + curDate = Date.now().toString(); + InitPlayer(); + + for (const nal of nalUnits) { + UpdatePlayer(); + + // 将数据复制到预分配的buffer进行解密 + const nalLen = nal.dataLen + 1; // +1 for header + if (nalLen > maxDecryptBufSize) continue; // 跳过过大的NAL + + // 复制header + data到临时buffer + tempDecryptBuf[0] = nal.header; + h264Data.copy(tempDecryptBuf, 1, nal.dataPos, nal.dataEnd); + + if (nal.nalUnitType === 25) { + shouldDecrypt = h264Data[nal.dataPos] === 1; + if (shouldDecrypt) { + decryptToBuf(tempDecryptBuf.subarray(0, nalLen), tempDecryptBuf); + } + } else if ((nal.nalUnitType === 1 || nal.nalUnitType === 5) && shouldDecrypt) { + const decLen = decryptToBuf(tempDecryptBuf.subarray(0, nalLen), tempDecryptBuf); + // 解密结果从索引1开始(跳过header) + const decryptedDataLen = decLen - 1; + const writePos = nal.dataPos; + + // 原地替换 + if (decryptedDataLen <= nal.dataLen) { + // 解密数据更小或相等 + if (decryptedDataLen > 0) { + tempDecryptBuf.copy(h264Data, writePos, 1, 1 + decryptedDataLen); + } + if (decryptedDataLen < nal.dataLen) { + h264Data.fill(0, writePos + decryptedDataLen, nal.dataEnd); + } + } else { + // 解密数据更大,截断 + tempDecryptBuf.copy(h264Data, writePos, 1, 1 + nal.dataLen); + } + } + } + UnInitPlayer(); + + return h264Data; +} + +// ==================== TS解密处理函数 ==================== +async function Parse_TS(buffer) { + // 确保WASM模块已初始化 + await initWasmModule(); + + const originalTS = Buffer.from(buffer); + + // 第一遍扫描:计算视频数据总量并收集PES包信息 + const videoPESRanges = []; // 只存储位置和长度信息,不存储数据引用 + let totalH264Size = 0; + let currentPESDataSize = 0; + let inPES = false; + + for (let i = 0; i < originalTS.length; i += TS_PACKET_SIZE) { + if (i + TS_PACKET_SIZE > originalTS.length) break; + const packet = originalTS.subarray(i, i + TS_PACKET_SIZE); + if (packet[0] !== 0x47) continue; + + const pid = ((packet[1] & 0x1F) << 8) | packet[2]; + if (pid !== VIDEO_PID) continue; + + const payloadStart = (packet[1] & 0x40) !== 0; + const adaptation = (packet[3] & 0x20) !== 0; + const payload = (packet[3] & 0x10) !== 0; + + let offset = 4; + if (adaptation && offset < 188) { + const adaptationLen = packet[offset]; + offset += adaptationLen + 1; + } + + if (payload && offset < 188) { + const dataSize = 188 - offset; + + if (payloadStart) { + // 保存上一个PES包的范围信息 + if (inPES && currentPESDataSize > 0) { + videoPESRanges.push({ size: currentPESDataSize }); + totalH264Size += currentPESDataSize; + } + + // 开始新的PES包 - 只计算数据大小 + let pesHeaderEnd = 9; + const data = packet.subarray(offset); + if (data.length >= 9) { + pesHeaderEnd = 9 + data[8]; + } + pesHeaderEnd = Math.min(pesHeaderEnd, data.length); + + const pesPayloadSize = dataSize - pesHeaderEnd; + currentPESDataSize = pesPayloadSize; + inPES = true; + } else if (inPES) { + currentPESDataSize += dataSize; + } + } + } + + // 保存最后一个PES包 + if (inPES && currentPESDataSize > 0) { + videoPESRanges.push({ size: currentPESDataSize }); + totalH264Size += currentPESDataSize; + } + + // 如果没有视频数据,直接返回原始TS + if (totalH264Size === 0) { + return originalTS; + } + + // 第二遍扫描:一次性提取所有H.264数据到预分配的buffer + const h264Data = Buffer.allocUnsafe(totalH264Size); + let h264WritePos = 0; + inPES = false; + + for (let i = 0; i < originalTS.length; i += TS_PACKET_SIZE) { + if (i + TS_PACKET_SIZE > originalTS.length) break; + const packet = originalTS.subarray(i, i + TS_PACKET_SIZE); + if (packet[0] !== 0x47) continue; + + const pid = ((packet[1] & 0x1F) << 8) | packet[2]; + if (pid !== VIDEO_PID) continue; + + const payloadStart = (packet[1] & 0x40) !== 0; + const adaptation = (packet[3] & 0x20) !== 0; + const payload = (packet[3] & 0x10) !== 0; + + let offset = 4; + if (adaptation && offset < 188) { + const adaptationLen = packet[offset]; + offset += adaptationLen + 1; + } + + if (payload && offset < 188) { + if (payloadStart) { + let pesHeaderEnd = 9; + const data = packet.subarray(offset); + if (data.length >= 9) { + pesHeaderEnd = 9 + data[8]; + } + pesHeaderEnd = Math.min(pesHeaderEnd, data.length); + + const pesPayload = packet.subarray(offset + pesHeaderEnd); + pesPayload.copy(h264Data, h264WritePos); + h264WritePos += pesPayload.length; + inPES = true; + } else if (inPES) { + const data = packet.subarray(offset); + data.copy(h264Data, h264WritePos); + h264WritePos += data.length; + } + } + } + + // 解密H.264数据(原地修改) + const decryptedH264 = await decryptH264InPlace(h264Data); + + // 第三遍扫描:将解密数据写回,原地修改originalTS + let h264ReadPos = 0; + + for (let i = 0; i < originalTS.length; i += TS_PACKET_SIZE) { + if (i + TS_PACKET_SIZE > originalTS.length) break; + + const pid = ((originalTS[i + 1] & 0x1F) << 8) | originalTS[i + 2]; + if (pid !== VIDEO_PID) continue; + + const payloadStart = (originalTS[i + 1] & 0x40) !== 0; + const adaptation = (originalTS[i + 3] & 0x20) !== 0; + const payload = (originalTS[i + 3] & 0x10) !== 0; + + let offset = 4; + if (adaptation && offset < 188) { + const adaptationLen = originalTS[i + offset]; + offset += adaptationLen + 1; + } + + if (payload && offset < 188) { + if (payloadStart) { + let pesHeaderEnd = 9; + if (offset + 9 <= 188) { + pesHeaderEnd = 9 + originalTS[i + offset + 8]; + } + pesHeaderEnd = Math.min(pesHeaderEnd, 188 - offset); + + // 跳过PES头,直接写入解密后的H.264数据 + const writeOffset = i + offset + pesHeaderEnd; + const remaining = 188 - offset - pesHeaderEnd; + const toCopy = Math.min(remaining, decryptedH264.length - h264ReadPos); + + if (toCopy > 0) { + decryptedH264.copy(originalTS, writeOffset, h264ReadPos, h264ReadPos + toCopy); + h264ReadPos += toCopy; + } + + // 填充剩余空间 + if (toCopy < remaining) { + originalTS.fill(0xFF, writeOffset + toCopy, i + 188); + } + } else { + const writeOffset = i + offset; + const remaining = 188 - offset; + const toCopy = Math.min(remaining, decryptedH264.length - h264ReadPos); + + if (toCopy > 0) { + decryptedH264.copy(originalTS, writeOffset, h264ReadPos, h264ReadPos + toCopy); + h264ReadPos += toCopy; + } + + if (toCopy < remaining) { + originalTS.fill(0xFF, writeOffset + toCopy, i + 188); + } + } + } + } + + return originalTS; +} + +// ==================== 主处理函数 ==================== +async function processFile(url, extension) { + // 下载原始TS文件 + let buffer = await getBinaryFromUrl(url); + + // 如果是.ts文件,调用Parse_TS进行解密 + if (extension === '.ts') { + buffer = await Parse_TS(buffer); + } + + return buffer; +} + +module.exports = { + processFile, +} diff --git a/drpy-node-bundle/spider/js/_lib.tingyou.js b/drpy-node-bundle/spider/js/_lib.tingyou.js new file mode 100644 index 00000000..410345d6 --- /dev/null +++ b/drpy-node-bundle/spider/js/_lib.tingyou.js @@ -0,0 +1,922 @@ +function Co(e) { + for (let t = 0; t < e.length; t++) + e[t] = 0; + return e +} + +function _o(e, t=new Uint8Array(4), n=0) { + return t[n + 0] = e >>> 0, + t[n + 1] = e >>> 8, + t[n + 2] = e >>> 16, + t[n + 3] = e >>> 24, + t +} + +function Do(e, t, n) { + let a = 1634760805 + , o = 857760878 + , r = 2036477234 + , s = 1797285236 + , i = e[3] << 24 | e[2] << 16 | e[1] << 8 | e[0] + , l = e[7] << 24 | e[6] << 16 | e[5] << 8 | e[4] + , c = e[11] << 24 | e[10] << 16 | e[9] << 8 | e[8] + , u = e[15] << 24 | e[14] << 16 | e[13] << 8 | e[12] + , d = e[19] << 24 | e[18] << 16 | e[17] << 8 | e[16] + , f = e[23] << 24 | e[22] << 16 | e[21] << 8 | e[20] + , v = e[27] << 24 | e[26] << 16 | e[25] << 8 | e[24] + , p = e[31] << 24 | e[30] << 16 | e[29] << 8 | e[28] + , h = t[3] << 24 | t[2] << 16 | t[1] << 8 | t[0] + , m = t[7] << 24 | t[6] << 16 | t[5] << 8 | t[4] + , y = t[11] << 24 | t[10] << 16 | t[9] << 8 | t[8] + , g = t[15] << 24 | t[14] << 16 | t[13] << 8 | t[12]; + for (let k = 0; k < 20; k += 2) + a = a + i | 0, + h ^= a, + h = h >>> 16 | h << 16, + d = d + h | 0, + i ^= d, + i = i >>> 20 | i << 12, + o = o + l | 0, + m ^= o, + m = m >>> 16 | m << 16, + f = f + m | 0, + l ^= f, + l = l >>> 20 | l << 12, + r = r + c | 0, + y ^= r, + y = y >>> 16 | y << 16, + v = v + y | 0, + c ^= v, + c = c >>> 20 | c << 12, + s = s + u | 0, + g ^= s, + g = g >>> 16 | g << 16, + p = p + g | 0, + u ^= p, + u = u >>> 20 | u << 12, + r = r + c | 0, + y ^= r, + y = y >>> 24 | y << 8, + v = v + y | 0, + c ^= v, + c = c >>> 25 | c << 7, + s = s + u | 0, + g ^= s, + g = g >>> 24 | g << 8, + p = p + g | 0, + u ^= p, + u = u >>> 25 | u << 7, + o = o + l | 0, + m ^= o, + m = m >>> 24 | m << 8, + f = f + m | 0, + l ^= f, + l = l >>> 25 | l << 7, + a = a + i | 0, + h ^= a, + h = h >>> 24 | h << 8, + d = d + h | 0, + i ^= d, + i = i >>> 25 | i << 7, + a = a + l | 0, + g ^= a, + g = g >>> 16 | g << 16, + v = v + g | 0, + l ^= v, + l = l >>> 20 | l << 12, + o = o + c | 0, + h ^= o, + h = h >>> 16 | h << 16, + p = p + h | 0, + c ^= p, + c = c >>> 20 | c << 12, + r = r + u | 0, + m ^= r, + m = m >>> 16 | m << 16, + d = d + m | 0, + u ^= d, + u = u >>> 20 | u << 12, + s = s + i | 0, + y ^= s, + y = y >>> 16 | y << 16, + f = f + y | 0, + i ^= f, + i = i >>> 20 | i << 12, + r = r + u | 0, + m ^= r, + m = m >>> 24 | m << 8, + d = d + m | 0, + u ^= d, + u = u >>> 25 | u << 7, + s = s + i | 0, + y ^= s, + y = y >>> 24 | y << 8, + f = f + y | 0, + i ^= f, + i = i >>> 25 | i << 7, + o = o + c | 0, + h ^= o, + h = h >>> 24 | h << 8, + p = p + h | 0, + c ^= p, + c = c >>> 25 | c << 7, + a = a + l | 0, + g ^= a, + g = g >>> 24 | g << 8, + v = v + g | 0, + l ^= v, + l = l >>> 25 | l << 7; + return _o(a, n, 0), + _o(o, n, 4), + _o(r, n, 8), + _o(s, n, 12), + _o(h, n, 16), + _o(m, n, 20), + _o(y, n, 24), + _o(g, n, 28), + n +} + +class Po { + nonceLength = 24; + tagLength = 16; + _key; + constructor(e) { + if (32 !== e.length) + throw new Error("ChaCha20Poly1305 needs 32-byte key"); + this._key = new Uint8Array(e) + } + seal(e, t, n, a) { + if (24 !== e.length) + throw new Error("XChaCha20Poly1305: incorrect nonce length"); + const o = Do(this._key, e.subarray(0, 16), new Uint8Array(32)) + , r = new Uint8Array(12); + r.set(e.subarray(16), 4); + const s = new jo(o) + , i = s.seal(r, t, n, a); + return Co(o), + Co(r), + s.clean(), + i + } + open(e, t, n, a) { + if (24 !== e.length) + throw new Error("XChaCha20Poly1305: incorrect nonce length"); + if (t.length < this.tagLength) + return null; + const o = Do(this._key, e.subarray(0, 16), new Uint8Array(32)) + , r = new Uint8Array(12); + r.set(e.subarray(16), 4); + const s = new jo(o) + , i = s.open(r, t, n, a); + return Co(o), + Co(r), + s.clean(), + i + } + clean() { + return Co(this._key), + this + } +} + +function So(e, t, n, a, o=0) { + if (32 !== e.length) + throw new Error("ChaCha: key size must be 32 bytes"); + if (a.length < n.length) + throw new Error("ChaCha: destination is shorter than source"); + let r, s; + if (0 === o) { + if (8 !== t.length && 12 !== t.length) + throw new Error("ChaCha nonce must be 8 or 12 bytes"); + r = new Uint8Array(16), + s = r.length - t.length, + r.set(t, s) + } else { + if (16 !== t.length) + throw new Error("ChaCha nonce with counter must be 16 bytes"); + r = t, + s = o + } + const i = new Uint8Array(64); + for (let l = 0; l < n.length; l += 64) { + Lo(i, r, e); + for (let e = l; e < l + 64 && e < n.length; e++) + a[e] = n[e] ^ i[e - l]; + Ao(r, 0, s) + } + return Co(i), + 0 === o && Co(r), + a +} + +function Ao(e, t, n) { + let a = 1; + for (; n--; ) + a = a + (255 & e[t]) | 0, + e[t] = 255 & a, + a >>>= 8, + t++; + if (a > 0) + throw new Error("ChaCha: counter overflow") +} + +function Lo(e, t, n) { + let a = 1634760805 + , o = 857760878 + , r = 2036477234 + , s = 1797285236 + , i = n[3] << 24 | n[2] << 16 | n[1] << 8 | n[0] + , l = n[7] << 24 | n[6] << 16 | n[5] << 8 | n[4] + , c = n[11] << 24 | n[10] << 16 | n[9] << 8 | n[8] + , u = n[15] << 24 | n[14] << 16 | n[13] << 8 | n[12] + , d = n[19] << 24 | n[18] << 16 | n[17] << 8 | n[16] + , f = n[23] << 24 | n[22] << 16 | n[21] << 8 | n[20] + , v = n[27] << 24 | n[26] << 16 | n[25] << 8 | n[24] + , p = n[31] << 24 | n[30] << 16 | n[29] << 8 | n[28] + , h = t[3] << 24 | t[2] << 16 | t[1] << 8 | t[0] + , m = t[7] << 24 | t[6] << 16 | t[5] << 8 | t[4] + , y = t[11] << 24 | t[10] << 16 | t[9] << 8 | t[8] + , g = t[15] << 24 | t[14] << 16 | t[13] << 8 | t[12] + , k = a + , b = o + , w = r + , _ = s + , x = i + , C = l + , L = c + , S = u + , M = d + , A = f + , D = v + , E = p + , I = h + , j = m + , P = y + , T = g; + for (let R = 0; R < 20; R += 2) + k = k + x | 0, + I ^= k, + I = I >>> 16 | I << 16, + M = M + I | 0, + x ^= M, + x = x >>> 20 | x << 12, + b = b + C | 0, + j ^= b, + j = j >>> 16 | j << 16, + A = A + j | 0, + C ^= A, + C = C >>> 20 | C << 12, + w = w + L | 0, + P ^= w, + P = P >>> 16 | P << 16, + D = D + P | 0, + L ^= D, + L = L >>> 20 | L << 12, + _ = _ + S | 0, + T ^= _, + T = T >>> 16 | T << 16, + E = E + T | 0, + S ^= E, + S = S >>> 20 | S << 12, + w = w + L | 0, + P ^= w, + P = P >>> 24 | P << 8, + D = D + P | 0, + L ^= D, + L = L >>> 25 | L << 7, + _ = _ + S | 0, + T ^= _, + T = T >>> 24 | T << 8, + E = E + T | 0, + S ^= E, + S = S >>> 25 | S << 7, + b = b + C | 0, + j ^= b, + j = j >>> 24 | j << 8, + A = A + j | 0, + C ^= A, + C = C >>> 25 | C << 7, + k = k + x | 0, + I ^= k, + I = I >>> 24 | I << 8, + M = M + I | 0, + x ^= M, + x = x >>> 25 | x << 7, + k = k + C | 0, + T ^= k, + T = T >>> 16 | T << 16, + D = D + T | 0, + C ^= D, + C = C >>> 20 | C << 12, + b = b + L | 0, + I ^= b, + I = I >>> 16 | I << 16, + E = E + I | 0, + L ^= E, + L = L >>> 20 | L << 12, + w = w + S | 0, + j ^= w, + j = j >>> 16 | j << 16, + M = M + j | 0, + S ^= M, + S = S >>> 20 | S << 12, + _ = _ + x | 0, + P ^= _, + P = P >>> 16 | P << 16, + A = A + P | 0, + x ^= A, + x = x >>> 20 | x << 12, + w = w + S | 0, + j ^= w, + j = j >>> 24 | j << 8, + M = M + j | 0, + S ^= M, + S = S >>> 25 | S << 7, + _ = _ + x | 0, + P ^= _, + P = P >>> 24 | P << 8, + A = A + P | 0, + x ^= A, + x = x >>> 25 | x << 7, + b = b + L | 0, + I ^= b, + I = I >>> 24 | I << 8, + E = E + I | 0, + L ^= E, + L = L >>> 25 | L << 7, + k = k + C | 0, + T ^= k, + T = T >>> 24 | T << 8, + D = D + T | 0, + C ^= D, + C = C >>> 25 | C << 7; + _o(k + a | 0, e, 0), + _o(b + o | 0, e, 4), + _o(w + r | 0, e, 8), + _o(_ + s | 0, e, 12), + _o(x + i | 0, e, 16), + _o(C + l | 0, e, 20), + _o(L + c | 0, e, 24), + _o(S + u | 0, e, 28), + _o(M + d | 0, e, 32), + _o(A + f | 0, e, 36), + _o(D + v | 0, e, 40), + _o(E + p | 0, e, 44), + _o(I + h | 0, e, 48), + _o(j + m | 0, e, 52), + _o(P + y | 0, e, 56), + _o(T + g | 0, e, 60) +} + +class Eo { + digestLength = 16; + _buffer = new Uint8Array(16); + _r = new Uint16Array(10); + _h = new Uint16Array(10); + _pad = new Uint16Array(8); + _leftover = 0; + _fin = 0; + _finished = !1; + constructor(e) { + let t = e[0] | e[1] << 8; + this._r[0] = 8191 & t; + let n = e[2] | e[3] << 8; + this._r[1] = 8191 & (t >>> 13 | n << 3); + let a = e[4] | e[5] << 8; + this._r[2] = 7939 & (n >>> 10 | a << 6); + let o = e[6] | e[7] << 8; + this._r[3] = 8191 & (a >>> 7 | o << 9); + let r = e[8] | e[9] << 8; + this._r[4] = 255 & (o >>> 4 | r << 12), + this._r[5] = r >>> 1 & 8190; + let s = e[10] | e[11] << 8; + this._r[6] = 8191 & (r >>> 14 | s << 2); + let i = e[12] | e[13] << 8; + this._r[7] = 8065 & (s >>> 11 | i << 5); + let l = e[14] | e[15] << 8; + this._r[8] = 8191 & (i >>> 8 | l << 8), + this._r[9] = l >>> 5 & 127, + this._pad[0] = e[16] | e[17] << 8, + this._pad[1] = e[18] | e[19] << 8, + this._pad[2] = e[20] | e[21] << 8, + this._pad[3] = e[22] | e[23] << 8, + this._pad[4] = e[24] | e[25] << 8, + this._pad[5] = e[26] | e[27] << 8, + this._pad[6] = e[28] | e[29] << 8, + this._pad[7] = e[30] | e[31] << 8 + } + _blocks(e, t, n) { + let a = this._fin ? 0 : 2048 + , o = this._h[0] + , r = this._h[1] + , s = this._h[2] + , i = this._h[3] + , l = this._h[4] + , c = this._h[5] + , u = this._h[6] + , d = this._h[7] + , f = this._h[8] + , v = this._h[9] + , p = this._r[0] + , h = this._r[1] + , m = this._r[2] + , y = this._r[3] + , g = this._r[4] + , k = this._r[5] + , b = this._r[6] + , w = this._r[7] + , _ = this._r[8] + , x = this._r[9]; + for (; n >= 16; ) { + let C = e[t + 0] | e[t + 1] << 8; + o += 8191 & C; + let L = e[t + 2] | e[t + 3] << 8; + r += 8191 & (C >>> 13 | L << 3); + let S = e[t + 4] | e[t + 5] << 8; + s += 8191 & (L >>> 10 | S << 6); + let M = e[t + 6] | e[t + 7] << 8; + i += 8191 & (S >>> 7 | M << 9); + let A = e[t + 8] | e[t + 9] << 8; + l += 8191 & (M >>> 4 | A << 12), + c += A >>> 1 & 8191; + let D = e[t + 10] | e[t + 11] << 8; + u += 8191 & (A >>> 14 | D << 2); + let E = e[t + 12] | e[t + 13] << 8; + d += 8191 & (D >>> 11 | E << 5); + let I = e[t + 14] | e[t + 15] << 8; + f += 8191 & (E >>> 8 | I << 8), + v += I >>> 5 | a; + let j = 0 + , P = j; + P += o * p, + P += r * (5 * x), + P += s * (5 * _), + P += i * (5 * w), + P += l * (5 * b), + j = P >>> 13, + P &= 8191, + P += c * (5 * k), + P += u * (5 * g), + P += d * (5 * y), + P += f * (5 * m), + P += v * (5 * h), + j += P >>> 13, + P &= 8191; + let T = j; + T += o * h, + T += r * p, + T += s * (5 * x), + T += i * (5 * _), + T += l * (5 * w), + j = T >>> 13, + T &= 8191, + T += c * (5 * b), + T += u * (5 * k), + T += d * (5 * g), + T += f * (5 * y), + T += v * (5 * m), + j += T >>> 13, + T &= 8191; + let R = j; + R += o * m, + R += r * h, + R += s * p, + R += i * (5 * x), + R += l * (5 * _), + j = R >>> 13, + R &= 8191, + R += c * (5 * w), + R += u * (5 * b), + R += d * (5 * k), + R += f * (5 * g), + R += v * (5 * y), + j += R >>> 13, + R &= 8191; + let B = j; + B += o * y, + B += r * m, + B += s * h, + B += i * p, + B += l * (5 * x), + j = B >>> 13, + B &= 8191, + B += c * (5 * _), + B += u * (5 * w), + B += d * (5 * b), + B += f * (5 * k), + B += v * (5 * g), + j += B >>> 13, + B &= 8191; + let O = j; + O += o * g, + O += r * y, + O += s * m, + O += i * h, + O += l * p, + j = O >>> 13, + O &= 8191, + O += c * (5 * x), + O += u * (5 * _), + O += d * (5 * w), + O += f * (5 * b), + O += v * (5 * k), + j += O >>> 13, + O &= 8191; + let U = j; + U += o * k, + U += r * g, + U += s * y, + U += i * m, + U += l * h, + j = U >>> 13, + U &= 8191, + U += c * p, + U += u * (5 * x), + U += d * (5 * _), + U += f * (5 * w), + U += v * (5 * b), + j += U >>> 13, + U &= 8191; + let W = j; + W += o * b, + W += r * k, + W += s * g, + W += i * y, + W += l * m, + j = W >>> 13, + W &= 8191, + W += c * h, + W += u * p, + W += d * (5 * x), + W += f * (5 * _), + W += v * (5 * w), + j += W >>> 13, + W &= 8191; + let H = j; + H += o * w, + H += r * b, + H += s * k, + H += i * g, + H += l * y, + j = H >>> 13, + H &= 8191, + H += c * m, + H += u * h, + H += d * p, + H += f * (5 * x), + H += v * (5 * _), + j += H >>> 13, + H &= 8191; + let N = j; + N += o * _, + N += r * w, + N += s * b, + N += i * k, + N += l * g, + j = N >>> 13, + N &= 8191, + N += c * y, + N += u * m, + N += d * h, + N += f * p, + N += v * (5 * x), + j += N >>> 13, + N &= 8191; + let V = j; + V += o * x, + V += r * _, + V += s * w, + V += i * b, + V += l * k, + j = V >>> 13, + V &= 8191, + V += c * g, + V += u * y, + V += d * m, + V += f * h, + V += v * p, + j += V >>> 13, + V &= 8191, + j = (j << 2) + j | 0, + j = j + P | 0, + P = 8191 & j, + j >>>= 13, + T += j, + o = P, + r = T, + s = R, + i = B, + l = O, + c = U, + u = W, + d = H, + f = N, + v = V, + t += 16, + n -= 16 + } + this._h[0] = o, + this._h[1] = r, + this._h[2] = s, + this._h[3] = i, + this._h[4] = l, + this._h[5] = c, + this._h[6] = u, + this._h[7] = d, + this._h[8] = f, + this._h[9] = v + } + finish(e, t=0) { + const n = new Uint16Array(10); + let a, o, r, s; + if (this._leftover) { + for (s = this._leftover, + this._buffer[s++] = 1; s < 16; s++) + this._buffer[s] = 0; + this._fin = 1, + this._blocks(this._buffer, 0, 16) + } + for (a = this._h[1] >>> 13, + this._h[1] &= 8191, + s = 2; s < 10; s++) + this._h[s] += a, + a = this._h[s] >>> 13, + this._h[s] &= 8191; + for (this._h[0] += 5 * a, + a = this._h[0] >>> 13, + this._h[0] &= 8191, + this._h[1] += a, + a = this._h[1] >>> 13, + this._h[1] &= 8191, + this._h[2] += a, + n[0] = this._h[0] + 5, + a = n[0] >>> 13, + n[0] &= 8191, + s = 1; s < 10; s++) + n[s] = this._h[s] + a, + a = n[s] >>> 13, + n[s] &= 8191; + for (n[9] -= 8192, + o = (1 ^ a) - 1, + s = 0; s < 10; s++) + n[s] &= o; + for (o = ~o, + s = 0; s < 10; s++) + this._h[s] = this._h[s] & o | n[s]; + for (this._h[0] = 65535 & (this._h[0] | this._h[1] << 13), + this._h[1] = 65535 & (this._h[1] >>> 3 | this._h[2] << 10), + this._h[2] = 65535 & (this._h[2] >>> 6 | this._h[3] << 7), + this._h[3] = 65535 & (this._h[3] >>> 9 | this._h[4] << 4), + this._h[4] = 65535 & (this._h[4] >>> 12 | this._h[5] << 1 | this._h[6] << 14), + this._h[5] = 65535 & (this._h[6] >>> 2 | this._h[7] << 11), + this._h[6] = 65535 & (this._h[7] >>> 5 | this._h[8] << 8), + this._h[7] = 65535 & (this._h[8] >>> 8 | this._h[9] << 5), + r = this._h[0] + this._pad[0], + this._h[0] = 65535 & r, + s = 1; s < 8; s++) + r = (this._h[s] + this._pad[s] | 0) + (r >>> 16) | 0, + this._h[s] = 65535 & r; + return e[t + 0] = this._h[0] >>> 0, + e[t + 1] = this._h[0] >>> 8, + e[t + 2] = this._h[1] >>> 0, + e[t + 3] = this._h[1] >>> 8, + e[t + 4] = this._h[2] >>> 0, + e[t + 5] = this._h[2] >>> 8, + e[t + 6] = this._h[3] >>> 0, + e[t + 7] = this._h[3] >>> 8, + e[t + 8] = this._h[4] >>> 0, + e[t + 9] = this._h[4] >>> 8, + e[t + 10] = this._h[5] >>> 0, + e[t + 11] = this._h[5] >>> 8, + e[t + 12] = this._h[6] >>> 0, + e[t + 13] = this._h[6] >>> 8, + e[t + 14] = this._h[7] >>> 0, + e[t + 15] = this._h[7] >>> 8, + this._finished = !0, + this + } + update(e) { + let t, n = 0, a = e.length; + if (this._leftover) { + t = 16 - this._leftover, + t > a && (t = a); + for (let a = 0; a < t; a++) + this._buffer[this._leftover + a] = e[n + a]; + if (a -= t, + n += t, + this._leftover += t, + this._leftover < 16) + return this; + this._blocks(this._buffer, 0, 16), + this._leftover = 0 + } + if (a >= 16 && (t = a - a % 16, + this._blocks(e, n, t), + n += t, + a -= t), + a) { + for (let t = 0; t < a; t++) + this._buffer[this._leftover + t] = e[n + t]; + this._leftover += a + } + return this + } + digest() { + if (this._finished) + throw new Error("Poly1305 was finished"); + let e = new Uint8Array(16); + return this.finish(e), + e + } + clean() { + return Co(this._buffer), + Co(this._r), + Co(this._h), + Co(this._pad), + this._leftover = 0, + this._fin = 0, + this._finished = !0, + this + } +} + +function Mo(e, t, n, a=0) { + return Co(n), + So(e, t, n, n, a) +} + +function xo(e, t=new Uint8Array(8), n=0) { + return _o(e >>> 0, t, n), + _o(e / 4294967296 >>> 0, t, n + 4), + t +} + +const Io = new Uint8Array(16); + +class jo { + nonceLength = 12; + tagLength = 16; + _key; + constructor(e) { + if (32 !== e.length) + throw new Error("ChaCha20Poly1305 needs 32-byte key"); + this._key = new Uint8Array(e) + } + seal(e, t, n, a) { + if (e.length > 16) + throw new Error("ChaCha20Poly1305: incorrect nonce length"); + const o = new Uint8Array(16); + o.set(e, o.length - e.length); + const r = new Uint8Array(32); + Mo(this._key, o, r, 4); + const s = t.length + this.tagLength; + let i; + if (a) { + if (a.length !== s) + throw new Error("ChaCha20Poly1305: incorrect destination length"); + i = a + } else + i = new Uint8Array(s); + return So(this._key, o, t, i, 4), + this._authenticate(i.subarray(i.length - this.tagLength, i.length), r, i.subarray(0, i.length - this.tagLength), n), + Co(o), + i + } + open(e, t, n, a) { + if (e.length > 16) + throw new Error("ChaCha20Poly1305: incorrect nonce length"); + if (t.length < this.tagLength) + return null; + const o = new Uint8Array(16); + o.set(e, o.length - e.length); + const r = new Uint8Array(32); + Mo(this._key, o, r, 4); + const s = new Uint8Array(this.tagLength); + if (this._authenticate(s, r, t.subarray(0, t.length - this.tagLength), n), + i = s, + l = t.subarray(t.length - this.tagLength, t.length), + 0 === i.length || 0 === l.length || 0 === function(e, t) { + if (e.length !== t.length) + return 0; + let n = 0; + for (let a = 0; a < e.length; a++) + n |= e[a] ^ t[a]; + return 1 & n - 1 >>> 8 + }(i, l)) + return null; + var i, l; + const c = t.length - this.tagLength; + let u; + if (a) { + if (a.length !== c) + throw new Error("ChaCha20Poly1305: incorrect destination length"); + u = a + } else + u = new Uint8Array(c); + return So(this._key, o, t.subarray(0, t.length - this.tagLength), u, 4), + Co(o), + u + } + clean() { + return Co(this._key), + this + } + _authenticate(e, t, n, a) { + const o = new Eo(t); + a && (o.update(a), + a.length % 16 > 0 && o.update(Io.subarray(a.length % 16))), + o.update(n), + n.length % 16 > 0 && o.update(Io.subarray(n.length % 16)); + const r = new Uint8Array(8); + a && xo(a.length, r), + o.update(r), + xo(n.length, r), + o.update(r); + const s = o.digest(); + for (let i = 0; i < s.length; i++) + e[i] = s[i]; + o.clean(), + Co(s), + Co(r) + } +} + + +function Uo(e) { + const t = new Uint8Array(e.length / 2); + for (let n = 0; n < t.length; n++) + t[n] = parseInt(e.slice(2 * n, 2 * n + 2), 16); + return t +} + +function decryptResponse(e, t, n=1) { + if (32 !== t.length) + throw new Error("密钥长度必须为32字节"); + if (e.length < 41) + throw new Error("密文长度不足"); + const a = e[0] + , o = e.subarray(1, 25) + , r = e.subarray(25) + , s = 2 === a ? r.slice().reverse() : r + , i = new Po(t).open(o, s); + if (!i) + throw new Error("认证失败"); + return i +} + +async function encryptRequest(e, t, n=1) { + if (32 !== t.length) + throw new Error("密钥长度必须为32字节"); + const a = new Uint8Array(12); + globalThis.crypto.getRandomValues(a); + const o = { + name: "AES-GCM", + iv: a + } + , r = await crypto.subtle.importKey("raw", t, "AES-GCM", !1, ["encrypt"]) + , s = new Uint8Array(await crypto.subtle.encrypt(o, r, e)); + 2 === n && function(e) { + for (let t = 0, n = e.length - 1; t < n; t++, + n--) { + const a = e[t]; + e[t] = e[n], + e[n] = a + } + }(s); + const i = new Uint8Array(1 + a.length + s.length); + return i[0] = 2 === n ? 2 : 1, + i.set(a, 1), + i.set(s, 1 + a.length), + i +} + +function n() { + return { + key : 'ea9d9d4f9a983fe6f6382f29c7b46b8d6dc47abc6da36662e6ddff8c78902f65', + version : 1 + } +} + + + +async function decryptText(encodeText) { + const {key: a, version: o} = n() + , r = Uo(a || ""); + const s = Number(o || 0) + const t = Uo(encodeText) + , xx = decryptResponse(t, r, s); + return (new TextDecoder).decode(xx) +} + +async function encryptText(data) { + const {key: a, version: o} = n() + , r = Uo(a || ""); + const b = await encryptRequest((new TextEncoder).encode(data), r); + return Array.from(b).map(e => e.toString(16).padStart(2, "0")).join("") +} + +$.exports = { + decryptText, + encryptText +} \ No newline at end of file diff --git "a/drpy-node-bundle/spider/js/\345\220\254\345\217\213[\345\220\254].js" "b/drpy-node-bundle/spider/js/\345\220\254\345\217\213[\345\220\254].js" new file mode 100644 index 00000000..4af3af6e --- /dev/null +++ "b/drpy-node-bundle/spider/js/\345\220\254\345\217\213[\345\220\254].js" @@ -0,0 +1,300 @@ +/* +@header({ + searchable: 2, + filterable: 1, + quickSearch: 0, + title: '听友[听]', + '类型': '听书', + lang: 'ds' +}) +*/ +const {getHtml,req_,req_proxy} = $.require('./_lib.request.js') +const {decryptText,encryptText} = $.require('./_lib.tingyou.js') +var rule = { + 类型: '听书', + title: '听友[听]', + host: 'https://tingyou.fm', + url: '/api/category_page/types/fyclass/popular/pfypage', + detailUrl:'/api/chapters_list/fyid', + searchUrl: '/api/search', + searchable: 2, + quickSearch: 0, + timeout: 5000, + class_parse:async function(){ + let classes = [ + { + "type_id": 46, + "type_name": "玄幻奇幻" + }, + { + "type_id": 11, + "type_name": "武侠小说" + }, + { + "type_id": 19, + "type_name": "言情通俗" + }, + { + "type_id": 21, + "type_name": "相声小品" + }, + { + "type_id": 14, + "type_name": "恐怖惊悚" + }, + { + "type_id": 17, + "type_name": "官场商战" + }, + { + "type_id": 15, + "type_name": "历史军事" + }, + { + "type_id": 9, + "type_name": "百家讲坛" + }, + { + "type_id": 16, + "type_name": "刑侦反腐" + }, + { + "type_id": 10, + "type_name": "有声文学" + }, + { + "type_id": 18, + "type_name": "人物纪实" + }, + { + "type_id": 36, + "type_name": "广播剧" + }, + { + "type_id": 22, + "type_name": "英文读物" + }, + { + "type_id": 23, + "type_name": "轻音清心" + }, + { + "type_id": 31, + "type_name": "二人转" + }, + { + "type_id": 33, + "type_name": "健康养生" + }, + { + "type_id": 34, + "type_name": "综艺娱乐" + }, + { + "type_id": 40, + "type_name": "头条" + }, + { + "type_id": 38, + "type_name": "戏曲" + }, + { + "type_id": 41, + "type_name": "脱口秀" + }, + { + "type_id": 42, + "type_name": "商业财经" + }, + { + "type_id": 43, + "type_name": "亲子教育" + }, + { + "type_id": 44, + "type_name": "教育培训" + }, + { + "type_id": 45, + "type_name": "时尚生活" + }, + { + "type_id": 20, + "type_name": "童话寓言" + }, + { + "type_id": 47, + "type_name": "未分类" + }, + { + "type_id": 1, + "type_name": "单田芳" + }, + { + "type_id": 2, + "type_name": "刘兰芳" + }, + { + "type_id": 3, + "type_name": "田连元" + }, + { + "type_id": 4, + "type_name": "袁阔成" + }, + { + "type_id": 5, + "type_name": "连丽如" + }, + { + "type_id": 8, + "type_name": "孙一" + }, + { + "type_id": 30, + "type_name": "王子封臣" + }, + { + "type_id": 25, + "type_name": "马长辉" + }, + { + "type_id": 26, + "type_name": "昊儒书场" + }, + { + "type_id": 27, + "type_name": "王军" + }, + { + "type_id": 28, + "type_name": "王玥波" + }, + { + "type_id": 29, + "type_name": "石连君" + }, + { + "type_id": 12, + "type_name": "粤语评书" + }, + { + "type_id": 35, + "type_name": "关永超" + }, + { + "type_id": 6, + "type_name": "张少佐" + }, + { + "type_id": 7, + "type_name": "田战义" + }, + { + "type_id": 13, + "type_name": "其他评书" + } + ] + + return { + class:classes + } + }, + headers:{ + 'User-Agent': 'zybk/1.0.6', + 'Accept-Encoding': 'gzip', + 'authorization': 'Bearer gAAAAABpsEFsPBrHfY1bGsn15TbqqXUC4WSFwm8VU97NW6qmSAewn1rbYMzbIXLajyJnSZ94oZsS6hil8Qkb-IknSuggyn9XLDitEE930CD9OapDQOzq1xSJb7foWNh5YdeT_7p4ZSyYyhW4b2ZWmI-Itb8YBTjDmWIM3FiTQ9MYATmWKJQ6d6IY5Z0bupvW6hjWoHppAa5v0_k2KkIEHdzyw7AiKTPPqUYVmKvrvISlBkMHGdyK83AgiOi80-mKwmCIY1kXuj_vg_mY1HxvmsPpNcYLaoOYUA==', + // 'cookie':'session=dvJGYQ7gKDJvm-FXEzmCCHPd0IK7fzjLz1hfmi5RSxlhGi6EayEATHlH9_c%3D;' + }, + play_parse: true, + 预处理: async () => { + let data = '02956c849999374a66745e3ac9957f00ad9022036ec6b1a20c7f86327c8817'; + let config = { + method: 'POST', + url: 'https://azybk.tingyou8.vip/apk/auth/me', + headers: { + 'User-Agent': 'zybk/1.0.6', + 'Accept-Encoding': 'gzip', + 'authorization': 'Bearer gAAAAABpsAkJlSPlhBJAKM71X7PpktM1kpibFvpxnJbGXBAN0ydCgx4gviLacuou6QJKAZ4FtCpdCe8HZLKdveUTv-BTfeVFB7wGBv6yiylsWmAeKwc5YLunEbwXQv1VtMLNn4W7e4PZQlLSSOTZHbwYsC0Herb1GohZ4NU47-85y_eNuz8qq0mmxtY_2JMG9T00YcFAevfvCkfkngr0ttUZEgLVK2W_SKfHL-CSvfe6mJWQxNh88p3ViNSTK0sbL-2XPgBdDPD3urXgA4eZ7pQfPYKF3aj3ow==' + }, + data: data + }; + let html = await axios.request(config).catch(e=>e.response.headers['set-cookie']) + if(html[0]){ + rule.headers['cookie'] = html[0].replace('Path=/; Domain=tingyou8.vip; Max-Age=604800; HttpOnly','') + } + return [] + }, + lazy: async function () { + let {input} = this; + console.log(input) + let data = { + "album_id": Number(input.split('^')[0]), + "chapter_idx": Number(input.split('^')[1]) + } + let encodeData = await encryptText(JSON.stringify(data)) + let html = await req_('https://azybk.tingyou8.vip/apk/play/play_token','post', rule.headers,encodeData); + let link = JSON.parse(await decryptText(html.payload)).play_url + return {url: link, parse: 0}; + }, + double: true, + 一级: async function () { + let {input} = this; + const videos = [] + let html = await req_(input); + let data = html.payload + let list = JSON.parse(await decryptText(data)).data + list.forEach(item => { + videos.push({ + vod_id: item.id, + vod_name: item.title, + vod_pic: item.cover_url, + vod_remarks: item.status === 1 ? "连载":"完结", + }) + }) + return videos; + }, + 二级: async function () { + let {input,orId} = this; + let urls = []; + let html = await req_(input); + let list = JSON.parse(await decryptText(html.payload)).chapters + list.forEach(item => { + urls.push(item.title+"$"+orId+"^"+item.index) + }) + let js = await req_(input.replace('chapters_list','album_detail')) + let content = JSON.parse(await decryptText(js.payload)) + let VOD = { + vod_id:content.id, + vod_name:content.title, + vod_pic:content.cover_url, + vod_remarks:content.status === 1 ? "连载":"完结", + vod_content:content.synosis||'', + vod_play_from: '球球啦', + vod_play_url: urls.join('#') + }; + return VOD; + }, + 搜索: async function (wd, quick, pg) { + let {input} = this; + let videos = []; + let data = { + "keyword": wd, + "page": pg, + "sort_by": "updated_at", + "sort_order": "desc" + } + let encodeData = await encryptText(JSON.stringify(data)) + let html = await req_('https://azybk.tingyou8.vip/apk/search','post', rule.headers,encodeData); + let list = JSON.parse(await decryptText(html.payload)).results + list.forEach(item => { + videos.push({ + vod_id: item.id, + vod_name: item.title, + vod_pic: item.cover_url, + vod_remarks: item.status === 1 ? "连载":"完结", + }) + }) + return videos; + } +} \ No newline at end of file diff --git "a/drpy-node-bundle/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" "b/drpy-node-bundle/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" index 73866aca..49b61343 100644 --- "a/drpy-node-bundle/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" +++ "b/drpy-node-bundle/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" @@ -4,11 +4,32 @@ filterable: 1, quickSearch: 0, title: '央视大全', - lang: 'ds' + lang: 'ds', + isProxyPath: true, + more: { + parseApi: [ + { + host: 'cctv://(.+)', + flag: 'CCTV' + }, + { + host: 'cctv4k://(.+)', + flag: 'CCTV4K' + }, + { + host: 'cctvlive://(.+)', + flag: 'CCTV直播' + }, + ] + }, + }) */ -const {processFile, indexHtml} = $.require('./_lib.cntv.js'); +// const {processFile, indexHtml} = $.require('./_lib.cntv.js'); +const {parseCCTVUrl, detectInputType, getVideoInfoByPid} = require('./_lib.cntv-urlparse.cjs'); +const {processFile} = require('./_lib.cntv2026.cjs'); +const {indexHtml} = $.require('./_lib.cntv.js'); const {setH5Str} = $.require('./_lib.cntv.live.js'); var rule = { title: '央视大全', @@ -31,7 +52,7 @@ var rule = { play_parse: true, lazy: async function () { let {input, flag, getProxyUrl} = this; - // log(input); + log(input); // log(flag); let guid = ''; let url = ''; @@ -251,9 +272,10 @@ var rule = { let url = ''; let is_live = 0; if (proxyPath) { - const BASE_URL = 'https://dh5.cntv.qcloudcdn.com/'.rstrip('/'); + // const BASE_URL = 'https://dh5.cntv.qcloudcdn.com/'.rstrip('/'); // const BASE_URL = 'https://dh5.cntv.myalicdn.com/'.rstrip('/'); - url = `${BASE_URL}/${proxyPath}`; + // url = `${BASE_URL}/${proxyPath}`; + url = proxyPath; } else { url = base64Decode(input.split('#')[0]); is_live = 1; @@ -284,6 +306,7 @@ var rule = { return [200, 'application/vnd.apple.mpegurl', m3u8Str] } const contentType = extension === '.ts' ? 'video/MP2T' : 'application/vnd.apple.mpegurl'; + // log('url:', url); const buffer = await processFile(url, extension); const headers = { 'Content-Disposition': `attachment; filename="${filename}"`, @@ -472,6 +495,13 @@ function getRegexText(text, regexText, index) { } async function getM3u8(pid, getProxyUrl) { + const info = await getVideoInfoByPid(pid); + const proxy_path = info.download_url; + log('[getM3u8] proxy_path:', proxy_path); + return getProxyUrl().split('?')[0].rstrip('/') + '/' + proxy_path; +} + +async function getM3u8Old(pid, getProxyUrl) { const url = `https://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=${pid}`; const htmlTxt = await request(url); const jo = JSON.parse(htmlTxt); diff --git "a/drpy-node-bundle/spider/js/\347\210\261\346\216\250\345\233\276[\347\224\273].js" "b/drpy-node-bundle/spider/js/\347\210\261\346\216\250\345\233\276[\347\224\273].js" index 4665d881..1f224ec1 100644 --- "a/drpy-node-bundle/spider/js/\347\210\261\346\216\250\345\233\276[\347\224\273].js" +++ "b/drpy-node-bundle/spider/js/\347\210\261\346\216\250\345\233\276[\347\224\273].js" @@ -26,15 +26,6 @@ var rule = { searchable: 2, quickSearch: 0, filterable: 0, - 预处理: async function () { - // console.log(encodeStr('你好')); - // console.log(typeof JSEncrypt); - // console.log(typeof JSON5); - // console.log(typeof gbkTool); - // console.log(typeof NODERSA); - // console.log(typeof atob); - // console.log(typeof btoa); - }, headers: { 'User-Agent': 'MOBILE_UA', }, @@ -64,10 +55,6 @@ var rule = { 推荐: '*', searchUrl: '/sou-**-fypage.html', 一级: '#content&&article;h2&&Text;img&&data-src;;a&&href', - // 一级: async function () { - // let {getProxyUrl} = this; - // console.log('本地代理地址:' + getProxyUrl()); - // }, 二级: '*', 搜索: '*', } \ No newline at end of file diff --git "a/drpy-node-bundle/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" "b/drpy-node-bundle/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" index 1db8bd51..8f728a3d 100644 --- "a/drpy-node-bundle/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" +++ "b/drpy-node-bundle/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" @@ -4,6 +4,7 @@ filterable: 0, quickSearch: 0, title: '设置中心', + isProxyPath: true, logo: 'https://avatars.githubusercontent.com/u/49803097?v=4', more: { sourceTag: '设置,动作', @@ -65,6 +66,7 @@ let quick_data = { 阿里: 'https://www.alipan.com/s/vgXMcowK8pQ', 天翼: 'https://cloud.189.cn/web/share?code=INJbU3NbqyUj', 百度: 'https://pan.baidu.com/s/1L0UIv4p0X0QrbbKErJuc_w?pwd=2pwj', + 迅雷: 'https://pan.xunlei.com/s/VOkBwLBNoXN8eO9WrcVbXdTcA1?pwd=8tvj#', 移动1: 'https://yun.139.com/shareweb/#/w/i/0i5CLQ7BpV7Ai', 移动2: 'https://caiyun.139.com/m/i?2jexC1gcjeN7q', 移动3: 'https://yun.139.com/shareweb/#/w/i/2i2MoE9ZHn9p1', @@ -72,6 +74,7 @@ let quick_data = { 直链1: 'https://vdse.bdstatic.com//628ca08719cef5987ea2ae3c6f0d2386.mp4', 嗅探1: 'https://www.6080kk.cc/haokanplay/178120-1-1.html', 嗅探2: 'https://www.hahads.com/play/537106-3-1.html', + 央视跨源: 'cctv://3c18e2b3bba249b78b831e910608cfec', 多集: 'https://v.qq.com/x/cover/m441e3rjq9kwpsc/m00253deqqo.html@https://pan.quark.cn/s/6c8158e258f3@https://pan.baidu.com/s/1TdbgcwaMG1dK7B5pQ1LbBg?pwd=1234', 海阔二级单线路: gzip(JSON.stringify({ "actor": "剧集", @@ -121,11 +124,13 @@ var rule = { 类型: '设置', title: '设置中心', 推荐: async function () { - let {publicUrl} = this; + let {publicUrl, requestHost} = this; // log('publicUrl:', publicUrl); let setIcon = urljoin(publicUrl, './images/icon_cookie/设置.png'); let searchIcon = urljoin(publicUrl, './images/icon_cookie/搜索.jpg'); let chatIcon = urljoin(publicUrl, './images/icon_cookie/chat.webp'); + let drpysIcon = urljoin(publicUrl, './images/drpys.png'); + let drpyshIcon = urljoin(publicUrl, './images/drpysh.png'); const data = deepCopy(action_data); data.push({ vod_id: JSON.stringify({ @@ -141,6 +146,29 @@ var rule = { vod_pic: searchIcon, vod_tag: 'action', }); + data.unshift({ + vod_id: JSON.stringify({ + actionId: 'browser', + type: 'browser', + title: 'DS仓库', + url: 'https://repo.tvshare.cn/', + }), + vod_name: 'DS仓库', + vod_pic: drpyshIcon, + vod_tag: 'action' + }); + data.unshift({ + vod_id: JSON.stringify({ + actionId: 'browser', + type: 'browser', + title: '后台管理', + url: requestHost + '/apps/admin', + header: {'Authorization': 'Basic YWRtaW46ZHJweXM='}, + }), + vod_name: '后台管理', + vod_pic: drpysIcon, + vod_tag: 'action' + }); data.forEach(it => { if (!it.vod_pic) { it.vod_pic = setIcon; @@ -481,8 +509,7 @@ var rule = { vod_name: '测试代理流', vod_play_from: 'drpyS本地流代理', // vod_play_url: '测试播放流$' + getProxyUrl().split('?')[0] + media_url + '#不代理直接播$' + media_url + '#8k播放$' + m3u8_url, - // vod_play_url: '测试播放流$' + getProxyUrl().split('?')[0] + media_url + '#不代理直接播$' + media_url - vod_play_url: '测试播放流$' + getProxyUrl() + '&url=' + media_url + '#不代理直接播$' + media_url + vod_play_url: '测试播放流$' + getProxyUrl().split('?')[0] + media_url + '#不代理直接播$' + media_url } } }, @@ -491,16 +518,15 @@ var rule = { let {input} = this; return {parse: 0, url: input} }, - proxy_rule: async function (params) { + proxy_rule: async function () { let {input, proxyPath} = this; - const url = proxyPath || params.url; + const url = proxyPath; log('start proxy:', url); try { const headers = { 'user-agent': PC_UA, } - // return [200, null, url, headers, 2] - return [302, null, '', {location: url}] + return [200, null, url, headers, 2] } catch (e) { log('proxy error:', e.message); return [500, 'text/plain', e.message] diff --git a/drpy-node-mcp/index.js b/drpy-node-mcp/index.js index ac912bf5..f64341d1 100644 --- a/drpy-node-mcp/index.js +++ b/drpy-node-mcp/index.js @@ -12,6 +12,7 @@ import * as fsTools from "./tools/fsTools.js"; import * as spiderTools from "./tools/spiderTools.js"; import * as dbTools from "./tools/dbTools.js"; import * as systemTools from "./tools/systemTools.js"; +import * as apiTools from "./tools/apiTools.js"; const server = new Server( { @@ -43,6 +44,9 @@ const toolHandlers = { validate_spider: spiderTools.validate_spider, check_syntax: spiderTools.check_syntax, + // API Tools + get_drpy_api_list: apiTools.get_drpy_api_list, + // DB Tools sql_query: dbTools.sql_query, @@ -130,6 +134,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { properties: {} }, }, + { + name: "get_drpy_api_list", + description: "Get the full list of drpy-node API interfaces with parameters and return examples", + inputSchema: { + type: "object", + properties: {} + }, + }, { name: "fetch_spider_url", description: "Fetch a URL using drpy-node's request library to debug connectivity and anti-crawling measures (UA/headers).", diff --git a/drpy-node-mcp/tools/apiTools.js b/drpy-node-mcp/tools/apiTools.js new file mode 100644 index 00000000..297cdaf4 --- /dev/null +++ b/drpy-node-mcp/tools/apiTools.js @@ -0,0 +1,262 @@ + +/** + * API Tools for drpy-node + * Provides documentation and information about the available API endpoints. + */ + +export const get_drpy_api_list = async () => { + const apiList = [ + { + category: "Core Video Source API", + endpoints: [ + { + path: "/api/:module", + method: "GET/POST", + description: "Main interface for video sources. Supports listing categories, details, searching, and playing.", + params: { + "module": { "type": "path", "required": true, "description": "Engine name. Available: 'drpyS', 'hipy', 'php', 'xbpq', 'catvod'" }, + "ac": { "type": "query", "required": false, "description": "Action type. 't'=Categories/List, 'ids'=Detail, 'action'=Custom Action. If omitted with 'wd', performs search." }, + "t": { "type": "query", "required": false, "description": "Category ID (tid) when ac=t" }, + "pg": { "type": "query", "required": false, "description": "Page number (default: 1)" }, + "wd": { "type": "query", "required": false, "description": "Search keyword" }, + "ids": { "type": "query", "required": false, "description": "Comma-separated VOD IDs when ac=ids" }, + "play": { "type": "query", "required": false, "description": "URL to resolve for playback" }, + "flag": { "type": "query", "required": false, "description": "Playlist flag (for play action)" }, + "filter": { "type": "query", "required": false, "description": "Filter conditions (boolean/string)" }, + "extend": { "type": "query", "required": false, "description": "Extended info (JSON string)" } + } + }, + { + path: "/proxy/:module/:url", + method: "GET", + description: "Proxy wrapper for source requests (headers, etc.)", + params: { + "module": "Engine name", + "url": "Target URL (may need encoding)" + } + }, + { + path: "/parse/:jx", + method: "GET", + description: "Video parsing interface", + params: { + "jx": "Parser name or alias", + "url": "Video URL to parse" + } + } + ] + }, + { + category: "Configuration", + endpoints: [ + { + path: "/config", + method: "GET", + description: "Get the generated JSON configuration for apps (TVBox, etc.)", + params: {} + }, + { + path: "/config/:id", + method: "GET", + description: "Get specific configuration variant" + } + ] + }, + { + category: "System & Tools", + endpoints: [ + { + path: "/", + method: "GET", + description: "Home page / README" + }, + { + path: "/health", + method: "GET", + description: "Server health check" + }, + { + path: "/encoder", + method: "POST", + description: "Encode text/url", + params: { "text": "Content to encode", "mode": "Encoding mode" } + }, + { + path: "/decoder", + method: "POST", + description: "Decode text/url", + params: { "text": "Content to decode" } + }, + { + path: "/authcoder", + method: "GET", + description: "Generate random strings", + params: { "len": "Length", "number": "Count" } + }, + { + path: "/http", + method: "POST", + description: "HTTP Proxy Request", + params: { "url": "Target URL", "method": "GET/POST", "headers": "Headers object", "data": "Body data" } + }, + { + path: "/ai", + method: "GET", + description: "Simple AI Chat interface", + params: { "text": "User input" } + }, + { + path: "/req/*", + method: "ALL", + description: "Request forwarder (if enabled)" + }, + { + path: "/gh/release", + method: "GET", + description: "Get latest GitHub release for drpy-node" + }, + { + path: "/cat/index.html", + method: "GET", + description: "Cat interface page" + } + ] + }, + { + category: "Admin & Management", + endpoints: [ + { + path: "/admin/encoder", + method: "GET", + description: "Encoder tool UI" + }, + { + path: "/admin/cookie-set", + method: "POST", + description: "Set system cookies", + params: { "cookie_auth_code": "Auth code", "key": "Cookie key", "value": "Cookie value" } + }, + { + path: "/admin/download", + method: "GET", + description: "Download page for project archives" + } + ] + }, + { + category: "Task Management", + endpoints: [ + { + path: "/execute-now/:taskName?", + method: "GET", + description: "Execute a cron task immediately" + }, + { + path: "/tasks", + method: "GET", + description: "List all scheduled tasks" + }, + { + path: "/tasks/:taskName", + method: "GET", + description: "Get details of a specific task" + } + ] + }, + { + category: "File & Image Services", + endpoints: [ + { + path: "/image/upload", + method: "POST", + description: "Upload image (base64)", + params: { "imageId": "Unique ID", "base64Data": "Base64 content" } + }, + { + path: "/image/:imageId", + method: "GET", + description: "Get image content" + }, + { + path: "/image/list", + method: "GET", + description: "List stored images" + }, + { + path: "/clipboard/add", + method: "POST", + description: "Add content to clipboard", + params: { "text": "Content", "mode": "append/overwrite" } + }, + { + path: "/clipboard/read", + method: "GET", + description: "Read clipboard content" + }, + { + path: "/source-checker/reports/save", + method: "POST", + description: "Save source check report" + }, + { + path: "/source-checker/reports/latest", + method: "GET", + description: "Get latest source check report" + } + ] + }, + { + category: "Proxy Services", + endpoints: [ + { + path: "/unified-proxy/proxy", + method: "GET/HEAD", + description: "Unified Smart Proxy (auto detects m3u8/file)", + params: { "url": "Target URL", "type": "force type (optional)" } + }, + { + path: "/m3u8-proxy/playlist", + method: "GET", + description: "M3U8 Playlist Proxy" + }, + { + path: "/mediaProxy", + method: "ALL", + description: "General Media Proxy" + }, + { + path: "/file-proxy/proxy", + method: "GET/HEAD", + description: "Remote File Proxy" + }, + { + path: "/webdav/file", + method: "GET", + description: "WebDAV File Proxy" + }, + { + path: "/ftp/file", + method: "GET/HEAD", + description: "FTP File Proxy" + } + ] + }, + { + category: "Realtime", + endpoints: [ + { + path: "/ws", + method: "GET", + description: "WebSocket connection for logs and status" + } + ] + } + ]; + + return { + content: [{ + type: "text", + text: JSON.stringify(apiList, null, 2) + }] + }; +}; diff --git a/drpy-node-mcp/tools/fsTools.js b/drpy-node-mcp/tools/fsTools.js index 5688c61f..e65fc894 100644 --- a/drpy-node-mcp/tools/fsTools.js +++ b/drpy-node-mcp/tools/fsTools.js @@ -31,8 +31,48 @@ export const read_file = async (args) => { if (!filePath || !isSafePath(filePath)) { throw new Error("Invalid path"); } + + // Check if it's an image file + const imageExts = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.bmp', '.tiff', '.tif']; + const isImage = imageExts.some(ext => filePath.toLowerCase().endsWith(ext)); + + if (isImage) { + // Read as buffer and convert to base64 + const buffer = await fs.readFile(resolvePath(filePath)); + const base64 = buffer.toString('base64'); + // Get mime type + const ext = filePath.split('.').pop().toLowerCase(); + const mimeTypes = { + 'png': 'image/png', + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'gif': 'image/gif', + 'svg': 'image/svg+xml', + 'webp': 'image/webp', + 'ico': 'image/x-icon', + 'bmp': 'image/bmp', + 'tiff': 'image/tiff', + 'tif': 'image/tiff' + }; + const mimeType = mimeTypes[ext] || 'image/png'; + + return { + content: [ + { + type: "text", + text: JSON.stringify({ + type: 'image', + mimeType, + dataUrl: `data:${mimeType};base64,${base64}` + }), + }, + ], + }; + } + + // Read as text for non-image files let content = await fs.readFile(resolvePath(filePath), "utf-8"); - + // Attempt to decode if it's a JS file (for DS sources) if (filePath.endsWith('.js')) { content = await decodeDsSource(content); @@ -42,7 +82,10 @@ export const read_file = async (args) => { content: [ { type: "text", - text: content, + text: JSON.stringify({ + type: 'text', + content + }), }, ], }; diff --git a/drpy-node-mcp/tools/systemTools.js b/drpy-node-mcp/tools/systemTools.js index c775a959..5d223f75 100644 --- a/drpy-node-mcp/tools/systemTools.js +++ b/drpy-node-mcp/tools/systemTools.js @@ -108,9 +108,15 @@ export const manage_config = async (args) => { export const restart_service = async () => { try { - await execPromise("pm2 restart drpys"); - return { content: [{ type: "text", text: "Service restart command issued." }] }; + // Check if running under PM2 + try { + await execPromise("pm2 restart drpys"); + return { content: [{ type: "text", text: JSON.stringify({ success: true, message: "服务已通过 PM2 重启" }) }] }; + } catch (pm2Error) { + // Not running under PM2, return helpful message + return { content: [{ type: "text", text: JSON.stringify({ success: false, message: "当前未使用 PM2 运行。请在终端中手动重启服务:\n1. 按 Ctrl+C 停止当前服务\n2. 运行 npm run dev 重新启动" }) }] }; + } } catch (e) { - return { isError: true, content: [{ type: "text", text: `Failed to restart service: ${e.message}` }] }; + return { isError: true, content: [{ type: "text", text: JSON.stringify({ success: false, message: `重启失败: ${e.message}` }) }] }; } }; diff --git a/drpy2-quickjs/FastifyRoute.java b/drpy2-quickjs/FastifyRoute.java new file mode 100644 index 00000000..b62ba69e --- /dev/null +++ b/drpy2-quickjs/FastifyRoute.java @@ -0,0 +1,180 @@ +package com.fongmi.android.tv.server; + +import fi.iki.elonen.NanoHTTPD.IHTTPSession; +import fi.iki.elonen.NanoHTTPD.Response; + +import java.util.*; + +public class Route { + + public interface Handler { + Response handle(IHTTPSession session, Map params); + } + + private static class Node { + Map children = new HashMap<>(); + Handler handler; + boolean isParam; + boolean isWildcard; + String paramName; + } + + private final Node root; + + public Route() { + root = new Node(); + } + + // ====================== Fastify 方法 ====================== + public Route get(String path, Handler handler) { + addRoute(path, handler); + return this; + } + + public Route post(String path, Handler handler) { + addRoute(path, handler); + return this; + } + + public Route put(String path, Handler handler) { + addRoute(path, handler); + return this; + } + + public Route delete(String path, Handler handler) { + addRoute(path, handler); + return this; + } + + public Route head(String path, Handler handler) { + addRoute(path, handler); + return this; + } + + public Route options(String path, Handler handler) { + addRoute(path, handler); + return this; + } + + public Route all(String path, Handler handler) { + get(path, handler); + post(path, handler); + put(path, handler); + delete(path, handler); + head(path, handler); + options(path, handler); + return this; + } + + // ====================== 核心路由注册 ====================== + private void addRoute(String path, Handler handler) { + if (path == null || path.isEmpty()) path = "/"; + if (!path.startsWith("/")) path = "/" + path; + + Node node = root; + String[] parts = path.split("/"); + + for (String part : parts) { + if (part.isEmpty()) continue; + + if (part.equals("*")) { + node.children.putIfAbsent("*", new Node()); + Node wild = node.children.get("*"); + wild.isWildcard = true; + wild.paramName = "*"; + node = wild; + break; + } else if (part.startsWith(":") && part.endsWith("*") && part.length() > 2) { + String name = part.substring(1, part.length() - 1); + node.children.putIfAbsent(":*", new Node()); + Node pw = node.children.get(":*"); + pw.isParam = true; + pw.isWildcard = true; + pw.paramName = name; + node = pw; + break; + } else if (part.startsWith(":")) { + node.children.putIfAbsent(":", new Node()); + Node param = node.children.get(":"); + param.isParam = true; + param.paramName = part.substring(1); + node = param; + } else { + node.children.putIfAbsent(part, new Node()); + node = node.children.get(part); + } + } + node.handler = handler; + } + + // ====================== 路由匹配 ====================== + private Match match(String path) { + Node node = root; + Map params = new HashMap<>(); + String[] parts = path.split("/"); + int i = 0; + + while (i < parts.length) { + if (node.isWildcard) break; + + String part = parts[i]; + if (part.isEmpty()) { + i++; + continue; + } + + if (node.children.containsKey(part)) { + node = node.children.get(part); + } else if (node.children.containsKey(":")) { + node = node.children.get(":"); + params.put(node.paramName, part); + } else if (node.children.containsKey(":*")) { + node = node.children.get(":*"); + params.put(node.paramName, joinRest(parts, i)); + break; + } else if (node.children.containsKey("*")) { + node = node.children.get("*"); + params.put("*", joinRest(parts, i)); + break; + } else { + return null; + } + i++; + } + + if (node.handler == null) return null; + Match m = new Match(); + m.handler = node.handler; + m.params = params; + return m; + } + + private static class Match { + Handler handler; + Map params; + } + + private String joinRest(String[] parts, int index) { + StringBuilder sb = new StringBuilder(); + for (int j = index; j < parts.length; j++) { + if (!parts[j].isEmpty()) { + if (sb.length() > 0) sb.append("/"); + sb.append(parts[j]); + } + } + return sb.toString(); + } + + // ====================== 原有接口不动 ====================== + public Response handle(IHTTPSession session) { + String path = session.getUri().trim(); + if (path.contains("?")) path = path.substring(0, path.indexOf("?")); + Match match = match(path); + return match == null ? null : match.handler.handle(session, match.params); + } + + public boolean hasRoute(String method, String path) { + if (path.contains("?")) path = path.substring(0, path.indexOf("?")); + return match(path) != null; + } +} diff --git a/index.js b/index.js index f31b67ae..45f74d33 100644 --- a/index.js +++ b/index.js @@ -76,7 +76,7 @@ fastify.addHook('onClose', async () => { // 给静态目录插件中心挂载basic验证 fastify.addHook('preHandler', (req, reply, done) => { - if (req.raw.url.startsWith('/apps/')) { + if (req.raw.url.startsWith('/apps/') || req.raw.url.startsWith('/api/admin/')) { if (req.raw.url.includes('clipboard-pusher/index.html')) { validateBasicAuth(req, reply, async () => { validatHtml(req, reply, rootDir).then(() => done()); diff --git "a/json/\345\237\237\345\220\215\351\205\215\347\275\256.json" "b/json/\345\237\237\345\220\215\351\205\215\347\275\256.json" index e0b4ba96..20750936 100644 --- "a/json/\345\237\237\345\220\215\351\205\215\347\275\256.json" +++ "b/json/\345\237\237\345\220\215\351\205\215\347\275\256.json" @@ -1,88 +1,84 @@ { - "玩偶": [ - "https://wogg.xxooo.cf", - "https://wogg.333232.xyz", - "https://woggpan.333232.xyz", - "https://wogg.heshiheng.top", - "https://www.wogg.one", - "https://www.wogg.lol" - ], - "至臻": [ - "https://xiaomiai.site", - "http://mihdr.top", - "http://xiaomi666.fun", - "http://www.miqk.cc" - ], - "蜡笔": [ - "http://xiaocge.fun", - "https://feimao666.fun", - "http://feimao888.fun", - "http://feimaoai.site", - "http://www.labi88.sbs", - "http://fmao.site", - "https://fmao.shop" - ], - "木偶": [ - "http://123.666291.xyz", - "https://mogg.5568.eu.org", - "https://mo.666291.xyz", - "http://666.666291.xyz", - "https://mo.muouso.fun" - ], - "小米": [ - "https://www.54271.fun", - "https://54271.fun", - "https://www.mucpan.cc", - "https://www.milvdou.fun", - "https://mucpan.cc", - "http://milvdou.fun", - "https://xiaomi.628383.xyz", - "http://156.238.229.163" - ], - "百家": [ - "https://bj.jiexi.news", - "http://baijia.filegear-sg.me", - "http://cj.jiexi.news", - "http://baijia.885525.xyz" - ], - "二小": [ - "https://wexwp.cc", - "https://erxiaofn.click", - "http://2xiaopan.fun", - "http://xhww.net", - "http://www.xhww.net", - "https://erxiaofn.site", - "http://www.2xiaopan.fun", - "https://xiaoer.5568.eu.org", - "http://wexfnw.999888456.xyz", - "http://89.213.49.249" - ], - "多多": [ - "https://tv.yydsys.top", - "https://tv.yydsys.cc", - "https://tv.214521.xyz" - ], - "虎斑": [ - "http://103.45.162.207:20720", - "http://xsayang.fun:12512" - ], - "欧歌": [ - "https://woog.xn--dkw.xn--6qq986b3xl", - "https://woog.nxog.eu.org" - ], - "下饭": [ - "http://154.204.177.231", - "http://www.xn--ghqy10g1w0a.xyz" - ], - "闪电": [ - "http://1.95.79.193", - "http://1.95.79.193:666" - ], - "雷鲸": [ - "https://leijing.xyz", - "https://leijing1.com" - ], - "盘它": [ - "https://www.91panta.cn" - ] + "玩偶": [ + "https://wogg.xxooo.cf", + "https://wogg.333232.xyz", + "https://woggpan.333232.xyz", + "https://wogg.heshiheng.top", + "https://www.wogg.one", + "https://www.wogg.lol" + ], + "至臻": [ + "https://mihdr.top", + "https://xiaomi666.fun", + "https://zhizhen8.click", + "https://www.zhizhen8.click" + ], + "蜡笔": [ + "http://xiaocge.fun", + "http://feimo.fun", + "https://feimao666.fun", + "http://feimao888.fun", + "http://www.labi88.sbs", + "http://fmao.site", + "http://fmao.shop", + "http://xiaocgege.shop" + ], + "木偶": [ + "http://123.666291.xyz", + "https://mogg.5568.eu.org", + "https://mo.666291.xyz", + "http://666.666291.xyz", + "https://mo.muouso.fun" + ], + "小米": [ + "https://www.54271.fun", + "https://54271.fun", + "https://www.mucpan.cc", + "https://www.milvdou.fun", + "https://mucpan.cc", + "http://milvdou.fun", + "https://xiaomi.628383.xyz", + "http://156.238.229.163" + ], + "百家": [ + "https://bj.jiexi.news", + "http://baijia.filegear-sg.me", + "http://cj.jiexi.news", + "http://baijia.885525.xyz" + ], + "二小": [ + "https://www.wexwp.cc", + "https://wexwp.cc", + "https://zhizhen1.top", + "https://www.2xiaopan.fun", + "https://2xiaopan.fun" + ], + "多多": [ + "https://tv.yydsys.top", + "https://tv.yydsys.cc", + "https://tv.214521.xyz" + ], + "虎斑": [ + "http://103.45.162.207:20720", + "http://xsayang.fun:12512" + ], + "欧歌": [ + "https://woog.xn--dkw.xn--6qq986b3xl", + "https://woog.nxog.eu.org" + ], + "下饭": [ + "http://154.204.177.231", + "http://www.xn--ghqy10g1w0a.xyz" + ], + "闪电": [ + "http://1.95.79.193", + "http://1.95.79.193:666" + ], + "雷鲸": [ + "https://leijing.xyz", + "https://leijing1.com" + ], + "盘它": [ + "https://www.91panta.cn" + ] } \ No newline at end of file diff --git a/libs/drpyS.js b/libs/drpyS.js index 1d8ec91f..dee69db4 100644 --- a/libs/drpyS.js +++ b/libs/drpyS.js @@ -63,7 +63,7 @@ globalThis.JsonBig = JSONbig({storeAsString: true}); globalThis.require = rootRequire; initializeGlobalDollar(); -const {Ali, Baidu, Baidu2, Cloud, Pan, Quark, UC, Yun} = PanS; +const {Ali, Baidu, Baidu2, Cloud, Pan, Quark, UC, Yun, Xun} = PanS; const { sleep, sleepSync, getNowTime, computeHash, deepCopy, urljoin, urljoin2, joinUrl, keysToLowerCase, naturalSort, $js, @@ -74,6 +74,9 @@ const CACHE_OPTIONS = { max: 100, ttl: 1000 * 60 * 10, // 10分钟 }; +// const moduleCache = new Map(); +// const ruleObjectCache = new Map(); +// const jxCache = new Map(); const moduleCache = new LRUCache(CACHE_OPTIONS); const ruleObjectCache = new LRUCache(CACHE_OPTIONS); const jxCache = new LRUCache(CACHE_OPTIONS); @@ -175,7 +178,7 @@ const STATIC_LIBS_SANDBOX = { matchesAll, cut, gbkTool, CryptoJS, JSEncrypt, NODERSA, pako, JSON5, jinja, template, batchExecute, atob, btoa, base64Encode, base64Decode, md5, rc4Encrypt, rc4Decrypt, rc4, rc4_decode, randomUa, jsonpath, hlsParser, axios, axiosX, URL, pathLib, executeParse, qs, Buffer, URLSearchParams, COOKIE, - ENV, _ENV, Quark, Baidu, Baidu2, UC, Ali, Cloud, Yun, Pan, createWebDAVClient, createFTPClient, + ENV, _ENV, Quark, Baidu, Baidu2, UC, Ali, Cloud, Yun, Pan, Xun, createWebDAVClient, createFTPClient, require: rootRequire, WebSocket, WebSocketServer, zlib, JSONbig, JsonBig, minizlib, iconv: globalThis.iconv, cheerio: globalThis.cheerio, }; @@ -455,9 +458,9 @@ export async function init(filePath, env = {}, refresh) { // delete sandbox.rule; // 清理沙箱中的临时构建变量 - delete sandbox._asyncGetRule; - delete sandbox.module; - delete sandbox.exports; + // delete sandbox._asyncGetRule; + // delete sandbox.module; + // delete sandbox.exports; // 缓存模块和文件的 hash 值 moduleCache.set(hashMd5, {moduleObject, hash: fileHash}); @@ -515,9 +518,9 @@ export async function getRuleObject(filePath, env, refresh) { // delete sandbox.rule; // 清理沙箱中的临时构建变量 - delete sandbox._asyncGetRule; - delete sandbox.module; - delete sandbox.exports; + // delete sandbox._asyncGetRule; + // delete sandbox.module; + // delete sandbox.exports; // 缓存模块和文件的 hash 值 ruleObjectCache.set(filePath, {ruleObject, hash: fileHash}); @@ -569,9 +572,9 @@ export async function initJx(filePath, env, refresh) { log(`[initJx] 加载解析:${filePath} 耗时 ${cost}毫秒`) // 清理沙箱中的临时构建变量 - delete sandbox._asyncGetLazy; - delete sandbox.module; - delete sandbox.exports; + // delete sandbox._asyncGetLazy; + // delete sandbox.module; + // delete sandbox.exports; jxCache.set(hashMd5, {jxObj, hash: fileHash}); return jxObj; diff --git a/libs/dsGlobal.js b/libs/dsGlobal.js index 731c99a4..556ee370 100644 --- a/libs/dsGlobal.js +++ b/libs/dsGlobal.js @@ -71,6 +71,10 @@ globalThis.Baidu = Baidu; // 百度网盘接口2 - 百度网盘的另一个实现版本 globalThis.Baidu2 = Baidu2; + +// 迅雷网盘 +globalThis.Xun = Xun; + // webdav globalThis.createWebDAVClient = createWebDAVClient; // ftp diff --git a/libs_drpy/jsonpath-adapter.js b/libs_drpy/jsonpath-adapter.js new file mode 100644 index 00000000..b1d35335 --- /dev/null +++ b/libs_drpy/jsonpath-adapter.js @@ -0,0 +1,22 @@ +import * as jpNamespace from './jsonpathplus.min.js'; + +let jp; + +// Try to find JSONPath in the imported namespace (ESM/Rolldown handling of UMD) +if (jpNamespace && jpNamespace.JSONPath) { + jp = jpNamespace.JSONPath; +} else if (jpNamespace && jpNamespace.default && jpNamespace.default.JSONPath) { + jp = jpNamespace.default.JSONPath; +} + +// Fallback to globalThis (browser/legacy behavior) +if (!jp && typeof globalThis !== 'undefined' && globalThis.JSONPath) { + if (typeof globalThis.JSONPath.JSONPath === 'function') { + jp = globalThis.JSONPath.JSONPath; + } else if (typeof globalThis.JSONPath === 'function') { + jp = globalThis.JSONPath; + } +} + +export const JSONPath = jp; +export default jp; diff --git a/libs_drpy/moduleLoader.js b/libs_drpy/moduleLoader.js index b47a7803..621113e0 100644 --- a/libs_drpy/moduleLoader.js +++ b/libs_drpy/moduleLoader.js @@ -1,6 +1,6 @@ import {readFileSync, existsSync} from 'fs'; import path from "path"; -import {createRequire} from 'module'; +import Module, {createRequire} from 'module'; import {fileURLToPath} from "url"; import axios from 'axios'; import fetchSync from 'sync-fetch'; @@ -11,6 +11,21 @@ const LIB_ROOT = path.join(ROOT_DIR, 'spider/js'); const customRequire = createRequire(import.meta.url); +/** + * Patch Module.prototype.require to handle bundled modules in CJS context + * This allows native CJS modules (like those loaded via require('./lib.js')) to find + * bundled dependencies (axios, iconv-lite, etc.) which are exposed on globalThis. + */ +const originalRequire = Module.prototype.require; +Module.prototype.require = function(id) { + if (id === 'iconv-lite' && globalThis.iconv) return globalThis.iconv; + if (id === 'axios' && globalThis.axios) return globalThis.axios; + if (id === 'cheerio' && globalThis.cheerio) return globalThis.cheerio; + if (id === 'qs' && globalThis.qs) return globalThis.qs; + if (id === 'crypto-js' && globalThis.CryptoJS) return globalThis.CryptoJS; + return originalRequire.apply(this, arguments); +}; + // 导出 rootRequire export const rootRequire = (modulePath) => { // 处理内置模块或打包模块 diff --git a/package-bundle.js b/package-bundle.js index 957d7e9d..3299a7cd 100644 --- a/package-bundle.js +++ b/package-bundle.js @@ -1,5 +1,5 @@ import {execSync} from 'child_process'; -import {existsSync, statSync} from 'fs'; +import {existsSync, statSync, readdirSync, copyFileSync, mkdirSync} from 'fs'; import {join, basename, dirname, resolve} from 'path'; import url from 'url'; @@ -8,13 +8,77 @@ const INCLUDE_ITEMS = [ 'libs', 'spider', 'jx', + 'json', 'localt5.js', 'localDsCoreTest.js' ]; +// 需要额外复制的特定文件列表 (文件名,相对于 spider/js) +const EXTRA_FILES = [ + '30wMV[听].js', + '爱推图[画].js', + '央视大全[官].js', + '设置中心.js', + '听友[听].js', + '360影视[官].js', + 'Appget[模板].js', + 'Appmuou[模板].js', + 'AppShark[模板].js', + 'APP模板配置.js', +]; + // 获取脚本所在目录 (e:\gitwork\drpy-node) const getScriptDir = () => dirname(resolve(url.fileURLToPath(import.meta.url))); +// 复制 _lib 开头的文件及额外指定的文件到 bundle 目录 +const copyFiles = (scriptDir) => { + const sourceDir = join(scriptDir, 'spider', 'js'); + const targetDir = join(scriptDir, 'drpy-node-bundle', 'spider', 'js'); + + if (!existsSync(sourceDir)) { + console.warn(`警告: 源目录 ${sourceDir} 不存在,跳过复制文件。`); + return; + } + + if (!existsSync(targetDir)) { + console.log(`创建目标目录: ${targetDir}`); + mkdirSync(targetDir, {recursive: true}); + } + + console.log(`正在从 ${sourceDir} 复制文件到 ${targetDir}...`); + + try { + const files = readdirSync(sourceDir); + let libCount = 0; + let extraCount = 0; + + for (const file of files) { + let shouldCopy = false; + + // 检查是否是 _lib 文件 + if (file.startsWith('_lib') && (file.endsWith('.js') || file.endsWith('.cjs'))) { + shouldCopy = true; + libCount++; + } + // 检查是否在额外文件列表中 + else if (EXTRA_FILES.includes(file)) { + shouldCopy = true; + extraCount++; + } + + if (shouldCopy) { + const srcPath = join(sourceDir, file); + const destPath = join(targetDir, file); + copyFileSync(srcPath, destPath); + // console.log(`已复制: ${file}`); + } + } + console.log(`成功复制了 ${libCount} 个 lib 文件和 ${extraCount} 个额外文件。`); + } catch (error) { + console.error(`复制文件失败: ${error.message}`); + } +}; + // 压缩 drpy-node-bundle 目录 const compressBundle = (scriptDir) => { // drpy-node-bundle 目录路径 @@ -79,6 +143,7 @@ const compressBundle = (scriptDir) => { // 主程序入口 const main = () => { const scriptDir = getScriptDir(); + copyFiles(scriptDir); compressBundle(scriptDir); }; diff --git a/package-lock.json b/package-lock.json index c057f262..f855dd0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "drpy-node", - "version": "1.3.27", + "version": "1.3.31", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "drpy-node", - "version": "1.3.27", + "version": "1.3.31", "license": "MIT", "dependencies": { "@fastify/formbody": "^7.4.0", @@ -18,7 +18,6 @@ "cron": "^4.3.3", "crypto-js": "^4.2.0", "dayjs": "^1.11.13", - "dns-over-http-resolver": "^3.0.15", "dotenv": "^16.4.7", "fastify": "^4.15.0", "fastq": "^1.17.1", @@ -30,7 +29,7 @@ "json-bigint": "^1.0.0", "lodash": "^4.17.21", "lru-cache": "^9.1.2", - "marked": "^17.0.3", + "marked": "^12.0.2", "mime-types": "^2.1.35", "minizlib": "^3.0.1", "node-forge": "^1.3.1", @@ -57,7 +56,7 @@ "rolldown": "^1.0.0-rc.4" }, "engines": { - "node": ">17 <23" + "node": ">17 <25" } }, "node_modules/@anthropic-ai/mcpb": { @@ -1302,16 +1301,6 @@ "node": ">= 0.8" } }, - "node_modules/dns-over-http-resolver": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-3.0.16.tgz", - "integrity": "sha512-Qnq8HhNRuMnA61pf1lVPlStCAv1BVrraCx0umPESWgYKf995tUMF5oNhW59PKdnf7E8d5yqwHlEoFywXjsNMCw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "quick-lru": "^7.0.0", - "weald": "^1.0.2" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -2162,15 +2151,15 @@ } }, "node_modules/marked": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.4.tgz", - "integrity": "sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==", + "version": "12.0.2", + "resolved": "https://registry.npmmirror.com/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "license": "MIT", "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 20" + "node": ">= 18" } }, "node_modules/math-intrinsics": { @@ -2683,18 +2672,6 @@ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "license": "MIT" }, - "node_modules/quick-lru": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.3.0.tgz", - "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -3115,18 +3092,6 @@ "node": ">=8" } }, - "node_modules/supports-color": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", - "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/sync-fetch": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0.tgz", @@ -3250,25 +3215,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/weald": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/weald/-/weald-1.1.1.tgz", - "integrity": "sha512-PaEQShzMCz8J/AD2N3dJMc1hTZWkJeLKS2NMeiVkV5KDHwgZe7qXLEzyodsT/SODxWDdXJJqocuwf3kHzcXhSQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "ms": "^3.0.0-canary.1", - "supports-color": "^10.0.0" - } - }, - "node_modules/weald/node_modules/ms": { - "version": "3.0.0-canary.202508261828", - "resolved": "https://registry.npmjs.org/ms/-/ms-3.0.0-canary.202508261828.tgz", - "integrity": "sha512-NotsCoUCIUkojWCzQff4ttdCfIPoA1UGZsyQbi7KmqkNRfKCrvga8JJi2PknHymHOuor0cJSn/ylj52Cbt2IrQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", @@ -3454,7 +3400,6 @@ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.js b/package.js index 82bab77e..cea90454 100644 --- a/package.js +++ b/package.js @@ -4,7 +4,7 @@ import {join, basename, dirname, resolve, relative} from 'path'; import url from 'url'; // 要排除的目录列表 -const EXCLUDE_DIRS = ['.git', '.idea', 'soft', 'examples', 'apps/cat', 'plugins/pvideo', 'plugins/req-proxy', 'plugins/pup-sniffer', 'plugins/mediaProxy', 'pyTools', 'drop_code', 'local', 'logs', '对话1.txt', 'vod_cache', 'data/mv', 'drpy-node-mcp', 'drpy-node-bundle', 'drpy2-quickjs']; +const EXCLUDE_DIRS = ['.git', '.idea', 'soft', 'examples', 'apps/cat', 'plugins/pvideo', 'plugins/req-proxy', 'plugins/pup-sniffer', 'plugins/mediaProxy', 'pyTools', 'drop_code', 'local', 'logs', '对话1.txt', 'vod_cache', 'data/mv', 'drpy-node-mcp', 'drpy-node-bundle', 'drpy-node-admin', 'drpy2-quickjs']; // 要排除的文件列表 const EXCLUDE_FILES = ['config/env.json', '.env', '.claude', 'clipboard.txt', 'clipboard.txt.bak', '.plugins.js', 'yarn.lock', 't4_daemon.pid', 'spider/js/UC分享.js', 'spider/js/百忙无果[官].js', 'spider/catvod/mtv60w[差].js', 'json/UC分享.json', 'jx/_30wmv.js', 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', 'custom.json']; diff --git a/package.json b/package.json index 2ce84b50..e1cfd67c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "drpy-node", - "version": "1.3.28", + "version": "1.4.1", "main": "index.js", "type": "module", "scripts": { @@ -26,10 +26,13 @@ "moontv": "node scripts/mjs/moontv.mjs 采集2025.json -p", "bundle": "cd drpy-node-bundle && npx rolldown -c", "test:bundle": "cd drpy-node-bundle && node localDsCoreTest.js", - "test-bun:bundle": "cd drpy-node-bundle && bun localDsCoreTest.js" + "test-bun:bundle": "cd drpy-node-bundle && bun localDsCoreTest.js", + "admin:dev": "cd drpy-node-admin && npm run dev", + "admin:build": "cd drpy-node-admin && npm run build:apps", + "admin:install": "cd drpy-node-admin && npm install" }, "engines": { - "node": ">17 <23" + "node": ">17 <24" }, "repository": "https://github.com/hjdhnx/drpy-node.git", "author": "晚风拂柳颜 <434857005@qq.com>", @@ -45,11 +48,11 @@ "cron": "^4.3.3", "crypto-js": "^4.2.0", "dayjs": "^1.11.13", - "dns-over-http-resolver": "^3.0.15", "dotenv": "^16.4.7", "fastify": "^4.15.0", "fastq": "^1.17.1", "form-data": "^4.0.4", + "fs-extra": "^11.3.4", "google-protobuf": "^3.21.4", "https-proxy-agent": "^7.0.6", "iconv-lite": "^0.6.3", @@ -57,7 +60,7 @@ "json-bigint": "^1.0.0", "lodash": "^4.17.21", "lru-cache": "^9.1.2", - "marked": "^17.0.3", + "marked": "^17.0.4", "mime-types": "^2.1.35", "minizlib": "^3.0.1", "node-forge": "^1.3.1", diff --git a/package.py b/package.py index 28ef230c..97e90a69 100644 --- a/package.py +++ b/package.py @@ -9,7 +9,7 @@ 'pyTools', 'drop_code', 'local', 'logs', '对话1.txt', - 'vod_cache', 'data/mv', 'drpy-node-mcp', 'drpy-node-bundle', 'drpy2-quickjs'] + 'vod_cache', 'data/mv', 'drpy-node-mcp', 'drpy-node-bundle', 'drpy-node-admin', 'drpy2-quickjs'] # 要排除的文件列表 EXCLUDE_FILES = ['config/env.json', '.env', '.claude', 'clipboard.txt', 'clipboard.txt.bak', '.plugins.js', 'yarn.lock', diff --git a/public/images/drpys.png b/public/images/drpys.png new file mode 100644 index 00000000..dac857da Binary files /dev/null and b/public/images/drpys.png differ diff --git a/public/images/drpysh.png b/public/images/drpysh.png new file mode 100644 index 00000000..9e7902c1 Binary files /dev/null and b/public/images/drpysh.png differ diff --git a/public/index.html b/public/index.html index 212ba651..62dcb9f4 100644 --- a/public/index.html +++ b/public/index.html @@ -7,11 +7,10 @@ drpyS-README -

drpyS(drpy-node)

+

drpyS(drpy-node)

zread -Ask DeepWiki

-

nodejs作为服务端的drpy实现。全面升级异步写法
积极开发中,每日一更,当前进度 100%
找工作中,随缘更新
上班当牛马,下班要带娃,阶段性佛系趁娃睡觉熬夜更新

-

常用超链接

+Ask DeepWiki
drpyS
nodejs作为服务端的drpy实现。全面升级异步写法
积极开发中,每日一更,当前进度 100%
找工作中,随缘更新
上班当牛马,下班要带娃,阶段性佛系趁娃睡觉熬夜更新

+

常用超链接


-

插件应用列表

+

插件应用列表

-

同作者项目

+

同作者项目

-

免费壳子推荐

+

免费壳子推荐

-

更新记录

-

20260314

+

更新记录

+

20260320

+

更新至V1.4.1

+

20260319

+

更新至V1.3.31

+

20260317

+

更新至V1.3.30

+

20260315

+

更新至V1.3.29

+

20260314

更新至V1.3.28

-

20260301

-

更新至V1.3.27

-

20260228

-

更新至V1.3.26

-

20260225

-

更新至V1.3.25

-

20260214

-

更新至V1.3.24

-

20260212

-

更新至V1.3.23

-

20260208

-

更新至V1.3.22

点此查看完整更新记录

注意事项

总是有人遇到各种奇葩问题,像什么没弹幕,访问/config/1服务马上崩溃等等,能自行解决最好,解决不了我建议你使用下方安装教程 3.道长腾讯轻量云服务器安装方案 跟我一样还有问题那就不可能了,我能用你即能用

-

基础框架

+

基础框架

todo:

  1. js里的源能否去除export开头,保持跟qjs一致
  2. @@ -107,7 +103,7 @@

    基础框架

  3. pino-pretty
  4. deasync
-

参考资料

+

参考资料

-

问题说明

+

问题说明

  1. windows上直接运行index.js可能会发现运行过程中的日志打印出中文乱码。建议通过yarn dev运行或者在package.json里点击dev脚本运行
  2. pinyin 库依赖的 nodejieba 跑路了现在无法完成安装
  3. new Promise 里发生的错误无法被外部try catch 导致程序崩溃,如 番薯动漫.js 里的写法
-

安装说明

+

安装说明

1.zy安装方案

  • 多平台安装教程
  • @@ -159,13 +155,13 @@

    安装说明

    pm2 start drpys pm2 restart drpys -

    代理转发功能测试

    +

    代理转发功能测试

    -

    友链(白嫖接口服务)

    +

    友链(白嫖接口服务)

    -

    AI接入

    +

    AI接入

    -

    版权

    +

    版权

    本项目主体框架由道长开发,项目内相关源收集于互联网,可供学习交流测试使用,禁止商用或者直接转卖代码,转载代码请带上出处。

    -

    免责声明

    +

    免责声明

    1. 此程序仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
    2. 由于此程序仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
    3. diff --git a/scripts/build-admin.js b/scripts/build-admin.js new file mode 100644 index 00000000..2bd2e14f --- /dev/null +++ b/scripts/build-admin.js @@ -0,0 +1,37 @@ +import { execSync } from 'child_process'; +import fs from 'fs-extra'; +import path from 'path'; + +console.log('🔨 开始构建 drpy-node-admin...'); + +// 1. 进入 admin 目录 +process.chdir(path.join(process.cwd(), 'drpy-node-admin')); + +// 2. 安装依赖(如果需要) +if (!fs.existsSync('node_modules')) { + console.log('📦 安装依赖...'); + execSync('npm install', { stdio: 'inherit' }); +} + +// 3. 构建 +console.log('🏗️ 构建生产版本...'); +execSync('npm run build:apps', { stdio: 'inherit' }); + +// 4. 验证构建结果 +const adminDistPath = path.join(process.cwd(), '../apps/admin'); +if (!fs.existsSync(adminDistPath)) { + console.error('❌ 构建失败:未找到输出目录'); + process.exit(1); +} + +const indexHtml = path.join(adminDistPath, 'index.html'); +if (!fs.existsSync(indexHtml)) { + console.error('❌ 构建失败:未找到 index.html'); + process.exit(1); +} + +console.log('✅ 构建成功!'); +console.log(`📂 输出目录: ${adminDistPath}`); +console.log(''); +console.log('现在可以通过以下地址访问管理面板:'); +console.log(' http://localhost:5757/apps/admin/'); diff --git a/scripts/test/test_cctv_header.js b/scripts/test/test_cctv_header.js new file mode 100644 index 00000000..4382785b --- /dev/null +++ b/scripts/test/test_cctv_header.js @@ -0,0 +1,175 @@ +import fs from 'fs/promises'; +import path from 'path'; +import {fileURLToPath} from 'url'; +import FileHeaderManager from '../../utils/fileHeaderManager.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// 源文件路径 +const sourceFile = path.resolve(__dirname, '../../spider/js/央视大全[官].js'); +// 测试文件路径 +const testFile = path.resolve(__dirname, 'test_cctv_header_temp.js'); + +async function runTest() { + console.log('=== 开始测试文件头操作 ==='); + console.log(`源文件: ${sourceFile}`); + console.log(`测试文件: ${testFile}`); + + try { + // 1. 复制文件 + console.log('\n[1/6] 正在复制源文件到测试文件...'); + try { + await fs.copyFile(sourceFile, testFile); + console.log('✅ 复制完成。'); + } catch (e) { + console.error('❌ 复制失败:', e.message); + return; + } + + // 2. 读取文件头 + console.log('\n[2/6] 正在读取文件头...'); + const startTime = performance.now(); + let header = await FileHeaderManager.readHeader(testFile); + const endTime = performance.now(); + const duration = endTime - startTime; + console.log(`⏱️ 读取耗时: ${duration.toFixed(4)} ms`); + + if (header) { + console.log('✅ 读取到的文件头:', JSON.stringify(header, null, 2)); + } else { + console.log('⚠️ 未找到文件头,将尝试创建新文件头。'); + header = {}; + } + + // 3. 修改文件头 + console.log('\n[3/6] 正在修改并写入文件头...'); + const timestamp = Date.now(); + const originalTitle = header.title || 'Unknown'; + header.title = `${originalTitle}_TEST_${timestamp}`; + header.test_timestamp = timestamp; + + try { + await FileHeaderManager.writeHeader(testFile, header); + console.log('✅ 写入操作完成。'); + } catch (e) { + console.error('❌ 写入失败:', e.message); + throw e; + } + + // 4. 再次读取验证 + console.log('\n[4/6] 再次读取以验证写入...'); + const newHeader = await FileHeaderManager.readHeader(testFile); + console.log('读取到的新文件头:', JSON.stringify(newHeader, null, 2)); + + if (newHeader && newHeader.test_timestamp === timestamp) { + console.log('✅ 验证成功:新字段已存在且值正确。'); + } else { + console.error('❌ 验证失败:新字段未找到或值不匹配。'); + throw new Error('Verification failed'); + } + + // 5. 移除文件头 + console.log('\n[5/6] 正在移除文件头...'); + // 注意:removeHeader 返回处理后的内容字符串,不自动写入文件 + const contentWithoutHeader = await FileHeaderManager.removeHeader(testFile); + + // 我们需要手动写入文件以验证 + await fs.writeFile(testFile, contentWithoutHeader); + console.log('✅ 移除操作完成,已写回文件。'); + + // 6. 验证移除结果 + console.log('\n[6/6] 验证移除结果...'); + const headerAfterRemove = await FileHeaderManager.readHeader(testFile); + if (!headerAfterRemove || Object.keys(headerAfterRemove).length === 0) { + console.log('✅ 验证成功:文件头已移除。'); + } else { + console.log('❌ 验证失败:文件头仍然存在:', headerAfterRemove); + throw new Error('Removal verification failed'); + } + + // 7. 性能测试 (循环 10000 次) + const iterations = 10000; + console.log(`\n[7/10] 性能基准测试 (读取 ${iterations} 次取平均)...`); + // 确保文件有头 + await fs.copyFile(sourceFile, testFile); + + const perfStart = performance.now(); + for(let i=0; i 查找位置 -> 拼接 Buffer -> 写入" 的过程 + + // 模拟:我们找到了 header 的 start 和 end + // 实际逻辑应该复用 FileHeaderManager.findHeaderBlock + // 但 findHeaderBlock 操作的是 string。 + + // 关键在于:是否可以只把 commentBlock 转 string,找到 offset, + // 然后在原始 Buffer 上进行 slice 和 concat? + + // 假设 headerStartOffset 和 headerEndOffset 是相对于 buffer 的 + const headerGlobalStart = start + headerStart; + // 简单模拟 header 长度为 100 字节 + const headerGlobalEnd = headerGlobalStart + 100; + + const newBuf = Buffer.concat([ + buffer.subarray(0, headerGlobalStart), + buffer.subarray(headerGlobalEnd) + ]); + + await fs.writeFile(filePath, newBuf); + + } finally { + await handle.close(); + } +} + +async function runTest() { + console.log('=== 开始大文件性能对比测试 ==='); + + // 1. 创建大文件 (500KB) + console.log('正在生成 500KB 测试文件...'); + let content = await fs.readFile(sourceFile, 'utf8'); + // 重复内容直到达到 500KB + while (Buffer.byteLength(content) < 500 * 1024) { + content += '\n// Padding content to increase file size...\n' + content; + } + // 确保头部有 @header + if (!content.includes('@header(')) { + console.warn('源文件没有 @header,测试可能无效'); + } + + await fs.writeFile(testFile, content); + const stats = await fs.stat(testFile); + console.log(`测试文件大小: ${(stats.size / 1024).toFixed(2)} KB`); + + const iterations = 100; // 大文件操作慢,减少次数 + + // 2. 测试现有 String 模式 (FileHeaderManager.removeHeader) + console.log(`\n[String Mode] removeHeader 测试 (${iterations} 次)...`); + + // 预热 + const header = await FileHeaderManager.readHeader(testFile); + + const startString = performance.now(); + for (let i = 0; i < iterations; i++) { + // removeHeader 目前只返回字符串,不写入 + // 为了模拟真实场景,我们需要包含 fs.readFile 和 fs.writeFile + // FileHeaderManager.removeHeader 内部如果不传 path 传 content,则不包含读。 + // 如果传 path,则包含读。 + // 但它不包含写。 + + // 模拟完整流程:读 -> 处理 -> 写 + const newContent = await FileHeaderManager.removeHeader(testFile); // 包含 readFile + await fs.writeFile(testFile, newContent); + + // 恢复文件头以便下一次循环 (为了测试 remove,必须先有) + // 这步不计入时间?不,这很麻烦。 + // 我们可以测试 "读取 -> 替换(即使没找到也算处理) -> 写入" 的开销 + // 或者只测试 removeHeader 的处理部分。 + + // 为了简单,我们测试 "Write Header" 吧,因为 writeHeader 包含 读 -> 改 -> 写 + await FileHeaderManager.writeHeader(testFile, header, { createBackup: false }); + } + const endString = performance.now(); + const timeString = endString - startString; + console.log(`String Mode 总耗时: ${timeString.toFixed(2)} ms`); + console.log(`String Mode 平均耗时: ${(timeString / iterations).toFixed(2)} ms`); + + + // 3. 测试模拟 Buffer 模式 + // 由于 FileHeaderManager 没有 Buffer 模式,我们只能模拟 "读 Buffer -> 改 Buffer -> 写 Buffer" + // 对比 "读 String -> 改 String -> 写 String" + + console.log(`\n[Buffer Mode (Simulated)] writeHeader 测试 (${iterations} 次)...`); + + const startBuffer = performance.now(); + for (let i = 0; i < iterations; i++) { + const handle = await fs.open(testFile, 'r'); + const bufStats = await handle.stat(); + const buffer = Buffer.alloc(bufStats.size); + await handle.read(buffer, 0, bufStats.size, 0); + await handle.close(); + + // 模拟修改:在 Buffer 中找到 header 位置并替换 + // 实际算法: + // 1. 找到 comment block (buffer.indexOf) -> 极快 + // 2. 将 comment block 转 string (很短) -> 极快 + // 3. 在 comment string 中找 header -> 极快 + // 4. 拼接 Buffer -> 极快 (不需要编解码大段代码) + + const startComment = buffer.indexOf('/*'); + const endComment = buffer.indexOf('*/', startComment); + + // 假设我们找到了 offset,进行拼接 + // 这里不做真实解析,只做 Buffer 操作模拟开销 + const newBuf = Buffer.concat([ + buffer.subarray(0, startComment), + Buffer.from('/* Updated Header */'), // 模拟新头 + buffer.subarray(endComment + 2) + ]); + + await fs.writeFile(testFile, newBuf); + + // 恢复 (其实上面已经写入了,不需要额外恢复,因为每次都覆盖) + } + const endBuffer = performance.now(); + const timeBuffer = endBuffer - startBuffer; + console.log(`Buffer Mode 总耗时: ${timeBuffer.toFixed(2)} ms`); + console.log(`Buffer Mode 平均耗时: ${(timeBuffer / iterations).toFixed(2)} ms`); + + const improvement = ((timeString - timeBuffer) / timeString * 100).toFixed(2); + console.log(`\n🚀 预计 Buffer 模式提升: ${improvement}%`); + + // 清理 + await fs.unlink(testFile); +} + +runTest(); diff --git a/scripts/test/test_doh.js b/scripts/test/test_doh.js new file mode 100644 index 00000000..bfdd7c85 --- /dev/null +++ b/scripts/test/test_doh.js @@ -0,0 +1,68 @@ +/** + * Test DNS over HTTPS (DoH) functionality + * Run with: node scripts/test/test_doh.js + */ + +import { resolveDoh, getSystemProxy } from '../../utils/dns_doh.js'; +import { performance } from 'perf_hooks'; + +// Ensure ENV is loaded if needed, though dns_doh.js imports it. +// Mock ENV if running in isolation without full app context, +// but here we assume utils/env.js handles defaults or .env loading. + +async function testDohResolution(domain) { + console.log(`\nTesting DoH resolution for: ${domain}`); + const start = performance.now(); + try { + const ip = await resolveDoh(domain); + const end = performance.now(); + + console.log(`Result: ${ip}`); + console.log(`Time: ${(end - start).toFixed(2)}ms`); + + if (ip && /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(ip)) { + console.log('✅ Success: Valid IPv4 address returned'); + return true; + } else if (ip === domain) { + console.log('⚠️ Warning: Returned original domain (DoH disabled or failed gracefully)'); + return false; + } else { + console.log('❌ Failed: Invalid result'); + return false; + } + } catch (error) { + console.error('❌ Error during resolution:', error.message); + return false; + } +} + +async function runTests() { + console.log('=== Starting DoH Test ==='); + + // 1. Check System Proxy + console.log('\nChecking System Proxy...'); + const proxy = await getSystemProxy(); + if (proxy) { + console.log(`ℹ️ System Proxy detected: ${proxy}`); + } else { + console.log('ℹ️ No System Proxy detected'); + } + + // 2. Test common domains + const domains = [ + 'www.baidu.com', + 'www.google.com', + 'github.com' + ]; + + for (const domain of domains) { + await testDohResolution(domain); + } + + // 3. Test IP (should return as-is) + await testDohResolution('8.8.8.8'); + + console.log('\n=== Test Complete ==='); +} + +runTests().catch(err => console.error('Test runner error:', err)); diff --git a/scripts/test/test_fileHeaderManager.js b/scripts/test/test_fileHeaderManager.js index 9a797483..3371e5c2 100644 --- a/scripts/test/test_fileHeaderManager.js +++ b/scripts/test/test_fileHeaderManager.js @@ -87,6 +87,61 @@ function test() { await FileHeaderManager.writeHeader(jsWithCommentFile, headerObj); console.log('\n添加文件头后:'); console.log(await fs.readFile(jsWithCommentFile, 'utf8')); + + // 测试3.5: 复杂嵌套头信息 + console.log('\n\n测试3.5: 复杂嵌套头信息'); + const complexFile = path.join(testDir, 'complex.js'); + const complexContent = `/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: '央视大全', + lang: 'ds', + isProxyPath: true, + more: { + parseApi: [ + { + host: 'cctv://(.+)', + flag: 'CCTV' + }, + { + host: 'cctv4k://(.+)', + flag: 'CCTV4K' + }, + { + host: 'cctvlive://(.+)', + flag: 'CCTV直播' + }, + ] + }, + +}) +*/ +var rule = {};`; + await createTestFile(complexFile, complexContent); + + // 读取并验证 + const complexHeader = await FileHeaderManager.readHeader(complexFile); + console.log('读取复杂头信息:', complexHeader.title); + if (complexHeader.more && complexHeader.more.parseApi && complexHeader.more.parseApi.length === 3) { + console.log('✓ 复杂结构解析正确'); + } else { + console.error('✗ 复杂结构解析失败'); + } + + // 写入并验证不损坏 + await FileHeaderManager.writeHeader(complexFile, complexHeader); + const newComplexContent = await fs.readFile(complexFile, 'utf8'); + // Check for cleanliness (no trailing garbage like in the bug) + // The bug caused "})'," or similar garbage at the end of the comment block + // The correct content should end the comment cleanly. + if (newComplexContent.includes("host: 'cctv://(.+)'") && !newComplexContent.includes("})',")) { + console.log('✓ 写入复杂头信息正确 (无乱码残留)'); + } else { + console.error('✗ 写入复杂头信息失败 (可能有残留)'); + console.log(newComplexContent); + } // 测试4: 测试内容完整性检查 console.log('\n\n测试4: 内容完整性检查'); diff --git a/scripts/test/test_header_parser_perf.js b/scripts/test/test_header_parser_perf.js new file mode 100644 index 00000000..983828cd --- /dev/null +++ b/scripts/test/test_header_parser_perf.js @@ -0,0 +1,162 @@ + +import FileHeaderManager from '../../utils/fileHeaderManager.js'; + +// 旧的算法实现 (为了对比) +function findHeaderBlockOld(text, ext) { + const startMarker = '@header('; + const startIndex = text.indexOf(startMarker); + if (startIndex === -1) return null; + + let index = startIndex + startMarker.length; + let balance = 1; + let inString = false; + let stringChar = ''; + let escape = false; + let inLineComment = false; + let inBlockComment = false; + + for (; index < text.length; index++) { + const char = text[index]; + + if (inLineComment) { + if (char === '\n') inLineComment = false; + continue; + } + + if (inBlockComment) { + if (char === '*' && text[index + 1] === '/') { + inBlockComment = false; + index++; + } + continue; + } + + if (inString) { + if (escape) { + escape = false; + } else if (char === '\\') { + escape = true; + } else if (char === stringChar) { + inString = false; + } + continue; + } + + // Start of comment + if (char === '/' && text[index + 1] === '/') { + inLineComment = true; + index++; + } else if (char === '/' && text[index + 1] === '*') { + inBlockComment = true; + index++; + } else if (ext === '.py' && char === '#') { + inLineComment = true; + } else if (char === '"' || char === "'") { + inString = true; + stringChar = char; + } else if (char === '(') { + balance++; + } else if (char === ')') { + balance--; + if (balance === 0) { + return { + start: startIndex, + end: index + 1, + content: text.substring(startIndex + startMarker.length, index) + }; + } + } + } + return null; +} + +// 构造测试数据 +const simpleHeader = ` +/* +@header({ + title: "Simple", + version: 1 +}) +*/ +`; + +const complexHeader = ` +/* +@header({ + title: "Complex Header", + description: "Contains strings with parens ) and comments // inside strings", + nested: { + obj: { a: 1, b: 2 }, + arr: [1, 2, 3, "string with )"] + }, + regex: "cctv://(.+)", + // This is a comment inside the block + /* Another block comment */ + code: "function() { return 'ok'; }" +}) +*/ +`; + +const largeHeader = ` +/* +@header({ + title: "Large Header", + data: "${'x'.repeat(5000)}", + items: [ + ${Array(100).fill('{ name: "item", value: "test string with ) inside" }').join(',\n')} + ] +}) +*/ +`; + +async function runBenchmark() { + console.log('=== findHeaderBlock 算法性能基准测试 ==='); + const iterations = 100000; // 增加循环次数以放大差异 + + const testCases = [ + { name: 'Simple Header', data: simpleHeader }, + { name: 'Complex Header', data: complexHeader }, + { name: 'Large Header (~10KB)', data: largeHeader } + ]; + + for (const testCase of testCases) { + console.log(`\n测试场景: ${testCase.name} (循环 ${iterations} 次)`); + + // 1. 测试旧算法 + const startOld = performance.now(); + for (let i = 0; i < iterations; i++) { + findHeaderBlockOld(testCase.data, '.js'); + } + const endOld = performance.now(); + const timeOld = endOld - startOld; + console.log(`[旧算法] 总耗时: ${timeOld.toFixed(4)} ms | 平均: ${(timeOld/iterations).toFixed(5)} ms`); + + // 2. 测试新算法 + const startNew = performance.now(); + for (let i = 0; i < iterations; i++) { + FileHeaderManager.findHeaderBlock(testCase.data, '.js'); + } + const endNew = performance.now(); + const timeNew = endNew - startNew; + console.log(`[新算法] 总耗时: ${timeNew.toFixed(4)} ms | 平均: ${(timeNew/iterations).toFixed(5)} ms`); + + // 3. 计算提升 + const improvement = ((timeOld - timeNew) / timeOld * 100).toFixed(2); + console.log(`🚀 性能提升: ${improvement}%`); + + // 验证正确性 + const resOld = findHeaderBlockOld(testCase.data, '.js'); + const resNew = FileHeaderManager.findHeaderBlock(testCase.data, '.js'); + if (resOld?.content !== resNew?.content) { + console.error('❌ 结果不一致!'); + console.log('Old Content Length:', resOld?.content?.length); + console.log('New Content Length:', resNew?.content?.length); + // console.log('Old:', resOld?.content); + // console.log('New:', resNew?.content); + } else { + console.log('✅ 结果一致'); + } + } +} + +runBenchmark(); diff --git a/spider/js/_lib.cntv-urlparse.cjs b/spider/js/_lib.cntv-urlparse.cjs new file mode 100644 index 00000000..a3a76855 --- /dev/null +++ b/spider/js/_lib.cntv-urlparse.cjs @@ -0,0 +1,282 @@ +#!/usr/bin/env node +/** + * CCTV Video URL Parser + * 解析央视视频URL,获取视频下载链接 + * + * 使用方法: + * node parse_url.js "https://tv.cctv.com/2026/03/13/VIDE1I89jcwxtmOiZUd6zsLR260313.shtml" + * node parse_url.js "330318aa5ca745d286b8d6c57e971a39" + * echo "..." | node parse_url.js - + */ + +const crypto = require('crypto'); +const fs = require('fs'); + +// 固定参数 +const CCTV_API_URL = 'https://vdn.apps.cntv.cn/api/getHttpVideoInfo.do'; +const SECRET_KEY = '47899B86370B879139C08EA3B5E88267'; +const UID = '826D8646DEBBFD97A82D23CAE45A55BE'; + +// 提取视频ID的正则规则 +const PID_RULES = [ + /var\s+guid\s*=\s*["']([\da-fA-F]+)["']/, + /videoCenterId(?:["']\s*,|:)\s*["']([\da-fA-F]+)["']/, + /changePlayer\s*\(\s*["']([\da-fA-F]+)["']\)/, + /load[Vv]ideo\s*\(\s*["']([\da-fA-F]+)["']\)/, + /var\s+initMyAray\s*=\s*["']([\da-fA-F]+)["']/, + /var\s+ids\s*=\s*\[["']([\da-fA-F]+)["']\]/ +]; + +// PID格式:32位十六进制字符串 +const PID_PATTERN = /^[\da-fA-F]{32}$/; + +/** + * MD5哈希函数 + */ +function md5(value) { + return crypto.createHash('md5').update(value, 'utf-8').digest('hex'); +} + +/** + * HTTP GET请求(使用fetch) + */ +async function httpGet(url) { + try { + const response = await fetch(url, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' + } + }); + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + return await response.text(); + } catch (error) { + throw error; + } +} + +/** + * 判断输入类型 + * @param {string} input - 用户输入 + * @returns {string} - 'url' | 'pid' | 'html' | 'stdin' + */ +function detectInputType(input) { + if (input === '-') { + return 'stdin'; + } + // 优先检测URL + if (input.match(/^https?:\/\//i)) { + return 'url'; + } + // 检测HTML/JavaScript内容(包含HTML标签或JavaScript变量声明) + if (input.includes(' bestBandwidth) { + bestBandwidth = bandwidth; + bestUri = uriLine; + } + break; + } + } + } + } + } + + // 如果没有找到多码率流,直接返回第一个非空行(单码率情况) + if (!bestUri) { + for (const line of lines) { + const trimmed = line.trim(); + if (trimmed && !trimmed.startsWith('#')) { + bestUri = trimmed; + break; + } + } + } + + // 处理路径 + if (bestUri && !bestUri.startsWith('http')) { + const urlObj = new URL(m3u8BaseUrl); + // 如果是绝对路径(以/开头) + if (bestUri.startsWith('/')) { + bestUri = `${urlObj.protocol}//${urlObj.host}${bestUri}`; + } else { + // 相对路径 + const basePath = urlObj.pathname.substring(0, urlObj.pathname.lastIndexOf('/') + 1); + bestUri = `${urlObj.protocol}//${urlObj.host}${basePath}${bestUri}`; + } + } + + return bestUri; +} + +/** + * 根据PID获取视频信息 + * @param {string} pid - 视频ID + * @returns {Promise} 视频信息对象 + */ +async function getVideoInfoByPid(pid) { + console.log(`使用视频ID: ${pid}`); + + // 构建API请求参数 + console.log('步骤1: 构建API请求...'); + const tsp = Math.floor(Date.now() / 1000); + const vn = '2049'; + const vc = md5(tsp + vn + SECRET_KEY + UID); + + const apiParams = new URLSearchParams({ + pid: pid, + client: 'flash', + im: '0', + tsp: tsp.toString(), + vn: vn, + vc: vc, + uid: UID, + wlan: '' + }); + + const apiUrl = `${CCTV_API_URL}?${apiParams.toString()}`; + console.log(`API URL: ${apiUrl}`); + + // 调用API获取视频信息 + console.log('步骤2: 获取视频信息...'); + const apiResponse = await httpGet(apiUrl); + const videoData = JSON.parse(apiResponse); + + console.log('视频信息:', { + title: videoData.title, + pgtv: videoData.pgtv + }); + + // 获取m3u8下载链接 + console.log('步骤3: 解析下载链接...'); + const manifest = videoData.manifest || {}; + let hlsUrl = manifest.hls_h5e_url || manifest.hls_url || videoData.hls_h5e_url || videoData.hls_url; + + if (!hlsUrl) { + throw new Error('无法获取HLS下载链接'); + } + console.log(`HLS URL: ${hlsUrl}`); + + // 解析m3u8获取最高质量的流 + console.log('步骤4: 解析M3U8获取最佳质量...'); + const m3u8Content = await httpGet(hlsUrl); + const downloadUrl = parseM3U8ForBestQuality(m3u8Content, hlsUrl); + + if (!downloadUrl) { + throw new Error('无法解析M3U8内容'); + } + + console.log(`最终下载链接: ${downloadUrl}`); + + return { + success: true, + title: videoData.title, + pid: pid, + pgtv: videoData.pgtv, + hls_key: manifest.hls_h5e_url ? 'hls_h5e_url' : 'hls_url', + download_url: downloadUrl, + m3u8_url: hlsUrl, + cover_url: videoData.image + }; +} + +/** + * 主函数:解析CCTV视频URL + * @param {string} input - 输入(URL、PID或HTML内容) + * @returns {Promise} 视频信息对象 + */ +async function parseCCTVUrl(input) { + try { + const inputType = detectInputType(input); + console.log(`检测到输入类型: ${inputType}`); + + // 如果是PID,直接调用API + if (inputType === 'pid') { + return await getVideoInfoByPid(input); + } + + // 如果是URL,获取页面内容并提取PID + if (inputType === 'url') { + console.log(`正在解析URL: ${input}`); + console.log('步骤1: 获取页面内容...'); + const html = await httpGet(input); + const pid = extractPid(html); + + if (!pid) { + throw new Error('无法从页面中提取视频ID'); + } + console.log(`找到视频ID: ${pid}`); + + return await getVideoInfoByPid(pid); + } + + // 如果是HTML内容,直接提取PID + if (inputType === 'html') { + console.log('检测到HTML内容,直接提取视频ID...'); + const pid = extractPid(input); + + if (!pid) { + throw new Error('无法从HTML内容中提取视频ID'); + } + console.log(`找到视频ID: ${pid}`); + + return await getVideoInfoByPid(pid); + } + + throw new Error(`不支持的输入类型: ${inputType}`); + + } catch (error) { + console.error('解析失败:', error.message); + return { + success: false, + error: error.message + }; + } +} + +// 导出函数供其他模块使用 +module.exports = {parseCCTVUrl, detectInputType, getVideoInfoByPid}; \ No newline at end of file diff --git a/spider/js/_lib.cntv-wasm.cjs b/spider/js/_lib.cntv-wasm.cjs new file mode 100644 index 00000000..942a789c --- /dev/null +++ b/spider/js/_lib.cntv-wasm.cjs @@ -0,0 +1,5 @@ +var CNTVModule=function(){var _scriptDir="undefined"!=typeof document&&document.currentScript?document.currentScript.src:void 0;return function(CNTVModule){CNTVModule=CNTVModule||{};var Module=void 0!==CNTVModule?CNTVModule:{},moduleOverrides={},key;for(key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var arguments_=[],thisProgram="./this.program",quit_=function(A,e){throw e},ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_HAS_NODE=!1,ENVIRONMENT_IS_SHELL=!1,ENVIRONMENT_IS_WEB="object"==typeof window,ENVIRONMENT_IS_WORKER="function"==typeof importScripts,ENVIRONMENT_HAS_NODE="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER,scriptDirectory="",read_,readAsync,readBinary,setWindowTitle;function locateFile(A){return Module.locateFile?Module.locateFile(A,scriptDirectory):scriptDirectory+A}(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&(ENVIRONMENT_IS_WORKER?scriptDirectory=self.location.href:document.currentScript&&(scriptDirectory=document.currentScript.src),_scriptDir&&(scriptDirectory=_scriptDir),scriptDirectory=0!==scriptDirectory.indexOf("blob:")?scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1):"",read_=function(e){try{var t=new XMLHttpRequest;return t.open("GET",e,!1),t.send(null),t.responseText}catch(A){t=tryParseAsDataURI(e);if(t)return intArrayToString(t);throw A}},ENVIRONMENT_IS_WORKER&&(readBinary=function(e){try{var t=new XMLHttpRequest;return t.open("GET",e,!1),t.responseType="arraybuffer",t.send(null),new Uint8Array(t.response)}catch(A){t=tryParseAsDataURI(e);if(t)return t;throw A}}),readAsync=function(e,t,g){var r=new XMLHttpRequest;r.open("GET",e,!0),r.responseType="arraybuffer",r.onload=function(){var A;200==r.status||0==r.status&&r.response?t(r.response):(A=tryParseAsDataURI(e))?t(A.buffer):g()},r.onerror=g,r.send(null)},setWindowTitle=function(A){document.title=A});var out=Module.print||console.log.bind(console),err=Module.printErr||console.warn.bind(console);for(key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);function dynamicAlloc(A){var e=HEAP32[DYNAMICTOP_PTR>>2],A=e+A+15&-16;return A>_emscripten_get_heap_size()&&abort(),HEAP32[DYNAMICTOP_PTR>>2]=A,e}function getNativeTypeSize(A){switch(A){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:var e;return"*"===A[A.length-1]?4:"i"===A[0]?(assert((e=parseInt(A.substr(1)))%8==0,"getNativeTypeSize invalid bits "+e+", type "+A),e/8):0}}function warnOnce(A){warnOnce.shown||(warnOnce.shown={}),warnOnce.shown[A]||(warnOnce.shown[A]=1,err(A))}moduleOverrides=null,Module.arguments&&(arguments_=Module.arguments),Module.thisProgram&&(thisProgram=Module.thisProgram),Module.quit&&(quit_=Module.quit);var asm2wasmImports={"f64-rem":function(A,e){return A%e},debugger:function(){}},jsCallStartIndex=1,functionPointers=new Array(14);function addFunction(A,e){for(var t=0;t<14;t++)if(!functionPointers[t])return functionPointers[t]=A,jsCallStartIndex+t;throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}function makeBigInt(A,e,t){return t?(A>>>0)+4294967296*(e>>>0):(A>>>0)+4294967296*(0|e)}var tempRet0=0,setTempRet0=function(A){tempRet0=A},getTempRet0=function(){return tempRet0},wasmBinary,wasmMemory,wasmTable;function setValue(A,e,t,g){switch(t="*"===(t=t||"i8").charAt(t.length-1)?"i32":t){case"i1":case"i8":HEAP8[A>>0]=e;break;case"i16":HEAP16[A>>1]=e;break;case"i32":HEAP32[A>>2]=e;break;case"i64":tempI64=[e>>>0,1<=+Math_abs(tempDouble=e)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0],HEAP32[A>>2]=tempI64[0],HEAP32[A+4>>2]=tempI64[1];break;case"float":HEAPF32[A>>2]=e;break;case"double":HEAPF64[A>>3]=e;break;default:abort("invalid type for setValue: "+t)}}Module.wasmBinary&&(wasmBinary=Module.wasmBinary),"object"!=typeof WebAssembly&&err("no native wasm support detected");var ABORT=!1,EXITSTATUS=0;function assert(A,e){A||abort("Assertion failed: "+e)}var ALLOC_NONE=3;function allocate(A,e,t,g){var r,B,n="number"==typeof A?(r=!0,A):(r=!1,A.length),E="string"==typeof e?e:null,C=t==ALLOC_NONE?g:[_malloc,stackAlloc,dynamicAlloc][t](Math.max(n,E?1:e.length));if(r){for(assert(0==(3&(g=C))),B=C+(-4&n);g>2]=0;for(B=C+n;g>0]=0}else if("i8"===E)A.subarray||A.slice?HEAPU8.set(A,C):HEAPU8.set(new Uint8Array(A),C);else for(var o,I,Q=0;Q>10,56320|1023&E)))):B+=String.fromCharCode(C)}return B}function UTF8ToString(A,e){return A?UTF8ArrayToString(HEAPU8,A,e):""}function stringToUTF8Array(A,e,t,g){if(!(0>6}else{if(E<=65535){if(B<=t+2)break;e[t++]=224|E>>12}else{if(B<=t+3)break;e[t++]=240|E>>18,e[t++]=128|E>>12&63}e[t++]=128|E>>6&63}e[t++]=128|63&E}}return e[t]=0,t-r}function stringToUTF8(A,e,t){return stringToUTF8Array(A,HEAPU8,e,t)}function lengthBytesUTF8(A){for(var e=0,t=0;t>2]=DYNAMIC_BASE;var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for("function"==typeof Module.preRun&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=!0,Module.noFSInit||FS.init.initialized||FS.init(),TTY.init(),callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=!1,callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=!0}function postRun(){if(Module.postRun)for("function"==typeof Module.postRun&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(A){__ATPRERUN__.unshift(A)}function addOnPostRun(A){__ATPOSTRUN__.unshift(A)}function unSign(A,e,t){return 0<=A?A:e<=32?2*Math.abs(1<>2]=HEAPU32[eb+A[e]>>2]+eb});var ___exception_infos={},___exception_caught=[];function ___exception_addRef(A){A&&___exception_infos[A].refcount++}function ___exception_deAdjust(A){if(A&&!___exception_infos[A])for(var e in ___exception_infos)for(var t=+e,g=___exception_infos[t].adjusted,r=g.length,B=0;B>2]=A),A}var PATH_FS={resolve:function(){for(var A="",e=!1,t=arguments.length-1;-1<=t&&!e;t--){var g=0<=t?arguments[t]:FS.cwd();if("string"!=typeof g)throw new TypeError("Arguments to path.resolve must be strings");if(!g)return"";A=g+"/"+A,e="/"===g.charAt(0)}return(e?"/":"")+(A=PATH.normalizeArray(A.split("/").filter(function(A){return!!A}),!e).join("/"))||"."},relative:function(A,e){function t(A){for(var e=0;ee)A.contents.length=e;else for(;A.contents.length=A.node.usedBytes)return 0;var n=Math.min(A.node.usedBytes-r,g);if(8t.timestamp)&&(n.push(A),B++)}),[]);if(Object.keys(r.entries).forEach(function(A){r.entries[A];g.entries[A]||(t.push(A),B++)}),!B)return e(null);var E=!1,A=("remote"===g.type?g:r).db.transaction([IDBFS.DB_STORE_NAME],"readwrite"),C=A.objectStore(IDBFS.DB_STORE_NAME);function o(A){if(A&&!E)return E=!0,e(A)}A.onerror=function(A){o(this.error),A.preventDefault()},A.oncomplete=function(A){E||e(null)},n.sort().forEach(function(t){"local"===r.type?IDBFS.loadRemoteEntry(C,t,function(A,e){if(A)return o(A);IDBFS.storeLocalEntry(t,e,o)}):IDBFS.loadLocalEntry(t,function(A,e){if(A)return o(A);IDBFS.storeRemoteEntry(C,t,e,o)})}),t.sort().reverse().forEach(function(A){"local"===r.type?IDBFS.removeLocalEntry(A,o):IDBFS.removeRemoteEntry(C,A,o)})}},WORKERFS={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:function(A){assert(ENVIRONMENT_IS_WORKER),WORKERFS.reader||(WORKERFS.reader=new FileReaderSync);var B=WORKERFS.createNode(null,"/",WORKERFS.DIR_MODE,0),n={};function g(A){for(var e=A.split("/"),t=B,g=0;g=A.node.size?0:(A=A.node.contents.slice(r,r+g),r=WORKERFS.reader.readAsArrayBuffer(A),e.set(new Uint8Array(r),t),A.size)},write:function(A,e,t,g,r){throw new FS.ErrnoError(5)},llseek:function(A,e,t){if(1===t?e+=A.position:2===t&&FS.isFile(A.node.mode)&&(e+=A.node.size),e<0)throw new FS.ErrnoError(22);return e}}},FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:!1,ignorePermissions:!0,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(A){if(A instanceof FS.ErrnoError)return ___setErrNo(A.errno);throw A+" : "+stackTrace()},lookupPath:function(A,e){if(e=e||{},!(A=PATH_FS.resolve(FS.cwd(),A)))return{path:"",node:null};var t,g={follow_mount:!0,recurse_count:0};for(t in g)void 0===e[t]&&(e[t]=g[t]);if(8>>0)%FS.nameTable.length},hashAddNode:function(A){var e=FS.hashName(A.parent.id,A.name);A.name_next=FS.nameTable[e],FS.nameTable[e]=A},hashRemoveNode:function(A){var e=FS.hashName(A.parent.id,A.name);if(FS.nameTable[e]===A)FS.nameTable[e]=A.name_next;else for(var t=FS.nameTable[e];t;){if(t.name_next===A){t.name_next=A.name_next;break}t=t.name_next}},lookupNode:function(A,e){var t=FS.mayLookup(A);if(t)throw new FS.ErrnoError(t,A);for(var t=FS.hashName(A.id,e),g=FS.nameTable[t];g;g=g.name_next){var r=g.name;if(g.parent.id===A.id&&r===e)return g}return FS.lookup(A,e)},createNode:function(A,e,t,g){FS.FSNode||(FS.FSNode=function(A,e,t,g){this.parent=A=A||this,this.mount=A.mount,this.mounted=null,this.id=FS.nextInode++,this.name=e,this.mode=t,this.node_ops={},this.stream_ops={},this.rdev=g},FS.FSNode.prototype={},Object.defineProperties(FS.FSNode.prototype,{read:{get:function(){return 365==(365&this.mode)},set:function(A){A?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146==(146&this.mode)},set:function(A){A?this.mode|=146:this.mode&=-147}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}}));A=new FS.FSNode(A,e,t,g);return FS.hashAddNode(A),A},destroyNode:function(A){FS.hashRemoveNode(A)},isRoot:function(A){return A===A.parent},isMountpoint:function(A){return!!A.mounted},isFile:function(A){return 32768==(61440&A)},isDir:function(A){return 16384==(61440&A)},isLink:function(A){return 40960==(61440&A)},isChrdev:function(A){return 8192==(61440&A)},isBlkdev:function(A){return 24576==(61440&A)},isFIFO:function(A){return 4096==(61440&A)},isSocket:function(A){return 49152==(49152&A)},flagModes:{r:0,rs:1052672,"r+":2,w:577,wx:705,xw:705,"w+":578,"wx+":706,"xw+":706,a:1089,ax:1217,xa:1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(A){var e=FS.flagModes[A];if(void 0===e)throw new Error("Unknown file open mode: "+A);return e},flagsToPermissionString:function(A){var e=["r","w","rw"][3&A];return 512&A&&(e+="w"),e},nodePermissions:function(A,e){return FS.ignorePermissions||(-1===e.indexOf("r")||292&A.mode)&&(-1===e.indexOf("w")||146&A.mode)&&(-1===e.indexOf("x")||73&A.mode)?0:13},mayLookup:function(A){var e=FS.nodePermissions(A,"x");return e||(A.node_ops.lookup?0:13)},mayCreate:function(A,e){try{FS.lookupNode(A,e);return 17}catch(A){}return FS.nodePermissions(A,"wx")},mayDelete:function(A,e,t){var g;try{g=FS.lookupNode(A,e)}catch(A){return A.errno}e=FS.nodePermissions(A,"wx");if(e)return e;if(t){if(!FS.isDir(g.mode))return 20;if(FS.isRoot(g)||FS.getPath(g)===FS.cwd())return 16}else if(FS.isDir(g.mode))return 21;return 0},mayOpen:function(A,e){return A?FS.isLink(A.mode)?40:FS.isDir(A.mode)&&("r"!==FS.flagsToPermissionString(e)||512&e)?21:FS.nodePermissions(A,FS.flagsToPermissionString(e)):2},MAX_OPEN_FDS:4096,nextfd:function(A,e){e=e||FS.MAX_OPEN_FDS;for(var t=A=A||0;t<=e;t++)if(!FS.streams[t])return t;throw new FS.ErrnoError(24)},getStream:function(A){return FS.streams[A]},createStream:function(A,e,t){FS.FSStream||(FS.FSStream=function(){},FS.FSStream.prototype={},Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(A){this.node=A}},isRead:{get:function(){return 1!=(2097155&this.flags)}},isWrite:{get:function(){return 0!=(2097155&this.flags)}},isAppend:{get:function(){return 1024&this.flags}}}));var g,r=new FS.FSStream;for(g in A)r[g]=A[g];A=r;e=FS.nextfd(e,t);return A.fd=e,FS.streams[e]=A},closeStream:function(A){FS.streams[A]=null},chrdev_stream_ops:{open:function(A){var e=FS.getDevice(A.node.rdev);A.stream_ops=e.stream_ops,A.stream_ops.open&&A.stream_ops.open(A)},llseek:function(){throw new FS.ErrnoError(29)}},major:function(A){return A>>8},minor:function(A){return 255&A},makedev:function(A,e){return A<<8|e},registerDevice:function(A,e){FS.devices[A]={stream_ops:e}},getDevice:function(A){return FS.devices[A]},getMounts:function(A){for(var e=[],t=[A];t.length;){var g=t.pop();e.push(g),t.push.apply(t,g.mounts)}return e},syncfs:function(e,t){"function"==typeof e&&(t=e,e=!1),FS.syncFSRequests++,1=g.length&&B(null)}g.forEach(function(A){if(!A.type.syncfs)return n(null);A.type.syncfs(A,e,n)})},mount:function(A,e,t){var g,r="/"===t,B=!t;if(r&&FS.root)throw new FS.ErrnoError(16);if(!r&&!B){B=FS.lookupPath(t,{follow_mount:!1});if(t=B.path,g=B.node,FS.isMountpoint(g))throw new FS.ErrnoError(16);if(!FS.isDir(g.mode))throw new FS.ErrnoError(20)}B={type:A,opts:e,mountpoint:t,mounts:[]},e=A.mount(B);return(e.mount=B).root=e,r?FS.root=e:g&&(g.mounted=B,g.mount)&&g.mount.mounts.push(B),e},unmount:function(A){A=FS.lookupPath(A,{follow_mount:!1});if(!FS.isMountpoint(A.node))throw new FS.ErrnoError(22);var A=A.node,e=A.mounted,g=FS.getMounts(e),e=(Object.keys(FS.nameTable).forEach(function(A){for(var e=FS.nameTable[A];e;){var t=e.name_next;-1!==g.indexOf(e.mount)&&FS.destroyNode(e),e=t}}),A.mounted=null,A.mount.mounts.indexOf(e));A.mount.mounts.splice(e,1)},lookup:function(A,e){return A.node_ops.lookup(A,e)},mknod:function(A,e,t){var g=FS.lookupPath(A,{parent:!0}).node,A=PATH.basename(A);if(!A||"."===A||".."===A)throw new FS.ErrnoError(22);var r=FS.mayCreate(g,A);if(r)throw new FS.ErrnoError(r);if(g.node_ops.mknod)return g.node_ops.mknod(g,A,e,t);throw new FS.ErrnoError(1)},create:function(A,e){return FS.mknod(A,e=(e=void 0!==e?e:438)&4095|32768,0)},mkdir:function(A,e){return FS.mknod(A,e=(e=void 0!==e?e:511)&1023|16384,0)},mkdirTree:function(A,e){for(var t=A.split("/"),g="",r=0;rthis.length-1||A<0))return e=A%this.chunkSize,A=A/this.chunkSize|0,this.getter(A)[e]},r.prototype.setDataGetter=function(A){this.getter=A},r.prototype.cacheLength=function(){var A=new XMLHttpRequest;if(A.open("HEAD",n,!1),A.send(null),!(200<=A.status&&A.status<300||304===A.status))throw new Error("Couldn't load "+n+". Status: "+A.status);var e,g=Number(A.getResponseHeader("Content-length")),t=(e=A.getResponseHeader("Accept-Ranges"))&&"bytes"===e,A=(e=A.getResponseHeader("Content-Encoding"))&&"gzip"===e,r=1048576,B=(t||(r=g),this);B.setDataGetter(function(A){var e=A*r,t=(A+1)*r-1,t=Math.min(t,g-1);if(void 0===B.chunks[A]&&(B.chunks[A]=function(A,e){if(e=B.length)return 0;var n=Math.min(B.length-r,g);if(B.slice)for(var E=0;E>2]=g.dev,HEAP32[t+4>>2]=0,HEAP32[t+8>>2]=g.ino,HEAP32[t+12>>2]=g.mode,HEAP32[t+16>>2]=g.nlink,HEAP32[t+20>>2]=g.uid,HEAP32[t+24>>2]=g.gid,HEAP32[t+28>>2]=g.rdev,HEAP32[t+32>>2]=0,tempI64=[g.size>>>0,(tempDouble=g.size,1<=+Math_abs(tempDouble)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[t+40>>2]=tempI64[0],HEAP32[t+44>>2]=tempI64[1],HEAP32[t+48>>2]=4096,HEAP32[t+52>>2]=g.blocks,HEAP32[t+56>>2]=g.atime.getTime()/1e3|0,HEAP32[t+60>>2]=0,HEAP32[t+64>>2]=g.mtime.getTime()/1e3|0,HEAP32[t+68>>2]=0,HEAP32[t+72>>2]=g.ctime.getTime()/1e3|0,HEAP32[t+76>>2]=0,tempI64=[g.ino>>>0,(tempDouble=g.ino,1<=+Math_abs(tempDouble)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[t+80>>2]=tempI64[0],HEAP32[t+84>>2]=tempI64[1],0},doMsync:function(A,e,t,g){A=new Uint8Array(HEAPU8.subarray(A,A+t));FS.msync(e,A,0,t,g)},doMkdir:function(A,e){return"/"===(A=PATH.normalize(A))[A.length-1]&&(A=A.substr(0,A.length-1)),FS.mkdir(A,e,0),0},doMknod:function(A,e,t){switch(61440&e){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-22}return FS.mknod(A,e,t),0},doReadlink:function(A,e,t){var g,r;return t<=0?-22:(A=FS.readlink(A),g=Math.min(t,lengthBytesUTF8(A)),r=HEAP8[e+g],stringToUTF8(A,e,t+1),HEAP8[e+g]=r,g)},doAccess:function(A,e){var t;return-8&e?-22:(A=FS.lookupPath(A,{follow:!0}).node)?(t="",4&e&&(t+="r"),2&e&&(t+="w"),1&e&&(t+="x"),t&&FS.nodePermissions(A,t)?-13:0):-2},doDup:function(A,e,t){var g=FS.getStream(t);return g&&FS.close(g),FS.open(A,e,0,t,t).fd},doReadv:function(A,e,t,g){for(var r=0,B=0;B>2],E=HEAP32[e+(8*B+4)>>2],n=FS.read(A,HEAP8,n,E,g);if(n<0)return-1;if(r+=n,n>2],E=HEAP32[e+(8*B+4)>>2],n=FS.write(A,HEAP8,n,E,g);if(n<0)return-1;r+=n}return r},varargs:0,get:function(A){return SYSCALLS.varargs+=4,HEAP32[SYSCALLS.varargs-4>>2]},getStr:function(){return UTF8ToString(SYSCALLS.get())},getStreamFromFD:function(){var A=FS.getStream(SYSCALLS.get());if(A)return A;throw new FS.ErrnoError(9)},get64:function(){var A=SYSCALLS.get();SYSCALLS.get();return A},getZero:function(){SYSCALLS.get()}};function ___syscall140(A,e){SYSCALLS.varargs=e;try{var t=SYSCALLS.getStreamFromFD(),g=SYSCALLS.get(),r=SYSCALLS.get(),B=SYSCALLS.get(),n=SYSCALLS.get(),E=4294967296*g+(r>>>0),C=9007199254740992;return E<=-C||C<=E?-75:(FS.llseek(t,E,n),tempI64=[t.position>>>0,(tempDouble=t.position,1<=+Math_abs(tempDouble)?0>>0:~~+Math_ceil((tempDouble-(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[B>>2]=tempI64[0],HEAP32[B+4>>2]=tempI64[1],t.getdents&&0==E&&0===n&&(t.getdents=null),0)}catch(A){return void 0!==FS&&A instanceof FS.ErrnoError||abort(A),-A.errno}}function ___syscall146(A,e){SYSCALLS.varargs=e;try{var t=SYSCALLS.getStreamFromFD(),g=SYSCALLS.get(),r=SYSCALLS.get();return SYSCALLS.doWritev(t,g,r)}catch(A){return void 0!==FS&&A instanceof FS.ErrnoError||abort(A),-A.errno}}function ___syscall6(A,e){SYSCALLS.varargs=e;try{var t=SYSCALLS.getStreamFromFD();return FS.close(t),0}catch(A){return void 0!==FS&&A instanceof FS.ErrnoError||abort(A),-A.errno}}function getShiftFromSize(A){switch(A){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+A)}}function embind_init_charCodes(){for(var A=new Array(256),e=0;e<256;++e)A[e]=String.fromCharCode(e);embind_charCodes=A}var embind_charCodes=void 0;function readLatin1String(A){for(var e="",t=A;HEAPU8[t];)e+=embind_charCodes[HEAPU8[t++]];return e}var awaitingDependencies={},registeredTypes={},typeDependencies={},char_0=48,char_9=57;function makeLegalFunctionName(A){var e;return void 0===A?"_unknown":(e=(A=A.replace(/[^a-zA-Z0-9_]/g,"$")).charCodeAt(0),char_0<=e&&e<=char_9?"_"+A:A)}function createNamedFunction(A,e){return A=makeLegalFunctionName(A),new Function("body","return function "+A+'() {\n "use strict"; return body.apply(this, arguments);\n};\n')(e)}function extendError(A,e){var t=createNamedFunction(e,function(A){this.name=e,this.message=A;A=new Error(A).stack;void 0!==A&&(this.stack=this.toString()+"\n"+A.replace(/^Error(:[^\n]*)?\n/,""))});return t.prototype=Object.create(A.prototype),(t.prototype.constructor=t).prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message},t}var BindingError=void 0;function throwBindingError(A){throw new BindingError(A)}var InternalError=void 0;function registerType(A,e,t){if(t=t||{},!("argPackAdvance"in e))throw new TypeError("registerType registeredInstance requires argPackAdvance");var g=e.name;if(A||throwBindingError('type "'+g+'" must have a positive integer typeid pointer'),registeredTypes.hasOwnProperty(A)){if(t.ignoreDuplicateRegistrations)return;throwBindingError("Cannot register type '"+g+"' twice")}registeredTypes[A]=e,delete typeDependencies[A],awaitingDependencies.hasOwnProperty(A)&&(t=awaitingDependencies[A],delete awaitingDependencies[A],t.forEach(function(A){A()}))}function __embind_register_bool(A,t,g,r,B){var n=getShiftFromSize(g);registerType(A,{name:t=readLatin1String(t),fromWireType:function(A){return!!A},toWireType:function(A,e){return e?r:B},argPackAdvance:8,readValueFromPointer:function(A){var e;if(1===g)e=HEAP8;else if(2===g)e=HEAP16;else{if(4!==g)throw new TypeError("Unknown boolean type size: "+t);e=HEAP32}return this.fromWireType(e[A>>n])},destructorFunction:null})}var emval_free_list=[],emval_handle_array=[{},{value:{href:"blob:https://tv.cctv.com/a2a31e32-7705-4db1-b190-1bd401598188"}},{value:null},{value:!0},{value:!1}];function __emval_decref(A){4>2])}function __embind_register_emval(A,e){registerType(A,{name:e=readLatin1String(e),fromWireType:function(A){var e=emval_handle_array[A].value;return __emval_decref(A),e},toWireType:function(A,e){return __emval_register(e)},argPackAdvance:8,readValueFromPointer:simpleReadValueFromPointer,destructorFunction:null})}function _embind_repr(A){var e;return null===A?"null":"object"==(e=typeof A)||"array"==e||"function"==e?A.toString():""+A}function floatReadValueFromPointer(A,e){switch(e){case 2:return function(A){return this.fromWireType(HEAPF32[A>>2])};case 3:return function(A){return this.fromWireType(HEAPF64[A>>3])};default:throw new TypeError("Unknown float type: "+A)}}function __embind_register_float(A,e,t){t=getShiftFromSize(t);registerType(A,{name:e=readLatin1String(e),fromWireType:function(A){return A},toWireType:function(A,e){if("number"!=typeof e&&"boolean"!=typeof e)throw new TypeError('Cannot convert "'+_embind_repr(e)+'" to '+this.name);return e},argPackAdvance:8,readValueFromPointer:floatReadValueFromPointer(e,t),destructorFunction:null})}function integerReadValueFromPointer(A,e,t){switch(e){case 0:return t?function(A){return HEAP8[A]}:function(A){return HEAPU8[A]};case 1:return t?function(A){return HEAP16[A>>1]}:function(A){return HEAPU16[A>>1]};case 2:return t?function(A){return HEAP32[A>>2]}:function(A){return HEAPU32[A>>2]};default:throw new TypeError("Unknown integer type: "+A)}}function __embind_register_integer(A,t,e,g,r){t=readLatin1String(t),-1===r&&(r=4294967295);var B,n=getShiftFromSize(e),E=function(A){return A},C=(0===g&&(B=32-8*e,E=function(A){return A<>>B}),-1!=t.indexOf("unsigned"));registerType(A,{name:t,fromWireType:E,toWireType:function(A,e){if("number"!=typeof e&&"boolean"!=typeof e)throw new TypeError('Cannot convert "'+_embind_repr(e)+'" to '+this.name);if(e>>0:0|e},argPackAdvance:8,readValueFromPointer:integerReadValueFromPointer(t,n,0!==g),destructorFunction:null})}function __embind_register_memory_view(A,e,t){var g=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][e];function r(A){var e=HEAPU32,t=e[A>>=2],A=e[A+1];return new g(e.buffer,A,t)}registerType(A,{name:t=readLatin1String(t),fromWireType:r,argPackAdvance:8,readValueFromPointer:r},{ignoreDuplicateRegistrations:!0})}function __embind_register_std_string(A,e){var I="std::string"===(e=readLatin1String(e));registerType(A,{name:e,fromWireType:function(A){var e=HEAPU32[A>>2];if(I){for(var t=HEAPU8[A+4+e],g=0,r=(0!=t&&(g=t,HEAPU8[A+4+e]=0),A+4),B=0;B<=e;++B){var n,E,C=A+4+B;0==HEAPU8[C]&&(n=UTF8ToString(r),E=void 0===E?n:E+String.fromCharCode(0)+n,r=C+1)}0!=g&&(HEAPU8[A+4+e]=g)}else{for(var o=new Array(e),B=0;B>2]=g,I&&t)stringToUTF8(e,r+4,g+1);else if(t)for(var B=0;B>2],g=new Array(t),r=A+4>>o,B=0;B>2]=g,r+4>>o),n=0;n>2]=r,e.toWireType(g,A)}var emval_symbols={};function getStringOrSymbol(A){var e=emval_symbols[A];return void 0===e?readLatin1String(A):e}function emval_get_global(){return"object"==typeof globalThis?globalThis:Function("return this")()}function __emval_get_global(A){return 0===A?__emval_register(emval_get_global()):(A=getStringOrSymbol(A),__emval_register(emval_get_global()[A]))}function __emval_get_property(A,e){return __emval_register((A=requireHandle(A))[e=requireHandle(e)])}function runDestructors(A){for(;A.length;){var e=A.pop();A.pop()(e)}}function __emval_run_destructors(A){runDestructors(emval_handle_array[A].value),__emval_decref(A)}function __emval_take_value(A,e){return __emval_register((A=requireRegisteredType(A,"_emval_take_value")).readValueFromPointer(e))}function _abort(){Module.abort()}function _emscripten_date_now(){return Date.now()}function __emscripten_traverse_stack(A){if(!A||!A.callee||!A.callee.name)return[null,"",""];A.callee.toString();var e,t=A.callee.name,g="(",r=!0;for(e in A){var B=A[e];r||(g+=", "),r=!1,g+="number"==typeof B||"string"==typeof B?B:"("+typeof B+")"}g+=")";var n=A.callee.caller;return[A=n?n.arguments:[],t,g=r?"":g]}function _emscripten_get_callstack_js(A){var e=(g=jsStackTrace()).lastIndexOf("_emscripten_log"),t=g.lastIndexOf("_emscripten_get_callstack"),e=g.indexOf("\n",Math.max(e,t))+1,g=g.slice(e),r=(8&A&&"undefined"==typeof emscripten_source_map&&(warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.'),A=8^A|16),null);if(128&A)for(r=__emscripten_traverse_stack(arguments);0<=r[1].indexOf("_emscripten_");)r=__emscripten_traverse_stack(r[0]);var B,n=g.split("\n"),E=(g="",new RegExp("\\s*(.*?)@(.*?):([0-9]+):([0-9]+)")),C=new RegExp("\\s*(.*?)@(.*):(.*)(:(.*))?"),o=new RegExp("\\s*at (.*?) \\((.*):(.*):(.*)\\)");for(B in n){var I=n[B],Q="",i="",a=0,s=0,l=o.exec(I);if(l&&5==l.length)Q=l[1],i=l[2],a=l[3],s=l[4];else{if(!((l=(l=E.exec(I))||C.exec(I))&&4<=l.length)){g+=I+"\n";continue}Q=l[1],i=l[2],a=l[3],s=0|l[4]}var c,I=(I=32&A?demangle(Q):Q)||Q,l=!1;8&A&&(l=(c=emscripten_source_map.originalPositionFor({line:a,column:s}))&&c.source)&&(64&A&&(c.source=c.source.substring(c.source.replace(/\\/g,"/").lastIndexOf("/")+1)),g+=" at "+I+" ("+c.source+":"+c.line+":"+c.column+")\n"),(16&A||!l)&&(g+=(l?" = "+Q:" at "+I)+" ("+(i=64&A?i.substring(i.replace(/\\/g,"/").lastIndexOf("/")+1):i)+":"+a+":"+s+")\n"),128&A&&r[0]&&(r[1]==Q&&0>3],r+=8):"i64"==A?(e=[HEAP32[r>>2],HEAP32[r+4>>2]],r+=8):(assert(0==(3&r)),A="i32",e=HEAP32[r>>2],r+=4),e}for(var B,n=[];;){var E,C=t;if(0===(E=HEAP8[t>>0]))break;if(B=HEAP8[t+1>>0],37==E){var o=!1,I=!1,Q=!1,i=!1,a=!1;A:for(;;){switch(B){case 43:o=!0;break;case 45:I=!0;break;case 35:Q=!0;break;case 48:if(i)break A;i=!0;break;case 32:a=!0;break;default:break A}B=HEAP8[++t+1>>0]}var s=0;if(42==B)s=g("i32"),B=HEAP8[++t+1>>0];else for(;48<=B&&B<=57;)s=10*s+(B-48),B=HEAP8[++t+1>>0];var l=!1,c=-1;if(46==B){if(l=!(c=0),42==(B=HEAP8[++t+1>>0]))c=g("i32"),t++;else for(;;){var w=HEAP8[t+1>>0];if(w<48||57>0]}switch(c<0&&(l=!(c=6)),String.fromCharCode(B)){case"h":var u=104==HEAP8[t+2>>0]?(t++,1):2;break;case"l":u=108==HEAP8[t+2>>0]?(t++,8):4;break;case"L":case"q":case"j":u=8;break;case"z":case"t":case"I":u=4;break;default:u=null}switch(u&&t++,B=HEAP8[t+1>>0],String.fromCharCode(B)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":var M,d,F=100==B||105==B,F=(d=g("i"+8*(u=u||4)),8==u&&(d=makeBigInt(d[0],d[1],117==B)),u<=4&&(d=(F?reSign:unSign)(d&Math.pow(256,u)-1,8*u)),Math.abs(d)),f="";if(100==B||105==B)M=reSign(d,8*u,1).toString(10);else if(117==B)M=unSign(d,8*u,1).toString(10),d=Math.abs(d);else if(111==B)M=(Q?"0":"")+F.toString(8);else if(120==B||88==B){if(f=Q&&0!=d?"0x":"",d<0){d=-d,M=(F-1).toString(16);for(var Y=[],D=0;Dh++;)R[0]+="0";M=R[0]+(1>0]);else n=n.concat(intArrayFromString("(null)".substr(0,y),!0));if(I)for(;y>2]=n.length;break;case"%":n.push(E);break;default:for(D=C;D>0])}t+=2}else n.push(E),t+=1}return n}function _emscripten_log_js(A,e){24&A&&(e=e.replace(/\s+$/,""),e+=(0>2],g=(e+=4,"");if(t)for(var r=__formatString(t,e),B=0;B>2]=e,HEAPU32[A+4>>2]=e/4294967296|0},openDatabase:function(A,e,t,g){try{var r=indexedDB.open(A,e)}catch(A){return g(A)}r.onupgradeneeded=function(A){A=A.target.result;A.objectStoreNames.contains("FILES")&&A.deleteObjectStore("FILES"),A.createObjectStore("FILES")},r.onsuccess=function(A){t(A.target.result)},r.onerror=function(A){g(A)}},staticInit:function(){var e="undefined"==typeof ENVIRONMENT_IS_FETCH_WORKER;Fetch.openDatabase("emscripten_filesystem",1,function(A){Fetch.dbInstance=A,e&&removeRunDependency("library_fetch_init")},function(){Fetch.dbInstance=!1,e&&removeRunDependency("library_fetch_init")}),"undefined"!=typeof ENVIRONMENT_IS_FETCH_WORKER&&ENVIRONMENT_IS_FETCH_WORKER||addRunDependency("library_fetch_init")}};function __emscripten_fetch_xhr(r,B,n,g,e){var A=HEAPU32[r+8>>2];if(A){var A=UTF8ToString(A),t=r+112,E=(E=UTF8ToString(t))||"GET",C=(HEAPU32[t+32>>2],HEAPU32[t+52>>2]),o=HEAPU32[t+56>>2],I=!!HEAPU32[t+60>>2],Q=(HEAPU32[t+64>>2],HEAPU32[t+68>>2]),i=HEAPU32[t+72>>2],a=HEAPU32[t+76>>2],s=HEAPU32[t+80>>2],l=HEAPU32[t+84>>2],t=HEAPU32[t+88>>2],c=!!(1&C),w=!!(2&C),C=!!(64&C),Q=Q?UTF8ToString(Q):void 0,i=i?UTF8ToString(i):void 0,u=s?UTF8ToString(s):void 0,M=new XMLHttpRequest;if(M.withCredentials=I,M.open(E,A,!C,Q,i),C||(M.timeout=o),M.url_=A,assert(!w,"streaming uses moz-chunked-arraybuffer which is no longer supported; TODO: rewrite using fetch()"),M.responseType="arraybuffer",s&&M.overrideMimeType(u),a)for(;;){var d=HEAPU32[a>>2];if(!d)break;var F=HEAPU32[a+4>>2];if(!F)break;a+=8;d=UTF8ToString(d),F=UTF8ToString(F);M.setRequestHeader(d,F)}Fetch.xhrs.push(M);I=Fetch.xhrs.length,E=(HEAPU32[r+0>>2]=I,l&&t?HEAPU8.slice(l,l+t):null);M.onload=function(A){var e=M.response?M.response.byteLength:0,t=0,g=0;c&&!w&&(t=_malloc(g=e),HEAPU8.set(new Uint8Array(M.response),t)),HEAPU32[r+12>>2]=t,Fetch.setu64(r+16,g),Fetch.setu64(r+24,0),e&&Fetch.setu64(r+32,e),HEAPU16[r+40>>1]=M.readyState,4===M.readyState&&0===M.status&&(M.status=0>1]=M.status,M.statusText&&stringToUTF8(M.statusText,r+44,64),200<=M.status&&M.status<300?B&&B(r,M,A):n&&n(r,M,A)},M.onerror=function(A){var e=M.status;4===M.readyState&&0===e&&(e=404),HEAPU32[r+12>>2]=0,Fetch.setu64(r+16,0),Fetch.setu64(r+24,0),Fetch.setu64(r+32,0),HEAPU16[r+40>>1]=M.readyState,HEAPU16[r+42>>1]=e,n&&n(r,M,A)},M.ontimeout=function(A){n&&n(r,M,A)},M.onprogress=function(A){var e=c&&w&&M.response?M.response.byteLength:0,t=0;c&&w&&(t=_malloc(e),HEAPU8.set(new Uint8Array(M.response),t)),HEAPU32[r+12>>2]=t,Fetch.setu64(r+16,e),Fetch.setu64(r+24,A.loaded-e),Fetch.setu64(r+32,A.total),HEAPU16[r+40>>1]=M.readyState,3<=M.readyState&&0===M.status&&0>1]=M.status,M.statusText&&stringToUTF8(M.statusText,r+44,64),g&&g(r,M,A)},M.onreadystatechange=function(A){HEAPU16[r+40>>1]=M.readyState,2<=M.readyState&&(HEAPU16[r+42>>1]=M.status),e&&e(r,M,A)};try{M.send(E)}catch(A){n&&n(r,M,A)}}else n(r,0,"no url specified!")}function __emscripten_fetch_cache_data(A,e,t,g,r){if(A){var B=UTF8ToString(HEAPU32[e+112+64>>2]||HEAPU32[e+8>>2]);try{var n=A.transaction(["FILES"],"readwrite").objectStore("FILES").put(t,B);n.onsuccess=function(A){HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=200,stringToUTF8("OK",e+44,64),g(e,0,B)},n.onerror=function(A){HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=413,stringToUTF8("Payload Too Large",e+44,64),r(e,0,A)}}catch(A){r(e,0,A)}}else r(e,0,"IndexedDB not available!")}function __emscripten_fetch_load_cached_data(A,g,r,B){if(A){var e=UTF8ToString(HEAPU32[g+112+64>>2]||HEAPU32[g+8>>2]);try{var t=A.transaction(["FILES"],"readonly").objectStore("FILES").get(e);t.onsuccess=function(A){var e,t;A.target.result?(e=(A=A.target.result).byteLength||A.length,t=_malloc(e),HEAPU8.set(new Uint8Array(A),t),HEAPU32[g+12>>2]=t,Fetch.setu64(g+16,e),Fetch.setu64(g+24,0),Fetch.setu64(g+32,e),HEAPU16[g+40>>1]=4,HEAPU16[g+42>>1]=200,stringToUTF8("OK",g+44,64),r(g,0,A)):(HEAPU16[g+40>>1]=4,HEAPU16[g+42>>1]=404,stringToUTF8("Not Found",g+44,64),B(g,0,"no data"))},t.onerror=function(A){HEAPU16[g+40>>1]=4,HEAPU16[g+42>>1]=404,stringToUTF8("Not Found",g+44,64),B(g,0,A)}}catch(A){B(g,0,A)}}else B(g,0,"IndexedDB not available!")}function __emscripten_fetch_delete_cached_data(A,e,t,g){if(A){var r=UTF8ToString(HEAPU32[e+112+64>>2]||HEAPU32[e+8>>2]);try{var B=A.transaction(["FILES"],"readwrite").objectStore("FILES").delete(r);B.onsuccess=function(A){A=A.target.result;HEAPU32[e+12>>2]=0,Fetch.setu64(e+16,0),Fetch.setu64(e+24,0),Fetch.setu64(e+32,0),HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=200,stringToUTF8("OK",e+44,64),t(e,0,A)},B.onerror=function(A){HEAPU16[e+40>>1]=4,HEAPU16[e+42>>1]=404,stringToUTF8("Not Found",e+44,64),g(e,0,A)}}catch(A){g(e,0,A)}}else g(e,0,"IndexedDB not available!")}function _emscripten_start_fetch(A,g,r,B,n){void 0!==Module&&(Module.noExitRuntime=!0);function E(A,e,t){i?dynCall_vi(i,A):g&&g(A)}function C(A,e,t){s?dynCall_vi(s,A):B&&B(A)}function o(A,e,t){a?dynCall_vi(a,A):r&&r(A)}function I(A,e,t){l?dynCall_vi(l,A):n&&n(A)}function Q(A,e,t){__emscripten_fetch_cache_data(Fetch.dbInstance,A,e.response,function(A,e,t){i?dynCall_vi(i,A):g&&g(A)},function(A,e,t){i?dynCall_vi(i,A):g&&g(A)})}var e=A+112,t=UTF8ToString(e),i=HEAPU32[e+36>>2],a=HEAPU32[e+40>>2],s=HEAPU32[e+44>>2],l=HEAPU32[e+48>>2],c=HEAPU32[e+52>>2],w=!!(4&c),u=!!(32&c),c=!!(16&c);if((!c||"EM_IDB_STORE"===t||"EM_IDB_DELETE"===t)&&!Fetch.dbInstance)return o(A),0;if("EM_IDB_STORE"===t){var M=HEAPU32[e+84>>2];__emscripten_fetch_cache_data(Fetch.dbInstance,A,HEAPU8.slice(M,M+HEAPU32[e+88>>2]),E,o)}else if("EM_IDB_DELETE"===t)__emscripten_fetch_delete_cached_data(Fetch.dbInstance,A,E,o);else if(c){if(u)return 0;__emscripten_fetch_xhr(A,w?Q:E,o,C,I)}else __emscripten_fetch_load_cached_data(Fetch.dbInstance,A,E,u?o:w?function(A,e,t){__emscripten_fetch_xhr(A,Q,o,C,I)}:function(A,e,t){__emscripten_fetch_xhr(A,E,o,C,I)});return A}function _gettimeofday(A){var e=Date.now();return HEAP32[A>>2]=e/1e3|0,HEAP32[A+4>>2]=e%1e3*1e3|0,0}function _llvm_trap(){abort("trap!")}function _emscripten_memcpy_big(A,e,t){HEAPU8.set(HEAPU8.subarray(e,e+t),A)}function abortOnCannotGrowMemory(A){abort("OOM")}function emscripten_realloc_buffer(A){A=alignUp(A,65536);var e=buffer.byteLength;try{return-1!==wasmMemory.grow((A-e)/65536)?(buffer=wasmMemory.buffer,1):void 0}catch(A){}}function _emscripten_resize_heap(A){var e=_emscripten_get_heap_size(),t=2147418112;if(t>2,t=(3&B)<<6|(n=E.indexOf(A.charAt(o++))),C+=String.fromCharCode(g<<2|r>>4),64!==B&&(C+=String.fromCharCode(e)),64!==n&&(C+=String.fromCharCode(t)),o>2]=allocateUTF8OnStack(thisProgram);for(var g=1;g>2)+g]=allocateUTF8OnStack(A[g-1]);HEAP32[(t>>2)+e]=0;var r,B=Module.emtStackSave();try{var n=Module._main(e,t);Module.noExitRuntime||exit(n,!0)}catch(A){A instanceof ExitStatus||("SimulateInfiniteLoop"==A?(Module.noExitRuntime=!0,Module.emtStackRestore(B)):((r=A)&&"object"==typeof A&&A.stack&&(r=[A,A.stack]),err("exception thrown: "+r),quit_(1,A)))}finally{calledMain=!0}}function run(A){function e(){calledRun||(calledRun=!0,Module.calledRun=!0,ABORT)||(initRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),shouldRunNow&&callMain(A),postRun())}A=A||arguments_,0 { + if (typeof CNTVModuleFactory !== 'function') { + console.error('ERROR: CNTVModuleFactory is not a function:', CNTVModuleFactory); + // Try to handle if it's wrapped in default export + if (CNTVModuleFactory && typeof CNTVModuleFactory.default === 'function') { + CNTVH5PlayerModule = CNTVModuleFactory.default(); + } else if (CNTVModuleFactory && typeof CNTVModuleFactory.CNTVModule === 'function') { + CNTVH5PlayerModule = CNTVModuleFactory.CNTVModule(); + } else { + throw new Error('CNTVModuleFactory is not a function'); + } + } else { + CNTVH5PlayerModule = CNTVModuleFactory(); + } + + await new Promise((resolve) => { + if (CNTVH5PlayerModule.calledRun) resolve(); + else CNTVH5PlayerModule.onRuntimeInitialized = resolve; + }); + })(); + await wasmInitPromise; +} + +// ==================== 从网络地址获取二进制数据 ==================== +async function getBinaryFromUrl(url) { + try { + const response = await axios.get(url, { + responseType: 'arraybuffer', + timeout: 60000, + headers: {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'} + }); + if (response.status !== 200) { + throw new Error(`Failed to fetch binary: ${response.status} ${response.statusText}`); + } + return new Uint8Array(response.data); + } catch (error) { + throw new Error(`Request failed: ${error.message}`); + } +} + +// ==================== NAL单元处理 ==================== +function findNALUnits(buffer) { + const nalUnits = []; + let i = 0; + while (i < buffer.length - 3) { + if (buffer[i] === 0x00 && buffer[i + 1] === 0x00) { + let nalStart = -1; + if (buffer[i + 2] === 0x01 && i + 3 < buffer.length) { + nalStart = i + 3; + } else if (buffer[i + 2] === 0x00 && buffer[i + 3] === 0x01 && i + 4 < buffer.length) { + nalStart = i + 4; + } + if (nalStart >= 0) { + let nextStart = buffer.length; + for (let j = nalStart; j < buffer.length - 2; j++) { + if (buffer[j] === 0x00 && buffer[j + 1] === 0x00) { + if (buffer[j + 2] === 0x01 || (buffer[j + 2] === 0x00 && j + 3 < buffer.length && buffer[j + 3] === 0x01)) { + nextStart = j; + break; + } + } + } + const nalData = buffer.subarray(i, nextStart); + if (nalData.length >= 2) { + const header = nalData[nalStart - i]; + const data = nalData.subarray(nalStart - i + 1); + const nal = {header, data, nalUnitType: header & 0x1F}; + nalUnits.push(nal); + } + i = nextStart; + continue; + } + } + i++; + } + return nalUnits; +} + +// ==================== H.264解密核心 ==================== +// 解密H.264数据,保持原始数据结构不变,直接在原buffer上修改 +// 优化内存使用:避免创建不必要的buffer副本和对象 +async function decryptH264InPlace(h264Data) { + let curDate = Date.now().toString(); + const MemoryExtend = 2048; + let vmpTag = ''; + + // 预分配临时解密buffer(复用) + const maxDecryptBufSize = 1024 * 1024; // 1MB上限,足够处理单个NAL + const tempDecryptBuf = Buffer.allocUnsafe(maxDecryptBufSize); + + function _common(o) { + const memory = CNTVH5PlayerModule._jsmalloc(curDate.length + MemoryExtend); + CNTVH5PlayerModule.HEAP8.fill(0, memory, memory + curDate.length + MemoryExtend); + CNTVH5PlayerModule.HEAP8.set(Array.from(curDate, e => e.charCodeAt(0)), memory); + let ret; + switch (o) { + case "InitPlayer": + ret = CNTVH5PlayerModule._CNTV_InitPlayer(memory); + break; + case "UnInitPlayer": + ret = CNTVH5PlayerModule._CNTV_UnInitPlayer(memory); + break; + case "UpdatePlayer": + vmpTag = CNTVH5PlayerModule._CNTV_UpdatePlayer(memory).toString(16); + vmpTag = ['0'.repeat(8 - vmpTag.length), vmpTag].join(''); + ret = 0; + break; + } + CNTVH5PlayerModule._jsfree(memory); + return ret; + } + + function InitPlayer() { + return _common("InitPlayer"); + } + + function UnInitPlayer() { + return _common("UnInitPlayer"); + } + + function UpdatePlayer() { + return _common("UpdatePlayer"); + } + + // 解密到预分配的buffer,返回实际解密长度 + function decryptToBuf(srcBuf, destBuf) { + const pageHost = "https://tv.cctv.com"; + const addr = CNTVH5PlayerModule._jsmalloc(srcBuf.length + MemoryExtend); + const StaticCallModuleVod = { + H264NalSet: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD7(t, i, n, r); + }, + H265NalData: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD6(t, i, n, r); + }, + AVS1AudioKey: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD5(t, i, n, r); + }, + HEVC2AAC: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD4(t, i, n, r); + }, + HASHMap: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD3(t, i, n, r); + }, + BASE64Dec: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD2(t, i, n, r); + }, + MediaSession: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD1(t, i, n, r); + }, + Mp4fragment: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD0(t, i, n, r); + }, + MpegAudio: function (e, t, i, n, r) { + return e._CNTV_jsdecVOD8(t, i, n, r); + }, + AACDemuxer: function (e, t, i, n, r) { + return e._jsdecVOD(i, n, r); + } + }; + + function StaticCallModuleVodAPI(e, t, i, n, r, a) { + return StaticCallModuleVod[a](e, t, i, n, r); + } + + CNTVH5PlayerModule.HEAP8.set(srcBuf, addr); + CNTVH5PlayerModule.HEAP8.set(Array.from(pageHost, e => e.charCodeAt(0)), addr + srcBuf.length); + const addr2 = CNTVH5PlayerModule._jsmalloc(curDate.length); + CNTVH5PlayerModule.HEAP8.set(Array.from(curDate, e => e.charCodeAt(0)), addr2); + + for (const i in vmpTag) + if ("0123456".includes(vmpTag[i])) + StaticCallModuleVodAPI(CNTVH5PlayerModule, addr2, addr, srcBuf.length, pageHost.length, Object.keys(StaticCallModuleVod)[i]); + + const decRet = StaticCallModuleVodAPI(CNTVH5PlayerModule, addr2, addr, srcBuf.length, pageHost.length, Object.keys(StaticCallModuleVod)[8]); + + // 复制到预分配的buffer (HEAP8是Uint8Array,使用set方法) + const copyLen = Math.min(decRet, destBuf.length); + destBuf.set(CNTVH5PlayerModule.HEAP8.subarray(addr, addr + copyLen)); + + CNTVH5PlayerModule._jsfree(addr); + CNTVH5PlayerModule._jsfree(addr2); + return decRet; + } + + // 找到所有NAL单元的位置信息(只存储必要的位置信息,不存储数据引用) + const nalUnits = []; // { dataPos, dataEnd, header, nalUnitType } + let i = 0; + while (i < h264Data.length - 3) { + if (h264Data[i] === 0x00 && h264Data[i + 1] === 0x00) { + let startCodeLen = 0; + let nalStart = -1; + + // 查找起始码 + if (h264Data[i + 2] === 0x01 && i + 3 < h264Data.length) { + startCodeLen = 3; + nalStart = i + 3; + } else if (h264Data[i + 2] === 0x00 && h264Data[i + 3] === 0x01 && i + 4 < h264Data.length) { + startCodeLen = 4; + nalStart = i + 4; + } + + if (nalStart >= 0) { + // 找到下一个起始码位置 + let nextStart = h264Data.length; + for (let j = nalStart; j < h264Data.length - 2; j++) { + if (h264Data[j] === 0x00 && h264Data[j + 1] === 0x00) { + if (h264Data[j + 2] === 0x01 || (h264Data[j + 2] === 0x00 && j + 3 < h264Data.length && h264Data[j + 3] === 0x01)) { + nextStart = j; + break; + } + } + } + + const header = h264Data[nalStart]; + const dataStart = nalStart + 1; + const dataEnd = nextStart; + const nalUnitType = header & 0x1F; + + // 只存储位置信息,不存储subarray引用 + nalUnits.push({ + dataPos: dataStart, + dataEnd: dataEnd, + header: header, + dataLen: dataEnd - dataStart, + nalUnitType: nalUnitType + }); + + i = nextStart; + continue; + } + } + i++; + } + + // 解密并替换原始buffer中的数据(原地修改) + let shouldDecrypt = false; + curDate = Date.now().toString(); + InitPlayer(); + + for (const nal of nalUnits) { + UpdatePlayer(); + + // 将数据复制到预分配的buffer进行解密 + const nalLen = nal.dataLen + 1; // +1 for header + if (nalLen > maxDecryptBufSize) continue; // 跳过过大的NAL + + // 复制header + data到临时buffer + tempDecryptBuf[0] = nal.header; + h264Data.copy(tempDecryptBuf, 1, nal.dataPos, nal.dataEnd); + + if (nal.nalUnitType === 25) { + shouldDecrypt = h264Data[nal.dataPos] === 1; + if (shouldDecrypt) { + decryptToBuf(tempDecryptBuf.subarray(0, nalLen), tempDecryptBuf); + } + } else if ((nal.nalUnitType === 1 || nal.nalUnitType === 5) && shouldDecrypt) { + const decLen = decryptToBuf(tempDecryptBuf.subarray(0, nalLen), tempDecryptBuf); + // 解密结果从索引1开始(跳过header) + const decryptedDataLen = decLen - 1; + const writePos = nal.dataPos; + + // 原地替换 + if (decryptedDataLen <= nal.dataLen) { + // 解密数据更小或相等 + if (decryptedDataLen > 0) { + tempDecryptBuf.copy(h264Data, writePos, 1, 1 + decryptedDataLen); + } + if (decryptedDataLen < nal.dataLen) { + h264Data.fill(0, writePos + decryptedDataLen, nal.dataEnd); + } + } else { + // 解密数据更大,截断 + tempDecryptBuf.copy(h264Data, writePos, 1, 1 + nal.dataLen); + } + } + } + UnInitPlayer(); + + return h264Data; +} + +// ==================== TS解密处理函数 ==================== +async function Parse_TS(buffer) { + // 确保WASM模块已初始化 + await initWasmModule(); + + const originalTS = Buffer.from(buffer); + + // 第一遍扫描:计算视频数据总量并收集PES包信息 + const videoPESRanges = []; // 只存储位置和长度信息,不存储数据引用 + let totalH264Size = 0; + let currentPESDataSize = 0; + let inPES = false; + + for (let i = 0; i < originalTS.length; i += TS_PACKET_SIZE) { + if (i + TS_PACKET_SIZE > originalTS.length) break; + const packet = originalTS.subarray(i, i + TS_PACKET_SIZE); + if (packet[0] !== 0x47) continue; + + const pid = ((packet[1] & 0x1F) << 8) | packet[2]; + if (pid !== VIDEO_PID) continue; + + const payloadStart = (packet[1] & 0x40) !== 0; + const adaptation = (packet[3] & 0x20) !== 0; + const payload = (packet[3] & 0x10) !== 0; + + let offset = 4; + if (adaptation && offset < 188) { + const adaptationLen = packet[offset]; + offset += adaptationLen + 1; + } + + if (payload && offset < 188) { + const dataSize = 188 - offset; + + if (payloadStart) { + // 保存上一个PES包的范围信息 + if (inPES && currentPESDataSize > 0) { + videoPESRanges.push({ size: currentPESDataSize }); + totalH264Size += currentPESDataSize; + } + + // 开始新的PES包 - 只计算数据大小 + let pesHeaderEnd = 9; + const data = packet.subarray(offset); + if (data.length >= 9) { + pesHeaderEnd = 9 + data[8]; + } + pesHeaderEnd = Math.min(pesHeaderEnd, data.length); + + const pesPayloadSize = dataSize - pesHeaderEnd; + currentPESDataSize = pesPayloadSize; + inPES = true; + } else if (inPES) { + currentPESDataSize += dataSize; + } + } + } + + // 保存最后一个PES包 + if (inPES && currentPESDataSize > 0) { + videoPESRanges.push({ size: currentPESDataSize }); + totalH264Size += currentPESDataSize; + } + + // 如果没有视频数据,直接返回原始TS + if (totalH264Size === 0) { + return originalTS; + } + + // 第二遍扫描:一次性提取所有H.264数据到预分配的buffer + const h264Data = Buffer.allocUnsafe(totalH264Size); + let h264WritePos = 0; + inPES = false; + + for (let i = 0; i < originalTS.length; i += TS_PACKET_SIZE) { + if (i + TS_PACKET_SIZE > originalTS.length) break; + const packet = originalTS.subarray(i, i + TS_PACKET_SIZE); + if (packet[0] !== 0x47) continue; + + const pid = ((packet[1] & 0x1F) << 8) | packet[2]; + if (pid !== VIDEO_PID) continue; + + const payloadStart = (packet[1] & 0x40) !== 0; + const adaptation = (packet[3] & 0x20) !== 0; + const payload = (packet[3] & 0x10) !== 0; + + let offset = 4; + if (adaptation && offset < 188) { + const adaptationLen = packet[offset]; + offset += adaptationLen + 1; + } + + if (payload && offset < 188) { + if (payloadStart) { + let pesHeaderEnd = 9; + const data = packet.subarray(offset); + if (data.length >= 9) { + pesHeaderEnd = 9 + data[8]; + } + pesHeaderEnd = Math.min(pesHeaderEnd, data.length); + + const pesPayload = packet.subarray(offset + pesHeaderEnd); + pesPayload.copy(h264Data, h264WritePos); + h264WritePos += pesPayload.length; + inPES = true; + } else if (inPES) { + const data = packet.subarray(offset); + data.copy(h264Data, h264WritePos); + h264WritePos += data.length; + } + } + } + + // 解密H.264数据(原地修改) + const decryptedH264 = await decryptH264InPlace(h264Data); + + // 第三遍扫描:将解密数据写回,原地修改originalTS + let h264ReadPos = 0; + + for (let i = 0; i < originalTS.length; i += TS_PACKET_SIZE) { + if (i + TS_PACKET_SIZE > originalTS.length) break; + + const pid = ((originalTS[i + 1] & 0x1F) << 8) | originalTS[i + 2]; + if (pid !== VIDEO_PID) continue; + + const payloadStart = (originalTS[i + 1] & 0x40) !== 0; + const adaptation = (originalTS[i + 3] & 0x20) !== 0; + const payload = (originalTS[i + 3] & 0x10) !== 0; + + let offset = 4; + if (adaptation && offset < 188) { + const adaptationLen = originalTS[i + offset]; + offset += adaptationLen + 1; + } + + if (payload && offset < 188) { + if (payloadStart) { + let pesHeaderEnd = 9; + if (offset + 9 <= 188) { + pesHeaderEnd = 9 + originalTS[i + offset + 8]; + } + pesHeaderEnd = Math.min(pesHeaderEnd, 188 - offset); + + // 跳过PES头,直接写入解密后的H.264数据 + const writeOffset = i + offset + pesHeaderEnd; + const remaining = 188 - offset - pesHeaderEnd; + const toCopy = Math.min(remaining, decryptedH264.length - h264ReadPos); + + if (toCopy > 0) { + decryptedH264.copy(originalTS, writeOffset, h264ReadPos, h264ReadPos + toCopy); + h264ReadPos += toCopy; + } + + // 填充剩余空间 + if (toCopy < remaining) { + originalTS.fill(0xFF, writeOffset + toCopy, i + 188); + } + } else { + const writeOffset = i + offset; + const remaining = 188 - offset; + const toCopy = Math.min(remaining, decryptedH264.length - h264ReadPos); + + if (toCopy > 0) { + decryptedH264.copy(originalTS, writeOffset, h264ReadPos, h264ReadPos + toCopy); + h264ReadPos += toCopy; + } + + if (toCopy < remaining) { + originalTS.fill(0xFF, writeOffset + toCopy, i + 188); + } + } + } + } + + return originalTS; +} + +// ==================== 主处理函数 ==================== +async function processFile(url, extension) { + // 下载原始TS文件 + let buffer = await getBinaryFromUrl(url); + + // 如果是.ts文件,调用Parse_TS进行解密 + if (extension === '.ts') { + buffer = await Parse_TS(buffer); + } + + return buffer; +} + +module.exports = { + processFile, +} diff --git a/spider/js/_lib.tingyou.js b/spider/js/_lib.tingyou.js new file mode 100644 index 00000000..410345d6 --- /dev/null +++ b/spider/js/_lib.tingyou.js @@ -0,0 +1,922 @@ +function Co(e) { + for (let t = 0; t < e.length; t++) + e[t] = 0; + return e +} + +function _o(e, t=new Uint8Array(4), n=0) { + return t[n + 0] = e >>> 0, + t[n + 1] = e >>> 8, + t[n + 2] = e >>> 16, + t[n + 3] = e >>> 24, + t +} + +function Do(e, t, n) { + let a = 1634760805 + , o = 857760878 + , r = 2036477234 + , s = 1797285236 + , i = e[3] << 24 | e[2] << 16 | e[1] << 8 | e[0] + , l = e[7] << 24 | e[6] << 16 | e[5] << 8 | e[4] + , c = e[11] << 24 | e[10] << 16 | e[9] << 8 | e[8] + , u = e[15] << 24 | e[14] << 16 | e[13] << 8 | e[12] + , d = e[19] << 24 | e[18] << 16 | e[17] << 8 | e[16] + , f = e[23] << 24 | e[22] << 16 | e[21] << 8 | e[20] + , v = e[27] << 24 | e[26] << 16 | e[25] << 8 | e[24] + , p = e[31] << 24 | e[30] << 16 | e[29] << 8 | e[28] + , h = t[3] << 24 | t[2] << 16 | t[1] << 8 | t[0] + , m = t[7] << 24 | t[6] << 16 | t[5] << 8 | t[4] + , y = t[11] << 24 | t[10] << 16 | t[9] << 8 | t[8] + , g = t[15] << 24 | t[14] << 16 | t[13] << 8 | t[12]; + for (let k = 0; k < 20; k += 2) + a = a + i | 0, + h ^= a, + h = h >>> 16 | h << 16, + d = d + h | 0, + i ^= d, + i = i >>> 20 | i << 12, + o = o + l | 0, + m ^= o, + m = m >>> 16 | m << 16, + f = f + m | 0, + l ^= f, + l = l >>> 20 | l << 12, + r = r + c | 0, + y ^= r, + y = y >>> 16 | y << 16, + v = v + y | 0, + c ^= v, + c = c >>> 20 | c << 12, + s = s + u | 0, + g ^= s, + g = g >>> 16 | g << 16, + p = p + g | 0, + u ^= p, + u = u >>> 20 | u << 12, + r = r + c | 0, + y ^= r, + y = y >>> 24 | y << 8, + v = v + y | 0, + c ^= v, + c = c >>> 25 | c << 7, + s = s + u | 0, + g ^= s, + g = g >>> 24 | g << 8, + p = p + g | 0, + u ^= p, + u = u >>> 25 | u << 7, + o = o + l | 0, + m ^= o, + m = m >>> 24 | m << 8, + f = f + m | 0, + l ^= f, + l = l >>> 25 | l << 7, + a = a + i | 0, + h ^= a, + h = h >>> 24 | h << 8, + d = d + h | 0, + i ^= d, + i = i >>> 25 | i << 7, + a = a + l | 0, + g ^= a, + g = g >>> 16 | g << 16, + v = v + g | 0, + l ^= v, + l = l >>> 20 | l << 12, + o = o + c | 0, + h ^= o, + h = h >>> 16 | h << 16, + p = p + h | 0, + c ^= p, + c = c >>> 20 | c << 12, + r = r + u | 0, + m ^= r, + m = m >>> 16 | m << 16, + d = d + m | 0, + u ^= d, + u = u >>> 20 | u << 12, + s = s + i | 0, + y ^= s, + y = y >>> 16 | y << 16, + f = f + y | 0, + i ^= f, + i = i >>> 20 | i << 12, + r = r + u | 0, + m ^= r, + m = m >>> 24 | m << 8, + d = d + m | 0, + u ^= d, + u = u >>> 25 | u << 7, + s = s + i | 0, + y ^= s, + y = y >>> 24 | y << 8, + f = f + y | 0, + i ^= f, + i = i >>> 25 | i << 7, + o = o + c | 0, + h ^= o, + h = h >>> 24 | h << 8, + p = p + h | 0, + c ^= p, + c = c >>> 25 | c << 7, + a = a + l | 0, + g ^= a, + g = g >>> 24 | g << 8, + v = v + g | 0, + l ^= v, + l = l >>> 25 | l << 7; + return _o(a, n, 0), + _o(o, n, 4), + _o(r, n, 8), + _o(s, n, 12), + _o(h, n, 16), + _o(m, n, 20), + _o(y, n, 24), + _o(g, n, 28), + n +} + +class Po { + nonceLength = 24; + tagLength = 16; + _key; + constructor(e) { + if (32 !== e.length) + throw new Error("ChaCha20Poly1305 needs 32-byte key"); + this._key = new Uint8Array(e) + } + seal(e, t, n, a) { + if (24 !== e.length) + throw new Error("XChaCha20Poly1305: incorrect nonce length"); + const o = Do(this._key, e.subarray(0, 16), new Uint8Array(32)) + , r = new Uint8Array(12); + r.set(e.subarray(16), 4); + const s = new jo(o) + , i = s.seal(r, t, n, a); + return Co(o), + Co(r), + s.clean(), + i + } + open(e, t, n, a) { + if (24 !== e.length) + throw new Error("XChaCha20Poly1305: incorrect nonce length"); + if (t.length < this.tagLength) + return null; + const o = Do(this._key, e.subarray(0, 16), new Uint8Array(32)) + , r = new Uint8Array(12); + r.set(e.subarray(16), 4); + const s = new jo(o) + , i = s.open(r, t, n, a); + return Co(o), + Co(r), + s.clean(), + i + } + clean() { + return Co(this._key), + this + } +} + +function So(e, t, n, a, o=0) { + if (32 !== e.length) + throw new Error("ChaCha: key size must be 32 bytes"); + if (a.length < n.length) + throw new Error("ChaCha: destination is shorter than source"); + let r, s; + if (0 === o) { + if (8 !== t.length && 12 !== t.length) + throw new Error("ChaCha nonce must be 8 or 12 bytes"); + r = new Uint8Array(16), + s = r.length - t.length, + r.set(t, s) + } else { + if (16 !== t.length) + throw new Error("ChaCha nonce with counter must be 16 bytes"); + r = t, + s = o + } + const i = new Uint8Array(64); + for (let l = 0; l < n.length; l += 64) { + Lo(i, r, e); + for (let e = l; e < l + 64 && e < n.length; e++) + a[e] = n[e] ^ i[e - l]; + Ao(r, 0, s) + } + return Co(i), + 0 === o && Co(r), + a +} + +function Ao(e, t, n) { + let a = 1; + for (; n--; ) + a = a + (255 & e[t]) | 0, + e[t] = 255 & a, + a >>>= 8, + t++; + if (a > 0) + throw new Error("ChaCha: counter overflow") +} + +function Lo(e, t, n) { + let a = 1634760805 + , o = 857760878 + , r = 2036477234 + , s = 1797285236 + , i = n[3] << 24 | n[2] << 16 | n[1] << 8 | n[0] + , l = n[7] << 24 | n[6] << 16 | n[5] << 8 | n[4] + , c = n[11] << 24 | n[10] << 16 | n[9] << 8 | n[8] + , u = n[15] << 24 | n[14] << 16 | n[13] << 8 | n[12] + , d = n[19] << 24 | n[18] << 16 | n[17] << 8 | n[16] + , f = n[23] << 24 | n[22] << 16 | n[21] << 8 | n[20] + , v = n[27] << 24 | n[26] << 16 | n[25] << 8 | n[24] + , p = n[31] << 24 | n[30] << 16 | n[29] << 8 | n[28] + , h = t[3] << 24 | t[2] << 16 | t[1] << 8 | t[0] + , m = t[7] << 24 | t[6] << 16 | t[5] << 8 | t[4] + , y = t[11] << 24 | t[10] << 16 | t[9] << 8 | t[8] + , g = t[15] << 24 | t[14] << 16 | t[13] << 8 | t[12] + , k = a + , b = o + , w = r + , _ = s + , x = i + , C = l + , L = c + , S = u + , M = d + , A = f + , D = v + , E = p + , I = h + , j = m + , P = y + , T = g; + for (let R = 0; R < 20; R += 2) + k = k + x | 0, + I ^= k, + I = I >>> 16 | I << 16, + M = M + I | 0, + x ^= M, + x = x >>> 20 | x << 12, + b = b + C | 0, + j ^= b, + j = j >>> 16 | j << 16, + A = A + j | 0, + C ^= A, + C = C >>> 20 | C << 12, + w = w + L | 0, + P ^= w, + P = P >>> 16 | P << 16, + D = D + P | 0, + L ^= D, + L = L >>> 20 | L << 12, + _ = _ + S | 0, + T ^= _, + T = T >>> 16 | T << 16, + E = E + T | 0, + S ^= E, + S = S >>> 20 | S << 12, + w = w + L | 0, + P ^= w, + P = P >>> 24 | P << 8, + D = D + P | 0, + L ^= D, + L = L >>> 25 | L << 7, + _ = _ + S | 0, + T ^= _, + T = T >>> 24 | T << 8, + E = E + T | 0, + S ^= E, + S = S >>> 25 | S << 7, + b = b + C | 0, + j ^= b, + j = j >>> 24 | j << 8, + A = A + j | 0, + C ^= A, + C = C >>> 25 | C << 7, + k = k + x | 0, + I ^= k, + I = I >>> 24 | I << 8, + M = M + I | 0, + x ^= M, + x = x >>> 25 | x << 7, + k = k + C | 0, + T ^= k, + T = T >>> 16 | T << 16, + D = D + T | 0, + C ^= D, + C = C >>> 20 | C << 12, + b = b + L | 0, + I ^= b, + I = I >>> 16 | I << 16, + E = E + I | 0, + L ^= E, + L = L >>> 20 | L << 12, + w = w + S | 0, + j ^= w, + j = j >>> 16 | j << 16, + M = M + j | 0, + S ^= M, + S = S >>> 20 | S << 12, + _ = _ + x | 0, + P ^= _, + P = P >>> 16 | P << 16, + A = A + P | 0, + x ^= A, + x = x >>> 20 | x << 12, + w = w + S | 0, + j ^= w, + j = j >>> 24 | j << 8, + M = M + j | 0, + S ^= M, + S = S >>> 25 | S << 7, + _ = _ + x | 0, + P ^= _, + P = P >>> 24 | P << 8, + A = A + P | 0, + x ^= A, + x = x >>> 25 | x << 7, + b = b + L | 0, + I ^= b, + I = I >>> 24 | I << 8, + E = E + I | 0, + L ^= E, + L = L >>> 25 | L << 7, + k = k + C | 0, + T ^= k, + T = T >>> 24 | T << 8, + D = D + T | 0, + C ^= D, + C = C >>> 25 | C << 7; + _o(k + a | 0, e, 0), + _o(b + o | 0, e, 4), + _o(w + r | 0, e, 8), + _o(_ + s | 0, e, 12), + _o(x + i | 0, e, 16), + _o(C + l | 0, e, 20), + _o(L + c | 0, e, 24), + _o(S + u | 0, e, 28), + _o(M + d | 0, e, 32), + _o(A + f | 0, e, 36), + _o(D + v | 0, e, 40), + _o(E + p | 0, e, 44), + _o(I + h | 0, e, 48), + _o(j + m | 0, e, 52), + _o(P + y | 0, e, 56), + _o(T + g | 0, e, 60) +} + +class Eo { + digestLength = 16; + _buffer = new Uint8Array(16); + _r = new Uint16Array(10); + _h = new Uint16Array(10); + _pad = new Uint16Array(8); + _leftover = 0; + _fin = 0; + _finished = !1; + constructor(e) { + let t = e[0] | e[1] << 8; + this._r[0] = 8191 & t; + let n = e[2] | e[3] << 8; + this._r[1] = 8191 & (t >>> 13 | n << 3); + let a = e[4] | e[5] << 8; + this._r[2] = 7939 & (n >>> 10 | a << 6); + let o = e[6] | e[7] << 8; + this._r[3] = 8191 & (a >>> 7 | o << 9); + let r = e[8] | e[9] << 8; + this._r[4] = 255 & (o >>> 4 | r << 12), + this._r[5] = r >>> 1 & 8190; + let s = e[10] | e[11] << 8; + this._r[6] = 8191 & (r >>> 14 | s << 2); + let i = e[12] | e[13] << 8; + this._r[7] = 8065 & (s >>> 11 | i << 5); + let l = e[14] | e[15] << 8; + this._r[8] = 8191 & (i >>> 8 | l << 8), + this._r[9] = l >>> 5 & 127, + this._pad[0] = e[16] | e[17] << 8, + this._pad[1] = e[18] | e[19] << 8, + this._pad[2] = e[20] | e[21] << 8, + this._pad[3] = e[22] | e[23] << 8, + this._pad[4] = e[24] | e[25] << 8, + this._pad[5] = e[26] | e[27] << 8, + this._pad[6] = e[28] | e[29] << 8, + this._pad[7] = e[30] | e[31] << 8 + } + _blocks(e, t, n) { + let a = this._fin ? 0 : 2048 + , o = this._h[0] + , r = this._h[1] + , s = this._h[2] + , i = this._h[3] + , l = this._h[4] + , c = this._h[5] + , u = this._h[6] + , d = this._h[7] + , f = this._h[8] + , v = this._h[9] + , p = this._r[0] + , h = this._r[1] + , m = this._r[2] + , y = this._r[3] + , g = this._r[4] + , k = this._r[5] + , b = this._r[6] + , w = this._r[7] + , _ = this._r[8] + , x = this._r[9]; + for (; n >= 16; ) { + let C = e[t + 0] | e[t + 1] << 8; + o += 8191 & C; + let L = e[t + 2] | e[t + 3] << 8; + r += 8191 & (C >>> 13 | L << 3); + let S = e[t + 4] | e[t + 5] << 8; + s += 8191 & (L >>> 10 | S << 6); + let M = e[t + 6] | e[t + 7] << 8; + i += 8191 & (S >>> 7 | M << 9); + let A = e[t + 8] | e[t + 9] << 8; + l += 8191 & (M >>> 4 | A << 12), + c += A >>> 1 & 8191; + let D = e[t + 10] | e[t + 11] << 8; + u += 8191 & (A >>> 14 | D << 2); + let E = e[t + 12] | e[t + 13] << 8; + d += 8191 & (D >>> 11 | E << 5); + let I = e[t + 14] | e[t + 15] << 8; + f += 8191 & (E >>> 8 | I << 8), + v += I >>> 5 | a; + let j = 0 + , P = j; + P += o * p, + P += r * (5 * x), + P += s * (5 * _), + P += i * (5 * w), + P += l * (5 * b), + j = P >>> 13, + P &= 8191, + P += c * (5 * k), + P += u * (5 * g), + P += d * (5 * y), + P += f * (5 * m), + P += v * (5 * h), + j += P >>> 13, + P &= 8191; + let T = j; + T += o * h, + T += r * p, + T += s * (5 * x), + T += i * (5 * _), + T += l * (5 * w), + j = T >>> 13, + T &= 8191, + T += c * (5 * b), + T += u * (5 * k), + T += d * (5 * g), + T += f * (5 * y), + T += v * (5 * m), + j += T >>> 13, + T &= 8191; + let R = j; + R += o * m, + R += r * h, + R += s * p, + R += i * (5 * x), + R += l * (5 * _), + j = R >>> 13, + R &= 8191, + R += c * (5 * w), + R += u * (5 * b), + R += d * (5 * k), + R += f * (5 * g), + R += v * (5 * y), + j += R >>> 13, + R &= 8191; + let B = j; + B += o * y, + B += r * m, + B += s * h, + B += i * p, + B += l * (5 * x), + j = B >>> 13, + B &= 8191, + B += c * (5 * _), + B += u * (5 * w), + B += d * (5 * b), + B += f * (5 * k), + B += v * (5 * g), + j += B >>> 13, + B &= 8191; + let O = j; + O += o * g, + O += r * y, + O += s * m, + O += i * h, + O += l * p, + j = O >>> 13, + O &= 8191, + O += c * (5 * x), + O += u * (5 * _), + O += d * (5 * w), + O += f * (5 * b), + O += v * (5 * k), + j += O >>> 13, + O &= 8191; + let U = j; + U += o * k, + U += r * g, + U += s * y, + U += i * m, + U += l * h, + j = U >>> 13, + U &= 8191, + U += c * p, + U += u * (5 * x), + U += d * (5 * _), + U += f * (5 * w), + U += v * (5 * b), + j += U >>> 13, + U &= 8191; + let W = j; + W += o * b, + W += r * k, + W += s * g, + W += i * y, + W += l * m, + j = W >>> 13, + W &= 8191, + W += c * h, + W += u * p, + W += d * (5 * x), + W += f * (5 * _), + W += v * (5 * w), + j += W >>> 13, + W &= 8191; + let H = j; + H += o * w, + H += r * b, + H += s * k, + H += i * g, + H += l * y, + j = H >>> 13, + H &= 8191, + H += c * m, + H += u * h, + H += d * p, + H += f * (5 * x), + H += v * (5 * _), + j += H >>> 13, + H &= 8191; + let N = j; + N += o * _, + N += r * w, + N += s * b, + N += i * k, + N += l * g, + j = N >>> 13, + N &= 8191, + N += c * y, + N += u * m, + N += d * h, + N += f * p, + N += v * (5 * x), + j += N >>> 13, + N &= 8191; + let V = j; + V += o * x, + V += r * _, + V += s * w, + V += i * b, + V += l * k, + j = V >>> 13, + V &= 8191, + V += c * g, + V += u * y, + V += d * m, + V += f * h, + V += v * p, + j += V >>> 13, + V &= 8191, + j = (j << 2) + j | 0, + j = j + P | 0, + P = 8191 & j, + j >>>= 13, + T += j, + o = P, + r = T, + s = R, + i = B, + l = O, + c = U, + u = W, + d = H, + f = N, + v = V, + t += 16, + n -= 16 + } + this._h[0] = o, + this._h[1] = r, + this._h[2] = s, + this._h[3] = i, + this._h[4] = l, + this._h[5] = c, + this._h[6] = u, + this._h[7] = d, + this._h[8] = f, + this._h[9] = v + } + finish(e, t=0) { + const n = new Uint16Array(10); + let a, o, r, s; + if (this._leftover) { + for (s = this._leftover, + this._buffer[s++] = 1; s < 16; s++) + this._buffer[s] = 0; + this._fin = 1, + this._blocks(this._buffer, 0, 16) + } + for (a = this._h[1] >>> 13, + this._h[1] &= 8191, + s = 2; s < 10; s++) + this._h[s] += a, + a = this._h[s] >>> 13, + this._h[s] &= 8191; + for (this._h[0] += 5 * a, + a = this._h[0] >>> 13, + this._h[0] &= 8191, + this._h[1] += a, + a = this._h[1] >>> 13, + this._h[1] &= 8191, + this._h[2] += a, + n[0] = this._h[0] + 5, + a = n[0] >>> 13, + n[0] &= 8191, + s = 1; s < 10; s++) + n[s] = this._h[s] + a, + a = n[s] >>> 13, + n[s] &= 8191; + for (n[9] -= 8192, + o = (1 ^ a) - 1, + s = 0; s < 10; s++) + n[s] &= o; + for (o = ~o, + s = 0; s < 10; s++) + this._h[s] = this._h[s] & o | n[s]; + for (this._h[0] = 65535 & (this._h[0] | this._h[1] << 13), + this._h[1] = 65535 & (this._h[1] >>> 3 | this._h[2] << 10), + this._h[2] = 65535 & (this._h[2] >>> 6 | this._h[3] << 7), + this._h[3] = 65535 & (this._h[3] >>> 9 | this._h[4] << 4), + this._h[4] = 65535 & (this._h[4] >>> 12 | this._h[5] << 1 | this._h[6] << 14), + this._h[5] = 65535 & (this._h[6] >>> 2 | this._h[7] << 11), + this._h[6] = 65535 & (this._h[7] >>> 5 | this._h[8] << 8), + this._h[7] = 65535 & (this._h[8] >>> 8 | this._h[9] << 5), + r = this._h[0] + this._pad[0], + this._h[0] = 65535 & r, + s = 1; s < 8; s++) + r = (this._h[s] + this._pad[s] | 0) + (r >>> 16) | 0, + this._h[s] = 65535 & r; + return e[t + 0] = this._h[0] >>> 0, + e[t + 1] = this._h[0] >>> 8, + e[t + 2] = this._h[1] >>> 0, + e[t + 3] = this._h[1] >>> 8, + e[t + 4] = this._h[2] >>> 0, + e[t + 5] = this._h[2] >>> 8, + e[t + 6] = this._h[3] >>> 0, + e[t + 7] = this._h[3] >>> 8, + e[t + 8] = this._h[4] >>> 0, + e[t + 9] = this._h[4] >>> 8, + e[t + 10] = this._h[5] >>> 0, + e[t + 11] = this._h[5] >>> 8, + e[t + 12] = this._h[6] >>> 0, + e[t + 13] = this._h[6] >>> 8, + e[t + 14] = this._h[7] >>> 0, + e[t + 15] = this._h[7] >>> 8, + this._finished = !0, + this + } + update(e) { + let t, n = 0, a = e.length; + if (this._leftover) { + t = 16 - this._leftover, + t > a && (t = a); + for (let a = 0; a < t; a++) + this._buffer[this._leftover + a] = e[n + a]; + if (a -= t, + n += t, + this._leftover += t, + this._leftover < 16) + return this; + this._blocks(this._buffer, 0, 16), + this._leftover = 0 + } + if (a >= 16 && (t = a - a % 16, + this._blocks(e, n, t), + n += t, + a -= t), + a) { + for (let t = 0; t < a; t++) + this._buffer[this._leftover + t] = e[n + t]; + this._leftover += a + } + return this + } + digest() { + if (this._finished) + throw new Error("Poly1305 was finished"); + let e = new Uint8Array(16); + return this.finish(e), + e + } + clean() { + return Co(this._buffer), + Co(this._r), + Co(this._h), + Co(this._pad), + this._leftover = 0, + this._fin = 0, + this._finished = !0, + this + } +} + +function Mo(e, t, n, a=0) { + return Co(n), + So(e, t, n, n, a) +} + +function xo(e, t=new Uint8Array(8), n=0) { + return _o(e >>> 0, t, n), + _o(e / 4294967296 >>> 0, t, n + 4), + t +} + +const Io = new Uint8Array(16); + +class jo { + nonceLength = 12; + tagLength = 16; + _key; + constructor(e) { + if (32 !== e.length) + throw new Error("ChaCha20Poly1305 needs 32-byte key"); + this._key = new Uint8Array(e) + } + seal(e, t, n, a) { + if (e.length > 16) + throw new Error("ChaCha20Poly1305: incorrect nonce length"); + const o = new Uint8Array(16); + o.set(e, o.length - e.length); + const r = new Uint8Array(32); + Mo(this._key, o, r, 4); + const s = t.length + this.tagLength; + let i; + if (a) { + if (a.length !== s) + throw new Error("ChaCha20Poly1305: incorrect destination length"); + i = a + } else + i = new Uint8Array(s); + return So(this._key, o, t, i, 4), + this._authenticate(i.subarray(i.length - this.tagLength, i.length), r, i.subarray(0, i.length - this.tagLength), n), + Co(o), + i + } + open(e, t, n, a) { + if (e.length > 16) + throw new Error("ChaCha20Poly1305: incorrect nonce length"); + if (t.length < this.tagLength) + return null; + const o = new Uint8Array(16); + o.set(e, o.length - e.length); + const r = new Uint8Array(32); + Mo(this._key, o, r, 4); + const s = new Uint8Array(this.tagLength); + if (this._authenticate(s, r, t.subarray(0, t.length - this.tagLength), n), + i = s, + l = t.subarray(t.length - this.tagLength, t.length), + 0 === i.length || 0 === l.length || 0 === function(e, t) { + if (e.length !== t.length) + return 0; + let n = 0; + for (let a = 0; a < e.length; a++) + n |= e[a] ^ t[a]; + return 1 & n - 1 >>> 8 + }(i, l)) + return null; + var i, l; + const c = t.length - this.tagLength; + let u; + if (a) { + if (a.length !== c) + throw new Error("ChaCha20Poly1305: incorrect destination length"); + u = a + } else + u = new Uint8Array(c); + return So(this._key, o, t.subarray(0, t.length - this.tagLength), u, 4), + Co(o), + u + } + clean() { + return Co(this._key), + this + } + _authenticate(e, t, n, a) { + const o = new Eo(t); + a && (o.update(a), + a.length % 16 > 0 && o.update(Io.subarray(a.length % 16))), + o.update(n), + n.length % 16 > 0 && o.update(Io.subarray(n.length % 16)); + const r = new Uint8Array(8); + a && xo(a.length, r), + o.update(r), + xo(n.length, r), + o.update(r); + const s = o.digest(); + for (let i = 0; i < s.length; i++) + e[i] = s[i]; + o.clean(), + Co(s), + Co(r) + } +} + + +function Uo(e) { + const t = new Uint8Array(e.length / 2); + for (let n = 0; n < t.length; n++) + t[n] = parseInt(e.slice(2 * n, 2 * n + 2), 16); + return t +} + +function decryptResponse(e, t, n=1) { + if (32 !== t.length) + throw new Error("密钥长度必须为32字节"); + if (e.length < 41) + throw new Error("密文长度不足"); + const a = e[0] + , o = e.subarray(1, 25) + , r = e.subarray(25) + , s = 2 === a ? r.slice().reverse() : r + , i = new Po(t).open(o, s); + if (!i) + throw new Error("认证失败"); + return i +} + +async function encryptRequest(e, t, n=1) { + if (32 !== t.length) + throw new Error("密钥长度必须为32字节"); + const a = new Uint8Array(12); + globalThis.crypto.getRandomValues(a); + const o = { + name: "AES-GCM", + iv: a + } + , r = await crypto.subtle.importKey("raw", t, "AES-GCM", !1, ["encrypt"]) + , s = new Uint8Array(await crypto.subtle.encrypt(o, r, e)); + 2 === n && function(e) { + for (let t = 0, n = e.length - 1; t < n; t++, + n--) { + const a = e[t]; + e[t] = e[n], + e[n] = a + } + }(s); + const i = new Uint8Array(1 + a.length + s.length); + return i[0] = 2 === n ? 2 : 1, + i.set(a, 1), + i.set(s, 1 + a.length), + i +} + +function n() { + return { + key : 'ea9d9d4f9a983fe6f6382f29c7b46b8d6dc47abc6da36662e6ddff8c78902f65', + version : 1 + } +} + + + +async function decryptText(encodeText) { + const {key: a, version: o} = n() + , r = Uo(a || ""); + const s = Number(o || 0) + const t = Uo(encodeText) + , xx = decryptResponse(t, r, s); + return (new TextDecoder).decode(xx) +} + +async function encryptText(data) { + const {key: a, version: o} = n() + , r = Uo(a || ""); + const b = await encryptRequest((new TextEncoder).encode(data), r); + return Array.from(b).map(e => e.toString(16).padStart(2, "0")).join("") +} + +$.exports = { + decryptText, + encryptText +} \ No newline at end of file diff --git a/spider/js/push_agent.js b/spider/js/push_agent.js index 2248db32..5e8ae9a8 100644 --- a/spider/js/push_agent.js +++ b/spider/js/push_agent.js @@ -78,7 +78,7 @@ var rule = { let list = input.split('@'); // log(list); for (let i = 0; i < list.length; i++) { - if (/pan.quark.cn|drive.uc.cn|www.alipan.com|www.aliyundrive.com|cloud.189.cn|yun.139.com|caiyun.139.com|www.123684.com|www.123865.com|www.123912.com|www.123pan.com|www.123pan.cn|www.123592.com|pan.baidu.com/.test(list[i])) { + if (/pan.quark.cn|drive.uc.cn|www.alipan.com|www.aliyundrive.com|cloud.189.cn|yun.139.com|caiyun.139.com|www.123684.com|www.123865.com|www.123912.com|www.123pan.com|www.123pan.cn|www.123592.com|pan.baidu.com|pan.xunlei.com/.test(list[i])) { if (/pan.quark.cn/.test(list[i])) { playPans.push(list[i]); const shareData = Quark.getShareData(list[i]); @@ -189,12 +189,21 @@ var rule = { }) vod.vod_content = vod_content_add.join('\n'); } + if (/pan.xunlei.com/.test(input)) { + const data = await Xun.getShareData(input) + Object.keys(data).forEach(it => { + playform.push('Xun-' + it) + const urls = data[it].map(item => item.name + "$" + [item.fileId, item.share_id, item.parent_id, item.pass_code_token].join('*')).join('#'); + playurls.push(urls); + }) + } + } else { playform.push('推送'); playurls.push("推送" + '$' + list[i]) } } - } else if (/pan.quark.cn|drive.uc.cn|www.alipan.com|www.aliyundrive.com|cloud.189.cn|yun.139.com|caiyun.139.com|www.123684.com|www.123865.com|www.123912.com|www.123pan.com|www.123pan.cn|www.123592.com|pan.baidu.com/.test(input)) { + } else if (/pan.quark.cn|drive.uc.cn|www.alipan.com|www.aliyundrive.com|cloud.189.cn|yun.139.com|caiyun.139.com|www.123684.com|www.123865.com|www.123912.com|www.123pan.com|www.123pan.cn|www.123592.com|pan.baidu.com|pan.xunlei.com/.test(input)) { if (/pan.quark.cn/.test(input)) { playPans.push(input); const shareData = Quark.getShareData(input); @@ -305,6 +314,15 @@ var rule = { }) vod.vod_content = vod_content_add.join('\n'); } + if (/pan.xunlei.com/.test(input)) { + const data = await Xun.getShareData(input) + Object.keys(data).forEach(it => { + playform.push('Xun-' + it) + const urls = data[it].map(item => item.name + "$" + [item.fileId, item.share_id, item.parent_id, item.pass_code_token].join('*')).join('#'); + playurls.push(urls); + }) + } + } else { playform.push('推送'); playurls.push("推送" + '$' + input) @@ -333,28 +351,36 @@ var rule = { // 确保返回parse: 0和正确的URL格式,避免前端创建新的播放列表 return {parse: 0, url: ["原画", input]} } - } else if (/Quark-|UC-|Ali-|Cloud-|Yun-|Pan123-|Baidu-/.test(flag)) { + } else if (/Quark-|UC-|Ali-|Cloud-|Yun-|Pan123-|Baidu-|Xun-/.test(flag)) { const ids = id.split('*'); let UCDownloadingCache = {}; let downUrl = '' if (flag.startsWith('Quark-')) { log("夸克网盘解析开始") - const down = await Quark.getDownload(ids[0], ids[1], ids[2], ids[3], true); const headers = { // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 QuarkPC/4.5.5.535 quark-cloud-drive/2.5.40 Channel/pckk_other_ch', // 'origin': 'https://pan.quark.cn', // 'referer': 'https://pan.quark.cn/', 'Cookie': ENV.get('quark_cookie') }; + //无限不转存 + const link = await Quark.getUrl(ids[0], ids[1], ids[2], ids[3]); + link.forEach(item => { + if (item !== undefined) { + urls.push("无限" + item.name, item.url + "#isVideo=true##fastPlayMode##threads=20#") + urls.push("无限猫" + item.name, `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=256&url=` + encodeURIComponent(item.url) + '&header=' + encodeURIComponent(JSON.stringify(headers))); + } + }); + const down = await Quark.getDownload(ids[0], ids[1], ids[2], ids[3], true); down.forEach((t) => { - if(t.url!==undefined){ - urls.push("猫"+t.name, `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=256&url=` + encodeURIComponent(t.url)); - urls.push(t.name, t.url+ "#isVideo=true##fastPlayMode##threads=20#") + if (t.url !== undefined) { + urls.push("猫" + t.name, `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=256&url=` + encodeURIComponent(t.url)); + urls.push(t.name, t.url + "#isVideo=true##fastPlayMode##threads=20#") } }); const transcoding = (await Quark.getLiveTranscoding(ids[0], ids[1], ids[2], ids[3])).filter((t) => t.accessable); transcoding.forEach((t) => { - urls.push(t.resolution === 'low' ? "流畅" : t.resolution === 'high' ? "高清" : t.resolution === 'super' ? "超清" : t.resolution, t.video_info.url+ "#isVideo=true##fastPlayMode##threads=20#") + urls.push(t.resolution === 'low' ? "流畅" : t.resolution === 'high' ? "高清" : t.resolution === 'super' ? "超清" : t.resolution, t.video_info.url + "#isVideo=true##fastPlayMode##threads=20#") }); // urls.push("原画", down.download_url + '#fastPlayMode##threads=10#'); // urls.push("原代服", mediaProxyUrl + `?thread=${ENV.get('thread') || 6}&form=urlcode&randUa=1&url=` + encodeURIComponent(down.download_url) + '&header=' + encodeURIComponent(JSON.stringify(headers))); @@ -455,6 +481,24 @@ var rule = { } } } + if (flag.startsWith('Xun-')) { + log('迅雷云盘开始解析') + //转码和下载的第二个值不同 + let urls = await Xun.getShareUrl(ids[0], ids[1], ids[3]) + // let url = await Xun.getDownloadUrl(ids[0],ids[2],ids[3]) + // if(url!==''){ + // urls.push('原画',url+ "#isVideo=true##fastPlayMode##threads=20#") + // urls.push("猫画", `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=256&url=` + encodeURIComponent(url)); + // } + return { + parse: 0, + url: urls, + header: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" + } + } + } + } else { return input } diff --git "a/spider/js/\345\220\254\345\217\213[\345\220\254].js" "b/spider/js/\345\220\254\345\217\213[\345\220\254].js" new file mode 100644 index 00000000..4af3af6e --- /dev/null +++ "b/spider/js/\345\220\254\345\217\213[\345\220\254].js" @@ -0,0 +1,300 @@ +/* +@header({ + searchable: 2, + filterable: 1, + quickSearch: 0, + title: '听友[听]', + '类型': '听书', + lang: 'ds' +}) +*/ +const {getHtml,req_,req_proxy} = $.require('./_lib.request.js') +const {decryptText,encryptText} = $.require('./_lib.tingyou.js') +var rule = { + 类型: '听书', + title: '听友[听]', + host: 'https://tingyou.fm', + url: '/api/category_page/types/fyclass/popular/pfypage', + detailUrl:'/api/chapters_list/fyid', + searchUrl: '/api/search', + searchable: 2, + quickSearch: 0, + timeout: 5000, + class_parse:async function(){ + let classes = [ + { + "type_id": 46, + "type_name": "玄幻奇幻" + }, + { + "type_id": 11, + "type_name": "武侠小说" + }, + { + "type_id": 19, + "type_name": "言情通俗" + }, + { + "type_id": 21, + "type_name": "相声小品" + }, + { + "type_id": 14, + "type_name": "恐怖惊悚" + }, + { + "type_id": 17, + "type_name": "官场商战" + }, + { + "type_id": 15, + "type_name": "历史军事" + }, + { + "type_id": 9, + "type_name": "百家讲坛" + }, + { + "type_id": 16, + "type_name": "刑侦反腐" + }, + { + "type_id": 10, + "type_name": "有声文学" + }, + { + "type_id": 18, + "type_name": "人物纪实" + }, + { + "type_id": 36, + "type_name": "广播剧" + }, + { + "type_id": 22, + "type_name": "英文读物" + }, + { + "type_id": 23, + "type_name": "轻音清心" + }, + { + "type_id": 31, + "type_name": "二人转" + }, + { + "type_id": 33, + "type_name": "健康养生" + }, + { + "type_id": 34, + "type_name": "综艺娱乐" + }, + { + "type_id": 40, + "type_name": "头条" + }, + { + "type_id": 38, + "type_name": "戏曲" + }, + { + "type_id": 41, + "type_name": "脱口秀" + }, + { + "type_id": 42, + "type_name": "商业财经" + }, + { + "type_id": 43, + "type_name": "亲子教育" + }, + { + "type_id": 44, + "type_name": "教育培训" + }, + { + "type_id": 45, + "type_name": "时尚生活" + }, + { + "type_id": 20, + "type_name": "童话寓言" + }, + { + "type_id": 47, + "type_name": "未分类" + }, + { + "type_id": 1, + "type_name": "单田芳" + }, + { + "type_id": 2, + "type_name": "刘兰芳" + }, + { + "type_id": 3, + "type_name": "田连元" + }, + { + "type_id": 4, + "type_name": "袁阔成" + }, + { + "type_id": 5, + "type_name": "连丽如" + }, + { + "type_id": 8, + "type_name": "孙一" + }, + { + "type_id": 30, + "type_name": "王子封臣" + }, + { + "type_id": 25, + "type_name": "马长辉" + }, + { + "type_id": 26, + "type_name": "昊儒书场" + }, + { + "type_id": 27, + "type_name": "王军" + }, + { + "type_id": 28, + "type_name": "王玥波" + }, + { + "type_id": 29, + "type_name": "石连君" + }, + { + "type_id": 12, + "type_name": "粤语评书" + }, + { + "type_id": 35, + "type_name": "关永超" + }, + { + "type_id": 6, + "type_name": "张少佐" + }, + { + "type_id": 7, + "type_name": "田战义" + }, + { + "type_id": 13, + "type_name": "其他评书" + } + ] + + return { + class:classes + } + }, + headers:{ + 'User-Agent': 'zybk/1.0.6', + 'Accept-Encoding': 'gzip', + 'authorization': 'Bearer gAAAAABpsEFsPBrHfY1bGsn15TbqqXUC4WSFwm8VU97NW6qmSAewn1rbYMzbIXLajyJnSZ94oZsS6hil8Qkb-IknSuggyn9XLDitEE930CD9OapDQOzq1xSJb7foWNh5YdeT_7p4ZSyYyhW4b2ZWmI-Itb8YBTjDmWIM3FiTQ9MYATmWKJQ6d6IY5Z0bupvW6hjWoHppAa5v0_k2KkIEHdzyw7AiKTPPqUYVmKvrvISlBkMHGdyK83AgiOi80-mKwmCIY1kXuj_vg_mY1HxvmsPpNcYLaoOYUA==', + // 'cookie':'session=dvJGYQ7gKDJvm-FXEzmCCHPd0IK7fzjLz1hfmi5RSxlhGi6EayEATHlH9_c%3D;' + }, + play_parse: true, + 预处理: async () => { + let data = '02956c849999374a66745e3ac9957f00ad9022036ec6b1a20c7f86327c8817'; + let config = { + method: 'POST', + url: 'https://azybk.tingyou8.vip/apk/auth/me', + headers: { + 'User-Agent': 'zybk/1.0.6', + 'Accept-Encoding': 'gzip', + 'authorization': 'Bearer gAAAAABpsAkJlSPlhBJAKM71X7PpktM1kpibFvpxnJbGXBAN0ydCgx4gviLacuou6QJKAZ4FtCpdCe8HZLKdveUTv-BTfeVFB7wGBv6yiylsWmAeKwc5YLunEbwXQv1VtMLNn4W7e4PZQlLSSOTZHbwYsC0Herb1GohZ4NU47-85y_eNuz8qq0mmxtY_2JMG9T00YcFAevfvCkfkngr0ttUZEgLVK2W_SKfHL-CSvfe6mJWQxNh88p3ViNSTK0sbL-2XPgBdDPD3urXgA4eZ7pQfPYKF3aj3ow==' + }, + data: data + }; + let html = await axios.request(config).catch(e=>e.response.headers['set-cookie']) + if(html[0]){ + rule.headers['cookie'] = html[0].replace('Path=/; Domain=tingyou8.vip; Max-Age=604800; HttpOnly','') + } + return [] + }, + lazy: async function () { + let {input} = this; + console.log(input) + let data = { + "album_id": Number(input.split('^')[0]), + "chapter_idx": Number(input.split('^')[1]) + } + let encodeData = await encryptText(JSON.stringify(data)) + let html = await req_('https://azybk.tingyou8.vip/apk/play/play_token','post', rule.headers,encodeData); + let link = JSON.parse(await decryptText(html.payload)).play_url + return {url: link, parse: 0}; + }, + double: true, + 一级: async function () { + let {input} = this; + const videos = [] + let html = await req_(input); + let data = html.payload + let list = JSON.parse(await decryptText(data)).data + list.forEach(item => { + videos.push({ + vod_id: item.id, + vod_name: item.title, + vod_pic: item.cover_url, + vod_remarks: item.status === 1 ? "连载":"完结", + }) + }) + return videos; + }, + 二级: async function () { + let {input,orId} = this; + let urls = []; + let html = await req_(input); + let list = JSON.parse(await decryptText(html.payload)).chapters + list.forEach(item => { + urls.push(item.title+"$"+orId+"^"+item.index) + }) + let js = await req_(input.replace('chapters_list','album_detail')) + let content = JSON.parse(await decryptText(js.payload)) + let VOD = { + vod_id:content.id, + vod_name:content.title, + vod_pic:content.cover_url, + vod_remarks:content.status === 1 ? "连载":"完结", + vod_content:content.synosis||'', + vod_play_from: '球球啦', + vod_play_url: urls.join('#') + }; + return VOD; + }, + 搜索: async function (wd, quick, pg) { + let {input} = this; + let videos = []; + let data = { + "keyword": wd, + "page": pg, + "sort_by": "updated_at", + "sort_order": "desc" + } + let encodeData = await encryptText(JSON.stringify(data)) + let html = await req_('https://azybk.tingyou8.vip/apk/search','post', rule.headers,encodeData); + let list = JSON.parse(await decryptText(html.payload)).results + list.forEach(item => { + videos.push({ + vod_id: item.id, + vod_name: item.title, + vod_pic: item.cover_url, + vod_remarks: item.status === 1 ? "连载":"完结", + }) + }) + return videos; + } +} \ No newline at end of file diff --git "a/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" "b/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" index f3f4aabb..92437831 100644 --- "a/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" +++ "b/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" @@ -26,6 +26,7 @@ var rule = { headers: { 'User-Agent': 'MOBILE_UA', }, + timeout: 10000, play_parse: true, lazy: async function () { let {input, pdfh} = this; diff --git "a/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" "b/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" index 73866aca..49b61343 100644 --- "a/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" +++ "b/spider/js/\345\244\256\350\247\206\345\244\247\345\205\250[\345\256\230].js" @@ -4,11 +4,32 @@ filterable: 1, quickSearch: 0, title: '央视大全', - lang: 'ds' + lang: 'ds', + isProxyPath: true, + more: { + parseApi: [ + { + host: 'cctv://(.+)', + flag: 'CCTV' + }, + { + host: 'cctv4k://(.+)', + flag: 'CCTV4K' + }, + { + host: 'cctvlive://(.+)', + flag: 'CCTV直播' + }, + ] + }, + }) */ -const {processFile, indexHtml} = $.require('./_lib.cntv.js'); +// const {processFile, indexHtml} = $.require('./_lib.cntv.js'); +const {parseCCTVUrl, detectInputType, getVideoInfoByPid} = require('./_lib.cntv-urlparse.cjs'); +const {processFile} = require('./_lib.cntv2026.cjs'); +const {indexHtml} = $.require('./_lib.cntv.js'); const {setH5Str} = $.require('./_lib.cntv.live.js'); var rule = { title: '央视大全', @@ -31,7 +52,7 @@ var rule = { play_parse: true, lazy: async function () { let {input, flag, getProxyUrl} = this; - // log(input); + log(input); // log(flag); let guid = ''; let url = ''; @@ -251,9 +272,10 @@ var rule = { let url = ''; let is_live = 0; if (proxyPath) { - const BASE_URL = 'https://dh5.cntv.qcloudcdn.com/'.rstrip('/'); + // const BASE_URL = 'https://dh5.cntv.qcloudcdn.com/'.rstrip('/'); // const BASE_URL = 'https://dh5.cntv.myalicdn.com/'.rstrip('/'); - url = `${BASE_URL}/${proxyPath}`; + // url = `${BASE_URL}/${proxyPath}`; + url = proxyPath; } else { url = base64Decode(input.split('#')[0]); is_live = 1; @@ -284,6 +306,7 @@ var rule = { return [200, 'application/vnd.apple.mpegurl', m3u8Str] } const contentType = extension === '.ts' ? 'video/MP2T' : 'application/vnd.apple.mpegurl'; + // log('url:', url); const buffer = await processFile(url, extension); const headers = { 'Content-Disposition': `attachment; filename="${filename}"`, @@ -472,6 +495,13 @@ function getRegexText(text, regexText, index) { } async function getM3u8(pid, getProxyUrl) { + const info = await getVideoInfoByPid(pid); + const proxy_path = info.download_url; + log('[getM3u8] proxy_path:', proxy_path); + return getProxyUrl().split('?')[0].rstrip('/') + '/' + proxy_path; +} + +async function getM3u8Old(pid, getProxyUrl) { const url = `https://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=${pid}`; const htmlTxt = await request(url); const jo = JSON.parse(htmlTxt); diff --git "a/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" "b/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" index 98e71dda..605fa258 100644 --- "a/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" +++ "b/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" @@ -14,8 +14,8 @@ var rule = { 类型: '漫画', title: '番茄漫画', - // host: 'https://qkfqapi.vv9v.cn', - host: 'http://47.108.80.161:5005', + host: 'https://qkfqapi.vv9v.cn', + // host: 'http://47.108.80.161:5005', homeUrl: '/api/discover/style?tab=漫画', url: 'fyclass', searchUrl: '/api/search?key=**&tab_type=8&offset=((fypage-1)*10)', diff --git "a/spider/js/\347\275\221\347\233\230[\346\250\241\346\235\277].js" "b/spider/js/\347\275\221\347\233\230[\346\250\241\346\235\277].js" index a4091284..b43671f1 100644 --- "a/spider/js/\347\275\221\347\233\230[\346\250\241\346\235\277].js" +++ "b/spider/js/\347\275\221\347\233\230[\346\250\241\346\235\277].js" @@ -1,11 +1,11 @@ /* @header({ - searchable: 1, - filterable: 1, - quickSearch: 1, - title: '网盘[模板]', - '类型': '影视', - lang: 'ds' + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '网盘[模板]', + '类型': '影视', + lang: 'ds' }) */ @@ -18,572 +18,508 @@ var rule = { "User-Agent": "PC_UA", 'Accept': 'text/html; charset=utf-8' }, - line_order: [ '百度', '优汐', '夸克', '天翼', '123', '移动', '阿里'], + line_order: ['百度', '夸克', '优汐', '天翼', '123', '移动', '阿里'], play_parse: true, search_match: true, searchable: 1, filterable: 1, timeout: 60000, quickSearch: 1, - - hostJs: async function() { - let startTime = Date.now(); - - try { - // 解析参数 + + // 夸克网盘转存配置(true=开启下载和转码,false=关闭转存) + quark_transfer: false, + + hostJs: async function () { + let parts = rule.params.split('$'); + if (parts.length < 2) { + return host || ''; + } + let _host = parts[0]; - let html = await request(_host); - let json = JSON.parse(html); let paramKey = decodeURIComponent(parts[1]); - let config = json[paramKey] || {}; rule_type = parts.length > 2 ? parts[2] : ""; rule._name = paramKey; - // 处理域名配置 + // 读取有效的域名缓存 + const cacheKey = `domain_cache_${paramKey}`; + let cached = await local.get('host_cache', cacheKey); + console.log('读取域名缓存:', cacheKey, cached); + if (cached) { + // 验证缓存域名是否仍然有效 + let testRes = await request(cached, { + method: 'HEAD', + timeout: 3000, + headers: {'User-Agent': 'Mozilla/5.0'} + }); + if (testRes) { + return cached; + } + // 缓存域名失效,继续获取新域名 + await local.set('host_cache', cacheKey, null); + } + + let html = await request(_host); + let json = JSON.parse(html); + let config = json[paramKey] || {}; + let domains = Array.isArray(config) ? config : [config]; - domains = domains.filter(u => u?.trim()).map(u => { + domains = domains.filter(u => u && typeof u === 'string' && u.trim()).map(u => { u = u.trim(); - return /^https?:\/\//i.test(u) ? u : - (u.includes('https') || u.includes('ssl')) ? `https://${u.replace(/^(https?:\/\/)?/i, '')}` : - `http://${u.replace(/^(https?:\/\/)?/i, '')}`; + if (/^https?:\/\//i.test(u)) return u; + if (u.includes('https') || u.includes('ssl')) { + return `https://${u.replace(/^(https?:\/\/)?/i, '')}`; + } + return `http://${u.replace(/^(https?:\/\/)?/i, '')}`; }); - console.log(`${rule._name}域名加载成功,共${domains.length}个`); + if (domains.length === 0) { + return ''; + } - // 域名检查函数 - 使用HEAD方法提高速度 - let check = url => new Promise(resolve => { - let mod = url.startsWith('https') ? require('https') : require('http'); - let t0 = Date.now(); - - let options = { - method: 'HEAD', - timeout: 2000, - headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0.0.0 Safari/537.36' + const results = await Promise.any( + domains.map(async (url) => { + let res = await request(url, { + method: 'GET', + timeout: 5000, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' + } + }); + + if (res && res.includes('index.php')) { + return url; } - }; - - let req = mod.request(url, options, res => { - let t = Date.now() - t0; - let valid = res.statusCode >= 200 && res.statusCode < 400; - console.log(`${valid ? '✅' : '❌'} ${url} (${t}ms, 状态: ${res.statusCode})`); - resolve({ url, t, valid, code: res.statusCode }); - req.destroy(); - }).on('error', () => { - resolve({ url, t: Infinity, valid: false, code: 0 }); - }).on('timeout', () => { - req.destroy(); - resolve({ url, t: 2000, valid: false, code: 0 }); - }); - - req.end(); - }); + throw new Error('无效域名'); + }) + ).catch(() => null); - // 并发检查域名 - const CONCURRENT_LIMIT = 5; - let results = []; - - for (let i = 0; i < domains.length; i += CONCURRENT_LIMIT) { - const chunk = domains.slice(i, i + CONCURRENT_LIMIT); - const chunkResults = await Promise.all(chunk.map(check)); - results = results.concat(chunkResults); - - // 提前终止检查 - const validResults = results.filter(r => r.valid); - if (validResults.length > 0) break; + if (results) { + await local.set('host_cache', cacheKey, results); + return results; } - - // 选择最佳域名 - let validDomains = results.filter(x => x.valid); - validDomains.sort((a, b) => a.t - b.t); - let bestDomain = validDomains[0]?.url || domains[0]; - - console.log(validDomains.length ? - `✅ 最终选用: ${bestDomain}(延迟: ${validDomains[0].t}ms)` : - `⚠️ 无可用域名,使用默认: ${bestDomain}` - ); - - return bestDomain; - } catch (e) { - console.error(`域名检测出错: ${e.message}`); - return ''; - } finally { - console.log(`⏱️ 域名检测耗时: ${Date.now() - startTime}ms`); - } -}, + + return domains[0] || ''; + }, class_parse: async function () { - const { input, pdfa, pdfh, pd, host, MY_CATE } = this; + const {input, pdfa, pdfh, pd, host, MY_CATE} = this; + + const cacheKey = `class_cache_${input}_${MY_CATE || 'default'}`; + const cacheExpiration = 7 * 24 * 60 * 60 * 1000; // 7天 + + let cached = await local.get('class_cache', cacheKey); + console.log('读取分类缓存:', cacheKey, cached ? '有缓存' : '无缓存'); + if (cached) { + let parsed = JSON.parse(cached); + if (parsed.timestamp > Date.now() - cacheExpiration && + parsed.classes && parsed.classes.length > 0 && + parsed.filters && Object.keys(parsed.filters).length > 0) { + return {class: parsed.classes, filters: parsed.filters}; + } else { + await local.set('class_cache', cacheKey, null); + } + } + const classes = []; const filters = {}; const seenTypeIds = new Set(); - - // 添加缓存逻辑 - const cacheExpiration = 30 * 24 * 60 * 60 * 1000; - const cacheKey = `${input}_${MY_CATE || 'default'}`; - if (!this.cache) this.cache = {}; + let html = await request(input); + let navItems = pdfa(html, '.nav-menu-items&&li') || []; + navItems.forEach(item => { + let href = pd(item, 'a&&href')?.trim() || ''; + let typeName = pdfh(item, 'a&&Text')?.trim() || ''; + let match = href.match(/\/([^\/]+)\.html$/); + if (match && typeName && /^\d+$/.test(match[1]) && !seenTypeIds.has(match[1])) { + classes.push({type_name: typeName, type_id: match[1]}); + seenTypeIds.add(match[1]); + } + }); - if (this.cache[cacheKey] && this.cache[cacheKey].timestamp > Date.now() - cacheExpiration) { - console.log(`📦 命中缓存 [Key: ${cacheKey}]`); - return { - class: this.cache[cacheKey].data, - filters: this.cache[cacheKey].filters || {} - }; + if (classes.length === 0) { + return {class: [], filters: {}}; } - try { - const html = await request(input); - const navItems = pdfa(html, '.nav-menu-items&&li'); - - navItems.forEach((item) => { - const href = pd(item, 'a&&href').trim(); - const typeName = pdfh(item, 'a&&Text').trim(); - const matchResult = href.match(/\/([^\/]+)\.html$/); - - if (matchResult && typeName && !seenTypeIds.has(matchResult[1])) { - const typeId = matchResult[1]; - if (/^\d+$/.test(typeId)) { - classes.push({ - type_name: typeName, - type_id: typeId - }); - seenTypeIds.add(typeId); + let urls = classes.map(item => { + let url = rule_type ? + `${host}/vodshow/${item.type_id}-----------.html` : + `${host}/index.php/vod/show/id/${item.type_id}.html`; + return {url, options: {headers: rule.headers, timeout: 5000}}; + }); + + let htmls = await batchFetch(urls); + + const CATEGORIES = [ + {key: 'cateId', name: '类型', reg: /\/id\/(\d+)/}, + {key: 'class', name: '剧情'}, + {key: 'lang', name: '语言'}, + {key: 'area', name: '地区'}, + {key: 'year', name: '时间'}, + {key: 'letter', name: '字母'} + ]; + + let hasValidFilters = false; + + htmls.forEach((html, i) => { + let type_id = classes[i].type_id; + filters[type_id] = []; + if (!html || html.length < 300) { + return; + } + + CATEGORIES.forEach(cat => { + const libraryBoxes = pdfa(html, '.library-box'); + const box = libraryBoxes.find(b => pdfh(b, 'a&&Text').includes(cat.name)); + if (!box) return; + + const linkItems = pdfa(box, 'div a'); + let values = linkItems.map(a => { + const n = pdfh(a, "a&&Text") || "全部"; + let v = n; + if (cat.key === 'cateId') { + const href = pd(a, 'a&&href', host); + v = href?.match(cat.reg)?.[1] || n; } + if (/全部|字母/.test(n)) return {n: "全部", v: ""}; + return {n, v}; + }).filter(x => x?.n) + .filter((item, idx, self) => self.findIndex(i => i.n === item.n) === idx); + + if (values.length > 3) { + filters[type_id].push({key: cat.key, name: cat.name, value: values}); + hasValidFilters = true; } }); - const htmlArr = await batchFetch(classes.map(item => { - let url = rule_type ? - `${host}/vodshow/${item.type_id}-----------.html` : - `${host}/index.php/vod/show/id/${item.type_id}.html`; - return { - url: url, - options: { timeout: 100000, headers: rule.headers} - }; - })); - - const CATEGORIES = [ - {key:'cateId', name:'类型', reg:/\/id\/(\d+)/}, - {key:'class', name:'剧情'}, - {key:'lang', name:'语言'}, - {key:'area', name:'地区'}, - {key:'year', name:'时间'}, - {key:'letter', name:'字母'}, - ]; - - const SORT_OPTIONS = { - "时间": "time", - "人气": "hits", - "评分": "score", - }; - htmlArr.forEach((it, i) => { - if (!it) { - filters[classes[i].type_id] = []; - return; - } - const type_id = classes[i].type_id; - filters[type_id] = CATEGORIES.map((category) => { - const box = pdfa(it, '.library-box').find(b => b.includes(category.name)) || ""; - let values = []; - - if (box) { - values = pdfa(box, "div a").map(a => { - const n = pdfh(a, "a&&Text") || "全部"; - let v = n; - - if (category.key === 'cateId') { - const href = pd(a, 'a&&href'); - v = href.match(category.reg)?.[1] || n; - } - - return { n, v }; - }).filter(x => x.n && x.v); - } - - return { - key: category.key, - name: category.name, - value: values - }; - }).filter(item => item.value && item.value.length > 3); - - const sortValues = Object.entries(SORT_OPTIONS).map(([name, value]) => ({ - n: name, - v: value - })); - - if (sortValues.length > 0) { - filters[type_id].push({ - key: "by", - name: "排序", - value: sortValues - }); - } + filters[type_id].push({ + key: "by", + name: "排序", + value: [ + {n: "时间", v: "time"}, + {n: "人气", v: "hits"}, + {n: "评分", v: "score"} + ] }); - - // 保存到缓存 - this.cache[cacheKey] = { + hasValidFilters = true; + }); + + if (classes.length > 0 && hasValidFilters) { + await local.set('class_cache', cacheKey, JSON.stringify({ timestamp: Date.now(), - data: classes, + classes: classes, filters: filters - }; - - return { class: classes, filters }; - } catch (error) { - classes.forEach(cls => { - filters[cls.type_id] = []; - }); - return { class: classes, filters }; + })); } + + return {class: classes, filters}; }, - // 以下代码保持不变... 推荐: async function () { let {input, pdfa, pdfh, pd} = this; let html = await request(input); + let d = []; - let data = pdfa(html, '.module-items .module-item'); - data.forEach(it => { - let title = pdfh(it, 'a&&title'); + let items = pdfa(html, '.module-items .module-item') || []; + + items.forEach(it => { d.push({ - title: title, - img: pd(it, 'img&&data-src'), - desc: pdfh(it, '.module-item-text&&Text'), - url: pd(it, 'a&&href') + title: pdfh(it, 'a&&title') || '', + img: pd(it, 'img&&data-src') || '', + desc: pdfh(it, '.module-item-text&&Text') || '', + url: pd(it, 'a&&href') || '' }); }); return setResult(d); }, - + 一级: async function () { - let { input, pdfa, pdfh, pd, MY_CATE, MY_FL, MY_PAGE, host } = this; - const fl = MY_FL || {}; - const pg = MY_PAGE || 1; - const type = MY_CATE || fl.cateId; + let {input, pdfa, pdfh, pd, MY_CATE, MY_FL, MY_PAGE, host} = this; + let fl = MY_FL || {}; + let pg = MY_PAGE || 1; + let type = MY_CATE || fl.cateId; let url; if (rule_type) { url = `${host}/vodshow/${type}-${fl.area || ''}-${fl.by || 'time'}-${fl.class || ''}--${fl.letter || ''}---${pg}---${fl.year || ''}.html`; } else { - const parts = [ - fl.area ? `area/${fl.area}` : '', - fl.by ? `by/${fl.by}` : '', - fl.class ? `class/${fl.class}` : '', - fl.cateId ? `id/${fl.cateId}` : `id/${MY_CATE}`, - fl.lang ? `lang/${fl.lang}` : '', - fl.letter ? `letter/${fl.letter}` : '', - fl.year ? `year/${fl.year}` : '' - ].filter(Boolean); - - url = `${host}/index.php/vod/show/${parts.join('/')}/page/${pg}.html`; + let parts = []; + if (fl.area) parts.push(`area/${fl.area}`); + if (fl.by) parts.push(`by/${fl.by}`); + if (fl.class) parts.push(`class/${fl.class}`); + if (fl.lang) parts.push(`lang/${fl.lang}`); + if (fl.letter) parts.push(`letter/${fl.letter}`); + if (fl.year) parts.push(`year/${fl.year}`); + url = `${host}/index.php/vod/show/${parts.join('/')}/id/${MY_CATE}/page/${pg}.html`; } - + let html = await request(url); - let data = pdfa(html, '.module-items .module-item'); - let d = data.map((it) => ({ - title: pd(it, 'a&&title') || pdfh(it, '.module-item-title&&Text'), - pic_url: pd(it, 'img&&data-src') || pd(it, 'img&&src'), - desc: pdfh(it, '.module-item-text&&Text') || pdfh(it, '.module-item-content&&Text'), - url: pd(it, 'a&&href') - })); + + if (!html) { + return setResult([]); + } + + let items = pdfa(html, '.module-items .module-item') || []; + + let d = items.map(it => { + return { + title: pd(it, 'a&&title') || pdfh(it, '.module-item-title&&Text') || '', + pic_url: pd(it, 'img&&data-src') || pd(it, 'img&&src') || '', + desc: pdfh(it, '.module-item-text&&Text') || pdfh(it, '.module-item-content&&Text') || '', + url: pd(it, 'a&&href') || '' + }; + }).filter(item => item !== null); + return setResult(d); }, - 二级: async function (ids) { - try { - let { input, pdfa, pdfh, pd } = this; - let html = await request(input); - let data = pdfa(html, '.module-row-title'); - - let vod = { - vod_name: pdfh(html, '.video-info&&h1&&Text') || '', - type_name: pdfh(html, '.tag-link&&Text') || '', - vod_pic: pd(html, '.lazyload&&data-original||data-src||src') || '', - vod_content: pdfh(html, '.sqjj_a--span&&Text') || '', - vod_remarks: pdfh(html, '.video-info-items:eq(3)&&Text') || '', - vod_year: pdfh(html, '.tag-link:eq(2)&&Text') || '', - vod_area: pdfh(html, '.tag-link:eq(3)&&Text') || '', - vod_actor: pdfh(html, '.video-info-actor:eq(1)&&Text') || '', - vod_director: pdfh(html, '.video-info-actor:eq(0)&&Text') || '' - }; + let {input, pdfa, pdfh, pd, host} = this; + let html = await request(input); - let playform = []; - let playurls = []; - let playPans = []; - - let panCounters = { - '夸克': 1, - '优汐': 1, - '百度': 1, - '天翼': 1, - '123': 1, - '移动': 1, - '阿里': 1 - }; + let vod = { + vod_name: pdfh(html, '.video-info h1&&Text') || pdfh(html, 'h1&&Text') || '未知名称', + type_name: pdfh(html, '.tag-link&&Text') || '', + vod_pic: pd(html, '.lazyload&&data-original') || pd(html, 'img&&data-src') || '', + vod_content: pdfh(html, '.sqjj_a--span&&Text') || pdfh(html, '.video-info-content&&Text') || '暂无简介', + vod_remarks: pdfh(html, '.video-info-items:eq(3)&&Text') || '', + vod_year: pdfh(html, '.tag-link:eq(2)&&Text') || '未知年份', + vod_area: pdfh(html, '.tag-link:eq(3)&&Text') || '未知地区', + vod_actor: pdfh(html, '.video-info-actor:eq(1)&&Text') || '未知演员', + vod_director: pdfh(html, '.video-info-actor:eq(0)&&Text') || '未知导演' + }; - let allLines = []; - let allLinks = new Set(); + let allLinks = new Set(); + pdfa(html, '.module-row-title').forEach(item => { + let link = pd(item, 'p&&Text')?.trim(); + if (link) allLinks.add(link); + }); - for (let item of data) { - let link = pd(item, 'p&&Text'); - if (link) { - link = link.trim(); - allLinks.add(link); - } - } + let playSources = []; + let counters = {百度: 1, 优汐: 1, 夸克: 1, 天翼: 1, 123: 1, 移动: 1, 阿里: 1}; - let baiduLinks = Array.from(allLinks).filter(link => /pan\.baidu\.com/.test(link)); - let baiduLinkCount = baiduLinks.length; - - for (let link of allLinks) { - if (/\.quark/.test(link)) { - playPans.push(link); - let shareData = await Quark.getShareData(link); - if (shareData) { - let videos = await Quark.getFilesByShareUrl(shareData); - let lineName = '夸克#' + panCounters.夸克; - let playUrl = videos.length > 0 - ? videos.map(v => `${v.file_name}$${[ - shareData.shareId, - v.stoken, - v.fid, - v.share_fid_token, - v.subtitle?.fid || '', - v.subtitle?.share_fid_token || '' - ].join('*')}`).join('#') - : "资源已经失效,请访问其他资源"; - allLines.push({ name: lineName, url: playUrl, type: '夸克' }); - panCounters.夸克++; - } - } - else if (/\.uc/i.test(link)) { - playPans.push(link); - let shareData = await UC.getShareData(link); - if (shareData) { - let videos = await UC.getFilesByShareUrl(shareData); - let lineName = '优汐#' + panCounters.优汐; - let playUrl = videos.length > 0 - ? videos.map(v => `${v.file_name}$${[ - shareData.shareId, - v.stoken, - v.fid, - v.share_fid_token, - v.subtitle?.fid || '', - v.subtitle?.share_fid_token || '' - ].join('*')}`).join('#') - : "资源已经失效,请访问其他资源"; - allLines.push({ name: lineName, url: playUrl, type: '优汐' }); - panCounters.优汐++; - } + for (let link of allLinks) { + if (/\.quark/.test(link)) { + let share = await Quark.getShareData(link); + if (!share) continue; + let videos = await Quark.getFilesByShareUrl(share); + if (videos && videos.length > 0) { + let name = '夸克#' + counters.夸克++; + let urls = videos.map(v => { + let sizeStr = v.formatted_size || (v.size ? formatFileSize(v.size) : ''); + return `${v.file_name}${sizeStr ? ' 【' + sizeStr + '】' : ''}$${[share.shareId, v.stoken, v.fid, v.share_fid_token].join('*')}`; + }).join('#'); + let pics = videos.map(v => v.thumbnail || '').join('#'); + playSources.push({name, urls, pics, pan: link, type: '夸克'}); } - else if (/\.189/.test(link)) { - playPans.push(link); - let cloudData = await Cloud.getShareData(link); - Object.keys(cloudData).forEach(it => { - let lineName = '天翼-' + it; - const urls = cloudData[it].map(item => - `${item.name}$${[item.fileId, item.shareId].join('*')}` - ).join('#'); - allLines.push({ name: lineName, url: urls, type: '天翼' }); - }); + } else if (/\.uc/i.test(link)) { + let share = await UC.getShareData(link); + if (!share) continue; + let videos = await UC.getFilesByShareUrl(share); + if (videos && videos.length > 0) { + let name = '优汐#' + counters.优汐++; + let urls = videos.map(v => { + let sizeStr = v.formatted_size || (v.size ? formatFileSize(v.size) : ''); + return `${v.file_name}${sizeStr ? ' 【' + sizeStr + '】' : ''}$${[share.shareId, v.stoken, v.fid, v.share_fid_token].join('*')}`; + }).join('#'); + let pics = videos.map(v => v.thumbnail || '').join('#'); + playSources.push({name, urls, pics, pan: link, type: '优汐'}); } - else if (/\.139/.test(link)) { - playPans.push(link); - let yunData = await Yun.getShareData(link); - Object.keys(yunData).forEach(it => { - let lineName = '移动-' + it; - const urls = yunData[it].map(item => - `${item.name}$${[item.contentId, item.linkID].join('*')}` - ).join('#'); - allLines.push({ name: lineName, url: urls, type: '移动' }); + } else if (/\.189/.test(link)) { + let share = await Cloud.getShareData(link); + if (share && Object.keys(share).length > 0) { + Object.keys(share).forEach(k => { + if (share[k] && share[k].length > 0) { + let urls = share[k].map(v => { + let sizeStr = v.formatted_size || (v.size ? formatFileSize(v.size) : ''); + return `${v.name}${sizeStr ? ' 【' + sizeStr + '】' : ''}$${[v.fileId, v.shareId].join('*')}`; + }).join('#'); + let pics = share[k].map(v => v.thumbnail || '').join('#'); + playSources.push({name: '天翼-' + k, urls, pics, pan: link, type: '天翼'}); + } }); } - else if (/\.123/.test(link)) { - playPans.push(link); - let shareData = await Pan.getShareData(link); - let videos = await Pan.getFilesByShareUrl(shareData); - Object.keys(videos).forEach(it => { - let lineName = '123-' + it; - const urls = videos[it].map(v => - `${v.FileName}$${[v.ShareKey, v.FileId, v.S3KeyFlag, v.Size, v.Etag].join('*')}` - ).join('#'); - allLines.push({ name: lineName, url: urls, type: '123' }); + } else if (/\.139/.test(link)) { + let share = await Yun.getShareData(link); + if (share && Object.keys(share).length > 0) { + Object.keys(share).forEach(k => { + if (share[k] && share[k].length > 0) { + let urls = share[k].map(v => { + let sizeStr = v.formatted_size || (v.size ? formatFileSize(v.size) : ''); + return `${v.name}${sizeStr ? ' 【' + sizeStr + '】' : ''}$${[v.contentId, v.linkID].join('*')}`; + }).join('#'); + let pics = share[k].map(v => v.thumbnail || '').join('#'); + playSources.push({name: '移动-' + k, urls, pics, pan: link, type: '移动'}); + } }); } - else if (/\.baidu/.test(link)) { - playPans.push(link); - let baiduData = await Baidu2.getShareData(link); - - Object.keys(baiduData).forEach((it, index) => { - let lineName; - if (baiduLinkCount === 1) { - lineName = '百度#1'; - } else { - let lastPart = it.split('/').pop(); - lineName = '百度-' + lastPart; + } else if (/\.123/.test(link)) { + let share = await Pan.getShareData(link); + let videos = await Pan.getFilesByShareUrl(share); + if (videos && Object.keys(videos).length > 0) { + Object.keys(videos).forEach(k => { + if (videos[k] && videos[k].length > 0) { + let urls = videos[k].map(v => { + let sizeStr = v.formatted_size || (v.Size ? formatFileSize(v.Size) : ''); + return `${v.FileName}${sizeStr ? ' 【' + sizeStr + '】' : ''}$${[v.ShareKey, v.FileId, v.S3KeyFlag, v.Size, v.Etag].join('*')}`; + }).join('#'); + let pics = videos[k].map(v => v.Thumbnail || '').join('#'); + playSources.push({name: '123-' + k, urls, pics, pan: link, type: '123'}); } - - const urls = baiduData[it].map(item => - item.name + "$" + [item.path, item.uk, item.shareid, item.fsid].join('*') - ).join('#'); - allLines.push({ name: lineName, url: urls, type: '百度' }); }); } - else if (/\.alipan/.test(link)) { - playPans.push(link); - const shareData = await Ali.getShareData(link); - if (shareData) { - const videos = await Ali.getFilesByShareUrl(shareData); - let lineName = '阿里#' + panCounters.阿里; - let playUrl; - if (videos.length > 0) { - playUrl = videos.map((v) => { - const ids = [ - v.share_id, - v.file_id, - v.subtitle ? v.subtitle.file_id : '' - ]; - return `${v.name}$${ids.join('*')}`; + } else if (/\.baidu/.test(link)) { + let share = await Baidu2.getShareData(link); + if (share && Object.keys(share).length > 0) { + Object.keys(share).forEach((k, idx) => { + if (share[k] && share[k].length > 0) { + let name = allLinks.size === 1 ? '百度#1' : '百度-' + k.split('/').pop(); + let urls = share[k].map(v => { + let sizeStr = v.formatted_size || (v.size ? formatFileSize(v.size) : ''); + return `${v.name}${sizeStr ? ' 【' + sizeStr + '】' : ''}$${[v.path, v.uk, v.shareid, v.fsid].join('*')}`; }).join('#'); - } else { - playUrl = "资源已经失效,请访问其他资源"; + let pics = share[k].map(v => v.thumbnail || '').join('#'); + playSources.push({name, urls, pics, pan: link, type: '百度'}); } - allLines.push({ name: lineName, url: playUrl, type: '阿里' }); - panCounters.阿里++; - } + }); + } + } else if (/\.alipan/.test(link)) { + let share = await Ali.getShareData(link); + if (!share) continue; + let videos = await Ali.getFilesByShareUrl(share); + if (videos && videos.length > 0) { + let name = '阿里#' + counters.阿里++; + let urls = videos.map(v => { + let sizeStr = v.formatted_size || (v.size ? formatFileSize(v.size) : ''); + return `${v.name}${sizeStr ? ' 【' + sizeStr + '】' : ''}$${[v.share_id, v.file_id, v.subtitle?.file_id || ''].join('*')}`; + }).join('#'); + let pics = videos.map(v => v.thumbnail || '').join('#'); + playSources.push({name, urls, pics, pan: link, type: '阿里'}); } } + } + + // 按照 line_order 排序 + if (playSources.length > 0) { + // 创建类型优先级映射 + const typePriority = {}; + rule.line_order.forEach((type, index) => { + typePriority[type] = index; + }); - allLines.sort((a, b) => { - let aIndex = rule.line_order.indexOf(a.type); - let bIndex = rule.line_order.indexOf(b.type); - if (aIndex === -1) aIndex = Infinity; - if (bIndex === -1) bIndex = Infinity; - return aIndex - bIndex; + playSources.sort((a, b) => { + const priorityA = typePriority[a.type] !== undefined ? typePriority[a.type] : 999; + const priorityB = typePriority[b.type] !== undefined ? typePriority[b.type] : 999; + return priorityA - priorityB; }); - playform = allLines.map(line => line.name); - playurls = allLines.map(line => line.url); + let playform = playSources.map(s => s.name); + let playurls = playSources.map(s => s.urls); + let playPics = playSources.map(s => s.pics); + let playPans = playSources.map(s => s.pan); + vod.vod_play_from = playform.join("$$$"); vod.vod_play_url = playurls.join("$$$"); + vod.vod_play_pic = playPics.join('$$$'); + vod.vod_play_pic_ratio = 1.0; vod.vod_play_pan = playPans.join("$$$"); - - return vod; - } catch (error) { - return { - vod_name: '加载失败', - type_name: '错误', - vod_pic: '', - vod_content: `加载失败: ${error.message}`, - vod_remarks: '请检查网络连接或配置是否正确', - vod_play_from: '加载错误$$$所有链接无效', - vod_play_url: `错误详情: ${error.message}$$$建议重试或联系维护者`, - vod_play_pan: '' - }; } + + return vod; }, - - 搜索: async function(wd, quick, pg) { - let { host, input, pdfa, pdfh, pd } = this; - - let url = rule_type ? + + 搜索: async function (wd, quick, pg) { + let {host, input, pdfa, pdfh, pd} = this; + let url = rule_type ? `${host}/vodsearch/${wd}----------${pg}---.html` : `${host}/index.php/vod/search/page/${pg}/wd/${wd}.html`; - - let d = []; + let html = await request(url); - let data = pdfa(html, '.module-items .module-search-item'); - data.forEach(it => { + let d = []; + let items = pdfa(html, '.module-items .module-search-item') || []; + + items.forEach(it => { let title = pdfh(it, '.video-info&&a&&title'); - let desc = pdfh(it, '.video-serial&&Text'); - let content = pdfh(it, '.video-info-item:eq(2)&&Text').replace(/(bsp;)|(&n.*?)|( )|(\s+)/gi, ''); - if (rule.search_match && !title.includes(wd)) { - return; - } - + if (rule.search_match && !title.includes(wd)) return; d.push({ title, img: pd(it, 'img&&data-src'), - desc: desc, - content: content, + desc: pdfh(it, '.video-serial&&Text'), + content: pdfh(it, '.video-info-item:eq(2)&&Text').replace(/(bsp;)|(&n.*?)|( )|(\s+)/gi, ''), url: pd(it, '.video-info&&a&&href') }); }); - return setResult(d); }, + lazy: async function (flag, id, flags) { - let { input, mediaProxyUrl } = this; + let {input, mediaProxyUrl} = this; let ids = input.split('*'); let urls = []; let UCDownloadingCache = {}; let UCTranscodingCache = {}; if (flag.startsWith('夸克')) { - let down = await Quark.getDownload(ids[0], ids[1], ids[2], ids[3], true); - let headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', - 'origin': 'https://pan.quark.cn', - 'referer': 'https://pan.quark.cn/', - 'Cookie': Quark.cookie + console.log("夸克网盘解析开始"); + const headers = { + 'Cookie': ENV.get('quark_cookie') }; - urls.push("原画", down.download_url + '#fastPlayMode##threads=10#'); - urls.push( - "原代服", - mediaProxyUrl + `?thread=${ENV.get('thread') || 6}&form=urlcode&randUa=1&url=` + - encodeURIComponent(down.download_url) + '&header=' + encodeURIComponent(JSON.stringify(headers)) - ); - if (ENV.get('play_local_proxy_type', '1') === '2') { - urls.push( - "原代本", - `http://127.0.0.1:7777/?thread=${ENV.get('thread') || 6}&form=urlcode&randUa=1&url=` + - encodeURIComponent(down.download_url) + '&header=' + encodeURIComponent(JSON.stringify(headers)) - ); - } else { - urls.push( - "原代本", - `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=256&url=` + - encodeURIComponent(down.download_url) - ); - } - let transcoding = (await Quark.getLiveTranscoding(ids[0], ids[1], ids[2], ids[3])).filter((t) => t.accessable); - transcoding.forEach((t) => { - let res = t.resolution === 'low' ? "流畅" : - t.resolution === 'high' ? "高清" : - t.resolution === 'super' ? "超清" : - t.resolution === 'dolby_vision' ? "HDR" : "4K"; - urls.push(res, t.video_info.url); + + // 始终获取基础链接 + const link = await Quark.getUrl(ids[0], ids[1], ids[2], ids[3]); + link.forEach(item => { + if (item !== undefined) { + urls.push("无限" + item.name, item.url + "#isVideo=true##fastPlayMode##threads=20#") + urls.push("无限猫" + item.name, `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=256&url=` + encodeURIComponent(item.url) + '&header=' + encodeURIComponent(JSON.stringify(headers))); + } }); - + + // 根据 quark_transfer 配置决定是否获取下载和转码链接 + if (rule.quark_transfer) { + console.log("夸克网盘获取下载和转码链接"); + + // 获取下载链接 + const down = await Quark.getDownload(ids[0], ids[1], ids[2], ids[3], true); + down.forEach((t) => { + if (t.url !== undefined) { + urls.push(t.name, t.url + "#isVideo=true##fastPlayMode##threads=20#") + urls.push("猫" + t.name, `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=1024&url=` + encodeURIComponent(t.url)); + } + }); + + // 获取转码链接 + const transcoding = (await Quark.getLiveTranscoding(ids[0], ids[1], ids[2], ids[3])).filter((t) => t.accessable); + transcoding.forEach((t) => { + urls.push(t.resolution === 'low' ? "流畅" : t.resolution === 'high' ? "高清" : t.resolution === 'super' ? "超清" : t.resolution, t.video_info.url + "#isVideo=true##fastPlayMode##threads=20#") + }); + } + return { parse: 0, url: urls, header: headers }; - } else if (flag.startsWith('优汐')) { - let down = await UC.getDownload(ids[0], ids[1], ids[2], ids[3], true); - down.forEach(t => { - let res = t.name === 'low' ? "流畅" : - t.name === 'high' ? "高清" : - t.name === 'super' ? "超清" : - t.name === 'dolby_vision' ? "HDR" : "4K"; - urls.push(res, `${t.url}`); - }); - - return { parse: 0, url: urls }; + } else if (flag.startsWith('UC')) { + console.log("UC网盘解析开始"); + if (!UCDownloadingCache[ids[1]]) { + let down = await UC.getDownload(ids[0], ids[1], ids[2], ids[3], true); + if (down) UCDownloadingCache[ids[1]] = down; + } + let downCache = UCDownloadingCache[ids[1]]; + return await UC.getLazyResult(downCache, mediaProxyUrl); } else if (flag.startsWith('移动')) { + console.log("移动网盘解析开始"); let url = await Yun.getSharePlay(ids[0], ids[1]); return { url: `${url}` }; } else if (flag.startsWith('天翼')) { + console.log("天翼网盘解析开始"); let url = await Cloud.getShareUrl(ids[0], ids[1]); return { url: `${url}` }; } else if (flag.startsWith('123')) { + console.log("123网盘解析开始"); let url = await Pan.getDownload(ids[0], ids[1], ids[2], ids[3], ids[4]); urls.push("原画", url); return { @@ -599,6 +535,7 @@ var rule = { SD: "540 标清", LD: "360 流畅" }; + console.log("阿里网盘解析开始"); const down = await Ali.getDownload(ids[0], ids[1], flag === 'down'); urls.push("原画", down.url + "#isVideo=true##ignoreMusic=true#"); urls.push("极速原画", down.url + "#fastPlayMode##threads=10#"); @@ -617,11 +554,12 @@ var rule = { } }; } else if (flag.startsWith('百度')) { + console.log("百度网盘开始解析"); let url = await Baidu2.getAppShareUrl(ids[0], ids[1], ids[2], ids[3]); urls.push("原画", url + "#isVideo=true##fastPlayMode##threads=10#"); urls.push( - "原代本", - `http://127.0.0.1:7777/?thread=${ENV.get('thread') || 6}&form=urlcode&randUa=1&url=` + + "原代本", + `http://127.0.0.1:7777/?thread=${ENV.get('thread') || 6}&form=urlcode&randUa=1&url=` + encodeURIComponent(url) ); return { @@ -633,4 +571,14 @@ var rule = { }; } } +} + +function formatFileSize(bytes) { + if (!bytes) return '0 B'; + let units = ['B', 'KB', 'MB', 'GB', 'TB'], i = 0; + while (bytes >= 1024 && i < 4) { + bytes /= 1024; + i++; + } + return bytes.toFixed(2) + ' ' + units[i]; } \ No newline at end of file diff --git "a/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" "b/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" index 17af5d19..8f728a3d 100644 --- "a/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" +++ "b/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" @@ -4,6 +4,7 @@ filterable: 0, quickSearch: 0, title: '设置中心', + isProxyPath: true, logo: 'https://avatars.githubusercontent.com/u/49803097?v=4', more: { sourceTag: '设置,动作', @@ -65,6 +66,7 @@ let quick_data = { 阿里: 'https://www.alipan.com/s/vgXMcowK8pQ', 天翼: 'https://cloud.189.cn/web/share?code=INJbU3NbqyUj', 百度: 'https://pan.baidu.com/s/1L0UIv4p0X0QrbbKErJuc_w?pwd=2pwj', + 迅雷: 'https://pan.xunlei.com/s/VOkBwLBNoXN8eO9WrcVbXdTcA1?pwd=8tvj#', 移动1: 'https://yun.139.com/shareweb/#/w/i/0i5CLQ7BpV7Ai', 移动2: 'https://caiyun.139.com/m/i?2jexC1gcjeN7q', 移动3: 'https://yun.139.com/shareweb/#/w/i/2i2MoE9ZHn9p1', @@ -72,6 +74,7 @@ let quick_data = { 直链1: 'https://vdse.bdstatic.com//628ca08719cef5987ea2ae3c6f0d2386.mp4', 嗅探1: 'https://www.6080kk.cc/haokanplay/178120-1-1.html', 嗅探2: 'https://www.hahads.com/play/537106-3-1.html', + 央视跨源: 'cctv://3c18e2b3bba249b78b831e910608cfec', 多集: 'https://v.qq.com/x/cover/m441e3rjq9kwpsc/m00253deqqo.html@https://pan.quark.cn/s/6c8158e258f3@https://pan.baidu.com/s/1TdbgcwaMG1dK7B5pQ1LbBg?pwd=1234', 海阔二级单线路: gzip(JSON.stringify({ "actor": "剧集", @@ -121,11 +124,13 @@ var rule = { 类型: '设置', title: '设置中心', 推荐: async function () { - let {publicUrl} = this; + let {publicUrl, requestHost} = this; // log('publicUrl:', publicUrl); let setIcon = urljoin(publicUrl, './images/icon_cookie/设置.png'); let searchIcon = urljoin(publicUrl, './images/icon_cookie/搜索.jpg'); let chatIcon = urljoin(publicUrl, './images/icon_cookie/chat.webp'); + let drpysIcon = urljoin(publicUrl, './images/drpys.png'); + let drpyshIcon = urljoin(publicUrl, './images/drpysh.png'); const data = deepCopy(action_data); data.push({ vod_id: JSON.stringify({ @@ -141,6 +146,29 @@ var rule = { vod_pic: searchIcon, vod_tag: 'action', }); + data.unshift({ + vod_id: JSON.stringify({ + actionId: 'browser', + type: 'browser', + title: 'DS仓库', + url: 'https://repo.tvshare.cn/', + }), + vod_name: 'DS仓库', + vod_pic: drpyshIcon, + vod_tag: 'action' + }); + data.unshift({ + vod_id: JSON.stringify({ + actionId: 'browser', + type: 'browser', + title: '后台管理', + url: requestHost + '/apps/admin', + header: {'Authorization': 'Basic YWRtaW46ZHJweXM='}, + }), + vod_name: '后台管理', + vod_pic: drpysIcon, + vod_tag: 'action' + }); data.forEach(it => { if (!it.vod_pic) { it.vod_pic = setIcon; diff --git "a/spider/js_dr2/\346\234\250\345\205\256[\344\274\230].js" "b/spider/js_dr2/\346\234\250\345\205\256[\344\274\230].js" new file mode 100644 index 00000000..096a36bf --- /dev/null +++ "b/spider/js_dr2/\346\234\250\345\205\256[\344\274\230].js" @@ -0,0 +1,295 @@ +/* +@header({ + searchable: 2, + filterable: 0, + quickSearch: 1, + title: '木兮', + 类型: '影视', + lang: 'dr2', +}) +*/ + +function i4e(url, timestamp, session, traceId) { + // 1. 获取 URL 的路径部分(去除查询参数) + let hh = `${rule.host}/api`; + let path = url.split("?")[0].replace(hh, ''); + + // 2. 构造盐值 (Salt) + let salt = "symx_" + session; + + // 3. 构造映射对象 + let mapObj = { + p: path, + t: timestamp, + s: salt + }; + + // 4. 根据 traceId 构造原始 Payload 字符串 + let payload = traceId.split("").map(char => mapObj[char]).join(""); + + // 5. 对 Payload 进行字符替换混淆 + payload = payload + .replaceAll("1", "i") + .replaceAll("0", "o") + .replaceAll("5", "s"); + + // 6. 使用 session 作为密钥,对 payload 进行 HmacSHA256 加密并转为字符串 + return CryptoJS.HmacSHA256(payload, session).toString(); +} + +function decrypt(data) { + let key = "0x1A2B3C4D5E6F7A8B9C"; + let output = ""; + + for (let i = 0; i < data.length; i += 2) { + let hexChar = data.substr(i, 2); + let intVal = parseInt(hexChar, 16); + let charCode = intVal ^ key.charCodeAt((i / 2) % key.length); + output += String.fromCharCode(charCode); + } + + return output; +} + +function gettime(params) { + var prefix = params.substring(0, 12); + var sum = 0; + for (var i = 0; i < prefix.length; i++) { + sum += parseInt(prefix.charAt(i), 10); + } + var checkDigit = sum % 10; + var result = prefix + checkDigit.toString(); + return result; +} + +globalThis.i4e = i4e; +globalThis.decrypt = decrypt; +globalThis.gettime = gettime; + +var rule = { + title: '木兮', + host: 'https://film.symx.club', + url: '/api/film/category/list?fyfilter', + detailUrl: '/api/film/detail/play?filmId=fyid', + searchUrl: '/api/film/search?keyword=**&pageNum=fypage&pageSize=10', + filter_url: 'categoryId=fyclass&language={{fl.lang}}&pageNum=fypage&pageSize=15&sort={{fl.by or "updateTime"}}&year={{fl.year}}', + searchable: 2, + quickSearch: 1, + filterable: 0, + headers: { + 'User-Agent': 'SYMX_ANDROID', + 'x-platform': 'android' + }, + play_parse: true, + search_match: true, + class_name: '电视剧&电影&综艺&动漫&短剧', + class_url: '1&2&3&4&5', + 预处理: $js.toString(() => { + let result = reqCookie(`${rule.host}/api/stats/track`, { + method: 'GET', + headers: { + 'User-Agent': 'SYMX_ANDROID', + 'x-platform': 'android', + 'referer': `${rule.host}/m/index` + } + }, false); + console.log(result.cookie); + rule.cookies = result.cookie; + rule.headers["cookie"] = result.cookie; + + let result2 = request(`${rule.host}/api/system/config`, { + method: 'GET', + headers: { + 'User-Agent': 'SYMX_ANDROID', + 'x-platform': 'android', + 'cookie': rule.cookies, + 'referer': `${rule.host}/` + } + }); + let securityConfig = JSON.parse(result2).data; + rule.reportId = decrypt(securityConfig.reportId); + log("rule.reportId>>>>>" + rule.reportId); + rule.session = decrypt(securityConfig.session); + log("rule.session>>>>>" + rule.session); + rule.traceId = decrypt(securityConfig.traceId); + log("rule.traceId>>>>>" + rule.traceId); + }), + 推荐: $js.toString(() => { + let d = []; + let html = request(input + '/api/film/category'); + let categories = JSON.parse(html).data; + categories.forEach(category => { + category.filmList.forEach(item => { + let title = item.name; + if (!/名称|排除/.test(title)) { + d.push({ + title: title, + desc: item.updateStatus, + img: item.cover, + url: item.id, + content: item.blurb, + }); + } + }); + }); + setResult(d); + }), + 一级: $js.toString(() => { + let d = []; + let html = request(input); + let data = JSON.parse(html).data.list; + data.forEach(item => { + let title = item.name; + if (!/名称|排除/.test(title)) { + d.push({ + title: title, + desc: item.updateStatus, + img: item.cover, + url: item.id, + content: item.blurb, + }); + } + }); + setResult(d); + }), + + 二级: $js.toString(() => { + let timestamp = Date.now(); + log("timestamp>>>>>" + timestamp); + log("input>>>>>" + input); + let sign = i4e(input, timestamp, rule.session, rule.traceId); + let html = request(input, { + headers: { + 'User-Agent': 'SYMX_ANDROID', + 'x-platform': 'android', + 'cookie': rule.cookies, + [rule.reportId]: sign, + 'x-timestamp': timestamp, + 'referer': `${rule.host}` + }, + method: 'GET' + }); + log("html>>>>>" + html) + + let data = JSON.parse(html).data; + + rule.cid = data.categoryId; + rule.filmid = data.id; + + // 定义类型映射 + let categoryMap = { + 1: "电视剧", + 2: "电影", + 3: "综艺", + 4: "动漫", + 5: "短剧" + }; + + let categoryName = categoryMap[data.categoryId]; + VOD = { + vod_id: data.id, + vod_name: data.name, + type_name: categoryName, + vod_pic: data.cover, + vod_remarks: data.updateStatus, + vod_content: data.blurb + }; + + let playlist = data.playLineList || []; + let playFrom = []; + let playUrl = []; + + playlist.forEach(line => { + playFrom.push(line.playerName); + let lines = line.lines || []; + let lineUrls = lines.map(tag => { + let title = tag.name; + let url = tag.id; + return `${title}$${url}@${url}`; + }); + playUrl.push(lineUrls.join("#")); + }); + + VOD.vod_play_from = playFrom.join("$$$"); + VOD.vod_play_url = playUrl.join("$$$"); + }), + + 搜索: $js.toString(() => { + let d = []; + + let timestamp = new Date().getTime().toString(); + timestamp = gettime(timestamp); + log("timestamp>>>>>" + timestamp); + let sign = i4e(input, timestamp, rule.session, rule.traceId); + let html = request(input, { + headers: { + 'User-Agent': 'SYMX_ANDROID', + 'Accept': 'application/json, text/plain, */*', + 'x-platform': 'android', + 'x-timestamp': timestamp, + [rule.reportId]: sign, + 'referer': `${rule.host}/m/search?keyword=${encodeURIComponent(KEY)}`, + 'cookie': rule.cookies + }, + method: 'GET' + }); + + let data = JSON.parse(html).data.list; + data.forEach(item => { + let title = item.name; + d.push({ + title: title, + desc: item.updateStatus, + img: item.cover, + url: item.id, + content: item.blurb, + }); + }); + setResult(d); + }), + lazy: $js.toString(() => { + let linesid = input.split('@')[1]; + let purl1 = `${rule.host}/api/danmaku?filmId=${rule.filmid}&index=${rule.cid}&lineId=${linesid}`; + let timestamp1 = new Date().getTime().toString(); + timestamp1 = gettime(timestamp1); + let sign1 = i4e(purl1, timestamp1, rule.session, rule.traceId); + let html1 = request(purl1, { + headers: { + 'User-Agent': 'SYMX_ANDROID', + 'Accept': 'application/json, text/plain, */*', + 'x-platform': 'android', + 'x-timestamp': timestamp1, + [rule.reportId]: sign1, + 'referer': `${rule.host}/m/player?cid=${rule.cid}&film_id=${rule.filmid}&line_id=${linesid}`, + 'cookie': rule.cookies + }, + method: 'GET' + }); + + let purl = `${rule.host}/api/line/play/parse?lineId=${linesid}`; + + let timestamp = new Date().getTime().toString(); + timestamp = gettime(timestamp); + log("timestamp>>>>>" + timestamp); + let sign = i4e(purl, timestamp, rule.session, rule.traceId); + let html = request(purl, { + headers: { + 'User-Agent': 'SYMX_ANDROID', + 'Accept': 'application/json, text/plain, */*', + 'x-platform': 'android', + 'x-timestamp': timestamp, + [rule.reportId]: sign, + 'referer': `${rule.host}/m/player?cid=${rule.cid}&film_id=${rule.filmid}&line_id=${linesid}`, + 'cookie': rule.cookies + }, + method: 'GET' + }); + + let url = JSON.parse(html).data; + input = { + parse: 0, + url: url + }; + }), + +} \ No newline at end of file diff --git a/spider/py/data/bili_config.json b/spider/py/data/bili_config.json index 297e65af..a3ecd149 100644 --- a/spider/py/data/bili_config.json +++ b/spider/py/data/bili_config.json @@ -2,9 +2,9 @@ "users": { "fake": { "cookies_dic": { - "buvid3": "C388E051-8B09-CBB4-D24F-553E939CBA0568463infoc", - "b_nut": "1758067368", - "__at_once": "4811634013224838281" + "buvid3": "43B433F6-257E-682E-49FB-77BD7E3F5D5117302infoc", + "b_nut": "1773463317", + "__at_once": "845925766005833919" } } }, @@ -28,7 +28,7 @@ "v": "2_878" }, { - "n": "CS:GO", + "n": "CS2", "v": "2_89" }, { @@ -47,6 +47,10 @@ "n": "守望先锋", "v": "2_87" }, + { + "n": "lol云顶之弈", + "v": "2_260" + }, { "n": "DOTA2", "v": "2_92" @@ -71,13 +75,17 @@ "n": "炉石传说", "v": "2_91" }, + { + "n": "失落星船:马拉松", + "v": "2_1048" + }, { "n": "解限机", "v": "2_915" }, { - "n": "界外狂潮", - "v": "2_941" + "n": "终极角逐(The Finals)", + "v": "2_846" }, { "n": "彩虹六号", @@ -143,6 +151,14 @@ "n": "最终幻想14", "v": "2_102" }, + { + "n": "无烬战争", + "v": "2_1015" + }, + { + "n": "午夜行者", + "v": "2_1044" + }, { "n": "命运扳机", "v": "2_998" @@ -291,6 +307,10 @@ "n": "黑色沙漠", "v": "2_632" }, + { + "n": "VRChat", + "v": "2_656" + }, { "n": "天涯明月刀", "v": "2_596" @@ -351,6 +371,10 @@ "n": "堡垒之夜", "v": "2_164" }, + { + "n": "ARC Raiders", + "v": "2_1023" + }, { "n": "失控进化", "v": "2_1008" @@ -408,8 +432,8 @@ "v": "2_909" }, { - "n": "终极角逐(The Finals)", - "v": "2_846" + "n": "界外狂潮", + "v": "2_941" }, { "n": "DeadLock", @@ -418,6 +442,14 @@ { "n": "其他射击", "v": "2_953" + }, + { + "n": "逆战:未来", + "v": "2_1036" + }, + { + "n": "HighGuard", + "v": "2_1037" } ] } @@ -436,6 +468,10 @@ "n": "和平精英", "v": "3_256" }, + { + "n": "明日方舟:终末地", + "v": "3_848" + }, { "n": "绝区零", "v": "3_662" @@ -456,18 +492,26 @@ "n": "崩坏:星穹铁道", "v": "3_549" }, + { + "n": "二重螺旋", + "v": "3_981" + }, { "n": "火影忍者手游", "v": "3_292" }, { - "n": "崩坏:因缘精灵", - "v": "3_1011" + "n": "王者荣耀世界", + "v": "3_1033" }, { "n": "鸣潮", "v": "3_874" }, + { + "n": "星布谷地", + "v": "3_1028" + }, { "n": "明日方舟", "v": "3_255" @@ -476,10 +520,26 @@ "n": "异环", "v": "3_940" }, + { + "n": "超自然行动组", + "v": "3_1017" + }, { "n": "无限暖暖", "v": "3_892" }, + { + "n": "星塔旅人", + "v": "3_1024" + }, + { + "n": "境·界 刀鸣", + "v": "3_1029" + }, + { + "n": "王者万象棋", + "v": "3_1034" + }, { "n": "航海王壮志雄心", "v": "3_902" @@ -520,6 +580,14 @@ "n": "三国:谋定天下", "v": "3_871" }, + { + "n": "三国:百将牌", + "v": "3_1021" + }, + { + "n": "命运:群星", + "v": "3_1022" + }, { "n": "伊莫", "v": "3_994" @@ -532,17 +600,25 @@ "n": "鹅鸭杀手游", "v": "3_993" }, + { + "n": "粒粒的小人国", + "v": "3_1051" + }, { "n": "NBA2K手游", "v": "3_959" }, { - "n": "奥特曼:超时空英雄", - "v": "3_999" + "n": "漫威秘法狂潮", + "v": "3_1019" }, { - "n": "二重螺旋", - "v": "3_981" + "n": "三国:天下归心", + "v": "3_1035" + }, + { + "n": "奥特曼:超时空英雄", + "v": "3_999" }, { "n": "影之诗", @@ -552,10 +628,6 @@ "n": "永远的蔚蓝星球", "v": "3_990" }, - { - "n": "逆战:未来", - "v": "3_1007" - }, { "n": "仙剑世界", "v": "3_950" @@ -568,6 +640,10 @@ "n": "最终幻想14水晶世界", "v": "3_982" }, + { + "n": "源序空间", + "v": "3_1016" + }, { "n": "异人之下", "v": "3_956" @@ -576,6 +652,14 @@ "n": "洛克王国:世界", "v": "3_958" }, + { + "n": "奥星热浪", + "v": "3_1042" + }, + { + "n": "卡厄思梦境", + "v": "3_1045" + }, { "n": "银与绯", "v": "3_968" @@ -664,10 +748,26 @@ "n": "剑与骑士团", "v": "3_921" }, + { + "n": "龙迹之城", + "v": "3_1046" + }, + { + "n": "三国群英传:策定九州", + "v": "3_1018" + }, { "n": "决胜巅峰", "v": "3_947" }, + { + "n": "杖剑传说", + "v": "3_1032" + }, + { + "n": "吉星派对", + "v": "3_1039" + }, { "n": "望月", "v": "3_944" @@ -728,6 +828,10 @@ "n": "萤火突击", "v": "3_870" }, + { + "n": "仙遇手游", + "v": "3_1038" + }, { "n": "月圆之夜", "v": "3_215" @@ -784,6 +888,10 @@ "n": "光遇", "v": "3_687" }, + { + "n": "嘟嘟脸恶作剧", + "v": "3_1031" + }, { "n": "以闪亮之名", "v": "3_755" @@ -976,6 +1084,10 @@ "n": "小动物之星", "v": "3_473" }, + { + "n": "名将杀", + "v": "3_1041" + }, { "n": "天地劫:幽城再临", "v": "3_448" @@ -1074,9 +1186,33 @@ "v": "6_276" }, { - "n": "战地风云", + "n": "生化危机", + "v": "6_721" + }, + { + "n": "杀戮尖塔2", + "v": "6_1050" + }, + { + "n": "仁王3", + "v": "6_313" + }, + { + "n": "战地风云6", "v": "6_597" }, + { + "n": "逃离鸭科夫", + "v": "6_977" + }, + { + "n": "使命召唤22", + "v": "6_282" + }, + { + "n": "暗黑破坏神Ⅳ", + "v": "6_780" + }, { "n": "无主之地4", "v": "6_1012" @@ -1098,7 +1234,7 @@ "v": "6_976" }, { - "n": "刺客信条:影", + "n": "刺客信条", "v": "6_227" }, { @@ -1106,7 +1242,7 @@ "v": "6_951" }, { - "n": "怪物猎人:荒野", + "n": "怪物猎人", "v": "6_578" }, { @@ -1121,24 +1257,12 @@ "n": "命运2", "v": "6_277" }, - { - "n": "矩阵:零日危机", - "v": "6_996" - }, - { - "n": "使命召唤21", - "v": "6_282" - }, - { - "n": "禁闭求生2", - "v": "6_1010" - }, { "n": "最后纪元", "v": "6_877" }, { - "n": "消逝的光芒:困兽", + "n": "消逝的光芒", "v": "6_586" }, { @@ -1189,6 +1313,10 @@ "n": "全境封锁2", "v": "6_243" }, + { + "n": "FC26", + "v": "6_830" + }, { "n": "植物大战僵尸", "v": "6_309" @@ -1197,10 +1325,6 @@ "n": "雀魂麻将", "v": "6_803" }, - { - "n": "生化危机", - "v": "6_721" - }, { "n": "格斗游戏", "v": "6_433" @@ -1221,10 +1345,6 @@ "n": "策略游戏", "v": "6_570" }, - { - "n": "暗黑破坏神Ⅳ", - "v": "6_780" - }, { "n": "宝可梦集换式卡牌游戏", "v": "6_720" @@ -1257,10 +1377,6 @@ "n": "Dark and Darker", "v": "6_795" }, - { - "n": "仁王2", - "v": "6_313" - }, { "n": "只狼", "v": "6_245" @@ -1269,10 +1385,6 @@ "n": "暗黑破坏神", "v": "6_535" }, - { - "n": "FC25", - "v": "6_830" - }, { "n": "以撒", "v": "6_219" @@ -1368,6 +1480,10 @@ { "n": "致命公司", "v": "6_858" + }, + { + "n": "魔法工艺", + "v": "6_936" } ] } @@ -1405,6 +1521,10 @@ { "n": "虚拟PK", "v": "9_775" + }, + { + "n": "虚拟VRchat", + "v": "9_1049" } ] } @@ -1469,13 +1589,13 @@ "key": "tid", "name": "赛事", "value": [ - { - "n": "赛事综合", - "v": "13_563" - }, { "n": "游戏赛事", "v": "13_561" + }, + { + "n": "赛事综合", + "v": "13_563" } ] } diff --git a/utils/admin/logReader.js b/utils/admin/logReader.js new file mode 100644 index 00000000..f49c399a --- /dev/null +++ b/utils/admin/logReader.js @@ -0,0 +1,27 @@ +import fs from '../fsWrapper.js'; +import path from 'path'; + +export async function readLogLines(lines = 50) { + const logDir = path.join(process.cwd(), 'logs'); + + if (!await fs.pathExists(logDir)) { + return { file: null, content: '日志目录不存在' }; + } + + const files = await fs.readdir(logDir); + const logFiles = files + .filter(f => f.endsWith('.log.txt')) + .sort() + .reverse(); + + if (logFiles.length === 0) { + return { file: null, content: '没有日志文件' }; + } + + const latestLog = path.join(logDir, logFiles[0]); + const content = await fs.readFile(latestLog, 'utf-8'); + const allLines = content.trim().split('\n'); + const lastLines = allLines.slice(-lines); + + return { file: logFiles[0], content: lastLines.join('\n'), lastLines }; +} diff --git a/utils/api_helper.js b/utils/api_helper.js index 936b85d8..498ed073 100644 --- a/utils/api_helper.js +++ b/utils/api_helper.js @@ -39,11 +39,15 @@ export function startJsonWatcher(ENGINES, jsonDir) { // 清理已完成的计时器 debounceTimers.delete(filename); }, 100); // 100ms防抖延迟 + if (timer.unref) timer.unref(); debounceTimers.set(filename, timer); } }); + // 允许监听器不阻止进程退出 + if (jsonWatcher.unref) jsonWatcher.unref(); + // console.log(`start json file hot reload success,listening path: ${jsonDir}`); } catch (error) { console.error('start json file listening failed with error:', error); diff --git a/utils/dns_doh.js b/utils/dns_doh.js index d459ee8d..89fc53e3 100644 --- a/utils/dns_doh.js +++ b/utils/dns_doh.js @@ -1,12 +1,11 @@ /** * DNS over HTTPS (DOH) Utility Module * - * Uses 'dns-over-http-resolver' package for robust DOH resolution. + * Uses direct HTTP requests for robust DOH resolution. * Reads configuration from config/player.json. * Automatically detects system proxy (Env vars or Windows Registry) to bypass local DNS pollution. */ -import DnsOverHttpResolver from 'dns-over-http-resolver'; import axios from 'axios'; import https from 'https'; import fs from 'fs'; @@ -20,21 +19,20 @@ import {ENV} from './env.js'; // Import ENV utility const execAsync = util.promisify(exec); const __dirname = path.dirname(fileURLToPath(import.meta.url)); -// DOH Configuration and Resolver Lazy Init +// DOH Configuration let dohServers = null; -let resolver = null; const configPath = path.resolve(__dirname, '../config/player.json'); -// Initialize Resolver Lazy -function getResolver() { +// Initialize Servers Lazy +function getDohServers() { // Check if DOH is enabled via ENV (default: 0/false) const enableDoh = ENV.get('enable_doh', '0') === '1' || ENV.get('enable_doh') === 'true'; if (!enableDoh) { // console.log('[DOH] DOH is disabled via ENV.'); - return null; + return []; } - if (resolver) return resolver; + if (dohServers) return dohServers; try { // Load config if not loaded if (!dohServers) { @@ -50,20 +48,11 @@ function getResolver() { console.error('[DOH] Failed to load DOH config:', e.message); } } - - resolver = new DnsOverHttpResolver({ - maxCache: 1000, - request: customRequest - }); - - if (dohServers && dohServers.length > 0) { - resolver.setServers(dohServers); - } } catch (e) { console.error('[DOH] Init failed:', e.message); - return null; + return []; } - return resolver; + return dohServers || []; } // Proxy Detection Logic @@ -202,14 +191,13 @@ export function getSystemProxy() { } // Custom request function using axios -const customRequest = async (resource, signal) => { +const customRequest = async (resource) => { try { const proxy = await getSystemProxy(); const config = { headers: { 'Accept': 'application/dns-json' }, - signal: signal, timeout: 5000 }; @@ -227,10 +215,6 @@ const customRequest = async (resource, signal) => { } }; -// Initialize Resolver - REMOVED top-level init -// const resolver = new DnsOverHttpResolver({ ... }); -// if (dohServers.length > 0) { resolver.setServers(dohServers); } - /** * Resolve domain using DOH * @param {string} domain @@ -243,12 +227,29 @@ export async function resolveDoh(domain) { if (domain === 'localhost' || domain === '127.0.0.1') return domain; try { - const resolver = getResolver(); - if (!resolver) return null; + const servers = getDohServers(); + if (!servers || servers.length === 0) return null; - const ips = await resolver.resolve(domain, 'A'); - if (ips && ips.length > 0) { - return ips[0]; + for (const server of servers) { + try { + // Construct URL + const url = new URL(server); + url.searchParams.set('name', domain); + url.searchParams.set('type', 'A'); + + const data = await customRequest(url.toString()); + + // Parse JSON response + // Format: https://developers.google.com/speed/public-dns/docs/doh/json + if (data && data.Status === 0 && data.Answer) { + for (const ans of data.Answer) { + if (ans.type === 1) return ans.data; // Type 1 is A record + } + } + } catch (e) { + // Try next server + continue; + } } } catch (e) { // console.error(`[DOH] Failed to resolve ${domain}:`, e.message); diff --git a/utils/fileHeaderManager.js b/utils/fileHeaderManager.js index c13a9901..f327cc62 100644 --- a/utils/fileHeaderManager.js +++ b/utils/fileHeaderManager.js @@ -1,6 +1,7 @@ // fileHeaderManager.js import fs from 'fs/promises'; import path from 'path'; +import '../libs_drpy/_dist/json5.js'; class FileHeaderManager { static COMMENT_CONFIG = { @@ -21,26 +22,117 @@ class FileHeaderManager { headerRegex: /@header\(([\s\S]*?)\)/, createComment: (content) => `"""\n${content}\n"""`, topCommentsRegex: /^(\s*(#[^\n]*\n|'''[\s\S]*?'''|"""[\s\S]*?""")\s*)+/ + }, + '.php': { + start: '/*', + end: '*/', + // PHP 文件通常以 `/*\n${content}\n*/`, + topCommentsRegex: /(<\?php\s*)?(\s*(\/\/[^\n]*\n|\/\*[\s\S]*?\*\/)\s*)+/ } }; + + /** + * Find the @header(...) block in the comment text + * Optimized state machine for parsing nested structures + * @param {string} text Comment text + * @param {string} ext File extension (.js or .py) + * @returns {Object|null} { start, end, content } + */ + static findHeaderBlock(text, ext) { + const startMarker = '@header('; + const startIndex = text.indexOf(startMarker); + if (startIndex === -1) return null; + + let index = startIndex + startMarker.length; + let balance = 1; + const len = text.length; + + // Fast scan loop + while (index < len) { + const char = text[index]; + + // 1. String literal detection (Most common content inside JSON) + if (char === '"' || char === "'") { + const quote = char; + index++; + while (index < len) { + const c = text[index]; + if (c === '\\') { + index += 2; // Skip escaped char + } else if (c === quote) { + index++; // Include closing quote + break; // End of string + } else { + index++; + } + } + continue; // Continue outer loop + } + // 2. Parentheses balance + else if (char === '(') { + balance++; + } else if (char === ')') { + balance--; + if (balance === 0) { + return { + start: startIndex, + end: index + 1, + content: text.substring(startIndex + startMarker.length, index) + }; + } + } + // 3. Comments skipping (Only if strictly needed inside header object, usually standard JSON doesn't have comments but JS objects might) + // Optimization: Assume standard JSON5/JS object format inside @header, check for comments only if / or # encountered + else if (char === '/') { + const next = text[index + 1]; + if (next === '/') { // Line comment + index += 2; + const newline = text.indexOf('\n', index); + index = newline === -1 ? len : newline; + continue; + } else if (next === '*') { // Block comment + index += 2; + const endComment = text.indexOf('*/', index); + if (endComment === -1) { index = len; } + else { index = endComment + 2; } + continue; + } + } + else if (ext === '.py' && char === '#') { // Python comment + const newline = text.indexOf('\n', index + 1); + index = newline === -1 ? len : newline; + continue; + } + + index++; + } + return null; + } + /** - * 解析JavaScript对象字面量(支持无引号属性名) + * 解析对象字符串 * @param {string} str 对象字符串 * @returns {Object} 解析后的对象 */ static parseObjectLiteral(str) { - const normalized = str - .replace(/([{,]\s*)([a-zA-Z_$][\w$]*)(\s*:)/g, '$1"$2"$3') - .replace(/'([^']+)'/g, '"$1"'); - try { - return JSON.parse(normalized); + return JSON5.parse(str); } catch (e) { + // console.warn('JSON5 parse failed, falling back to eval:', e.message); try { + // 尝试处理一些常见的非标准JSON格式 + // 1. 给未加引号的键加上引号 (简单的正则替换,不够完美但能处理大部分情况) + // 注意:这里不再做简单的正则替换,因为 JSON5 已经能处理无引号键。 + // 如果 JSON5 失败,很可能是因为包含了函数或其他非数据类型,或者格式严重错误。 + + // 为了兼容旧的非标准写法,保留 eval 方式作为最后的手段 return (new Function(`return ${str}`))(); - } catch { - throw new Error(`Invalid header object: ${str}`); + } catch (evalError) { + throw new Error(`Invalid header object: ${str}. Error: ${evalError.message}`); } } } @@ -51,6 +143,7 @@ class FileHeaderManager { * @returns {Object|null} 头信息对象 */ static async readHeader(filePath) { + // 对于大多数脚本文件(通常 < 1MB),直接全量读取比 open+read+close 更快 const content = await fs.readFile(filePath, 'utf8'); const ext = path.extname(filePath); const config = this.COMMENT_CONFIG[ext]; @@ -60,11 +153,11 @@ class FileHeaderManager { const match = content.match(config.regex); if (!match) return null; - const headerMatch = match[0].match(config.headerRegex); - if (!headerMatch) return null; + const headerBlock = this.findHeaderBlock(match[0], ext); + if (!headerBlock) return null; try { - return this.parseObjectLiteral(headerMatch[1].trim()); + return this.parseObjectLiteral(headerBlock.content.trim()); } catch { return null; } @@ -119,6 +212,19 @@ class FileHeaderManager { throw new Error('Invalid header object'); } + const ext = path.extname(filePath); + const config = this.COMMENT_CONFIG[ext]; + + if (!config) throw new Error(`Unsupported file type: ${ext}`); + + const headerStr = `@header(${JSON5.stringify(headerObj, null, 2)})`; + + // 尝试使用 Buffer 优化写入 (针对已存在 header 的情况) + const bufferSuccess = await this._replaceHeaderBuffer(filePath, headerStr, config, ext); + if (bufferSuccess) { + return; + } + let content; try { content = await fs.readFile(filePath, 'utf8'); @@ -126,17 +232,11 @@ class FileHeaderManager { throw new Error(`Failed to read file: ${error.message}`); } - // 备份原始内容 - const originalContent = content; - const ext = path.extname(filePath); - const config = this.COMMENT_CONFIG[ext]; - - if (!config) throw new Error(`Unsupported file type: ${ext}`); - - const headerStr = `@header(${JSON.stringify(headerObj, null, 2) - .replace(/"([a-zA-Z_$][\w$]*)":/g, '$1:') - .replace(/"/g, "'")})`; + // 优化:先尝试只读取头部来匹配正则,避免全量匹配 + // 但由于 writeHeader 需要重写整个文件,全量内容是必须的 + // 所以这里的优化点主要在于减少不必要的全量正则匹配 + // 使用优化后的 regex 只匹配头部注释 const match = content.match(config.regex); let newContent; @@ -147,24 +247,63 @@ class FileHeaderManager { // 确保匹配的注释块确实在文件开头(允许前面有空白字符) const beforeComment = content.substring(0, commentStartIndex); - if (beforeComment.trim() !== '') { - // 如果注释块前面有非空白内容,说明这不是文件头注释,创建新的头注释 - const newComment = config.createComment(headerStr) + '\n\n'; - newContent = newComment + content; + + // 针对 PHP 特殊处理:忽略开头的 { - const trimmed = line.trim(); - return trimmed && !trimmed.startsWith('//') && !trimmed.startsWith('/*') && - !trimmed.startsWith('*') && !trimmed.startsWith('*/') && - !trimmed.startsWith('#') && !trimmed.startsWith('"""') && !trimmed.startsWith("'''"); - }); - - const newCodeLines = newContent.split('\n').filter(line => { - const trimmed = line.trim(); - return trimmed && !trimmed.startsWith('//') && !trimmed.startsWith('/*') && - !trimmed.startsWith('*') && !trimmed.startsWith('*/') && - !trimmed.startsWith('#') && !trimmed.startsWith('"""') && !trimmed.startsWith("'''") && - !trimmed.includes('@header('); - }); - - // 如果新内容的代码行数比原始内容少了很多,可能出现了问题 - if (originalCodeLines.length > 5 && newCodeLines.length < originalCodeLines.length * 0.8) { - throw new Error('Content integrity check failed: significant code loss detected, operation aborted'); + // 简单的内容完整性检查:确保新内容大小与原始内容大小差异在合理范围内 + // 移除复杂的行级比对以提升性能 + const diffRatio = Math.abs(newContent.length - content.length) / content.length; + if (content.length > 100 && diffRatio > 0.5 && newContent.length < content.length) { + throw new Error('Content integrity check failed: significant size reduction detected, operation aborted'); } // 创建备份(如果启用) @@ -243,6 +381,119 @@ class FileHeaderManager { } } + /** + * 使用 Buffer 高效地替换文件头,避免大文件 String 转换开销 + * @private + */ + static async _replaceHeaderBuffer(filePath, headerStr, config, ext) { + let handle; + try { + handle = await fs.open(filePath, 'r'); + const stats = await handle.stat(); + + // 如果文件太小,Buffer 优化的开销可能不划算,fallback 到 string 处理 + // 或者如果文件太大 (如 > 5MB),我们只读取前 64KB 寻找 header + const MAX_SCAN_SIZE = 64 * 1024; // 64KB + const scanSize = Math.min(stats.size, MAX_SCAN_SIZE); + + const buffer = Buffer.alloc(scanSize); + await handle.read(buffer, 0, scanSize, 0); + await handle.close(); + handle = null; + + // 将 buffer 转为 string 进行正则匹配 (只转前 64KB) + const contentHead = buffer.toString('utf8'); + + const match = contentHead.match(config.regex); + + if (match) { + const [fullComment] = match; + // 找到 headerBlock + const headerBlock = this.findHeaderBlock(fullComment, ext); + + if (headerBlock) { + // 计算 headerBlock 在文件中的 byte offset + // 注意:fullComment 是 regex 匹配出来的 string + // 我们需要找到 fullComment 在 buffer 中的 byte offset + + // Buffer.indexOf(string) 可以找到 byte offset + // 但 regex 匹配的 fullComment 可能包含 unicode,直接 indexOf string 是安全的 + // 前提是 encoding 一致 (utf8) + + const commentStartOffset = buffer.indexOf(fullComment); + if (commentStartOffset === -1) { + // Fallback if not found (encoding issues?) + return false; + } + + // headerBlock.start 是相对于 fullComment 字符串的 char index + // 我们需要 byte index。这有点麻烦,因为 fullComment 可能包含多字节字符。 + // 所以我们需要把 fullComment.substring(0, headerBlock.start) 转为 Buffer 算长度 + + const preHeaderStr = fullComment.substring(0, headerBlock.start); + const preHeaderLen = Buffer.byteLength(preHeaderStr); + + const postHeaderStr = fullComment.substring(headerBlock.end); + + // 构造新的 header buffer + const newHeaderBuf = Buffer.from(headerStr); + + // 计算替换点 + const replaceStart = commentStartOffset + preHeaderLen; + + // 原有的 header content byte length + const oldHeaderContentStr = headerBlock.content; // 这里包含了 header(...) 括号内的内容? + // findHeaderBlock 返回的是 {start, end, content} + // start/end 是相对于 fullComment 的 index + // content 是 header(...) 括号内的内容,还是 @header(...)? + // 看 findHeaderBlock 实现: + // content: text.substring(startIndex + startMarker.length, index) -> 只是括号内的内容 + // start: startIndex ( "@" 的位置 ) + // end: index + 1 ( ")" 后面的位置 ) + + // 所以 headerBlock.start 指向 "@header" 的 "@" + // headerBlock.end 指向 ")" 后面 + + // 原始的 header 部分 (string) + const oldHeaderFullStr = fullComment.substring(headerBlock.start, headerBlock.end); + const oldHeaderByteLen = Buffer.byteLength(oldHeaderFullStr); + + // 准备写入 + // 如果新旧 header 长度一致,可以直接 overwrite (极快) + // 如果不一致,需要重写文件剩余部分 + + if (newHeaderBuf.length === oldHeaderByteLen) { + // Overwrite inplace + const writeHandle = await fs.open(filePath, 'r+'); + await writeHandle.write(newHeaderBuf, 0, newHeaderBuf.length, replaceStart); + await writeHandle.close(); + return true; + } else { + // 重写文件 + // 读取整个文件为 Buffer 然后 concat + // 避免 string 转换 + + const fullFileBuf = await fs.readFile(filePath); + const finalBuf = Buffer.concat([ + fullFileBuf.subarray(0, replaceStart), + newHeaderBuf, + fullFileBuf.subarray(replaceStart + oldHeaderByteLen) + ]); + + await fs.writeFile(filePath, finalBuf); + return true; + } + } + } + + return false; // Fallback to string mode if no match or complex case + } catch (e) { + if (handle) await handle.close(); + return false; + } + } + + /** * 移除头信息区域 * @param {string} input 文件路径或文件内容 @@ -290,21 +541,46 @@ class FileHeaderManager { const match = content.match(config.regex); if (!match) return content.trim(); - let [fullComment, innerContent] = match; - - if (config.headerRegex.test(innerContent)) { - innerContent = innerContent.replace(config.headerRegex, ''); - - const cleanedInner = innerContent + let [fullComment] = match; + + const headerBlock = this.findHeaderBlock(fullComment, ext); + + if (headerBlock) { + // 获取 header 之前和之后的内容 + let beforeHeader = fullComment.substring(0, headerBlock.start); + let afterHeader = fullComment.substring(headerBlock.end); + + // 移除注释开始符和结束符 + beforeHeader = beforeHeader.replace(config.start, ''); + afterHeader = afterHeader.replace(config.end, ''); + + // PHP: 如果是 line.trim().length > 0) + .map(line => line.trim()) + .filter(line => line.length > 0) .join('\n'); - if (!cleanedInner.trim()) { - content = content.replace(fullComment, ''); + if (!cleanedInner) { + // 如果只剩下 header,整个注释块移除 + // 但如果是 PHP 文件, newComment); } } @@ -348,4 +624,4 @@ class FileHeaderManager { } } -export default FileHeaderManager; \ No newline at end of file +export default FileHeaderManager; diff --git a/utils/fsWrapper.js b/utils/fsWrapper.js new file mode 100644 index 00000000..07ee4f2a --- /dev/null +++ b/utils/fsWrapper.js @@ -0,0 +1,157 @@ +/** + * Wrapper for native fs module to simulate fs-extra methods. + * This makes it easy to switch between native fs and fs-extra. + */ +import fs from 'fs'; +import path from 'path'; + +// Promisified fs methods are available in fs.promises +const fsp = fs.promises; + +/** + * Ensures that the directory exists. If the directory structure does not exist, it is created. + * @param {string} dirPath + */ +async function ensureDir(dirPath) { + try { + await fsp.mkdir(dirPath, { recursive: true }); + } catch (err) { + if (err.code !== 'EEXIST') throw err; + } +} + +/** + * Ensures that the directory exists synchronously. + * @param {string} dirPath + */ +function ensureDirSync(dirPath) { + try { + fs.mkdirSync(dirPath, { recursive: true }); + } catch (err) { + if (err.code !== 'EEXIST') throw err; + } +} + +/** + * Checks if a file or directory exists. + * @param {string} fileOrDirPath + * @returns {Promise} + */ +async function pathExists(fileOrDirPath) { + try { + await fsp.access(fileOrDirPath); + return true; + } catch { + return false; + } +} + +/** + * Copies a file or directory. The directory can have contents. + * @param {string} src + * @param {string} dest + * @param {object} [options] + */ +async function copy(src, dest, options = {}) { + const stats = await fsp.stat(src); + if (stats.isDirectory()) { + await ensureDir(dest); + const entries = await fsp.readdir(src); + for (const entry of entries) { + const srcPath = path.join(src, entry); + const destPath = path.join(dest, entry); + await copy(srcPath, destPath, options); + } + } else { + await ensureDir(path.dirname(dest)); + if (options.overwrite !== false) { + await fsp.copyFile(src, dest); + } else { + const exists = await pathExists(dest); + if (!exists) { + await fsp.copyFile(src, dest); + } + } + } +} + +/** + * Removes a file or directory. The directory can have contents. + * @param {string} fileOrDirPath + */ +async function remove(fileOrDirPath) { + try { + await fsp.rm(fileOrDirPath, { recursive: true, force: true }); + } catch (err) { + if (err.code !== 'ENOENT') throw err; + } +} + +/** + * Reads a JSON file and parses it. + * @param {string} file + * @param {object|string} [options] + * @returns {Promise} + */ +async function readJson(file, options) { + const content = await fsp.readFile(file, options || 'utf-8'); + return JSON.parse(content); +} + +/** + * Writes an object to a JSON file. + * @param {string} file + * @param {any} object + * @param {object|string} [options] + */ +async function writeJson(file, object, options = {}) { + const spaces = options.spaces || 2; + const str = JSON.stringify(object, null, spaces); + await fsp.writeFile(file, str, options); +} + +/** + * Reads a JSON file synchronously and parses it. + * @param {string} file + * @param {object|string} [options] + * @returns {any} + */ +function readJsonSync(file, options) { + const content = fs.readFileSync(file, options || 'utf-8'); + return JSON.parse(content); +} + +/** + * Writes an object to a JSON file synchronously. + * @param {string} file + * @param {any} object + * @param {object|string} [options] + */ +function writeJsonSync(file, object, options = {}) { + const spaces = options.spaces || 2; + const str = JSON.stringify(object, null, spaces); + fs.writeFileSync(file, str, options); +} + +// Export a combined object containing both standard fsp methods and our custom fs-extra-like methods +const fsWrapper = { + ...fsp, + // Original sync methods if needed + existsSync: fs.existsSync, + readFileSync: fs.readFileSync, + writeFileSync: fs.writeFileSync, + readdirSync: fs.readdirSync, + statSync: fs.statSync, + // Custom fs-extra methods + ensureDir, + ensureDirSync, + pathExists, + copy, + remove, + readJson, + writeJson, + readJsonSync, + writeJsonSync, +}; + +export default fsWrapper; diff --git a/utils/pan/ali.js b/utils/pan/ali.js index 786c8c01..468467d1 100644 --- a/utils/pan/ali.js +++ b/utils/pan/ali.js @@ -511,7 +511,7 @@ class AliDrive { if (item.type === 'folder') { subDir.push(item); } else if (item.type === 'file' && item.category === 'video') { - let text = /[#|'"\[\]&<>]/g + let text = /[#|'"\[\]&<>]/g; if (item.size < 1024 * 1024 * 5) continue; item.name = item.name.replace(/玩偶哥.*【神秘的哥哥们】/g, ''); item.name = text.test(item.name) ? item.name.replace(text, '') : item.name diff --git a/utils/pan/baidu2.js b/utils/pan/baidu2.js index eb875d1d..ca8dfae9 100644 --- a/utils/pan/baidu2.js +++ b/utils/pan/baidu2.js @@ -6,7 +6,7 @@ import '../../libs_drpy/jsencrypt.js' import {ENV} from "../env.js"; import axios from "axios"; -import qs from "qs"; // 添加缺失的qs模块导入 +import qs from "qs"; /** * 百度网盘驱动类 @@ -18,7 +18,7 @@ class BaiduDrive { */ constructor() { // 百度网盘分享链接正则表达式 - this.regex = /https:\/\/pan\.baidu\.com\/s\/(.*)\?.*?pwd=([^&]+)/;//https://pan.baidu.com/s/1kbM0KWLDpeS8I49tmwS6lQ?pwd=74j5 + this.regex = /https:\/\/pan\.baidu\.com\/s\/(.*)\?.*?pwd=([^&]+)/; // 支持的视频质量类型 this.type = ["M3U8_AUTO_4K", "M3U8_AUTO_2K", "M3U8_AUTO_1080", "M3U8_AUTO_720", "M3U8_AUTO_480"]; // 请求头配置 @@ -49,6 +49,23 @@ class BaiduDrive { this.channel = 'chunlei'; } + /** + * 格式化文件大小 + * @param {number} bytes - 文件字节数 + * @returns {string} 格式化后的大小字符串 + */ + formatFileSize(bytes) { + if (!bytes || bytes === 0) return '0 B'; + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + let i = 0; + let size = bytes; + while (size >= 1024 && i < units.length - 1) { + size /= 1024; + i++; + } + return size.toFixed(2) + ' ' + units[i]; + } + /** * 初始化方法,加载本地配置 * @returns {Promise} @@ -169,12 +186,24 @@ class BaiduDrive { if (item.category === '1' || item.category === 1) { // 确保所有情况下都提取文件名 const fileName = item.server_filename || item.path.split('/').pop(); + + // 提取缩略图 + let thumbnail = ''; + if (item.thumbs) { + thumbnail = item.thumbs.url || item.thumbs.icon || ''; + } else if (item.icon) { + thumbnail = item.icon; + } + videos.push({ - name: fileName, // 只使用文件名 - path: item.path.replaceAll('#', '\0'), // 如果路径里含有#,替换为非法文本\0,所有系统的路径都不可能存在这个文本 + name: fileName, + path: item.path.replaceAll('#', '\0'), uk: this.uk, shareid: this.shareid, - fsid: item.fs_id || item.fsid + fsid: item.fs_id || item.fsid, + size: item.size, + formatted_size: this.formatFileSize(item.size), + thumbnail: thumbnail }) } }); @@ -227,12 +256,24 @@ class BaiduDrive { if (item.category === '1' || item.category === 1) { // 确保所有情况下都提取文件名 const fileName = item.server_filename || item.path.split('/').pop(); + + // 提取缩略图 + let thumbnail = ''; + if (item.thumbs) { + thumbnail = item.thumbs.url || item.thumbs.icon || ''; + } else if (item.icon) { + thumbnail = item.icon; + } + videos.push({ - name: fileName, // 只使用文件名 - path: item.path.replaceAll('#', '\0'), // 如果路径里含有#,替换为非法文本\0,所有系统的路径都不可能存在这个文本 + name: fileName, + path: item.path.replaceAll('#', '\0'), uk: this.uk, shareid: this.shareid, - fsid: item.fs_id || item.fsid + fsid: item.fs_id || item.fsid, + size: item.size, + formatted_size: this.formatFileSize(item.size), + thumbnail: thumbnail }) } }); @@ -323,12 +364,6 @@ class BaiduDrive { headers: header })).data if (data.errno === 0 && data.list.length > 0) { - // let relink = await axios.get(link,{ - // headers:header, - // redirect: false, - // onlyHeaders: true - // }) - // console.log(relink) return data.list[0].dlink // 返回直链地址 } } diff --git a/utils/pan/quark.js b/utils/pan/quark.js index c0c9e8b5..ff0f5f14 100644 --- a/utils/pan/quark.js +++ b/utils/pan/quark.js @@ -17,7 +17,7 @@ * @since 1.0.0 */ -import req from '../req.js'; +import {reqs} from '../req.js'; import {ENV} from '../env.js'; import COOKIE from '../cookieManager.js'; import CryptoJS from "crypto-js"; @@ -143,16 +143,16 @@ class QuarkHandler { * @returns {Promise} */ async initQuark() { - if (this.token) { - let exp = JSON.parse(CryptoJS.enc.Base64.parse(this.token.split('.')[1]).toString(CryptoJS.enc.Utf8)) - let now = Math.floor(Date.now() / 1000) - if (exp.exp < now) { - console.log('登录状态已过期,重新登录,请及时更换Token') - } else { - console.log('登录成功,继续使用,可使用时间截止到:' + (new Date(exp.exp * 1000)).toLocaleString()) - console.log('QuarkTV token获取成功:' + this.token) - } - } + // if(this.token){ + // let exp = JSON.parse(CryptoJS.enc.Base64.parse(this.token.split('.')[1]).toString(CryptoJS.enc.Utf8)) + // let now = Math.floor(Date.now() / 1000) + // if (exp.exp < now) { + // console.log('登录状态已过期,重新登录,请及时更换Token') + // } else { + // console.log('登录成功,继续使用,可使用时间截止到:' + (new Date(exp.exp * 1000)).toLocaleString()) + // console.log('QuarkTV token获取成功:' + this.token) + // } + // } if (this.cookie) { console.log("cookie 获取成功"); } else { @@ -335,12 +335,12 @@ class QuarkHandler { let link = `${this.apiUrl}/${url}` // 发送请求 - 根据方法类型选择GET或POST请求 const resp = - method === 'get' ? await req.get(link, { + method === 'get' ? await reqs.get(link, { headers: headers, }).catch((err) => { console.error(err.message); return err.response || {status: 500, data: {}}; - }) : await req.post(link, data, { + }) : await reqs.post(link, data, { headers: headers, }).catch((err) => { console.error(err.message); @@ -650,7 +650,6 @@ class QuarkHandler { const resCookie = cookieResDataSelf['set-cookie']; if (!resCookie) { console.log(`${from}自动更新夸克 cookie: 没返回新的cookie`); - return } const cookieObject = COOKIE.parse(resCookie); @@ -719,40 +718,43 @@ class QuarkHandler { return CryptoJS.SHA256(data).toString(); } - async refreshToken() { - let data = JSON.stringify({ - "req_id": reqId, - "app_ver": this.conf.appVer, - "device_id": deviceID, - "device_brand": "OPPO", - "platform": "tv", - "device_name": "PCRT00", - "device_model": "PCRT00", - "build_device": "aosp", - "build_product": "PCRT00", - "device_gpu": "Adreno%20(TM)%20640", - "activity_rect": "%7B%7D", - "channel": this.conf.channel, - "refresh_token": this.token - }); - let config = { - method: 'POST', - url: 'http://api.extscreen.com/quarkdrive', - headers: { - 'User-Agent': 'Mozilla/5.0 (Linux; U; Android 7.1.2; zh-cn; PCRT00 Build/N2G47O) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1', - 'Connection': 'Keep-Alive', - 'Accept-Encoding': 'gzip', - 'Content-Type': 'application/json', - 'Cookie': 'sl-session=VIaxTAKF8mdJBhU2uda0zA==' - }, - data: data - }; - let req = await axios.request(config); - if (req.status === 200) { - ENV.set('uc_token_cookie', req.data.data.refresh_token) - return await this.getDownload(shareId, stoken, fileId, fileToken, clean) - } - } + // async refreshToken(shareId, stoken, fileId, fileToken, clean){ + // const timestamp = Math.floor(Date.now() / 1000).toString() + '000'; // 13位时间戳需调整 + // const deviceID = this.Addition.DeviceID || this.generateDeviceID(timestamp); + // const reqId = this.generateReqId(deviceID, timestamp); + // let data = JSON.stringify({ + // "req_id": reqId, + // "app_ver": this.conf.appVer, + // "device_id": deviceID, + // "device_brand": "OPPO", + // "platform": "tv", + // "device_name": "PCRT00", + // "device_model": "PCRT00", + // "build_device": "aosp", + // "build_product": "PCRT00", + // "device_gpu": "Adreno%20(TM)%20640", + // "activity_rect": "%7B%7D", + // "channel": this.conf.channel, + // "refresh_token": this.token + // }); + // let config = { + // method: 'POST', + // url: 'http://api.extscreen.com/quarkdrive', + // headers: { + // 'User-Agent': 'Mozilla/5.0 (Linux; U; Android 7.1.2; zh-cn; PCRT00 Build/N2G47O) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1', + // 'Connection': 'Keep-Alive', + // 'Accept-Encoding': 'gzip', + // 'Content-Type': 'application/json', + // 'Cookie': 'sl-session=VIaxTAKF8mdJBhU2uda0zA==' + // }, + // data: data + // }; + // let req = await axios.request(config); + // if(req.status === 200) { + // ENV.set('quark_token_cookie',req.data.data.refresh_token) + // return await this.getDownload(shareId, stoken, fileId, fileToken, clean) + // } + // } async getDownload(shareId, stoken, fileId, fileToken, clean) { await this.initQuark() @@ -1000,10 +1002,83 @@ class QuarkHandler { } + async getToken() { + let t = Math.floor(new Date().getTime() / 1e3) + + let data = JSON.stringify({ + "conversation_id": "300000" + t, + "conversation_type": 3, + "msg_id": t + "000" + }); + + let config = { + method: 'POST', + url: 'https://drive-social-api.quark.cn/1/clouddrive/chat/conv/file/acquire_dl_token?pr=ucpro&fr=pc&sys=darwin&ve=3.19', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/3.23.2 Chrome/112.0.5615.165 Electron/24.1.3.8 Safari/537.36 Channel/pckk_other_ch', + 'Connection': 'keep-alive', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/json', + 'accept-language': 'zh-CN', + 'origin': 'https://pan.quark.cn', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'cross-site', + 'sec-ch-ua': '"Not:A-Brand";v="99", "Chromium";v="112"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'referer': 'https://pan.quark.cn/', + 'Cookie': this.cookie + }, + data: data + }; + let html = await axios.request(config) + if (html.status === 200) { + return html.data.data.token + } + } + + //伪造token实现无限不转存 + async getUrl(shareId, stoken, fileId, fileToken) { + await this.initQuark() + let token = await this.getToken() + let data = JSON.stringify({ + "fids": [fileId], + "fids_token": [fileToken], + "pwd_id": shareId, + "stoken": stoken, + "speedup_session": "", + "token": token + }); + let config = { + method: 'POST', + url: 'https://drive-pc.quark.cn/1/clouddrive/file/download?pr=ucpro&fr=pc', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/3.20.0 Chrome/112.0.5615.165 Electron/24.1.3.8 Safari/537.36 Channel/pckk_other_ch', + 'Connection': 'keep-alive', + 'Accept': '*/*,application/json;charset=utf-8', + 'Accept-Encoding': 'gzip, deflate, br, zstd', + 'Content-Type': 'application/json', + 'Cookie': this.cookie + }, + data: data + }; + let html = await axios.request(config).catch(e => e) + if (html.status === 200) { + return html.data.data.map(it => { + return { + name: it.video_max_resolution, + url: it.download_url + } + }) + } + } + async testSupport(url, headers) { - const resp = await req + const resp = await reqs .get(url, { @@ -1236,7 +1311,7 @@ class QuarkHandler { console.log(inReq.id, chunkIdx); - const dlResp = await req.get(url, { + const dlResp = await reqs.get(url, { responseType: 'stream', diff --git a/utils/pan/uc.js b/utils/pan/uc.js index 0e8d93cd..baf72e5f 100644 --- a/utils/pan/uc.js +++ b/utils/pan/uc.js @@ -406,6 +406,7 @@ class UCHandler { // 收集子目录 subDir.push(item); } else if (item.file === true && item.obj_category === 'video') { + let text = /[#|'"\[\]&<>]/g; // 过滤小于5MB的视频文件 if (item.size < 1024 * 1024 * 5) continue; item.stoken = this.shareTokenCache[shareData.shareId].stoken; diff --git a/utils/pan/xun.js b/utils/pan/xun.js new file mode 100644 index 00000000..6b029e49 --- /dev/null +++ b/utils/pan/xun.js @@ -0,0 +1,805 @@ +import axios from "axios"; +import {ENV} from "../env.js"; +import CryptoJS from "crypto-js"; + +class XunDriver { + constructor() { + this.regex = /https:\/\/pan.xunlei.com\/s\/(.*)\?.*?pwd=([^&]+)/;//https://pan.baidu.com/s/1kbM0KWLDpeS8I49tmwS6lQ?pwd=74j5 + this.headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "Connection": "keep-alive", + "Accept": "application/json, text/plain, */*", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6" + }; + this.api = 'https://xluser-ssl.xunlei.com/'; + this.xun_api = 'https://api-pan.xunlei.com/' + this.captcha_token = '' + this.parent_id = '' + this.share_id = '' + this.pass_code = '' + this.pass_code_token = '' + this.filename = 'ds' + this.fileId = '' + this.vodID = '' + this.client_id = 'XW5SkOhLDjnOZP7J' + this.x_client_id = 'XW-G4v1H72tgfJym' + this.device_id = '652c6bb3cacdb4b80e852dfc3cb3cca4' + this.i = 0 + } + + // 初始化方法,加载本地配置 + async init() { + if (this.auth) { + let info = JSON.parse(CryptoJS.enc.Base64.parse(this.auth.split('.')[1]).toString(CryptoJS.enc.Utf8)) + if (info.exp > Math.floor(Date.now() / 1000)) { + console.log("登录成功") + } else { + console.log("登录过期,重新登录") + } + } else { + await this.getAuth() + } + } + + get username() { + return ENV.get('xun_username') + } + + get password() { + return ENV.get('xun_password') + } + + get auth() { + return ENV.get('xun_auth') + } + + get app_auth() { + return ENV.get('xun_app_auth') + } + + get refresh_token() { + return ENV.get('xun_refresh_token') + } + + get userId() { + return ENV.get('xun_user_id') + } + + /** + * 延时函数 + * + * 创建一个Promise,在指定毫秒数后resolve,用于控制请求频率。 + * + * @param {number} ms - 延时毫秒数 + * @returns {Promise} 延时Promise + * + * @example + * await delay(1000); // 延时1秒 + */ + delay(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + async execUrl(url) { + this.link = url + const matches = this.regex.exec(url); + if (matches && matches[1]) { + this.share_id = matches[1]; + this.pass_code = matches[2] || ''; + } + } + + async login() { + let data = JSON.stringify({ + "protocolVersion": "301", + "sequenceNo": "1000001", + "platformVersion": "10", + "isCompressed": "0", + "appid": "40", + "clientVersion": "8.03.0.9067", + "peerID": "c9b076a446517969dff638cd37fa9ff1", + "appName": "ANDROID-com.xunlei.downloadprovider", + "sdkVersion": "231500", + "devicesign": "div101.b71a923eb0e2239842599a3c016b4098612f6cf6d6e9fd1925845ec59285716c", + "netWorkType": "2G", + "providerName": "NONE", + "deviceModel": "22021211RC", + "deviceName": "Xiaomi_22021211Rc", + "OSVersion": "12", + "creditkey": "", + "hl": "zh-CN", + "userName": this.username, + "passWord": this.password, + "verifyKey": "", + "verifyCode": "", + "isMd5Pwd": "0" + }); + let config = { + method: 'POST', + url: `${this.api}xluser.core.login/v3/login`, + headers: { + 'Content-Type': 'application/json' + }, + data: data + }; + let login_data = (await axios.request(config)) + if (login_data.status === 200) { + console.log('登录成功') + return login_data.data.sessionID; + } + } + + async getSignCaptcha() { + let data = JSON.stringify({ + "client_id": this.x_client_id, + "action": "POST:/v1/auth/signin", + "device_id": this.device_id, + "captcha_token": "", + "meta": { + "phone_number": `+86 ${this.username}` + } + }); + + let config = { + method: 'POST', + url: `${this.api}v1/shield/captcha/init`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json' + }, + data: data + }; + let signin = await axios.request(config) + if (signin.status === 200) { + return signin.data.captcha_token + } + } + + async getAuth() { + let need_auth = 1; + if (this.auth) { + let info = JSON.parse(CryptoJS.enc.Base64.parse(this.auth.split('.')[1]).toString(CryptoJS.enc.Utf8)) + if (info.exp > Math.floor(Date.now() / 1000)) { + console.log("登录成功"); + need_auth = 0; + } + } + if (need_auth) { + console.log("登录过期,重新登录") + let captcha_token = await this.getSignCaptcha(); + let data = JSON.stringify({ + "username": `+86 ${this.username}`, + "password": this.password, + "client_id": this.x_client_id + }); + let config = { + method: 'POST', + url: `${this.api}v1/auth/signin`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json', + 'accept-language': 'zh-cn', + 'x-captcha-token': captcha_token, + 'x-client-id': this.x_client_id, + 'x-device-id': this.device_id + }, + data: data + }; + let auth_data = (await axios.request(config)) + if (auth_data.status === 200) { + ENV.set('xun_auth', auth_data.data.token_type + " " + auth_data.data.access_token) + ENV.set('xun_user_id', auth_data.data.user_id) + } + await this.safecaptcha() + } + + } + + async safecaptcha() { + let data = JSON.stringify({ + "client_id": this.x_client_id, + "action": "get:/drive/v1/privilege/USER_SECURITY_TOKEN", + "device_id": this.device_id, + "captcha_token": "", + "meta": { + "username": "", + "phone_number": "", + "email": "", + "package_name": "pan.xunlei.com", + "client_version": "1.92.9", + "captcha_sign": "1.98cda33124387df2c03dea12799af2af", + "timestamp": "1757397551603", + "user_id": this.userId + } + }); + let config = { + method: 'POST', + url: 'https://xluser-ssl.xunlei.com/v1/shield/captcha/init', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'content-type': 'text/plain;charset=UTF-8' + }, + data: data + }; + let safe = (await axios.request(config)).data + let captcha_token = safe.captcha_token + let cfg = { + method: 'GET', + url: 'https://api-pan.xunlei.com/drive/v1/privilege/USER_SECURITY_TOKEN', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': this.auth, + 'content-type': 'application/json', + 'x-captcha-token': captcha_token, + 'x-client-id': this.x_client_id, + 'x-device-id': this.device_id + } + }; + let safe_data = (await axios(cfg)).data + } + + async getCaptcha_token(path, mth) { + let action = `${mth}:${path}` + let data = JSON.stringify({ + "client_id": 'Xqp0kJBXWhwaTpB6', + "action": action, + "device_id": "1bf91caf40093318e8040916eb7ad16a", + "captcha_token": "", + "meta": { + "username": "", + "phone_number": "", + "email": "", + "package_name": "pan.xunlei.com", + "client_version": "1.92.9", + "captcha_sign": "1.cbc20fd633c54023baab5b816228bf90", + "timestamp": "1757383155459", + "user_id": this.userId//this.user_id + } + }); + let config = { + method: 'POST', + url: `${this.api}v1/shield/captcha/init`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json', + }, + data: data + }; + let captcha_data = (await axios.request(config)) + if (captcha_data.status === 200) { + return captcha_data.data.captcha_token; + } + } + + async getAppCaptcha_token(path, mth) { + let action = `${mth}:${path}` + let data = JSON.stringify({ + "client_id": "XW-G4v1H72tgfJym", + "action": action, + "device_id": "652c6bb3cacdb4b80e852dfc3cb3cca4", + "captcha_token": "", + "meta": { + "package_name": "ThunderPanPlugin", + "client_version": "3.1.5", + "captcha_sign": "1.ee2cef5f061a7cdf4374df81b370d2ec", + "timestamp": "1773293019719", + "user_id": this.userId + } + }); + let config = { + method: 'POST', + url: `${this.api}v1/shield/captcha/init`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json', + }, + data: data + }; + let captcha_data = (await axios.request(config)) + if (captcha_data.status === 200) { + return captcha_data.data.captcha_token; + } + } + + sign() { + let x = [ + "QG3/GhopO+5+T", + "1Sv94+ANND3lDmmw", + "q2eTxRva8b3B5d", + "m2", + "VIc5CZRBMU71ENfbOh0+RgWIuzLy", + "66M8Wpw6nkBEekOtL6e", + "N0rucK7S8W/vrRkfPto5urIJJS8dVY0S", + "oLAR7pdUVUAp9xcuHWzrU057aUhdCJrt", + "6lxcykBSsfI//GR9", + "r50cz+1I4gbU/fk8", + "tdwzrTc4SNFC4marNGTgf05flC85A", + "qvNVUDFjfsOMqvdi2gB8gCvtaJAIqxXs" + ] + const c = { + ClientID: 'Xqp0kJBXWhwaTpB6', + ClientVersion: '1.92.9', + PackageName: 'pan.xunlei.com', + DeviceID: '1bf91caf40093318e8040916eb7ad16a' + } + const timestamp = Date.now() + let w = c.ClientID + c.ClientVersion + c.PackageName + c.DeviceID + '1757338961011' + for (let i = 0; i < x.length; i++) { + w = CryptoJS.MD5(w + x[i]).toString(); + } + return "1." + w + } + + async getShareList() { + let path = '/drive/v1/share' + let mth = 'get' + let captcha_data = await this.getCaptcha_token(path, mth) + let config = { + method: 'GET', + url: `${this.xun_api}drive/v1/share?share_id=${this.share_id}&pass_code=${this.pass_code}&limit=100&page_token=&thumbnail_size=SIZE_SMALL`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': '', + 'x-captcha-token': captcha_data, + 'x-client-id': 'Xqp0kJBXWhwaTpB6', + 'x-device-id': '1bf91caf40093318e8040916eb7ad16a' + } + }; + let sharelist = await axios.request(config) + if (sharelist.status === 200) { + let file = {} + let dirs = [] + let videos = [] + this.pass_code_token = sharelist.data.pass_code_token + sharelist.data.files.map(it => { + if (it.mime_type === '') { + dirs.push(it.id) + } else { + let text = /[#|'"\[\]&<>]/g + let name = text.test(it.name) ? it.name.replace(text, '') : it.name + videos.push({ + name: name, + fileId: it.id, + share_id: this.share_id, + parent_id: it.parent_id, + pass_code_token: encodeURIComponent(this.pass_code_token) + }) + } + }) + if (!(sharelist.data.title in file) && sharelist.data.title !== undefined) { + file[sharelist.data.title] = []; + } + if (videos.length > 0 && sharelist.data.title !== undefined) { + file[sharelist.data.title] = [...videos] + } + let result = await Promise.all(dirs.map(async (id) => this.getShareDetail(id))) + result = result.filter(item => item !== undefined && item !== null).flat() + if (result.length >= 0) { + file[sharelist.data.title].push(...result); + } + return file + } + } + + async getShareDetail(id) { + let path = '/drive/v1/share' + let mth = 'get' + let captcha_data = await this.getCaptcha_token(path, mth) + let config = { + method: 'GET', + url: `${this.xun_api}drive/v1/share/detail?share_id=${this.share_id}&parent_id=${id}&pass_code_token=${encodeURIComponent(this.pass_code_token)}&limit=100&page_token=&thumbnail_size=SIZE_SMALL`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': '', + 'content-type': 'application/json', + 'x-captcha-token': captcha_data, + 'x-client-id': 'Xqp0kJBXWhwaTpB6', + 'x-device-id': '1bf91caf40093318e8040916eb7ad16a' + } + }; + let detail_data = await axios.request(config) + if (detail_data.status === 200) { + let dirs = [] + let videos = [] + detail_data.data.files.map(it => { + if (it.mime_type === '') { + dirs.push(it.id) + } else { + let text = /[#|'"\[\]&<>]/g + let name = text.test(it.name) ? it.name.replace(text, '') : it.name + videos.push({ + name: name, + fileId: it.id, + share_id: this.share_id, + parent_id: it.parent_id, + pass_code_token: encodeURIComponent(this.pass_code_token) + }) + } + }) + let result = await Promise.all(dirs.map(async (id) => this.getShareDetail(id))) + result = result.filter(item => item !== undefined && item !== null) + return [...videos, ...result.flat()]; + } + } + + async getShareUrl(fileId, share_id, pass_code_token) { + let path = '/drive/v1/share' + let mth = 'get' + let captcha_data = await this.getCaptcha_token(path, mth) + let config = { + method: 'GET', + url: `${this.xun_api}drive/v1/share/file_info?pass_code_token=${encodeURIComponent(pass_code_token)}&space=&file_id=${fileId}&share_id=${share_id}&&pass_code=${this.pass_code}`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': '', + 'cache-control': 'no-cache', + 'content-type': 'application/json', + 'x-captcha-token': captcha_data, + 'x-client-id': 'Xqp0kJBXWhwaTpB6', + 'x-device-id': '1bf91caf40093318e8040916eb7ad16a' + } + }; + let url_list = await axios.request(config) + if (url_list.status === 200) { + let urls = [] + url_list.data.file_info.medias.map(it => { + if (it.link !== null) { + urls.push(it.media_name, it.link.url + "#isVideo=true##fastPlayMode##threads=20#") + urls.push("猫画" + it.media_name, `http://127.0.0.1:5575/proxy?thread=${ENV.get('thread') || 6}&chunkSize=256&url=` + encodeURIComponent(it.link.url)) + } + }) + return urls + } + } + + //获取分享文件列表 + async getShareData(url) { + if (url.startsWith('https://')) { + await this.execUrl(url) + return await this.getShareList() + } + // if(url.startsWith('magnet:')){ + // return await this.getMagnetData(url) + // } + } + + async saveResult(fileId, share_id, pass_code_token) { + let path = 'drive/v1/files' + let mth = 'get' + let captcha_data = await this.getAppCaptcha_token(path, mth) + let data = JSON.stringify({ + "parent_id": this.fileId, + "share_id": share_id, + "pass_code_token": decodeURIComponent(pass_code_token), + "ancestor_ids": [], + "file_ids": [ + fileId + ], + "specify_parent_id": true + }); + let config = { + method: 'POST', + url: `${this.xun_api}drive/v1/share/restore`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': this.auth, + 'x-captcha-token': captcha_data, + 'x-client-id': 'XW-G4v1H72tgfJym', + 'x-device-id': '652c6bb3cacdb4b80e852dfc3cb3cca4' + }, + data: data + }; + let file_data = await axios.request(config).catch(e => e.response) + if (file_data.status === 200) { + console.log("转存文件成功") + } + if (file_data.status === 404) { + this.i++ + if (this.i < 3) { + await this.saveResult(fileId, share_id, pass_code_token) + } else { + this.i = 0 + console.log("转存失败:" + file_data.data) + } + } + } + + //转存文件 + async saveFile(fileId, share_id, pass_code_token) { + await this.createFile() + if (this.fileId !== '' && this.fileId !== undefined) { + await this.delay(5000) + await this.saveResult(fileId, share_id, pass_code_token) + } + } + + //查询存储文件是否存在 + async getFile() { + if (this.auth === undefined || this.auth === '') { + await this.getAuth() + } + let path = 'drive/v1/files' + let mth = 'get' + let captcha_data = await this.getAppCaptcha_token(path, mth) + let url = `${this.xun_api}drive/v1/files?parent_id=&filters=%7B%22phase%22%3A%7B%22eq%22%3A%22PHASE_TYPE_COMPLETE%22%7D%2C%22trashed%22%3A%7B%22eq%22%3Afalse%7D%7D&with_audit=true&thumbnail_size=SIZE_SMALL&limit=50` + let config = { + method: 'GET', + url: url, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': this.auth, + 'content-type': 'application/json', + 'x-captcha-token': captcha_data, + 'x-client-id': 'XW-G4v1H72tgfJym', + 'x-device-id': '652c6bb3cacdb4b80e852dfc3cb3cca4' + } + }; + let file_data = await axios.request(config) + if (file_data.status === 200) { + file_data.data.files.map(it => { + if (it.name === this.filename) { + this.fileId = it.id; + } + }) + } + } + + //创建存储文件并写入文件夹ID + async createFile() { + await this.getFile() + let path = 'drive/v1/files' + let mth = 'get' + let captcha_data = await this.getAppCaptcha_token(path, mth) + let data = JSON.stringify({ + "parent_id": "", + "name": this.filename, + "kind": "drive#folder", + "space": "" + }); + let config = { + method: 'POST', + url: `${this.xun_api}drive/v1/files`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': this.auth, + 'x-captcha-token': captcha_data, + 'x-client-id': 'XW-G4v1H72tgfJym', + 'x-device-id': '652c6bb3cacdb4b80e852dfc3cb3cca4' + }, + data: data + }; + let file_data = await axios.request(config).catch(e => e.response) + if (file_data.status === 200) { + this.fileId = file_data.data.file.id + } + } + + //查询存储文件内容并获取文件ID + async getVodId() { + let path = 'drive/v1/files' + let mth = 'get' + let captcha_data = await this.getAppCaptcha_token(path, mth) + let url = `${this.xun_api}drive/v1/files?parent_id=${this.fileId}&filters=%7B%22phase%22%3A%7B%22eq%22%3A%22PHASE_TYPE_COMPLETE%22%7D%2C%22trashed%22%3A%7B%22eq%22%3Afalse%7D%7D&with_audit=true&thumbnail_size=SIZE_SMALL&limit=50` + let config = { + method: 'GET', + url: url, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': this.auth, + 'content-type': 'application/json', + 'x-captcha-token': captcha_data, + 'x-client-id': 'XW-G4v1H72tgfJym', + 'x-device-id': '652c6bb3cacdb4b80e852dfc3cb3cca4' + } + }; + let file_data = await axios.request(config) + if (file_data.status === 200) { + file_data.data.files.map(it => { + this.vodID = it.id + }) + } + return this.vodID + } + + //删除文件夹所有内容 + async deleteFile() { + await this.getFile() + if (this.fileId !== '' && this.fileId !== undefined) { + let path = 'drive/v1/files' + let mth = 'get' + let captcha_data = await this.getAppCaptcha_token(path, mth) + let data = JSON.stringify({ + "ids": [ + this.fileId + ], + "space": "" + }); + let config = { + method: 'POST', + url: `${this.xun_api}drive/v1/files:batchDelete`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json', + 'accept-language': 'zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6', + 'authorization': this.auth, + 'x-captcha-token': captcha_data, + 'x-client-id': 'XW-G4v1H72tgfJym', + 'x-device-id': '652c6bb3cacdb4b80e852dfc3cb3cca4' + }, + data: data + }; + let delete_data = await axios.request(config).catch(e => e.response) + if (delete_data.status === 200) { + console.log("删除文件成功") + } else if (delete_data.status === 404) { + console.log("文件未找到,删除失败") + } + } + } + + async getDownload_CAPTCHA_TOKEN() { + let data = { + "client_id": "XW-G4v1H72tgfJym", + "action": "GET:CAPTCHA_TOKEN", + "device_id": "652c6bb3cacdb4b80e852dfc3cb3cca4", + "captcha_token": "", + "meta": { + "package_name": "ThunderPanPlugin", + "client_version": "3.1.1", + "captcha_sign": "1.0eada0deeeaac52a6376f2e167fa9f29", + "timestamp": "1757378771289", + "user_id": this.userId + } + }; + let config = { + method: 'POST', + url: `${this.api}v1/shield/captcha/init`, + headers: { + "User-Agent": "thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + data: data + }; + let captcha_data = (await axios.request(config)) + if (captcha_data.status === 200) { + return captcha_data.data.captcha_token; + } + } + + async getAppCaptcha() { + let data = JSON.stringify({ + "client_id": 'Xqp0kJBXWhwaTpB6', + "action": "POST:/v1/auth/signin", + "device_id": "652c6bb3cacdb4b80e852dfc3cb3cca4", + "captcha_token": "", + "meta": { + "phone_number": `+86 ${this.username}` + } + }); + + let config = { + method: 'POST', + url: `${this.api}v1/shield/captcha/init`, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'Content-Type': 'application/json' + }, + data: data + }; + let signin = await axios.request(config) + if (signin.status === 200) { + return signin.data.captcha_token + } + } + + async AppAuth() { + if (this.app_auth) { + let info = JSON.parse(CryptoJS.enc.Base64.parse(this.app_auth.split('.')[1]).toString(CryptoJS.enc.Utf8)) + if (info.exp > Math.floor(Date.now() / 1000)) { + console.log("登录成功") + } else { + console.log("登录过期,重新登录") + let captcha_token = await this.getAppCaptcha(); + let data = JSON.stringify({ + "username": `+86 ${this.username}`, + "password": this.password, + "client_id": 'XW-G4v1H72tgfJym' + }); + let config = { + method: 'POST', + url: `${this.api}v1/auth/signin`, + headers: { + "User-Agent": "thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36", + "Content-Type": "application/json", + "x-captcha-token": captcha_token, + "x-client-id": "XW-G4v1H72tgfJym", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + }, + data: data + }; + let auth_data = (await axios.request(config)) + if (auth_data.status === 200) { + ENV.set('xun_refresh_token', auth_data.data.refresh_token) + ENV.set('xun_app_auth', auth_data.data.token_type + " " + auth_data.data.access_token) + } + } + } + } + + async getDownload_auth() { + await this.AppAuth() + let data = JSON.stringify({ + "client_id": "XW-G4v1H72tgfJym", + "client_secret": "Qbaferw2knfQKqxa25EYJGtZ2_6755CMwzXBN3ctW54", + "grant_type": "refresh_token", + "refresh_token": this.refresh_token + }); + let config = { + method: 'POST', + url: 'https://xluser-ssl.xunlei.com/v1/auth/token', + headers: { + 'User-Agent': 'thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36', + 'Content-Type': 'application/json', + 'x-client-id': 'XW-G4v1H72tgfJym', + 'x-device-id': '652c6bb3cacdb4b80e852dfc3cb3cca4', + }, + data: data + }; + let dwon_data = await axios(config).catch(e => e.response); + if (dwon_data.status === 200) { + ENV.set('xun_retoken', dwon_data.data.refresh_token); + ENV.set('xun_App_auth', dwon_data.data.token_type + " " + dwon_data.data.access_token) + } + } + + //下载 + async getDownloadUrl(fileId, share_id, pass_code_token) { + try { + await this.getDownload_auth() + await this.deleteFile() + await this.delay(1000) + await this.saveFile(fileId, share_id, pass_code_token) + let vodID = await this.getVodId() + let x_captcha_token = await this.getDownload_CAPTCHA_TOKEN() + let config = { + method: 'GET', + url: `${this.xun_api}drive/v1/files/${vodID}?space=&with[0]=public_share_tag&usage=FETCH`, + headers: { + "User-Agent": "thunder/12.4.4.3740 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 XDASKernel/22.3.27 Safari/537.36", + "Connection": "keep-alive", + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "x-captcha-token": x_captcha_token, + "authorization": this.app_auth, + "content-type": "application/json", + "x-device-id": "652c6bb3cacdb4b80e852dfc3cb3cca4" + } + }; + let file_data = await axios.request(config) + if (file_data.status === 200) { + console.log("下载地址:" + file_data.data.links['application/octet-stream'].url || file_data.data['web_content_link']) + return file_data.data.links['application/octet-stream'].url || file_data.data['web_content_link'] + } + } catch (e) { + console.log(e) + return '' + } + + } +} + +export const Xun = new XunDriver() \ No newline at end of file diff --git a/utils/pans.js b/utils/pans.js index f65e92e5..0c4d1241 100644 --- a/utils/pans.js +++ b/utils/pans.js @@ -27,6 +27,7 @@ import {Pan} from "./pan/pan123.js"; // 123网盘服务 import {Quark} from "./pan/quark.js"; // 夸克网盘服务 import {UC} from "./pan/uc.js"; // UC网盘服务 import {Yun} from "./pan/yun.js"; // 115网盘服务 +import {Xun} from "./pan/xun.js"; // 迅雷网盘服务 // 统一导出所有网盘服务 -export default {Ali, Baidu, Baidu2, Cloud, Pan, Quark, UC, Yun} \ No newline at end of file +export default {Ali, Baidu, Baidu2, Cloud, Pan, Quark, UC, Yun, Xun} \ No newline at end of file diff --git a/utils/proxy-util.js b/utils/proxy-util.js index 01cd3425..338e967a 100644 --- a/utils/proxy-util.js +++ b/utils/proxy-util.js @@ -220,6 +220,11 @@ export class SmartCacheManager { this._performCleanup(); }, this.cleanupInterval); + // 允许进程在定时器存在时退出 + if (this.cleanupTimer.unref) { + this.cleanupTimer.unref(); + } + // 确保进程退出时清理定时器 if (typeof process !== 'undefined') { process.on('exit', () => this.stopCleanupTimer()); diff --git a/utils/req.js b/utils/req.js index 4709394a..839d73e5 100644 --- a/utils/req.js +++ b/utils/req.js @@ -110,50 +110,50 @@ export const reqs = new _axios.create({ }); // Add System Proxy & DOH interceptor to reqs as well -reqs.interceptors.request.use(async config => { - if (!config.url) return config; - try { - // 1. Check System Proxy - const proxy = await getSystemProxy(); - if (proxy) { - const agent = new HttpsProxyAgent(proxy); - config.httpsAgent = agent; - config.proxy = false; - return config; - } - - // 2. DOH - let fullUrl = config.url; - if (config.baseURL && !/^https?:\/\//i.test(fullUrl)) { - try { - const parsed = new URL(fullUrl, config.baseURL); - fullUrl = parsed.toString(); - } catch (e) { - } - } - const urlObj = new URL(fullUrl); - const hostname = urlObj.hostname; - if (!hostname || /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') return config; - const ip = await resolveDoh(hostname); - if (ip && ip !== hostname) { - if (!config.headers) config.headers = {}; - let hasHost = false; - const keys = Object.keys(config.headers); - for (const k of keys) { - if (k.toLowerCase() === 'host') { - hasHost = true; - break; - } - } - if (!hasHost) config.headers.Host = hostname; - urlObj.hostname = ip; - config.url = urlObj.toString(); - if (config.baseURL) delete config.baseURL; - } - } catch (e) { - } - return config; -}); +// reqs.interceptors.request.use(async config => { +// if (!config.url) return config; +// try { +// // 1. Check System Proxy +// const proxy = await getSystemProxy(); +// if (proxy) { +// const agent = new HttpsProxyAgent(proxy); +// config.httpsAgent = agent; +// config.proxy = false; +// return config; +// } +// +// // 2. DOH +// let fullUrl = config.url; +// if (config.baseURL && !/^https?:\/\//i.test(fullUrl)) { +// try { +// const parsed = new URL(fullUrl, config.baseURL); +// fullUrl = parsed.toString(); +// } catch (e) { +// } +// } +// const urlObj = new URL(fullUrl); +// const hostname = urlObj.hostname; +// if (!hostname || /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') return config; +// const ip = await resolveDoh(hostname); +// if (ip && ip !== hostname) { +// if (!config.headers) config.headers = {}; +// let hasHost = false; +// const keys = Object.keys(config.headers); +// for (const k of keys) { +// if (k.toLowerCase() === 'host') { +// hasHost = true; +// break; +// } +// } +// if (!hasHost) config.headers.Host = hostname; +// urlObj.hostname = ip; +// config.url = urlObj.toString(); +// if (config.baseURL) delete config.baseURL; +// } +// } catch (e) { +// } +// return config; +// }); // 导出默认的HTTP请求客户端 export default req; diff --git a/vercel.json b/vercel.json index 0360008a..c45beaa7 100644 --- a/vercel.json +++ b/vercel.json @@ -11,7 +11,8 @@ "spider/**", "jx/**", "config/**", - "json/**" + "json/**", + "node_modules/node-sqlite3-wasm/dist/**" ] } }