Skip to content

Commit

Permalink
feat(Provider): v2rayn_subscribe add compatible mode
Browse files Browse the repository at this point in the history
  • Loading branch information
broven committed Mar 25, 2020
1 parent abc424a commit 534e883
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 8 deletions.
7 changes: 7 additions & 0 deletions docs/guide/custom-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ module.exports = {
- 如果你正在使用 [DlerCloud](https://dlercloud.com/auth/register?affid=45071),可以使用「通用」类型的订阅地址
:::

### compatibleMode

- 类型: `boolean`
- 默认值: `false`

部分机场提供的订阅地址不符合标准,提供一个兼容模式进行解析。

## clash <Badge text="推荐" vertical="middle" />

:::warning 注意
Expand Down
14 changes: 7 additions & 7 deletions lib/provider/V2rayNSubscribeProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import Provider from './Provider';

export default class V2rayNSubscribeProvider extends Provider {
private readonly _url: string;

private readonly _compatibleMode?: boolean;
constructor(name: string, config: V2rayNSubscribeProviderConfig) {
super(name, config);

this._compatibleMode = config.compatibleMode;
const schema = Joi.object({
url: Joi
.string()
Expand Down Expand Up @@ -46,15 +46,16 @@ export default class V2rayNSubscribeProvider extends Provider {
}

public getNodeList(): ReturnType<typeof getV2rayNSubscription> {
return getV2rayNSubscription(this.url);
return getV2rayNSubscription(this.url, this._compatibleMode);
}
}

export const getV2rayNSubscription = async (
url: string,
isCompatibleMode: boolean
): Promise<ReadonlyArray<VmessNodeConfig>> => {
assert(url, '未指定订阅地址 url');

if (isCompatibleMode) { logger.warn('运行在兼容模式,请注意生成的节点是否正确。'); }
async function requestConfigFromRemote(): Promise<ReadonlyArray<VmessNodeConfig>> {
const response = ConfigCache.has(url) ? ConfigCache.get(url) : await (async () => {
const res = await got.get(url, {
Expand All @@ -74,10 +75,9 @@ export const getV2rayNSubscription = async (
const json = JSON.parse(fromBase64(item.replace('vmess://', '')));

// istanbul ignore next
if (!json.v || Number(json.v) !== 2) {
throw new Error(`该订阅 ${url} 可能不是一个有效的 V2rayN 订阅。请参考 http://bit.ly/2N4lZ8X 进行排查`);
if (!isCompatibleMode && (!json.v || Number(json.v) !== 2)) {
throw new Error(`该订阅 ${url} 可能不是一个有效的 V2rayN 订阅。请参考 http://bit.ly/2N4lZ8X 进行排查, 或者将解析模式改为兼容模式`);
}

// istanbul ignore next
if (['kcp', 'http'].indexOf(json.net) > -1) {
logger.warn(`不支持读取 network 类型为 ${json.net} 的 Vmess 节点,节点 ${json.ps} 会被省略`);
Expand Down
21 changes: 20 additions & 1 deletion lib/provider/__tests__/V2rayNSubscribeProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test('V2rayNSubscribeProvider', async t => {

test('getV2rayNSubscription', async t => {
const url = 'http://example.com/test-v2rayn-sub.txt';
const configList = await getV2rayNSubscription(url);
const configList = await getV2rayNSubscription(url, false);

t.deepEqual(configList[0], {
alterId: '64',
Expand Down Expand Up @@ -44,3 +44,22 @@ test('getV2rayNSubscription', async t => {
uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
});
});

test('getV2rayNSubscription compatible mode', async t => {
const url = 'http://example.com/test-v2rayn-sub-compatible.txt';
const configList = await getV2rayNSubscription(url, true);

t.deepEqual(configList[0], {
alterId: '64',
host: 'example.com',
hostname: '1.1.1.1',
method: 'auto',
network: 'ws',
nodeName: '测试 1',
path: '/',
port: 8080,
tls: false,
type: NodeTypeEnum.Vmess,
uuid: '1386f85e-657b-4d6e-9d56-78badb75e1fd',
});
});
1 change: 1 addition & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export interface ShadowsocksrSubscribeProviderConfig extends ProviderConfig {

export interface V2rayNSubscribeProviderConfig extends ProviderConfig {
readonly url: string;
readonly compatibleMode?: boolean;
}

export interface ClashProviderConfig extends ProviderConfig {
Expand Down
1 change: 1 addition & 0 deletions test/asset/test-v2rayn-sub-compatible.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dm1lc3M6Ly9leUp3Y3lJNkl1YTFpK2l2bFNBeElpd2lZV1JrSWpvaU1TNHhMakV1TVNJc0luQnZjblFpT2pnd09EQXNJbWxrSWpvaU1UTTRObVk0TldVdE5qVTNZaTAwWkRabExUbGtOVFl0TnpoaVlXUmlOelZsTVdaa0lpd2lZV2xrSWpvaU5qUWlMQ0p1WlhRaU9pSjNjeUlzSW5SNWNHVWlPaUp1YjI1bElpd2lhRzl6ZENJNkltVjRZVzF3YkdVdVkyOXRJaXdpY0dGMGFDSTZJbHd2SWl3aWJYVjRJanA3SW1WdVlXSnNaV1FpT2lKbVlXeHpaU0o5ZlE9PQ==
7 changes: 7 additions & 0 deletions test/stub-axios.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ const scope = nock('http://example.com')
encoding: 'utf8',
})
)
.get(/\/test-v2rayn-sub-compatible\.txt/)
.reply(
200,
fs.readFileSync(path.join(__dirname, 'asset/test-v2rayn-sub-compatible.txt'), {
encoding: 'utf8',
})
)
.get(/\/netflix\.list/)
.reply(
200,
Expand Down

0 comments on commit 534e883

Please sign in to comment.