diff --git a/Scripts/resource-parser.js b/Scripts/resource-parser.js index 760ba1f..0669676 100644 --- a/Scripts/resource-parser.js +++ b/Scripts/resource-parser.js @@ -1,5 +1,5 @@ /** -☑️ 资源解析器 ©𝐒𝐡𝐚𝐰𝐧 ⟦2020-08-25 10:45⟧ +☑️ 资源解析器 ©𝐒𝐡𝐚𝐰𝐧 ⟦2020-08-29 17:19⟧ ---------------------------------------------------------- 🛠 发现 𝐁𝐔𝐆 请反馈: @Shawn_KOP_bot ⛳️ 关注 🆃🅶 相关频道: https://t.me/QuanX_API @@ -26,21 +26,21 @@ ⦿ 𝗶𝗻, 𝗼𝘂𝘁, 分别为 保留、删除 节点; ❖ 多参数(逻辑"或")用 "+", 逻辑"与"用 "." 表示; ❖ 支持中文, 操作以下特殊字符时请先替换 - ∎ "+"⇒"%2B", 空格⇒"%20", "&"⇒"%26", "."⇒"\." + ∎ "+"⇒"%2B", 空格⇒"%20", "&"⇒"%26", "."⇒"\." ❖ 示范: "𝐢𝐧=香港.0\.2倍率+台湾&𝐨𝐮𝐭=香港%20𝐁𝐆𝐏" ⦿ 𝗿𝗲𝗴𝗲𝘅, 正则筛选, 请自行折腾正则表达式; ❖ 可与 𝗶𝗻/𝗼𝘂𝘁 参数搭配使用, 𝗶𝗻/𝗼𝘂𝘁 会优先执行; ❖ 对节点的完整信息进行匹配(类型、端口、加密等) ⦿ 𝗿𝗲𝗻𝗮𝗺𝗲 重命名, "旧名@新名", "前缀@", "@后缀", 用 "+" 连接多个参数; ❖ 支持中文, 操作以下特殊字符时请先替换 - ∎ "@"⇒"%40","+"⇒"%2B", 空格⇒"%20", "&"⇒"%26" + ∎ "@"⇒"%40","+"⇒"%2B", 空格⇒"%20", "&"⇒"%26" ❖ 删除字段: "字段1.字段2☠️", 想删除 "." 时用 "\." 替代 ❖ 示范: "𝐫𝐞𝐧𝐚𝐦𝐞=香港@𝐇𝐊+[𝐒𝐒]@+@[1𝐗]+流量.0\.2☠️" ❖ 默认emoji 先生效, 如想更改顺序, 请用 𝗿𝗿𝗻𝗮𝗺𝗲 参数 ⦿ 𝗱𝗲𝗹𝗿𝗲𝗴, 利用正则表达式来删除节点名中的字段(⚠️ 慎用) ⦿ 𝘀𝗼𝗿𝘁=1, -1, x, 分别根据节点名 正序/逆序/随机 排序 ⦿ 𝗿𝗲𝗽𝗹𝗮𝗰𝗲 参数, 正则替换 𝐬𝐞𝐫𝐯𝐞𝐫 中内容, 可用于重命名/更改加密方式等 -⦿ 进阶参数: 𝘀𝗳𝗶𝗹𝘁𝗲𝗿/𝘀𝗿𝗲𝗻𝗮𝗺𝗲, 可传入一段 base64 编码的脚本, 用于过滤/重命名订阅节点 +⦿ ⟦进阶参数⟧: 𝘀𝗳𝗶𝗹𝘁𝗲𝗿/𝘀𝗿𝗲𝗻𝗮𝗺𝗲, 传入一段 base64 编码的脚本, 可用于过滤/重命名订阅节点 ❖ 说明: https://github.com/KOP-XIAO/QuantumultX/pull/9 2⃣️ ⟦𝐫𝐞𝐰𝐫𝐢𝐭𝐞 重写⟧/⟦𝐟𝐢𝐥𝐭𝐞𝐫 分流⟧ ➠ 参数说明: @@ -54,10 +54,11 @@ ⦿ 𝗽𝗼𝗹𝗶𝗰𝘆 参数, 用于直接指定策略组,或为 𝐒𝐮𝐫𝐠𝐞 类型 𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 生成策略组(默认"𝐒𝐡𝐚𝐰𝐧"策略组); ⦿ 𝗿𝗲𝗽𝗹𝗮𝗰𝗲 参数, 正则替换 𝐟𝐢𝐥𝐭𝐞𝐫/𝐫𝐞𝐰𝐫𝐢𝐭𝐞 内容, regex@newregex; ❖ 将淘宝比价中脚本替换成 lite 版本, tiktok 中 JP 换成 KR - ∎ 𝐫𝐞𝐩𝐥𝐚𝐜𝐞=(𝐩𝐫𝐢𝐜𝐞)(.*)@$1_𝐥𝐢𝐭𝐞$2+𝐣𝐩@𝐤𝐫 -⦿ 𝗱𝘀𝘁=𝗿𝗲𝗴𝗲𝘅/𝘀𝗰𝗿𝗶𝗽𝘁,分别为只保留 𝐒𝐮𝐫𝐠𝐞-𝐦𝐨𝐝𝐮𝐥𝐞 中的 𝐮𝐫𝐥-𝐫𝐞𝐠𝐞𝐱/𝐬𝐜𝐫𝐢𝐩𝐭(302/307), 默认全部保留; - ❖ 把含 𝐮𝐫𝐥-𝐫𝐞𝐠𝐞𝐱 的 𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 转成重写时, 一定要 𝗱𝘀𝘁=𝗿𝗲𝗴𝗲𝘅; - ❖ 暂不处理 𝐦𝐨𝐝𝐮𝐥𝐞 中非 𝐮𝐫𝐥-𝐫𝐞𝐠𝐞𝐱 的规则类型 + ∎ 𝐫𝐞𝐩𝐥𝐚𝐜𝐞=(𝐩𝐫𝐢𝐜𝐞)(.*)@$1_𝐥𝐢𝐭𝐞$2+𝐣𝐩@𝐤𝐫 +⦿ 𝗱𝘀𝘁=𝐫𝐞𝐰𝐫𝐢𝐭𝐞/𝐟𝐢𝐥𝐭𝐞𝐫,分别为将 𝐦𝐨𝐝𝐮𝐥𝐞&𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 转换成 重写/分流; + ❖ ⚠️ 默认将 𝐦𝐨𝐝𝐮𝐥𝐞 转换到重写, 𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 转成分流 + ❖ ⚠️ 把 𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 中 𝐮𝐫𝐥-𝐫𝐞𝐠𝐞𝐱 转成重写时, 必须要加 𝗱𝘀𝘁=𝐫𝐞𝐰𝐫𝐢𝐭𝐞; + ❖ ⚠️ 把 𝐦𝐨𝐝𝐮𝐥𝐞 中的分流规则转换时, 必须要加 𝗱𝘀𝘁=𝐟𝐢𝐥𝐭𝐞𝐫 3⃣️ 通知参数 𝗻𝘁𝗳=0/1, 用于 关闭/打开 资源解析器的提示通知 ⦿ 𝗿𝗲𝘄𝗿𝗶𝘁𝗲/𝗳𝗶𝗹𝘁𝗲𝗿 默认“开启”通知提示, 以防规则误删除 @@ -177,16 +178,11 @@ if (type0 == "Subs-B64Encode") { total = isQuanX(content0); } else if (type0 == "Surge") { total = Surge2QX(content0); -} else if (type0 == "sgmodule") { // surge module 模块,只处理到 rewrite 部分 - flag = 2 - if (para1.indexOf("dst=regex") != -1) { - total = URX2QX(content0) - } else if (para1.indexOf("dst=script") != -1) { - total = SCP2QX(content0) - } else { - total = SGMD2QX(content0) - } - total = Rewrite_Filter(total, Pin0, Pout0); +} else if (type0 == "sgmodule") { // surge module 模块/含 url-regex 的 rule-set + flag = 2 + total = SGMD2QX(content0) // 转换 + total = Rewrite_Filter(total, Pin0, Pout0); // 筛选过滤 + if (Preplace) { total = ReplaceReg(total, Preplace) } total = total.join("\n") } else if (type0 == "rewrite") { // rewrite 类型 flag = 2; @@ -198,6 +194,7 @@ if (type0 == "Subs-B64Encode") { total = Rule_Handle(content0.split("\n"), Pout0, Pin0); if (Preg && total.length!=0) { // 正则筛选规则 filter total = total.map(Regex).filter(Boolean).join("\n") + if (Preplace) { total = ReplaceReg(total, Preplace) } RegCheck(total, "分流引用", Preg)} total = total.join("\n") } else if (content0.trim() == "") { @@ -210,6 +207,8 @@ if (type0 == "Subs-B64Encode") { flag = -1; } else { flag = 0 } +if (Pcnt == 1) {$notify("final content" , "Nodes", total)} + if (flag == 1) { //server 类型统一处理 if (Pinfo == 1 && ntf_flow == 0) { //假节点类型的流量通知 flowcheck(total) @@ -239,7 +238,7 @@ if (flag == 1) { //server 类型统一处理 total = QXSort(total, Psort0); } total = TagCheck_QX(total) //节点名检查 - if (Pcnt == 1) {$notify("final content" , "Nodes", total)} + //if (Pcnt == 1) {$notify("final content" , "Nodes", total)} if (flag == 1) { total = Base64.encode(total.join("\n")) } //强制节点类型 base64 加密后再导入 Quantumult X $done({ content: total }); } else { $done({ content: total });} @@ -307,10 +306,10 @@ function Type_Check(subs) { type = "Clash"; //console.log(type) content0 = Clash2QX(subs) - } else if (subi.indexOf("[Script]") != -1 || subi.indexOf("[Rule]") != -1 || subs.indexOf("[URL Rewrite]") != -1 || subs.indexOf("[Map Local]") != -1 || para1.indexOf("dst=regex") != -1) { // Surge module /rule-set(url-regex) 类型 + } else if ( (subi.indexOf("[Script]") != -1 || subi.indexOf("[Rule]") != -1 || subs.indexOf("[URL Rewrite]") != -1 || subs.indexOf("[Map Local]") != -1 || subs.indexOf("[MITM]") != -1 || para1.indexOf("dst=rewrite") != -1) && (para1.indexOf("dst=filter") == -1) ) { // Surge 类型 module /rule-set(含url-regex) 类型 type = "sgmodule" } else if (subi.indexOf("hostname=") != -1 || RewriteK.some(RewriteCheck)) { - type = "rewrite" + type = "rewrite" //Quantumult X 类型 rewrite } else if (RuleK.some(RuleCheck) && subs.indexOf(html) == -1) { type = "Rule"; } else if (DomainK.some(RuleCheck)) { @@ -371,13 +370,13 @@ function URX2QX(subs) { var rw = "" subs = subs.split("\n") for (var i = 0; i < subs.length; i++) { - if (subs[i].slice(0, 9) == "URL-REGEX") { + if (subs[i].slice(0, 9) == "URL-REGEX") { // regex 类型 rw = subs[i].replace(/ /g, "").split(",REJECT")[0].split("GEX,")[1] + " url " + "reject-200" nrw.push(rw) - } else if (subs[i].indexOf("data=") != -1 && subs.indexOf("[Map Local]") != -1){ + } else if (subs[i].indexOf("data=") != -1 && subs.indexOf("[Map Local]") != -1){ // Map Local 类型 rw = subs[i].replace(/ /g, "").split("data=")[0] + " url " + "reject-dict" nrw.push(rw) - } + } } return nrw } @@ -409,8 +408,16 @@ function SCP2QX(subs) { } rw = ptn + " url " + type + js nrw.push(rw) - } else if (subs[i].indexOf(" 302") != -1 || subs[i].indexOf(" 307") != -1) { //rewrite 复写 - rw = subs[i].split(" ")[0] + " url " + subs[i].split(" ")[2] + " " + subs[i].split(" ")[3] + } else if (subs[i].indexOf(" 302") != -1 || subs[i].indexOf(" 307") != -1) { //rewrite 302&307 复写 + rw = subs[i].split(" ")[0] + " url " + subs[i].split(" ")[2] + " " + subs[i].split(" ")[1] + nrw.push(rw) + } else if(subs[i].split(" ")[2] == "header") { // rewrite header 类型 + var pget = subs[i].split(" ")[0].split(".com")[1] + var pgetn = subs[i].split(" ")[1].split(".com")[1] + rw = subs[i].split(" ")[0] + " url request-header ^GET " + pget +"(.+\\r\\n)Host:.+(\\r\\n) request-header GET " + pgetn + "$1Host: " + subs[i].split(" ")[1].split("://")[1].split(".com")[0] + ".com$2" + nrw.push(rw) + } else if(subs[i].indexOf(" - reject") != -1) { // rewrite reject 类型 + rw = subs[i].split(" ")[0] + " url reject-200" nrw.push(rw) } else if (subs[i].indexOf("script-path") != -1) { //surge js 旧写法 type = subs[i].split(" ")[0] @@ -1468,8 +1475,8 @@ function YAMLFix(cnt){ cnt = cnt.replace(/{name: /g,"{name: \"").replace(/, server:/g,"\", server:") cnt = cnt.replace(/{|}/g,"").replace(/,/g,"\n ") } - cnt = cnt.replace(/ -\n.*name/g," - name") - console.log(cnt) + cnt = cnt.replace(/ -\n.*name/g," - name").replace(/\$|\`/g,"").split("proxy-providers:")[0].split("proxy-groups:")[0] + //console.log(cnt) return cnt } @@ -1478,6 +1485,7 @@ function Clash2QX(cnt) { const yaml = new YAML() var aa = JSON.stringify(yaml.parse(YAMLFix(cnt))) var bb = JSON.parse(aa).proxies + //$notify("YAML Parse", "content", JSON.stringify(bb)) //console.log(bb) var nl = bb.length var nodelist=[] @@ -1591,7 +1599,7 @@ function CH2QX(cnt){ pwd = cnt.password ? "password=" + cnt.password : "" tls = cnt.tls ? "over-tls=true" : "" cert = cnt["skip-cert-verify"] && cnt.tls ? "tls-verification=false" : "" - if (Pcert0 == 0 && cnt.tls) { cert = "tls-verification=false" } + if (Pcert0 == 0) { cert = "tls-verification=false" } node = "http="+[ipt, uname, pwd, tls, cert, tag].filter(Boolean).join(", ") //console.log(node) return node