clash.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import picocolors from 'picocolors';
  2. import { domainWildCardToRegex } from './misc';
  3. import { isProbablyIpv4, isProbablyIpv6 } from './is-fast-ip';
  4. const identity = <T>(x: T): T => x;
  5. const unsupported = Symbol('unsupported');
  6. // https://dreamacro.github.io/clash/configuration/rules.html
  7. const PROCESSOR: Record<string, ((raw: string, type: string, value: string) => string) | typeof unsupported> = {
  8. DOMAIN: identity,
  9. 'DOMAIN-SUFFIX': identity,
  10. 'DOMAIN-KEYWORD': identity,
  11. 'DOMAIN-WILDCARD': (_raw, _type, value) => `DOMAIN-REGEX,${domainWildCardToRegex(value)}`,
  12. GEOIP: identity,
  13. 'IP-CIDR': identity,
  14. 'IP-CIDR6': identity,
  15. 'IP-ASN': identity,
  16. 'SRC-IP': (_raw, _type, value) => {
  17. if (value.includes('/')) {
  18. return `SRC-IP-CIDR,${value}`;
  19. }
  20. if (isProbablyIpv4(value)) {
  21. return `SRC-IP-CIDR,${value}/32`;
  22. }
  23. if (isProbablyIpv6(value)) {
  24. return `SRC-IP-CIDR6,${value}/128`;
  25. }
  26. return '';
  27. },
  28. 'SRC-IP-CIDR': identity,
  29. 'SRC-PORT': identity,
  30. 'DST-PORT': identity,
  31. 'PROCESS-NAME': identity,
  32. 'PROCESS-PATH': identity,
  33. 'DEST-PORT': (_raw, _type, value) => `DST-PORT,${value}`,
  34. 'IN-PORT': (_raw, _type, value) => `SRC-PORT,${value}`,
  35. 'URL-REGEX': unsupported,
  36. 'USER-AGENT': unsupported
  37. };
  38. export const surgeRulesetToClashClassicalTextRuleset = (rules: string[] | Set<string>) => {
  39. return Array.from(rules).reduce<string[]>((acc, cur) => {
  40. let buf = '';
  41. let type = '';
  42. let i = 0;
  43. for (const len = cur.length; i < len; i++) {
  44. if (cur[i] === ',') {
  45. type = buf;
  46. break;
  47. }
  48. buf += cur[i];
  49. }
  50. if (type === '') {
  51. return acc;
  52. }
  53. const value = cur.slice(i + 1);
  54. if (type in PROCESSOR) {
  55. const proc = PROCESSOR[type];
  56. if (proc !== unsupported) {
  57. acc.push(proc(cur, type, value));
  58. }
  59. } else {
  60. console.log(picocolors.yellow(`[clash] unknown rule type: ${type}`), cur);
  61. }
  62. return acc;
  63. }, []);
  64. };
  65. export const surgeDomainsetToClashDomainset = (domainset: string[]) => {
  66. return domainset.map(i => (i[0] === '.' ? `+${i}` : i));
  67. };
  68. export const surgeDomainsetToClashRuleset = (domainset: string[]) => {
  69. return domainset.map(i => (i[0] === '.' ? `DOMAIN-SUFFIX,${i.slice(1)}` : `DOMAIN,${i}`));
  70. };