ruleset.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import type { Span } from '../../trace';
  2. import createKeywordFilter from '../aho-corasick';
  3. import { appendArrayInPlace } from '../append-array-in-place';
  4. import { appendArrayFromSet } from '../misc';
  5. import type { SingboxSourceFormat } from '../singbox';
  6. import { sortDomains } from '../stable-sort-domain';
  7. import { RuleOutput } from './base';
  8. export class RulesetOutput extends RuleOutput {
  9. constructor(span: Span, id: string, protected type: 'non_ip' | 'ip') {
  10. super(span, id);
  11. }
  12. private $computed: [domain: string[], domainSuffix: string[], sortedDomainRules: string[]] | null = null;
  13. private get computed() {
  14. if (!this.$computed) {
  15. const kwfilter = createKeywordFilter(this.domainKeywords);
  16. const domains: string[] = [];
  17. const domainSuffixes: string[] = [];
  18. const sortedDomainRules: string[] = [];
  19. for (const domain of sortDomains(this.domainTrie.dump(), this.apexDomainMap, this.subDomainMap)) {
  20. if (kwfilter(domain)) {
  21. continue;
  22. }
  23. if (domain[0] === '.') {
  24. domainSuffixes.push(domain.slice(1));
  25. sortedDomainRules.push(`DOMAIN-SUFFIX,${domain.slice(1)}`);
  26. } else {
  27. domains.push(domain);
  28. sortedDomainRules.push(`DOMAIN,${domain}`);
  29. }
  30. }
  31. this.$computed = [domains, domainSuffixes, sortedDomainRules];
  32. }
  33. return this.$computed;
  34. }
  35. surge(): string[] {
  36. const results: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
  37. appendArrayInPlace(results, this.computed[2]);
  38. appendArrayFromSet(results, this.domainKeywords, i => `DOMAIN-KEYWORD,${i}`);
  39. appendArrayFromSet(results, this.domainWildcard, i => `DOMAIN-WILDCARD,${i}`);
  40. appendArrayFromSet(results, this.userAgent, i => `USER-AGENT,${i}`);
  41. appendArrayFromSet(results, this.processName, i => `PROCESS-NAME,${i}`);
  42. appendArrayFromSet(results, this.processPath, i => `PROCESS-NAME,${i}`);
  43. appendArrayInPlace(results, this.otherRules);
  44. appendArrayFromSet(results, this.urlRegex, i => `URL-REGEX,${i}`);
  45. appendArrayFromSet(results, this.ipcidrNoResolve, i => `IP-CIDR,${i},no-resolve`);
  46. appendArrayFromSet(results, this.ipcidr6NoResolve, i => `IP-CIDR6,${i},no-resolve`);
  47. appendArrayFromSet(results, this.ipasnNoResolve, i => `IP-ASN,${i},no-resolve`);
  48. appendArrayFromSet(results, this.groipNoResolve, i => `GEOIP,${i},no-resolve`);
  49. appendArrayFromSet(results, this.ipcidr, i => `IP-CIDR,${i}`);
  50. appendArrayFromSet(results, this.ipcidr6, i => `IP-CIDR6,${i}`);
  51. appendArrayFromSet(results, this.ipasn, i => `IP-ASN,${i}`);
  52. appendArrayFromSet(results, this.geoip, i => `GEOIP,${i}`);
  53. return results;
  54. }
  55. clash(): string[] {
  56. const results: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
  57. appendArrayInPlace(results, this.computed[2]);
  58. appendArrayFromSet(results, this.domainKeywords, i => `DOMAIN-KEYWORD,${i}`);
  59. appendArrayFromSet(results, this.domainWildcard, i => `DOMAIN-REGEX,${RuleOutput.domainWildCardToRegex(i)}`);
  60. appendArrayFromSet(results, this.processName, i => `PROCESS-NAME,${i}`);
  61. appendArrayFromSet(results, this.processPath, i => `PROCESS-PATH,${i}`);
  62. // appendArrayInPlace(results, this.otherRules);
  63. appendArrayFromSet(results, this.ipcidrNoResolve, i => `IP-CIDR,${i},no-resolve`);
  64. appendArrayFromSet(results, this.ipcidr6NoResolve, i => `IP-CIDR6,${i},no-resolve`);
  65. appendArrayFromSet(results, this.ipasnNoResolve, i => `IP-ASN,${i},no-resolve`);
  66. appendArrayFromSet(results, this.groipNoResolve, i => `GEOIP,${i},no-resolve`);
  67. appendArrayFromSet(results, this.ipcidr, i => `IP-CIDR,${i}`);
  68. appendArrayFromSet(results, this.ipcidr6, i => `IP-CIDR6,${i}`);
  69. appendArrayFromSet(results, this.ipasn, i => `IP-ASN,${i}`);
  70. appendArrayFromSet(results, this.geoip, i => `GEOIP,${i}`);
  71. return results;
  72. }
  73. singbox(): string[] {
  74. const singbox: SingboxSourceFormat = {
  75. version: 2,
  76. rules: [{
  77. domain: ['this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'].concat(this.computed[0]),
  78. domain_suffix: this.computed[1],
  79. domain_keyword: Array.from(this.domainKeywords),
  80. domain_regex: Array.from(this.domainWildcard).map(RuleOutput.domainWildCardToRegex),
  81. ip_cidr: appendArrayFromSet([], [this.ipcidr, this.ipcidrNoResolve, this.ipcidr6, this.ipcidr6NoResolve]),
  82. process_name: Array.from(this.processName),
  83. process_path: Array.from(this.processPath)
  84. }]
  85. };
  86. return RuleOutput.jsonToLines(singbox);
  87. }
  88. }