tuling123-bot.ts 3.6 KB
Newer Older
1
/**
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
2
 *
3 4 5 6 7 8 9 10 11 12
 * Wechaty bot use a Tuling123.com brain
 *
 * Apply your own tuling123.com API_KEY
 * at: http://www.tuling123.com/html/doc/api.html
 *
 * Enjoy!
 *
 * Wechaty - https://github.com/zixia/wechaty
 *
 */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
13 14
/* tslint:disable:no-var-requires */
/* tslint:disable:variable-name */
15 16
const QrcodeTerminal  = require('qrcode-terminal')
const Tuling123       = require('tuling123-client')
17

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
18 19 20 21 22 23 24 25
import { EventEmitter } from 'events'

import {
    Config
  , Wechaty
  , log
} from '../'

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
26
// log.level = 'verbose'
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
27
// log.level = 'silly'
28

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
29
/**
30 31
 *
 * Apply Your Own Tuling123 Developer API_KEY at:
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
32
 * http://www.tuling123.com
33
 *
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
34
 */
35 36 37
const TULING123_API_KEY = '18f25157e0446df58ade098479f74b21'
const brain = new Tuling123(TULING123_API_KEY)

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
38
const bot = Wechaty.instance({ profile: Config.DEFAULT_PROFILE })
39 40 41 42

console.log(`
Welcome to Tuling Wechaty Bot.
Tuling API: http://www.tuling123.com/html/doc/api.html
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
43

44 45
Notice: This bot will only active in the room which name contains 'wechaty'.
/* if (/Wechaty/i.test(room.get('name'))) { */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
46

47 48 49
Loading...
`)

50
bot
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
51
.on('login'  , user => log.info('Bot', `bot login: ${user}`))
52
.on('logout' , e => log.info('Bot', 'bot logout.'))
53
.on('scan', (url, code) => {
54 55 56 57 58
  if (!/201|200/.test(String(code))) {
    let loginUrl = url.replace(/\/qrcode\//, '/l/')
    QrcodeTerminal.generate(loginUrl)
  }
  console.log(`${url}\n[${code}] Scan QR Code in above url to login: `)
59
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
60
.on('message', async m => {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
61
  if (m.self()) return
62

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
63 64
  try {
    const msg = await m.ready()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
65
    const room = m.room()
66

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
67
    if (room && /Wechaty/i.test(room.topic())) {
68 69 70 71
      log.info('Bot', 'talk: %s'  , msg)
      talk(m)
    } else {
      log.info('Bot', 'recv: %s'  , msg)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
72
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
73 74 75
  } catch (e) {
    log.error('Bot', 'on message rejected: %s' , e)
  }
76 77
})

78 79 80 81 82 83 84
bot.init()
.catch(e => {
  log.error('Bot', 'init() fail:' + e)
  bot.quit()
  process.exit(-1)
})

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
85 86 87 88 89
class Talker extends EventEmitter {
  private obj: {
    text: any
    time: any
  }
90
  private timer: number | null
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
91 92

  constructor(private thinker) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
93
    super()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
94
    log.verbose('Talker()')
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
95 96 97 98 99
    this.obj = {
      text: []
      , time: []
    }
  }
100

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
101
  public save(text) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
102 103 104 105
    log.verbose('Talker', 'save(%s)', text)
    this.obj.text.push(text)
    this.obj.time.push(Date.now())
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
106
  public load() {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
107 108 109 110 111 112
    const text = this.obj.text.join(', ')
    log.verbose('Talker', 'load(%s)', text)
    this.obj.text = []
    this.obj.time = []
    return text
  }
113

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
114
  public updateTimer(delayTime?) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
115 116
    delayTime = delayTime || this.delayTime()
    log.verbose('Talker', 'updateTimer(%s)', delayTime)
117

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
118 119 120
    if (this.timer) { clearTimeout(this.timer) }
    this.timer = setTimeout(this.say.bind(this), delayTime)
  }
121

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
122
  public hear(text) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
123 124 125 126
    log.verbose('Talker', `hear(${text})`)
    this.save(text)
    this.updateTimer()
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
127
  public say() {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
128 129 130 131 132 133
    log.verbose('Talker', 'say()')
    const text  = this.load()
    this.thinker(text)
    .then(reply => this.emit('say', reply))
    this.timer = null
  }
134

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
135
  public delayTime() {
136 137 138
    const minDelayTime = 5000
    const maxDelayTime = 15000
    const delayTime = Math.floor(Math.random() * (maxDelayTime - minDelayTime)) + minDelayTime
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
139 140 141
    return delayTime
  }
}
142

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
143
/* tslint:disable:variable-name */
144
let Talkers: Talker[] = []
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
145 146

function talk(m) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
147 148 149
  const fromId  = m.from().id
  const roomId =  m.room().id
  const content = m.content()
150 151

  const talkerName = fromId + roomId
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
152 153 154 155 156 157
  if (!Talkers[talkerName]) {
    Talkers[talkerName] = new Talker(function(text) {
      return brain.ask(text, {userid: talkerName})
      .then(r => {
        log.info('Tuling123', 'Talker reply:"%s" for "%s" ', r.text, text)
        return r.text
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
158
      })
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
159 160 161 162
    })
    Talkers[talkerName].on('say', reply => bot.reply(m, reply))
  }
  Talkers[talkerName].hear(content)
163
}