From 0d4e140b974e393bcf9cd8baf764ebceb42dfc44 Mon Sep 17 00:00:00 2001 From: Shawn Wen <45581750+KOP-XIAO@users.noreply.github.com> Date: Thu, 8 Jan 2026 19:53:03 +0800 Subject: [PATCH] Update resource-parser.js --- Scripts/resource-parser.js | 72 ++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/Scripts/resource-parser.js b/Scripts/resource-parser.js index 958fa83..727bbf8 100644 --- a/Scripts/resource-parser.js +++ b/Scripts/resource-parser.js @@ -1,5 +1,5 @@ /** -☑️ 资源解析器 ©𝐒𝐡𝐚𝐰𝐧 ⟦2026-01-07 13:45⟧ +☑️ 资源解析器 ©𝐒𝐡𝐚𝐰𝐧 ⟦2026-01-08 19:50⟧ ---------------------------------------------------------- 🛠 发现 𝐁𝐔𝐆 请反馈: https://t.me/ShawnKOP_Parser_Bot ⛳️ 关注 🆃🅶 相关频道: https://t.me/QuanX_API @@ -1574,7 +1574,7 @@ function Reality_Handle(cnt) { //add reality-base64-pubkey, reality-hex-shortid, vless-flow=xtls-rprx-vision a1=param("reality-base64-pubkey","pbk=",cnt) a2=param("reality-hex-shortid","sid=",cnt) - a3=(cnt.indexOf("flow=xtls-rprx-vision")!=-1 || cnt.indexOf("xtls=2")!=-1) && a1 != "" ? "vless-flow=xtls-rprx-vision": "" + a3=(cnt.indexOf("flow=xtls-rprx-vision")!=-1 || cnt.indexOf("xtls=2")!=-1)? "vless-flow=xtls-rprx-vision": "" rnt=[a1,a2,a3].filter(Boolean).join(", ") return rnt } @@ -1724,7 +1724,7 @@ function QX_TLS(cnt,Pcert0,PTls13) { cnt = cnt.replace(new RegExp("tag.*?\=", "gmi"), tls13+"tag=") } } - if (!/^(shadowsocks|trojan|vmess)/.test(cnt.trim())) { //关闭非 ss/ssr/trojan/vmess 类型的 udp + if (!/^(shadowsocks|trojan|vmess|vless)/.test(cnt.trim())) { //关闭非 ss/ssr/trojan/vmess/vless 类型的 udp udp = "udp-relay=false, " if(cnt.indexOf("udp-relay") != -1){ var cnt = cnt.replace(RegExp("udp\-relay.*?\,", "gmi"), udp) @@ -3041,10 +3041,10 @@ function YAMLFix(cnt){ cnt = cnt.replace(/\[/g,"yaml@bug1").replace(/\\r/g,"").replace(/\*/g,"yaml@bug2") //2022-08-08 增加 .replace(/\*/g,"🌟@bug2") 以解决名字以 * 开始时引起的部分问题 if (cnt.indexOf("{") != -1 && /\{\s*\"*(name|type|server)/.test(cnt)){ - cnt = cnt.replace(/(^|\n)- /g, "$1 - ").replace(/ - /g," - ").replace(/:(?!\s)/g,": ").replace(/\,\"/g,", \"").replace(/: {/g, ": {, ").replace(/, (Host|host|path|mux)/g,", $1") + cnt = cnt.replace(/(^|\n)- /g, "$1 - ").replace(/ - /g," - ").replace(/:(?!\s)/g,": ").replace(/\,\"/g,", \"").replace(/: {\s{0,1}/g, ": {, ").replace(/, (Host|host|path|mux)/g,", $1") //2022-04-11 remove tls|skip from replace(/, (Host|host|path|mux)/g,", $1") console.log("1st:\n"+cnt) - cnt = cnt.replace(/{\s*name: (.*?), (.*?):/g,"{name: \"$1\", $2:").replace(/, short-id/gi,", short-id") //cnt.replace(/{\s*name: /g,"{name: \"").replace(/, (.*?):/,"\", $1:") + cnt = cnt.replace(/{\s*name: (.*?), (.*?):/g,"{name: \"$1\", $2:").replace(/\"/gi,"").replace(/, short-id\"{0,1}/gi,", short-id") //cnt.replace(/{\s*name: /g,"{name: \"").replace(/, (.*?):/,"\", $1:") cnt = cnt.replace(/{\s*|\s*}/g,"").replace(/,/g,"\n ") } cnt = cnt.replace(/\n\s*\-\s*\n.*name/g,"\n - name").replace(/\$|\`/g,"").split("proxy-providers:")[0].split("proxy-groups:")[0].replace(/\"(name|type|server|port|cipher|password|uuid|alterId|udp)(\"*)/g,"$1") @@ -3089,6 +3089,64 @@ function yamlcheck(cnt){ } } +//2026-01-07 + +/** +* 将不规范的 JS 对象字符串转换为标准 JSON 对象 +*/ +function superMagicParse(str) { + let s = str; + $notify(1,1,s) + // 1. 结构修复:解决你的 "...right"]" 缺少 "}" 的问题 + // 逻辑:如果发现 冒号+值+"]" 的组合,说明少了一个 "}",把它变成 "}]" + // (这里兼容了值带引号或不带引号的情况) + s = s.replace(/(:\s*(?:".*?"|[^,}\]]+?))\s*]/g, '$1}]'); + $notify(1,2,s) + // 2. 补全 Key 的引号 + // 逻辑:匹配 { 或 , 开头,后面跟着“非冒号的任意字符”,直到冒号为止 + // 允许 key 中包含字母、数字、下划线、横杠 - 等 + s = s.replace(/([{\s,])([a-zA-Z0-9_\-]+)\s*:/g, '$1"$2":'); + + // 3. 补全 Value 的引号 (核心修改部分) + // 逻辑:匹配 冒号,后面捕获“非引号、非逗号、非括号”的一串字符 + s = s.replace(/:\s*([^",}\]]+?)\s*(?=[,}\]])/g, (match, rawValue) => { + const val = rawValue.trim(); + + // A. 如果是纯数字,保持原样 (支持负数和小数) + if (!isNaN(Number(val))) { + return `:${val}`; + } + + // B. 如果是关键字,保持原样 + if (['true', 'false', 'null', 'undefined'].includes(val)) { + return `:${val}`; + } + + // C. 其他情况(包括带 - 的字符串、UUID、日期等),全部加上双引号 + return `:"${val}"`; + }); + $notify(1,3,s) + // 调试输出,这一步很有用,能让你看到变成什么样了 + // console.log("标准化后的字符串:", s); + + try { + return s;//JSON.parse(s); + } catch (e) { + //console.error("解析失败,可能是标点符号仍有错误:", e.message); + return null; // 或者返回 undefined + } +} + +//yaml string - {} type direct to json +function YJSON(cnt) { + cnt=cnt.replace(/proxies\:\n.*?\-/g,"{\"proxies\":[").replace(/}\s*\n.*?\-/g,"},").replace(/\n/g,"")+"]}" + //console.log(cnt) + cnt=superMagicParse(cnt) + //console.log("repair"+"\n"+cnt) + return cnt +} + + // Clash parser function Clash2QX(cnt) { const yaml = new YAML() @@ -3318,7 +3376,7 @@ function CVL2QX(cnt){ const ppbk=getValue(()=>cnt["reality-opts"]["public-key"]) const psid=getValue(()=>cnt["reality-opts"]["short-id"]) pbk=ppbk? "reality-base64-pubkey="+ppbk : "" - sid=psid? "reality-hex-shortid="+psid : "" + sid=typeof(psid)=='string'? "reality-hex-shortid="+psid : "" // console.log(obfs) const phost = getValue(()=>cnt["ws-opts"]["headers"]["Host"]) ohost = cnt["ws-headers"]? "obfs-host=" + cnt["ws-headers"]["Host"] : "" @@ -3339,7 +3397,7 @@ function CVL2QX(cnt){ // UDP/TFO 参数 (强制 surge/quanx 类型转换) function XUDP(cnt,pudp) { - var udp = pudp == 1 && /^(shadowsocks|trojan|vmess)/.test(cnt.trim()) ? "udp-relay=true, " : "udp-relay=false, " + var udp = pudp == 1 && /^(shadowsocks|trojan|vmess|vless)/.test(cnt.trim()) ? "udp-relay=true, " : "udp-relay=false, " if(cnt.indexOf("udp-relay") != -1){ var cnt0 = cnt.replace(RegExp("udp\-relay.*?\,", "gmi"), udp) }else{