clash.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import picocolors from 'picocolors';
  2. import { domainWildCardToRegex } from './misc';
  3. const identity = <T>(x: T): T => x;
  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-CIDR': identity,
  16. 'SRC-PORT': identity,
  17. 'DST-PORT': identity,
  18. 'PROCESS-NAME': identity,
  19. 'PROCESS-PATH': identity,
  20. 'DEST-PORT': (_raw, _type, value) => `DST-PORT,${value}`,
  21. 'IN-PORT': (_raw, _type, value) => `SRC-PORT,${value}`,
  22. 'URL-REGEX': unsupported,
  23. 'USER-AGENT': unsupported
  24. };
  25. export const surgeRulesetToClashClassicalTextRuleset = (rules: string[] | Set<string>) => {
  26. return Array.from(rules).reduce<string[]>((acc, cur) => {
  27. let buf = '';
  28. let type = '';
  29. let i = 0;
  30. for (const len = cur.length; i < len; i++) {
  31. if (cur[i] === ',') {
  32. type = buf;
  33. break;
  34. }
  35. buf += cur[i];
  36. }
  37. if (type === '') {
  38. return acc;
  39. }
  40. const value = cur.slice(i + 1);
  41. if (type in PROCESSOR) {
  42. const proc = PROCESSOR[type];
  43. if (proc !== unsupported) {
  44. acc.push(proc(cur, type, value));
  45. }
  46. } else {
  47. console.log(picocolors.yellow(`[clash] unknown rule type: ${type}`), cur);
  48. }
  49. return acc;
  50. }, []);
  51. };
  52. export const surgeDomainsetToClashDomainset = (domainset: string[]) => {
  53. return domainset.map(i => (i[0] === '.' ? `+${i}` : i));
  54. };
  55. export const surgeDomainsetToClashRuleset = (domainset: string[]) => {
  56. return domainset.map(i => (i[0] === '.' ? `DOMAIN-SUFFIX,${i.slice(1)}` : `DOMAIN,${i}`));
  57. };