From f3eaaed03727de525e12a454a8a966fd923f8d89 Mon Sep 17 00:00:00 2001 From: Roy Li Date: Sat, 2 Nov 2019 22:03:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20udp-relay=20=E7=9A=84=E5=80=BC=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=B8=83=E5=B0=94=E7=B1=BB=E5=9E=8B=EF=BC=8C=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E5=AD=97=E7=AC=A6=E4=B8=B2=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/guide/custom-provider.md | 2 +- lib/class/ClashProvider.ts | 2 +- lib/class/CustomProvider.ts | 19 +++++++++++++++++-- lib/command/generate.ts | 2 +- lib/command/speed.ts | 3 ++- lib/command/upload.ts | 2 +- lib/gateway/index.ts | 2 +- lib/misc/deprecation.ts | 1 + lib/misc/flag_cn.ts | 2 +- lib/types.ts | 4 ++-- lib/utils/config.ts | 21 +++++++++++++++++++++ lib/utils/index.ts | 27 +++------------------------ test/class/ClashProvider.test.ts | 10 +++++----- test/utils/utils.test.ts | 20 ++++++++++---------- 14 files changed, 67 insertions(+), 50 deletions(-) diff --git a/docs/guide/custom-provider.md b/docs/guide/custom-provider.md index e25c33499..29644c054 100644 --- a/docs/guide/custom-provider.md +++ b/docs/guide/custom-provider.md @@ -156,7 +156,7 @@ module.exports = { password: 'password', obfs: 'tls', // tls 或 http 'obfs-host': 'gateway-carry.icloud.com', - 'udp-relay': 'true', + 'udp-relay': true, } ``` diff --git a/lib/class/ClashProvider.ts b/lib/class/ClashProvider.ts index 06b7f5d72..cb45bde8d 100644 --- a/lib/class/ClashProvider.ts +++ b/lib/class/ClashProvider.ts @@ -96,7 +96,7 @@ async function requestConfigFromRemote(url: string, udpRelay?: boolean): Promise port: item.port, method: item.cipher, password: item.password, - 'udp-relay': resolveUdpRelay(item.udp, udpRelay) ? 'true' : 'false', + 'udp-relay': resolveUdpRelay(item.udp, udpRelay), ...(item.plugin && item.plugin === 'obfs' ? { obfs: item['plugin-opts'].mode, 'obfs-host': item['plugin-opts'].host || 'www.bing.com', diff --git a/lib/class/CustomProvider.ts b/lib/class/CustomProvider.ts index 3694138fe..1c8851097 100644 --- a/lib/class/CustomProvider.ts +++ b/lib/class/CustomProvider.ts @@ -1,9 +1,11 @@ import Joi from '@hapi/joi'; +import * as util from 'util'; +import { DEP002 } from '../misc/deprecation'; import { CustomProviderConfig, NodeTypeEnum, PossibleNodeConfigType } from '../types'; import Provider from './Provider'; export default class CustomProvider extends Provider { - public readonly nodeList: ReadonlyArray; + public readonly nodeList: ReadonlyArray; constructor(config: CustomProviderConfig) { super(config); @@ -33,6 +35,19 @@ export default class CustomProvider extends Provider { } public async getNodeList(): Promise> { - return this.nodeList; + return this.nodeList.map(item => { + if (item.type === NodeTypeEnum.Shadowsocks) { + // 兼容字符串 true 和 false 的写法,会弃用 + if (typeof item['udp-relay'] === 'string') { + notifyDepUdpRelay(); + item['udp-relay'] = item['udp-relay'] === 'true'; + } + } + return item; + }); } } + +const notifyDepUdpRelay = util.deprecate(() => { + // do nothing +}, DEP002, 'DEP002'); diff --git a/lib/command/generate.ts b/lib/command/generate.ts index 7eeae48d8..df3407776 100644 --- a/lib/command/generate.ts +++ b/lib/command/generate.ts @@ -1,7 +1,7 @@ import Command from 'common-bin'; import path from 'path'; -import { loadConfig } from '../utils'; +import { loadConfig } from '../utils/config'; import generate from '../generate'; import { errorHandler } from '../utils/error-helper'; diff --git a/lib/command/speed.ts b/lib/command/speed.ts index d857655b3..5bd88c447 100644 --- a/lib/command/speed.ts +++ b/lib/command/speed.ts @@ -16,7 +16,8 @@ import speedTest from 'speedtest-net'; import winston, { format, Logger } from 'winston'; import { NodeTypeEnum, PossibleNodeConfigType, ShadowsocksNodeConfig } from '../types'; -import { getClashNodes, loadConfig, toYaml } from '../utils'; +import { getClashNodes, toYaml } from '../utils'; +import { loadConfig } from '../utils/config'; import getProvider from '../utils/get-provider'; import { errorHandler } from '../utils/error-helper'; diff --git a/lib/command/upload.ts b/lib/command/upload.ts index 406fe036b..afd5c2218 100644 --- a/lib/command/upload.ts +++ b/lib/command/upload.ts @@ -6,7 +6,7 @@ import dir from 'node-dir'; import ora, { Ora } from 'ora'; import path from 'path'; -import { loadConfig } from '../utils'; +import { loadConfig } from '../utils/config'; import { errorHandler } from '../utils/error-helper'; class GenerateCommand extends Command { diff --git a/lib/gateway/index.ts b/lib/gateway/index.ts index 7abcb8053..a726aeb18 100644 --- a/lib/gateway/index.ts +++ b/lib/gateway/index.ts @@ -6,7 +6,7 @@ import Router from 'koa-router'; import util from 'util'; import { DEP001 } from '../misc/deprecation'; -import { loadConfig } from '../utils'; +import { loadConfig } from '../utils/config'; import { Server } from './server'; import { FcRequest, FcResponse } from './types'; diff --git a/lib/misc/deprecation.ts b/lib/misc/deprecation.ts index 46f7bec8e..6f917322d 100644 --- a/lib/misc/deprecation.ts +++ b/lib/misc/deprecation.ts @@ -1 +1,2 @@ export const DEP001 = 'nowHandler 已不推荐使用,请参考 http://bit.ly/2q5daCK 尽快更新您的代码'; +export const DEP002 = 'udp-relay 的值已改为布尔类型,字符串类型依然可用但推荐更改'; diff --git a/lib/misc/flag_cn.ts b/lib/misc/flag_cn.ts index 50a770496..8bcaae305 100644 --- a/lib/misc/flag_cn.ts +++ b/lib/misc/flag_cn.ts @@ -26,7 +26,7 @@ export default { '🇵🇭': ['菲律宾'], '🇷🇴': ['罗马尼亚'], '🇷🇺': ['RU', '普京', '俄罗斯', '伯力', '莫斯科', '圣彼得堡', '西伯利亚', '新西伯利亚'], - '🇸🇬': ['SG', '新加坡', '狮城','新'], + '🇸🇬': ['SG', '新加坡', '狮城'], '🇹🇭': ['泰国', '曼谷'], '🇹🇷': ['土耳其', '伊斯坦布尔'], '🇺🇲': [ diff --git a/lib/types.ts b/lib/types.ts index 90341bcda..62c5e2983 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -107,7 +107,7 @@ export interface ClashProviderConfig extends ProviderConfig { } export interface CustomProviderConfig extends ProviderConfig { - readonly nodeList: ReadonlyArray; + readonly nodeList: ReadonlyArray; } export interface HttpsNodeConfig extends SimpleNodeConfig { @@ -124,7 +124,7 @@ export interface ShadowsocksNodeConfig extends SimpleNodeConfig { readonly port: number|string; readonly method: string; readonly password: string; - readonly 'udp-relay'?: 'true'|'false'; + readonly 'udp-relay'?: boolean; readonly obfs?: 'tls'|'http'; readonly 'obfs-host'?: string; } diff --git a/lib/utils/config.ts b/lib/utils/config.ts index 63b8999ef..bf7651565 100644 --- a/lib/utils/config.ts +++ b/lib/utils/config.ts @@ -6,6 +6,27 @@ import path from 'path'; import { CommandConfig } from '../types'; import { ensureConfigFolder } from './index'; +export const loadConfig = (cwd: string, configPath: string, override?: Partial): CommandConfig => { + const absPath = path.resolve(cwd, configPath); + + if (!fs.existsSync(absPath)) { + throw new Error(`配置文件 ${absPath} 不存在`); + } + + const userConfig = _.cloneDeep(require(absPath)); + + validateConfig(userConfig); + + if (override) { + return { + ...normalizeConfig(cwd, userConfig), + ...override, + }; + } + + return normalizeConfig(cwd, userConfig); +}; + export const normalizeConfig = (cwd: string, userConfig: Partial): CommandConfig => { const defaultConfig: Partial = { artifacts: [], diff --git a/lib/utils/index.ts b/lib/utils/index.ts index a8c692d0b..09d09fcbb 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -112,7 +112,7 @@ export const getShadowsocksJSONConfig = async (url: string, udpRelay: boolean): }; if (typeof udpRelay === 'boolean') { - nodeConfig['udp-relay'] = udpRelay ? 'true' : 'false'; + nodeConfig['udp-relay'] = udpRelay; } if (item.plugin === 'obfs-local') { const obfs = item.plugin_opts.match(/obfs=(\w+)/); @@ -162,7 +162,7 @@ export const getShadowsocksSubscription = async (url: string, udpRelay?: boolean method: userInfo[0], password: userInfo[1], ...(typeof udpRelay === 'boolean' ? { - 'udp-relay': udpRelay ? 'true' : 'false', + 'udp-relay': udpRelay, } : null), ...(pluginInfo['obfs-local'] ? { obfs: pluginInfo.obfs, @@ -451,7 +451,7 @@ export const getClashNodes = ( password: nodeConfig.password, port: nodeConfig.port, server: nodeConfig.hostname, - udp: nodeConfig['udp-relay'] === 'true', + udp: nodeConfig['udp-relay'] || false, ...(nodeConfig.obfs ? { plugin: 'obfs', 'plugin-opts': { @@ -849,27 +849,6 @@ export const decodeStringList = (stringList: ReadonlyArray): return result as T; }; -export const loadConfig = (cwd: string, configPath: string, override?: Partial): CommandConfig => { - const absPath = path.resolve(cwd, configPath); - - if (!fs.existsSync(absPath)) { - throw new Error(`文件 ${absPath} 不存在`); - } - - const userConfig = _.cloneDeep(require(absPath)); - - validateConfig(userConfig); - - if (override) { - return { - ...normalizeConfig(cwd, userConfig), - ...override, - }; - } - - return normalizeConfig(cwd, userConfig); -}; - export const normalizeClashProxyGroupConfig = ( nodeList: ReadonlyArray, customFilters: PlainObjectOf, diff --git a/test/class/ClashProvider.test.ts b/test/class/ClashProvider.test.ts index 516dca8c6..413e0ea77 100644 --- a/test/class/ClashProvider.test.ts +++ b/test/class/ClashProvider.test.ts @@ -13,7 +13,7 @@ test('getClashSubscription', async t => { port: 443, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true' + 'udp-relay': true }); t.deepEqual(config[1], { type: NodeTypeEnum.Shadowsocks, @@ -22,7 +22,7 @@ test('getClashSubscription', async t => { port: 443, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'false', + 'udp-relay': false, obfs: 'tls', 'obfs-host': 'www.bing.com' }); @@ -53,7 +53,7 @@ test('getClashSubscription', async t => { port: 443, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'false', + 'udp-relay': false, obfs: 'tls', 'obfs-host': 'example.com' }); @@ -69,7 +69,7 @@ test('getClashSubscription udpRelay', async t => { port: 443, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, }); t.deepEqual(config[1], { type: NodeTypeEnum.Shadowsocks, @@ -78,7 +78,7 @@ test('getClashSubscription udpRelay', async t => { port: 443, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, obfs: 'tls', 'obfs-host': 'www.bing.com' }); diff --git a/test/utils/utils.test.ts b/test/utils/utils.test.ts index 610739e9f..2c9518a54 100644 --- a/test/utils/utils.test.ts +++ b/test/utils/utils.test.ts @@ -32,7 +32,7 @@ test('getSurgeNodes', async t => { password: 'password', obfs: 'tls', 'obfs-host': 'example.com', - 'udp-relay': 'true', + 'udp-relay': true, }, { nodeName: 'Test Node 2', type: NodeTypeEnum.Shadowsocks, @@ -155,7 +155,7 @@ test('getClashNodes', async t => { password: 'password', obfs: 'tls', 'obfs-host': 'example.com', - 'udp-relay': 'true', + 'udp-relay': true, }, { nodeName: 'Test Node 2', type: NodeTypeEnum.Shadowsocks, @@ -251,7 +251,7 @@ test('getShadowsocksNodes', async t => { password: 'password', obfs: 'tls', 'obfs-host': 'gateway.icloud.com', - 'udp-relay': 'true', + 'udp-relay': true, }, ]; const txt1 = utils.getShadowsocksNodes(nodeList, 'GroupName'); @@ -355,7 +355,7 @@ test('getShadowsocksJSONConfig', async t => { port: 443, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, obfs: 'tls', 'obfs-host': 'gateway-carry.icloud.com', }); @@ -366,7 +366,7 @@ test('getShadowsocksJSONConfig', async t => { port: 444, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, }); t.deepEqual(config[2], { nodeName: '🇺🇸US 3', @@ -375,7 +375,7 @@ test('getShadowsocksJSONConfig', async t => { port: 445, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, obfs: 'tls', 'obfs-host': 'www.bing.com', }); @@ -386,7 +386,7 @@ test('getShadowsocksJSONConfig', async t => { port: 80, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, obfs: 'http', 'obfs-host': 'www.bing.com', }); @@ -625,7 +625,7 @@ test('getQuantumultNodes', t => { port: 443, method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, obfs: 'tls', 'obfs-host': 'gateway-carry.icloud.com', }, @@ -744,7 +744,7 @@ test('getShadowsocksSubscription with udp', async t => { port: '443', method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, obfs: 'tls', 'obfs-host': 'gateway-carry.icloud.com', }); @@ -755,7 +755,7 @@ test('getShadowsocksSubscription with udp', async t => { port: '443', method: 'chacha20-ietf-poly1305', password: 'password', - 'udp-relay': 'true', + 'udp-relay': true, }); });