config.ts 5.3 KB
Newer Older
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
1 2
/**
 * Wechaty - Wechaty for Bot, Connect ChatBots, Chat as a Service
3
 *
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
4 5
 * https://github.com/wechaty/wechaty/
 */
6 7
const isCi      = require('is-ci')
const isDocker  = require('is-docker')
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
8

9 10
import { Puppet } from './puppet'
import { log }    from './brolog-env'
11

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
12
export type PuppetName = 'web' | 'android' | 'ios'
13
export type HeadName = 'chrome' | 'phantomjs' | 'firefox'
14

15
export interface ConfigSetting {
16

17
  DEFAULT_HEAD: HeadName
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
18
  DEFAULT_PUPPET: PuppetName
19 20 21
  DEFAULT_APIHOST: string
  DEFAULT_PROFILE: string
  DEFAULT_TOKEN:  string
22 23
  DEFAULT_PROTOCOL: string
  CMD_CHROMIUM: string
24 25 26 27 28 29 30
  DEFAULT_PORT: number

  port: number
  profile: string
  token: string
  debug: boolean

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
31
  puppet: PuppetName
32
  head: HeadName
33 34

  apihost: string
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
35
  validApiHost: (host: string) => boolean
36 37 38

  httpPort: number

39 40 41
  _puppetInstance: Puppet | null
  puppetInstance(): Puppet
  puppetInstance(empty: null): void
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
42
  puppetInstance(instance: Puppet): void
43
  puppetInstance(instance?: Puppet | null): Puppet | void
44

45
  isDocker: boolean
46 47

}
48 49
/* tslint:disable:variable-name */
/* tslint:disable:no-var-requires */
50
export const Config: ConfigSetting = require('../package.json').wechaty
51

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
52 53 54
/**
 * 1. ENVIRONMENT VARIABLES + PACKAGES.JSON (default)
 */
55
Object.assign(Config, {
L
lijiarui 已提交
56 57 58 59
  head:       process.env['WECHATY_HEAD']      || Config.DEFAULT_HEAD,
  puppet:   process.env['WECHATY_PUPPET']    || Config.DEFAULT_PUPPET,
  apihost:  process.env['WECHATY_APIHOST']   || Config.DEFAULT_APIHOST,
  validApiHost,
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
60 61
})

62
function validApiHost(apihost: string): boolean {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
63 64 65 66 67 68 69
  if (/^[a-zA-Z0-9\.\-\_]+:?[0-9]*$/.test(apihost)) {
    return true
  }
  throw new Error('validApiHost() fail for ' + apihost)
}
validApiHost(Config.apihost)

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
70 71 72 73
/**
 * 2. ENVIRONMENT VARIABLES (only)
 */
Object.assign(Config, {
L
lijiarui 已提交
74 75 76 77
  port:       process.env['WECHATY_PORT']     || null, // 0 for disable port
  profile:  process.env['WECHATY_PROFILE']    || null, // DO NOT set DEFAULT_PROFILE, because sometimes user do not want to save session
  token:    process.env['WECHATY_TOKEN']      || null, // DO NOT set DEFAULT, because sometimes user do not want to connect to io cloud service
  debug:    !!(process.env['WECHATY_DEBUG'])  || false,
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
78
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
79

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
80 81 82 83 84
/**
 * 3. Service Settings
 */
Object.assign(Config, {
  // get PORT form cloud service env, ie: heroku
L
lijiarui 已提交
85
  httpPort: process.env['PORT'] || process.env['WECHATY_PORT'] || Config.DEFAULT_PORT,
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
86 87 88 89 90 91
})

/**
 * 4. Envioronment Identify
 */
Object.assign(Config, {
92 93
  isDocker:  isWechatyDocker(),
  isGlobal:  isWechatyInstalledGlobal(),
94
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
95

96 97 98 99 100 101 102 103 104 105
function isWechatyInstalledGlobal() {
  /**
   * TODO:
   * 1. check /node_modules/wechaty
   * 2. return true if exists
   * 3. otherwise return false
   */
   return false
}

106
function isWechatyDocker() {
107
  /**
108
   * false for Continuous Integration System
109
   */
110 111 112
  if (isCi) {
    return false
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
113

114
  /**
115
   * false Cloud9 IDE
116 117 118 119 120 121 122
   */
  const c9 = Object.keys(process.env)
                  .filter(k => /^C9_/.test(k))
                  .length
  if (c9 > 7 && process.env['C9_PORT']) {
    return false
  }
Huan (李卓桓)'s avatar
lint  
Huan (李卓桓) 已提交
123

124 125 126
  /**
   * return indentify result by NPM module `is-docker`
   */
127
  return isDocker()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
128 129
}

130 131 132
/**
 * 5. live setting
 */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
133 134 135 136
function puppetInstance(): Puppet
function puppetInstance(empty: null): void
function puppetInstance(instance: Puppet): void

137
function puppetInstance(instance?: Puppet | null): Puppet | void {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
138 139

  if (instance === undefined) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
140
    if (!this._puppetInstance) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
141
      throw new Error('no puppet instance')
142
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
143
    return this._puppetInstance
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
144 145

  } else if (instance === null) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
146
    log.verbose('Config', 'puppetInstance(null)')
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
147
    this._puppetInstance = null
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
148
    return
149
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
150

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
151
  log.verbose('Config', 'puppetInstance(%s)', instance.constructor.name)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
152
  this._puppetInstance = instance
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
153 154
  return

155 156
}

157
Object.assign(Config, {
L
lijiarui 已提交
158
  puppetInstance,
159 160
})

Huan (李卓桓)'s avatar
bug fix  
Huan (李卓桓) 已提交
161 162 163 164
export type WatchdogFoodName = 'HEARTBEAT'
                              | 'POISON'
                              | 'SCAN'

165
export type WatchdogFood = {
L
lijiarui 已提交
166 167 168
  data: any,
  timeout?: number,  // millisecond
  type?: WatchdogFoodName,
169 170
}

171
export type ScanInfo = {
L
lijiarui 已提交
172 173
  url: string,
  code: number,
174 175
}

176 177 178
/**
 * from Message
 */
179
export type RecommendInfo = {
L
lijiarui 已提交
180 181 182 183
  UserName:   string,
  NickName:   string,  // display_name
  Content:    string,  // request message
  HeadImgUrl: string,  // message.RecommendInfo.HeadImgUrl
184

L
lijiarui 已提交
185 186
  Ticket:     string,  // a pass token
  VerifyFlag: number,
187

188 189
}

190
export interface Sayable {
191
  say(content: string, replyTo?: any|any[]): Promise<void>
192
}
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
193

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
194 195 196
export interface Sleepable {
  sleep(millisecond: number): Promise<void>
}
197

198 199 200 201 202 203 204 205
/**
 * ISSUE #72
 * Introduce the SELENIUM_PROMISE_MANAGER environment variable.
 * When set to 1, selenium-webdriver will use the existing ControlFlow scheduler.
 * When set to 0, the SimpleScheduler will be used.
 */
process.env['SELENIUM_PROMISE_MANAGER'] = 0

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
206 207 208 209 210 211 212 213
/**
 * to count how many times this piece of code is instanciaed
 */
if (!global['WECHATY_CONFIG_INSTANCE_COUNTER']) {
  global['WECHATY_CONFIG_INSTANCE_COUNTER'] = 0
}
global['WECHATY_CONFIG_INSTANCE_COUNTER']++

Huan (李卓桓)'s avatar
lint  
Huan (李卓桓) 已提交
214 215 216
export {
  log
}
217 218 219 220

/**
 * to handle unhandled exceptions
 */
221
/*
222
process.on('unhandledRejection', (reason, promise) => {
223
  log.error('Config', '###########################')
224
  log.error('Config', 'unhandledRejection: %s %s', reason, promise)
225
  log.error('Config', '###########################')
226 227 228
  promise.catch(err => {
    log.error('Config', 'unhandledRejection::catch(%s)', err.message || err)
  })
229
})
230
*/