diff --git a/docs/guide/custom-provider.md b/docs/guide/custom-provider.md index 6893b8f37..2f2c34c1c 100644 --- a/docs/guide/custom-provider.md +++ b/docs/guide/custom-provider.md @@ -351,7 +351,7 @@ module.exports = { 'udp-relay': false, // 可选, 仅 Clash 支持 sni: 'example.com', // 可选, 仅 Surge 支持 tfo: true, // 可选, 仅 Surge 支持 - clientCert: 'item' // 可选, 仅 Surge 支持, 参考 https://github.com/Blankwonder/Surge-Manual/blob/master/release-note/surge-mac.md#version-250 + clientCert: 'item' // 可选, 仅 Surge 支持, 参考 https://github.com/Blankwonder/Surge-Manual/blob/master/release-note/surge-mac.md#version-250 } ``` @@ -492,7 +492,8 @@ module.exports = { ### provider.startPort - 类型: `Number` -- 默认值: `61100` + +在调用 `getSurgeNodes` 时会强制要求设置该值。建议大于 10000。 在生成 Surge 的 Shadowsocksr 和 Vmess 配置文件时,本地监听端口会根据此配置递增。这样做的好处是切换配置文件时不会遇到端口冲突。同一个 Provider 被用在不同的 Artifact 中也会进行递增。 diff --git a/lib/provider/Provider.ts b/lib/provider/Provider.ts index 52972e8da..61372d83f 100644 --- a/lib/provider/Provider.ts +++ b/lib/provider/Provider.ts @@ -3,11 +3,10 @@ import Joi from '@hapi/joi'; import { ProviderConfig, SupportProviderEnum, - PossibleNodeConfigType, SubscriptionUserinfo, + PossibleNodeConfigType, + SubscriptionUserinfo, } from '../types'; -let globalPort = 61100; - export default class Provider { public readonly type: SupportProviderEnum; public readonly nodeFilter?: ProviderConfig['nodeFilter']; @@ -19,38 +18,56 @@ export default class Provider { public readonly tfo?: boolean; public readonly mptcp?: boolean; public readonly renameNode?: ProviderConfig['renameNode']; - public readonly relayUrl?: boolean|string; + public readonly relayUrl?: boolean | string; // 是否支持在订阅中获取用户流量信息 public supportGetSubscriptionUserInfo: boolean; - // External Provider 的起始端口,Surge 配置中使用 - private startPort?: number; + public startPort?: number; constructor(public name: string, config: ProviderConfig) { const schema = Joi.object({ type: Joi.string() .valid(...Object.values(SupportProviderEnum)) .required(), - nodeFilter: Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() })), - netflixFilter: Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() })), - youtubePremiumFilter: Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() })), - customFilters: Joi.object() - .pattern( - Joi.string(), - Joi.any().allow(Joi.function(), Joi.object({ filter: Joi.function(), supportSort: Joi.boolean().strict() })) - ), + nodeFilter: Joi.any().allow( + Joi.function(), + Joi.object({ + filter: Joi.function(), + supportSort: Joi.boolean().strict(), + }) + ), + netflixFilter: Joi.any().allow( + Joi.function(), + Joi.object({ + filter: Joi.function(), + supportSort: Joi.boolean().strict(), + }) + ), + youtubePremiumFilter: Joi.any().allow( + Joi.function(), + Joi.object({ + filter: Joi.function(), + supportSort: Joi.boolean().strict(), + }) + ), + customFilters: Joi.object().pattern( + Joi.string(), + Joi.any().allow( + Joi.function(), + Joi.object({ + filter: Joi.function(), + supportSort: Joi.boolean().strict(), + }) + ) + ), addFlag: Joi.boolean().strict(), removeExistingFlag: Joi.boolean().strict(), mptcp: Joi.boolean().strict(), tfo: Joi.boolean().strict(), startPort: Joi.number().integer().min(1024).max(65535), - relayUrl: [ - Joi.boolean().strict(), - Joi.string(), - ], + relayUrl: [Joi.boolean().strict(), Joi.string()], renameNode: Joi.function(), - }) - .unknown(); + }).unknown(); const { error } = schema.validate(config); @@ -74,7 +91,7 @@ export default class Provider { 'startPort', 'renameNode', 'relayUrl', - ].forEach(key => { + ].forEach((key) => { this[key] = config[key]; }); } @@ -83,11 +100,13 @@ export default class Provider { if (this.startPort) { return this.startPort++; } - return globalPort++; + return 0; } // istanbul ignore next - public async getSubscriptionUserInfo(): Promise { + public async getSubscriptionUserInfo(): Promise< + SubscriptionUserinfo | undefined + > { throw new Error('此 Provider 不支持该功能'); } diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 2a5bbbbb3..92f3842d1 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -321,6 +321,12 @@ export const getSurgeNodes = function ( `local-port = ${config.localPort}`, ]; + if (typeof config.provider?.startPort === 'undefined') { + throw new Error( + `为 Surge 生成 SSR 配置时必须为 Provider ${config.provider?.name} 设置 startPort` + ); + } + if (config.hostnameIp && config.hostnameIp.length) { configString.push( ...config.hostnameIp.map((item) => `addresses = ${item}`) @@ -404,6 +410,12 @@ export const getSurgeNodes = function ( ); } + if (typeof config.provider?.startPort === 'undefined') { + throw new Error( + `为 Surge 生成 Vmess 配置时必须为 Provider ${config.provider?.name} 设置 startPort` + ); + } + const jsonFileName = `v2ray_${config.localPort}_${config.hostname}_${config.port}.json`; const jsonFilePath = join(ensureConfigFolder(), jsonFileName); const jsonFile = formatV2rayConfig(