mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-06-04 11:13:59 +08:00
1 line
46 KiB
JavaScript
1 line
46 KiB
JavaScript
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(/>/g,">").replace(/</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}}}();
|