config.ts 6.1 KB
Newer Older
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
1
/**
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
2
 *   Wechaty - https://github.com/chatie/wechaty
3 4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 *   Copyright 2016-2017 Huan LI <zixia@zixia.net>
 *
 *   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.
17
 *
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
18
 */
19 20
const isCi      = require('is-ci')
const isDocker  = require('is-docker')
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
21

22 23
import { log }    from 'brolog'

24
import { Puppet } from './puppet'
25

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
const logLevel = process.env['WECHATY_LOG']
if (logLevel) {
  log.level(logLevel.toLowerCase())
  log.silly('Brolog', 'WECHATY_LOG set level to %s', logLevel)
}

/**
 * to handle unhandled exceptions
 */
if (/verbose|silly/i.test(logLevel)) {
  log.info('Config', 'registering process.on("unhandledRejection") for development/debug')
  process.on('unhandledRejection', (reason, promise) => {
    log.error('Config', '###########################')
    log.error('Config', 'unhandledRejection: %s %s', reason, promise)
    log.error('Config', '###########################')
    promise.catch(err => {
      log.error('Config', 'unhandledRejection::catch(%s)', err.message)
      console.error('Config', err) // I don't know if log.error has similar full trace print support like console.error
    })
  })
46
}
47

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

51
export interface ConfigSetting {
52

53
  DEFAULT_HEAD: HeadName
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
54
  DEFAULT_PUPPET: PuppetName
55 56 57
  DEFAULT_APIHOST: string
  DEFAULT_PROFILE: string
  DEFAULT_TOKEN:  string
58 59
  DEFAULT_PROTOCOL: string
  CMD_CHROMIUM: string
60 61 62 63 64 65 66
  DEFAULT_PORT: number

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

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
67
  puppet: PuppetName
68
  head: HeadName
69 70

  apihost: string
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
71
  validApiHost: (host: string) => boolean
72 73 74

  httpPort: number

75 76 77
  _puppetInstance: Puppet | null
  puppetInstance(): Puppet
  puppetInstance(empty: null): void
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
78
  puppetInstance(instance: Puppet): void
79
  puppetInstance(instance?: Puppet | null): Puppet | void
80

81
  isDocker: boolean
82 83

}
84 85
/* tslint:disable:variable-name */
/* tslint:disable:no-var-requires */
86
export const Config: ConfigSetting = require('../package.json').wechaty
87

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
88 89 90
/**
 * 1. ENVIRONMENT VARIABLES + PACKAGES.JSON (default)
 */
91
Object.assign(Config, {
L
lijiarui 已提交
92 93 94 95
  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 (李卓桓) 已提交
96 97
})

98
function validApiHost(apihost: string): boolean {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
99 100 101 102 103 104 105
  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 (李卓桓) 已提交
106 107 108 109
/**
 * 2. ENVIRONMENT VARIABLES (only)
 */
Object.assign(Config, {
L
lijiarui 已提交
110 111 112 113
  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 (李卓桓) 已提交
114
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
115

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
116 117 118 119 120
/**
 * 3. Service Settings
 */
Object.assign(Config, {
  // get PORT form cloud service env, ie: heroku
L
lijiarui 已提交
121
  httpPort: process.env['PORT'] || process.env['WECHATY_PORT'] || Config.DEFAULT_PORT,
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
122 123 124 125 126 127
})

/**
 * 4. Envioronment Identify
 */
Object.assign(Config, {
128 129
  isDocker:  isWechatyDocker(),
  isGlobal:  isWechatyInstalledGlobal(),
130
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
131

132 133 134 135 136 137 138 139 140 141
function isWechatyInstalledGlobal() {
  /**
   * TODO:
   * 1. check /node_modules/wechaty
   * 2. return true if exists
   * 3. otherwise return false
   */
   return false
}

142
function isWechatyDocker() {
143
  /**
144
   * false for Continuous Integration System
145
   */
146 147 148
  if (isCi) {
    return false
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
149

150
  /**
151
   * false Cloud9 IDE
152 153 154 155 156 157 158
   */
  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 (李卓桓) 已提交
159

160 161 162
  /**
   * return indentify result by NPM module `is-docker`
   */
163
  return isDocker()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
164 165
}

166 167 168
/**
 * 5. live setting
 */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
169 170 171 172
function puppetInstance(): Puppet
function puppetInstance(empty: null): void
function puppetInstance(instance: Puppet): void

173
function puppetInstance(instance?: Puppet | null): Puppet | void {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
174 175

  if (instance === undefined) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
176
    if (!this._puppetInstance) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
177
      throw new Error('no puppet instance')
178
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
179
    return this._puppetInstance
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
180 181

  } else if (instance === null) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
182
    log.verbose('Config', 'puppetInstance(null)')
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
183
    this._puppetInstance = null
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
184
    return
185
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
186

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
187
  log.verbose('Config', 'puppetInstance(%s)', instance.constructor.name)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
188
  this._puppetInstance = instance
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
189 190
  return

191 192
}

193
Object.assign(Config, {
L
lijiarui 已提交
194
  puppetInstance,
195 196
})

Huan (李卓桓)'s avatar
bug fix  
Huan (李卓桓) 已提交
197 198 199 200
export type WatchdogFoodName = 'HEARTBEAT'
                              | 'POISON'
                              | 'SCAN'

201
export interface WatchdogFood {
L
lijiarui 已提交
202 203 204
  data: any,
  timeout?: number,  // millisecond
  type?: WatchdogFoodName,
205 206
}

207
export interface ScanInfo {
L
lijiarui 已提交
208 209
  url: string,
  code: number,
210 211
}

212 213 214
/**
 * from Message
 */
215
export interface RecommendInfo {
L
lijiarui 已提交
216 217 218 219
  UserName:   string,
  NickName:   string,  // display_name
  Content:    string,  // request message
  HeadImgUrl: string,  // message.RecommendInfo.HeadImgUrl
220

L
lijiarui 已提交
221 222
  Ticket:     string,  // a pass token
  VerifyFlag: number,
223

224 225
}

226
export interface Sayable {
227
  say(content: string, replyTo?: any|any[]): Promise<boolean>
228
}
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
229

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
230 231 232
export interface Sleepable {
  sleep(millisecond: number): Promise<void>
}
233

234 235 236 237 238 239 240 241
/**
 * 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

242 243 244 245
export {
  log,
}

246
export default Config