validate-domainset.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Surge Domain Set can not include root domain from public suffix list.
  2. import * as tldts from 'tldts'; // hit ratio way too low, dont cache
  3. import picocolors from 'picocolors';
  4. import path from 'path';
  5. import listDir from '@sukka/listdir';
  6. import { readFileByLine } from './lib/fetch-text-by-line';
  7. import { processLine } from './lib/process-line';
  8. import { task } from './trace';
  9. const SPECIAL_SUFFIXES = new Set([
  10. 'linodeobjects.com', // only *.linodeobjects.com are public suffix
  11. 'vultrobjects.com', // only *.vultrobjects.com are public suffix
  12. 'dweb.link' // only *.dweb.link are public suffix
  13. ]);
  14. const validateDomainSet = async (filePath: string) => {
  15. for await (const l of readFileByLine(path.resolve(import.meta.dir, '../List/domainset', filePath))) {
  16. // starts with #
  17. const line = processLine(l);
  18. if (!line) {
  19. continue;
  20. }
  21. const domain = line[0] === '.' ? line.slice(1) : line;
  22. const parsed = tldts.parse(domain, { allowPrivateDomains: true, detectIp: false });
  23. if (
  24. (
  25. parsed.isPrivate
  26. || parsed.isIcann
  27. ) && domain === parsed.publicSuffix
  28. ) {
  29. console.error(`[${filePath}]`, picocolors.yellow(domain), picocolors.red('is in public suffix list!'));
  30. }
  31. }
  32. };
  33. const _validateRuleset = async (filePath: string) => {
  34. console.log(`[${filePath}]`);
  35. for await (const l of readFileByLine(path.resolve(import.meta.dir, '../List/non_ip', filePath))) {
  36. // starts with #
  37. const line = processLine(l);
  38. if (!line) {
  39. continue;
  40. }
  41. if (!line.startsWith('DOMAIN-SUFFIX,')) {
  42. continue;
  43. }
  44. const domain = line.slice(14);
  45. const parsed = tldts.parse(domain, { allowPrivateDomains: true, detectIp: false });
  46. if (domain !== parsed.publicSuffix) {
  47. if (!SPECIAL_SUFFIXES.has(domain)) {
  48. console.warn(picocolors.yellow(domain), picocolors.green('is not in public suffix list!'));
  49. }
  50. }
  51. }
  52. };
  53. export const validate = task(import.meta.path, async () => {
  54. // const [domainsetFiles, _rulesetFiles] = await Promise.all([
  55. // listDir(path.resolve(import.meta.dir, '../List/domainset')),
  56. // listDir(path.resolve(import.meta.dir, '../List/non_ip'))
  57. // ]);
  58. return Promise.all([
  59. listDir(path.resolve(import.meta.dir, '../List/domainset'))
  60. .then(domainsetFiles => Promise.all(domainsetFiles.map(file => validateDomainSet(file))))
  61. // rulesetFiles.map(file => validateRuleset(file))
  62. ]);
  63. });
  64. if (import.meta.main) {
  65. validate();
  66. }