mirror of
https://github.com/violettoolssite/CFspider.git
synced 2026-04-05 03:09:01 +08:00
1 line
63 KiB
JavaScript
1 line
63 KiB
JavaScript
import{connect as e}from"cloudflare:sockets";function s(e,s="x27cn2026"){if(!e)return"";const r=(new TextEncoder).encode(s),o=(new TextEncoder).encode(e),a=new Uint8Array(o.length);for(let e=0;e<o.length;e++){let t=o[e]^r[e%r.length];t=255&(t<<3|t>>5),t=t+e&255,a[e]=t}return Array.from(a).map(e=>e.toString(16).padStart(2,"0")).join("")}let r,o,a,i="",c=null,l=!1,d="",u={},p=0,h=!0,f="https://doh.cmliussss.net/CMLiussss",g=["*tapecontent.net","*cloudatacdn.com","*loadshare.org","*cdn-centaurus.com","scholar.google.com"];const m="https://edt-pages.github.io";export default{async fetch(e,t,n){const o=new URL(e.url),a=e.headers.get("User-Agent")||"null",p=e.headers.get("Upgrade"),C=t.ADMIN||t.admin||t.PASSWORD||t.password||t.pswd||t.TOKEN||t.KEY||t.UUID||t.uuid||"cfspider-public",A=t.KEY||"cfspider-default-key",T=await S(C+A),P=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/,_=t.UUID||t.uuid,N=_&&P.test(_)?_.toLowerCase():[T.slice(0,8),T.slice(8,12),"4"+T.slice(13,16),"8"+T.slice(17,20),T.slice(20)].join("-"),j=(t.HOST?(await v(t.HOST)).map(e=>e.toLowerCase().replace(/^https?:\/\//,"").split("/")[0].split(":")[0]):[o.hostname])[0];if(t.PROXYIP){const e=await v(t.PROXYIP);i=e[Math.floor(Math.random()*e.length)],h=!1}else i=(e.cf.colo+".PrOxYIp.CmLiUsSsS.nEt").toLowerCase();const D=e.headers.get("X-Real-IP")||e.headers.get("CF-Connecting-IP")||e.headers.get("X-Forwarded-For")||e.headers.get("True-Client-IP")||e.headers.get("Fly-Client-IP")||e.headers.get("X-Appengine-Remote-Addr")||e.headers.get("X-Forwarded-For")||e.headers.get("X-Real-IP")||e.headers.get("X-Cluster-Client-IP")||e.cf?.clientTcpRtt||"unknownIP";if(t.GO2SOCKS5&&(g=await v(t.GO2SOCKS5)),f=t.ECH_DOH||t.DOH||f,p&&"websocket"===p){if(C){await async function(e){const t=new URL(e.url),{pathname:n,searchParams:s}=t,r=n.toLowerCase();d=s.get("socks5")||s.get("http")||null,l=s.has("globalproxy")||!1;const o=r.match(/\/(proxyip[.=]|pyip=|ip=)(.+)/);if(s.has("proxyip")){const e=s.get("proxyip");return i=e.includes(",")?e.split(",")[Math.floor(Math.random()*e.split(",").length)]:e,void(h=!1)}if(o){const e="proxyip."===o[1]?`proxyip.${o[2]}`:o[2];return i=e.includes(",")?e.split(",")[Math.floor(Math.random()*e.split(",").length)]:e,void(h=!1)}let a;if(a=n.match(/\/(socks5?|http):\/?\/?(.+)/i)){if(c="http"===a[1].toLowerCase()?"http":"socks5",d=a[2].split("#")[0],l=!0,d.includes("@")){const e=d.lastIndexOf("@");let t=d.substring(0,e).replaceAll("%3D","=");/^(?:[A-Z0-9+/]{4})*(?:[A-Z0-9+/]{2}==|[A-Z0-9+/]{3}=)?$/i.test(t)&&!t.includes(":")&&(t=atob(t)),d=`${t}@${d.substring(e+1)}`}}else if(a=n.match(/\/(g?s5|socks5|g?http)=(.+)/i)){const e=a[1].toLowerCase();d=a[2],c=e.includes("http")?"http":"socks5",l=e.startsWith("g")||l}if(d)try{u=await E(d),c=s.get("http")?"http":c}catch(e){console.error("parseSOCKS5addrFailed:",e.message),c=null}else c=null}(e);const n=new URL(e.url).pathname;let s="";if(n.includes("two_proxy=")){const e=n.match(/two_proxy=([^&]+)/);e&&(s=decodeURIComponent(decodeURIComponent(e[1])))}const r=s||t.TWO_PROXY||t.two_proxy||"";return await async function(e,t,n=""){const s=new WebSocketPair,[r,o]=Object.values(s);o.accept();let a={socket:null},i=!1;const c=e.headers.get("sec-websocket-protocol")||"",l=function(e,t){let n=!1;return new ReadableStream({start(s){e.addEventListener("message",e=>{n||s.enqueue(e.data)}),e.addEventListener("close",()=>{n||(b(e),s.close())}),e.addEventListener("error",e=>s.error(e));const{earlyData:r,error:o}=function(e){if(!e)return{error:null};try{const t=atob(e.replace(/-/g,"+").replace(/_/g,"/")),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return{earlyData:n.buffer,error:null}}catch(e){return{error:e}}}(t);o?s.error(o):r&&s.enqueue(r)},cancel(){n=!0,b(e)}})}(o,c);let d=null,u=null;if(n){const e=n.split(":");e.length>=2&&(u={hostname:e[0],port:parseInt(e[1],10),username:e[2]||"",password:e[3]||""},console.log(`[twoProxy] enabled: ${u.hostname}:${u.port}`))}return l.pipeTo(new WritableStream({async write(e){if(i)return await y(e,o,null);if(a.socket){const t=a.socket.writable.getWriter();return await t.write(e),void t.releaseLock()}if(null===d){const t=new Uint8Array(e);d=t.byteLength>=58&&13===t[56]&&10===t[57]}if(a.socket){const t=a.socket.writable.getWriter();return await t.write(e),void t.releaseLock()}if(d){const{port:n,hostname:s,rawClientData:r}=function(e,t){const n=function(e){const t=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],n=(e,t)=>(e>>>t|e<<32-t)>>>0,s=8*(e=unescape(encodeURIComponent(e))).length;e+=String.fromCharCode(128);for(;8*e.length%512!=448;)e+=String.fromCharCode(0);const r=[3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428],o=Math.floor(s/4294967296),a=4294967295&s;e+=String.fromCharCode(o>>>24&255,o>>>16&255,o>>>8&255,255&o,a>>>24&255,a>>>16&255,a>>>8&255,255&a);const i=[];for(let t=0;t<e.length;t+=4)i.push(e.charCodeAt(t)<<24|e.charCodeAt(t+1)<<16|e.charCodeAt(t+2)<<8|e.charCodeAt(t+3));for(let e=0;e<i.length;e+=16){const s=new Array(64).fill(0);for(let t=0;t<16;t++)s[t]=i[e+t];for(let e=16;e<64;e++){const t=n(s[e-15],7)^n(s[e-15],18)^s[e-15]>>>3,r=n(s[e-2],17)^n(s[e-2],19)^s[e-2]>>>10;s[e]=s[e-16]+t+s[e-7]+r>>>0}let[o,a,c,l,d,u,p,h]=r;for(let e=0;e<64;e++){const r=h+(n(d,6)^n(d,11)^n(d,25))+(d&u^~d&p)+t[e]+s[e]>>>0,i=o&a^o&c^a&c;h=p,p=u,u=d,d=l+r>>>0,l=c,c=a,a=o,o=r+((n(o,2)^n(o,13)^n(o,22))+i>>>0)>>>0}for(let e=0;e<8;e++)r[e]=r[e]+(0===e?o:1===e?a:2===e?c:3===e?l:4===e?d:5===e?u:6===e?p:h)>>>0}let c="";for(let e=0;e<7;e++)for(let t=24;t>=0;t-=8)c+=(r[e]>>>t&255).toString(16).padStart(2,"0");return c}(t);if(e.byteLength<56)return{hasError:!0,message:"invalid data"};let s=56;if(13!==new Uint8Array(e.slice(56,57))[0]||10!==new Uint8Array(e.slice(57,58))[0])return{hasError:!0,message:"invalid header format"};if((new TextDecoder).decode(e.slice(0,s))!==n)return{hasError:!0,message:"invalid password"};const r=e.slice(s+2);if(r.byteLength<6)return{hasError:!0,message:"invalid S5 request data"};const o=new DataView(r);if(1!==o.getUint8(0))return{hasError:!0,message:"unsupported command, only TCP is allowed"};const a=o.getUint8(1);let i=0,c=2,l="";switch(a){case 1:i=4,l=new Uint8Array(r.slice(c,c+i)).join(".");break;case 3:i=new Uint8Array(r.slice(c,c+1))[0],c+=1,l=(new TextDecoder).decode(r.slice(c,c+i));break;case 4:i=16;const e=new DataView(r.slice(c,c+i)),t=[];for(let n=0;n<8;n++)t.push(e.getUint16(2*n).toString(16));l=t.join(":");break;default:return{hasError:!0,message:`invalid addressType is ${a}`}}if(!l)return{hasError:!0,message:`address is empty, addressType is ${a}`};const d=c+i,u=r.slice(d,d+2),p=new DataView(u).getUint16(0);return{hasError:!1,addressType:a,port:p,hostname:l,rawClientData:r.slice(d+4)}}(e,t);if(x(s))throw new Error("Speedtest site is blocked");await w(s,n,r,o,null,a,t,u)}else{const{port:n,hostname:s,rawIndex:r,version:c,isUDP:l}=function(e,t){if(e.byteLength<24)return{hasError:!0,message:"Invalid data"};const n=new Uint8Array(e.slice(0,1));if(function(e,t=0){const n=[...e.slice(t,t+16)].map(e=>e.toString(16).padStart(2,"0")).join("");return`${n.substring(0,8)}-${n.substring(8,12)}-${n.substring(12,16)}-${n.substring(16,20)}-${n.substring(20)}`}(new Uint8Array(e.slice(1,17)))!==t)return{hasError:!0,message:"Invalid uuid"};const s=new Uint8Array(e.slice(17,18))[0],r=new Uint8Array(e.slice(18+s,19+s))[0];let o=!1;if(1===r);else{if(2!==r)return{hasError:!0,message:"Invalid command"};o=!0}const a=19+s,i=new DataView(e.slice(a,a+2)).getUint16(0);let c=a+2,l=0,d=c+1,u="";const p=new Uint8Array(e.slice(c,d))[0];switch(p){case 1:l=4,u=new Uint8Array(e.slice(d,d+l)).join(".");break;case 2:l=new Uint8Array(e.slice(d,d+1))[0],d+=1,u=(new TextDecoder).decode(e.slice(d,d+l));break;case 3:l=16;const t=[],n=new DataView(e.slice(d,d+l));for(let e=0;e<8;e++)t.push(n.getUint16(2*e).toString(16));u=t.join(":");break;default:return{hasError:!0,message:`Invalid address type: ${p}`}}return u?{hasError:!1,addressType:p,port:i,hostname:u,isUDP:o,rawIndex:d+l,version:n}:{hasError:!0,message:`Invalid address: ${p}`}}(e,t);if(x(s))throw new Error("Speedtest site is blocked");if(l){if(53!==n)throw new Error("UDP is not supported");i=!0}const d=new Uint8Array([c[0],0]),p=e.slice(r);if(i)return y(p,o,d);await w(s,n,p,o,d,a,t,u)}}})).catch(e=>{}),new Response(null,{status:101,webSocket:r})}(e,N,r)}}else{if("http:"===o.protocol)return Response.redirect(o.href.replace(`http://${o.hostname}`,`https://${o.hostname}`),301);const i=o.pathname.slice(1).toLowerCase(),c=("false"!==t.NEW_IP&&t.NEW_IP,!_||!P.test(_)),l=t.TWO_PROXY||t.two_proxy||"";if(""===i||"/"===i){const t=e.cf?.colo||"UNKNOWN",n="/"+N+(l?"?two_proxy="+encodeURIComponent(l):""),r="vless://"+N+"@"+o.hostname+":443?security=tls&type=ws&host="+o.hostname+"&sni="+o.hostname+"&path="+encodeURIComponent(n)+"&encryption=none#Node-"+t,a={status:"online",version:"1.8.7",colo:t,host:o.hostname,uuid:N,vless:r,two_proxy:l||null};return new Response(s(JSON.stringify(a)),{headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*","X-Enc":"x27cn"}})}if("api/proxyip"===i){const n=e.cf?.colo||"UNKNOWN",r=(n+".proxyip.cmliussss.net").toLowerCase(),o=t.PROXYIP||"",a={colo:n,default:r,hk:"proxyip.cfspider.com",env:o||null,current:o||r,options:{default:{name:"nlNode",address:r},hk:{name:"hkNode",address:"proxyip.cfspider.com"}}};return new Response(s(JSON.stringify(a)),{headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*","X-Enc":"x27cn"}})}if("api/uuid"===i||"api/config"===i){const e="false"!==t.NEW_IP&&"0"!==t.NEW_IP,n=t.TWO_PROXY||t.two_proxy||"",r={host:o.hostname,new_ip:e,version:"1.8.7",is_default_uuid:c,two_proxy_enabled:!!n};if(c?(r.uuid=N,r.vless_path=n?"/"+N+"?two_proxy="+encodeURIComponent(n):"/"+N):n&&(r.two_proxy=n),n){const e=n.split(":");r.two_proxy_host=e[0]||"",r.two_proxy_port=e[1]||""}return new Response(s(JSON.stringify(r)),{headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*","X-Enc":"x27cn"}})}if("proxy"===i||i.startsWith("proxy?")){const n=o.searchParams.get("url"),s=o.searchParams.get("method")||"GET",r=o.searchParams.get("two_proxy");if(!n)return new Response(JSON.stringify({error:"Missing url parameter"}),{status:400,headers:{"Content-Type":"application/json"}});try{const o={};for(const[t,n]of e.headers)if(t.toLowerCase().startsWith("x-custom-header-")){o[t.substring(18)]=n}let a;const i=r||t.TWO_PROXY||t.two_proxy||"";if(i){const t=i.split(":"),r=t[0],a=parseInt(t[1])||3128,c=t[2]||"",l=t[3]||"",d=new URL(n),u=d.hostname,p=(d.port||d.protocol,"https:"===d.protocol),{connect:h}=await import("cloudflare:sockets");if(p)return new Response(JSON.stringify({error:"HTTPS + two_proxy notSupportedViaProxyAPI。useCfspiderGetWithTwoProxy。",hint:"client.get(url, cf_proxies=..., uuid=..., two_proxy=...)",reason:"Workers /proxy API onlyHTTPTwoProxySupported"}),{status:501,headers:{"Content-Type":"application/json","Access-Control-Allow-Origin":"*"}});{const t=h({hostname:r,port:a}),i=t.writable.getWriter(),d=t.readable.getReader();let p=`${s} ${n} HTTP/1.1\r\nHost: ${u}\r\n`;if(c&&l){p+=`Proxy-Authorization: Basic ${btoa(`${c}:${l}`)}\r\n`}for(const[e,t]of Object.entries(o))p+=`${e}: ${t}\r\n`;p+="Connection: close\r\n\r\n",await i.write((new TextEncoder).encode(p));let f=new Uint8Array(0);for(;;){const{value:e,done:t}=await d.read();if(t)break;const n=new Uint8Array(f.length+e.length);n.set(f),n.set(e,f.length),f=n}const g=(new TextDecoder).decode(f),m=g.indexOf("\r\n\r\n"),w=g.substring(0,m),y=f.slice((new TextEncoder).encode(g.substring(0,m+4)).length),b=w.split("\r\n")[0],C=parseInt(b.split(" ")[1])||200,x=new Headers;return w.split("\r\n").slice(1).forEach(e=>{const[t,...n]=e.split(":");t&&n.length&&x.set(t.trim(),n.join(":").trim())}),x.set("Access-Control-Allow-Origin","*"),x.set("X-CF-Colo",e.cf?.colo||"unknown"),x.set("X-Worker-Version","1.8.6"),x.set("X-Two-Proxy","enabled"),new Response(y,{status:C,headers:x})}}{const t=new Request(n,{method:s,headers:o,body:"GET"!==s&&"HEAD"!==s?e.body:null});a=await fetch(t);const r=new Headers(a.headers);return r.set("Access-Control-Allow-Origin","*"),r.set("X-CF-Colo",e.cf?.colo||"unknown"),r.set("X-Worker-Version","1.8.6"),new Response(a.body,{status:a.status,headers:r})}}catch(e){return new Response(JSON.stringify({error:e.message}),{status:500,headers:{"Content-Type":"application/json"}})}}if("api/config/new_ip"===i&&"POST"===e.method){const e="false"!==t.NEW_IP&&"0"!==t.NEW_IP;return new Response(JSON.stringify({new_ip:e,message:"setNEWIPViaDashboard"}),{headers:{"Content-Type":"application/json","Access-Control-Allow-Origin":"*"}})}if(!C)return fetch(m+"/noADMIN").then(e=>{const t=new Headers(e.headers);return t.set("Cache-Control","no-store, no-cache, must-revalidate, proxy-revalidate"),t.set("Pragma","no-cache"),t.set("Expires","0"),new Response(e.body,{status:404,statusText:e.statusText,headers:t})});if(t.KV&&"function"==typeof t.KV.get){const s=o.pathname.slice(1).toLowerCase(),i=o.pathname.slice(1);if(i===A&&"doNotModifyDefaultKey"!==A){const e=new URLSearchParams(o.search);return e.set("token",await S(j+N)),new Response("redirecting...",{status:302,headers:{Location:`/sub?${e.toString()}`}})}if("login"===s){const t=e.headers.get("Cookie")||"",n=t.split(";").find(e=>e.trim().startsWith("auth="))?.split("=")[1];if(n==await S(a+A+C))return new Response("redirecting...",{status:302,headers:{Location:"/admin"}});if("POST"===e.method){const t=await e.text();if(new URLSearchParams(t).get("password")===C){const e=new Response(JSON.stringify({success:!0}),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}});return e.headers.set("Set-Cookie",`auth=${await S(a+A+C)}; Path=/; Max-Age=86400; HttpOnly`),e}}return fetch(m+"/login")}if("admin"===s||s.startsWith("admin/")){const c=e.headers.get("Cookie")||"",l=c.split(";").find(e=>e.trim().startsWith("auth="))?.split("=")[1];if(!l||l!==await S(a+A+C))return new Response("redirecting...",{status:302,headers:{Location:"/login"}});if("admin/log.json"===s){const e=await t.KV.get("log.json")||"[]";return new Response(e,{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}if("admin/getCloudflareUsage"===i)try{const e=await O(o.searchParams.get("Email"),o.searchParams.get("GlobalAPIKey"),o.searchParams.get("AccountID"),o.searchParams.get("APIToken"));return new Response(JSON.stringify(e,null,2),{status:200,headers:{"Content-Type":"application/json"}})}catch(e){const t={msg:"queryRequestFailed,reason:"+e.message,error:e.message};return new Response(JSON.stringify(t,null,2),{status:500,headers:{"Content-Type":"application/json;charset=utf-8"}})}else{if("admin/getADDAPI"===i){if(o.searchParams.get("url")){const e=o.searchParams.get("url");try{new URL(e);const t=await k([e],o.searchParams.get("port")||"443"),n=t[0].length>0?t[0]:t[1];return new Response(JSON.stringify({success:!0,data:n},null,2),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}catch(e){const t={msg:"verifyAPIFailed,reason:"+e.message,error:e.message};return new Response(JSON.stringify(t,null,2),{status:500,headers:{"Content-Type":"application/json;charset=utf-8"}})}}return new Response(JSON.stringify({success:!1,data:[]},null,2),{status:403,headers:{"Content-Type":"application/json;charset=utf-8"}})}if("admin/check"===s){let e;if(o.searchParams.has("socks5"))e=await R("socks5",o.searchParams.get("socks5"));else{if(!o.searchParams.has("http"))return new Response(JSON.stringify({error:"missingProxyParam"}),{status:400,headers:{"Content-Type":"application/json;charset=utf-8"}});e=await R("http",o.searchParams.get("http"))}return new Response(JSON.stringify(e,null,2),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}}if(r=await I(t,j,N,t.PATH),"admin/init"===s)try{return r=await I(t,j,N,t.PATH,!0),n.waitUntil($(t,e,D,"Init_Config",r)),r.init="configResetToDefault",new Response(JSON.stringify(r,null,2),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}catch(e){const t={msg:"configResetFailed,reason:"+e.message,error:e.message};return new Response(JSON.stringify(t,null,2),{status:500,headers:{"Content-Type":"application/json;charset=utf-8"}})}else if("POST"===e.method)if("admin/config.json"===s)try{const s=await e.json();return s.UUID&&s.HOST?(await t.KV.put("config.json",JSON.stringify(s,null,2)),n.waitUntil($(t,e,D,"Save_Config",r)),new Response(JSON.stringify({success:!0,message:"configSaved"}),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})):new Response(JSON.stringify({error:"incompleteConfig"}),{status:400,headers:{"Content-Type":"application/json;charset=utf-8"}})}catch(e){return console.error("saveConfigFailed:",e),new Response(JSON.stringify({error:"saveConfigFailed: "+e.message}),{status:500,headers:{"Content-Type":"application/json;charset=utf-8"}})}else if("admin/cf.json"===s)try{const s=await e.json(),o={Email:null,GlobalAPIKey:null,AccountID:null,APIToken:null,UsageAPI:null};if(!s.init||!0!==s.init)if(s.Email&&s.GlobalAPIKey)o.Email=s.Email,o.GlobalAPIKey=s.GlobalAPIKey;else if(s.AccountID&&s.APIToken)o.AccountID=s.AccountID,o.APIToken=s.APIToken;else{if(!s.UsageAPI)return new Response(JSON.stringify({error:"incompleteConfig"}),{status:400,headers:{"Content-Type":"application/json;charset=utf-8"}});o.UsageAPI=s.UsageAPI}return await t.KV.put("cf.json",JSON.stringify(o,null,2)),n.waitUntil($(t,e,D,"Save_Config",r)),new Response(JSON.stringify({success:!0,message:"configSaved"}),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}catch(e){return console.error("saveConfigFailed:",e),new Response(JSON.stringify({error:"saveConfigFailed: "+e.message}),{status:500,headers:{"Content-Type":"application/json;charset=utf-8"}})}else if("admin/tg.json"===s)try{const s=await e.json();if(s.init&&!0===s.init){const e={BotToken:null,ChatID:null};await t.KV.put("tg.json",JSON.stringify(e,null,2))}else{if(!s.BotToken||!s.ChatID)return new Response(JSON.stringify({error:"incompleteConfig"}),{status:400,headers:{"Content-Type":"application/json;charset=utf-8"}});await t.KV.put("tg.json",JSON.stringify(s,null,2))}return n.waitUntil($(t,e,D,"Save_Config",r)),new Response(JSON.stringify({success:!0,message:"configSaved"}),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}catch(e){return console.error("saveConfigFailed:",e),new Response(JSON.stringify({error:"saveConfigFailed: "+e.message}),{status:500,headers:{"Content-Type":"application/json;charset=utf-8"}})}else{if("admin/ADD.txt"!==i)return new Response(JSON.stringify({error:"unsupportedPOSTPath"}),{status:404,headers:{"Content-Type":"application/json;charset=utf-8"}});try{const s=await e.text();return await t.KV.put("ADD.txt",s),n.waitUntil($(t,e,D,"Save_Custom_IPs",r)),new Response(JSON.stringify({success:!0,message:"customIPSaved"}),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}catch(e){return console.error("saveCustomIPfailed:",e),new Response(JSON.stringify({error:"saveCustomIPfailed: "+e.message}),{status:500,headers:{"Content-Type":"application/json;charset=utf-8"}})}}else{if("admin/config.json"===s)return new Response(JSON.stringify(r,null,2),{status:200,headers:{"Content-Type":"application/json"}});if("admin/ADD.txt"===i){let n=await t.KV.get("ADD.txt")||"null";return"null"==n&&(n=(await U(e,r.subGenerator.localIPPool.randomCount,r.subGenerator.localIPPool.specifiedPort))[1]),new Response(n,{status:200,headers:{"Content-Type":"text/plain;charset=utf-8",asn:e.cf.asn}})}if("admin/cf.json"===s)return new Response(JSON.stringify(e.cf,null,2),{status:200,headers:{"Content-Type":"application/json;charset=utf-8"}})}return n.waitUntil($(t,e,D,"Admin_Login",r)),fetch(m+"/admin")}if("logout"===s||P.test(s)){const e=new Response("redirecting...",{status:302,headers:{Location:"/login"}});return e.headers.set("Set-Cookie","auth=; Path=/; Max-Age=0; HttpOnly"),e}if("sub"===s){const s=await S(j+N);if(o.searchParams.get("token")===s){r=await I(t,j,N,t.PATH),n.waitUntil($(t,e,D,"Get_SUB",r));const i=a.toLowerCase(),c=4102329600,l=Date.now(),d=new Date(l);d.setHours(0,0,0,0);const u=Math.floor((l-d.getTime())/864e5*24*1099511627776/2);let p=u,h=u,g=26388279066624;r.CF.Usage.success&&(p=r.CF.Usage.pages,h=r.CF.Usage.workers,g=Number.isFinite(r.CF.Usage.max)?r.CF.Usage.max/1e3*1024:102400);const m={"content-type":"text/plain; charset=utf-8","Profile-Update-Interval":r.subGenerator.SUBUpdateTime,"Profile-web-page-url":o.protocol+"//"+o.host+"/admin","Subscription-Userinfo":`upload=${p}; download=${h}; total=${g}; expire=${c}`,"Cache-Control":"no-store"},w=o.searchParams.has("b64")||o.searchParams.has("base64")||e.headers.get("subconverter-request")||e.headers.get("subconverter-version")||i.includes("subconverter")||i.includes("CF-Workers-SUB".toLowerCase())?"mixed":o.searchParams.has("target")?o.searchParams.get("target"):o.searchParams.has("clash")||i.includes("clash")||i.includes("meta")||i.includes("mihomo")?"clash":o.searchParams.has("sb")||o.searchParams.has("singbox")||i.includes("singbox")||i.includes("sing-box")?"singbox":o.searchParams.has("surge")||i.includes("surge")?"surge&ver=4":o.searchParams.has("quanx")||i.includes("quantumult")?"quanx":o.searchParams.has("loon")||i.includes("loon")?"loon":"mixed";i.includes("mozilla")||(m["Content-Disposition"]=`attachment; filename*=utf-8''${encodeURIComponent(r.subGenerator.SUBNAME)}`);const y=o.searchParams.has("surge")||i.includes("surge")?"trojan":r.protocolType;let b="";if("mixed"===w){const n=r.enable0RTT?r.PATH+"?ed=2560":r.PATH,s="Shadowrocket"==r.tlsFragment?`&fragment=${encodeURIComponent("1,40-60,30-50,tlshello")}`:"Happ"==r.tlsFragment?`&fragment=${encodeURIComponent("3,1,tlshello")}`:"";let a=[],i="";if(!o.searchParams.has("sub")&&r.subGenerator.local){const n=r.subGenerator.localIPPool.randomIP?(await U(e,r.subGenerator.localIPPool.randomCount,r.subGenerator.localIPPool.specifiedPort))[0]:await t.KV.get("ADD.txt")?await v(await t.KV.get("ADD.txt")):(await U(e,r.subGenerator.localIPPool.randomCount,r.subGenerator.localIPPool.specifiedPort))[0],s=[],o=[],c=[];for(const e of n)if(e.toLowerCase().startsWith("https://"))s.push(e);else if(e.toLowerCase().includes("://"))if(e.includes("#")){const t=e.split("#");c.push(t[0]+"#"+encodeURIComponent(decodeURIComponent(t[1])))}else c.push(e);else o.push(e);const l=await k(s),d=[...new Set(c.concat(l[1]))];i=d.length>0?d.join("\n")+"\n":"";const u=l[0];a=[...new Set(o.concat(u))]}else{let e=o.searchParams.get("sub")||r.subGenerator.SUB;e=e&&!/^https?:\/\//i.test(e)?`https://${e}`:e;const t=`${e}/sub?host=example.com&uuid=00000000-0000-4000-8000-000000000000`;try{const e=await fetch(t,{headers:{"User-Agent":"v2rayN/edgetunnel (https://github.com/cmliu/edgetunnel)"}});if(!e.ok)return new Response("subGenError:"+e.statusText,{status:e.status});const n=atob(await e.text()),s=n.includes("\r\n")?n.split("\r\n"):n.split("\n");for(const e of s)if(e.trim())if(e.includes("00000000-0000-4000-8000-000000000000")&&e.includes("example.com")){const t=e.match(/:\/\/[^@]+@([^?]+)/);if(t){let n=t[1],s="";const r=e.match(/#(.+)$/);r&&(s="#"+decodeURIComponent(r[1])),a.push(n+s)}}else i+=e+"\n"}catch(e){return new Response("subGenError:"+e.message,{status:403})}}const c=r.ECH?`&ech=${encodeURIComponent("cloudflare-ech.com+"+f)}`:"";b=i+a.map(e=>{const t=e.match(/^(\[[\da-fA-F:]+\]|[\d.]+|[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*)(?::(\d+))?(?:#(.+))?$/);let o,a,i="443";return t?(o=t[1],i=t[2]||"443",a=t[3]||o,`${y}://00000000-0000-4000-8000-000000000000@${o}:${i}?security=tls&type=${r.transport+c}&host=example.com&fp=${r.Fingerprint}&sni=example.com&path=${encodeURIComponent(r.randomPath?function(){const e=["about","account","acg","act","activity","ad","ads","ajax","album","albums","anime","api","app","apps","archive","archives","article","articles","ask","auth","avatar","bbs","bd","blog","blogs","book","books","bt","buy","cart","category","categories","cb","channel","channels","chat","china","city","class","classify","clip","clips","club","cn","code","collect","collection","comic","comics","community","company","config","contact","content","course","courses","cp","data","detail","details","dh","directory","discount","discuss","dl","dload","doc","docs","document","documents","doujin","download","downloads","drama","edu","en","ep","episode","episodes","event","events","f","faq","favorite","favourites","favs","feedback","file","files","film","films","forum","forums","friend","friends","game","games","gif","go","go.html","go.php","group","groups","help","home","hot","htm","html","image","images","img","index","info","intro","item","items","ja","jp","jump","jump.html","jump.php","jumping","knowledge","lang","lesson","lessons","lib","library","link","links","list","live","lives","m","mag","magnet","mall","manhua","map","member","members","message","messages","mobile","movie","movies","music","my","new","news","note","novel","novels","online","order","out","out.html","out.php","outbound","p","page","pages","pay","payment","pdf","photo","photos","pic","pics","picture","pictures","play","player","playlist","post","posts","product","products","program","programs","project","qa","question","rank","ranking","read","readme","redirect","redirect.html","redirect.php","reg","register","res","resource","retrieve","sale","search","season","seasons","section","seller","series","service","services","setting","settings","share","shop","show","shows","site","soft","sort","source","special","star","stars","static","stock","store","stream","streaming","streams","student","study","tag","tags","task","teacher","team","tech","temp","test","thread","tool","tools","topic","topics","torrent","trade","travel","tv","txt","type","u","upload","uploads","url","urls","user","users","v","version","video","videos","view","vip","vod","watch","web","wenku","wiki","work","www","zh","zh-cn","zh-tw","zip"],t=Math.floor(3*Math.random()+1),n=e.sort(()=>.5-Math.random()).slice(0,t).join("/");return`/${n}`}()+n:n)+s}&encryption=none${r.skipCertVerify?"&insecure=1&allowInsecure=1":""}#${encodeURIComponent(a)}`):(console.warn(`[subContent] invalidIPIgnored: ${e}`),null)}).filter(e=>null!==e).join("\n")}else{const e=`${r.subConverterConfig.SUBAPI}/sub?target=${w}&url=${encodeURIComponent(o.protocol+"//"+o.host+"/sub?target=mixed&token="+s+(o.searchParams.has("sub")&&""!=o.searchParams.get("sub")?`&sub=${o.searchParams.get("sub")}`:""))}&config=${encodeURIComponent(r.subConverterConfig.SUBCONFIG)}&emoji=${r.subConverterConfig.SUBEMOJI}&scv=${r.skipCertVerify}`;try{const t=await fetch(e,{headers:{"User-Agent":"Subconverter for "+w+" edgetunnel(https://github.com/cmliu/edgetunnel)"}});if(!t.ok)return new Response("subConverterError:"+t.statusText,{status:t.status});b=await t.text(),(o.searchParams.has("surge")||i.includes("surge"))&&(b=function(e,t,n){const s=e.includes("\r\n")?e.split("\r\n"):e.split("\n");let r="";const o=n.enable0RTT?n.PATH+"?ed=2560":n.PATH;for(let e of s)if(!e.includes("= trojan,")||e.includes("ws=true")||e.includes("ws-path="))r+=e+"\n";else{const t=e.split("sni=")[1].split(",")[0],s=`sni=${t}, skip-cert-verify=${n.skipCertVerify}`,a=`sni=${t}, skip-cert-verify=${n.skipCertVerify}, ws=true, ws-path=${o}, ws-headers=Host:"${t}"`;r+=e.replace(new RegExp(s,"g"),a).replace("[","").replace("]","")+"\n"}return r=`#!MANAGED-CONFIG ${t} interval=${60*n.subGenerator.SUBUpdateTime*60} strict=false`+r.substring(r.indexOf("\n")),r}(b,o.protocol+"//"+o.host+"/sub?token="+s+"&surge",r))}catch(e){return new Response("subConverterError:"+e.message,{status:403})}}return i.includes("subconverter")||(b=await function(e,t,n=2){const s=[...t].sort(()=>Math.random()-.5);let r=0,o=null;return e.replace(/example\.com/g,()=>(r%n===0&&(o=function(e){if(!e?.includes("*"))return e;const t="abcdefghijklmnopqrstuvwxyz0123456789";return e.replace(/\*/g,()=>{let e="";for(let n=0;n<Math.floor(14*Math.random())+3;n++)e+=t[Math.floor(36*Math.random())];return e})}(s[Math.floor(r/n)%s.length])),r++,o))}(b.replace(/00000000-0000-4000-8000-000000000000/g,r.UUID),r.HOSTS)),"mixed"!==w||i.includes("mozilla")&&!o.searchParams.has("b64")&&!o.searchParams.has("base64")||(b=btoa(b)),"singbox"===w?(b=function(e,t=null,n="chrome",s=null){try{let r=JSON.parse(e);Array.isArray(r.inbounds)&&r.inbounds.forEach(e=>{if("tun"===e.type){const t=[];e.inet4_address&&t.push(e.inet4_address),e.inet6_address&&t.push(e.inet6_address),t.length>0&&(e.address=t,delete e.inet4_address,delete e.inet6_address);const n=[];Array.isArray(e.inet4_route_address)&&n.push(...e.inet4_route_address),Array.isArray(e.inet6_route_address)&&n.push(...e.inet6_route_address),n.length>0&&(e.route_address=n,delete e.inet4_route_address,delete e.inet6_route_address);const s=[];Array.isArray(e.inet4_route_exclude_address)&&s.push(...e.inet4_route_exclude_address),Array.isArray(e.inet6_route_exclude_address)&&s.push(...e.inet6_route_exclude_address),s.length>0&&(e.route_exclude_address=s,delete e.inet4_route_exclude_address,delete e.inet6_route_exclude_address)}});const o=new Map,a=(e,t=!1)=>{Array.isArray(e)&&e.forEach(e=>{if(e.geosite){const t=Array.isArray(e.geosite)?e.geosite:[e.geosite];e.rule_set=t.map(e=>{const t=`geosite-${e}`;return o.has(t)||o.set(t,{tag:t,type:"remote",format:"binary",url:`https://gh.090227.xyz/https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-${e}.srs`,download_detour:"DIRECT"}),t}),delete e.geosite}if(e.geoip){const t=Array.isArray(e.geoip)?e.geoip:[e.geoip];e.rule_set=e.rule_set||[],t.forEach(t=>{const n=`geoip-${t}`;o.has(n)||o.set(n,{tag:n,type:"remote",format:"binary",url:`https://gh.090227.xyz/https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-${t}.srs`,download_detour:"DIRECT"}),e.rule_set.push(n)}),delete e.geoip}const n=t?"server":"outbound",s=String(e[n]).toUpperCase();"REJECT"!==s&&"BLOCK"!==s||(e.action="reject",e.method="drop",delete e[n])})};r.dns&&r.dns.rules&&a(r.dns.rules,!0),r.route&&r.route.rules&&a(r.route.rules,!1),o.size>0&&(r.route||(r.route={}),r.route.rule_set=Array.from(o.values())),r.outbounds||(r.outbounds=[]),r.outbounds=r.outbounds.filter(e=>"REJECT"!==e.tag&&"block"!==e.tag);const i=new Set(r.outbounds.map(e=>e.tag));if(i.has("DIRECT")||(r.outbounds.push({type:"direct",tag:"DIRECT"}),i.add("DIRECT")),r.dns&&r.dns.servers){const e=new Set(r.dns.servers.map(e=>e.tag));r.dns.rules&&r.dns.rules.forEach(t=>{t.server&&!e.has(t.server)&&("dns_block"===t.server&&e.has("block")?t.server="block":t.server.toLowerCase().includes("block")&&!e.has(t.server)&&(r.dns.servers.push({tag:t.server,address:"rcode://success"}),e.add(t.server)))})}return r.outbounds.forEach(e=>{"selector"!==e.type&&"urltest"!==e.type||Array.isArray(e.outbounds)&&(e.outbounds=e.outbounds.filter(e=>{const t=e.toUpperCase();return i.has(e)&&"REJECT"!==t&&"BLOCK"!==t}),0===e.outbounds.length&&e.outbounds.push("DIRECT"))}),t&&r.outbounds.forEach(e=>{(e.uuid&&e.uuid===t||e.password&&e.password===t)&&(e.tls||(e.tls={enabled:!0}),n&&(e.tls.utls={enabled:!0,fingerprint:n}),s&&(e.tls.ech={enabled:!0,config:`-----BEGIN ECH CONFIGS-----\n${s}\n-----END ECH CONFIGS-----`}))}),JSON.stringify(r,null,2)}catch(t){return console.error("singboxPatchFailed:",t),JSON.stringify(JSON.parse(e),null,2)}}(b,r.UUID,r.Fingerprint,r.ECH?await async function(e){try{const t=await fetch(`https://1.1.1.1/dns-query?name=${encodeURIComponent(e)}&type=65`,{headers:{accept:"application/dns-json"}}),n=await t.json();if(!n.Answer?.length)return"";for(let e of n.Answer){if(65!==e.type||!e.data)continue;const t=e.data.match(/ech=([^\s]+)/);if(t)return t[1].replace(/"/g,"");if(e.data.startsWith("\\#")){const t=e.data.split(" ").slice(2).join(""),n=new Uint8Array(t.match(/.{1,2}/g).map(e=>parseInt(e,16)));let s=2;for(;s<n.length&&0!==n[s++];)s+=n[s-1];for(;s+4<=n.length;){const e=n[s]<<8|n[s+1],t=n[s+2]<<8|n[s+3];if(s+=4,5===e)return btoa(String.fromCharCode(...n.slice(s,s+t)));s+=t}}}return""}catch{return""}}(j):null),m["content-type"]="application/json; charset=utf-8"):"clash"===w&&(b=function(e,t=null,n=!1,s=[]){let r=e.replace(/mode:\s*Rule\b/g,"mode: rule");const o="dns:\n enable: true\n default-nameserver:\n - 223.5.5.5\n - 119.29.29.29\n - 114.114.114.114\n use-hosts: true\n nameserver:\n - https://sm2.doh.pub/dns-query\n - https://dns.alidns.com/dns-query\n fallback:\n - 8.8.4.4\n - 101.101.101.101\n - 208.67.220.220\n fallback-filter:\n geoip: true\n domain: [+.google.com, +.facebook.com, +.youtube.com]\n ipcidr:\n - 240.0.0.0/4\n - 0.0.0.0/32\n geoip-code: CN\n";/^dns:\s*(?:\n|$)/m.test(r)||(r=o+r);if(n&&s.length>0){const e=s.map(e=>` "${e}":\n - tls://8.8.8.8\n - https://doh.cmliussss.com/CMLiussss\n - ${f}`).join("\n");if(/^\s{2}nameserver-policy:\s*(?:\n|$)/m.test(r))r=r.replace(/^(\s{2}nameserver-policy:\s*\n)/m,`$1${e}\n`);else{const t=r.split("\n");let n=-1,s=!1;for(let e=0;e<t.length;e++){const r=t[e];if(/^dns:\s*$/.test(r))s=!0;else if(s&&/^[a-zA-Z]/.test(r)){n=e;break}}const o=` nameserver-policy:\n${e}`;-1!==n?t.splice(n,0,o):t.push(o),r=t.join("\n")}}if(!t||!n)return r;const a=r.split("\n"),i=[];let c=0;for(;c<a.length;){const e=a[c],n=e.trim();if(n.startsWith("- {")&&(n.includes("uuid:")||n.includes("password:"))){let n=e,s=(e.match(/\{/g)||[]).length-(e.match(/\}/g)||[]).length;for(;s>0&&c+1<a.length;)c++,n+="\n"+a[c],s+=(a[c].match(/\{/g)||[]).length-(a[c].match(/\}/g)||[]).length;const r=n.match(/type:\s*(\w+)/);let o="uuid";"trojan"===(r?r[1]:"vless")&&(o="password");const l=new RegExp(`${o}:\\s*([^,}\\n]+)`),d=n.match(l);d&&d[1].trim()===t.trim()&&(n=n.replace(/\}(\s*)$/,", ech-opts: {enable: true}}$1")),i.push(n),c++}else if(n.startsWith("- name:")){let n=[e],s=e.search(/\S/),r=s+2;for(c++;c<a.length;){const e=a[c],t=e.trim();if(!t){n.push(e),c++;break}const r=e.search(/\S/);if(r<=s&&t.startsWith("- "))break;if(r<s&&t)break;n.push(e),c++}const o=n.join("\n"),l=o.match(/type:\s*(\w+)/);let d="uuid";"trojan"===(l?l[1]:"vless")&&(d="password");const u=new RegExp(`${d}:\\s*([^\\n]+)`),p=o.match(u);if(p&&p[1].trim()===t.trim()){let e=-1;for(let t=n.length-1;t>=0;t--)if(n[t].trim()){e=t;break}if(e>=0){const t=" ".repeat(r);n.splice(e+1,0,`${t}ech-opts:`,`${t} enable: true`)}}i.push(...n)}else i.push(e),c++}return i.join("\n")}(b,r.UUID,r.ECH,r.HOSTS),m["content-type"]="application/x-yaml; charset=utf-8"),new Response(b,{status:200,headers:m})}}else if("locations"===s){const t=e.headers.get("Cookie")||"",n=t.split(";").find(e=>e.trim().startsWith("auth="))?.split("=")[1];if(n&&n==await S(a+A+C))return fetch(new Request("https://speed.cloudflare.com/locations",{headers:{Referer:"https://speed.cloudflare.com/"}}))}else if("robots.txt"===s)return new Response("User-agent: *\nDisallow: /",{status:200,headers:{"Content-Type":"text/plain; charset=UTF-8"}})}else if(!_)return fetch(m+"/noKV").then(e=>{const t=new Headers(e.headers);return t.set("Cache-Control","no-store, no-cache, must-revalidate, proxy-revalidate"),t.set("Pragma","no-cache"),t.set("Expires","0"),new Response(e.body,{status:404,statusText:e.statusText,headers:t})})}let F=t.URL||"nginx";if(F&&"nginx"!==F&&"1101"!==F){F=F.trim().replace(/\/$/,""),F.match(/^https?:\/\//i)||(F="https://"+F),F.toLowerCase().startsWith("http://")&&(F="https://"+F.substring(7));try{const e=new URL(F);F=e.protocol+"//"+e.host}catch(e){F="nginx"}}if("1101"===F)return new Response(await async function(e,t){const n=new Date,s=n.getFullYear()+"-"+String(n.getMonth()+1).padStart(2,"0")+"-"+String(n.getDate()).padStart(2,"0")+" "+String(n.getHours()).padStart(2,"0")+":"+String(n.getMinutes()).padStart(2,"0")+":"+String(n.getSeconds()).padStart(2,"0"),r=Array.from(crypto.getRandomValues(new Uint8Array(8))).map(e=>e.toString(16).padStart(2,"0")).join("");return`<!DOCTYPE html>\n\x3c!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]--\x3e\n\x3c!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]--\x3e\n\x3c!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]--\x3e\n\x3c!--[if gt IE 8]>\x3c!--\x3e <html class="no-js" lang="en-US"> \x3c!--<![endif]--\x3e\n<head>\n<title>Worker threw exception | ${e} | Cloudflare</title>\n<meta charset="UTF-8" />\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\n<meta http-equiv="X-UA-Compatible" content="IE=Edge" />\n<meta name="robots" content="noindex, nofollow" />\n<meta name="viewport" content="width=device-width,initial-scale=1" />\n<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />\n\x3c!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]--\x3e\n<style>body{margin:0;padding:0}</style>\n\n\n\x3c!--[if gte IE 10]>\x3c!--\x3e\n<script>\n if (!navigator.cookieEnabled) {\n window.addEventListener('DOMContentLoaded', function () {\n var cookieEl = document.getElementById('cookie-alert');\n cookieEl.style.display = 'block';\n })\n }\n<\/script>\n\x3c!--<![endif]--\x3e\n\n</head>\n<body>\n <div id="cf-wrapper">\n <div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>\n <div id="cf-error-details" class="cf-error-details-wrapper">\n <div class="cf-wrapper cf-header cf-error-overview">\n <h1>\n <span class="cf-error-type" data-translate="error">Error</span>\n <span class="cf-error-code">1101</span>\n <small class="heading-ray-id">Ray ID: ${r} • ${s} UTC</small>\n </h1>\n <h2 class="cf-subheadline" data-translate="error_desc">Worker threw exception</h2>\n </div>\x3c!-- /.header --\x3e\n \n <section></section>\x3c!-- spacer --\x3e\n \n <div class="cf-section cf-wrapper">\n <div class="cf-columns two">\n <div class="cf-column">\n <h2 data-translate="what_happened">What happened?</h2>\n <p>You've requested a page on a website (${e}) that is on the <a href="https://www.cloudflare.com/5xx-error-landing?utm_source=error_100x" target="_blank">Cloudflare</a> network. An unknown error occurred while rendering the page.</p>\n </div>\n \n <div class="cf-column">\n <h2 data-translate="what_can_i_do">What can I do?</h2>\n <p><strong>If you are the owner of this website:</strong><br />refer to <a href="https://developers.cloudflare.com/workers/observability/errors/" target="_blank">Workers - Errors and Exceptions</a> and check Workers Logs for ${e}.</p>\n </div>\n \n </div>\n </div>\x3c!-- /.section --\x3e\n \n <div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">\n <p class="text-13">\n <span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold"> ${r}</strong></span>\n <span class="cf-footer-separator sm:hidden">•</span>\n <span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">\n Your IP:\n <button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>\n <span class="hidden" id="cf-footer-ip">${t}</span>\n <span class="cf-footer-separator sm:hidden">•</span>\n </span>\n <span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>\n \n </p>\n <script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();<\/script>\n </div>\x3c!-- /.error-footer --\x3e\n\n </div>\x3c!-- /#cf-error-details --\x3e\n </div>\x3c!-- /#cf-wrapper --\x3e\n\n <script>\n window._cf_translation = {};\n \n \n <\/script> \n</body>\n</html>`}(o.host,D),{status:200,headers:{"Content-Type":"text/html; charset=UTF-8"}});try{const t=new URL(F),n=new Headers(e.headers);n.set("Host",t.host),n.set("Referer",t.origin),n.set("Origin",t.origin),!n.has("User-Agent")&&a&&"null"!==a&&n.set("User-Agent",a);const s=await fetch(t.origin+o.pathname+o.search,{method:e.method,headers:n,body:e.body,cf:e.cf}),r=s.headers.get("content-type")||"";if(/text|javascript|json|xml/.test(r)){const e=(await s.text()).replaceAll(t.host,o.host);return new Response(e,{status:s.status,headers:{...Object.fromEntries(s.headers),"Cache-Control":"no-store"}})}return s}catch(e){}return new Response(await async function(){return'\n\t<!DOCTYPE html>\n\t<html>\n\t<head>\n\t<title>Welcome to nginx!</title>\n\t<style>\n\t\tbody {\n\t\t\twidth: 35em;\n\t\t\tmargin: 0 auto;\n\t\t\tfont-family: Tahoma, Verdana, Arial, sans-serif;\n }\n </style>\n</head>\n<body>\n\t<h1>Welcome to nginx!</h1>\n\t<p>If you see this page, the nginx web server is successfully installed and\n\tworking. Further configuration is required.</p>\n\t\n\t<p>For online documentation and support please refer to\n\t<a href="http://nginx.org/">nginx.org</a>.<br/>\n\tCommercial support is available at\n\t<a href="http://nginx.com/">nginx.com</a>.</p>\n\t\n\t<p><em>Thank you for using nginx.</em></p>\n\t</body>\n\t</html>\n\t'}(),{status:200,headers:{"Content-Type":"text/html; charset=UTF-8"}})}};async function w(t,n,s,r,d,u,f,m=null){async function w(t,n,s,o=null,a=!0){let i;if(o&&o.length>0)for(let t=0;t<o.length;t++){const n=(p+t)%o.length,[r,a]=o[n];try{console.log(`[proxyConn] connectingTo: ${r}:${a} (idx: ${n})`),i=e({hostname:r,port:a}),await Promise.race([i.opened,new Promise((e,t)=>setTimeout(()=>t(new Error("connTimeout")),1e3))]);const t=i.writable.getWriter();return await t.write(s),t.releaseLock(),console.log(`[proxyConn] connectedTo: ${r}:${a}`),p=n,i}catch(e){console.log(`[proxyConn] connFailed: ${r}:${a}, err: ${e.message}`);try{i?.close?.()}catch(e){}continue}}if(a){i=e({hostname:t,port:n});const r=i.writable.getWriter();return await r.write(s),r.releaseLock(),i}throw b(r),new Error("[proxyConn] allProxyFailed,andNotenableProxyFallback,connTerminated。")}async function y(){let e;if("socks5"===c)console.log(`[SOCKS5proxy] proxyTo: ${t}:${n}`),e=await A(t,n,s);else if("http"===c||"https"===c)console.log(`[HTTPproxy] proxyTo: ${t}:${n}`),e=await T(t,n,s);else{console.log(`[proxyConn] proxyTo: ${t}:${n}`);const r=await async function(e,t="dash.cloudflare.com",n="00000000-0000-4000-8000-000000000000"){if(o&&a&&o===e)console.log(`[proxyParse] readCache total: ${a.length}\n${a.map(([e,t],n)=>`${n+1}. ${e}:${t}`).join("\n")}`);else{async function s(e,t){try{const n=await fetch(`https://1.1.1.1/dns-query?name=${e}&type=${t}`,{headers:{Accept:"application/dns-json"}});if(!n.ok)return[];return(await n.json()).Answer||[]}catch(e){return console.error(`dohQueryFailed (${t}):`,e),[]}}function r(e){let t=e,n=443;if(e.includes("]:")){const s=e.split("]:");t=s[0]+"]",n=parseInt(s[1],10)||n}else if(e.includes(":")&&!e.startsWith("[")){const s=e.lastIndexOf(":");t=e.slice(0,s),n=parseInt(e.slice(s+1),10)||n}return[t,n]}let i=[];if((e=e.toLowerCase()).includes(".william"))try{const p=(await s(e,"TXT")).filter(e=>16===e.type).map(e=>e.data);if(p.length>0){let h=p[0];h.startsWith('"')&&h.endsWith('"')&&(h=h.slice(1,-1));i=h.replace(/\\010/g,",").replace(/\n/g,",").split(",").map(e=>e.trim()).filter(Boolean).map(e=>r(e))}}catch(f){console.error("parseWilliamFailed:",f)}else{let[g,m]=r(e);if(e.includes(".tp")){const y=e.match(/\.tp(\d+)/);y&&(m=parseInt(y[1],10))}const w=/^\[?([a-fA-F0-9:]+)\]?$/;if(/^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/.test(g)||w.test(g))i=[[g,m]];else{const[b,C]=await Promise.all([s(g,"A"),s(g,"AAAA")]),x=[...b.filter(e=>1===e.type).map(e=>e.data),...C.filter(e=>28===e.type).map(e=>`[${e.data}]`)];i=x.length>0?x.map(e=>[e,m]):[[g,m]]}}const c=i.sort((e,t)=>e[0].localeCompare(t[0])),l=t.includes(".")?t.split(".").slice(-2).join("."):t;let d=[...l+n].reduce((e,t)=>e+t.charCodeAt(0),0);console.log(`[proxyParse] randSeed: ${d}\ntargetSite: ${l}`);const u=[...c].sort(()=>(d=1103515245*d+12345&2147483647)/2147483647-.5);a=u.slice(0,8),console.log(`[proxyParse] parseComplete total: ${a.length}\n${a.map(([e,t],n)=>`${n+1}. ${e}:${t}`).join("\n")}`),o=e}return a}(i,t,f);e=await w(atob("UFJPWFlJUC50cDEuMDkwMjI3Lnh5eg=="),1,s,r,h)}u.socket=e,e.closed.catch(()=>{}).finally(()=>b(r)),C(e,r,d,null)}console.log(`[TCPforward] target: ${t}:${n} | proxyIP: ${i} | twoProxy: ${m?m.hostname+":"+m.port:"no"} | proxyType: ${c||"proxyip"}`);if(m){console.log("[TCPforward] usingTwoProxy");try{const o=await async function(){if(!m)throw new Error("twoProxyNotConfigured");console.log(`[twoProxy] via ${m.hostname}:${m.port} connTo ${t}:${n}`);const r=e({hostname:m.hostname,port:m.port}),o=r.writable.getWriter(),a=r.readable.getReader();try{const e=m.username&&m.password?`Proxy-Authorization: Basic ${btoa(`${m.username}:${m.password}`)}\r\n`:"",i=`CONNECT ${t}:${n} HTTP/1.1\r\nHost: ${t}:${n}\r\n${e}User-Agent: Mozilla/5.0\r\nConnection: keep-alive\r\n\r\n`;await o.write((new TextEncoder).encode(i));let c=new Uint8Array(0),l=-1,d=0;for(;-1===l&&d<8192;){const{done:e,value:t}=await a.read();if(e)throw new Error("proxyClosed");c=new Uint8Array([...c,...t]),d=c.length;for(let e=0;e<c.length-3;e++)if(13===c[e]&&10===c[e+1]&&13===c[e+2]&&10===c[e+3]){l=e+4;break}}if(-1===l)throw new Error("invalidProxyResp");const u=(new TextDecoder).decode(c.slice(0,l)).match(/HTTP\/\d\.\d\s+(\d+)/),p=u?parseInt(u[1]):0;if(p<200||p>=300)throw new Error(`proxyConnFailed: HTTP ${p}`);return console.log(`[twoProxy] tunnelEstablished: ${t}:${n}`),await o.write(s),o.releaseLock(),a.releaseLock(),r}catch(e){try{o.releaseLock()}catch(e){}try{a.releaseLock()}catch(e){}try{r.close()}catch(e){}throw e}}();u.socket=o,o.closed.catch(()=>{}).finally(()=>b(r)),C(o,r,d,null)}catch(e){console.log(`[twoProxy] connFailed: ${e.message}, fallbackToDefault`);try{await y()}catch(e){throw e}}}else if(c&&(l||(x=t,g.some(e=>new RegExp(`^${e.replace(/\*/g,".*")}$`,"i").test(x))))){console.log("[TCPforward] enableGlobalProxy");try{await y()}catch(e){throw e}}else try{console.log(`[TCPforward] directConnTo: ${t}:${n}`);const e=await w(t,n,s);u.socket=e,C(e,r,d,y)}catch(e){await y()}var x}async function y(t,n,s){try{const r=e({hostname:"8.8.4.4",port:53});let o=s;const a=r.writable.getWriter();await a.write(t),a.releaseLock(),await r.readable.pipeTo(new WritableStream({async write(e){if(n.readyState===WebSocket.OPEN)if(o){const t=new Uint8Array(o.length+e.byteLength);t.set(o,0),t.set(e,o.length),n.send(t.buffer),o=null}else n.send(e)}}))}catch(e){}}function b(e){try{e.readyState!==WebSocket.OPEN&&e.readyState!==WebSocket.CLOSING||e.close()}catch(e){}}async function C(e,t,n,s){let r=n,o=!1;await e.readable.pipeTo(new WritableStream({async write(e,n){if(o=!0,t.readyState!==WebSocket.OPEN&&n.error("ws.readyState is not open"),r){const n=new Uint8Array(r.length+e.byteLength);n.set(r,0),n.set(e,r.length),t.send(n.buffer),r=null}else t.send(e)},abort(){}})).catch(e=>{b(t)}),!o&&s&&await s()}function x(e){const t=[atob("c3BlZWQuY2xvdWRmbGFyZS5jb20=")];if(t.includes(e))return!0;for(const n of t)if(e.endsWith("."+n)||e===n)return!0;return!1}async function A(t,n,s){const{username:r,password:o,hostname:a,port:i}=u,c=e({hostname:a,port:i}),l=c.writable.getWriter(),d=c.readable.getReader();try{const e=r&&o?new Uint8Array([5,2,0,2]):new Uint8Array([5,1,0]);await l.write(e);let a=await d.read();if(a.done||a.value.byteLength<2)throw new Error("S5 method selection failed");const i=new Uint8Array(a.value)[1];if(2===i){if(!r||!o)throw new Error("S5 requires authentication");const e=(new TextEncoder).encode(r),t=(new TextEncoder).encode(o),n=new Uint8Array([1,e.length,...e,t.length,...t]);if(await l.write(n),a=await d.read(),a.done||0!==new Uint8Array(a.value)[1])throw new Error("S5 authentication failed")}else if(0!==i)throw new Error(`S5 unsupported auth method: ${i}`);const u=(new TextEncoder).encode(t),p=new Uint8Array([5,1,0,3,u.length,...u,n>>8,255&n]);if(await l.write(p),a=await d.read(),a.done||0!==new Uint8Array(a.value)[1])throw new Error("S5 connection failed");return await l.write(s),l.releaseLock(),d.releaseLock(),c}catch(e){try{l.releaseLock()}catch(e){}try{d.releaseLock()}catch(e){}try{c.close()}catch(e){}throw e}}async function T(t,n,s){const{username:r,password:o,hostname:a,port:i}=u,c=e({hostname:a,port:i}),l=c.writable.getWriter(),d=c.readable.getReader();try{const e=`CONNECT ${t}:${n} HTTP/1.1\r\nHost: ${t}:${n}\r\n${r&&o?`Proxy-Authorization: Basic ${btoa(`${r}:${o}`)}\r\n`:""}User-Agent: Mozilla/5.0\r\nConnection: keep-alive\r\n\r\n`;await l.write((new TextEncoder).encode(e));let a=new Uint8Array(0),i=-1,u=0;for(;-1===i&&u<8192;){const{done:e,value:t}=await d.read();if(e)throw new Error("Connection closed before receiving HTTP response");a=new Uint8Array([...a,...t]),u=a.length;const n=a.findIndex((e,t)=>t<a.length-3&&13===a[t]&&10===a[t+1]&&13===a[t+2]&&10===a[t+3]);-1!==n&&(i=n+4)}if(-1===i)throw new Error("Invalid HTTP response");const p=parseInt((new TextDecoder).decode(a.slice(0,i)).split("\r\n")[0].match(/HTTP\/\d\.\d\s+(\d+)/)[1]);if(p<200||p>=300)throw new Error(`Connection failed: HTTP ${p}`);return await l.write(s),l.releaseLock(),d.releaseLock(),c}catch(e){try{l.releaseLock()}catch(e){}try{d.releaseLock()}catch(e){}try{c.close()}catch(e){}throw e}}async function $(e,t,n,s="Get_SUB",r){try{const o=new Date,a={TYPE:s,IP:n,ASN:`AS${t.cf.asn||"0"} ${t.cf.asOrganization||"Unknown"}`,CC:`${t.cf.country||"N/A"} ${t.cf.city||"N/A"}`,URL:t.url,UA:t.headers.get("User-Agent")||"Unknown",TIME:o.getTime()};let i=[];const c=await e.KV.get("log.json");if(c)try{if(i=JSON.parse(c),Array.isArray(i))if("Get_SUB"!==s){const e=o.getTime()-18e5;if(i.some(s=>"Get_SUB"!==s.TYPE&&s.IP===n&&s.URL===t.url&&s.UA===(t.headers.get("User-Agent")||"Unknown")&&s.TIME>=e))return;for(i.push(a);JSON.stringify(i,null,2).length>4194304&&i.length>0;)i.shift()}else for(i.push(a);JSON.stringify(i,null,2).length>4194304&&i.length>0;)i.shift();else i=[a];if(r.TG.enable)try{const t=await e.KV.get("tg.json"),n=JSON.parse(t);await async function(e,t,n,s){if(!e||!t)return;try{const r=new Date(n.TIME).toLocaleString("zh-CN",{timeZone:"Asia/Shanghai"}),o=new URL(n.URL),a=`<b>#${s.subGenerator.SUBNAME} logNotify</b>\n\n📌 <b>type:</b>#${n.TYPE}\n🌐 <b>IP:</b><code>${n.IP}</code>\n📍 <b>location:</b>${n.CC}\n🏢 <b>ASN:</b>${n.ASN}\n🔗 <b>domain:</b><code>${o.host}</code>\n🔍 <b>path:</b><code>${o.pathname+o.search}</code>\n🤖 <b>UA:</b><code>${n.UA}</code>\n📅 <b>time:</b>${r}\n`+(s.CF.Usage.success?`📊 <b>requestUsage:</b>${s.CF.Usage.total}/100000 <b>${(s.CF.Usage.total/1e5*100).toFixed(2)}%</b>\n`:""),i=`https://api.telegram.org/bot${e}/sendMessage?chat_id=${t}&parse_mode=HTML&text=${encodeURIComponent(a)}`;return fetch(i,{method:"GET",headers:{Accept:"text/html,application/xhtml+xml,application/xml;","Accept-Encoding":"gzip, deflate, br","User-Agent":n.UA||"Unknown"}})}catch(e){console.error("Error sending message:",e)}}(n.BotToken,n.ChatID,a,r)}catch(e){console.error(`readtg.jsonerror: ${e.message}`)}}catch(e){i=[a]}else i=[a];await e.KV.put("log.json",JSON.stringify(i,null,2))}catch(e){console.error(`logFailed: ${e.message}`)}}function P(e,t=3,n=2){if(!e||"string"!=typeof e)return e;if(e.length<=t+n)return e;const s=e.slice(0,t),r=e.slice(-n),o=e.length-t-n;return`${s}${"*".repeat(o)}${r}`}async function S(e){const t=new TextEncoder,n=await crypto.subtle.digest("MD5",t.encode(e)),s=Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,"0")).join(""),r=await crypto.subtle.digest("MD5",t.encode(s.slice(7,27)));return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("").toLowerCase()}async function I(e,t,n,o,a=!1){const i=t,u=performance.now(),p={TIME:(new Date).toISOString(),HOST:i,HOSTS:[t],UUID:n,protocolType:"vless",transport:"ws",skipCertVerify:!0,enable0RTT:!1,tlsFragment:null,randomPath:!1,ECH:!1,Fingerprint:"chrome",subGenerator:{local:!0,localIPPool:{randomIP:!0,randomCount:16,specifiedPort:-1},SUB:null,SUBNAME:"edgetunnel",SUBUpdateTime:3,TOKEN:await S(t+n)},subConverterConfig:{SUBAPI:"https://SUBAPI.cmliussss.net",SUBCONFIG:"https://raw.githubusercontent.com/cmliu/ACL4SSR/refs/heads/main/Clash/config/ACL4SSR_Online_Mini_MultiMode_CF.ini",SUBEMOJI:!1},reverseProxy:{PROXYIP:"auto",SOCKS5:{enable:c,globalMode:l,account:d,whitelist:g}},TG:{enable:!1,BotToken:null,ChatID:null},CF:{Email:null,GlobalAPIKey:null,AccountID:null,APIToken:null,UsageAPI:null,Usage:{success:!1,pages:0,workers:0,total:0,max:1e5}}};try{let t=await e.KV.get("config.json");t&&1!=a?r=JSON.parse(t):(await e.KV.put("config.json",JSON.stringify(p,null,2)),r=p)}catch(e){console.error(`readconfig_JSONerror: ${e.message}`),r=p}r.HOST=i,r.HOSTS||(r.HOSTS=[t]),e.HOST&&(r.HOSTS=(await v(e.HOST)).map(e=>e.toLowerCase().replace(/^https?:\/\//,"").split("/")[0].split(":")[0])),r.UUID=n,r.PATH=o?o.startsWith("/")?o:"/"+o:r.reverseProxy.SOCKS5.enable?"/"+r.reverseProxy.SOCKS5.enable+(r.reverseProxy.SOCKS5.globalMode?"://":"=")+r.reverseProxy.SOCKS5.account:"auto"===r.reverseProxy.PROXYIP?"/":`/proxyip=${r.reverseProxy.PROXYIP}`;const h="Shadowrocket"==r.tlsFragment?`&fragment=${encodeURIComponent("1,40-60,30-50,tlshello")}`:"Happ"==r.tlsFragment?`&fragment=${encodeURIComponent("3,1,tlshello")}`:"";r.Fingerprint||(r.Fingerprint="chrome"),r.ECH?r.subGenerator.SUBUpdateTime=1:r.ECH=!1;const m=r.ECH?`&ech=${encodeURIComponent("cloudflare-ech.com+"+f)}`:"";r.LINK=s(`${r.protocolType}://${n}@${i}:443?security=tls&type=${r.transport+m}&host=${i}&fp=${r.Fingerprint}&sni=${i}&path=${encodeURIComponent(r.enable0RTT?r.PATH+"?ed=2560":r.PATH)+h}&encryption=none${r.skipCertVerify?"&insecure=1&allowInsecure=1":""}#${encodeURIComponent(r.subGenerator.SUBNAME)}`),r.subGenerator.TOKEN=await S(t+n);const w={BotToken:null,ChatID:null};r.TG={enable:!!r.TG.enable&&r.TG.enable,...w};try{const t=await e.KV.get("tg.json");if(t){const e=JSON.parse(t);r.TG.ChatID=e.ChatID?e.ChatID:null,r.TG.BotToken=e.BotToken?P(e.BotToken):null}else await e.KV.put("tg.json",JSON.stringify(w,null,2))}catch(e){console.error(`readtg.jsonerror: ${e.message}`)}const y={Email:null,GlobalAPIKey:null,AccountID:null,APIToken:null,UsageAPI:null};r.CF={...y,Usage:{success:!1,pages:0,workers:0,total:0,max:1e5}};try{const t=await e.KV.get("cf.json");if(t){const e=JSON.parse(t);if(e.UsageAPI)try{const t=await fetch(e.UsageAPI),n=await t.json();r.CF.Usage=n}catch(e){console.error(`request CF_JSON.UsageAPI failed: ${e.message}`)}else{r.CF.Email=e.Email?e.Email:null,r.CF.GlobalAPIKey=e.GlobalAPIKey?P(e.GlobalAPIKey):null,r.CF.AccountID=e.AccountID?P(e.AccountID):null,r.CF.APIToken=e.APIToken?P(e.APIToken):null,r.CF.UsageAPI=null;const t=await O(e.Email,e.GlobalAPIKey,e.AccountID,e.APIToken);r.CF.Usage=t}}else await e.KV.put("cf.json",JSON.stringify(y,null,2))}catch(e){console.error(`readcf.jsonerror: ${e.message}`)}return r.loadtime=(performance.now()-u).toFixed(2)+"ms",r}async function U(e,t=16,n=-1){const s={9808:"cmcc",4837:"cu",4134:"ct"},r=e.cf.asn,o=s[r]?`https://raw.githubusercontent.com/cmliu/cmliu/main/CF-CIDR/${s[r]}.txt`:"https://raw.githubusercontent.com/cmliu/cmliu/main/CF-CIDR.txt",a={9808:"CFCMCCOptimal",4837:"CFCUOptimal",4134:"CFCTOptimal"}[r]||"CFofficialOptimal",i=[443,2053,2083,2087,2096,8443];let c=[];try{const e=await fetch(o);c=e.ok?await v(await e.text()):["104.16.0.0/13"]}catch{c=["104.16.0.0/13"]}const l=Array.from({length:t},()=>`${(e=>{const[t,n]=e.split("/"),s=32-parseInt(n),r=((t.split(".").reduce((e,t,n)=>e|parseInt(t)<<24-8*n,0)&4294967295<<s>>>0)>>>0)+Math.floor(Math.random()*Math.pow(2,s))>>>0;return[r>>>24&255,r>>>16&255,r>>>8&255,255&r].join(".")})(c[Math.floor(Math.random()*c.length)])}:${-1===n?i[Math.floor(Math.random()*i.length)]:n}#${a}`);return[l,l.join("\n")]}async function v(e){var t=e.replace(/[ "'\r\n]+/g,",").replace(/,+/g,",");","==t.charAt(0)&&(t=t.slice(1)),","==t.charAt(t.length-1)&&(t=t.slice(0,t.length-1));return t.split(",")}async function k(e,t="443",n=3e3){if(!e?.length)return[[],[],[]];const s=new Set;let r="";await Promise.allSettled(e.map(async e=>{try{const o=new AbortController,a=setTimeout(()=>o.abort(),n),i=await fetch(e,{signal:o.signal});clearTimeout(a);let c="";try{const e=await i.arrayBuffer(),t=(i.headers.get("content-type")||"").toLowerCase(),n=t.match(/charset=([^\s;]+)/i)?.[1]?.toLowerCase()||"";let s=["utf-8","gb2312"];(n.includes("gb")||n.includes("gbk")||n.includes("gb2312"))&&(s=["gb2312","utf-8"]);let r=!1;for(const t of s)try{const n=new TextDecoder(t).decode(e);if(n&&n.length>0&&!n.includes("<22>")){c=n,r=!0;break}if(n&&n.length>0)continue}catch(e){continue}if(r||(c=await i.text()),!c||0===c.trim().length)return}catch(e){return void console.error("Failed to decode response:",e)}const l=function(e){if("string"!=typeof e)return!1;const t=e.replace(/\s/g,"");if(0===t.length||t.length%4!=0)return!1;if(!/^[A-Za-z0-9+/]+={0,2}$/.test(t))return!1;try{return atob(t),!0}catch{return!1}}(c)?function(e){const t=new Uint8Array(atob(e).split("").map(e=>e.charCodeAt(0)));return new TextDecoder("utf-8").decode(t)}(c):c;if(l.split("#")[0].includes("://"))return void(r+=l+"\n");const d=c.trim().split("\n").map(e=>e.trim()).filter(e=>e),u=d.length>1&&d[0].includes(","),p=/^[^\[\]]*:[^\[\]]*:[^\[\]]/;if(u){const n=d[0].split(",").map(e=>e.trim()),r=d.slice(1);if(n.includes("IPaddr")&&n.includes("port")&&n.includes("dataCenter")){const e=n.indexOf("IPaddr"),t=n.indexOf("port"),o=n.indexOf("country")>-1?n.indexOf("country"):n.indexOf("city")>-1?n.indexOf("city"):n.indexOf("dataCenter"),a=n.indexOf("TLS");r.forEach(n=>{const r=n.split(",").map(e=>e.trim());if(-1!==a&&"true"!==r[a]?.toLowerCase())return;const i=p.test(r[e])?`[${r[e]}]`:r[e];s.add(`${i}:${r[t]}#${r[o]}`)})}else if(n.some(e=>e.includes("IP"))&&n.some(e=>e.includes("latency"))&&n.some(e=>e.includes("dlSpeed"))){const o=n.findIndex(e=>e.includes("IP")),a=n.findIndex(e=>e.includes("latency")),i=n.findIndex(e=>e.includes("dlSpeed")),c=new URL(e).searchParams.get("port")||t;r.forEach(e=>{const t=e.split(",").map(e=>e.trim()),n=p.test(t[o])?`[${t[o]}]`:t[o];s.add(`${n}:${c}#CFOptimal ${t[a]}ms ${t[i]}MB/s`)})}}else d.forEach(n=>{const r=n.indexOf("#"),[o,a]=r>-1?[n.substring(0,r),n.substring(r)]:[n,""];let i=!1;if(o.startsWith("["))i=/\]:(\d+)$/.test(o);else{const e=o.lastIndexOf(":");i=e>-1&&/^\d+$/.test(o.substring(e+1))}const c=new URL(e).searchParams.get("port")||t;s.add(i?n:`${o}:${c}${a}`)})}catch(e){}}));const o=r.trim()?[...new Set(r.split(/\r?\n/).filter(e=>""!==e.trim()))]:[];return[Array.from(s),o,[]]}async function E(e){if(e.includes("@")){const t=e.lastIndexOf("@");let n=e.substring(0,t).replaceAll("%3D","=");/^(?:[A-Z0-9+/]{4})*(?:[A-Z0-9+/]{2}==|[A-Z0-9+/]{3}=)?$/i.test(n)&&!n.includes(":")&&(n=atob(n)),e=`${n}@${e.substring(t+1)}`}const t=e.lastIndexOf("@"),[n,s]=-1===t?[e,void 0]:[e.substring(t+1),e.substring(0,t)];let r,o,a,i;if(s&&([r,o]=s.split(":"),!o))throw new Error('invalid SOCKS addrFormat:authMustBe "username:password" format');if(n.includes("]:"))[a,i]=[n.split("]:")[0]+"]",Number(n.split("]:")[1].replace(/[^\d]/g,""))];else if(n.startsWith("["))[a,i]=[n,80];else{const e=n.split(":");[a,i]=2===e.length?[e[0],Number(e[1].replace(/[^\d]/g,""))]:[n,80]}if(isNaN(i))throw new Error("invalid SOCKS addrFormat:portMustBeNumber");if(a.includes(":")&&!/^\[.*\]$/.test(a))throw new Error("invalid SOCKS addrFormat:IPv6 addrMustBeBracketed,like [2001:db8::1]");return{username:r,password:o,hostname:a,port:i}}async function O(e,t,n,s){const r="https://api.cloudflare.com/client/v4",o=e=>e?.reduce((e,t)=>e+(t?.sum?.requests||0),0)||0,a={"Content-Type":"application/json"};try{if(!(n||e&&t))return{success:!1,pages:0,workers:0,total:0,max:1e5};if(!n){const s=await fetch(`${r}/accounts`,{method:"GET",headers:{...a,"X-AUTH-EMAIL":e,"X-AUTH-KEY":t}});if(!s.ok)throw new Error(`accountGetFailed: ${s.status}`);const o=await s.json();if(!o?.result?.length)throw new Error("accountNotFound");const i=o.result.findIndex(t=>t.name?.toLowerCase().startsWith(e.toLowerCase()));n=o.result[i>=0?i:0]?.id}const i=new Date;i.setUTCHours(0,0,0,0);const c=s?{...a,Authorization:`Bearer ${s}`}:{...a,"X-AUTH-EMAIL":e,"X-AUTH-KEY":t},l=await fetch(`${r}/graphql`,{method:"POST",headers:c,body:JSON.stringify({query:"query getBillingMetrics($AccountID: String!, $filter: AccountWorkersInvocationsAdaptiveFilter_InputObject) {\n viewer { accounts(filter: {accountTag: $AccountID}) {\n pagesFunctionsInvocationsAdaptiveGroups(limit: 1000, filter: $filter) { sum { requests } }\n workersInvocationsAdaptive(limit: 10000, filter: $filter) { sum { requests } }\n } }\n }",variables:{AccountID:n,filter:{datetime_geq:i.toISOString(),datetime_leq:(new Date).toISOString()}}})});if(!l.ok)throw new Error(`queryFailed: ${l.status}`);const d=await l.json();if(d.errors?.length)throw new Error(d.errors[0].message);const u=d?.data?.viewer?.accounts?.[0];if(!u)throw new Error("accountDataNotFound");const p=o(u.pagesFunctionsInvocationsAdaptiveGroups),h=o(u.workersInvocationsAdaptive),f=p+h,g=1e5;return console.log(`statResult - Pages: ${p}, Workers: ${h}, totalCnt: ${f}, limit: 100000`),{success:!0,pages:p,workers:h,total:f,max:g}}catch(e){return console.error("getUsageError:",e.message),{success:!1,pages:0,workers:0,total:0,max:1e5}}}async function R(e="socks5",t){const n=Date.now();try{u=await E(t)}catch(s){return{success:!1,error:s.message,proxy:e+"://"+t,responseTime:Date.now()-n}}const{username:s,password:r,hostname:o,port:a}=u,i=s&&r?`${s}:${r}@${o}:${a}`:`${o}:${a}`;try{const t=new Uint8Array(0),s="socks5"==e?await A("check.socks5.090227.xyz",80,t):await T("check.socks5.090227.xyz",80,t);if(!s)return{success:!1,error:"cannotConnectToProxy",proxy:e+"://"+i,responseTime:Date.now()-n};try{const t=s.writable.getWriter(),r=new TextEncoder;await t.write(r.encode("GET /cdn-cgi/trace HTTP/1.1\r\nHost: check.socks5.090227.xyz\r\nConnection: close\r\n\r\n")),t.releaseLock();const o=s.readable.getReader(),a=new TextDecoder;let c="";try{for(;;){const{done:e,value:t}=await o.read();if(e)break;c+=a.decode(t,{stream:!0})}}finally{o.releaseLock()}return await s.close(),{success:!0,proxy:e+"://"+i,ip:c.match(/ip=(.*)/)[1],loc:c.match(/loc=(.*)/)[1],responseTime:Date.now()-n}}catch(t){try{await s.close()}catch(e){console.log("errorClosingConn:",e)}return{success:!1,error:t.message,proxy:e+"://"+i,responseTime:Date.now()-n}}}catch(t){return{success:!1,error:t.message,proxy:e+"://"+i,responseTime:Date.now()-n}}} |