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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. import { 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. path.resolve(__dirname, '../List/non_ip/domestic.conf'),
  46. path.resolve(__dirname, '../Clash/non_ip/domestic.txt')
  47. ),
  48. createRuleset(
  49. span,
  50. 'Sukka\'s Ruleset - Direct Rules',
  51. [
  52. ...SHARED_DESCRIPTION,
  53. '',
  54. 'This file contains domains and process that should not be proxied.'
  55. ],
  56. new Date(),
  57. res[1],
  58. 'ruleset',
  59. path.resolve(__dirname, '../List/non_ip/direct.conf'),
  60. path.resolve(__dirname, '../Clash/non_ip/direct.txt')
  61. ),
  62. createRuleset(
  63. span,
  64. 'Sukka\'s Ruleset - LAN',
  65. [
  66. ...SHARED_DESCRIPTION,
  67. '',
  68. 'This file includes rules for LAN DOMAIN and reserved TLDs.'
  69. ],
  70. new Date(),
  71. res[2],
  72. 'ruleset',
  73. path.resolve(__dirname, '../List/non_ip/lan.conf'),
  74. path.resolve(__dirname, '../Clash/non_ip/lan.txt')
  75. ),
  76. compareAndWriteFile(
  77. span,
  78. [
  79. '#!name=[Sukka] Local DNS Mapping',
  80. `#!desc=Last Updated: ${new Date().toISOString()}`,
  81. '',
  82. '[Host]',
  83. ...dataset.flatMap(([, { domains, dns, hosts }]) => [
  84. ...Object.entries(hosts).flatMap(([dns, ips]: [dns: string, ips: string[]]) => `${dns} = ${ips.join(', ')}`),
  85. ...domains.flatMap((domain) => [
  86. `${domain} = server:${dns}`,
  87. `*.${domain} = server:${dns}`
  88. ])
  89. ])
  90. ],
  91. path.resolve(__dirname, '../Modules/sukka_local_dns_mapping.sgmodule')
  92. ),
  93. writeFile(
  94. path.resolve(__dirname, '../Internal/clash_nameserver_policy.yaml'),
  95. yaml.stringify(
  96. {
  97. dns: {
  98. 'nameserver-policy': dataset.reduce<Record<string, string | string[]>>(
  99. (acc, [, { domains, dns }]) => {
  100. domains.forEach((domain) => {
  101. acc[`+.${domain}`] = dns === 'system'
  102. ? [
  103. 'system://',
  104. 'system',
  105. 'dhcp://system'
  106. ]
  107. : dns;
  108. });
  109. return acc;
  110. },
  111. {}
  112. )
  113. },
  114. hosts: dataset.reduce<Record<string, string>>(
  115. (acc, [, { domains, dns, ...rest }]) => {
  116. if ('hosts' in rest) {
  117. Object.assign(acc, rest.hosts);
  118. }
  119. return acc;
  120. },
  121. {}
  122. )
  123. },
  124. { version: '1.1' }
  125. )
  126. )
  127. ]);
  128. });