ding-dong-bot.ts 5.8 KB
Newer Older
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
1
/**
2
 *   Wechaty - https://github.com/chatie/wechaty
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
3
 *
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
4
 *   @copyright 2016-2018 Huan LI <zixia@zixia.net>
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
5
 *
6 7 8 9 10 11 12 13 14 15 16
 *   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.
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
17 18
 *
 */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
19 20
import * as fs    from 'fs'
import * as path  from 'path'
21 22

/* tslint:disable:variable-name */
23 24 25
import { generate } from 'qrcode-terminal'
import { finis }    from 'finis'
import { FileBox }  from 'file-box'
26

27 28 29 30 31
/**
 * Change `import { ... } from '../'`
 * to     `import { ... } from 'wechaty'`
 * when you are runing with Docker or NPM instead of Git Source.
 */
32
import {
Huan (李卓桓)'s avatar
clean  
Huan (李卓桓) 已提交
33 34
  Wechaty,
  log,
35 36
  qrcodeValueToImageUrl,
}                         from '../src/'
37

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
38
const BOT_QR_CODE_IMAGE_FILE = path.resolve(
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
39 40 41 42
  __dirname,
  '../docs/images/bot-qr-code.png',
)

43 44
const bot = Wechaty.instance()

45
const welcome = `
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
46 47
| __        __        _           _
| \\ \\      / /__  ___| |__   __ _| |_ _   _
48 49 50
|  \\ \\ /\\ / / _ \\/ __| '_ \\ / _\` | __| | | |
|   \\ V  V /  __/ (__| | | | (_| | |_| |_| |
|    \\_/\\_/ \\___|\\___|_| |_|\\__,_|\\__|\\__, |
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
51
|                                     |___/
52 53

=============== Powered by Wechaty ===============
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
54
-------- https://github.com/chatie/wechaty --------
55
          Version: ${bot.version(true)}
56

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
57
I'm a bot, my superpower is talk in Wechat.
58 59 60 61

If you send me a 'ding', I will reply you a 'dong'!
__________________________________________________

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
62
Hope you like it, and you are very welcome to
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
63
upgrade me to more superpowers!
64 65 66 67 68 69

Please wait... I'm trying to login in...

`

console.log(welcome)
70

71
bot
Huan (李卓桓)'s avatar
clean  
Huan (李卓桓) 已提交
72
.on('logout'	, user => log.info('Bot', `${user.name()} logouted`))
73
.on('login'	  , user => {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
74
  log.info('Bot', `${user.name()} login`)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
75
  bot.say('Wechaty login').catch(console.error)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
76
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
77
.on('scan', (qrcode, status, data) => {
78 79 80 81
  generate(qrcode, { small: true })
  if (data) {
    console.log(data)
  }
82 83 84
  console.log(qrcodeValueToImageUrl(qrcode))
  console.log('^^^ Online QR Code Image URL ^^^ ')
  console.log(`[${status}] ${qrcode} Scan QR Code above url to log in: `)
85
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
86
.on('message', async msg => {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
87
  try {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
88
    console.log(msg.toString())
89

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
90
    if (/^(ding|ping|bing|code)$/i.test(msg.text()) /*&& !msg.self()*/) {
91 92 93
      /**
       * 1. reply 'dong'
       */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
94
      log.info('Bot', 'REPLY: dong')
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
95
      await msg.say('dong')
96

97 98 99 100
      const joinWechaty =  `Join Wechaty Developers' Community\n\n` +
                            `Wechaty is used in many ChatBot projects by hundreds of developers.\n\n` +
                            `If you want to talk with other developers, just scan the following QR Code in WeChat with secret code: wechaty,\n\n` +
                            `you can join our Wechaty Developers' Home at once`
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
101
      await msg.say(joinWechaty)
102 103 104 105

      /**
       * 2. reply qrcode image
       */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
106
      // const fileBox = FileBox.packLocal(BOT_QR_CODE_IMAGE_FILE)
107
      const fileBox = FileBox.fromStream(
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
108 109 110
        fs.createReadStream(BOT_QR_CODE_IMAGE_FILE),
        BOT_QR_CODE_IMAGE_FILE,
      )
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
111

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
112
      log.info('Bot', 'REPLY: %s', fileBox.toString())
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
113
      await msg.say(fileBox)
114 115 116 117

      /**
       * 3. reply 'scan now!'
       */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
118
      await msg.say('Scan now, because other Wechaty developers want to talk with you too!\n\n(secret code: wechaty)')
119

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
120
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
121 122
  } catch (e) {
    log.error('Bot', 'on(message) exception: %s' , e)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
123
    console.error(e)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
124
  }
125 126
})

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
127 128
bot.on('error', async e => {
  log.error('Bot', 'error: %s', e)
129
  if (bot.logonoff()) {
130 131
    await bot.say('Wechaty error: ' + e.message).catch(console.error)
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
132
  // await bot.stop()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
133 134
})

135 136 137 138 139 140 141 142 143 144 145 146
let killChrome: NodeJS.SignalsListener

bot.start()
.then(() => {
  const listenerList = process.listeners('SIGINT')
  for (const listener of listenerList) {
    if (listener.name === 'killChrome') {
      process.removeListener('SIGINT', listener)
      killChrome = listener
    }
  }
})
ruiruibupt's avatar
ruiruibupt 已提交
147
.catch(async e => {
148
  log.error('Bot', 'start() fail: %s', e)
ruiruibupt's avatar
ruiruibupt 已提交
149
  await bot.stop()
150 151 152
  process.exit(-1)
})

153
let quiting = false
ruiruibupt's avatar
ruiruibupt 已提交
154
finis(async (code, signal) => {
155 156 157 158 159 160 161
  log.info('Bot', 'finis(%s, %s)', code, signal)

  if (!bot.logonoff()) {
    log.info('Bot', 'finis() bot had been already stopped')
    doExit(code)
  }

162
  if (quiting) {
163
    log.warn('Bot', 'finis() already quiting... return and wait...')
164 165
    return
  }
166

167
  quiting = true
168 169 170
  let done = false
  // let checkNum = 0

171
  const exitMsg = `Wechaty will exit ${code} because of ${signal} `
172 173

  log.info('Bot', 'finis() broadcast quiting message for bot')
ruiruibupt's avatar
ruiruibupt 已提交
174
  await bot.say(exitMsg)
175 176 177 178 179 180 181 182 183 184 185 186 187 188
      // .then(() => bot.stop())
      .catch(e => log.error('Bot', 'finis() catch rejection: %s', e))
      .then(() => done = true)

  setImmediate(checkForExit)

  function checkForExit() {
    // if (checkNum++ % 100 === 0) {
    log.info('Bot', 'finis() checkForExit() checking done: %s', done)
    // }
    if (done) {
      log.info('Bot', 'finis() checkForExit() done!')
      setTimeout(() => doExit(code), 1000)  // delay 1 second
      return
189
    }
190 191 192 193 194
    // death loop to wait for `done`
    // process.nextTick(checkForExit)
    // setImmediate(checkForExit)
    setTimeout(checkForExit, 100)
  }
195
})
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

function doExit(code: number): void {
  log.info('Bot', 'doExit(%d)', code)
  if (killChrome) {
    killChrome('SIGINT')
  }
  process.exit(code)
}

// process.on('SIGINT', function() {
//   console.log('Nice SIGINT-handler')
//   const listeners = process.listeners('SIGINT')
//   for (let i = 0; i < listeners.length; i++) {
//       console.log(listeners[i].toString())
//   }
// })