UNPKG

@juzi/wechaty

Version:

Wechaty is a RPA SDK for Chatbot Makers.

217 lines 7.39 kB
/** * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * * @copyright 2016 Huan LI (李卓桓) <https://github.com/huan>, and * Wechaty Contributors <https://github.com/wechaty>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { StateSwitch } from 'state-switch'; import { PuppetServer, } from '@juzi/wechaty-puppet-service'; import { DISABLE_IO_WS, log, } from './config.js'; import { Io } from './io.js'; const DEFAULT_IO_CLIENT_OPTIONS = { port: 8788, }; export class IoClient { /** * Huan(20161026): keep io `null-able` or not? * Huan(202002): make it optional. */ io; puppetServer; state; options; constructor(options) { log.verbose('IoClient', 'constructor({%s})', Object.keys(options) .map(key => { return `${key}:${options[key]}`; }) .reduce((acc, cur) => `${acc}, ${cur}`)); const normalizedOptions = { ...DEFAULT_IO_CLIENT_OPTIONS, ...options, }; this.options = normalizedOptions; this.state = new StateSwitch('IoClient', { log }); } async startPuppetServer() { log.verbose('IoClient', 'startPuppetServer()'); if (this.puppetServer) { throw new Error('puppet server exists'); } const options = { endpoint: '0.0.0.0:' + this.options.port, /** * Huan(202110): FIXME: remove the any * by updating the puppet-service server code * to use PuppetInterface */ puppet: this.options.wechaty.puppet, token: this.options.token, }; this.puppetServer = new PuppetServer(options); await this.puppetServer.start(); } async stopPuppetServer() { log.verbose('IoClient', 'stopPuppetServer()'); if (!this.puppetServer) { log.error('IoClient', 'stopPuppetServer() this.puppetServer is `undefined`'); return; } await this.puppetServer.stop(); this.puppetServer = undefined; } async start() { log.verbose('IoClient', 'start()'); if (this.state.active()) { log.warn('IoClient', 'start() with a on state, wait and return'); await this.state.stable('active'); return; } this.state.active('pending'); try { await this.hookWechaty(this.options.wechaty); if (!DISABLE_IO_WS) { await this.startIo(); } await this.options.wechaty.start(); await this.startPuppetServer(); this.state.active(true); } catch (e) { log.error('IoClient', 'start() exception: %s', e.message); this.state.inactive(true); throw e; } } async hookWechaty(wechaty) { log.verbose('IoClient', 'hookWechaty()'); if (this.state.inactive()) { const e = new Error('state.off() is true, skipped'); log.warn('IoClient', 'initWechaty() %s', e.message); throw e; } wechaty .on('login', user => log.info('IoClient', `${user.name()} logged in`)) .on('logout', user => log.info('IoClient', `${user.name()} logged out`)) .on('message', msg => this.onMessage(msg)) .on('scan', (url, code) => { log.info('IoClient', [ `[${code}] ${url}`, `Online QR Code Image: https://wechaty.js.org/qrcode/${encodeURIComponent(url)}`, ].join('\n')); }); } async startIo() { log.verbose('IoClient', 'startIo() with token %s', this.options.token); if (this.state.inactive()) { const e = new Error('startIo() state.off() is true, skipped'); log.warn('IoClient', e.message); throw e; } if (this.io) { throw new Error('io exists'); } this.io = new Io({ servicePort: this.options.port, token: this.options.token, wechaty: this.options.wechaty, }); try { await this.io.start(); } catch (e) { log.verbose('IoClient', 'startIo() init fail: %s', e.message); throw e; } } async stopIo() { log.verbose('IoClient', 'stopIo()'); if (!this.io) { log.warn('IoClient', 'stopIo() io does not exist'); return; } await this.io.stop(); this.io = undefined; } async onMessage(msg) { log.verbose('IoClient', 'onMessage(%s)', msg); // const from = m.from() // const to = m.to() // const content = m.toString() // const room = m.room() // log.info('Bot', '%s<%s>:%s' // , (room ? '['+room.topic()+']' : '') // , from.name() // , m.toStringDigest() // ) // if (/^wechaty|chatie|botie/i.test(m.text()) && !m.self()) { // await m.say('https://www.chatie.io') // .then(_ => log.info('Bot', 'REPLIED to magic word "chatie"')) // } } async stop() { log.verbose('IoClient', 'stop()'); this.state.inactive('pending'); if (!DISABLE_IO_WS) { await this.stopIo(); } await this.stopPuppetServer(); await this.options.wechaty.stop(); this.state.inactive(true); // XXX 20161026 // this.io = null } async restart() { log.verbose('IoClient', 'restart()'); try { await this.stop(); await this.start(); } catch (e) { log.error('IoClient', 'restart() exception %s', e.message); throw e; } } async quit() { log.verbose('IoClient', 'quit()'); if (this.state.inactive() === 'pending') { log.warn('IoClient', 'quit() with state.off() = `pending`, skipped'); throw new Error('quit() with state.off() = `pending`'); } this.state.inactive('pending'); try { // if (this.options.wechaty) { await this.options.wechaty.stop(); // this.wechaty = null // } else { log.warn('IoClient', 'quit() no this.wechaty') } if (this.io) { await this.io.stop(); // this.io = null } else { log.warn('IoClient', 'quit() no this.io'); } } catch (e) { log.error('IoClient', 'exception: %s', e.message); throw e; } finally { this.state.inactive(true); } } } //# sourceMappingURL=io-client.js.map