Sub-Store/backend/sub-store.min.js
2020-09-09 20:30:25 +08:00

1 line
46 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const $=API("sub-store"),$app=express();$.http=HTTP({headers:{"User-Agent":"Quantumult%20X"}});const SUBS_KEY="subs",COLLECTIONS_KEY="collections",AVAILABLE_FILTERS={"Keyword Filter":KeywordFilter,"Useless Filter":UselessFilter,"Region Filter":RegionFilter,"Regex Filter":RegexFilter,"Type Filter":TypeFilter,"Script Filter":ScriptFilter},AVAILABLE_OPERATORS={"Set Property Operator":SetPropertyOperator,"Flag Operator":FlagOperator,"Sort Operator":SortOperator,"Keyword Sort Operator":KeywordSortOperator,"Keyword Rename Operator":KeywordRenameOperator,"Keyword Delete Operator":KeywordDeleteOperator,"Regex Rename Operator":RegexRenameOperator,"Regex Delete Operator":RegexDeleteOperator,"Script Operator":ScriptOperator};async function IP_API(e,t){const s=decodeURIComponent(e.params.server),r=await $.http.get(`http://ip-api.com/json/${s}?lang=zh-CN`).then(e=>JSON.parse(e.body));t.json(r)}async function downloadResource(e){let t=await $.http.get(e).then(e=>e.body).catch(t=>{res.status(500).json({status:"failed",message:`Cannot refresh remote resource: ${e}\n Reason: ${t}`})});const s=t.indexOf("proxies:");if(-1!==s){const e=t.lastIndexOf("}")+1;t=t.substring(s,e)}return t}async function refreshResource(e,t){const s=new Base64Code,{url:r}=e.body,n=await downloadResource(r);$.write(n,`#${s.safeEncode(r)}`),t.json({status:"success"})}async function downloadSub(e,t){const{name:s}=e.params,r=e.query.target||getPlatformFromHeaders(e.headers),n=$.read(SUBS_KEY);if(n[s]){const e=n[s];try{const s=await parseSub(e,r);t.send(s)}catch(e){t.status(500).json({status:"failed",message:e})}}else t.status(404).json({status:"failed",message:`订阅${s}不存在!`})}async function parseSub(e,t){let s;const r=(new Base64Code).safeEncode(e.url);if("Raw"===t||"URI"===t){const t=$.read(`#${r}`);t?(await $.wait(10),s=t):(s=await downloadResource(e.url),$.write(s,`#${r}`))}else s=await downloadResource(e.url),$.write(s,`#${e.url}`);$.info("======================================================================="),$.info(`Processing subscription: ${e.name}, target platform ==> ${t}.`),$.info("Initializing parsers...");const n=ProxyParser(t);n.addParsers([Clash_All,URI_SS,URI_SSR,URI_VMess,URI_Trojan,QX_SS,QX_SSR,QX_VMess,QX_Trojan,QX_Http,Loon_SS,Loon_SSR,Loon_VMess,Loon_Trojan,Loon_Http,Surge_SS,Surge_VMess,Surge_Trojan,Surge_Http]),$.info("Parsers initialized.");let o=n.parse(s);const a=ProxyFilter(),i=ProxyOperator();for(const t of e.process||[]){let e;if(-1!==t.type.indexOf("Script")){const{mode:s,content:r}=t.args;e="link"===s?await $.http.get(r).then(e=>e.body).catch(e=>{throw new Error(`Error when downloading remote script: ${t.args.content}.\n Reason: ${e}`)}):r}if(-1!==t.type.indexOf("Filter")){const s=AVAILABLE_FILTERS[t.type];if(s){$.info(`Applying filter "${t.type}" with arguments:\n >>> ${JSON.stringify(t.args)||"None"}`),-1!==t.type.indexOf("Script")?a.setFilter(s(e)):a.setFilter(s(t.args));try{o=a.process(o)}catch(e){$.error(`Failed to apply filter "${t.type}"!\n REASON: ${e}`)}}}else if(-1!==t.type.indexOf("Operator")){const s=AVAILABLE_OPERATORS[t.type];if(s){$.info(`Applying operator "${t.type}" with arguments: \n >>> ${JSON.stringify(t.args)||"None"}`),-1!==t.type.indexOf("Script")?i.setOperator(s(e)):i.setOperator(s(t.args));try{o=i.process(o)}catch(e){t.type}}}}return n.addProducers([QX_Producer,Loon_Producer,Surge_Producer,Raw_Producer,URI_Producer]),n.produce(o)}function getFlowHeaders(e,t){const s=Object.keys(e).filter(e=>/SUBSCRIPTION-USERINFO/i.test(e))[0];if(s){const t=e[s],r=Number(t.match(/upload=(\d+)/)[1]),n=Number(t.match(/download=(\d+)/)[1]),o=Number(t.match(/total=(\d+)/)[1]),a=(t.match(/expire=(\d+)/)||[])[1];return{key:"Subscription-Userinfo",value:`${r?"upload="+r+";":""}${n?"download="+n+";":""}${o?"total="+o+";":""}${a?"expire="+a+";":""}`}}{let e,s;for(const r of t)-1!==r.name.indexOf("剩余流量")&&(e=r.name),-1!==r.name.indexOf("过期时间")&&(s=r.name);return{key:"Raw-Subscription-Userinfo",value:`${e?"remains="+e+";":""}${s?"expire="+s+";":""}`}}}async function getSub(e,t){const{name:s}=e.params,r=$.read(SUBS_KEY)[s];r?t.json({status:"success",data:r}):t.status(404).json({status:"failed",message:`未找到订阅:${s}!`})}async function newSub(e,t){const s=e.body,r=$.read(SUBS_KEY);r[s.name]&&t.status(500).json({status:"failed",message:`订阅${s.name}已存在!`}),/^[\w-_]*$/.test(s.name)?(r[s.name]=s,$.write(r,SUBS_KEY),t.status(201).json({status:"success",data:s})):t.status(500).json({status:"failed",message:`订阅名称 ${s.name} 中含有非法字符!名称中只能包含英文字母、数字、下划线、横杠。`})}async function updateSub(e,t){const{name:s}=e.params;$.info(`Updating subscription: ${s}`);let r=e.body;const n=$.read(SUBS_KEY);if(n[s]){const e={...n[s],...r};if(s!==r.name){const t=$.read(COLLECTIONS_KEY);for(const e of Object.keys(t)){const n=t[e].subscriptions.indexOf(s);-1!==n&&(t[e].subscriptions[n]=r.name)}delete n[s],n[r.name]=e}else n[s]=e;$.write(n,SUBS_KEY),t.json({status:"success",data:e})}else t.status(500).json({status:"failed",message:`订阅${s}不存在,无法更新!`})}async function deleteSub(e,t){const{name:s}=e.params;let r=$.read(SUBS_KEY);delete r[s],$.write(r,SUBS_KEY);let n=$.read(COLLECTIONS_KEY);for(const e of Object.keys(n))n[e].subscriptions=n[e].subscriptions.filter(e=>e!==s);$.write(n,COLLECTIONS_KEY),t.json({status:"success"})}async function getAllSubs(e,t){const s=$.read(SUBS_KEY);t.json({status:"success",data:s})}async function deleteAllSubs(e,t){$.write({},SUBS_KEY),t.json({status:"success"})}async function downloadCollection(e,t){const{name:s}=e.params,r=$.read(COLLECTIONS_KEY)[s],n=getPlatformFromHeaders(e.headers);if(r){const e=r.subscriptions||[],s=await Promise.all(e.map(async e=>{const t=$.read(SUBS_KEY)[e];try{return parseSub(t,n)}catch(t){return console.log(`ERROR when process subscription: ${e}`),""}}));t.send(s.join("\n"))}else $.notify("[Sub-Store]",`❌ 未找到订阅集:${s}`),t.status(404).json({status:"failed",message:`❌ 未找到订阅集:${s}`})}async function getCollection(e,t){const{name:s}=e.params,r=$.read(COLLECTIONS_KEY)[s];r?t.json({status:"success",data:r}):t.status(404).json({status:"failed",message:`未找到订阅集:${s}!`})}async function newCollection(e,t){const s=e.body,r=$.read(COLLECTIONS_KEY);r[s.name]&&t.status(500).json({status:"failed",message:`订阅集${s.name}已存在!`}),/^[\w-_]*$/.test(s.name)?(r[s.name]=s,$.write(r,COLLECTIONS_KEY),t.status(201).json({status:"success",data:s})):t.status(500).json({status:"failed",message:`订阅集名称 ${s.name} 中含有非法字符!名称中只能包含英文字母、数字、下划线、横杠。`})}async function updateCollection(e,t){const{name:s}=e.params;let r=e.body;const n=$.read(COLLECTIONS_KEY);if(n[s]){const e={...n[s],...r};delete n[s],n[r.name||s]=e,$.write(n,COLLECTIONS_KEY),t.json({status:"success",data:e})}else t.status(500).json({status:"failed",message:`订阅集${s}不存在,无法更新!`})}async function deleteCollection(e,t){const{name:s}=e.params;let r=$.read(COLLECTIONS_KEY);delete r[s],$.write(r,COLLECTIONS_KEY),t.json({status:"success"})}async function getAllCollections(e,t){const s=$.read(COLLECTIONS_KEY);t.json({status:"success",data:s})}async function deleteAllCollections(e,t){$.write({},COLLECTIONS_KEY),t.json({status:"success"})}function ProxyParser(e){const t=[],s=[];return{parse:function(s){const r=(s=function(e){let t;if(-1!==e.indexOf("DOCTYPE html"))throw new Error("Invalid format HTML!");if(-1!==e.indexOf("proxies")){console.log("Preprocessing Clash config..."),-1!==e.indexOf("{")&&(e=e.replace(/ - /g," - ").replace(/:(?!\s)/g,": ").replace(/\,\"/g,', "').replace(/: {/g,": {, ").replace(/, (host|path|tls|mux|skip)/g,", $1").replace(/{name: /g,'{name: "').replace(/, server:/g,'", server:').replace(/{|}/g,"").replace(/,/g,"\n ")),e=e.replace(/ -\n.*name/g," - name").replace(/\$|\`/g,"").split("proxy-providers:")[0].split("proxy-groups:")[0].replace(/\"(name|type|server|port|cipher|password|)\"/g,"$1");const s=YAML.eval(e).proxies;t=s.map(e=>JSON.stringify(e))}else if(0===e.indexOf("ssd://")){t=[];const s=new Base64Code;let r=JSON.parse(s.safeDecode(e.split("ssd://")[1]));r.traffic_used,r.traffic_total,r.expiry,r.airport;let n=r.port,o=r.encryption,a=r.password,i=r.servers;for(let e=0;e<i.length;e++){let r=i[e];o=r.encryption?r.encryption:o,a=r.password?r.password:a;let p=s.safeEncode(o+":"+a),l=r.server;n=r.port?r.port:n;let u=r.remarks?r.remarks:e,c=r.plugin_options?"/?plugin="+encodeURIComponent(r.plugin+";"+r.plugin_options):"";t[e]="ss://"+p+"@"+l+":"+n+c+"#"+u}}else{const s=new Base64Code,r=["dm1lc3M","c3NyOi8v","dHJvamFu","c3M6Ly","c3NkOi8v"];t=(t=r.some(t=>-1!==e.indexOf(t))?s.safeDecode(e):e).split("\n");for(let e=0;e<t.length;e++)t[e]=t[e].trim()}return t.join("\n")}(s)).split("\n"),n=[];for(let s of r){if(0===(s=s.trim()).length)continue;if(s.startsWith("#"))continue;let r=!1;for(const o of t){const{patternTest:t,func:a}=o;let i;try{i=t(s)}catch(e){i=!1}if(i){r=!0;try{const t=a(s);if(!t){console.log(`ERROR: parser return nothing for \n${s}\n`);break}if(t.supported&&!1===t.supported[e])continue;n.push(t);break}catch(e){console.log(`ERROR: Failed to parse line: \n ${s}\n Reason: ${e}`)}}}r||console.log(`ERROR: Failed to find a rule to parse line: \n${s}\n`)}return n},produce:function(t){for(const r of s)if(r.targetPlatform===e)return t.map(e=>{try{return r.output(e)}catch(t){return console.log(`ERROR: cannot produce proxy: ${JSON.stringify(e)}\nReason: ${t}`),""}}).filter(e=>e.length>0).join("\n");throw new Error(`Cannot find any producer for target platform: ${e}`)},addParsers:function(e){e.forEach(e=>t.push(e())),$.info(`${e.length} parser added.`)},addProducers:function(e){e.forEach(e=>s.push(e()))}}}function ProxyFilter(){let e;return{process:function(t){let s=FULL(t.length,!0);try{s=AND(s,e.func(t))}catch(t){console.log(`Cannot apply filter ${e.name}\n Reason: ${t}`)}return t.filter((e,t)=>s[t])},setFilter:function(t){e=t}}}function ProxyOperator(){let e;return{setOperator:function(t){e=t},process:function(t){let s=objClone(t);try{const t=e.func(s);t&&(s=t)}catch(e){console.log(`ERROR: cannot apply operator ${op.name}! Reason: ${e}`)}return s}}}function URI_SS(){const e=new Base64Code,t={QX:!0,Loon:!0,Surge:!0,Raw:!0};return{patternTest:e=>/^ss:\/\//.test(e),func:s=>{let r=s.split("ss://")[1];const n={name:decodeURIComponent(s.split("#")[1]),type:"ss",supported:t},o=(r=r.split("#")[0]).match(/@([^\/]*)(\/|$)/)[1],a=o.lastIndexOf(":");n.server=o.substring(0,a),n.port=o.substring(a+1);const i=e.safeDecode(r.split("@")[0]).split(":");if(n.cipher=i[0],n.password=i[1],-1!==r.indexOf("?plugin=")){const e=("plugin="+decodeURIComponent(r.split("?plugin=")[1].split("&")[0])).split(";"),s={};for(const t of e){const[e,r]=t.split("=");e&&(s[e]=r||!0)}switch(s.plugin){case"obfs-local":case"simple-obfs":n.plugin="obfs",n["plugin-opts"]={mode:s.obfs,host:s["obfs-host"]};break;case"v2ray-plugin":n.supported={...t,Loon:!1,Surge:!1},n.obfs="v2ray-plugin",n["plugin-opts"]={mode:"websocket",host:s["obfs-host"],path:s.path||"",tls:s.tls};break;default:throw new Error(`Unsupported plugin option: ${s.plugin}`)}}return n}}}function URI_SSR(){const e=new Base64Code,t={QX:!0,Loon:!0,Surge:!1,Raw:!0};return{patternTest:e=>/^ssr:\/\//.test(e),func:s=>{let r=(s=e.safeDecode(s.split("ssr://")[1])).indexOf(":origin");-1===r&&(r=s.indexOf(":auth_"));const n=s.substring(0,r),o=n.substring(0,n.lastIndexOf(":")),a=n.substring(n.lastIndexOf(":")+1);let i=s.substring(r+1).split("/?")[0].split(":"),p={type:"ssr",server:o,port:a,protocol:i[0],cipher:i[1],obfs:i[2],password:e.safeDecode(i[3]),supported:t};if(i={},(s=s.split("/?")[1].split("&")).length>1)for(const e of s){const[t,s]=e.split("=");i[t]=s}return p={...p,name:e.safeDecode(i.remarks),"protocol-param":e.safeDecode(i.protoparam).replace(/\s/g,"")||"","obfs-param":e.safeDecode(i.obfsparam).replace(/\s/g,"")||""}}}}function URI_VMess(){const e=new Base64Code,t={QX:!0,Loon:!0,Surge:!0,Raw:!0};return{patternTest:e=>/^vmess:\/\//.test(e),func:s=>{s=s.split("vmess://")[1];const r=e.safeDecode(s);if(/=\s*vmess/.test(r)){const e=r.split(",").map(e=>e.trim()),t={};for(const s of e)if(-1!==s.indexOf("=")){const[e,r]=s.split("=");t[e.trim()]=r.trim()}const s={name:e[0].split("=")[0].trim(),type:"vmess",server:e[1],port:e[2],cipher:e[3],uuid:e[4].match(/^"(.*)"$/)[1],tls:"over-tls"===t.obfs||"wss"===t.obfs,udp:JSON.parse(t["udp-relay"]||"false"),tfo:JSON.parse(t["fast-open"]||"false")};return s.tls&&(s.sni=t["obfs-host"]||s.server,s.scert=!JSON.parse(t["tls-verification"]||"true")),"ws"!==t.obfs&&"wss"!==t.obfs||(s.network="ws",s["ws-path"]=t["obfs-uri"],s["ws-headers"]={Host:t["obfs-host"]||s.server}),s}{const e=JSON.parse(r),s={name:e.ps,type:"vmess",server:e.add,port:e.port,cipher:"auto",uuid:e.id,alterId:e.aid||0,tls:"tls"===e.tls||!0===e.tls,supported:t};return"ws"===e.net&&(s.network="ws",s["ws-path"]=e.path,s["ws-headers"]={Host:e.host||e.add}),s}}}}function URI_Trojan(){const e={QX:!0,Loon:!0,Surge:!0,Raw:!0};return{patternTest:e=>/^trojan:\/\//.test(e),func:t=>{if(-1===t.indexOf(":443"))throw new Error("Trojan port should always be 443!");const s=(t=t.split("trojan://")[1]).split("@")[1].split(":443")[0];return{name:t.split("#")[1].trim()||`[Trojan] ${s}`,type:"trojan",server:s,port:443,password:t.split("@")[0],supported:e}}}}function Clash_All(){return{patternTest:e=>-1!==e.indexOf("{"),func:e=>JSON.parse(e)}}function QX_SS(){const e={QX:!0,Loon:!0,Surge:!0,Raw:!0};return{patternTest:e=>/^shadowsocks\s*=/.test(e.split(",")[0].trim())&&-1===e.indexOf("ssr-protocol"),func:t=>{const s=getQXParams(t),r={name:s.tag,type:"ss",server:s.server,port:s.port,cipher:s.method,password:s.password,udp:JSON.parse(s["udp-relay"]||"false"),tfo:JSON.parse(s["fast-open"]||"false"),supported:e};if(s.obfs)switch(r["plugin-opts"]={host:s["obfs-host"]||r.server},s.obfs){case"http":case"tls":r.plugin="obfs",r["plugin-opts"].mode=s.obfs;break;case"ws":case"wss":r["plugin-opts"]={...r["plugin-opts"],mode:"websocket",path:s["obfs-uri"],tls:"wss"===s.obfs},r.plugin="v2ray-plugin",r.supported.Surge=!1,r.supported.Loon=!1}return r}}}function QX_SSR(){const e={QX:!0,Loon:!0,Surge:!1,Raw:!0};return{patternTest:e=>/^shadowsocks\s*=/.test(e.split(",")[0].trim())&&-1!==e.indexOf("ssr-protocol"),func:t=>{const s=getQXParams(t),r={name:s.tag,type:"ssr",server:s.server,port:s.port,cipher:s.method,password:s.password,protocol:s["ssr-protocol"],obfs:"plain","protocol-param":s["ssr-protocol-param"],udp:JSON.parse(s["udp-relay"]||"false"),tfo:JSON.parse(s["fast-open"]||"false"),supported:e};return s.obfs&&(r.obfs=s.obfs,r["obfs-param"]=s["obfs-host"]),r}}}function QX_VMess(){return{patternTest:e=>/^vmess\s*=/.test(e.split(",")[0].trim()),func:e=>{const t=getQXParams(e),s={type:"vmess",name:t.tag,server:t.server,port:t.port,cipher:t.method||"none",uuid:t.password,alterId:0,tls:"over-tls"===t.obfs||"wss"===t.obfs,udp:JSON.parse(t["udp-relay"]||"false"),tfo:JSON.parse(t["fast-open"]||"false")};return s.tls&&(s.sni=t["obfs-host"]||t.server,s.scert=!JSON.parse(t["tls-verification"]||"true")),"ws"!==t.obfs&&"wss"!==t.obfs||(s.network="ws",s["ws-path"]=t["obfs-uri"],s["ws-headers"]={Host:t["obfs-host"]||t.server}),s}}}function QX_Trojan(){return{patternTest:e=>/^trojan\s*=/.test(e.split(",")[0].trim()),func:e=>{const t=getQXParams(e),s={type:"trojan",name:t.tag,server:t.server,port:t.port,password:t.password,sni:t["tls-host"]||t.server,udp:JSON.parse(t["udp-relay"]||"false"),tfo:JSON.parse(t["fast-open"]||"false")};return s.scert=!JSON.parse(t["tls-verification"]||"true"),s}}}function QX_Http(){return{patternTest:e=>/^http\s*=/.test(e.split(",")[0].trim()),func:e=>{const t=getQXParams(e),s={type:"http",name:t.tag,server:t.server,port:t.port,username:t.username,password:t.password,tls:JSON.parse(t["over-tls"]||"false"),udp:JSON.parse(t["udp-relay"]||"false"),tfo:JSON.parse(t["fast-open"]||"false")};return s.tls&&(s.sni=t["tls-host"]||s.server,s.scert=!JSON.parse(t["tls-verification"]||"true")),s}}}function getQXParams(e){const t=e.split(","),s={},r=["shadowsocks","vmess","http","trojan"];return t.forEach(e=>{const[t,n]=e.split("=");if(-1!==r.indexOf(t)){s.type=t;const e=n.split(":");s.server=e[0],s.port=e[1]}else s[t.trim()]=n.trim()}),s}function Loon_SS(){return{patternTest:e=>"shadowsocks"===e.split(",")[0].split("=")[1].trim().toLowerCase(),func:e=>{const t=e.split("=")[1].split(","),s={name:e.split("=")[0].trim(),type:"ss",server:t[1],port:t[2],cipher:t[3],password:t[4].replace(/"/g,"")};return t.length>5&&(s.plugin="obfs",s["plugin-opts"]={mode:s.obfs,host:t[6]}),s}}}function Loon_SSR(){return{patternTest:e=>"shadowsocksr"===e.split(",")[0].split("=")[1].trim().toLowerCase(),func:e=>{const t=e.split("=")[1].split(",");return{name:e.split("=")[0].trim(),type:"ssr",server:t[1],port:t[2],cipher:t[3],password:t[4].replace(/"/g,""),protocol:t[5],"protocol-param":t[6].match(/{(.*)}/)[1],supported:{QX:!0,Loon:!0,Surge:!1,Raw:!0},obfs:t[7],"obfs-param":t[8].match(/{(.*)}/)[1]}}}}function Loon_VMess(){return{patternTest:e=>/^.*=\s*vmess/i.test(e.split(",")[0])&&-1===e.indexOf("username"),func:e=>{let t=e.split("=")[1].split(",");const s={name:e.split("=")[0].trim(),type:"vmess",server:t[1],port:t[2],cipher:t[3]||"none",uuid:t[4].replace(/"/g,""),alterId:0};t=t.splice(5);for(const e of t){const[s,r]=e.split(":");t[s]=r}switch(s.tls=JSON.parse(t["over-tls"]||"false"),s.tls&&(s.sni=t["tls-name"]||s.server,s.scert=JSON.parse(t["skip-cert-verify"]||"false")),t.transport){case"tcp":break;case"ws":s.network=t.transport,s["ws-path"]=t.path,s["ws-headers"]={Host:t.host}}return s.tls&&(s.scert=JSON.parse(t["skip-cert-verify"]||"false")),s}}}function Loon_Trojan(){return{patternTest:e=>/^.*=\s*trojan/i.test(e.split(",")[0])&&-1===e.indexOf("password"),func:e=>{const t=e.split("=")[1].split(","),s={name:e.split("=")[0].trim(),type:"trojan",server:t[1],port:t[2],password:t[3].replace(/"/g,""),sni:t[1],scert:JSON.parse(t["skip-cert-verify"]||"false")};if(t.length>4){const[r,n]=t[4].split(":");if("tls-name"!==r)throw new Error(`ERROR: unknown option ${r} for line: \n${e}`);s.sni=n}return s}}}function Loon_Http(){return{patternTest:e=>/^.*=\s*http/i.test(e.split(",")[0])&&5===e.split(",").length&&-1===e.indexOf("username")&&-1===e.indexOf("password"),func:e=>{const t=e.split("=")[1].split(","),s={name:e.split("=")[0].trim(),type:"http",server:t[1],port:t[2],tls:"443"===t[2],username:(t[3]||"").replace(/"/g,""),password:(t[4]||"").replace(/"/g,"")};return s.tls&&(s.sni=t["tls-name"]||s.server,s.scert=JSON.parse(t["skip-cert-verify"]||"false")),s}}}function Surge_SS(){return{patternTest:e=>/^.*=\s*ss/.test(e.split(",")[0]),func:e=>{const t=getSurgeParams(e),s={name:t.name,type:"ss",server:t.server,port:t.port,cipher:t["encrypt-method"],password:t.password,tfo:JSON.parse(t.tfo||"false"),udp:JSON.parse(t["udp-relay"]||"false")};return t.obfs&&(s.plugin="obfs",s["plugin-opts"]={mode:t.obfs,host:t["obfs-host"]}),s}}}function Surge_VMess(){return{patternTest:e=>/^.*=\s*vmess/.test(e.split(",")[0])&&-1!==e.indexOf("username"),func:e=>{const t=getSurgeParams(e),s={name:t.name,type:"vmess",server:t.server,port:t.port,uuid:t.username,alterId:0,cipher:"none",tls:JSON.parse(t.tls||"false"),tfo:JSON.parse(t.tfo||"false")};return s.tls&&(s.scert=JSON.parse(t["skip-cert-verify"]||"false"),s.sni=t.sni||t.server),JSON.parse(t.ws||"false")&&(s.network="ws",s["ws-path"]=t["ws-path"],s["ws-headers"]={Host:t.sni}),s}}}function Surge_Trojan(){return{patternTest:e=>/^.*=\s*trojan/.test(e.split(",")[0])&&-1!==e.indexOf("sni"),func:e=>{const t=getSurgeParams(e);return{name:t.name,type:"trojan",server:t.server,port:t.port,password:t.password,sni:t.sni||t.server,tfo:JSON.parse(t.tfo||"false"),scert:JSON.parse(t["skip-cert-verify"]||"false")}}}}function Surge_Http(){return{patternTest:e=>/^.*=\s*http/.test(e.split(",")[0])&&!Loon_Http().patternTest(e),func:e=>{const t=getSurgeParams(e),s={name:t.name,type:"http",server:t.server,port:t.port,tls:JSON.parse(t.tls||"false"),tfo:JSON.parse(t.tfo||"false")};return s.tls&&(s.scert=JSON.parse(t["skip-cert-verify"]||"false"),s.sni=t.sni||t.server),"none"!==t.username&&(s.username=t.username),"none"!==t.password&&(s.password=t.password),s}}}function getSurgeParams(e){const t={};t.name=e.split("=")[0].trim();const s=e.split(",");t.server=s[1].trim(),t.port=s[2].trim();for(let e=3;e<s.length;e++){const r=s[e];if(-1!==r.indexOf("=")){const[e,s]=r.split("=");t[e.trim()]=s.trim()}}return t}function QX_Producer(){return{targetPlatform:"QX",output:e=>{let t,s;switch(e.type){case"ss":if(t="","obfs"===e.plugin&&(t=`,obfs=${e["plugin-opts"].mode},obfs-host=${e["plugin-opts"].host}`),"v2ray-plugin"===e.plugin){const{tls:s,host:r,path:n}=e["plugin-opts"];t=`,obfs=${s?"wss":"ws"},obfs-host=${r}${n?",obfs-uri="+n:""}`}return`shadowsocks = ${e.server}:${e.port}, method=${e.cipher}, password=${e.password}${t}${e.tfo?", fast-open=true":", fast-open=false"}${e.udp?", udp-relay=true":", udp-relay=false"}, tag=${e.name}`;case"ssr":return`shadowsocks=${e.server}:${e.port},method=${e.cipher},password=${e.password},ssr-protocol=${e.protocol}${e["protocol-param"]?",ssr-protocol-param="+e["protocol-param"]:""}${e.obfs?",obfs="+e.obfs:""}${e["obfs-param"]?",obfs-host="+e["obfs-param"]:""}${e.tfo?",fast-open=true":",fast-open=false"}${e.udp?",udp-relay=true":",udp-relay=false"},tag=${e.name}`;case"vmess":return t="","ws"===e.network?t=e.tls?`,obfs=wss,obfs-host=${e.sni}${e["ws-path"]?",obfs-uri="+e["ws-path"]:""},tls-verification=${e.scert?"false":"true"}`:`,obfs=ws,obfs-host=${e["ws-headers"].Host}${e["ws-path"]?",obfs-uri="+e["ws-path"]:""}`:e.tls&&(t=`,obfs=over-tls,obfs-host=${e.sni},tls-verification=${e.scert?"false":"true"}`),`vmess=${e.server}:${e.port},method=${"auto"===e.cipher?"none":e.cipher},password=${e.uuid}${t}${e.tfo?",fast-open=true":",fast-open=false"}${e.udp?",udp-relay=true":",udp-relay=false"},tag=${e.name}`;case"trojan":return`trojan=${e.server}:${e.port},password=${e.password},tls-host=${e.sni},tls-verification=${e.scert?"false":"true"}${e.tfo?",fast-open=true":",fast-open=false"}${e.udp?",udp-relay=true":",udp-relay=false"},tag=${e.name}`;case"http":return s="",e.tls&&(s=`,over-tls=true,tls-verification=${e.scert?"false":"true"},tls-host=${e.sni}`),`http=${e.server}:${e.port},username=${e.username},password=${e.password}${s}${e.tfo?",fast-open=true":",fast-open=false"},tag=${e.name}`}throw new Error(`Platform QX does not support proxy type: ${e.type}`)}}}function Loon_Producer(){return{targetPlatform:"Loon",output:e=>{let t,s;switch(e.type){case"ss":if(t=",,",e.plugin){if("obfs"!==e.plugin)throw new Error(`Platform Loon does not support obfs option: ${e.obfs}`);{const{mode:s,host:r}=e["plugin-opts"];t=`,${s},${r}`}}return`${e.name}=shadowsocks,${e.server},${e.port},${e.cipher},"${e.password}"${t}`;case"ssr":return`${e.name}=shadowsocksr,${e.server},${e.port},${e.cipher},"${e.password}",${e.protocol},{${e["protocol-param"]}},${e.obfs},{${e["obfs-param"]}}`;case"vmess":return t="",t="ws"===e.network?`,transport:ws,host:${e["ws-headers"].Host},path:${e["ws-path"]||"/"}`:",transport:tcp",e.tls&&(t+=`,tls-name=${e.sni},skip-cert-verify:${e.scert}`),`${e.name}=vmess,${e.server},${e.port},${"auto"===e.cipher?"none":e.cipher},"${e.uuid}",over-tls:${e.tls}${t}`;case"trojan":return`${e.name}=trojan,${e.server},${e.port},"${e.password}",tls-name:${e.sni},skip-cert-verify:${e.scert}`;case"http":s="";const r=`${e.name}=${e.tls?"http":"https"},${e.server},${e.port},${e.username||""},${e.password||""}`;return e.tls?r+(s=`,skip-cert-verify:${e.scert},tls-name:${e.sni}`):r}throw new Error(`Platform Loon does not support proxy type: ${e.type}`)}}}function Surge_Producer(){return{targetPlatform:"Surge",output:e=>{let t,s;switch(e.type){case"ss":if(t="",e.plugin){if("obfs"!==e.plugin)throw new Error(`Platform Surge does not support obfs option: ${e.obfs}`);t=`,obfs=${e["plugin-opts"].mode},obfs-host=${e["plugin-opts"].host}`}return`${e.name}=ss,${e.server},${e.port},encrypt-method=${e.cipher},password=${e.password}${t},tfo=${e.tfo||"false"},udp-relay=${e.udp||"false"}`;case"vmess":s="";let r=`${e.name}=vmess,${e.server},${e.port},username=${e.uuid},tls=${e.tls},tfo=${e.tfo||"false"}`;if("ws"===e.network){const t=e["ws-path"],s=e["ws-headers"].Host;r+=`,ws=true${t?",ws-path="+t:""}${s?",ws-headers=HOST:"+s:""}`}return e.tls&&(r+=`,skip-cert-verify=${e.scert},sni=${e.sni}`),r;case"trojan":return`${e.name}=trojan,${e.server},${e.port},password=${e.password},sni=${e.sni},tfo=${e.tfo||"false"}`;case"http":return s=",tls=false",e.tls&&(s=`,tls=true,skip-cert-verify=${e.scert},sni=${e.sni}`),`${e.name}=http,${e.server},${e.port}${e.username?",username="+e.username:""}${e.password?",password="+e.password:""}${s},tfo=${e.tfo||"false"}`}throw new Error(`Platform Surge does not support proxy type: ${e.type}`)}}}function Raw_Producer(){return{targetPlatform:"Raw",output:e=>JSON.stringify(e)}}function URI_Producer(){const e=new Base64Code;return{targetPlatform:"URI",output:t=>{let s="";switch(t.type){case"ss":const r=`${t.cipher}:${t.password}`;if(s=`ss://${e.safeEncode(r)}@${t.server}:${t.port}/`,t.plugin){s+="?plugin=";const e=t["plugin-opts"];switch(t.plugin){case"obfs":s+=encodeURIComponent(`simple-obfs;obfs=${e.mode}${e.host?";obfs-host="+e.host:""}`);break;case"v2ray-plugin":s+=encodeURIComponent(`v2ray-plugin;obfs=${e.mode}${e.host?";obfs-host"+e.host:""}${e.tls?";tls":""}`);break;default:throw console.log("FUCK"),new Error(`Unsupported plugin option: ${t.plugin}`)}}s+=`#${encodeURIComponent(t.name)}`;break;case"ssr":s=`${t.server}:${t.port}:${t.protocol}:${t.cipher}:${t.obfs}:${e.safeEncode(t.password)}/`,s+=`?remarks=${t.name}${t["obfs-param"]?"&obfsparam="+e.safeEncode(t["obfs-param"]):""}${t["protocol-param"]?"&protocolparam="+e.safeEncode(t["protocol-param"]):""}`,s="vmess://"+e.safeEncode(s);break;case"vmess":s={ps:t.name,add:t.server,port:t.port,id:t.uuid,type:"",aid:0,net:t.network||"tcp",tls:t.tls?"tls":""},"ws"===t.network&&(s.path=t["ws-path"]||"/",s.host=t["ws-headers"].Host||t.server),s=e.safeEncode(JSON.stringify(s));break;case"trojan":s=`trojan://${t.password}@${t.server}:${t.port}#${t.name}`;break;default:throw new Error(`Cannot handle proxy type: ${t.type}`)}return s}}}function SetPropertyOperator({key:e,value:t}){return{name:"Set Property Operator",func:s=>s.map(s=>(s[e]=t,s))}}function FlagOperator(e=!0){return{name:"Flag Operator",func:t=>t.map(t=>{if(e){const e=getFlag(t.name);t.name=removeFlag(t.name),t.name=e+" "+t.name,t.name=t.name.replace(/🇹🇼/g,"🇨🇳")}else t.name=removeFlag(t.name);return t})}}function SortOperator(e="asc"){return{name:"Sort Operator",func:t=>{switch(e){case"asc":case"desc":return t.sort((t,s)=>{let r=t.name>s.name?1:-1;return r*="desc"===e?-1:1});case"random":return shuffle(t);default:throw new Error("Unknown sort option: "+e)}}}}function KeywordSortOperator(e){return{name:"Keyword Sort Operator",func:t=>t.sort((t,s)=>{const r=getKeywordOrder(e,t.name),n=getKeywordOrder(e,s.name);return r&&!n?-1:n&&!r?1:r&&n?r<n?-1:1:!r&&!n||r&&n&&r===n?t.name<s.name?-1:1:void 0})}}function getKeywordOrder(e,t){let s=null;for(let r=0;r<e.length;r++)if(-1!==t.indexOf(e[r])){s=r+1;break}return s}function KeywordRenameOperator(e){return{name:"Keyword Rename Operator",func:t=>t.map(t=>{for(const{old:s,now:r}of e)t.name=t.name.replaceAll(s,r).trim();return t})}}function RegexRenameOperator(e){return{name:"Regex Rename Operator",func:t=>t.map(t=>{for(const{expr:s,now:r}of e)t.name=t.name.replace(new RegExp(s,"g"),r).trim();return t})}}function KeywordDeleteOperator(e){return{name:"Keyword Delete Operator",func:KeywordRenameOperator(e.map(e=>({old:e,now:""}))).func}}function RegexDeleteOperator(e){return{name:"Regex Delete Operator",func:RegexRenameOperator(e.map(e=>({expr:e,now:""}))).func}}function ScriptOperator(script){return{name:"Script Operator",func:proxies=>{let output=proxies;return function(){const $get=(e,t)=>{const s=AVAILABLE_OPERATORS[e];if(s)return s(t).func;throw new Error(`No operator named ${e} is found!`)};eval(script),output=operator(proxies)}(),output}}}function KeywordFilter({keywords:e=[],keep:t=!0}){return{name:"Keyword Filter",func:s=>s.map(s=>{const r=e.some(e=>-1!==s.name.indexOf(e));return t?r:!r})}}function UselessFilter(){return{name:"Useless Filter",func:KeywordFilter({keywords:["网址","流量","时间","应急","过期","Bandwidth","expire"],keep:!1}).func}}function RegionFilter(e){const t={HK:"🇭🇰",TW:"🇹🇼",US:"🇺🇸",SG:"🇸🇬",JP:"🇯🇵",UK:"🇬🇧"};return{name:"Region Filter",func:s=>s.map(s=>{const r=getFlag(s.name);return e.some(e=>t[e]===r)})}}function RegexFilter({regex:e=[],keep:t=!0}){return{name:"Regex Filter",func:s=>s.map(s=>{const r=e.some(e=>(e=new RegExp(e)).test(s.name));return t?r:!r})}}function TypeFilter(e){return{name:"Type Filter",func:t=>t.map(t=>e.some(e=>t.type===e))}}function ScriptFilter(script){return{name:"Script Filter",func:proxies=>{let output=FULL(proxies.length,!0);return function(){const $get=(e,t)=>{const s=AVAILABLE_FILTERS[e];if(s)return s(t).func;throw new Error(`No filter named ${e} is found!`)};eval(script),output=filter(proxies)}(),output}}}function getFlag(e){const t={"🏳️‍🌈":["流量","时间","应急","过期","Bandwidth","expire"],"🇦🇨":["AC"],"🇦🇹":["奥地利","维也纳"],"🇦🇺":["AU","Australia","Sydney","澳大利亚","澳洲","墨尔本","悉尼"],"🇧🇪":["BE","比利时"],"🇧🇬":["保加利亚","Bulgaria"],"🇧🇷":["BR","Brazil","巴西","圣保罗"],"🇨🇦":["CA","Canada","Waterloo","加拿大","蒙特利尔","温哥华","楓葉","枫叶","滑铁卢","多伦多"],"🇨🇭":["瑞士","苏黎世","Switzerland"],"🇩🇪":["DE","German","GERMAN","德国","德國","法兰克福"],"🇩🇰":["丹麦"],"🇪🇸":["ES","西班牙","Spain"],"🇪🇺":["EU","欧盟","欧罗巴"],"🇫🇮":["Finland","芬兰","赫尔辛基"],"🇫🇷":["FR","France","法国","法國","巴黎"],"🇬🇧":["UK","GB","England","United Kingdom","英国","伦敦","英"],"🇲🇴":["MO","Macao","澳门","CTM"],"🇭🇺":["匈牙利","Hungary"],"🇭🇰":["HK","Hongkong","Hong Kong","香港","深港","沪港","呼港","HKT","HKBN","HGC","WTT","CMI","穗港","京港","港"],"🇮🇩":["Indonesia","印尼","印度尼西亚","雅加达"],"🇮🇪":["Ireland","爱尔兰","都柏林"],"🇮🇳":["India","印度","孟买","Mumbai"],"🇰🇵":["KP","朝鲜"],"🇰🇷":["KR","Korea","KOR","韩国","首尔","韩","韓"],"🇱🇻":["Latvia","Latvija","拉脱维亚"],"🇲🇽️":["MEX","MX","墨西哥"],"🇲🇾":["MY","Malaysia","马来西亚","吉隆坡"],"🇳🇱":["NL","Netherlands","荷兰","荷蘭","尼德蘭","阿姆斯特丹"],"🇵🇭":["PH","Philippines","菲律宾"],"🇷🇴":["RO","罗马尼亚"],"🇷🇺":["RU","Russia","俄罗斯","俄羅斯","伯力","莫斯科","圣彼得堡","西伯利亚","新西伯利亚","京俄","杭俄"],"🇸🇦":["沙特","迪拜"],"🇸🇪":["SE","Sweden"],"🇸🇬":["SG","Singapore","新加坡","狮城","沪新","京新","泉新","穗新","深新","杭新","广新"],"🇹🇭":["TH","Thailand","泰国","泰國","曼谷"],"🇹🇷":["TR","Turkey","土耳其","伊斯坦布尔"],"🇹🇼":["TW","Taiwan","台湾","台北","台中","新北","彰化","CHT","台","HINET"],"🇺🇸":["US","USA","America","United States","美国","美","京美","波特兰","达拉斯","俄勒冈","凤凰城","费利蒙","硅谷","矽谷","拉斯维加斯","洛杉矶","圣何塞","圣克拉拉","西雅图","芝加哥","沪美","哥伦布","纽约"],"🇻🇳":["VN","越南","胡志明市"],"🇮🇹":["Italy","IT","Nachash","意大利","米兰","義大利"],"🇿🇦":["South Africa","南非"],"🇦🇪":["United Arab Emirates","阿联酋"],"🇯🇵":["JP","Japan","日","日本","东京","大阪","埼玉","沪日","穗日","川日","中日","泉日","杭日","深日","辽日","广日"],"🇦🇷":["AR","阿根廷"],"🇳🇴":["Norway","挪威","NO"],"🇨🇳":["CN","China","回国","中国","江苏","北京","上海","广州","深圳","杭州","徐州","青岛","宁波","镇江","back"]};for(let s of Object.keys(t))if(t[s].some(t=>-1!==e.indexOf(t)))return s;return(e.match(/[\uD83C][\uDDE6-\uDDFF][\uD83C][\uDDE6-\uDDFF]/)||[])[0]||"🏴‍☠️"}function removeFlag(e){return e.replace(/[\uD83C][\uDDE6-\uDDFF][\uD83C][\uDDE6-\uDDFF]/g,"").trim()}function objClone(e){return JSON.parse(JSON.stringify(e))}function shuffle(e){let t,s,r=e.length;for(;0!==r;)s=Math.floor(Math.random()*r),t=e[r-=1],e[r]=e[s],e[s]=t;return e}function AND(...e){return e.reduce((e,t)=>e.map((e,s)=>t[s]&&e))}function OR(...e){return e.reduce((e,t)=>e.map((e,s)=>t[s]||e))}function NOT(e){return e.map(e=>!e)}function FULL(e,t){return[...Array(e).keys()].map(()=>t)}function UUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}function getPlatformFromHeaders(e){const t=Object.keys(e);let s="";for(let r of t)if(/USER-AGENT/i.test(r)){s=e[r];break}return-1!==s.indexOf("Quantumult%20X")?"QX":-1!==s.indexOf("Surge")?"Surge":-1!==s.indexOf("Decar")?"Loon":"Raw"}function ENV(){const e="undefined"!=typeof $task,t="undefined"!=typeof $loon,s="undefined"!=typeof $httpClient&&!this.isLoon,r="function"==typeof require&&"undefined"!=typeof $jsbox;return{isQX:e,isLoon:t,isSurge:s,isNode:"function"==typeof require&&!r,isJSBox:r,isRequest:"undefined"!=typeof $request}}function HTTP(e={}){const{isQX:t,isLoon:s,isSurge:r}=ENV();const n={};return["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"].forEach(o=>n[o.toLowerCase()]=(n=>(function(n,o){(o=o.hasOwnProperty("url")?o:{url:o}).url=e.baseURL?e.baseURL+o.url:o.url;const a=(o={...e,...o}).timeout,i={onRequest:()=>{},onResponse:e=>e,onTimeout:()=>{},...o.events};let p,l;i.onRequest(n,o),p=t?$task.fetch({method:n,...o}):new Promise((e,t)=>{(r||s?$httpClient:require("request"))[n.toLowerCase()](o,(s,r,n)=>{s?t(s):e({statusCode:r.status||r.statusCode,headers:r.headers,body:n})})});const u=a?new Promise((e,t)=>{l=setTimeout(()=>(i.onTimeout(),t(`${n} URL: ${o.url} exceeds the timeout ${a} ms`)),a)}):null;return(u?Promise.race([u,p]).then(e=>(clearTimeout(l),e)):p).then(e=>i.onResponse(e))})(o,n))),n}function API(e="untitled",t=!1){const{isQX:s,isLoon:r,isSurge:n,isNode:o,isJSBox:a,isScriptable:i}=ENV();return new class{constructor(e,t){this.name=e,this.debug=t,this.http=HTTP(),this.env=ENV(),this.node=(()=>{if(o){return{fs:require("fs")}}return null})(),this.initCache();Promise.prototype.delay=function(e){return this.then(function(t){return((e,t)=>new Promise(function(s){setTimeout(s.bind(null,t),e)}))(e,t)})}}initCache(){if(s&&(this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}")),(r||n)&&(this.cache=JSON.parse($persistentStore.read(this.name)||"{}")),o){let e="root.json";this.node.fs.existsSync(e)||this.node.fs.writeFileSync(e,JSON.stringify({}),{flag:"wx"},e=>console.log(e)),this.root={},e=`${this.name}.json`,this.node.fs.existsSync(e)?this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)):(this.node.fs.writeFileSync(e,JSON.stringify({}),{flag:"wx"},e=>console.log(e)),this.cache={})}}persistCache(){const e=JSON.stringify(this.cache);s&&$prefs.setValueForKey(e,this.name),(r||n)&&$persistentStore.write(e,this.name),o&&(this.node.fs.writeFileSync(`${this.name}.json`,e,{flag:"w"},e=>console.log(e)),this.node.fs.writeFileSync("root.json",JSON.stringify(this.root),{flag:"w"},e=>console.log(e)))}write(e,t){this.log(`SET ${t}`),-1!==t.indexOf("#")?(t=t.substr(1),n&r&&$persistentStore.write(e,t),s&&$prefs.setValueForKey(e,t),o&&(this.root[t]=e)):this.cache[t]=e,this.persistCache()}read(e){return this.log(`READ ${e}`),-1===e.indexOf("#")?this.cache[e]:(e=e.substr(1),n&r?$persistentStore.read(e):s?$prefs.valueForKey(e):o?this.root[e]:void 0)}delete(e){this.log(`DELETE ${e}`),-1!==e.indexOf("#")?(e=e.substr(1),n&r&&$persistentStore.write(null,e),s&&$prefs.removeValueForKey(e),o&&delete this.root[e]):delete this.cache[e],this.persistCache()}notify(e,t="",p="",l={}){const u=l["open-url"],c=l["media-url"],f=p+(u?`\n点击跳转: ${u}`:"")+(c?`\n多媒体: ${c}`:"");if(s&&$notify(e,t,p,l),n&&$notification.post(e,t,f),r){let s={};u&&(s.openUrl=u),c&&(s.mediaUrl=c),"{}"===JSON.stringify(s)?$notification.post(e,t,p):$notification.post(e,t,p,s)}if(o||i)if(a){require("push").schedule({title:e,body:(t?t+"\n":"")+f})}else console.log(`${e}\n${t}\n${f}\n\n`)}log(e){this.debug&&console.log(e)}info(e){console.log(e)}error(e){console.log("ERROR: "+e)}wait(e){return new Promise(t=>setTimeout(t,e))}done(e={}){s||r||n?$done(e):o&&!a&&"undefined"!=typeof $context&&($context.headers=e.headers,$context.statusCode=e.statusCode,$context.body=e.body)}}(e,t)}function express(e=3e3){const{isNode:t}=ENV(),s={"Content-Type":"text/plain;charset=UTF-8","Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"POST,GET,OPTIONS,PATCH,PUT,DELETE","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept"};if(t){const t=require("express"),r=require("body-parser"),n=t();return n.use(r.json({verify:i})),n.use(r.urlencoded({verify:i,extended:!0})),n.use(r.raw({verify:i,type:"*/*"})),n.use((e,t,r)=>{t.set(s),r()}),n.start=(()=>{n.listen(e,()=>{$.info(`Express started on port: ${e}`)})}),n}const r=[],n=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD'","ALL"],o=(e,t=0)=>{let{method:s,url:n,headers:a,body:i}=e;/json/i.test(a["Content-Type"])&&(i=JSON.parse(i)),s=s.toUpperCase();const{path:c,query:f}=function(e){const t=(e.match(/https?:\/\/[^\/]+(\/[^?]*)/)||[])[1]||"/",s=e.indexOf("?"),r={};if(-1!==s){let t=e.slice(e.indexOf("?")+1).split("&");for(let e=0;e<t.length;e++)hash=t[e].split("="),r[hash[0]]=hash[1]}return{path:t,query:r}}(n);let d,h=null;for(d=t;d<r.length;d++)if("ALL"===r[d].method||s===r[d].method){const{pattern:e}=r[d];if(l(e,c)){h=r[d];break}}if(h){const e=()=>{o(s,n,d)},t={method:s,url:n,path:c,query:f,params:u(h.pattern,c),headers:a,body:i},r=p();h.callback(t,r,e).catch(e=>{r.status(500).json({status:"failed",message:`Internal Server Error: ${e}`})})}else{p().status(404).json({status:"failed",message:"ERROR: 404 not found"})}},a={};return n.forEach(e=>{a[e.toLowerCase()]=((t,s)=>{r.push({method:e,pattern:t,callback:s})})}),a.route=(e=>{const t={};return n.forEach(s=>{t[s.toLowerCase()]=(n=>(r.push({method:s,pattern:e,callback:n}),t))}),t}),a.start=(()=>{o($request)}),a;function i(e,t,s,r){s&&s.length&&(e.rawBody=s.toString(r||"utf8"))}function p(){let e=200;const{isQX:t,isLoon:r,isSurge:n}=ENV(),o=s,a={200:"HTTP/1.1 200 OK",201:"HTTP/1.1 201 Created",404:"HTTP/1.1 404 Not Found",500:"HTTP/1.1 500 Internal Server Error"};return new class{status(t){return e=t,this}send(s=""){const i={status:t?a[e]:e,body:s,headers:o};t?$done(i):(r||n)&&$done({response:i})}end(){this.send()}html(e){this.set("Content-Type","text/html;charset=UTF-8"),this.send(e)}json(e){this.set("Content-Type","application/json;charset=UTF-8"),this.send(JSON.stringify(e))}set(e,t){return o[e]=t,this}}}function l(e,t){if(e instanceof RegExp&&e.test(t))return!0;if("/"===e)return!0;if(-1===e.indexOf(":")){const s=t.split("/"),r=e.split("/");for(let e=0;e<r.length;e++)if(s[e]!==r[e])return!1;return!0}return!!u(e,t)}function u(e,t){if(-1===e.indexOf(":"))return null;{const s={};for(let r=0,n=0;r<e.length;r++,n++)if(":"===e[r]){let o=[],a=[];for(;"/"!==e[++r]&&r<e.length;)o.push(e[r]);for(;"/"!==t[n]&&n<t.length;)a.push(t[n++]);s[o.join("")]=a.join("")}else if(e[r]!==t[n])return null;return s}}}function Base64Code(){const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=function(e){const t={};let s=0;const r=e.length;for(;s<r;s++)t[e.charAt(s)]=s;return t}(e),s=String.fromCharCode,r=function(e){let t;return e.length<2?(t=e.charCodeAt(0))<128?e:t<2048?s(192|t>>>6)+s(128|63&t):s(224|t>>>12&15)+s(128|t>>>6&63)+s(128|63&t):(t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320),s(240|t>>>18&7)+s(128|t>>>12&63)+s(128|t>>>6&63)+s(128|63&t))},n=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,o=function(t){const s=[0,2,1][t.length%3],r=t.charCodeAt(0)<<16|(t.length>1?t.charCodeAt(1):0)<<8|(t.length>2?t.charCodeAt(2):0);return[e.charAt(r>>>18),e.charAt(r>>>12&63),s>=2?"=":e.charAt(r>>>6&63),s>=1?"=":e.charAt(63&r)].join("")};this.encode=function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)?e.toString("base64"):function(e){return e.replace(n,r)}(String(e)).replace(/[\s\S]{1,3}/g,o)};const a=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,i=function(e){switch(e.length){case 4:const t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return s(55296+(t>>>10))+s(56320+(1023&t));case 3:return s((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return s((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},p=function(e){const r=e.length,n=r%4,o=(r>0?t[e.charAt(0)]<<18:0)|(r>1?t[e.charAt(1)]<<12:0)|(r>2?t[e.charAt(2)]<<6:0)|(r>3?t[e.charAt(3)]:0),a=[s(o>>>16),s(o>>>8&255),s(255&o)];return a.length-=[0,0,2,1][n],a.join("")},l=function(e){return e.replace(/\S{1,4}/g,p)},u=function(e){return l(e).replace(a,i)};this.decode=function(e){return u(String(e).replace(/[-_]/g,function(e){return"-"===e?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,"")).replace(/&gt;/g,">").replace(/&lt;/g,"<")},this.safeEncode=function(e){return this.encode(e.replace(/\+/g,"-").replace(/\//g,"_"))},this.safeDecode=function(e){return this.decode(e.replace(/-/g,"+").replace(/_/g,"/"))}}$.read(SUBS_KEY)||$.write({},SUBS_KEY),$.read(COLLECTIONS_KEY)||$.write({},COLLECTIONS_KEY),$.info("Initializing Express..."),$app.get("/download/collection/:name",downloadCollection),$app.get("/download/:name",downloadSub),$app.get("/api/IP_API/:server",IP_API),$app.route("/api/sub/:name").get(getSub).patch(updateSub).delete(deleteSub),$app.route("/api/sub").get(getAllSubs).post(newSub).delete(deleteAllSubs),$app.post("/api/refresh",refreshResource),$app.route("/api/collection/:name").get(getCollection).patch(updateCollection).delete(deleteCollection),$app.route("/api/collection").get(getAllCollections).post(newCollection).delete(deleteAllCollections),$app.all("/",async(e,t)=>{t.send("Hello from Sub-Store! Made with ❤️ by Peng-YM.")}),$.info("Express initialized"),$app.start();var YAML=function(){var e=[],t=[],s=0,r={regLevel:new RegExp("^([\\s\\-]+)"),invalidLine:new RegExp("^\\-\\-\\-|^\\.\\.\\.|^\\s*#.*|^\\s*$"),dashesString:new RegExp('^\\s*\\"([^\\"]*)\\"\\s*$'),quotesString:new RegExp("^\\s*\\'([^\\']*)\\'\\s*$"),float:new RegExp("^[+-]?[0-9]+\\.[0-9]+(e[+-]?[0-9]+(\\.[0-9]+)?)?$"),integer:new RegExp("^[+-]?[0-9]+$"),array:new RegExp("\\[\\s*(.*)\\s*\\]"),map:new RegExp("\\{\\s*(.*)\\s*\\}"),key_value:new RegExp("([a-z0-9_-][ a-z0-9_-]*):( .+)","i"),single_key_value:new RegExp("^([a-z0-9_-][ a-z0-9_-]*):( .+?)$","i"),key:new RegExp("([a-z0-9_-][ a-z0-9_-]*):( .+)?","i"),item:new RegExp("^-\\s+"),trim:new RegExp("^\\s+|\\s+$"),comment:new RegExp("([^\\'\\\"#]+([\\'\\\"][^\\'\\\"]*[\\'\\\"])*)*(#.*)?")};function n(e){return{parent:null,length:0,level:e,lines:[],children:[],addChild:function(e){this.children.push(e),e.parent=this,++this.length}}}function o(e){var t=null;if("true"==(e=e.replace(r.trim,"")))return!0;if("false"==e)return!1;if(".NaN"==e)return Number.NaN;if("null"==e)return null;if(".inf"==e)return Number.POSITIVE_INFINITY;if("-.inf"==e)return Number.NEGATIVE_INFINITY;if(t=e.match(r.dashesString))return t[1];if(t=e.match(r.quotesString))return t[1];if(t=e.match(r.float))return parseFloat(t[0]);if(t=e.match(r.integer))return parseInt(t[0]);if(isNaN(t=Date.parse(e))){if(t=e.match(r.single_key_value))return(a={})[t[1]]=o(t[2]),a;if(t=e.match(r.array)){for(var s=0,n=" ",a=[],i="",p=!1,l=0,u=t[1].length;l<u;++l){if("'"==(n=t[1][l])||'"'==n){if(!1===p){p=n,i+=n;continue}if("'"==n&&"'"==p||'"'==n&&'"'==p){p=!1,i+=n;continue}}else if(!1!==p||"["!=n&&"{"!=n)if(!1!==p||"]"!=n&&"}"!=n){if(!1===p&&0==s&&","==n){a.push(o(i)),i="";continue}}else--s;else++s;i+=n}return i.length>0&&a.push(o(i)),a}if(t=e.match(r.map)){for(s=0,n=" ",a=[],i="",p=!1,l=0,u=t[1].length;l<u;++l){if("'"==(n=t[1][l])||'"'==n){if(!1===p){p=n,i+=n;continue}if("'"==n&&"'"==p||'"'==n&&'"'==p){p=!1,i+=n;continue}}else if(!1!==p||"["!=n&&"{"!=n)if(!1!==p||"]"!=n&&"}"!=n){if(!1===p&&0==s&&","==n){a.push(i),i="";continue}}else--s;else++s;i+=n}i.length>0&&a.push(i);var c={};for(l=0,u=a.length;l<u;++l)(t=a[l].match(r.key_value))&&(c[t[1]]=o(t[2]));return c}return e}return new Date(t)}function a(e){for(var t=e.lines,s=e.children,r=[t.join(" ")],n=0,o=s.length;n<o;++n)r.push(a(s[n]));return r.join("\n")}function i(e){for(var t=e.lines,s=e.children,r=t.join("\n"),n=0,o=s.length;n<o;++n)r+=i(s[n]);return r}function p(s){return function s(n){for(var p=null,l={},u=null,c=null,f=null,d=-1,h=[],m=!0,g=0,$=n.length;g<$;++g)if(-1==d||d==n[g].level){h.push(g),d=n[g].level,u=n[g].lines,c=n[g].children,f=null;for(var w=0,S=u.length;w<S;++w){var y=u[w];if(p=y.match(r.key)){var O=p[1];if("-"==O[0]&&(O=O.replace(r.item,""),m&&(m=!1,void 0===l.length&&(l=[])),null!=f&&l.push(f),f={},m=!0),void 0!==p[2]){var b=p[2].replace(r.trim,"");if("&"==b[0]){var v=s(c);null!=f?f[O]=v:l[O]=v,t[b.substr(1)]=v}else if("|"==b[0])null!=f?f[O]=i(c.shift()):l[O]=i(c.shift());else if("*"==b[0]){var x=b.substr(1),E={};if(void 0===t[x])e.push("Reference '"+x+"' not found!");else{for(var R in t[x])E[R]=t[x][R];null!=f?f[O]=E:l[O]=E}}else">"==b[0]?null!=f?f[O]=a(c.shift()):l[O]=a(c.shift()):null!=f?f[O]=o(b):l[O]=o(b)}else null!=f?f[O]=s(c):l[O]=s(c)}else y.match(/^-\s*$/)?(m&&(m=!1,void 0===l.length&&(l=[])),null!=f&&l.push(f),f={},m=!0):(p=y.match(/^-\s*(.*)/))&&(null!=f?f.push(o(p[1])):(m&&(m=!1,void 0===l.length&&(l=[])),l.push(o(p[1]))))}null!=f&&(m&&(m=!1,void 0===l.length&&(l=[])),l.push(f))}for(g=h.length-1;g>=0;--g)n.splice.call(n,h[g],1);return l}(s.children)}return{eval:function(o){e=[],t=[],s=(new Date).getTime();var a=p(function(t){var s,o=r.regLevel,a=r.invalidLine,i=t.split("\n"),p=0,l=0,u=[],c=new n(-1),f=new n(0);c.addChild(f);var d=[],h="";u.push(f),d.push(p);for(var m=0,g=i.length;m<g;++m)if(!(h=i[m]).match(a)){if((p=(s=o.exec(h))?s[1].length:0)>l){var $=f;f=new n(p),$.addChild(f),u.push(f),d.push(p)}else if(p<l){for(var w=!1,S=d.length-1;S>=0;--S)if(d[S]==p){f=new n(p),u.push(f),d.push(p),null!=u[S].parent&&u[S].parent.addChild(f),w=!0;break}if(!w)return void e.push("Error: Invalid indentation at line "+m+": "+h)}f.lines.push(h.replace(r.trim,"")),l=p}return c}(function(e){var t,s=e.split("\n"),n=r.comment;for(var o in s)(t="string"==typeof s[o]&&s[o].match(n))&&void 0!==t[3]&&(s[o]=t[0].substr(0,t[0].length-t[3].length));return s.join("\n")}(o)));return s=(new Date).getTime()-s,a},getErrors:function(){return e},getProcessingTime:function(){return s}}}();