build-mitm-hostname.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { readFileByLine } from './lib/fetch-text-by-line';
  2. import Table from 'cli-table3';
  3. import { fdir as Fdir } from 'fdir';
  4. import { green, yellow } from 'picocolors';
  5. import { processLineFromReadline } from './lib/process-line';
  6. import { getHostname } from 'tldts';
  7. import { OUTPUT_SURGE_DIR } from './constants/dir';
  8. const PRESET_MITM_HOSTNAMES = [
  9. 'dsp-x.jd.com',
  10. 'bdsp-x.jd.com'
  11. ];
  12. (async () => {
  13. const rulesets = await new Fdir()
  14. .withFullPaths()
  15. .crawl(OUTPUT_SURGE_DIR)
  16. .withPromise();
  17. const urlRegexPaths: Array<{ origin: string, processed: string }> = [];
  18. await Promise.all(rulesets.map(async file => {
  19. const content = await processLineFromReadline(readFileByLine(file));
  20. urlRegexPaths.push(
  21. ...content
  22. .filter(i => (
  23. i.startsWith('URL-REGEX')
  24. && !i.includes('http://')
  25. ))
  26. .map(i => i.split(',')[1])
  27. .map(i => ({
  28. origin: i,
  29. processed: i
  30. .replaceAll('^https?://', '')
  31. .replaceAll('^https://', '')
  32. .replaceAll('^http://', '')
  33. .split('/')[0]
  34. .replaceAll(String.raw`\.`, '.')
  35. .replaceAll('.+', '*')
  36. .replaceAll(String.raw`\d`, '*')
  37. .replaceAll('([a-z])', '*')
  38. .replaceAll('[a-z]', '*')
  39. .replaceAll('([0-9])', '*')
  40. .replaceAll('[0-9]', '*')
  41. .replaceAll(/{.+?}/g, '')
  42. .replaceAll(/\*+/g, '*')
  43. }))
  44. );
  45. }));
  46. const mitmDomains = new Set(PRESET_MITM_HOSTNAMES); // Special case for parsed failed
  47. const parsedFailures = new Set();
  48. const dedupedUrlRegexPaths = [...new Set(urlRegexPaths)];
  49. dedupedUrlRegexPaths.forEach(i => {
  50. const result = getHostnameSafe(i.processed);
  51. if (result) {
  52. mitmDomains.add(result);
  53. } else {
  54. parsedFailures.add(`${i.origin} ${i.processed} ${result}`);
  55. }
  56. });
  57. const mitmDomainsRegExpArray = Array.from(mitmDomains)
  58. .slice()
  59. .filter(i => {
  60. return i.length > 3
  61. && !i.includes('.mp4') // Special Case
  62. && i !== '(www.)' // Special Case
  63. && !(i !== '*.meituan.net' && i.endsWith('.meituan.net'))
  64. && !i.startsWith('.')
  65. && !i.endsWith('.')
  66. && !i.endsWith('*');
  67. })
  68. .map(i => {
  69. return new RegExp(
  70. escapeRegExp(i)
  71. .replaceAll('{www or not}', '(www.)?')
  72. .replaceAll(String.raw`\*`, '(.*)')
  73. );
  74. });
  75. const parsedTable = new Table({
  76. head: ['Hostname Pattern', 'Original Rules']
  77. });
  78. dedupedUrlRegexPaths.forEach(i => {
  79. const result = getHostnameSafe(i.processed);
  80. if (result) {
  81. if (matchWithRegExpArray(result, mitmDomainsRegExpArray)) {
  82. parsedTable.push([green(result), i.origin]);
  83. } else {
  84. parsedTable.push([yellow(result), i.origin]);
  85. }
  86. }
  87. });
  88. console.log('Mitm Hostnames:');
  89. console.log(`hostname = %APPEND% ${Array.from(mitmDomains).join(', ')}`);
  90. console.log('--------------------');
  91. console.log('Parsed Sucessed:');
  92. console.log(parsedTable.toString());
  93. console.log('--------------------');
  94. console.log('Parsed Failed');
  95. console.log(Array.from(parsedFailures).join('\n'));
  96. })();
  97. /** Util function */
  98. function getHostnameSafe(input: string) {
  99. const res = getHostname(input);
  100. if (res && /[^\s\w*.-]/.test(res)) return null;
  101. return res;
  102. }
  103. function matchWithRegExpArray(input: string, regexps: RegExp[] = []) {
  104. for (const r of regexps) {
  105. if (r.test(input)) return true;
  106. }
  107. return false;
  108. }
  109. function escapeRegExp(string = '') {
  110. const reRegExpChar = /[$()*+.?[\\\]^{|}]/g;
  111. const reHasRegExpChar = new RegExp(reRegExpChar.source);
  112. return string && reHasRegExpChar.test(string)
  113. ? string.replaceAll(reRegExpChar, String.raw`\$&`)
  114. : string;
  115. }