build-domestic-direct-lan-ruleset-dns-mapping-module.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // @ts-check
  2. import path from 'path';
  3. import { DOMESTICS } from '../Source/non_ip/domestic';
  4. import { DIRECTS, LANS } from '../Source/non_ip/direct';
  5. import { readFileIntoProcessedArray } from './lib/fetch-text-by-line';
  6. import { compareAndWriteFile, createRuleset } from './lib/create-file';
  7. import { task } from './trace';
  8. import { SHARED_DESCRIPTION } from './lib/constants';
  9. import { createMemoizedPromise } from './lib/memo-promise';
  10. import * as yaml from 'yaml';
  11. import { appendArrayInPlace } from './lib/append-array-in-place';
  12. export const getDomesticAndDirectDomainsRulesetPromise = createMemoizedPromise(async () => {
  13. const domestics = await readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/domestic.conf'));
  14. const directs = await readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/direct.conf'));
  15. const lans: string[] = [];
  16. Object.entries(DOMESTICS).forEach(([, { domains }]) => {
  17. appendArrayInPlace(domestics, domains.map((domain) => `DOMAIN-SUFFIX,${domain}`));
  18. });
  19. Object.entries(DIRECTS).forEach(([, { domains }]) => {
  20. appendArrayInPlace(directs, domains.map((domain) => `DOMAIN-SUFFIX,${domain}`));
  21. });
  22. Object.entries(LANS).forEach(([, { domains }]) => {
  23. appendArrayInPlace(lans, domains.map((domain) => `DOMAIN-SUFFIX,${domain}`));
  24. });
  25. return [domestics, directs, lans] as const;
  26. });
  27. export const buildDomesticRuleset = task(import.meta.main, import.meta.path)(async (span) => {
  28. const res = await getDomesticAndDirectDomainsRulesetPromise();
  29. const dataset = Object.entries(DOMESTICS);
  30. appendArrayInPlace(dataset, Object.entries(DIRECTS));
  31. appendArrayInPlace(dataset, Object.entries(LANS));
  32. return Promise.all([
  33. createRuleset(
  34. span,
  35. 'Sukka\'s Ruleset - Domestic Domains',
  36. [
  37. ...SHARED_DESCRIPTION,
  38. '',
  39. 'This file contains known addresses that are avaliable in the Mainland China.'
  40. ],
  41. new Date(),
  42. res[0],
  43. 'ruleset',
  44. path.resolve(import.meta.dir, '../List/non_ip/domestic.conf'),
  45. path.resolve(import.meta.dir, '../Clash/non_ip/domestic.txt')
  46. ),
  47. createRuleset(
  48. span,
  49. 'Sukka\'s Ruleset - Direct Rules',
  50. [
  51. ...SHARED_DESCRIPTION,
  52. '',
  53. 'This file contains domains and process that should not be proxied.'
  54. ],
  55. new Date(),
  56. res[1],
  57. 'ruleset',
  58. path.resolve(import.meta.dir, '../List/non_ip/direct.conf'),
  59. path.resolve(import.meta.dir, '../Clash/non_ip/direct.txt')
  60. ),
  61. createRuleset(
  62. span,
  63. 'Sukka\'s Ruleset - LAN',
  64. [
  65. ...SHARED_DESCRIPTION,
  66. '',
  67. 'This file includes rules for LAN DOMAIN and reserved TLDs.'
  68. ],
  69. new Date(),
  70. res[2],
  71. 'ruleset',
  72. path.resolve(import.meta.dir, '../List/non_ip/lan.conf'),
  73. path.resolve(import.meta.dir, '../Clash/non_ip/lan.txt')
  74. ),
  75. compareAndWriteFile(
  76. span,
  77. [
  78. '#!name=[Sukka] Local DNS Mapping',
  79. `#!desc=Last Updated: ${new Date().toISOString()}`,
  80. '',
  81. '[Host]',
  82. ...dataset.flatMap(([, { domains, dns, hosts }]) => [
  83. ...Object.entries(hosts).flatMap(([dns, ips]: [dns: string, ips: string[]]) => `${dns} = ${ips.join(', ')}`),
  84. ...domains.flatMap((domain) => [
  85. `${domain} = server:${dns}`,
  86. `*.${domain} = server:${dns}`
  87. ])
  88. ])
  89. ],
  90. path.resolve(import.meta.dir, '../Modules/sukka_local_dns_mapping.sgmodule')
  91. ),
  92. Bun.write(
  93. path.resolve(import.meta.dir, '../Internal/clash_nameserver_policy.yaml'),
  94. yaml.stringify(
  95. {
  96. dns: {
  97. 'nameserver-policy': dataset.reduce<Record<string, string | string[]>>(
  98. (acc, [, { domains, dns }]) => {
  99. domains.forEach((domain) => {
  100. acc[`+.${domain}`] = dns === 'system'
  101. ? [
  102. 'system://',
  103. 'system',
  104. 'dhcp://system'
  105. ]
  106. : dns;
  107. });
  108. return acc;
  109. },
  110. {}
  111. )
  112. },
  113. hosts: dataset.reduce<Record<string, string>>(
  114. (acc, [, { domains, dns, ...rest }]) => {
  115. if ('hosts' in rest) {
  116. Object.assign(acc, rest.hosts);
  117. }
  118. return acc;
  119. },
  120. {}
  121. )
  122. },
  123. { version: '1.1' }
  124. )
  125. )
  126. ]);
  127. });