mirror of
https://github.com/KOP-XIAO/QuantumultX.git
synced 2026-01-25 13:05:10 +00:00
3070 lines
143 KiB
JavaScript
3070 lines
143 KiB
JavaScript
/**
|
||
☑️ 资源解析器 ©𝐒𝐡𝐚𝐰𝐧 ⟦2022-03-02 13:45⟧
|
||
----------------------------------------------------------
|
||
🛠 发现 𝐁𝐔𝐆 请反馈: @ShawnKOP_bot
|
||
⛳️ 关注 🆃🅶 相关频道: https://t.me/QuanX_API
|
||
🗣 🆃🄷🄰🄽🄺🅂 🆃🄾 @Jamie CHIEN, @M**F**, @c0lada, @Peng-YM, @vinewx, @love4taylor, @shadowdogy
|
||
|
||
🤖 主要功能:
|
||
❶ 将其它格式的⟦服务器订阅⟧解析成 𝐐𝐮𝐚𝐧𝐭𝐮𝐦𝐮𝐥𝐭 𝐗 格式
|
||
☑︎ 支持 𝐕2𝐫𝐚𝐲𝐍/𝗦𝗦(𝗥/𝗗)/𝗛𝗧𝗧𝗣(𝗦)/𝗧𝗿𝗼𝗷𝗮𝗻/𝗤𝘂𝗮𝗻𝘁𝘂𝗺𝘂𝗹𝘁(𝗫)/𝗦𝘂𝗿𝗴𝗲/𝐂𝐥𝐚𝐬𝐡/𝐒𝐡𝐚𝐝𝐨𝐰𝐫𝐨𝐜𝐤𝐞𝐭/𝐋𝐨𝐨𝐧 格式
|
||
☑︎ 提供说明 1⃣️ 中的可选个性化参数(筛选、重命名 等)
|
||
❷ 𝗿𝗲𝘄𝗿𝗶𝘁𝗲(重写) & 𝗳𝗶𝗹𝘁𝗲𝗿(分流) 的 转换 & 筛选
|
||
☑︎ 用于禁用/修改远程引用中某(几)项 𝗿𝗲𝘄𝗿𝗶𝘁𝗲/𝗵𝗼𝘀𝘁𝗻𝗮𝗺𝗲/𝗳𝗶𝗹𝘁𝗲𝗿
|
||
☑︎ 𝐒𝐮𝐫𝐠𝐞/𝐂𝐥𝐚𝐬𝐡 类型规则 𝗹𝗶𝘀𝘁 与 模块 𝐦𝐨𝐝𝐮𝐥𝐞 的解析使用
|
||
----------------------------------------------------------
|
||
0️⃣ 在 ⟦订阅链接⟧ 后加 "#" 使用, 不同参数用 "&" 连接
|
||
⚠️ ☞ “你的订阅连接”#emoji=1&tfo=1&in=香港+台湾
|
||
❖ 本地资源片段引用, 请将参数如 "#in=𝘅𝘅𝘅&out=yyy" 填入文件第 ① 行
|
||
❖ 🚦 支持中文, "操作" 以下特殊字符时请先替换 🚦
|
||
∎ "+"⇒"%2B", 空格⇒"%20", "@"⇒"%40", "&"⇒"%26", "."⇒"\."
|
||
|
||
1️⃣ ⟦𝐬𝐞𝐫𝐯𝐞𝐫 节点⟧ ➠ 参数说明:
|
||
⦿ emoji=1(国行设备用2)/-1, 添加/删除节点名内地区旗帜;
|
||
⦿ udp=1/-1, tfo=1/-1, 分别强制开启(关闭) 𝐮𝐝𝐩-𝐫𝐞𝐥𝐚𝐲/𝐟𝐚𝐬𝐭-𝐨𝐩𝐞𝐧;
|
||
⦿ tls13=1, cert=1, 分别开启 𝐭𝐥𝐬1.3 及 𝐭𝐥𝐬 证书验证(默认关闭);
|
||
⦿ in, out, regex, regout 分别为 保留、删除、正则保留、正则删除 节点;
|
||
❖ in, out 中多参数(逻辑"或")用 "+", 逻辑"与"用 "." 表示;
|
||
❖ in/out/regex/regout 均对节点的完整信息进行匹配(类型、端口、加密等);
|
||
❖ 示范: "in=香港.0\.2倍率+台湾&out=BGP®ex=iplc"
|
||
⦿ rename 重命名, "旧名@新名", "前缀@", "@后缀", 用 "+" 连接多个参数;
|
||
❖ 删除字段: "字段1.字段2☠️", 想删除 "." 时用 "\." 替代
|
||
❖ 示范: "rename=香港@𝐇𝐊+[𝐒𝐒]@+@[1𝐗]+流量.0\.2☠️"
|
||
❖ 默认 emoji 先生效, 如想调换顺序, 请用 𝗿𝗿𝗻𝗮𝗺𝗲 参数
|
||
⦿ replace 正则替换节点中字段, 可用于重命名/更改加密方式等
|
||
❖ replace=regex1@𝘀𝘁𝗿1+regex2@𝘀𝘁𝗿2
|
||
❖ replace=regex1@ 则等效于 delreg 参数
|
||
⦿ 占位符,可用于 rename/replace 等操作
|
||
❖ $type0/1/2/3/4/5/6/7 占位符,将节点类型(ss/ssr/vmess 等)作为可操作参数,如
|
||
∎ rename=@|$type2
|
||
∎ 样式分别为 "𝐬𝐬","𝐒𝐒","🅢🅢","🆂🆂","ⓢⓢ","🅂🅂","𝕊𝕊","ˢˢ"
|
||
❖ $index0/1/2/3/4/5/6/7/8 占位符,将节点的序号作为可操作参数,如
|
||
∎ rename=@「$index1」
|
||
∎ 样式分别为 1\①\❶\⓵\𝟙\¹\₁\𝟏\𝟷
|
||
❖ $emoji1/2 占位符, 将emoji(🇭🇰 等)作为可操作参数
|
||
∎ rename=@「$emoji1」
|
||
❖ $tag 占位符,将订阅的 tag 作为可操作参数,如
|
||
∎ 可接数字以单独给 tag 添加字母/数字样式
|
||
∎ rename=@「$tag34」, 样式同下边的 ptn/npt
|
||
⦿ ptn=1-8, 将节点名英文替换成样式 ⇒ 🅰/🄰/𝐀/𝗮/𝔸/𝕒/ᵃ/ᴬ
|
||
⦿ npt=1-8, 将节点名数字替换成样式 ⇒ ①\❶\⓵\𝟙\¹\₁\𝟏\𝟷
|
||
⦿ delreg, 利用正则表达式来删除 "节点名" 中的字段(⚠️ 慎用)
|
||
⦿ aead=-1, 关闭Vmess 的AEAD 参数
|
||
⦿ sort=1/-1/x/参数规则, 按节点名 正/逆/随机/参数规则 排序
|
||
❖ 参数规则是正则表达式或简单关键词, 用"<" 或 ">" 连接
|
||
❖ sort=🇭🇰>🇸🇬>🇯🇵>🇺🇸 , 靠前排序
|
||
❖ sort=IEPL<IPLC<BGP , 靠后排序
|
||
⦿ info=1, 开启通知提示机场 ✈️ 流量信息(如有提供);
|
||
⦿ del=1, 有重名节点时用此参数删除重复节点(默认改名保留)
|
||
⦿ ⟦进阶参数⟧: 𝘀𝗳𝗶𝗹𝘁𝗲𝗿/𝘀𝗿𝗲𝗻𝗮𝗺𝗲, 传入一段 base64 编码的脚本, 可用于更为复杂的[过滤/重命名] 需求
|
||
❖ 说明: https://github.com/KOP-XIAO/QuantumultX/pull/9
|
||
|
||
2⃣️ ⟦𝐫𝐞𝐰𝐫𝐢𝐭𝐞 重写⟧/⟦𝐟𝐢𝐥𝐭𝐞𝐫 分流⟧ ➠ 参数说明:
|
||
⦿ in, out, 根据关键词 保留/禁用 相关分流、重写规则;
|
||
⦿ inhn, outhn, “保留/删除”主机名(𝒉𝒐𝒔𝒕𝒏𝒂𝒎𝒆);
|
||
❖ 示范: 禁用 "淘宝比价" 及 "weibo" 的 js 同主机名
|
||
𝐡𝐭𝐭𝐩𝐬://𝐦𝐲𝐥𝐢𝐬𝐭#out=tb_price.js+wb_ad.js&outhn=weibo
|
||
⦿ regex/regout, 正则保留/删除, 请自行折腾正则表达式;
|
||
❖ 可与 in(hn)/out(hn) 一起使用,in(hn)/out(hn) 会优先执行;
|
||
❖ 对 𝒉𝒐𝒔𝒕𝒏𝒂𝒎𝒆 & 𝐫𝐞𝐰𝐫𝐢𝐭𝐞/𝐟𝐢𝐥𝐭𝐞𝐫 同时生效(⚠️ 慎用)
|
||
⦿ policy 参数, 用于直接指定策略组,或为 𝐒𝐮𝐫𝐠𝐞 类型 𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 生成策略组(默认"𝐒𝐡𝐚𝐰𝐧"策略组);
|
||
⦿ pset=regex1@policy1+regex2@policy2, 为同一分流规则中不同关键词(允许正则表达式)指定不同策略组;
|
||
⦿ replace 参数, 正则替换 𝐟𝐢𝐥𝐭𝐞𝐫/𝐫𝐞𝐰𝐫𝐢𝐭𝐞 内容, regex@newregex;
|
||
❖ 将淘宝比价中脚本替换成 lite 版本, tiktok 中 JP 换成 KR
|
||
∎ replace=(price)(.*)@$1_lite$2+jp@kr
|
||
⦿ dst=rewrite/filter,分别为将 𝐦𝐨𝐝𝐮𝐥𝐞&𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 转换成 重写/分流;
|
||
❖ ⚠️ 默认将 𝐦𝐨𝐝𝐮𝐥𝐞 转换到重写, 𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 转成分流
|
||
❖ ⚠️ 把 𝗿𝘂𝗹𝗲-𝘀𝗲𝘁 中 𝐮𝐫𝐥-𝐫𝐞𝐠𝐞𝐱 转成重写时, 必须要加 dst=rewrite;
|
||
❖ ⚠️ 把 𝐦𝐨𝐝𝐮𝐥𝐞 中的分流规则转换时, 必须要加 dst=filter
|
||
⦿ cdn=1, 将 github 脚本的地址转换成免翻墙cdn.jsdelivr.net
|
||
⦿ fcr=1/2, 为分流规则添加 force-cellular/multi-interface 参数,强制移动数据/混合数据
|
||
⦿ via=接口, 为分流规则添加 via-interface 参数, 0 表示 via-interface=%TUN%
|
||
|
||
3⃣️ 其他参数
|
||
⦿ 通知参数 ntf=0/1, 用于 关闭/打开 资源解析器的提示通知
|
||
❖ 𝗿𝗲𝘄𝗿𝗶𝘁𝗲/𝗳𝗶𝗹𝘁𝗲𝗿 默认“开启”通知提示, 以防规则误删除
|
||
❖ 𝘀𝗲𝗿𝘃𝗲𝗿 资源解析则默认”关闭“通知提示
|
||
⦿ 类型参数 type=domain-set/rule/module/list/nodes
|
||
❖ 当解析器未能正确识别类型时, 可尝试使用此参数强制指定
|
||
⦿ 隐藏参数 hide=1, 隐藏筛除的分流/重写,默认方式为禁用
|
||
----------------------------------------------------------
|
||
*/
|
||
|
||
/**
|
||
* 使用说明,
|
||
0️⃣ 在QuantumultX 配置文件中[general] 部分,加入
|
||
resource_parser_url = https://raw.githubusercontent.com/KOP-XIAO/QuantumultX/master/Scripts/resource-parser.js
|
||
⚠️⚠️如提示"没有自定义解析器",请长按右下角图标后点击左侧刷新按钮,更新资源,后台退出 app,直到出现解析器说明
|
||
|
||
------------------------------
|
||
*/
|
||
|
||
//beginning 解析器正常使用,調試註釋此部分
|
||
|
||
let [link0, content0, subinfo] = [$resource.link, $resource.content, $resource.info]
|
||
const subtag = $resource.tag != undefined ? $resource.tag : "";
|
||
////// 非 raw 链接的沙雕情形
|
||
content0 = content0.indexOf("DOCTYPE html") != -1 && link0.indexOf("github.com") != -1 ? ToRaw(content0) : content0 ;
|
||
//ends 正常使用部分,調試註釋此部分
|
||
|
||
|
||
var para = /^(http|https)\:\/\//.test(link0) ? link0 : content0.split("\n")[0];
|
||
var para1 = para.slice(para.indexOf("#") + 1).replace(/\$type/g,"node_type_para_prefix").replace(/\$emoji/g,"node_emoji_flag_prefix").replace(/\$tag/g,"node_tag_prefix").replace(/\$index/g,"node_index_prefix") //防止参数中其它位置也存在"#"
|
||
var mark0 = para.indexOf("#") != -1 ? true : false; //是否有參數需要解析
|
||
var Pinfo = mark0 && para1.indexOf("info=") != -1 ? para1.split("info=")[1].split("&")[0] : 0;
|
||
var ntf_flow = 0;
|
||
//常用量
|
||
const Base64 = new Base64Code();
|
||
const escapeRegExp = str => str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); //处理特殊符号以便正则匹配使用
|
||
var link1 = link0.split("#")[0]
|
||
const qxpng = "https://raw.githubusercontent.com/crossutility/Quantumult-X/master/quantumult-x.png" // server sub-info link
|
||
const subinfo_link = { "open-url": "https://t.me/QuanX_API", "media-url": "https://shrtm.nu/ebAr" };
|
||
const subinfo_link1 = { "open-url": link1, "media-url": "https://shrtm.nu/uo13" } // server sub-info link(fake-nodes)
|
||
const rwrite_link = { "open-url": link1, "media-url": "https://shrtm.nu/x3o2" } // rewrite filter link
|
||
const rwhost_link = { "open-url": link1, "media-url": "https://shrtm.nu/0n5J" } // hostname filter link
|
||
const rule_link = { "open-url": link1, "media-url": "https://shrtm.nu/cpHD" } // rule filter link
|
||
const nan_link = { "open-url": link1, "media-url": qxpng } // nan error link
|
||
const bug_link = { "open-url": "https://t.me/ShawnKOP_bot", "media-url": "https://shrtm.nu/obcB" } // bug link
|
||
const sub_link = { "open-url": link1, "media-url": "https://shrtm.nu/ebAr" } // server link
|
||
|
||
|
||
SubFlow() //流量通知
|
||
|
||
|
||
// 参数获取
|
||
var Pin0 = mark0 && para1.indexOf("in=") != -1 ? (para1.split("in=")[1].split("&")[0].split("+")).map(decodeURIComponent) : null;
|
||
var Pout0 = mark0 && para1.indexOf("out=") != -1 ? (para1.split("out=")[1].split("&")[0].split("+")).map(decodeURIComponent) : null;
|
||
var Psfilter = mark0 && para1.indexOf("sfilter=") != -1 ? Base64.decode(para1.split("sfilter=")[1].split("&")[0]) : null; // script filter
|
||
var Preg = mark0 && para1.indexOf("regex=") != -1 ? decodeURIComponent(para1.split("regex=")[1].split("&")[0]).replace(/\,/g,",") : null; //server正则过滤参数
|
||
var Pregout = mark0 && para1.indexOf("regout=") != -1 ? decodeURIComponent(para1.split("regout=")[1].split("&")[0]).replace(/\,/g,",") : null; //server正则删除参数
|
||
var Pregdel = mark0 && para1.indexOf("delreg=") != -1 ? decodeURIComponent(para1.split("delreg=")[1].split("&")[0]).replace(/\,/g,",") : null; // 正则删除参数
|
||
var Phin0 = mark0 && para1.indexOf("inhn=") != -1 ? (para1.split("inhn=")[1].split("&")[0].split("+")).map(decodeURIComponent) : null; //hostname
|
||
var Phout0 = mark0 && para1.indexOf("outhn=") != -1 ? (para1.split("outhn=")[1].split("&")[0].split("+")).map(decodeURIComponent) : null; //hostname
|
||
var Preplace = mark0 && para1.indexOf("replace=") != -1 ? para1.split("replace=")[1].split("&")[0] : null; //filter/rewrite 正则替换
|
||
var Pemoji = mark0 && para1.indexOf("emoji=") != -1 ? para1.split("emoji=")[1].split("&")[0] : null;
|
||
var Pdbg = mark0 && para1.indexOf("dbg=") != -1 ? para1.split("dbg=")[1].split("&")[0] : null;
|
||
var Pudp0 = mark0 && para1.indexOf("udp=") != -1 ? para1.split("udp=")[1].split("&")[0] : 0;
|
||
var Ptfo0 = mark0 && para1.indexOf("tfo=") != -1 ? para1.split("tfo=")[1].split("&")[0] : 0;
|
||
var Prname = mark0 && para1.indexOf("rename=") != -1 ? para1.split("rename=")[1].split("&")[0].split("+") : null;
|
||
var Psrename = mark0 && para1.indexOf("srename=") != -1 ? Base64.decode(para1.split("srename=")[1].split("&")[0]) : null; // script rename
|
||
var Prrname = mark0 && para1.indexOf("rrname=") != -1 ? para1.split("rrname=")[1].split("&")[0].split("+") : null;
|
||
var Psuffix = mark0 && para1.indexOf("suffix=") != -1 ? para1.split("suffix=")[1].split("&")[0] : 0;
|
||
var Ppolicy = mark0 && para1.indexOf("policy=") != -1 ? decodeURIComponent(para1.split("policy=")[1].split("&")[0]) : "Shawn";
|
||
var Ppolicyset = mark0 && para1.indexOf("pset=") != -1 ? decodeURIComponent(para1.split("pset=")[1].split("&")[0]) : "";
|
||
var Pcert0 = mark0 && para1.indexOf("cert=") != -1 ? para1.split("cert=")[1].split("&")[0] : 0;
|
||
var Psort0 = mark0 && para1.indexOf("sort=") != -1 ? para1.split("sort=")[1].split("&")[0] : 0;
|
||
var PsortX = mark0 && para1.indexOf("sortx=") != -1 ? para1.split("sortx=")[1].split("&")[0] : 0;
|
||
var PTls13 = mark0 && para1.indexOf("tls13=") != -1 ? para1.split("tls13=")[1].split("&")[0] : 0;
|
||
var Pntf0 = mark0 && para1.indexOf("ntf=") != -1 ? para1.split("ntf=")[1].split("&")[0] : 2;
|
||
var Phide = mark0 && para1.indexOf("hide=") != -1 ? para1.split("hide=")[1].split("&")[0] : 0;
|
||
var Pb64 = mark0 && para1.indexOf("b64=") != -1 ? para1.split("b64=")[1].split("&")[0] : 0;
|
||
var emojino = [" 0️⃣ ", " 1⃣️ ", " 2⃣️ ", " 3⃣️ ", " 4⃣️ ", " 5⃣️ ", " 6⃣️ ", " 7⃣️ ", " 8⃣️ ", " 9⃣️ ", " 🔟 "]
|
||
var pfi = Pin0 ? "in=" + Pin0.join(", ") + ", " : ""
|
||
var pfo = Pout0 ? "out=" + Pout0.join(", ") : ""
|
||
var pfihn = Phin0 ? "inhn=" + Phin0.join(", ") + ", " : ""
|
||
var pfohn = Phout0 ? "outhn=" + Phout0.join(", ") : ""
|
||
var Pcnt = para1.indexOf("cnt=") != -1 ? para1.split("cnt=")[1].split("&")[0] : 0;
|
||
var Pcap = para1.indexOf("cap=") != -1 ? para1.split("cap=")[1].split("&")[0] : "";
|
||
var Pptn = para1.indexOf("ptn=") != -1 ? para1.split("ptn=")[1].split("&")[0] : ""; //花式英文字符
|
||
var Pnptn = para1.indexOf("npt=") != -1 ? para1.split("npt=")[1].split("&")[0] : ""; //花式数字
|
||
var Pcdn = para1.indexOf("cdn=") != -1 ? para1.split("cdn=")[1].split("&")[0] : "";
|
||
let [flow, exptime, errornode, total] = "";
|
||
var Pdel = mark0 && para1.indexOf("del=") != -1 ? para1.split("del=")[1].split("&")[0] : 0; //删除重复节点
|
||
var typeU = para1.indexOf("type=") != -1 ? para1.split("type=")[1].split("&")[0] : "";
|
||
var Pfcr = para1.indexOf("fcr=") != -1 ? para1.split("fcr=")[1].split("&")[0] : ""; // force-cellular 参数
|
||
var Pvia = para1.indexOf("via=") != -1 ? para1.split("via=")[1].split("&")[0] : ""; // via-interface 参数
|
||
var Paead = para1.indexOf("aead=") != -1 ? para1.split("aead=")[1].split("&")[0] : ""; // vmess aead 参数
|
||
|
||
var typeQ = $resource.type? $resource.type:"unsupported" //返回 field 类型参数
|
||
|
||
|
||
|
||
//花漾字 pattern
|
||
var pat=[]
|
||
pat[0] = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","k","r","s","t","u","v","w","x","y","z"]
|
||
pat[1] = ["🅰","🅱","🅲","🅳","🅴","🅵","🅶","🅷","🅸","🅹","🅺","🅻","🅼","🅽","🅾","🅿","🅺","🆁","🆂","🆃","🆄","🆅","🆆","🆇","🆈","🆉"]
|
||
pat[2] = ["🄰","🄱","🄲","🄳","🄴","🄵","🄶","🄷","🄸","🄹","🄺","🄻","🄼","🄽","🄾","🄿","🄺","🅁","🅂","🅃","🅄","🅅","🅆","🅇","🅈","🅉"]
|
||
pat[3] = ["𝐀","𝐁","𝐂","𝐃","𝐄","𝐅","𝐆","𝐇","𝐈","𝐉","𝐊","𝐋","𝐌","𝐍","𝐎","𝐏","𝐊","𝐑","𝐒","𝐓","𝐔","𝐕","𝐖","𝐗","𝐘","𝐙"]
|
||
pat[4] = ["𝗮","𝗯","𝗰","𝗱","𝗲","𝗳","𝗴","𝗵"," |