clash.ts 2.2 KB

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