UNPKG

node-red-contrib-voice-assistant

Version:

一个小度-小爱-猫精音箱控制NODE-RED自定义设备的节点

251 lines (250 loc) 9.52 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const os_1 = __importDefault(require("os")); const got_1 = __importDefault(require("got")); const decompress_zip_1 = __importDefault(require("decompress-zip")); const ini_1 = __importDefault(require("ini")); const child_process_1 = require("child_process"); const sleep = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; class FrpClient { constructor() { this.url = ''; this.cacheUrl = path_1.default.join(__dirname, 'frpc.zip'); this.target = path_1.default.join(__dirname, 'frpc'); this.closeFlag = false; this.url = this.getCdnUrl(); this.cacheUrl = path_1.default.join(__dirname, 'frpc.zip'); //frp路径 this.target = path_1.default.join(__dirname, 'frpc'); this.config = { common: { server_addr: 'yyddyym.top', server_port: 7000, pritoken: '', }, }; } getCdnUrl() { const arch = os_1.default.platform() + os_1.default.arch(); const cdn = 'https://hasskit.com/'; const cdnPath = 'public/frp/'; const cdnFiles = { linuxarm: cdn + cdnPath + 'linux-arm.zip', linuxarm64: cdn + cdnPath + 'linux-arm64.zip', linuxia32: cdn + cdnPath + 'linux-386.zip', linuxx64: cdn + cdnPath + 'linux-amd64.zip', }; const url = cdnFiles[arch]; if (!url) { console.error('frpc - platform ' + arch + ' is not supported.'); return; } return url; } download() { const downloadStream = got_1.default.stream(this.url + ''); const fileWriteStream = fs_1.default.createWriteStream(this.cacheUrl); return new Promise((resolve, reject) => { downloadStream .on('downloadProgress', (info) => { this._ondownloadProgress && this._ondownloadProgress((info.percent.toFixed(2) * 100).toString()); }) .on('error', (err) => { resolve(null); }); fileWriteStream.on('finish', () => { resolve(true); console.log('下载完成'); }); downloadStream.pipe(fileWriteStream); }); } set onDownloadProgress(fn) { this._ondownloadProgress = fn; } removeFrp() { fs_1.default.unlinkSync(this.target); } //解包 extract() { return new Promise((resolve) => { const zip = new decompress_zip_1.default(this.cacheUrl); zip.extract({ path: __dirname }); zip.once('error', error); zip.once('extract', () => { fs_1.default.chmodSync(this.target, 755); if (!fs_1.default.existsSync(this.target) || fs_1.default.statSync(this.target).size <= 0) { return error(new Error('corrupted file ' + this.target)); } console.log('frp - binary unpacked to ' + this.target); resolve(null); fs_1.default.unlinkSync(this.cacheUrl); }); function error(e) { console.error('ngrok - error unpacking binary', e); resolve(e); } }); } //frp运行 createSection(ports, options) { options.forEach((it, index) => { if (index <= ports.length - 1) { this.config[ports[index].proxyName] = { type: 'tcp', local_ip: it.url, local_port: it.port, remote_port: ports[index].port, }; } }); } createConfig() { fs_1.default.writeFileSync(path_1.default.join(__dirname, 'frpc.ini'), ini_1.default.stringify(this.config)); } handleData(data) { const obj = { code: 0, msg: data, tunnel_addr: '', local_addr: '' }; console.log('handleData', data); const proxyname = /\[([0-9a-z]{32})\]/.exec(data); if (data.includes('service.go:104')) { obj.code = 401; obj.msg = 'frp连接失败'; } else if (data.includes('service.go:244')) { obj.code = 244; obj.msg = 'frp连接成功'; } else if (data.includes('control.go:162')) { obj.code = 401; obj.local_addr = this.config[proxyname[1]].local_ip + ':' + this.config[proxyname[1]].local_port; obj.msg = '远程端口占用'; } else if (data.includes('control.go:164')) { //console.log('164', proxyname, data); obj.local_addr = this.config[proxyname[1]].local_ip + ':' + this.config[proxyname[1]].local_port; obj.tunnel_addr = this.config.common.server_addr + ':' + this.config[proxyname[1]].remote_port; obj.code = 200; obj.msg = '端口映射成功'; } return obj; } setup(node) { return __awaiter(this, void 0, void 0, function* () { /* console.log(node.options) node.options = [ { url: '192.168.1.132', port: 8123 }, { url: '192.168.1.132', port: 1880 }, ]; */ for (let i = 0; i < node.options.length; i++) { if (node.options[i].url.trim() === '' && node.options[i].port.trim() === '') { return { msg: '映射参数未配配置' }; } } const topic = node.brokerConn.mqttClient.pubTopic + '/getFrpData'; node.brokerConn.mqttClient._client.publish(topic, `{"id":"${(Math.random() * 42949672950000000).toString(16)}"}`); yield sleep(1000); if (!this.authObj) { console.log('认证失败'); return { msg: '获取参数失败' }; } this.createSection(this.authObj.frpcPort, node.options); this.config.common.pritoken = this.authObj.token; this.createConfig(); yield sleep(500); if (!fs_1.default.existsSync(this.target) || fs_1.default.statSync(this.target).size <= 0) { this.onDownloadProgress = function (msg) { node.status({ fill: 'green', shape: 'dot', text: '下载进度:' + msg + '%' }); }; if (!this.url) return; const status = yield this.download(); if (!status) { node.status({ fill: 'red', shape: 'dot', text: '下载失败' }); this.removeFrp(); return; } const extract = yield this.extract(); if (!extract) { return; } else { this.removeFrp(); return { msg: '解包失败' }; } } return; }); } run(cb) { this.child = (0, child_process_1.spawn)(this.target, ['-c', path_1.default.join(__dirname, 'frpc.ini')]); this.child.on('error', function (err) { console.log('error', err); }); this.child.on('close', (code) => { this.emitClose && this.emitClose(); }); this.child.on('exit', () => { cb && cb({ code: 104, msg: 'frp断开连接' }); if (!this.closeFlag) setTimeout(() => { this.run(cb); }, 3000); }); this.child.stdout.on('data', (msg) => { msg.toString() .trim() .split('\n') .forEach((it) => { const msgObj = this.handleData(it); cb && cb(msgObj); }); }); } start(cb) { try { this.run(cb); return true; } catch (_a) { console.log(_a); return false; } } reconnect() { this.close(() => { setTimeout(() => { this.start(null); }, 3000); }); } close(done) { try { (0, child_process_1.spawn)('kill', ['-9', this.child.pid.toString()]); this.closeFlag = true; if (done) { this.emitClose(); done(); } } catch (_a) { done && done(); } } } exports.default = FrpClient;