@liblaf/sub-store 0.1.10 β†’ 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Subscription Store
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ var q="0.2.0";import{buildApplication as We,buildRouteMap as ze}from"@stricli/core";import{buildCommand as ce}from"@stricli/core";var K=ce({docs:{brief:"Print a friendly, customizable greeting."},parameters:{flags:{greeting:{kind:"parsed",parse:String,brief:"use TEXT as the greeting message",default:"Hello, world!"}}},async func({greeting:e}){console.log(e)}});import*as S from"fs/promises";import re from"path";import de from"consola";import ue from"ky";class f{client;constructor(e=process.env.SUB_STORE_URL??"https://sub.liblaf.me",r=process.env.SUB_STORE_TOKEN){this.client=ue.create({headers:{Authorization:`Bearer ${r}`},prefixUrl:e,redirect:"follow"})}async listProfiles(){let e=await this.client.get("api/profiles").json(),r={};for(let t of e.result)r[t.id]=t;return r}async uploadProfileArtifact(e,r,t){await this.client.post(`api/profiles/${e}/${r}`,{body:t})}async createProvider(e){await this.client.post(`api/providers/${e.id}`,{json:e})}async listProviders(){let e=await this.client.get("api/providers").json(),r={};for(let t of e.result)r[t.id]=t;return r}async downloadProviderArtifact(e,r){let t=await this.client.get(`api/providers/${e}/${r}`);if(t.headers.get("X-From-Cache")==="true")de.warn(`providers/${e}/${r} is from cache, it may be outdated.`);return t}async uploadProviderArtifact(e,r,t){if(r.endsWith(".json")){await this.client.post(`api/providers/${e}/${r}`,{json:t});return}else await this.client.post(`api/providers/${e}/${r}`,{body:t})}}var n={name:{common:"Unknown"},cca2:"UN",flag:"\uD83C\uDDFA\uD83C\uDDF3"};class C{wrapped;provider;country=n;emby=!1;info=!1;multiplier=1;constructor(e,r){this.wrapped=e;this.provider=r}get prettyName(){let e=this.name;if(e=this.name.match(/@(?<name>[\w-]+)/)?.groups?.name??this.name,e.startsWith("\u3010"))return`[${this.provider.id}]${e}`;return`[${this.provider.id}] ${e}`}}class k extends C{get name(){return this.wrapped.name}get type(){return this.wrapped.type}get server(){return this.wrapped.server}render(){return{...this.wrapped,name:this.prettyName}}}import fe from"js-yaml";function y(e){return fe.load(e)}import*as Y from"fs/promises";var B={"allow-lan":!0,"bind-address":"*","lan-allowed-ips":["100.64.0.0/10","127.0.0.0/8","172.16.0.0/12","::1/128"],"skip-auth-prefixes":["127.0.0.0/8","::1/128"],"log-level":"warning",ipv6:!0,"external-controller":"127.0.0.1:9090","external-ui":"ui","external-ui-url":"https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip",profile:{"store-selected":!0,"store-fake-ip":!0},"unified-delay":!1,"tcp-concurrent":!0,"geo-auto-update":!0,"geo-update-interval":24,"geox-url":{geoip:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat",geosite:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat",mmdb:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/country.mmdb",asn:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/GeoLite2-ASN.mmdb"},dns:{enable:!0,"cache-algorithm":"arc","prefer-h3":!1,ipv6:!0,"enhanced-mode":"redir-host","use-hosts":!0,"use-system-hosts":!0,"respect-rules":!0,"default-nameserver":["system","101.6.6.6","119.29.29.29","223.5.5.5"],"proxy-server-nameserver":["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],"direct-nameserver":["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],"direct-nameserver-follow-policy":!1,nameserver:["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],fallback:["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"],"fallback-filter":{geoip:!0,"geoip-code":"cn"},"nameserver-policy":{"ruleset:domain-direct":["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],"ruleset:domain-domestic":["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],"ruleset:domain-local":["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],"ruleset:domain-ai":["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"],"ruleset:domain-binance":["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"],"ruleset:domain-download":["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"],"ruleset:domain-global":["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"],"ruleset:domain-stream":["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"],"ruleset:domain-telegram":["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"]}},sniffer:{enable:!0,sniff:{HTTP:{ports:[80,8080],"override-destination":!0},TLS:{ports:[443,8443]},QUIC:{ports:[443,8443]}},"skip-domain":["Mijia Cloud","+.push.apple.com"]},"mixed-port":7892,rules:["AND,((DST-PORT,443),(NETWORK,UDP)),REJECT","RULE-SET,domain-direct,DIRECT","RULE-SET,domain-domestic,DIRECT","RULE-SET,domain-local,DIRECT","RULE-SET,domain-ai,AI","RULE-SET,domain-binance,Binance","RULE-SET,domain-download,Download","RULE-SET,domain-stream,Stream","RULE-SET,domain-telegram,PROXY","RULE-SET,domain-global,PROXY","RULE-SET,ipcidr-domestic,DIRECT","RULE-SET,ipcidr-local,DIRECT","RULE-SET,ipcidr-stream,Stream","RULE-SET,ipcidr-telegram,PROXY","RULE-SET,ipcidr-global,PROXY","MATCH,PROXY"],"__rule-providers-anchors":{classical:{type:"http",behavior:"classical",format:"text",interval:86400},domain:{type:"http",behavior:"domain",format:"mrs",interval:86400},ipcidr:{type:"http",behavior:"ipcidr",format:"mrs",interval:86400}},"rule-providers":{"domain-ai":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/ai.domain.mrs",path:"./rules/ai.domain.mrs"},"domain-binance":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/binance.domain.mrs",path:"./rules/binance.domain.mrs"},"domain-direct":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/direct.domain.mrs",path:"./rules/direct.domain.mrs"},"domain-domestic":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/domestic.domain.mrs",path:"./rules/domestic.domain.mrs"},"ipcidr-domestic":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/domestic.ipcidr.mrs",path:"./rules/domestic.ipcidr.mrs"},"domain-download":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/download.domain.mrs",path:"./rules/download.domain.mrs"},"domain-global":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/global.domain.mrs",path:"./rules/global.domain.mrs"},"ipcidr-global":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/global.ipcidr.mrs",path:"./rules/global.ipcidr.mrs"},"domain-local":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/local.domain.mrs",path:"./rules/local.domain.mrs"},"ipcidr-local":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/local.ipcidr.mrs",path:"./rules/local.ipcidr.mrs"},"domain-stream":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/stream.domain.mrs",path:"./rules/stream.domain.mrs"},"ipcidr-stream":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/stream.ipcidr.mrs",path:"./rules/stream.ipcidr.mrs"},"domain-telegram":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/telegram.domain.mrs",path:"./rules/telegram.domain.mrs"},"ipcidr-telegram":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/telegram.ipcidr.mrs",path:"./rules/telegram.ipcidr.mrs"}}};var X={"allow-lan":!0,"bind-address":"*","lan-allowed-ips":["100.64.0.0/10","127.0.0.0/8","172.16.0.0/12","::1/128"],"skip-auth-prefixes":["127.0.0.0/8","::1/128"],"log-level":"warning",ipv6:!0,"external-controller":"127.0.0.1:9090","external-ui":"ui","external-ui-url":"https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip",profile:{"store-selected":!0,"store-fake-ip":!0},"unified-delay":!1,"tcp-concurrent":!0,"geo-auto-update":!0,"geo-update-interval":24,"geox-url":{geoip:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat",geosite:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat",mmdb:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/country.mmdb",asn:"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/GeoLite2-ASN.mmdb"},dns:{enable:!0,"cache-algorithm":"arc","prefer-h3":!1,ipv6:!0,"enhanced-mode":"redir-host","use-hosts":!0,"use-system-hosts":!0,"respect-rules":!0,"default-nameserver":["system","101.6.6.6","119.29.29.29","223.5.5.5"],"proxy-server-nameserver":["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],"direct-nameserver":["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],"direct-nameserver-follow-policy":!1,nameserver:["system","https://101.6.6.6/dns-query","https://doh.pub/dns-query","https://dns.alidns.com/dns-query"],fallback:["https://cloudflare-dns.com/dns-query","https://dns.google/dns-query"],"fallback-filter":{geoip:!0,"geoip-code":"cn"}},sniffer:{enable:!0,sniff:{HTTP:{ports:[80,8080],"override-destination":!0},TLS:{ports:[443,8443]},QUIC:{ports:[443,8443]}},"skip-domain":["Mijia Cloud","+.push.apple.com"]},"mixed-port":7892,rules:["AND,((DST-PORT,443),(NETWORK,UDP)),REJECT","RULE-SET,domain-direct,DIRECT","RULE-SET,domain-domestic,DIRECT","RULE-SET,domain-local,DIRECT","RULE-SET,domain-ai,AI","RULE-SET,domain-binance,Binance","RULE-SET,domain-download,Download","RULE-SET,domain-stream,Stream","RULE-SET,domain-telegram,PROXY","RULE-SET,domain-global,PROXY","RULE-SET,ipcidr-domestic,DIRECT","RULE-SET,ipcidr-local,DIRECT","RULE-SET,ipcidr-stream,Stream","RULE-SET,ipcidr-telegram,PROXY","RULE-SET,ipcidr-global,PROXY","MATCH,PROXY"],"__rule-providers-anchors":{classical:{type:"http",behavior:"classical",format:"text",interval:86400},domain:{type:"http",behavior:"domain",format:"mrs",interval:86400},ipcidr:{type:"http",behavior:"ipcidr",format:"mrs",interval:86400}},"rule-providers":{"domain-ai":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/ai.domain.mrs",path:"./rules/ai.domain.mrs"},"domain-binance":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/binance.domain.mrs",path:"./rules/binance.domain.mrs"},"domain-direct":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/direct.domain.mrs",path:"./rules/direct.domain.mrs"},"domain-domestic":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/domestic.domain.mrs",path:"./rules/domestic.domain.mrs"},"ipcidr-domestic":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/domestic.ipcidr.mrs",path:"./rules/domestic.ipcidr.mrs"},"domain-download":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/download.domain.mrs",path:"./rules/download.domain.mrs"},"domain-global":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/global.domain.mrs",path:"./rules/global.domain.mrs"},"ipcidr-global":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/global.ipcidr.mrs",path:"./rules/global.ipcidr.mrs"},"domain-local":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/local.domain.mrs",path:"./rules/local.domain.mrs"},"ipcidr-local":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/local.ipcidr.mrs",path:"./rules/local.ipcidr.mrs"},"domain-stream":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/stream.domain.mrs",path:"./rules/stream.domain.mrs"},"ipcidr-stream":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/stream.ipcidr.mrs",path:"./rules/stream.ipcidr.mrs"},"domain-telegram":{interval:86400,format:"mrs",behavior:"domain",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/telegram.domain.mrs",path:"./rules/telegram.domain.mrs"},"ipcidr-telegram":{interval:86400,format:"mrs",behavior:"ipcidr",type:"http",url:"https://testingcf.jsdelivr.net/gh/liblaf/route-rules@mihomo/mihomo/telegram.ipcidr.mrs",path:"./rules/telegram.ipcidr.mrs"}}};var{$:ye}=globalThis.Bun;import ve from"consola";import we from"js-yaml";import*as w from"lodash-es";import a from"zod";var be=a.object({name:a.string(),type:a.string(),server:a.string()}),v=a.object({name:a.string(),type:a.enum(["select","url-test"]),proxies:a.array(a.string()),url:a.string().url().default("https://cp.cloudflare.com"),lazy:a.boolean().default(!0),"expected-status":a.number().int().min(100).max(599).default(204),icon:a.string().url().optional()}).passthrough(),mr=a.object({proxies:a.array(be).optional(),"proxy-groups":a.array(v).optional(),rules:a.array(a.string()).optional()});var Pe={"builtin://mihomo.yaml":B,"builtin://stash.yaml":X};class P{template;static async load(e){let r=Pe[e];if(!r){let t=await Y.readFile(e,"utf-8");r=y(t)}return new P(r)}constructor(e){this.template=e}render(e,r){let t=w.cloneDeep(this.template),o=this.renderDefaultGroup(),i=[o];for(let s of r)for(let[m,l]of s.group(e)){let p=this.renderGroup(m,l);o.proxies.push(p.name),i.push(p)}return t.proxies=e.map((s)=>s.render()),t["proxy-groups"]=i,t=this.sanitize(t),this.serialize(t)}renderDefaultGroup(){return v.parse({name:"PROXY",type:"select",proxies:[]})}renderGroup(e,r){let t=r.map((i)=>i.prettyName);return v.parse({name:e.name,type:e.type,proxies:t,url:e.url,"expected-status":e["expected-status"],icon:e.icon})}sanitize(e){e=w.omitBy(e,(i,s)=>{return s.startsWith("__")});let r=e.rules??[],t=["DIRECT","REJECT","REJECT-DROP","PASS"];for(let i of e.proxies??[])t.push(i.name);for(let i of e["proxy-groups"]??[])t.push(i.name);let o=new Set(t);return e.rules=r.filter((i)=>{i=i.replace(/,no-resolve$/,"");let s=i.split(","),m=s[s.length-1].trim(),l=o.has(m);if(!l)ve.warn(`delete invalid rule: ${i}`);return l}),e}serialize(e){return we.dump(e,{indent:2,noRefs:!0,sortKeys:!0})}async test(e){await ye`mihomo -f ${e} -t`}}class x{}class c extends x{*group(e){let r=e.filter(this.filter);if(r.length>0)yield[this.meta,r]}}function d(e){return!e.emby&&!e.info&&e.type!=="hysteria2"}class T extends c{meta={name:"Info",type:"url-test",emoji:"\u2139\uFE0F",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Airport.png"};filter(e){return e.info}}class j extends c{meta={name:"Auto",type:"url-test",emoji:"\uD83D\uDE80",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Auto.png"};filter(e){return d(e)&&e.multiplier<=2}}class R extends c{static BINANCE_EXCLUDE_REGIONS=new Set(["CA","CN","CU","HK","IR","KP","MO","NL","TW","US"]);meta={name:"Binance",type:"url-test",emoji:"\uD83E\uDE99",url:"https://api.binance.com/api/v3/ping"};filter(e){return d(e)&&!!e.country&&!R.BINANCE_EXCLUDE_REGIONS.has(e.country.cca2)}}class M extends c{static AI_EXCLUDE_REGIONS=new Set(["HK","MO"]);meta={name:"AI",type:"url-test",emoji:"\uD83E\uDD16",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/AI.png"};filter(e){return d(e)&&!!e.country&&!M.AI_EXCLUDE_REGIONS.has(e.country.cca2)}}class I extends c{meta={name:"Download",type:"url-test",emoji:"\uD83D\uDCE5",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Download.png"};filter(e){return d(e)&&e.multiplier<=1}}class L extends c{meta={name:"Stream",type:"url-test",emoji:"\uD83D\uDCFA",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/YouTube.png"};filter(e){return d(e)&&e.multiplier<2}}import E from"@twemoji/api";class U extends x{*group(e){let r={};for(let t of e){if(!d(t))continue;let o=t.country.cca2,i=t.country,s=r[o]?.[1]??[];s.push(t),r[o]=[i,s]}for(let t of Object.keys(r).sort()){let[o,i]=r[t],s=o.flag,m="".concat(E.base,E.size,"/",E.convert.toCodePoint(s),E.ext);yield[{name:o.name.common,type:o.cca2===n.cca2?"select":"url-test",emoji:s,icon:m},i]}}}function J(){return[new j,new M,new R,new I,new T,new L,new U]}import Z from"dns/promises";import Se from"dataloader";import{z as Oe}from"zod";import xe from"dataloader";import Re from"ky";import*as Q from"lodash-es";import{z as u}from"zod";var Me=u.object({ip:u.string().ip(),location:u.object({country_code:u.string().length(2)}).passthrough().optional()}).passthrough(),Ee=u.record(u.string(),Me);class A{endpoint="https://api.ipapi.is/";loader;key;constructor(){this.loader=new xe(async(e)=>await this.batchLoadFn(e),{maxBatchSize:100}),this.key=process.env.IPAPI_IS_KEY}async lookup(e){return await this.loader.load(e)}async batchLoadFn(e){let r=await Re.post(this.endpoint,{json:{ips:e,key:this.key}}).json();r=Q.omit(r,["total_elapsed_ms"]);let t=Ee.parse(r);return e.map((o)=>t[o])}}class G{api;loader;constructor(){this.api=new A,this.loader=new Se(async(e)=>await this.batchLoadFn(e))}async lookup(e){return await this.loader.load(e)}async batchLoadFn(e){return await Promise.all(e.map(async(r)=>await this.loadFn(r)))}async loadFn(e){let r=[];if(Ce(e))r=[e];else r=(await Z.lookup(e,{all:!0})).map((i)=>i.address);let t=await Promise.all(r.map(async(o)=>await this.api.lookup(o)));for(let o of t){if(!o.location?.country_code)continue;return o}return{ip:r[0]??"",location:{country_code:n.cca2}}}}function Ce(e){return Oe.string().ip().safeParse(e).success}import ke from"world-countries";function V(e){return ke.find((r)=>r.cca2===e)}import _ from"consola";import Te from"world-countries";class h{async process(e){return await Promise.all(e.map(async(r)=>await this.processSingle(r)))}processSingle(e){throw Error("processSingle() Not Implemented")}}class W extends h{geoip=new G;async processSingle(e){if(e.emby||e.info)return e.country=n,e;if(e.country.cca2===n.cca2)e=this.inferFromName(e);if(e.country.cca2===n.cca2)e=await this.inferFromServer(e);if(e.country.cca2===n.cca2)_.fail(`${e.prettyName} (${D(e.country)})`);return e}inferFromName(e){let r=e.name;for(let t of Te){if(t.cca2==="CN")continue;for(let o of je(t)){if(!o)continue;if(o.test(r))return _.success(`${e.prettyName} ~ ${o} (${D(t)})`),e.country=t,e}}return e}async inferFromServer(e){let r=await this.geoip.lookup(e.server);if(r.location?.country_code)e.country=V(r.location.country_code)||n;else e.country=n;if(e.country.cca2!==n.cca2)_.success(`${e.prettyName} -> ${r.ip} (${D(e.country)})`);return e}}function*je(e){let r=new Set(["GB"]);function t(i){if(!i)return;if(r.has(i))return;return new RegExp(`\\b${i}\\b`)}function o(i){if(!i)return;if(r.has(i))return;return new RegExp(i,"iu")}for(let i of["en","zh"])for(let s of["narrow","short","long"]){let m=new Intl.DisplayNames(i,{style:s,type:"region"});if(s==="narrow"||s==="short")yield t(m.of(e.cca2));else if(s==="long")yield o(m.of(e.cca2))}yield o(e.name.common),yield o(e.name.official);for(let i in e.name.native)yield o(e.name.native[i].common),yield o(e.name.native[i].official);yield t(e.cca2),yield t(e.cca3),yield t(e.cioc);for(let i of e.capital)yield o(i);yield o(e.flag)}function D(e){return`${e.flag} ${e.name.common} (${e.cca2})`}import Ie from"consola";class z extends h{pattern=/Expire|Traffic|\u5269\u4F59|\u5957\u9910\u5230\u671F/iu;async processSingle(e){if(e.info=this.pattern.test(e.name),e.info)Ie.success(`${e.prettyName} ~ \u2139\uFE0F INFO`);return e}}function ee(){return[new z,new W]}import{buildCommand as Le}from"@stricli/core";import te from"consola";var oe=Le({docs:{brief:""},parameters:{flags:{filename:{kind:"parsed",parse:String,brief:"",default:"mihomo.yaml"},template:{kind:"parsed",parse:String,brief:"",default:"builtin://mihomo.yaml"}}},async func(e){let r=await P.load(e.template),t=J(),o=ee(),i=new f,s=await i.listProfiles(),m=await i.listProviders(),l=(await Promise.all(Object.values(m).map(async(p)=>await Ue(i,p)))).flat();for(let p of o)l=await p.process(l);for(let p of Object.values(s)){let N=r.render(l.filter((pe)=>{return p.providers.includes(pe.provider.id)}),t),b=re.join("outputs",p.id,e.filename);await S.mkdir(re.dirname(b),{recursive:!0}),await S.writeFile(b,N),await r.test(b),te.success(`-> ${b}`),await i.uploadProfileArtifact(p.id,e.filename,N)}}});async function Ue(e,r){let o=await(await e.downloadProviderArtifact(r.id,"mihomo.yaml")).text(),i=y(o);if(!i.proxies)return te.warn(`No proxies found in ${r.id}/mihomo.yaml`),[];return i.proxies.map((s)=>new k(s,r))}import{NotFoundException as _e}from"chanfana";import Ge from"ky";import{z as g}from"zod/v3";var dt=g.object({upload:g.number().optional(),download:g.number().optional(),total:g.number().optional(),expire:g.number().optional()}).passthrough();function ie(e){let r={};if(!e)return r;for(let t of e.split(";")){let[o,i]=t.split("=");if(!o||!i)continue;if(o=o.trim(),i=i.trim(),!o||!i)continue;if(o==="upload"||o==="download"||o==="total"||o==="expire")r[o]=+i;else r[o]=i}return r}import se from"js-yaml";import Ae from"ky";async function O(e,r){r=r??Ae.create({redirect:"follow"});let t=await r.get(e,{headers:{"User-Agent":"clash.meta"}}),o=await t.text();if(!se.load(o).proxies)throw Error("empty subscription");let s=ie(t.headers.get("Subscription-Userinfo"));return{content:o,userinfo:s}}class F{url;fetcher;constructor(e=process.env.SUBLINK_URL??"https://sublink.liblaf.me",r){this.url=e;this.fetcher=r}get client(){return Ge.create({fetch:this.fetcher?.fetch.bind(this.fetcher),prefixUrl:this.url,redirect:"follow"})}async clash(e){let r=new URL(`${this.url}/clash`);return r.searchParams.set("config",e),r.searchParams.set("ua","clash.meta"),await O(r,this.client)}}class H{sublink;constructor(e){this.sublink=e??new F}}class $ extends H{async fetch(e){if(e.mihomo)return await O(e.mihomo);let r=e.singbox??e.surge??e.xray;if(!r){let{id:t}=e;throw new _e(`Provider ${t} does not support mihomo`)}return await this.sublink.clash(r)}}import{buildCommand as De}from"@stricli/core";var ae=De({docs:{brief:""},parameters:{flags:{provider:{kind:"parsed",parse:String,brief:""},bwcounter:{kind:"parsed",parse:String,brief:"",optional:!0},mihomo:{kind:"parsed",parse:String,brief:"",optional:!0},singbox:{kind:"parsed",parse:String,brief:"",optional:!0},xray:{kind:"parsed",parse:String,brief:"",optional:!0}}},async func(e){let r=new f,t=e.provider,o={id:t,bwcounter:e.bwcounter,mihomo:e.mihomo,singbox:e.singbox,xray:e.xray};await r.createProvider(o);let i=new $,{content:s,userinfo:m}=await i.fetch(o);await r.uploadProviderArtifact(t,"mihomo.yaml",s),await r.uploadProviderArtifact(t,"userinfo.json",m)}});var Fe=ze({docs:{brief:""},routes:{hello:K,merge:oe,upload:ae}}),ne=We(Fe,{name:"sub-store",versionInfo:{currentVersion:q},scanner:{caseStyle:"allow-kebab-for-camel"}});import He from"fs";import $e from"os";import Ne from"path";var me={process,os:$e,fs:He,path:Ne};import{run as qe}from"@stricli/core";await qe(ne,process.argv.slice(2),me);
4
+
5
+ //# debugId=47C5828F97A1007B64756E2164756E21
6
+ //# sourceMappingURL=sub-store.js.map
@@ -0,0 +1,38 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["cli/app.ts", "cli/cmd/hello.ts", "cli/cmd/merge.ts", "cli/client.ts", "core/geo/constants.ts", "core/formats/shared/outbound.ts", "core/formats/mihomo/outbound.ts", "core/formats/mihomo/parse.ts", "core/formats/mihomo/template.ts", "core/formats/mihomo/schema.ts", "core/group/abc.ts", "core/group/common.ts", "core/group/country.ts", "core/group/factory.ts", "core/geo/geoip/geoip.ts", "core/geo/geoip/ipapi.is.ts", "core/geo/lookup.ts", "core/processor/country.ts", "core/processor/abc.ts", "core/processor/info.ts", "core/processor/factory.ts", "shared/fetch/mihomo.ts", "shared/fetch/sublink.ts", "shared/schema/userinfo.ts", "shared/fetch/direct/mihomo.ts", "shared/fetch/abc.ts", "cli/cmd/upload.ts", "cli/types.ts", "cli/bin/sub-store.ts"],
4
+ "sourcesContent": [
5
+ "import { version } from \"@package.json\";\nimport type { CommandContext, RouteMap } from \"@stricli/core\";\nimport { buildApplication, buildRouteMap } from \"@stricli/core\";\nimport hello from \"./cmd/hello\";\nimport merge from \"./cmd/merge\";\nimport upload from \"./cmd/upload\";\n\nconst route: RouteMap<CommandContext> = buildRouteMap({\n docs: {\n brief: \"\",\n },\n routes: { hello, merge, upload },\n});\n\nexport default buildApplication(route, {\n name: \"sub-store\",\n versionInfo: {\n currentVersion: version,\n },\n scanner: {\n caseStyle: \"allow-kebab-for-camel\",\n },\n});\n",
6
+ "import type { CommandContext } from \"@stricli/core\";\nimport { buildCommand } from \"@stricli/core\";\n\ntype Flags = {\n greeting: string;\n};\n\nexport default buildCommand({\n docs: {\n brief: \"Print a friendly, customizable greeting.\",\n },\n parameters: {\n flags: {\n greeting: {\n kind: \"parsed\",\n parse: String,\n brief: \"use TEXT as the greeting message\",\n default: \"Hello, world!\",\n },\n },\n },\n async func(this: CommandContext, { greeting }: Flags): Promise<void> {\n console.log(greeting);\n },\n});\n",
7
+ "import * as fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { SubStoreClient } from \"@cli/client\";\nimport { MihomoOutboundWrapper } from \"@core/formats/mihomo/outbound\";\nimport { parseMihomoConfig } from \"@core/formats/mihomo/parse\";\nimport type { MihomoConfig, MihomoOutbound } from \"@core/formats/mihomo/schema\";\nimport { MihomoTemplate } from \"@core/formats/mihomo/template\";\nimport type { Grouper } from \"@core/group/abc\";\nimport { defaultGroupers } from \"@core/group/factory\";\nimport type { Processor } from \"@core/processor/abc\";\nimport { defaultProcessors } from \"@core/processor/factory\";\nimport type { Profiles } from \"@shared/schema/profile\";\nimport type { Provider, Providers } from \"@shared/schema/provider\";\nimport { buildCommand } from \"@stricli/core\";\nimport consola from \"consola\";\nimport type { KyResponse } from \"ky\";\n\ntype Flags = {\n filename: string;\n template: string;\n};\n\nexport default buildCommand({\n docs: {\n brief: \"\",\n },\n parameters: {\n flags: {\n filename: {\n kind: \"parsed\",\n parse: String,\n brief: \"\",\n default: \"mihomo.yaml\",\n },\n template: {\n kind: \"parsed\",\n parse: String,\n brief: \"\",\n default: \"builtin://mihomo.yaml\",\n },\n },\n },\n async func(flags: Flags): Promise<void> {\n const template: MihomoTemplate = await MihomoTemplate.load(flags.template);\n const groupers: Grouper[] = defaultGroupers();\n const processors: Processor[] = defaultProcessors();\n\n const client = new SubStoreClient();\n const profiles: Profiles = await client.listProfiles();\n const providers: Providers = await client.listProviders();\n let outbounds: MihomoOutboundWrapper[] = (\n await Promise.all(\n Object.values(providers).map(\n async (provider: Provider): Promise<MihomoOutboundWrapper[]> =>\n await fetchMihomoOutbounds(client, provider),\n ),\n )\n ).flat();\n for (const processor of processors)\n outbounds = await processor.process(outbounds);\n for (const profile of Object.values(profiles)) {\n const content: string = template.render(\n outbounds.filter((o: MihomoOutboundWrapper): boolean => {\n return profile.providers.includes(o.provider.id);\n }),\n groupers,\n );\n const filepath: string = path.join(\"outputs\", profile.id, flags.filename);\n await fs.mkdir(path.dirname(filepath), { recursive: true });\n await fs.writeFile(filepath, content);\n await template.test(filepath);\n consola.success(`-> ${filepath}`);\n await client.uploadProfileArtifact(profile.id, flags.filename, content);\n }\n },\n});\n\nasync function fetchMihomoOutbounds(\n client: SubStoreClient,\n provider: Provider,\n): Promise<MihomoOutboundWrapper[]> {\n const response: KyResponse = await client.downloadProviderArtifact(\n provider.id,\n \"mihomo.yaml\",\n );\n const content: string = await response.text();\n const config: MihomoConfig = parseMihomoConfig(content);\n if (!config.proxies) {\n consola.warn(`No proxies found in ${provider.id}/mihomo.yaml`);\n return [];\n }\n return config.proxies.map(\n (o: MihomoOutbound): MihomoOutboundWrapper =>\n new MihomoOutboundWrapper(o, provider),\n );\n}\n",
8
+ "import type { Profile, Profiles } from \"@shared/schema/profile\";\nimport type { Provider, Providers } from \"@shared/schema/provider\";\nimport consola from \"consola\";\nimport type { KyInstance, KyResponse } from \"ky\";\nimport ky from \"ky\";\n\nexport function createClient(): KyInstance {\n const url: string = process.env.SUB_STORE_URL ?? \"https://sub.liblaf.me\";\n const token: string = process.env.SUB_STORE_TOKEN!;\n return ky.create({\n headers: { Authorization: `Bearer ${token}` },\n prefixUrl: url,\n redirect: \"follow\",\n });\n}\n\nexport class SubStoreClient {\n private client: KyInstance;\n\n constructor(\n url: string = process.env.SUB_STORE_URL ?? \"https://sub.liblaf.me\",\n token: string = process.env.SUB_STORE_TOKEN!,\n ) {\n this.client = ky.create({\n headers: { Authorization: `Bearer ${token}` },\n prefixUrl: url,\n redirect: \"follow\",\n });\n }\n\n async listProfiles(): Promise<Profiles> {\n type ListProfilesResponse = { success: boolean; result: Profile[] };\n const response: ListProfilesResponse = await this.client\n .get(\"api/profiles\")\n .json<ListProfilesResponse>();\n const profiles: Profiles = {};\n for (const profile of response.result) {\n profiles[profile.id] = profile;\n }\n return profiles;\n }\n\n async uploadProfileArtifact(\n id: string,\n filename: string,\n content: string,\n ): Promise<void> {\n await this.client.post(`api/profiles/${id}/${filename}`, { body: content });\n }\n\n async createProvider(provider: Provider): Promise<void> {\n await this.client.post(`api/providers/${provider.id}`, { json: provider });\n }\n\n async listProviders(): Promise<Providers> {\n type ListProvidersResponse = { success: boolean; result: Provider[] };\n const response: ListProvidersResponse = await this.client\n .get(\"api/providers\")\n .json<ListProvidersResponse>();\n const providers: Providers = {};\n for (const provider of response.result) {\n providers[provider.id] = provider;\n }\n return providers;\n }\n\n async downloadProviderArtifact(\n id: string,\n filename: string,\n ): Promise<KyResponse> {\n const response: KyResponse = await this.client.get(\n `api/providers/${id}/${filename}`,\n );\n if (response.headers.get(\"X-From-Cache\") === \"true\") {\n consola.warn(\n `providers/${id}/${filename} is from cache, it may be outdated.`,\n );\n }\n return response;\n }\n\n async uploadProviderArtifact(\n id: string,\n filename: string,\n content: string | any,\n ): Promise<void> {\n if (filename.endsWith(\".json\")) {\n await this.client.post(`api/providers/${id}/${filename}`, {\n json: content,\n });\n return;\n } else {\n await this.client.post(`api/providers/${id}/${filename}`, {\n body: content,\n });\n }\n }\n}\n",
9
+ "import type { Country } from \"world-countries\";\n\nexport const COUNTRY_UNKNOWN = {\n name: { common: \"Unknown\" },\n cca2: \"UN\",\n flag: \"πŸ‡ΊπŸ‡³\",\n} as Country;\n",
10
+ "import { COUNTRY_UNKNOWN } from \"@core/geo/constants\";\nimport type { Provider } from \"@shared/schema/provider\";\nimport type { Country } from \"world-countries\";\n\nexport abstract class OutboundWrapper<T = unknown> {\n // metadata\n country: Country = COUNTRY_UNKNOWN;\n emby: boolean = false;\n info: boolean = false;\n multiplier: number = 1.0;\n [key: string]: any;\n\n constructor(\n public wrapped: T,\n public provider: Provider,\n ) {}\n\n abstract get name(): string;\n abstract get server(): string;\n abstract get type(): string;\n\n get prettyName(): string {\n let name: string = this.name;\n const match: RegExpMatchArray | null = this.name.match(/@(?<name>[\\w-]+)/);\n name = match?.groups?.name ?? this.name;\n if (name.startsWith(\"【\")) return `[${this.provider.id}]${name}`;\n return `[${this.provider.id}] ${name}`;\n }\n\n abstract render(): T;\n}\n",
11
+ "import { OutboundWrapper } from \"../shared/outbound\";\nimport type { MihomoOutbound } from \"./schema\";\n\nexport class MihomoOutboundWrapper extends OutboundWrapper<MihomoOutbound> {\n override get name(): string {\n return this.wrapped.name;\n }\n\n override get type(): string {\n return this.wrapped.type;\n }\n\n override get server(): string {\n return this.wrapped.server;\n }\n\n override render(): MihomoOutbound {\n return {\n ...this.wrapped,\n name: this.prettyName,\n };\n }\n}\n",
12
+ "import yaml from \"js-yaml\";\nimport type { MihomoConfig } from \"./schema\";\n\nexport function parseMihomoConfig(content: string): MihomoConfig {\n return yaml.load(content) as MihomoConfig;\n}\n",
13
+ "import * as fs from \"node:fs/promises\";\nimport type { Grouper, GroupMeta } from \"@core/group/abc\";\nimport mihomo from \"@templates/mihomo.yaml\";\nimport stash from \"@templates/stash.yaml\";\nimport { $ } from \"bun\";\nimport consola from \"consola\";\nimport yaml from \"js-yaml\";\nimport * as _ from \"lodash-es\";\nimport type z from \"zod\";\nimport type { MihomoOutboundWrapper } from \"./outbound\";\nimport { parseMihomoConfig } from \"./parse\";\nimport type { MihomoConfig, MihomoGroup, MihomoOutbound } from \"./schema\";\nimport { MIHOMO_GROUP_SCHEMA } from \"./schema\";\n\nconst PATH_TO_TEMPLATE: Record<string, MihomoConfig> = {\n \"builtin://mihomo.yaml\": mihomo,\n \"builtin://stash.yaml\": stash,\n};\n\nexport class MihomoTemplate {\n static async load(path: string): Promise<MihomoTemplate> {\n let template: MihomoConfig | undefined = PATH_TO_TEMPLATE[path];\n if (!template) {\n const content: string = await fs.readFile(path, \"utf-8\");\n template = parseMihomoConfig(content);\n }\n return new MihomoTemplate(template);\n }\n\n constructor(readonly template: MihomoConfig) {}\n\n render(outbounds: MihomoOutboundWrapper[], groupers: Grouper[]): string {\n let config: MihomoConfig = _.cloneDeep(this.template);\n const defaultGroup: MihomoGroup = this.renderDefaultGroup();\n const groups: MihomoGroup[] = [defaultGroup];\n for (const grouper of groupers) {\n for (const [meta, filtered] of grouper.group(outbounds)) {\n const group: MihomoGroup = this.renderGroup(meta, filtered);\n defaultGroup.proxies.push(group.name);\n groups.push(group);\n }\n }\n config.proxies = outbounds.map(\n (o: MihomoOutboundWrapper): MihomoOutbound => o.render(),\n );\n config[\"proxy-groups\"] = groups;\n config = this.sanitize(config);\n return this.serialize(config);\n }\n\n renderDefaultGroup(): MihomoGroup {\n return MIHOMO_GROUP_SCHEMA.parse({\n name: \"PROXY\",\n type: \"select\",\n proxies: [],\n } satisfies z.input<typeof MIHOMO_GROUP_SCHEMA>);\n }\n\n renderGroup(\n meta: GroupMeta,\n outbounds: MihomoOutboundWrapper[],\n ): MihomoGroup {\n const proxies: string[] = outbounds.map(\n (o: MihomoOutboundWrapper): string => o.prettyName,\n );\n const group: MihomoGroup = MIHOMO_GROUP_SCHEMA.parse({\n name: meta.name,\n type: meta.type,\n proxies,\n url: meta.url,\n \"expected-status\": meta[\"expected-status\"],\n icon: meta.icon,\n } satisfies z.input<typeof MIHOMO_GROUP_SCHEMA>);\n return group;\n }\n\n sanitize(config: MihomoConfig): MihomoConfig {\n config = _.omitBy(config, (_value: any, key: string): boolean => {\n return key.startsWith(\"__\");\n });\n const rules: string[] = config.rules ?? [];\n const array: string[] = [\"DIRECT\", \"REJECT\", \"REJECT-DROP\", \"PASS\"];\n for (const outbound of config.proxies ?? []) array.push(outbound.name);\n for (const group of config[\"proxy-groups\"] ?? []) array.push(group.name);\n const proxies: Set<string> = new Set(array);\n config.rules = rules.filter((rule: string): boolean => {\n rule = rule.replace(/,no-resolve$/, \"\");\n const parts: string[] = rule.split(\",\");\n const dest: string = parts[parts.length - 1]!.trim();\n const has: boolean = proxies.has(dest);\n if (!has) consola.warn(`delete invalid rule: ${rule}`);\n return has;\n });\n return config;\n }\n\n serialize(config: MihomoConfig): string {\n return yaml.dump(config, {\n indent: 2,\n noRefs: true,\n sortKeys: true,\n });\n }\n\n async test(filepath: string): Promise<void> {\n await $`mihomo -f ${filepath} -t`;\n }\n}\n",
14
+ "import z from \"zod\";\n\nexport const MIHOMO_OUTBOUND_SCHEMA = z.object({\n name: z.string(),\n type: z.string(),\n server: z.string(),\n});\nexport type MihomoOutbound = z.infer<typeof MIHOMO_OUTBOUND_SCHEMA>;\n\nexport const MIHOMO_GROUP_SCHEMA = z\n .object({\n name: z.string(),\n type: z.enum([\"select\", \"url-test\"]),\n proxies: z.array(z.string()),\n url: z.string().url().default(\"https://cp.cloudflare.com\"),\n lazy: z.boolean().default(true),\n \"expected-status\": z.number().int().min(100).max(599).default(204),\n icon: z.string().url().optional(),\n })\n .passthrough();\nexport type MihomoGroup = z.infer<typeof MIHOMO_GROUP_SCHEMA>;\n\nexport const MIHOMO_CONFIG_SCHEMA = z.object({\n proxies: z.array(MIHOMO_OUTBOUND_SCHEMA).optional(),\n \"proxy-groups\": z.array(MIHOMO_GROUP_SCHEMA).optional(),\n rules: z.array(z.string()).optional(),\n});\nexport type MihomoConfig = z.infer<typeof MIHOMO_CONFIG_SCHEMA>;\n",
15
+ "import type { OutboundWrapper } from \"@core/formats/shared/outbound\";\n\nexport type GroupMeta = {\n name: string;\n type: \"select\" | \"url-test\";\n emoji?: string;\n icon?: string;\n url?: string;\n \"expected-status\"?: number;\n};\n\nexport abstract class Grouper {\n abstract group<T = unknown>(\n outbounds: OutboundWrapper<T>[],\n ): Generator<[GroupMeta, OutboundWrapper<T>[]]>;\n}\n\nexport abstract class FilterGrouper extends Grouper {\n abstract meta: GroupMeta;\n\n override *group<T = unknown>(\n outbounds: OutboundWrapper<T>[],\n ): Generator<[GroupMeta, OutboundWrapper<T>[]]> {\n const grouped: OutboundWrapper<T>[] = outbounds.filter(this.filter);\n if (grouped.length > 0) {\n yield [this.meta, grouped];\n }\n }\n\n abstract filter(outbound: OutboundWrapper): boolean;\n}\n",
16
+ "import type { OutboundWrapper } from \"@core/formats/shared/outbound\";\nimport type { GroupMeta } from \"./abc\";\nimport { FilterGrouper } from \"./abc\";\n\nexport function good<T = unknown>(outbound: OutboundWrapper<T>): boolean {\n // connection quality of Hysteria2 is poor\n return !outbound.emby && !outbound.info && outbound.type !== \"hysteria2\";\n}\n\nexport class Info extends FilterGrouper {\n override meta: GroupMeta = {\n name: \"Info\",\n type: \"url-test\",\n emoji: \"ℹ️\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Airport.png\",\n };\n\n override filter(outbound: OutboundWrapper): boolean {\n return outbound.info;\n }\n}\n\nexport class Auto extends FilterGrouper {\n override meta: GroupMeta = {\n name: \"Auto\",\n type: \"url-test\",\n emoji: \"πŸš€\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Auto.png\",\n };\n\n override filter(outbound: OutboundWrapper): boolean {\n return good(outbound) && outbound.multiplier <= 2.0;\n }\n}\n\nexport class Binance extends FilterGrouper {\n static BINANCE_EXCLUDE_REGIONS: Set<string> = new Set([\n \"CA\",\n \"CN\",\n \"CU\",\n \"HK\",\n \"IR\",\n \"KP\",\n \"MO\",\n \"NL\",\n \"TW\",\n \"US\",\n ]);\n\n override meta: GroupMeta = {\n name: \"Binance\",\n type: \"url-test\",\n emoji: \"πŸͺ™\",\n // TODO: add icon\n url: \"https://api.binance.com/api/v3/ping\",\n };\n\n override filter(outbound: OutboundWrapper): boolean {\n return (\n good(outbound) &&\n !!outbound.country &&\n !Binance.BINANCE_EXCLUDE_REGIONS.has(outbound.country.cca2)\n );\n }\n}\n\nexport class Ai extends FilterGrouper {\n static AI_EXCLUDE_REGIONS: Set<string> = new Set([\"HK\", \"MO\"]);\n\n override meta: GroupMeta = {\n name: \"AI\",\n type: \"url-test\",\n emoji: \"πŸ€–\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/AI.png\",\n };\n\n override filter(outbound: OutboundWrapper): boolean {\n return (\n good(outbound) &&\n !!outbound.country &&\n !Ai.AI_EXCLUDE_REGIONS.has(outbound.country.cca2)\n );\n }\n}\n\nexport class Download extends FilterGrouper {\n override meta: GroupMeta = {\n name: \"Download\",\n type: \"url-test\",\n emoji: \"πŸ“₯\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Download.png\",\n };\n\n override filter(outbound: OutboundWrapper): boolean {\n return good(outbound) && outbound.multiplier <= 1.0;\n }\n}\n\nexport class Stream extends FilterGrouper {\n override meta: GroupMeta = {\n name: \"Stream\",\n type: \"url-test\",\n emoji: \"πŸ“Ί\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/YouTube.png\",\n };\n\n override filter(outbound: OutboundWrapper): boolean {\n return good(outbound) && outbound.multiplier < 2.0;\n }\n}\n",
17
+ "import type { OutboundWrapper } from \"@core/formats/shared/outbound\";\nimport { COUNTRY_UNKNOWN } from \"@core/geo/constants\";\nimport twemoji from \"@twemoji/api\";\nimport type { Country } from \"world-countries\";\nimport type { GroupMeta } from \"./abc\";\nimport { Grouper } from \"./abc\";\nimport { good } from \"./common\";\n\nexport class CountryGrouper extends Grouper {\n override *group<T = unknown>(\n outbounds: OutboundWrapper<T>[],\n ): Generator<[GroupMeta, OutboundWrapper<T>[]]> {\n const groups: Record<string, [Country, OutboundWrapper<T>[]]> = {};\n for (const outbound of outbounds) {\n if (!good(outbound)) continue;\n const cca2: string = outbound.country.cca2;\n const country = outbound.country;\n const filtered: OutboundWrapper<T>[] = groups[cca2]?.[1] ?? [];\n filtered.push(outbound);\n groups[cca2] = [country, filtered];\n }\n for (const cca2 of Object.keys(groups).sort()) {\n const [country, outbounds] = groups[cca2]!;\n const emoji: string = country.flag;\n const icon: string = \"\".concat(\n twemoji.base,\n twemoji.size,\n \"/\",\n twemoji.convert.toCodePoint(emoji),\n twemoji.ext,\n );\n const meta: GroupMeta = {\n name: country.name.common,\n type: country.cca2 === COUNTRY_UNKNOWN.cca2 ? \"select\" : \"url-test\",\n emoji,\n icon,\n };\n yield [meta, outbounds];\n }\n }\n}\n",
18
+ "import type { Grouper } from \"./abc\";\nimport { Ai, Auto, Binance, Download, Info, Stream } from \"./common\";\nimport { CountryGrouper } from \"./country\";\n\nexport function defaultGroupers(): Grouper[] {\n return [\n new Auto(),\n new Ai(),\n new Binance(),\n new Download(),\n new Info(),\n new Stream(),\n new CountryGrouper(),\n ];\n}\n",
19
+ "import type { LookupAddress } from \"node:dns\";\nimport dns from \"node:dns/promises\";\nimport DataLoader from \"dataloader\";\nimport { z } from \"zod\";\nimport { COUNTRY_UNKNOWN } from \"../constants\";\nimport type { GeoIpApiResponse } from \"./ipapi.is\";\nimport { IpapiIs } from \"./ipapi.is\";\n\nexport class GeoIP {\n private api: IpapiIs;\n private loader: DataLoader<string, GeoIpApiResponse>;\n\n public constructor() {\n this.api = new IpapiIs();\n this.loader = new DataLoader(\n async (servers: readonly string[]): Promise<GeoIpApiResponse[]> =>\n await this.batchLoadFn(servers),\n );\n }\n\n public async lookup(server: string): Promise<GeoIpApiResponse> {\n return await this.loader.load(server);\n }\n\n protected async batchLoadFn(\n servers: readonly string[],\n ): Promise<GeoIpApiResponse[]> {\n return await Promise.all(\n servers.map(\n async (server: string): Promise<GeoIpApiResponse> =>\n await this.loadFn(server),\n ),\n );\n }\n\n protected async loadFn(server: string): Promise<GeoIpApiResponse> {\n let ips: string[] = [];\n if (isIpAddr(server)) {\n ips = [server];\n } else {\n const addresses: LookupAddress[] = await dns.lookup(server, {\n all: true,\n });\n ips = addresses.map((addr: LookupAddress): string => addr.address);\n }\n const responses: GeoIpApiResponse[] = await Promise.all(\n ips.map(\n async (ip: string): Promise<GeoIpApiResponse> =>\n await this.api.lookup(ip),\n ),\n );\n for (const response of responses) {\n if (!response.location?.country_code) continue;\n return response;\n }\n return {\n ip: ips[0] ?? \"\",\n location: { country_code: COUNTRY_UNKNOWN.cca2 },\n };\n }\n}\n\nfunction isIpAddr(data: string): boolean {\n return z.string().ip().safeParse(data).success;\n}\n",
20
+ "import DataLoader from \"dataloader\";\nimport ky from \"ky\";\nimport * as _ from \"lodash-es\";\nimport { z } from \"zod\";\n\nconst RESPONSE_SCHEMA = z\n .object({\n ip: z.string().ip(),\n location: z\n .object({ country_code: z.string().length(2) })\n .passthrough()\n .optional(),\n })\n .passthrough();\nexport type GeoIpApiResponse = z.infer<typeof RESPONSE_SCHEMA>;\n\nconst BULK_RESPONSE_SCHEMA = z.record(z.string(), RESPONSE_SCHEMA);\ntype BulkApiResponse = z.infer<typeof BULK_RESPONSE_SCHEMA>;\n\nexport class IpapiIs {\n endpoint: string = \"https://api.ipapi.is/\";\n private loader: DataLoader<string, GeoIpApiResponse>;\n private key?: string;\n\n public constructor() {\n this.loader = new DataLoader(\n async (ips: readonly string[]): Promise<GeoIpApiResponse[]> =>\n await this.batchLoadFn(ips),\n { maxBatchSize: 100 },\n );\n this.key = process.env.IPAPI_IS_KEY;\n }\n\n public async lookup(ip: string): Promise<GeoIpApiResponse> {\n return await this.loader.load(ip);\n }\n\n protected async batchLoadFn(\n ips: readonly string[],\n ): Promise<GeoIpApiResponse[]> {\n let data: any = await ky\n .post(this.endpoint, { json: { ips, key: this.key } })\n .json();\n data = _.omit(data, [\"total_elapsed_ms\"]);\n const response: BulkApiResponse = BULK_RESPONSE_SCHEMA.parse(data);\n return ips.map((ip: string): GeoIpApiResponse => response[ip]!);\n }\n}\n",
21
+ "import type { Country } from \"world-countries\";\nimport countries from \"world-countries\";\n\nexport function lookupCountry(cca2: string): Country | undefined {\n return countries.find((c: Country): boolean => c.cca2 === cca2);\n}\n",
22
+ "import type { OutboundWrapper } from \"@core/formats/shared/outbound\";\nimport { COUNTRY_UNKNOWN } from \"@core/geo/constants\";\nimport { GeoIP } from \"@core/geo/geoip/geoip\";\nimport type { GeoIpApiResponse } from \"@core/geo/geoip/ipapi.is\";\nimport { lookupCountry } from \"@core/geo/lookup\";\nimport consola from \"consola\";\nimport countries, { type Country } from \"world-countries\";\nimport { Processor } from \"./abc\";\n\nexport class ProcessorCountry extends Processor {\n private readonly geoip: GeoIP = new GeoIP();\n\n public override async processSingle<\n O extends OutboundWrapper<T>,\n T = unknown,\n >(outbound: O): Promise<O> {\n if (outbound.emby || outbound.info) {\n outbound.country = COUNTRY_UNKNOWN;\n return outbound;\n }\n if (outbound.country.cca2 === COUNTRY_UNKNOWN.cca2)\n outbound = this.inferFromName(outbound);\n if (outbound.country.cca2 === COUNTRY_UNKNOWN.cca2)\n outbound = await this.inferFromServer(outbound);\n if (outbound.country.cca2 === COUNTRY_UNKNOWN.cca2) {\n consola.fail(\n `${outbound.prettyName} (${prettyCountry(outbound.country)})`,\n );\n }\n return outbound;\n }\n\n protected inferFromName<T extends OutboundWrapper>(outbound: T): T {\n const name: string = outbound.name;\n for (const country of countries) {\n if (country.cca2 === \"CN\") continue;\n for (const pattern of patterns(country)) {\n if (!pattern) continue;\n if (pattern.test(name)) {\n consola.success(\n `${outbound.prettyName} ~ ${pattern} (${prettyCountry(country)})`,\n );\n outbound.country = country;\n return outbound;\n }\n }\n }\n return outbound;\n }\n\n protected async inferFromServer<T extends OutboundWrapper>(\n outbound: T,\n ): Promise<T> {\n const response: GeoIpApiResponse = await this.geoip.lookup(outbound.server);\n if (response.location?.country_code) {\n outbound.country =\n lookupCountry(response.location.country_code) || COUNTRY_UNKNOWN;\n } else {\n outbound.country = COUNTRY_UNKNOWN;\n }\n if (outbound.country.cca2 !== COUNTRY_UNKNOWN.cca2) {\n consola.success(\n `${outbound.prettyName} -> ${response.ip} (${prettyCountry(outbound.country)})`,\n );\n }\n return outbound;\n }\n}\n\nfunction* patterns(country: Country): Generator<RegExp | undefined> {\n const EXCLUDE_PATTERNS = new Set([\n \"GB\", // gigabyte\n ]);\n\n function short(pattern?: string): RegExp | undefined {\n if (!pattern) return undefined;\n if (EXCLUDE_PATTERNS.has(pattern)) return undefined;\n return new RegExp(`\\\\b${pattern}\\\\b`);\n }\n\n function long(pattern?: string): RegExp | undefined {\n if (!pattern) return undefined;\n if (EXCLUDE_PATTERNS.has(pattern)) return undefined;\n return new RegExp(pattern, \"iu\");\n }\n\n for (const locale of [\"en\", \"zh\"]) {\n for (const style of [\"narrow\", \"short\", \"long\"]) {\n const display = new Intl.DisplayNames(locale, {\n style: style as Intl.RelativeTimeFormatStyle,\n type: \"region\",\n });\n if (style === \"narrow\" || style === \"short\") {\n yield short(display.of(country.cca2));\n } else if (style === \"long\") {\n yield long(display.of(country.cca2));\n }\n }\n }\n yield long(country.name.common);\n yield long(country.name.official);\n for (const lang in country.name.native) {\n yield long(country.name.native[lang]!.common);\n yield long(country.name.native[lang]!.official);\n }\n yield short(country.cca2);\n // yield long(country.ccn3);\n yield short(country.cca3);\n yield short(country.cioc);\n for (const capital of country.capital) yield long(capital);\n // for (const alt of country.altSpellings) yield long(alt);\n yield long(country.flag);\n}\n\nfunction prettyCountry(country: Country): string {\n return `${country.flag} ${country.name.common} (${country.cca2})`;\n}\n",
23
+ "import type { OutboundWrapper } from \"@core/formats/shared/outbound\";\n\nexport abstract class Processor {\n async process<O extends OutboundWrapper<T>, T = unknown>(\n outbounds: O[],\n ): Promise<O[]> {\n return await Promise.all(\n outbounds.map(async (o: O): Promise<O> => await this.processSingle(o)),\n );\n }\n\n processSingle<O extends OutboundWrapper<T>, T = unknown>(\n _outbound: O,\n ): Promise<O> {\n throw new Error(\"processSingle() Not Implemented\");\n }\n}\n",
24
+ "import type { OutboundWrapper } from \"@core/formats/shared/outbound\";\nimport consola from \"consola\";\nimport { Processor } from \"./abc\";\n\nexport class ProcessorInfo extends Processor {\n pattern: RegExp = /Expire|Traffic|剩余|ε₯—ι€εˆ°ζœŸ/iu;\n\n override async processSingle<O extends OutboundWrapper<T>, T = unknown>(\n outbound: O,\n ): Promise<O> {\n outbound.info = this.pattern.test(outbound.name);\n if (outbound.info) consola.success(`${outbound.prettyName} ~ ℹ️ INFO`);\n return outbound;\n }\n}\n",
25
+ "import type { Processor } from \"./abc\";\nimport { ProcessorCountry } from \"./country\";\nimport { ProcessorInfo } from \"./info\";\n\nexport function defaultProcessors(): Processor[] {\n return [new ProcessorInfo(), new ProcessorCountry()];\n}\n",
26
+ "import type { Provider } from \"@shared/schema/provider\";\nimport { NotFoundException } from \"chanfana\";\nimport { LocalFetcher } from \"./abc\";\nimport { fetchMihomoDirect } from \"./direct/mihomo\";\nimport type { LocalFetchResult } from \"./types\";\n\nexport class MihomoLocalFetcher extends LocalFetcher<string> {\n override async fetch(provider: Provider): Promise<LocalFetchResult<string>> {\n if (provider.mihomo) {\n return await fetchMihomoDirect(provider.mihomo);\n }\n const url: string | undefined =\n provider.singbox ?? provider.surge ?? provider.xray;\n if (!url) {\n const { id } = provider;\n throw new NotFoundException(`Provider ${id} does not support mihomo`);\n }\n return await this.sublink.clash(url);\n }\n}\n",
27
+ "import type { KyInstance } from \"ky\";\nimport ky from \"ky\";\nimport { fetchMihomoDirect } from \"./direct/mihomo\";\nimport type { LocalFetchResult } from \"./types\";\n\nexport class Sublink {\n constructor(\n private url: string = process.env.SUBLINK_URL ??\n \"https://sublink.liblaf.me\",\n private fetcher?: Fetcher,\n ) {}\n\n get client(): KyInstance {\n return ky.create({\n fetch: this.fetcher?.fetch.bind(this.fetcher),\n prefixUrl: this.url,\n redirect: \"follow\",\n });\n }\n\n async clash(url: string): Promise<LocalFetchResult<string>> {\n const input = new URL(`${this.url}/clash`);\n input.searchParams.set(\"config\", url);\n input.searchParams.set(\"ua\", \"clash.meta\");\n return await fetchMihomoDirect(input, this.client);\n }\n}\n",
28
+ "import { z } from \"zod/v3\";\n\nexport const USERINFO_SCHEMA = z\n .object({\n upload: z.number().optional(),\n download: z.number().optional(),\n total: z.number().optional(),\n expire: z.number().optional(),\n })\n .passthrough();\nexport type Userinfo = z.infer<typeof USERINFO_SCHEMA>;\n\nexport function parseUserinfo(header: string | null): Userinfo {\n const userinfo: Userinfo = {};\n if (!header) return userinfo;\n for (const part of header.split(\";\")) {\n let [key, value] = part.split(\"=\");\n if (!key || !value) continue;\n key = key.trim();\n value = value.trim();\n if (!key || !value) continue;\n if (\n key === \"upload\" ||\n key === \"download\" ||\n key === \"total\" ||\n key === \"expire\"\n ) {\n userinfo[key] = +value;\n } else {\n userinfo[key] = value;\n }\n }\n return userinfo;\n}\n\nexport function serializeUserinfo(userinfo: Userinfo): string {\n return Object.entries(userinfo)\n .map(([key, value]: [string, unknown]): string => `${key}=${value}`)\n .join(\"; \");\n}\n",
29
+ "import type { Userinfo } from \"@shared/schema/userinfo\";\nimport { parseUserinfo } from \"@shared/schema/userinfo\";\nimport yaml from \"js-yaml\";\nimport type { KyInstance, KyResponse } from \"ky\";\nimport ky from \"ky\";\nimport type { LocalFetchResult } from \"../types\";\n\ntype ClashConfig = {\n proxies: unknown[];\n};\n\nexport async function fetchMihomoDirect(\n input: string | URL,\n client?: KyInstance,\n): Promise<LocalFetchResult<string>> {\n client = client ?? ky.create({ redirect: \"follow\" });\n const response: KyResponse = await client.get(input, {\n headers: { \"User-Agent\": \"clash.meta\" },\n });\n const content: string = await response.text();\n const config = yaml.load(content) as ClashConfig;\n if (!config.proxies) {\n throw new Error(\"empty subscription\");\n }\n const userinfo: Userinfo = parseUserinfo(\n response.headers.get(\"Subscription-Userinfo\"),\n );\n return { content, userinfo };\n}\n",
30
+ "import type { Provider } from \"@shared/schema/provider\";\nimport { Sublink } from \"./sublink\";\nimport type { LocalFetchResult } from \"./types\";\n\nexport abstract class LocalFetcher<T> {\n protected sublink: Sublink;\n\n constructor(sublink?: Sublink) {\n this.sublink = sublink ?? new Sublink();\n }\n\n abstract fetch(provider: Provider): Promise<LocalFetchResult<T>>;\n}\n",
31
+ "import { SubStoreClient } from \"@cli/client\";\nimport { MihomoLocalFetcher } from \"@shared/fetch/mihomo\";\nimport type { Provider } from \"@shared/schema/provider\";\nimport { buildCommand } from \"@stricli/core\";\n\ntype Flags = {\n provider: string;\n bwcounter?: string;\n mihomo?: string;\n singbox?: string;\n xray?: string;\n};\n\nexport default buildCommand({\n docs: {\n brief: \"\",\n },\n parameters: {\n flags: {\n provider: { kind: \"parsed\", parse: String, brief: \"\" },\n bwcounter: { kind: \"parsed\", parse: String, brief: \"\", optional: true },\n mihomo: { kind: \"parsed\", parse: String, brief: \"\", optional: true },\n singbox: { kind: \"parsed\", parse: String, brief: \"\", optional: true },\n xray: { kind: \"parsed\", parse: String, brief: \"\", optional: true },\n },\n },\n async func(flags: Flags): Promise<void> {\n const client = new SubStoreClient();\n const id: string = flags.provider;\n const provider: Provider = {\n id,\n bwcounter: flags.bwcounter,\n mihomo: flags.mihomo,\n singbox: flags.singbox,\n xray: flags.xray,\n };\n await client.createProvider(provider);\n\n const fetcher = new MihomoLocalFetcher();\n const { content, userinfo } = await fetcher.fetch(provider);\n await client.uploadProviderArtifact(id, \"mihomo.yaml\", content);\n await client.uploadProviderArtifact(id, \"userinfo.json\", userinfo);\n },\n});\n",
32
+ "import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { StricliAutoCompleteContext } from \"@stricli/auto-complete\";\nimport type { CommandContext } from \"@stricli/core\";\n\nexport interface Context extends CommandContext, StricliAutoCompleteContext {\n readonly process: NodeJS.Process;\n}\n\nexport const context: Context = { process, os, fs, path };\n",
33
+ "#!/usr/bin/env bun\nimport app from \"@cli/app\";\nimport { context } from \"@cli/types\";\nimport { run } from \"@stricli/core\";\n\nawait run(app, process.argv.slice(2), context);\n"
34
+ ],
35
+ "mappings": "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",
36
+ "debugId": "47C5828F97A1007B64756E2164756E21",
37
+ "names": []
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liblaf/sub-store",
3
- "version": "0.1.10",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/liblaf/sub-store",
@@ -20,59 +20,78 @@
20
20
  },
21
21
  "type": "module",
22
22
  "exports": {
23
- ".": {
24
- "import": "./dist/index.js"
25
- },
26
- "./bin/sub-store": {
27
- "import": "./dist/bin/sub-store.js"
23
+ "./sub-store": {
24
+ "import": "./dist/sub-store.js"
28
25
  },
29
26
  "./package.json": "./package.json"
30
27
  },
31
- "module": "./dist/index.js",
32
28
  "bin": {
33
- "sub-store": "./dist/bin/sub-store.js"
29
+ "sub-store": "./dist/sub-store.js"
34
30
  },
35
31
  "files": [
36
32
  "dist"
37
33
  ],
38
34
  "scripts": {
39
35
  "build": "bunup",
36
+ "cf-typegen": "wrangler types --env-file '.dev.vars.example' --env-interface 'CloudflareBindings' './worker/worker-configuration.d.ts'",
37
+ "dev": "wrangler dev",
40
38
  "format": "biome format",
41
39
  "format:fix": "biome format --write",
42
40
  "lint": "biome check",
43
41
  "lint:fix": "biome check --write",
44
- "prepack": "npm run build",
42
+ "prepack": "bun run build",
43
+ "prepare": "bun run cf-typegen",
45
44
  "test": "bun test",
46
45
  "test:coverage": "bun test --coverage",
47
46
  "test:watch": "bun test --watch",
48
- "tsc": "tsc --noEmit"
47
+ "type-check": "tsc --noEmit"
48
+ },
49
+ "prettier": {
50
+ "plugins": [
51
+ "prettier-plugin-packagejson"
52
+ ],
53
+ "trailingComma": "none"
49
54
  },
50
55
  "dependencies": {
56
+ "@scalar/hono-api-reference": "^0.9.30",
57
+ "@scalar/openapi-to-markdown": "^0.3.12",
51
58
  "@stricli/core": "^1.2.4",
52
59
  "@twemoji/api": "^17.0.2",
60
+ "chanfana": "^2.8.3",
53
61
  "consola": "^3.4.2",
54
62
  "dataloader": "^2.2.3",
55
- "ky": "^1.14.1",
56
- "remeda": "^2.32.0",
63
+ "hono": "^4.11.3",
64
+ "js-yaml": "^4.1.1",
65
+ "ky": "^1.14.2",
66
+ "lodash-es": "^4.17.22",
57
67
  "world-countries": "^5.1.0",
58
- "yaml": "^2.8.2",
59
- "zod": "^4.1.13"
68
+ "zod": "^3.25.76"
60
69
  },
61
70
  "devDependencies": {
62
- "@biomejs/biome": "^2.3.8",
63
- "@liblaf/config": "^0.1.1",
71
+ "@biomejs/biome": "^2.3.10",
72
+ "@liblaf/config": "^0.1.3",
64
73
  "@stricli/auto-complete": "^1.2.4",
65
- "@types/bun": "^1.3.4",
66
- "bunup": "^0.16.10",
67
- "prettier": "^3.7.4"
74
+ "@types/bun": "^1.3.5",
75
+ "@types/js-yaml": "^4.0.9",
76
+ "@types/lodash-es": "^4.17.12",
77
+ "bunup": "^0.16.11",
78
+ "prettier": "^3.7.4",
79
+ "prettier-plugin-packagejson": "^2.5.20",
80
+ "typescript": "^5.9.3",
81
+ "wrangler": "^4.54.0"
68
82
  },
69
83
  "peerDependencies": {
70
- "typescript": "^5.9.2"
84
+ "typescript": "^5"
85
+ },
86
+ "peerDependenciesMeta": {
87
+ "typescript": {
88
+ "optional": true
89
+ }
71
90
  },
72
91
  "publishConfig": {
73
92
  "access": "public",
74
93
  "provenance": true,
75
94
  "registry": "https://registry.npmjs.org/"
76
95
  },
77
- "readme": "README.md"
96
+ "readme": "./README.md"
78
97
  }
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env bun
2
- // @bun
3
- import{run as Co}from"@stricli/core";import{buildApplication as Ao,buildRouteMap as Io}from"@stricli/core";var B="0.1.10",T="";import zo from"fs/promises";import{buildCommand as bo}from"@stricli/core";import Ro from"consola";import q from"world-countries";var m={name:{common:"Unknown"},cca2:"UN",flag:"\uD83C\uDDFA\uD83C\uDDF3"};function v(o){return q.find((e)=>e.cca2===o)}import $ from"dns/promises";import to from"dataloader";import V from"zod";import W from"dataloader";import oo from"ky";import*as Y from"remeda";import a from"zod";var eo=a.looseObject({ip:a.union([a.ipv4(),a.ipv6()]),location:a.looseObject({country_code:a.string().length(2)}).optional()}),ro=a.record(a.string(),eo);class y{endpoints="https://api.ipapi.is/";loader;key;constructor(){this.loader=new W(async(o)=>await this.batchLoadFn(o),{maxBatchSize:100}),this.key=process.env.IPAPI_IS_KEY}async lookup(o){return await this.loader.load(o)}async batchLoadFn(o){let e=await oo.post(this.endpoints,{json:{ips:o,key:this.key}}).json();e=Y.omit(e,["total_elapsed_ms"]);let r=ro.parse(e);return o.map((t)=>r[t])}}class O{api;loader;constructor(){this.api=new y,this.loader=new to(async(o)=>await this.batchLoadFn(o))}async lookup(o){return await this.loader.load(o)}async batchLoadFn(o){return await Promise.all(o.map(async(e)=>await this.loadFn(e)))}async loadFn(o){let e=[];if(io(o))e=[o];else e=(await $.lookup(o,{all:!0})).map((i)=>i.address);let r=await Promise.all(e.map(async(t)=>await this.api.lookup(t)));for(let t of r){if(!t.location?.country_code)continue;return t}return{ip:e[0]||"",location:{country_code:"UN"}}}}function io(o){return V.ipv4().safeParse(o).success||V.ipv6().safeParse(o).success}var so=process.env.SUBLINK_URL||"https://sublink.liblaf.me/clash";function C(o){let e=new URL(so);return e.searchParams.set("config",o),e.searchParams.set("ua","clash.meta"),e}class P{provider;country=m;info=!1;constructor(o){this.provider=o}get prettyName(){let o=this.name;if(this.provider.name==="JMS"){let e=this.name.match(/@(?<name>[\w-]+)/);if(e)o=e.groups?.name??this.name}if(o.startsWith("\u3010"))return`[${this.provider.name}]${o}`;return`[${this.provider.name}] ${o}`}}import po from"consola";import mo from"ky";import{z as c}from"zod";var J=c.object({name:c.string(),free:c.boolean().default(!1),jms:c.object({url:c.url()}).optional(),mihomo:c.object({url:c.url()}).optional()});class z{name;jms;mihomo;constructor(o){let{name:e,jms:r,mihomo:t}=J.parse(o);this.name=e,this.jms=r,this.mihomo=t}async fetchOutboundsMihomo(){let o=this.getMihomoURL();if(!o)return[];let e=new Headers({"User-Agent":"clash.meta"}),r=await mo.get(o,{headers:e}).text();return d(r).proxies.map((i)=>new M(i,this))}warnFormat(o){po.warn(`Provider '${this.name}' does not support '${o}'`)}getMihomoURL(){if(this.mihomo)return this.mihomo.url;if(this.jms)return C(this.jms.url);this.warnFormat("mihomo");return}}import s from"zod";var x=s.looseObject({name:s.string(),type:s.string(),server:s.string()}),g=s.looseObject({name:s.string(),type:s.enum(["select","url-test"]),proxies:s.array(s.string()),url:s.url().default("https://cp.cloudflare.com"),lazy:s.boolean().default(!0),"expected-status":s.int().min(100).max(599).default(204),icon:s.url().optional()}),b=s.looseObject({proxies:s.array(x).optional(),"proxy-groups":s.array(g).optional(),rules:s.array(s.string()).optional()});class M extends P{raw;constructor(o,e){super(e);this.raw=x.parse(o)}get name(){return this.raw.name}get type(){return this.raw.type}get server(){return this.raw.server}get mihomo(){return{...this.raw,name:this.prettyName}}}import no from"yaml";function d(o){let e=no.parse(o,{merge:!0});return b.parse(e)}import ao from"fs/promises";import*as R from"remeda";import lo from"yaml";class h{template;static async load(o){let e=await ao.readFile(o,"utf8");return new h(e)}constructor(o){this.template=d(o)}render(o,e){let r=R.clone(this.template);r.proxies=o.map((i)=>i.mihomo);let t=this.renderGroupProxy();r["proxy-groups"]=[t];for(let i of e){let p=this.renderGroup(o,i);if(!p)continue;r["proxy-groups"].push(p),t.proxies.push(p.name)}return r=this.sanitize(r),lo.stringify(r,{aliasDuplicateObjects:!1,sortMapEntries:!0})}sanitize(o){o=R.omitBy(o,(r,t)=>t.startsWith("__"));let e=new Set(["DIRECT","REJECT","REJECT-DROP","PASS"]);for(let r of o.proxies||[])e.add(r.name);for(let r of o["proxy-groups"]||[])e.add(r.name);if(o.rules)o.rules=o.rules.filter((r)=>{let t=r.split(",").filter((p)=>p.trim()!=="no-resolve"),i=t[t.length-1].trim();return e.has(i)});return o}renderGroup(o,e){let r=o.filter(e.filter);if(r.length===0)return;let t=r.map((p)=>p.prettyName),i={name:e.name,type:e.type,proxies:t,url:e.url,icon:e.icon};return g.parse(i)}renderGroupProxy(){let o={name:"PROXY",type:"select",proxies:[],icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Proxy.png"};return g.parse(o)}}function f(o){return!o.emby&&!o.info&&o.type!=="hysteria2"}var E={name:"Info",type:"url-test",emoji:"\u2139\uFE0F",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Airport.png",filter(o){return o.info}},w={name:"Auto",type:"url-test",emoji:"\uD83D\uDE80",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Auto.png",filter(o){return f(o)&&o.multiplier<=2}},co=new Set(["CA","CN","CU","HK","IR","KP","MO","NL","TW","US"]),K={name:"Binance",type:"url-test",emoji:"\uD83E\uDE99",url:"https://api.binance.com/api/v3/ping",filter(o){return f(o)&&!!o.country&&!co.has(o.country.cca2)}},fo=new Set(["HK","MO"]),G={name:"AI",type:"url-test",emoji:"\uD83E\uDD16",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/AI.png",filter(o){return f(o)&&!!o.country&&!fo.has(o.country.cca2)}};var _={name:"Stream",type:"url-test",emoji:"\uD83D\uDCFA",icon:"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/YouTube.png",filter(o){return f(o)&&o.multiplier<2}};import ho from"world-countries";import A from"@twemoji/api";function j(o,e){let{cca2:r,flag:t}=o,i=A.convert.toCodePoint(t),p="".concat(A.base,A.size,"/",i,A.ext);return{name:o.name.common,type:e?.type??"url-test",emoji:t,icon:p,filter(l){return f(l)&&l.country.cca2===r}}}function H(){return[w,E,G,K,_,...ho.map((o)=>j(o)),j(m)]}class u{async process(o){return await Promise.all(o.map(async(e)=>await this.processOne(e)))}}import L from"consola";import uo from"world-countries";class I extends u{geoip=new O;async processOne(o){if(o.emby||o.info)return o.country=m,o;if(o.country.cca2===m.cca2)o=this.inferFromName(o);if(o.country.cca2===m.cca2)o=await this.inferFromServer(o);if(o.country.cca2===m.cca2)L.fail(`${o.prettyName} (${k(o.country)})`);return o}inferFromName(o){let e=o.name;for(let r of uo){if(r.cca2==="CN")continue;for(let t of yo(r)){if(!t)continue;if(t.test(e))return L.success(`${o.prettyName} ~ ${t} (${k(r)})`),o.country=r,o}}return o}async inferFromServer(o){let e=await this.geoip.lookup(o.server);if(e.location?.country_code)o.country=v(e.location.country_code)||m;else o.country=m;if(o.country.cca2!==m.cca2)L.success(`${o.prettyName} -> ${e.ip} (${k(o.country)})`);return o}}function*yo(o){let e=new Set(["GB"]);function r(i){if(!i)return;if(e.has(i))return;return new RegExp(`\\b${i}\\b`)}function t(i){if(!i)return;if(e.has(i))return;return new RegExp(i,"iu")}for(let i of["en","zh"])for(let p of["narrow","short","long"]){let l=new Intl.DisplayNames(i,{style:p,type:"region"});if(p==="narrow"||p==="short")yield r(l.of(o.cca2));else if(p==="long")yield t(l.of(o.cca2))}yield t(o.name.common),yield t(o.name.official);for(let i in o.name.native)yield t(o.name.native[i].common),yield t(o.name.native[i].official);yield r(o.cca2),yield r(o.cca3),yield r(o.cioc);for(let i of o.capital)yield t(i);yield t(o.flag)}function k(o){return`${o.flag} ${o.name.common} (${o.cca2})`}import Oo from"consola";class Z extends u{pattern=/Expire|Traffic|\u5269\u4F59|\u5957\u9910\u5230\u671F/iu;async processOne(o){if(o.info=this.pattern.test(o.name),o.info)Oo.success(`${o.prettyName} ~ ${this.pattern}`);return o}}import Mo from"fs/promises";import xo from"yaml";import{z as n}from"zod";var go=n.object({name:n.string(),free:n.boolean().default(!1),jms:n.object({url:n.url()}).optional(),mihomo:n.object({url:n.url()}).optional()}),Po=n.object({providers:n.array(go)});class S{providers;static async load(o){let e=await Mo.readFile(o,"utf8"),r=xo.parse(e),t=Po.parse(r);return new S(t.providers)}constructor(o){this.providers=o.map((e)=>new z(e))}async fetchMihomoOutbounds(){return(await Promise.all(this.providers.map(async(e)=>await e.fetchOutboundsMihomo()))).flat()}}var D=bo({docs:{brief:""},async func(o){Ro.level=6;let e=H(),r=await S.load(o.profile),t=await h.load(o.template),i=await r.fetchMihomoOutbounds(),p=[new I,new Z];for(let Q of p)i=await Q.process(i);let l=t.render(i,e);await zo.writeFile(o.output,l)},parameters:{flags:{output:{kind:"parsed",brief:"",parse:String,default:"mihomo.yaml"},profile:{kind:"parsed",brief:"",parse:String,default:"profile.yaml"},template:{kind:"parsed",brief:"",parse:String,default:"templates/mihomo/default.yaml"}}}});var X=Io({routes:{mihomo:D},docs:{brief:T}}),U=Ao(X,{name:"sub-store",scanner:{caseStyle:"allow-kebab-for-camel"},versionInfo:{currentVersion:B}});import Zo from"fs";import So from"os";import vo from"path";var N={process,os:So,fs:Zo,path:vo};Co(U,process.argv.slice(2),N);
4
-
5
- //# debugId=23FEE569E939533C64756E2164756E21
6
- //# sourceMappingURL=sub-store.js.map
@@ -1,30 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["src/bin/sub-store.ts", "src/cli/app.ts", "src/cli/mihomo.ts", "src/utils/countries.ts", "src/utils/geoip/geoip.ts", "src/utils/geoip/ipapi.is.ts", "src/utils/sublink.ts", "src/core/outbound.ts", "src/core/provider.ts", "src/formats/mihomo/schema.ts", "src/formats/mihomo/outbound.ts", "src/formats/mihomo/parse.ts", "src/formats/mihomo/template.ts", "src/group/common.ts", "src/group/factory.ts", "src/group/country.ts", "src/processor/base.ts", "src/processor/country.ts", "src/processor/info.ts", "src/profile.ts", "src/cli/context.ts"],
4
- "sourcesContent": [
5
- "#!/usr/bin/env bun\nimport { run } from \"@stricli/core\";\nimport { app, context } from \"../cli\";\n\nrun(app, process.argv.slice(2), context);\n",
6
- "import type { Application, RouteMap } from \"@stricli/core\";\nimport { buildApplication, buildRouteMap } from \"@stricli/core\";\nimport { description, version } from \"../../package.json\";\nimport type { Context } from \"./context\";\nimport { mihomo } from \"./mihomo\";\n\nexport const routes: RouteMap<Context> = buildRouteMap({\n routes: { mihomo },\n docs: { brief: description },\n});\n\nexport const app: Application<Context> = buildApplication(routes, {\n name: \"sub-store\",\n scanner: { caseStyle: \"allow-kebab-for-camel\" },\n versionInfo: { currentVersion: version },\n});\n",
7
- "import fs from \"node:fs/promises\";\nimport { buildCommand, type Command } from \"@stricli/core\";\nimport consola from \"consola\";\nimport type { MihomoOutbound } from \"../formats\";\nimport { MihomoTemplate } from \"../formats\";\nimport type { Group } from \"../group\";\nimport { defaultGroups } from \"../group\";\nimport type { Processor } from \"../processor\";\nimport { ProcessorCountry, ProcessorInfo } from \"../processor\";\nimport { Profile } from \"../profile\";\nimport type { Context } from \"./context\";\n\ntype Flags = {\n output: string;\n profile: string;\n template: string;\n};\n\nexport const mihomo: Command<Context> = buildCommand({\n docs: { brief: \"\" },\n async func(this: Context, flags: Flags): Promise<void> {\n consola.level = 6;\n const groups: Group[] = defaultGroups();\n const profile = await Profile.load(flags.profile);\n const template: MihomoTemplate = await MihomoTemplate.load(flags.template);\n let outbounds: MihomoOutbound[] = await profile.fetchMihomoOutbounds();\n const processors: Processor[] = [\n new ProcessorCountry(),\n new ProcessorInfo(),\n ];\n for (const processor of processors)\n outbounds = await processor.process(outbounds);\n const config: string = template.render(outbounds, groups);\n await fs.writeFile(flags.output, config);\n },\n parameters: {\n flags: {\n output: {\n kind: \"parsed\",\n brief: \"\",\n parse: String,\n default: \"mihomo.yaml\",\n },\n profile: {\n kind: \"parsed\",\n brief: \"\",\n parse: String,\n default: \"profile.yaml\",\n },\n template: {\n kind: \"parsed\",\n brief: \"\",\n parse: String,\n default: \"templates/mihomo/default.yaml\",\n },\n },\n },\n});\n",
8
- "import type { Country } from \"world-countries\";\nimport countries from \"world-countries\";\n\nexport const COUNTRY_UNKNOWN = {\n name: { common: \"Unknown\" },\n cca2: \"UN\",\n flag: \"πŸ‡ΊπŸ‡³\",\n} as Country;\n\nexport function lookupCountry(cca2: string): Country | undefined {\n return countries.find((country: Country): boolean => country.cca2 === cca2);\n}\n",
9
- "import type { LookupAddress } from \"node:dns\";\nimport dns from \"node:dns/promises\";\nimport DataLoader from \"dataloader\";\nimport z from \"zod\";\nimport { type GeoIpApiResponse, IpapiIs } from \"./ipapi.is\";\n\nexport class GeoIP {\n private api: IpapiIs;\n private loader: DataLoader<string, GeoIpApiResponse>;\n\n public constructor() {\n this.api = new IpapiIs();\n this.loader = new DataLoader(\n async (servers: readonly string[]): Promise<GeoIpApiResponse[]> =>\n await this.batchLoadFn(servers),\n );\n }\n\n public async lookup(server: string): Promise<GeoIpApiResponse> {\n return await this.loader.load(server);\n }\n\n protected async batchLoadFn(\n servers: readonly string[],\n ): Promise<GeoIpApiResponse[]> {\n return await Promise.all(\n servers.map(\n async (server: string): Promise<GeoIpApiResponse> =>\n await this.loadFn(server),\n ),\n );\n }\n\n protected async loadFn(server: string): Promise<GeoIpApiResponse> {\n let ips: string[] = [];\n if (isIpAddr(server)) {\n ips = [server];\n } else {\n const addresses: LookupAddress[] = await dns.lookup(server, {\n all: true,\n });\n ips = addresses.map((addr: LookupAddress): string => addr.address);\n }\n const responses: GeoIpApiResponse[] = await Promise.all(\n ips.map(\n async (ip: string): Promise<GeoIpApiResponse> =>\n await this.api.lookup(ip),\n ),\n );\n for (const response of responses) {\n if (!response.location?.country_code) continue;\n return response;\n }\n return { ip: ips[0] || \"\", location: { country_code: \"UN\" } };\n }\n}\n\nfunction isIpAddr(data: string): boolean {\n return z.ipv4().safeParse(data).success || z.ipv6().safeParse(data).success;\n}\n",
10
- "import DataLoader from \"dataloader\";\nimport ky from \"ky\";\nimport * as R from \"remeda\";\nimport z from \"zod\";\n\nconst RESPONSE_SCHEMA: z.ZodObject<{\n ip: z.ZodUnion<readonly [z.ZodIPv4, z.ZodIPv6]>;\n location: z.ZodOptional<z.ZodObject<{ country_code: z.ZodString }>>;\n}> = z.looseObject({\n ip: z.union([z.ipv4(), z.ipv6()]),\n location: z.looseObject({ country_code: z.string().length(2) }).optional(),\n});\nexport type GeoIpApiResponse = z.infer<typeof RESPONSE_SCHEMA>;\n\nconst BULK_RESPONSE_SCHEMA: z.ZodRecord<z.ZodString, typeof RESPONSE_SCHEMA> =\n z.record(z.string(), RESPONSE_SCHEMA);\ntype BulkApiResponse = z.infer<typeof BULK_RESPONSE_SCHEMA>;\n\nexport class IpapiIs {\n public readonly endpoints: string = \"https://api.ipapi.is/\";\n private loader: DataLoader<string, GeoIpApiResponse>;\n private readonly key?: string;\n\n public constructor() {\n this.loader = new DataLoader(\n async (ips: readonly string[]): Promise<GeoIpApiResponse[]> =>\n await this.batchLoadFn(ips),\n { maxBatchSize: 100 },\n );\n this.key = process.env.IPAPI_IS_KEY;\n }\n\n public async lookup(ip: string): Promise<GeoIpApiResponse> {\n return await this.loader.load(ip);\n }\n\n protected async batchLoadFn(\n ips: readonly string[],\n ): Promise<GeoIpApiResponse[]> {\n let data: any = await ky\n .post(this.endpoints, { json: { ips, key: this.key } })\n .json();\n data = R.omit(data, [\"total_elapsed_ms\"]);\n const response: BulkApiResponse = BULK_RESPONSE_SCHEMA.parse(data);\n return ips.map((ip: string): GeoIpApiResponse => response[ip]!);\n }\n}\n",
11
- "const SUBLINK_URL: string =\n process.env.SUBLINK_URL || \"https://sublink.liblaf.me/clash\";\n\nexport function sublinkClashUrl(url: string): URL {\n const req = new URL(SUBLINK_URL);\n req.searchParams.set(\"config\", url);\n req.searchParams.set(\"ua\", \"clash.meta\");\n return req;\n}\n",
12
- "import type { Country } from \"world-countries\";\nimport { COUNTRY_UNKNOWN } from \"../utils\";\nimport type { Provider } from \"./provider\";\n\nexport abstract class Outbound {\n public readonly provider: Provider;\n\n // metadata\n public country: Country = COUNTRY_UNKNOWN;\n public info: boolean = false;\n [key: string]: any;\n\n constructor(provider: Provider) {\n this.provider = provider;\n }\n\n abstract get name(): string;\n\n abstract get type(): string;\n\n abstract get server(): string;\n\n get prettyName(): string {\n let name: string = this.name;\n if (this.provider.name === \"JMS\") {\n const match: RegExpMatchArray | null =\n this.name.match(/@(?<name>[\\w-]+)/);\n if (match) name = match.groups?.name ?? this.name;\n }\n if (name.startsWith(\"【\")) return `[${this.provider.name}]${name}`;\n return `[${this.provider.name}] ${name}`;\n }\n}\n",
13
- "import consola from \"consola\";\nimport ky from \"ky\";\nimport { z } from \"zod\";\nimport type { Mihomo, MihomoNode } from \"../formats\";\nimport { MihomoOutbound, mihomoParse } from \"../formats\";\nimport { sublinkClashUrl } from \"../utils\";\n\nexport const PROVIDER_SCHEMA: z.ZodObject<{\n name: z.ZodString;\n free: z.ZodDefault<z.ZodBoolean>;\n jms: z.ZodOptional<z.ZodObject<{ url: z.ZodURL }>>;\n mihomo: z.ZodOptional<z.ZodObject<{ url: z.ZodURL }>>;\n}> = z.object({\n name: z.string(),\n free: z.boolean().default(false),\n jms: z.object({ url: z.url() }).optional(),\n mihomo: z.object({ url: z.url() }).optional(),\n});\nexport type ProviderOptions = z.input<typeof PROVIDER_SCHEMA>;\n\nexport class Provider {\n public readonly name: string;\n public readonly jms?: { url: string };\n public readonly mihomo?: { url: string };\n\n public constructor(options: ProviderOptions) {\n const { name, jms, mihomo } = PROVIDER_SCHEMA.parse(options);\n this.name = name;\n this.jms = jms;\n this.mihomo = mihomo;\n }\n\n public async fetchOutboundsMihomo(): Promise<MihomoOutbound[]> {\n const url: string | URL | undefined = this.getMihomoURL();\n if (!url) return [];\n const headers = new Headers({ \"User-Agent\": \"clash.meta\" });\n const text: string = await ky.get(url, { headers }).text();\n const config: Mihomo = mihomoParse(text);\n return config.proxies!.map(\n (proxy: MihomoNode): MihomoOutbound => new MihomoOutbound(proxy, this),\n );\n }\n\n protected warnFormat(format: string): void {\n consola.warn(`Provider '${this.name}' does not support '${format}'`);\n }\n\n protected getMihomoURL(): string | URL | undefined {\n if (this.mihomo) return this.mihomo.url;\n if (this.jms) return sublinkClashUrl(this.jms.url);\n this.warnFormat(\"mihomo\");\n return undefined;\n }\n}\n",
14
- "import z from \"zod\";\n\nexport const MIHOMO_NODE_SCHEMA: z.ZodObject<{\n name: z.ZodString;\n type: z.ZodString;\n server: z.ZodString;\n}> = z.looseObject({\n name: z.string(),\n type: z.string(),\n server: z.string(),\n});\nexport type MihomoNode = z.infer<typeof MIHOMO_NODE_SCHEMA>;\nexport type MihomoNodeOptions = z.input<typeof MIHOMO_NODE_SCHEMA>;\n\nexport const MIHOMO_PROXY_GROUP_SCHEMA: z.ZodObject<{\n name: z.ZodString;\n type: z.ZodEnum<{\n select: \"select\";\n \"url-test\": \"url-test\";\n }>;\n proxies: z.ZodArray<z.ZodString>;\n url: z.ZodDefault<z.ZodURL>;\n lazy: z.ZodDefault<z.ZodBoolean>;\n \"expected-status\": z.ZodDefault<z.ZodInt>;\n icon: z.ZodOptional<z.ZodURL>;\n}> = z.looseObject({\n name: z.string(),\n type: z.enum([\"select\", \"url-test\"]),\n proxies: z.array(z.string()),\n url: z.url().default(\"https://cp.cloudflare.com\"),\n lazy: z.boolean().default(true),\n \"expected-status\": z.int().min(100).max(599).default(204),\n icon: z.url().optional(),\n});\nexport type MihomoProxyGroup = z.infer<typeof MIHOMO_PROXY_GROUP_SCHEMA>;\nexport type MihomoProxyGroupOptions = z.input<typeof MIHOMO_PROXY_GROUP_SCHEMA>;\n\nexport const MIHOMO_SCHEMA: z.ZodObject<{\n proxies: z.ZodOptional<\n z.ZodArray<\n z.ZodObject<{\n name: z.ZodString;\n type: z.ZodString;\n server: z.ZodString;\n }>\n >\n >;\n \"proxy-groups\": z.ZodOptional<\n z.ZodArray<\n z.ZodObject<{\n name: z.ZodString;\n type: z.ZodEnum<{\n select: \"select\";\n \"url-test\": \"url-test\";\n }>;\n proxies: z.ZodArray<z.ZodString>;\n url: z.ZodDefault<z.ZodURL>;\n lazy: z.ZodDefault<z.ZodBoolean>;\n \"expected-status\": z.ZodDefault<z.ZodInt>;\n icon: z.ZodOptional<z.ZodURL>;\n }>\n >\n >;\n rules: z.ZodOptional<z.ZodArray<z.ZodString>>;\n}> = z.looseObject({\n proxies: z.array(MIHOMO_NODE_SCHEMA).optional(),\n \"proxy-groups\": z.array(MIHOMO_PROXY_GROUP_SCHEMA).optional(),\n rules: z.array(z.string()).optional(),\n});\nexport type Mihomo = z.infer<typeof MIHOMO_SCHEMA>;\n",
15
- "import type { Provider } from \"../../core\";\nimport { Outbound } from \"../../core\";\nimport type { MihomoNode, MihomoNodeOptions } from \"./schema\";\nimport { MIHOMO_NODE_SCHEMA } from \"./schema\";\n\nexport class MihomoOutbound extends Outbound {\n private readonly raw: MihomoNode;\n\n public constructor(raw: MihomoNodeOptions, provider: Provider) {\n super(provider);\n this.raw = MIHOMO_NODE_SCHEMA.parse(raw);\n }\n\n public override get name(): string {\n return this.raw.name;\n }\n\n public override get type(): string {\n return this.raw.type;\n }\n\n public override get server(): string {\n return this.raw.server;\n }\n\n public get mihomo(): MihomoNode {\n return { ...this.raw, name: this.prettyName };\n }\n}\n",
16
- "import YAML from \"yaml\";\nimport { MIHOMO_SCHEMA, type Mihomo } from \"./schema\";\n\nexport function mihomoParse(text: string): Mihomo {\n const data: any = YAML.parse(text, { merge: true });\n return MIHOMO_SCHEMA.parse(data);\n}\n",
17
- "import fs from \"node:fs/promises\";\nimport * as R from \"remeda\";\nimport YAML from \"yaml\";\nimport type { Group } from \"../../group\";\nimport type { MihomoOutbound } from \"./outbound\";\nimport { mihomoParse } from \"./parse\";\nimport type {\n Mihomo,\n MihomoNode,\n MihomoProxyGroup,\n MihomoProxyGroupOptions,\n} from \"./schema\";\nimport { MIHOMO_PROXY_GROUP_SCHEMA } from \"./schema\";\n\nexport class MihomoTemplate {\n template: Mihomo;\n\n static async load(path: string): Promise<MihomoTemplate> {\n const template: string = await fs.readFile(path, \"utf8\");\n return new MihomoTemplate(template);\n }\n\n public constructor(template: string) {\n this.template = mihomoParse(template);\n }\n\n public render(outbounds: readonly MihomoOutbound[], groups: Group[]): string {\n let config: Mihomo = R.clone(this.template);\n config.proxies = outbounds.map((o: MihomoOutbound): MihomoNode => o.mihomo);\n const groupProxy: MihomoProxyGroup = this.renderGroupProxy();\n config[\"proxy-groups\"] = [groupProxy];\n for (const group of groups) {\n const rendered: MihomoProxyGroup | undefined = this.renderGroup(\n outbounds,\n group,\n );\n if (!rendered) continue;\n config[\"proxy-groups\"].push(rendered);\n groupProxy.proxies.push(rendered.name);\n }\n config = this.sanitize(config);\n return YAML.stringify(config, {\n aliasDuplicateObjects: false,\n sortMapEntries: true,\n });\n }\n\n protected sanitize(config: Mihomo): Mihomo {\n config = R.omitBy(config, (_value, key: string): boolean =>\n key.startsWith(\"__\"),\n );\n const outboundsNames: Set<string> = new Set([\n \"DIRECT\",\n \"REJECT\",\n \"REJECT-DROP\",\n \"PASS\",\n ]);\n for (const outbound of config.proxies || [])\n outboundsNames.add(outbound.name);\n for (const group of config[\"proxy-groups\"] || [])\n outboundsNames.add(group.name);\n if (config.rules) {\n config.rules = config.rules.filter((rule: string): boolean => {\n const parts: string[] = rule\n .split(\",\")\n .filter((p: string): boolean => p.trim() !== \"no-resolve\");\n const outbound: string = parts[parts.length - 1]!.trim();\n return outboundsNames.has(outbound);\n });\n }\n return config;\n }\n\n protected renderGroup(\n outbounds: readonly MihomoOutbound[],\n group: Group,\n ): MihomoProxyGroup | undefined {\n const filtered: MihomoOutbound[] = outbounds.filter(group.filter);\n if (filtered.length === 0) return undefined;\n const filteredNames: string[] = filtered.map(\n (o: MihomoOutbound): string => o.prettyName,\n );\n const options: MihomoProxyGroupOptions = {\n name: group.name,\n type: group.type,\n proxies: filteredNames,\n url: group.url,\n icon: group.icon,\n };\n return MIHOMO_PROXY_GROUP_SCHEMA.parse(options);\n }\n\n protected renderGroupProxy(): MihomoProxyGroup {\n const options: MihomoProxyGroupOptions = {\n name: \"PROXY\",\n type: \"select\",\n proxies: [],\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Proxy.png\",\n };\n return MIHOMO_PROXY_GROUP_SCHEMA.parse(options);\n }\n}\n",
18
- "import type { Outbound } from \"../core\";\nimport type { Group } from \"./base\";\n\nexport function good(outbound: Outbound): boolean {\n // connection quality of Hysteria2 is poor\n return !outbound.emby && !outbound.info && outbound.type !== \"hysteria2\";\n}\n\nexport const PROXY: Group = {\n name: \"PROXY\",\n type: \"select\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Proxy.png\",\n filter(_outbound: Outbound): boolean {\n return false;\n },\n};\n\nexport const INFO: Group = {\n name: \"Info\",\n type: \"url-test\",\n emoji: \"ℹ️\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Airport.png\",\n filter(outbound: Outbound): boolean {\n return outbound.info;\n },\n};\n\nexport const AUTO: Group = {\n name: \"Auto\",\n type: \"url-test\",\n emoji: \"πŸš€\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Auto.png\",\n filter(outbound: Outbound): boolean {\n return good(outbound) && outbound.multiplier <= 2.0;\n },\n};\n\nconst BINANCE_EXCLUDE_REGIONS = new Set([\n \"CA\",\n \"CN\",\n \"CU\",\n \"HK\",\n \"IR\",\n \"KP\",\n \"MO\",\n \"NL\",\n \"TW\",\n \"US\",\n]);\nexport const BINANCE: Group = {\n name: \"Binance\",\n type: \"url-test\",\n emoji: \"πŸͺ™\",\n // TODO: add icon\n url: \"https://api.binance.com/api/v3/ping\",\n filter(outbound: Outbound): boolean {\n return (\n good(outbound) &&\n !!outbound.country &&\n !BINANCE_EXCLUDE_REGIONS.has(outbound.country.cca2)\n );\n },\n};\n\nconst AI_EXCLUDE_REGIONS = new Set([\"HK\", \"MO\"]);\nexport const AI: Group = {\n name: \"AI\",\n type: \"url-test\",\n emoji: \"πŸ€–\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/AI.png\",\n filter(outbound: Outbound): boolean {\n return (\n good(outbound) &&\n !!outbound.country &&\n !AI_EXCLUDE_REGIONS.has(outbound.country.cca2)\n );\n },\n};\n\nexport const DOWNLOAD: Group = {\n name: \"Download\",\n type: \"url-test\",\n emoji: \"πŸ“₯\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/Download.png\",\n filter(outbound: Outbound): boolean {\n return good(outbound) && outbound.multiplier <= 1.0;\n },\n};\n\nexport const STREAM: Group = {\n name: \"Stream\",\n type: \"url-test\",\n emoji: \"πŸ“Ί\",\n icon: \"https://cdn.jsdelivr.net/gh/Koolson/Qure/IconSet/Color/YouTube.png\",\n filter(outbound: Outbound): boolean {\n return good(outbound) && outbound.multiplier < 2.0;\n },\n};\n",
19
- "import countries, { type Country } from \"world-countries\";\nimport { COUNTRY_UNKNOWN } from \"../utils\";\nimport type { Group } from \"./base\";\nimport { AI, AUTO, BINANCE, INFO, STREAM } from \"./common\";\nimport { newCountryGroup } from \"./country\";\n\nexport function defaultGroups(): Group[] {\n return [\n AUTO,\n INFO,\n AI,\n BINANCE,\n // CITRUSLAB_EMBY,\n // DOWNLOAD,\n STREAM,\n ...countries.map((c: Country): Group => newCountryGroup(c)),\n newCountryGroup(COUNTRY_UNKNOWN),\n ];\n}\n",
20
- "import twemoji from \"@twemoji/api\";\nimport type { Country } from \"world-countries\";\nimport type { Outbound } from \"../core\";\nimport type { Group } from \"./base\";\nimport { good } from \"./common\";\n\nexport function newCountryGroup(\n country: Country,\n options?: { type?: \"select\" | \"url-test\" },\n): Group {\n const { cca2, flag } = country;\n const codePoint: string = twemoji.convert.toCodePoint(flag);\n const icon: string = \"\".concat(\n twemoji.base,\n twemoji.size,\n \"/\",\n codePoint,\n twemoji.ext,\n );\n return {\n name: country.name.common,\n type: options?.type ?? \"url-test\",\n emoji: flag,\n icon,\n filter(outbound: Outbound): boolean {\n return good(outbound) && outbound.country.cca2 === cca2;\n },\n };\n}\n",
21
- "import type { Outbound } from \"../core\";\n\nexport abstract class Processor {\n async process<O extends Outbound>(outbounds: O[]): Promise<O[]> {\n return await Promise.all(\n outbounds.map(async (o: O): Promise<O> => await this.processOne(o)),\n );\n }\n\n abstract processOne<T extends Outbound>(outbound: T): Promise<T>;\n}\n",
22
- "import consola from \"consola\";\nimport countries, { type Country } from \"world-countries\";\nimport type { Outbound } from \"../core\";\nimport type { GeoIpApiResponse } from \"../utils\";\nimport { COUNTRY_UNKNOWN, GeoIP, lookupCountry } from \"../utils\";\nimport { Processor } from \"./base\";\n\nexport class ProcessorCountry extends Processor {\n private readonly geoip: GeoIP = new GeoIP();\n\n public override async processOne<O extends Outbound>(\n outbound: O,\n ): Promise<O> {\n if (outbound.emby || outbound.info) {\n outbound.country = COUNTRY_UNKNOWN;\n return outbound;\n }\n if (outbound.country.cca2 === COUNTRY_UNKNOWN.cca2)\n outbound = this.inferFromName(outbound);\n if (outbound.country.cca2 === COUNTRY_UNKNOWN.cca2)\n outbound = await this.inferFromServer(outbound);\n if (outbound.country.cca2 === COUNTRY_UNKNOWN.cca2) {\n consola.fail(\n `${outbound.prettyName} (${prettyCountry(outbound.country)})`,\n );\n }\n return outbound;\n }\n\n protected inferFromName<T extends Outbound>(outbound: T): T {\n const name: string = outbound.name;\n for (const country of countries) {\n if (country.cca2 === \"CN\") continue;\n for (const pattern of patterns(country)) {\n if (!pattern) continue;\n if (pattern.test(name)) {\n consola.success(\n `${outbound.prettyName} ~ ${pattern} (${prettyCountry(country)})`,\n );\n outbound.country = country;\n return outbound;\n }\n }\n }\n return outbound;\n }\n\n protected async inferFromServer<T extends Outbound>(outbound: T): Promise<T> {\n const response: GeoIpApiResponse = await this.geoip.lookup(outbound.server);\n if (response.location?.country_code) {\n outbound.country =\n lookupCountry(response.location.country_code) || COUNTRY_UNKNOWN;\n } else {\n outbound.country = COUNTRY_UNKNOWN;\n }\n if (outbound.country.cca2 !== COUNTRY_UNKNOWN.cca2) {\n consola.success(\n `${outbound.prettyName} -> ${response.ip} (${prettyCountry(outbound.country)})`,\n );\n }\n return outbound;\n }\n}\n\nfunction* patterns(country: Country): Generator<RegExp | undefined> {\n const EXCLUDE_PATTERNS = new Set([\n \"GB\", // gigabyte\n ]);\n\n function short(pattern?: string): RegExp | undefined {\n if (!pattern) return undefined;\n if (EXCLUDE_PATTERNS.has(pattern)) return undefined;\n return new RegExp(`\\\\b${pattern}\\\\b`);\n }\n\n function long(pattern?: string): RegExp | undefined {\n if (!pattern) return undefined;\n if (EXCLUDE_PATTERNS.has(pattern)) return undefined;\n return new RegExp(pattern, \"iu\");\n }\n\n for (const locale of [\"en\", \"zh\"]) {\n for (const style of [\"narrow\", \"short\", \"long\"]) {\n const display = new Intl.DisplayNames(locale, {\n style: style as Intl.RelativeTimeFormatStyle,\n type: \"region\",\n });\n if (style === \"narrow\" || style === \"short\") {\n yield short(display.of(country.cca2));\n } else if (style === \"long\") {\n yield long(display.of(country.cca2));\n }\n }\n }\n yield long(country.name.common);\n yield long(country.name.official);\n for (const lang in country.name.native) {\n yield long(country.name.native[lang]!.common);\n yield long(country.name.native[lang]!.official);\n }\n yield short(country.cca2);\n // yield long(country.ccn3);\n yield short(country.cca3);\n yield short(country.cioc);\n for (const capital of country.capital) yield long(capital);\n // for (const alt of country.altSpellings) yield long(alt);\n yield long(country.flag);\n}\n\nfunction prettyCountry(country: Country): string {\n return `${country.flag} ${country.name.common} (${country.cca2})`;\n}\n",
23
- "import consola from \"consola\";\nimport type { Outbound } from \"../core\";\nimport { Processor } from \"./base\";\n\nexport class ProcessorInfo extends Processor {\n public readonly pattern: RegExp = /Expire|Traffic|剩余|ε₯—ι€εˆ°ζœŸ/iu;\n\n public override async processOne<O extends Outbound>(\n outbound: O,\n ): Promise<O> {\n outbound.info = this.pattern.test(outbound.name);\n if (outbound.info)\n consola.success(`${outbound.prettyName} ~ ${this.pattern}`);\n return outbound;\n }\n}\n",
24
- "import fs from \"node:fs/promises\";\nimport YAML from \"yaml\";\nimport { z } from \"zod\";\nimport { Provider } from \"./core\";\nimport type { MihomoOutbound } from \"./formats\";\n\nexport const PROVIDER_SCHEMA: z.ZodObject<{\n name: z.ZodString;\n free: z.ZodDefault<z.ZodBoolean>;\n jms: z.ZodOptional<z.ZodObject<{ url: z.ZodURL }>>;\n mihomo: z.ZodOptional<z.ZodObject<{ url: z.ZodURL }>>;\n}> = z.object({\n name: z.string(),\n free: z.boolean().default(false),\n jms: z.object({ url: z.url() }).optional(),\n mihomo: z.object({ url: z.url() }).optional(),\n});\nexport type ProviderOptions = z.input<typeof PROVIDER_SCHEMA>;\n\nexport const PROFILE_SCHEMA: z.ZodObject<{\n providers: z.ZodArray<typeof PROVIDER_SCHEMA>;\n}> = z.object({\n providers: z.array(PROVIDER_SCHEMA),\n});\nexport type ProfileModel = z.infer<typeof PROFILE_SCHEMA>;\n\nexport class Profile {\n public providers: Provider[];\n\n static async load(file: string): Promise<Profile> {\n const data: string = await fs.readFile(file, \"utf8\");\n const parsed: any = YAML.parse(data);\n const profile: ProfileModel = PROFILE_SCHEMA.parse(parsed);\n return new Profile(profile.providers);\n }\n\n constructor(providers: readonly ProviderOptions[]) {\n this.providers = providers.map(\n (options: ProviderOptions): Provider => new Provider(options),\n );\n }\n\n async fetchMihomoOutbounds(): Promise<MihomoOutbound[]> {\n const outbounds: MihomoOutbound[][] = await Promise.all(\n this.providers.map(\n async (provider: Provider): Promise<MihomoOutbound[]> =>\n await provider.fetchOutboundsMihomo(),\n ),\n );\n return outbounds.flat();\n }\n}\n",
25
- "import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { StricliAutoCompleteContext } from \"@stricli/auto-complete\";\nimport type { CommandContext } from \"@stricli/core\";\n\nexport interface Context extends CommandContext, StricliAutoCompleteContext {\n readonly process: NodeJS.Process;\n}\n\nexport const context: Context = { process, os, fs, path };\n"
26
- ],
27
- "mappings": "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",
28
- "debugId": "23FEE569E939533C64756E2164756E21",
29
- "names": []
30
- }
package/dist/index.js DELETED
@@ -1,5 +0,0 @@
1
- // @bun
2
- var c=void 0;export{c as default};
3
-
4
- //# debugId=739F3CA43E7B60FB64756E2164756E21
5
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [
5
- ],
6
- "mappings": "",
7
- "debugId": "739F3CA43E7B60FB64756E2164756E21",
8
- "names": []
9
- }
@@ -1 +0,0 @@
1
- {"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"providers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"free":{"default":false,"type":"boolean"},"jms":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]},"mihomo":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["name"]}}},"required":["providers"]}