UNPKG

surgio

Version:

Generating rules for Surge, Clash, Quantumult like a PRO

184 lines 7.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSurfboardNodeNames = exports.getSurfboardNodes = exports.getSurfboardExtendHeaders = void 0; const logger_1 = require("@surgio/logger"); const constant_1 = require("../constant"); const types_1 = require("../types"); const filters_1 = require("../filters"); const index_1 = require("./index"); const logger = (0, logger_1.createLogger)({ service: 'surgio:utils:surfboard' }); const getSurfboardExtendHeaders = (wsHeaders) => { return Object.keys(wsHeaders) .map((headerKey) => `${headerKey}:${wsHeaders[headerKey]}`) .join('|'); }; exports.getSurfboardExtendHeaders = getSurfboardExtendHeaders; /** * @see https://getsurfboard.com/docs/profile-format/proxy/ */ const getSurfboardNodes = function (list, filter) { const result = (0, filters_1.applyFilter)(list, filter) .map(nodeListMapper) .filter((item) => item !== undefined) .map((item) => item[1]); return result.join('\n'); }; exports.getSurfboardNodes = getSurfboardNodes; const getSurfboardNodeNames = function (list, filter) { return (0, filters_1.applyFilter)(list, filter) .map(nodeListMapper) .filter((item) => item !== undefined) .map((item) => item[0]) .join(', '); }; exports.getSurfboardNodeNames = getSurfboardNodeNames; function nodeListMapper(nodeConfig) { switch (nodeConfig.type) { case types_1.NodeTypeEnum.Shadowsocks: { if (nodeConfig.obfs && ['ws', 'wss'].includes(nodeConfig.obfs)) { logger.warn(`不支持为 Surfboard 生成 v2ray-plugin 的 Shadowsocks 节点,节点 ${nodeConfig.nodeName} 会被省略`); return void 0; } return [ nodeConfig.nodeName, [ nodeConfig.nodeName, [ 'ss', nodeConfig.hostname, nodeConfig.port, 'encrypt-method=' + nodeConfig.method, ...(0, index_1.pickAndFormatStringList)(nodeConfig, ['password', 'udpRelay', 'obfs', 'obfsHost'], { keyFormat: 'kebabCase', }), ].join(', '), ].join(' = '), ]; } case types_1.NodeTypeEnum.HTTPS: { return [ nodeConfig.nodeName, [ nodeConfig.nodeName, [ 'https', nodeConfig.hostname, nodeConfig.port, nodeConfig.username /* istanbul ignore next */ || '', nodeConfig.password /* istanbul ignore next */ || '', ...(typeof nodeConfig.skipCertVerify === 'boolean' ? [`skip-cert-verify=${nodeConfig.skipCertVerify}`] : []), ...(0, index_1.pickAndFormatStringList)(nodeConfig, ['sni']), ].join(', '), ].join(' = '), ]; } case types_1.NodeTypeEnum.HTTP: { return [ nodeConfig.nodeName, [ nodeConfig.nodeName, [ 'http', nodeConfig.hostname, nodeConfig.port, nodeConfig.username /* istanbul ignore next */ || '', nodeConfig.password /* istanbul ignore next */ || '', ].join(', '), ].join(' = '), ]; } case types_1.NodeTypeEnum.Vmess: { if (!constant_1.SURFBOARD_SUPPORTED_VMESS_NETWORK.includes(nodeConfig.network)) { logger.warn(`Surfboard 不支持 ${nodeConfig.network} 的 Vmess 节点,节点 ${nodeConfig.nodeName} 会被省略`); return void 0; } const result = [ 'vmess', nodeConfig.hostname, nodeConfig.port, `username=${nodeConfig.uuid}`, ]; if (['chacha20-ietf-poly1305', 'aes-128-gcm'].includes(nodeConfig.method)) { result.push(`encrypt-method=${nodeConfig.method}`); } if (nodeConfig.network === 'ws') { result.push('ws=true'); result.push(`ws-path=${nodeConfig.wsOpts?.path || '/'}`); result.push('ws-headers=' + JSON.stringify((0, exports.getSurfboardExtendHeaders)({ 'user-agent': constant_1.OBFS_UA, ...nodeConfig.wsOpts?.headers, }))); } if (nodeConfig.tls) { result.push('tls=true'); if (nodeConfig.skipCertVerify) { result.push('skip-cert-verify=true'); } if (nodeConfig.sni) { result.push(`sni=${nodeConfig.sni}`); } } if (nodeConfig?.surfboardConfig?.vmessAEAD) { result.push('vmess-aead=true'); } else { result.push('vmess-aead=false'); } return [ nodeConfig.nodeName, [nodeConfig.nodeName, result.join(', ')].join(' = '), ]; } case types_1.NodeTypeEnum.Trojan: { const result = [ 'trojan', nodeConfig.hostname, `${nodeConfig.port}`, `password=${nodeConfig.password}`, ...(0, index_1.pickAndFormatStringList)(nodeConfig, ['sni']), ...(typeof nodeConfig.skipCertVerify === 'boolean' ? [`skip-cert-verify=${nodeConfig.skipCertVerify}`] : []), ]; if (nodeConfig.network === 'ws') { result.push('ws=true'); result.push(`ws-path=${nodeConfig.wsPath}`); if (nodeConfig.wsHeaders) { result.push('ws-headers=' + JSON.stringify((0, exports.getSurfboardExtendHeaders)(nodeConfig.wsHeaders))); } } return [ nodeConfig.nodeName, [nodeConfig.nodeName, result.join(', ')].join(' = '), ]; } case types_1.NodeTypeEnum.Socks5: { const result = [ nodeConfig.tls === true ? 'socks5-tls' : 'socks5', nodeConfig.hostname, nodeConfig.port, ...(0, index_1.pickAndFormatStringList)(nodeConfig, ['username', 'password', 'sni']), ]; if (nodeConfig.tls === true) { result.push(...(typeof nodeConfig.skipCertVerify === 'boolean' ? [`skip-cert-verify=${nodeConfig.skipCertVerify}`] : []), ...(typeof nodeConfig.clientCert === 'string' ? [`client-cert=${nodeConfig.clientCert}`] : [])); } return [ nodeConfig.nodeName, [nodeConfig.nodeName, result.join(', ')].join(' = '), ]; } // istanbul ignore next default: logger.warn(`不支持为 Surfboard 生成 ${nodeConfig.type} 的节点,节点 ${nodeConfig.nodeName} 会被省略`); return void 0; } } //# sourceMappingURL=surfboard.js.map