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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // @ts-check
  2. import path from 'node: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. import { output, writeFile } from './lib/misc';
  13. export const getDomesticAndDirectDomainsRulesetPromise = createMemoizedPromise(async () => {
  14. const domestics = await readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/domestic.conf'));
  15. const directs = await readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/direct.conf'));
  16. const lans: string[] = [];
  17. Object.entries(DOMESTICS).forEach(([, { domains }]) => {
  18. appendArrayInPlace(domestics, domains.map((domain) => `DOMAIN-SUFFIX,${domain}`));
  19. });
  20. Object.entries(DIRECTS).forEach(([, { domains }]) => {
  21. appendArrayInPlace(directs, domains.map((domain) => `DOMAIN-SUFFIX,${domain}`));
  22. });
  23. Object.entries(LANS).forEach(([, { domains }]) => {
  24. appendArrayInPlace(lans, domains.map((domain) => `DOMAIN-SUFFIX,${domain}`));
  25. });
  26. return [domestics, directs, lans] as const;
  27. });
  28. export const buildDomesticRuleset = task(require.main === module, __filename)(async (span) => {
  29. const res = await getDomesticAndDirectDomainsRulesetPromise();
  30. const dataset = Object.entries(DOMESTICS);
  31. appendArrayInPlace(dataset, Object.entries(DIRECTS));
  32. appendArrayInPlace(dataset, Object.entries(LANS));
  33. return Promise.all([
  34. createRuleset(
  35. span,
  36. 'Sukka\'s Ruleset - Domestic Domains',
  37. [
  38. ...SHARED_DESCRIPTION,
  39. '',
  40. 'This file contains known addresses that are avaliable in the Mainland China.'
  41. ],
  42. new Date(),
  43. res[0],
  44. 'ruleset',
  45. ...output('domestic', 'non_ip')
  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. ...output('direct', 'non_ip')
  59. ),
  60. createRuleset(
  61. span,
  62. 'Sukka\'s Ruleset - LAN',
  63. [
  64. ...SHARED_DESCRIPTION,
  65. '',
  66. 'This file includes rules for LAN DOMAIN and reserved TLDs.'
  67. ],
  68. new Date(),
  69. res[2],
  70. 'ruleset',
  71. ...output('lan', 'non_ip')
  72. ),
  73. compareAndWriteFile(
  74. span,
  75. [
  76. '#!name=[Sukka] Local DNS Mapping',
  77. `#!desc=Last Updated: ${new Date().toISOString()}`,
  78. '',
  79. '[Host]',
  80. ...dataset.flatMap(([, { domains, dns, hosts }]) => [
  81. ...Object.entries(hosts).flatMap(([dns, ips]: [dns: string, ips: string[]]) => `${dns} = ${ips.join(', ')}`),
  82. ...domains.flatMap((domain) => [
  83. `${domain} = server:${dns}`,
  84. `*.${domain} = server:${dns}`
  85. ])
  86. ])
  87. ],
  88. path.resolve(__dirname, '../Modules/sukka_local_dns_mapping.sgmodule')
  89. ),
  90. writeFile(
  91. path.resolve(__dirname, '../Internal/clash_nameserver_policy.yaml'),
  92. yaml.stringify(
  93. {
  94. dns: {
  95. 'nameserver-policy': dataset.reduce<Record<string, string | string[]>>(
  96. (acc, [, { domains, dns }]) => {
  97. domains.forEach((domain) => {
  98. acc[`+.${domain}`] = dns === 'system'
  99. ? [
  100. 'system://',
  101. 'system',
  102. 'dhcp://system'
  103. ]
  104. : dns;
  105. });
  106. return acc;
  107. },
  108. {}
  109. )
  110. },
  111. hosts: dataset.reduce<Record<string, string>>(
  112. (acc, [, { domains, dns, ...rest }]) => {
  113. if ('hosts' in rest) {
  114. Object.assign(acc, rest.hosts);
  115. }
  116. return acc;
  117. },
  118. {}
  119. )
  120. },
  121. { version: '1.1' }
  122. )
  123. )
  124. ]);
  125. });