优化部分转换逻辑

This commit is contained in:
Shawn
2020-08-29 16:28:40 +08:00
parent c88781ae26
commit e11da8cef0

View File

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