支持 surge(conf&list)发解析转换

This commit is contained in:
Shawn
2020-05-03 19:10:03 +08:00
committed by GitHub
parent 5953482655
commit 02456ea1fb

View File

@@ -1,9 +1,9 @@
/** /**
#Quantumult X 资源解析器 (2020-05-02: 12:53) #Quantumult X 资源解析器 (2020-05-03: 19:33)
本资源解析器作者: Shawn(@XIAO_KOP), 有问题请反馈: @Shawn_KOP_bot 本资源解析器作者: Shawn(@XIAO_KOP), 有问题请反馈: @Shawn_KOP_bot
主要功能: 将节点订阅解析成 Quantumult X 引用片段, 并提供下列可选参数 (已支持 V2RayN/SSR/SS/Trojan/QuanX 订阅) 主要功能: 将节点订阅解析成 Quantumult X 引用片段, 并提供下列可选参数 (已支持 V2RayN/SSR/SS/Trojan/QuanX(list)/Surge(conf&list)格式)
附赠功能rewrite 复写引用/ filter 分流 过滤 附赠功能rewrite 复写引用/ filter 分流 过滤
0⃣ 在订阅链接后加入 "#" 符号后再加参数, 不同参数间请使用 "&" 来连接, 如: "#in=香港+台湾&emoji=1&tfo=1" 0⃣ 在订阅链接后加入 "#" 符号后再加参数, 不同参数间请使用 "&" 来连接, 如: "#in=香港+台湾&emoji=1&tfo=1"
@@ -16,9 +16,9 @@
4⃣ rename 重命名, rename=旧名@新名, 以及 "前缀@", "@后缀", 用 "+" 连接, 如 "rename=香港@HK+[SS]@+@[1X]" 4⃣ rename 重命名, rename=旧名@新名, 以及 "前缀@", "@后缀", 用 "+" 连接, 如 "rename=香港@HK+[SS]@+@[1X]"
5⃣ rewrite(复写)/filter(分流) 引用的筛选,参数为 "out=xxx", 分流规则额外支持 "policy=xx" 参数, 可用于直接指定策略组,或者为 Surge 格式的 rule-set 生成策略组(默认"Shawn"策略组) 5⃣ rewrite(复写)/filter(分流) 引用的筛选,参数为 "out=xxx", 分流规则额外支持 "policy=xx" 参数, 可用于直接指定策略组,或者为 Surge 格式的 rule-set 生成策略组(默认"Shawn"策略组)
6⃣ info=1, 用于打开服务器类型下转换解析器的提示通知 (默认关闭), rewrite/filter 类型则强制在有 out 参数时开启通知,以免规则误删除 6⃣ info=1, 用于打开服务器类型下转换解析器的提示通知 (默认关闭), rewrite/filter 类型则强制在有 out 参数时开启通知,以免规则误删除
*/ */
@@ -60,6 +60,9 @@ if(type0=="Vmess"){
}else if(type0=="SS"){ }else if(type0=="SS"){
total=SS2QX(content0,Pudp0,Ptfo0); total=SS2QX(content0,Pudp0,Ptfo0);
flag=1 flag=1
}else if(type0=="Surge"){
total=Surge2QX(content0);
flag=1;
}else if(type0=="rewrite"){ }else if(type0=="rewrite"){
flag=2; flag=2;
content0=content0.split("\n"); content0=content0.split("\n");
@@ -112,7 +115,9 @@ function Type_Check(subs){
type="Rule"; type="Rule";
} else if (subs.indexOf("dm1lc3M6Ly")!= -1){ } else if (subs.indexOf("dm1lc3M6Ly")!= -1){
type="Vmess" type="Vmess"
} else if (subs.indexOf("tag")!=-1){ } else if(subs.indexOf("[Proxy]")!=-1){
type="Surge";
}else if (subs.indexOf("tag")!=-1){
type="QuanX" type="QuanX"
} else if (subs.indexOf("c3NyOi8v")!= -1){ } else if (subs.indexOf("c3NyOi8v")!= -1){
type="SSR" type="SSR"
@@ -122,7 +127,9 @@ function Type_Check(subs){
type="SS" type="SS"
} else if(subs.indexOf("hostname")!=-1){ } else if(subs.indexOf("hostname")!=-1){
type="rewrite" type="rewrite"
} } else if(subs.indexOf("ss"||"vmess"||"trojan"||"http")!=-1){
type="Surge"
}
return type return type
} }
@@ -468,6 +475,127 @@ function emoji_handle(servers,Pemoji){
return nlist return nlist
} }
//Surge2QX 转换主函数
function Surge2QX(conf){
var QXlist=conf.split("\n").map(isSurge).filter(Boolean)
var Nlist=[]
for(i=0;i<QXlist.length;i++){
var cnt=QXlist[i];
//console.log(cnt)
if(cnt.indexOf("trojan")!=-1){
Nlist.push(Strojan2QX(cnt))
}else if(cnt.split("=")[1].split(",")[0].indexOf("http")!=-1){
Nlist.push(Shttp2QX(cnt))
}else if(cnt.split("=")[1].split(",")[0].indexOf("vmess")!=-1){
Nlist.push(SVmess2QX(cnt))
}else if(cnt.split("=")[1].split(",")[0].indexOf("ss")!=-1){
Nlist.push(SSS2QX(cnt))
}
}
return(Nlist)
//console.log(Nlist)
}
// surge 中的 SS 类型
function SSS2QX(content){
var cnt=content;
var tag="tag="+cnt.split("=")[0].trim();
var ipport=cnt.split(",")[1].trim()+":"+cnt.split(",")[2].trim();
var pmtd="method="+cnt.split("encrypt-method")[1].split(",")[0].split("=")[1];
var pwd="password="+cnt.split("password")[1].split(",")[0].split("=")[1];
if(cnt.indexOf("obfs")!=-1){
pobfs="obfs="+cnt.replace(/obfs-host/,"").split("obfs")[1].split(",")[0].split("=")[1]
}else {pobfs=""}
var phost=cnt.indexOf("obfs-host")!=-1? "obfs-host"+cnt.split("obfs-host")[1].split(",")[0].trim():"";
if(phost!=""){
pobfs=pobfs+", "+phost
}
var ptfo= paraCheck(cnt,"tfo")=="true"? "fast-open=true":"fast-open=false";
var pudp= paraCheck(cnt,"udp")=="true"? "udp-relay=true":"udp-relay=false";
var nserver= pobfs!=""? "shadowsocks= "+[ipport,pmtd,pwd,pobfs,ptfo,pudp,tag].join(", "):"shadowsocks= "+[ipport,pmtd,pwd,ptfo,pudp,tag].join(", ");
return nserver
}
// surge 中的 Vmess 类型
function SVmess2QX(content){
var cnt=content;
var tag="tag="+cnt.split("=")[0].trim();
var ipport=cnt.split(",")[1].trim()+":"+cnt.split(",")[2].trim();
var puname=cnt.indexOf("username")!=-1? "password="+cnt.split("username")[1].split(",")[0].split("=")[1].trim():"";
var pmtd="method=aes-128-gcm";
var ptls13=paraCheck(cnt,"tls13")=="true"? "tls13=true":"tls13=false";
var pverify=paraCheck(cnt,"skip-cert-verify")=="true"? "tls-verification=false":"tls-verification=true";
if(paraCheck(cnt.replace(/tls13/,""),"tls")=="true" && paraCheck(cnt.replace(/ws-header/,""),"ws")=="true"){
pobfs="obfs=wss"+", "+ptls13+", "+pverify
}else if(paraCheck(cnt.replace(/ws-header/,""),"ws")=="true"){
pobfs="obfs=ws"
}else if(paraCheck(cnt.replace(/tls13/,""),"tls")!="false"){
pobfs="obfs=over-tls"+", "+ptls13+", "+pverify
}else if(paraCheck(cnt.replace(/ws-header/,""),"ws")=="false"){
pobfs=""
}
var puri=paraCheck(cnt,"ws-path")!="false"? "obfs-uri="+cnt.split("ws-path")[1].split(",")[0].split("=")[1].trim():"obfs-uri=/"
var phost=paraCheck(cnt,"ws-headers")!="false"? "obfs-host="+cnt.split("ws-headers")[1].split(",")[0].split("=")[1].split("Host:")[1].trim():"";
if(pobfs.indexOf("ws"||"wss")!=-1){
if(phost!=""){
pobfs=pobfs+", "+puri+", "+phost
}else {pobfs=pobfs+", "+puri}
}
var ptfo= paraCheck(cnt,"tfo")=="true"? "fast-open=true":"fast-open=false";
var nserver= pobfs!=""? "vmess= "+[ipport,puname,pmtd,pobfs,ptfo,tag].join(", "):"vmess= "+[ipport,puname,pmtd,ptfo,tag].join(", ");
return nserver
}
// 用于过滤非节点部分(比如整份配置中其它内容)
function isSurge(content){
if(content.indexOf("=")!=-1){
cnt=content.split("=")[1].split(",")[0].trim()
if(cnt=="http"||cnt=="ss"||cnt=="trojan"||cnt=="vmess"){
return content
}
}
}
// 用于参数检查
function paraCheck(content, para){
if(content.indexOf(para)==-1){
return false
} else{
return content.split(para)[1].split(",")[0].split("=")[1].trim()
}
}
//surge中 trojan 类型转换
function Strojan2QX(content){
var cnt=content;
var tag="tag="+cnt.split("=")[0].trim();
var ipport=cnt.split(",")[1].trim()+":"+cnt.split(",")[2].trim();
var pwd="password="+cnt.split("password")[1].split(",")[0].split("=")[1].trim();
var ptls="over-tls=true";
var ptfo= paraCheck(cnt,"tfo")=="true"? "fast-open=true":"fast-open=false";
var pverify=paraCheck(cnt,"skip-cert-verify")=="true"? "tls-verification=false":"tls-verification=true";
var ptls13=paraCheck(cnt,"tls13")=="true"? "tls13=true":"tls13=false";
var nserver="trojan= "+[ipport,pwd,ptls,ptfo,ptls13,pverify,tag].join(", ");
return nserver
//console.log(nserver)
}
// surge 中的 http 类型
function Shttp2QX(content){
var cnt=content;
var tag="tag="+cnt.split("=")[0].trim();
var ipport=cnt.split(",")[1].trim()+":"+cnt.split(",")[2].trim();
var puname=cnt.indexOf("username")!=-1? "username="+cnt.split("username")[1].split(",")[0].split("=")[1].trim():"";
var pwd=cnt.indexOf("password")!=-1? "password="+cnt.split("password")[1].split(",")[0].split("=")[1].trim():"";
var ptls=cnt.split("=")[1].split(",")[0].trim()=="https"? "over-tls=true":"over-tls=false";
var ptfo= paraCheck(cnt,"tfo")=="true"? "fast-open=true":"fast-open=false";
if(ptls=="over-tls=true"){
var pverify=paraCheck(cnt,"skip-cert-verify")=="true"? "tls-verification=false":"tls-verification=true";
var ptls13=paraCheck(cnt,"tls13")=="true"? "tls13=true":"tls13=false";
ptls=ptls+", "+pverify+", "+ptls13
}
var nserver= puname!=""? "http= "+[ipport,puname,pwd,ptls,ptfo,tag].join(", "):"http= "+[ipport,ptls,ptfo,tag].join(", ");
return nserver
}
// Base64, adapted from internet : https://www.jianshu.com/p/54084db83d70 // Base64, adapted from internet : https://www.jianshu.com/p/54084db83d70
function Base64(){ function Base64(){