build-sspanel-appprofile.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import { getAppleCdnDomainsPromise } from './build-apple-cdn';
  2. import { getDomesticDomainsRulesetPromise } from './build-domestic-ruleset';
  3. import { surgeRulesetToClashClassicalTextRuleset } from './lib/clash';
  4. import { readFileByLine } from './lib/fetch-text-by-line';
  5. import { processLineFromReadline } from './lib/process-line';
  6. import { task } from './trace';
  7. import path from 'path';
  8. import { ALL as AllStreamServices } from '../Source/stream';
  9. import { getChnCidrPromise } from './build-chn-cidr';
  10. import { getTelegramCIDRPromise } from './build-telegram-cidr';
  11. import { compareAndWriteFile } from './lib/create-file';
  12. import { getMicrosoftCdnRulesetPromise } from './build-microsoft-cdn';
  13. const POLICY_GROUPS: Array<[name: string, insertProxy: boolean, insertDirect: boolean]> = [
  14. ['Default Proxy', true, false],
  15. ['Global', true, true],
  16. ['Microsoft & Apple', true, true],
  17. ['Stream', true, false],
  18. ['Domestic', false, true],
  19. ['Final Match', true, true]
  20. ];
  21. const removeNoResolved = (line: string) => line.replace(',no-resolve', '');
  22. /**
  23. * This only generates a simplified version, for under-used users only.
  24. */
  25. export const buildSSPanelUIMAppProfile = task(import.meta.path, async (span) => {
  26. const [
  27. domesticDomains,
  28. appleCdnDomains,
  29. microsoftCdnDomains,
  30. appleCnDomains,
  31. neteaseMusicDomains,
  32. microsoftDomains,
  33. appleDomains,
  34. streamDomains,
  35. globalDomains,
  36. globalPlusDomains,
  37. telegramDomains,
  38. lanDomains,
  39. domesticCidrs,
  40. streamCidrs,
  41. { results: rawTelegramCidrs },
  42. lanCidrs
  43. ] = await Promise.all([
  44. // domestic - domains
  45. getDomesticDomainsRulesetPromise().then(surgeRulesetToClashClassicalTextRuleset),
  46. getAppleCdnDomainsPromise().then(domains => domains.map(domain => `DOMAIN-SUFFIX,${domain}`)),
  47. getMicrosoftCdnRulesetPromise().then(surgeRulesetToClashClassicalTextRuleset),
  48. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/apple_cn.conf'))),
  49. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/neteasemusic.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
  50. // microsoft & apple - domains
  51. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/microsoft.conf'))),
  52. (processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/apple_services.conf')))).then(surgeRulesetToClashClassicalTextRuleset),
  53. // stream - domains
  54. surgeRulesetToClashClassicalTextRuleset(AllStreamServices.flatMap((i) => i.rules)),
  55. // global - domains
  56. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/global.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
  57. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/global_plus.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
  58. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/telegram.conf'))).then(surgeRulesetToClashClassicalTextRuleset),
  59. // lan - domains
  60. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/lan.conf'))),
  61. // domestic - ip cidr
  62. getChnCidrPromise().then(cidrs => cidrs.map(cidr => `IP-CIDR,${cidr}`)),
  63. AllStreamServices.flatMap((i) => (
  64. i.ip
  65. ? [
  66. ...i.ip.v4.map((ip) => `IP-CIDR,${ip}`),
  67. ...i.ip.v6.map((ip) => `IP-CIDR6,${ip}`)
  68. ]
  69. : []
  70. )),
  71. // global - ip cidr
  72. getTelegramCIDRPromise(),
  73. // lan - ip cidr
  74. processLineFromReadline(readFileByLine(path.resolve(import.meta.dir, '../Source/ip/lan.conf')))
  75. ] as const);
  76. const telegramCidrs = rawTelegramCidrs.map(removeNoResolved);
  77. const output = generateAppProfile(
  78. [
  79. ...domesticDomains,
  80. ...appleCdnDomains,
  81. ...microsoftCdnDomains,
  82. ...appleCnDomains,
  83. ...neteaseMusicDomains
  84. ],
  85. [
  86. ...microsoftDomains,
  87. ...appleDomains
  88. ],
  89. streamDomains,
  90. [
  91. ...globalDomains,
  92. ...globalPlusDomains,
  93. ...telegramDomains
  94. ],
  95. lanDomains,
  96. domesticCidrs,
  97. streamCidrs,
  98. [
  99. ...telegramCidrs
  100. ],
  101. lanCidrs
  102. );
  103. await compareAndWriteFile(
  104. span,
  105. output,
  106. path.resolve(import.meta.dir, '../List/internal/appprofile.php')
  107. );
  108. });
  109. if (import.meta.main) {
  110. buildSSPanelUIMAppProfile();
  111. }
  112. const isTruthy = <T>(i: T | 0 | '' | false | null | undefined): i is T => !!i;
  113. function generateAppProfile(
  114. directDomains: string[],
  115. microsoftAppleDomains: string[],
  116. streamDomains: string[],
  117. globalDomains: string[],
  118. lanDomains: string[],
  119. directCidrs: string[],
  120. streamCidrs: string[],
  121. globalCidrs: string[],
  122. lanCidrs: string[]
  123. ) {
  124. const result: string[] = [];
  125. result.push(
  126. '<?php',
  127. '',
  128. `// # Build ${new Date().toISOString()}`,
  129. '',
  130. 'declare(strict_types=1);',
  131. '',
  132. '$_ENV[\'Clash_Config\'] = [',
  133. ' \'port\' => 7890,',
  134. ' \'socks-port\' => 7891,',
  135. ' \'allow-lan\' => false,',
  136. ' \'mode\' => \'Rule\',',
  137. ' \'ipv6\' => true,',
  138. ' \'log-level\' => \'error\',',
  139. ' \'external-controller\' => \'0.0.0.0:9090\',',
  140. ' \'tun\' => [',
  141. ' \'enable\' => true,',
  142. ' \'stack\' => \'system\',',
  143. ' \'auto-route\' => true,',
  144. ' \'auto-redir\' => true,',
  145. ' \'auto-detect-interface\' => true,',
  146. ' \'dns-hijack\' => [',
  147. ' \'8.8.8.8:53\',',
  148. ' \'any:53\',',
  149. ' \'tcp://8.8.8.8:53\',',
  150. ' \'tcp://any:53\',',
  151. ' ]',
  152. ' ]',
  153. '];',
  154. '',
  155. `$_ENV['Clash_Group_Indexes'] = [${JSON.stringify(POLICY_GROUPS.reduce<number[]>((acc, [, insertProxy], index) => {
  156. if (insertProxy) {
  157. acc.push(index);
  158. }
  159. return acc;
  160. }, [])).slice(1, -1)}];`,
  161. '$_ENV[\'Clash_Group_Config\'] = [',
  162. ' \'proxy-groups\' => [',
  163. ...POLICY_GROUPS.flatMap(([name, insertProxy, insertDirect]) => {
  164. return [
  165. ' [',
  166. ` 'name' => '${name}',`,
  167. ' \'type\' => \'select\',',
  168. ' \'proxies\' => [',
  169. insertProxy && name !== 'Default Proxy' && ' \'Default Proxy\',',
  170. insertDirect && ' \'DIRECT\',',
  171. ' ],',
  172. ' ],'
  173. ].filter(isTruthy);
  174. }),
  175. ' ],',
  176. ' \'rules\' => [',
  177. // domestic - domains
  178. ...directDomains.map(line => ` '${line},Domestic',`),
  179. // microsoft & apple - domains
  180. ...microsoftAppleDomains.map(line => ` '${line},Microsoft & Apple',`),
  181. // stream - domains
  182. ...streamDomains.map(line => ` '${line},Stream',`),
  183. // global - domains
  184. ...globalDomains.map(line => ` '${line},Global',`),
  185. // microsoft & apple - ip cidr (nope)
  186. // lan - domains
  187. ...lanDomains.map(line => ` '${line},DIRECT',`),
  188. // stream - ip cidr
  189. ...streamCidrs.map(line => ` '${line},Stream',`),
  190. // global - ip cidr
  191. ...globalCidrs.map(line => ` '${line},Global',`),
  192. // domestic - ip cidr
  193. ...directCidrs.map(line => ` '${line},Domestic',`),
  194. // lan - ip cidr
  195. ...lanCidrs.map(line => ` '${line},DIRECT',`),
  196. // match
  197. ' \'MATCH,Final Match\',',
  198. ' ],',
  199. '];'
  200. );
  201. return result;
  202. }