UNPKG

surgio

Version:

查看完整使用文档,前往 [surgio.royli.dev](https://surgio.royli.dev)。

193 lines 16.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; // istanbul ignore file const assert_1 = __importDefault(require("assert")); const chalk_1 = __importDefault(require("chalk")); const common_bin_1 = __importDefault(require("common-bin")); const debug_1 = __importDefault(require("debug")); const execa_1 = __importDefault(require("execa")); const get_port_1 = __importDefault(require("get-port")); const inquirer_1 = __importDefault(require("inquirer")); const merge_stream_1 = __importDefault(require("merge-stream")); const mz_1 = require("mz"); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const shelljs_1 = __importDefault(require("shelljs")); const speedtest_net_1 = __importDefault(require("speedtest-net")); const winston_1 = __importStar(require("winston")); const types_1 = require("../types"); const utils_1 = require("../utils"); const getProvider_1 = __importDefault(require("../utils/getProvider")); const { combine, timestamp, printf } = winston_1.format; const speedDebug = debug_1.default('speed'); const clashDebug = debug_1.default('speed:clash'); class SpeedCommand extends common_bin_1.default { constructor(rawArgv) { super(rawArgv); this.logger = this.getTypedConsoleLogger('speed'); this.usage = 'Usage: surgio speed [provider]'; this.options = { config: { alias: 'c', default: './surgio.conf.js', }, }; } get description() { return 'Speed test Shadowsocks server.'; } async run(ctx) { assert_1.default(ctx.argv._[0], 'No provider specified.'); const providerName = ctx.argv._[0]; const config = utils_1.loadConfig(ctx.cwd, ctx.argv.config); const filePath = path_1.default.resolve(config.providerDir, `./${providerName}.js`); const file = mz_1.fs.existsSync(filePath) ? require(filePath) : new Error('Provider file cannot be found.'); if (file instanceof Error) { throw file; } const provider = getProvider_1.default(file); const nodeList = await provider.getNodeList(); const nodeConfig = await this.promptSelections(nodeList); await this.runTest(nodeConfig); } async runTest(json) { const configDir = path_1.default.join(os_1.default.tmpdir(), 'surgio-config'); const configPath = path_1.default.join(configDir, 'config.yaml'); const clashBin = shelljs_1.default.which('clash'); assert_1.default(json.type === 'shadowsocks', 'Only Shadowsocks server config is supported.'); assert_1.default(clashBin, 'No runnable clash found.'); this.httpPort = await get_port_1.default({ port: 54455 }); this.socksPort = await get_port_1.default({ port: 54456 }); this.clashConfig = this.getClashConfig(json, this.httpPort, this.socksPort); speedDebug('configDir: %s', configDir); speedDebug('httpPort: %s', this.httpPort); this.logger.info('Starting Clash.'); if (!mz_1.fs.existsSync(configDir)) { await mz_1.fs.mkdir(configDir); } await mz_1.fs.writeFile(configPath, utils_1.toYaml(this.clashConfig)); this.clashProcess = execa_1.default(clashBin.toString(), ['-d', configDir]); await this.waitClashReady(); await this.speedTest(); this.clashProcess.kill(); } waitForInput() { return new Promise(resolve => { let result = ''; function onReadable() { const chunk = process.stdin.read(); if (chunk !== null) { result += chunk; } } function onEnd() { process.stdin.off('readable', onReadable); process.stdin.off('end', onEnd); resolve(result); } process.stdin.on('readable', onReadable); process.stdin.on('end', onEnd); }); } waitClashReady() { assert_1.default(this.clashProcess, 'Clash is not attached yet.'); return new Promise(resolve => { const proc = this.clashProcess; const stdout = merge_stream_1.default(proc.stderr, proc.stdout); function onData(chunk) { if (chunk !== null) { const text = chunk.toString().trim(); if (text) { clashDebug(text); if (text.indexOf('HTTP proxy listening') > -1) { resolve(); } } } } stdout.on('data', onData); }); } speedTest() { this.logger.info('Looking for the best test server.'); return new Promise((resolve, reject) => { const testcase = speedtest_net_1.default({ maxTime: 10000, proxy: `http://localhost:${this.httpPort}`, }); testcase.on('bestservers', servers => { const server = servers[0]; this.logger.info(`Endpoint: ${server.cc} - ${server.sponsor}`); this.logger.info(`Ping: ${chalk_1.default.blueBright(server.bestPing.toFixed(2) + 'ms')}`); this.logger.info('Waiting for final results.'); }); testcase.on('data', data => { this.logger.info('=== Results ==='); this.logger.info(`Your ISP: ${data.client.country} - ${data.client.isp}`); this.logger.info(`Download: ${chalk_1.default.blueBright(data.speeds.download) + 'Mbps'}`); this.logger.info(`Upload: ${chalk_1.default.blueBright(data.speeds.upload) + 'Mbps'}`); }); testcase.on('error', err => { reject(err); }); testcase.on('done', () => { resolve(); }); }); } getClashConfig(config, httpPort, socksPort) { return { port: httpPort, 'socks-port': socksPort, mode: 'Rule', 'log-level': 'info', Proxy: utils_1.getClashNodes([config]), Rule: [ `FINAL,${config.nodeName}` ], }; } getTypedConsoleLogger(loggerName) { // tslint:disable-next-line:no-shadowed-variable const myFormat = printf(({ level, message, timestamp }) => { return `${timestamp} [${chalk_1.default.cyan(loggerName)}] ${level}: ${message}`; }); return winston_1.default.createLogger({ level: 'info', transports: [new winston_1.default.transports.Console()], format: combine(timestamp(), myFormat), }); } async promptSelections(arr) { const choices = arr .filter(item => { return item.type === types_1.NodeTypeEnum.Shadowsocks; }) .map(item => { return { name: `${item.nodeName} - ${chalk_1.default.gray(item.hostname + ':' + item.port)}`, value: item, }; }); const answer = await inquirer_1.default.prompt([ { name: 'server', message: 'Which server?', type: 'list', choices, } ]); return answer.server; } } module.exports = SpeedCommand; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BlZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvY29tbWFuZC9zcGVlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBLHVCQUF1QjtBQUN2QixvREFBNEI7QUFDNUIsa0RBQTBCO0FBRTFCLDREQUFpQztBQUNqQyxrREFBMEI7QUFDMUIsa0RBQTBCO0FBQzFCLHdEQUErQjtBQUMvQix3REFBZ0M7QUFDaEMsZ0VBQWlDO0FBQ2pDLDJCQUF3QjtBQUN4Qiw0Q0FBb0I7QUFDcEIsZ0RBQXdCO0FBQ3hCLHNEQUE4QjtBQUM5QixrRUFBc0M7QUFDdEMsbURBQWtEO0FBR2xELG9DQUF1RjtBQUN2RixvQ0FBNkQ7QUFDN0QsdUVBQStDO0FBRS9DLE1BQU0sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxHQUFHLGdCQUFNLENBQUM7QUFDOUMsTUFBTSxVQUFVLEdBQUcsZUFBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ2xDLE1BQU0sVUFBVSxHQUFHLGVBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztBQUV4QyxNQUFNLFlBQWEsU0FBUSxvQkFBTztJQVFoQyxZQUFZLE9BQU87UUFDakIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBUFQsV0FBTSxHQUFXLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQVEzRCxJQUFJLENBQUMsS0FBSyxHQUFHLGdDQUFnQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixNQUFNLEVBQUU7Z0JBQ04sS0FBSyxFQUFFLEdBQUc7Z0JBQ1YsT0FBTyxFQUFFLGtCQUFrQjthQUM1QjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQsSUFBVyxXQUFXO1FBQ3BCLE9BQU8sZ0NBQWdDLENBQUM7SUFDMUMsQ0FBQztJQUVNLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRztRQUNsQixnQkFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMs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