surgio
Version:
查看完整使用文档,前往 [surgio.royli.dev](https://surgio.royli.dev)。
193 lines • 16.5 kB
JavaScript
;
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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