build-chn-cidr.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
  2. import { processLineFromReadline } from './lib/process-line';
  3. import { task } from './trace';
  4. import { contains as containsCidr, exclude as excludeCidr } from 'fast-cidr-tools';
  5. import { createMemoizedPromise } from './lib/memo-promise';
  6. import { CN_CIDR_MISSING_IN_CHNROUTE, NON_CN_CIDR_INCLUDED_IN_CHNROUTE } from './constants/cidr';
  7. import { appendArrayInPlace } from './lib/append-array-in-place';
  8. import { IPListOutput } from './lib/create-file';
  9. import { cachedOnlyFail } from './lib/fs-memo';
  10. const PROBE_CHN_CIDR_V4 = [
  11. // NetEase Hangzhou
  12. '223.252.196.38',
  13. // Aliyun ShenZhen
  14. '120.78.92.171'
  15. ];
  16. export const getChnCidrPromise = createMemoizedPromise(cachedOnlyFail(
  17. async function getChnCidr() {
  18. const [_cidr4, cidr6] = await Promise.all([
  19. fetchRemoteTextByLine('https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt').then(processLineFromReadline),
  20. fetchRemoteTextByLine('https://gaoyifan.github.io/china-operator-ip/china6.txt').then(processLineFromReadline)
  21. ]);
  22. const cidr4 = excludeCidr(
  23. appendArrayInPlace(_cidr4, CN_CIDR_MISSING_IN_CHNROUTE),
  24. NON_CN_CIDR_INCLUDED_IN_CHNROUTE,
  25. true
  26. );
  27. for (const probeIp of PROBE_CHN_CIDR_V4) {
  28. if (!containsCidr(cidr4, PROBE_CHN_CIDR_V4)) {
  29. const err = new TypeError('chnroutes missing probe IP');
  30. err.cause = probeIp;
  31. throw err;
  32. }
  33. }
  34. return [cidr4, cidr6] as const;
  35. },
  36. {
  37. serializer: JSON.stringify,
  38. deserializer: JSON.parse
  39. }
  40. ));
  41. export const buildChnCidr = task(require.main === module, __filename)(async (span) => {
  42. const [filteredCidr4, cidr6] = await span.traceChildAsync('download chnroutes2', getChnCidrPromise);
  43. // Can not use SHARED_DESCRIPTION here as different license
  44. const description = [
  45. 'License: CC BY-SA 2.0',
  46. 'Homepage: https://ruleset.skk.moe',
  47. 'GitHub: https://github.com/SukkaW/Surge',
  48. ''
  49. ];
  50. return Promise.all([
  51. new IPListOutput(span, 'china_ip', false)
  52. .withTitle('Sukka\'s Ruleset - Mainland China IPv4 CIDR')
  53. .withDescription([
  54. ...description,
  55. 'Data from https://misaka.io (misakaio @ GitHub)'
  56. ])
  57. .bulkAddCIDR4(filteredCidr4)
  58. .write(),
  59. new IPListOutput(span, 'china_ip_ipv6', false)
  60. .withTitle('Sukka\'s Ruleset - Mainland China IPv6 CIDR')
  61. .withDescription([
  62. ...description,
  63. 'Data from https://github.com/gaoyifan/china-operator-ip'
  64. ])
  65. .bulkAddCIDR6(cidr6)
  66. .write()
  67. ]);
  68. });