diff --git a/Scripts/resource-parser.js b/Scripts/resource-parser.js index 474dd83..087da6f 100644 --- a/Scripts/resource-parser.js +++ b/Scripts/resource-parser.js @@ -1,5 +1,5 @@ /** -☑️ 资源解析器 ©𝐒𝐡𝐚𝐰𝐧 ⟦2022-04-12 09:52⟧ +☑️ 资源解析器 ©𝐒𝐡𝐚𝐰𝐧 ⟦2022-04-12 18:52⟧ ---------------------------------------------------------- 🛠 发现 𝐁𝐔𝐆 请反馈: @ShawnKOP_bot ⛳️ 关注 🆃🅶 相关频道: https://t.me/QuanX_API @@ -420,7 +420,7 @@ function Type_Check(subs) { var RuleK = ["host,", "-suffix,", "domain,", "-keyword,", "ip-cidr,", "ip-cidr6,", "geoip,", "user-agent,", "ip6-cidr,"]; var DomainK = ["domain-set,"] var QuanXK = ["shadowsocks=", "trojan=", "vmess=", "http="]; - var SurgeK = ["=ss,", "=vmess,", "=trojan,", "=http,", "=custom,", "=https,", "=shadowsocks", "=shadowsocksr"]; + var SurgeK = ["=ss,", "=vmess,", "=trojan,", "=http,", "=custom,", "=https,", "=shadowsocks", "=shadowsocksr", "=sock5"]; var ClashK = ["proxies:"] var SubK = ["dm1lc3M", "c3NyOi8v", "CnNzOi8", "dHJvamFu", "c3M6Ly", "c3NkOi8v", "c2hhZG93",,"aHR0c", "CnRyb2phbjo"]; var RewriteK = [" url "] @@ -1158,8 +1158,8 @@ function ReplaceReg(cnt, para) { //混合订阅类型,用于未整体进行 base64 encode 以及已经 decode 后的类型 function Subs2QX(subs, Pudp, Ptfo, Pcert0, PTls13) { var list0 = subs.split("\n"); - var QuanXK = ["shadowsocks=", "trojan=", "vmess=", "http="]; - var SurgeK = ["=ss,", "=vmess,", "=trojan,", "=http,", "=custom,"]; + var QuanXK = ["shadowsocks=", "trojan=", "vmess=", "http=","socks5="]; + var SurgeK = ["=ss,", "=vmess,", "=trojan,", "=http,", "=https", "=custom,", "=socks5", "=socks5-tls"]; var LoonK = ["=shadowsocks", "=shadowsocksr"] var QXlist = []; var failedList = []; @@ -1171,6 +1171,7 @@ function Subs2QX(subs, Pudp, Ptfo, Pcert0, PTls13) { var tag0 = list0[i].indexOf("tag=")!=-1 ? list0[i].split(/\&*(emoji|udp|tf0|cert|rename|replace)\=/)[0].split("tag=")[1] : "" list0[i] = (type == "vmess" || type=="ssr") ? list0[i].split(/#|,|,/)[0] : list0[i] const NodeCheck = (item) => listi.toLowerCase().indexOf(item) != -1; + const NodeCheck1 = (item) => listi.toLowerCase().indexOf(item) == 0; try { if (type == "vmess" && list0[i].indexOf("remarks=") == -1) { var bnode = Base64.decode(list0[i].split("vmess://")[1]) @@ -1183,6 +1184,12 @@ function Subs2QX(subs, Pudp, Ptfo, Pcert0, PTls13) { } else if (type == "vmess" && list0[i].indexOf("remarks=") != -1) { //shadowrocket 类型 node = VR2QX(list0[i], Pudp, Ptfo, Pcert0, PTls13) node = tag0 != "" ? URI_TAG(node, tag0) : node + } else if (type == "socks" && list0[i].indexOf("remarks=") != -1) { //shadowrocket socks5 类型 + node = S5R2QX(list0[i]) + node = tag0 != "" ? URI_TAG(node, tag0) : node + } else if (type == "ssocks" && list0[i].indexOf("remarks=") != -1) { //shadowrocket socks5-tls 类型 + node = S5R2QX(list0[i],tlsp="over-tls") + node = tag0 != "" ? URI_TAG(node, tag0) : node } else if (type == "ssr") { node = SSR2QX(list0[i], Pudp, Ptfo) node = tag0 != "" ? URI_TAG(node, tag0) : node @@ -1198,13 +1205,13 @@ function Subs2QX(subs, Pudp, Ptfo, Pcert0, PTls13) { if (listi.indexOf("@") != -1) { node = HPS2QX(list0[i], Ptfo, Pcert0, PTls13) node = tag0 != "" ? URI_TAG(node, tag0) : node - } else { + } else { // b64 类型 var listh = Base64.decode(listi.split("https://")[1].split("#")[0]) listh = "https://" + listh + "#" + listi.split("https://")[1].split("#")[1] node = HPS2QX(listh, Ptfo, Pcert0, PTls13) node = tag0 != "" ? URI_TAG(node, tag0) : node } - } else if (QuanXK.some(NodeCheck)) { + } else if (QuanXK.some(NodeCheck1)) { node = QX_TLS(isQuanX(list0[i])[0], Pcert0, PTls13) } else if (SurgeK.some(NodeCheck)) { node = QX_TLS(Surge2QX(list0[i])[0], Pcert0, PTls13) @@ -1235,6 +1242,7 @@ function Subs2QX(subs, Pudp, Ptfo, Pcert0, PTls13) { if (failedList.length > 0 && Pntf0 != 0) { $notify(`⚠️ 有 ${failedList.length} 条数据解析失败, 已忽略`, "出错内容👇", failedList.join("\n")); } + //$notify("QXList","check below content",QXlist) return QXlist; } @@ -1403,6 +1411,26 @@ function VR2QX(subs, Pudp, Ptfo, Pcert0, PTls13) { return node } +//Shadowrocket 格式的 sockst URI 转换 +function S5R2QX(cnt,tlsp="false") { + var listh = Base64.decode(cnt.split("socks://")[1].split("#")[0].split("?")[0]) + server=listh+"#"+cnt.split("?")[1] + var nss = [] + if (server != "") { + var ipport = "socks5=" + server.split("@")[1].split("#")[0].split("/")[0]; + var uname = "username=" + server.split(":")[0]; + var pwd = "password=" + server.split("@")[0].split(":")[1]; + var tag = "tag=" + decodeURIComponent(server.split("remarks=")[1].split("&")[0]); + var tls = tlsp=="false"? "":"over-tls=true" + var cert = Pcert0 != 0 ? "tls-verification=true" : "tls-verification=false"; + cert = tls == ""? "":cert + var tfo = Ptfo0 == 1 ? "fast-open=true" : "fast-open=false"; + nss.push(ipport, uname, pwd, tls, cert, tfo, tag) + } + var QX = nss.filter(Boolean).join(","); + return QX +} + //V2RayN uri转换成 QUANX 格式 function V2QX(subs, Pudp, Ptfo, Pcert0, PTls13) { @@ -1735,7 +1763,7 @@ function isQuanX(content) { var cnti = cnts[i]; if (cnti.indexOf("=") != -1 && cnti.indexOf("tag") != -1) { var cnt = cnti.split("=")[0].trim() - if (cnt == "http" || cnt == "shadowsocks" || cnt == "trojan" || cnt == "vmess") { + if (cnt == "http" || cnt == "shadowsocks" || cnt == "trojan" || cnt == "vmess"|| cnt == "socks5") { nlist.push(QXFix(cnti)) } } @@ -2084,6 +2112,8 @@ function Surge2QX(conf) { node = SVmess2QX(cnt) //surge 3的Vmess } else if (cnt.split("=")[1].split(",")[0].indexOf("ss") != -1) { node = SSS2QX(cnt) //surge 3的SS + } else if (cnt.split("=")[1].split(",")[0].indexOf("socks5") != -1) { + node = SS52QX(cnt) //surge 3的Socks5 } else if (cnt.split("=")[1].split(",")[0].indexOf("custom") != -1) { node = SCT2QX(cnt) //surge2写法 } @@ -2141,6 +2171,7 @@ function SSS2QX(content) { return nserver } + // surge 中的 Vmess 类型 function SVmess2QX(content) { var cnt = content; @@ -2176,7 +2207,7 @@ function SVmess2QX(content) { function isSurge(content) { if (content.indexOf("=") != -1) { cnt = content.split("=")[1].split(",")[0].trim() - if (cnt == "http" || cnt == "ss" || cnt == "trojan" || cnt == "vmess" || cnt == "custom") { + if (cnt == "http" || cnt == "ss" || cnt == "trojan" || cnt == "vmess" || cnt == "custom" || cnt == "https" || cnt == "socks5"|| cnt == "socks5-tls") { return content } } @@ -2225,6 +2256,25 @@ function Shttp2QX(content) { return nserver } +// surge 中的 socks5 类型 +function SS52QX(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() == "socks5-tls" ? "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 = cnt.replace(/ /g,"").indexOf("skip-cert-verify=false") != -1 ? "tls-verification=true" : "tls-verification=false"; + pvefify = Pcert0 == 1? "tls-verification=true" : pverify ; + var ptls13 = paraCheck(cnt, "tls13") == "true" ? "tls13=true" : "tls13=false"; + ptls = ptls + ", " + pverify + ", " + ptls13 + } + var nserver = puname != "" ? "socks5= " + [ipport, puname, pwd, ptls, ptfo, tag].join(", ") : "socks5= " + [ipport, ptls, ptfo, tag].join(", "); + return nserver +} + function Loon2QX(cnt) { var type = cnt.split("=")[1].split(",")[0].trim() var node = "" @@ -2325,7 +2375,9 @@ function Clash2QX(cnt) { node = CT2QX(node) } else if (typec == "http"){ node = CH2QX(node) - } + } else if (typec == "socks5"){ + node = CS52QX(node) + } node = Pudp0 != 0 ? XUDP(node,Pudp0) : node node = Ptfo0 != 0 ? XTFO(node,Ptfo0) : node nodelist.push(node) @@ -2457,6 +2509,25 @@ function CH2QX(cnt){ return node } +// Clash socks5 +function CS52QX(cnt){ + tag = "tag="+cnt.name.replace(/\\U.+?\s{1}/gi," ") + ipt = cnt.server+":"+cnt.port + uname = cnt.username ? "username=" + cnt.username : "" + pwd = cnt.password && typeof(cnt.password) == "string" ? "password=" + cnt.password : "" + tls = cnt.tls ? "over-tls=true" : "" + cert = cnt["skip-cert-verify"] && cnt.tls ? "tls-verification=false" : "" + if (Pcert0 == 1 && cnt.tls) { + cert = "tls-verification=true" + } else if (Pcert0 != 1 && cnt.tls) { + cert = "tls-verification=false" + } + node = "socks5="+[ipt, uname, pwd, tls, cert, tag].filter(Boolean).join(", ") + //console.log(node) + return node +} + + // UDP/TFO 参数 (强制 surge/quanx 类型转换) function XUDP(cnt,pudp) { var udp = pudp == 1 && /^(shadowsocks|trojan|vmess)/.test(cnt.trim()) ? "udp-relay=true, " : "udp-relay=false, "