config.ts 4.4 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
import { execSync } from 'child_process'
7
import * as fs from 'fs'
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, {
56 57 58
  head:       process.env['WECHATY_HEAD']      || Config.DEFAULT_HEAD
  , puppet:   process.env['WECHATY_PUPPET']    || Config.DEFAULT_PUPPET
  , apihost:  process.env['WECHATY_APIHOST']   || Config.DEFAULT_APIHOST
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
59
  , 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, {
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
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
  isDocker:   isWechatyDocker()
93
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
94

95
function isWechatyDocker() {
96 97 98
  /**
   * Continuous Integration System
   */
99 100 101 102
  const isCi = require('is-ci')
  if (isCi) {
    return false
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
103

104 105 106 107 108 109 110 111 112
  /**
   * Cloud9 IDE
   */
  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 (李卓桓) 已提交
113

114
  const cgroup = '/proc/1/cgroup'
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
115
  try       { fs.statSync(cgroup).isFile() }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
116 117
  catch (e) { return false }

118 119
  // http://stackoverflow.com/a/20624315/1123955
  const line = execSync(`sort -n ${cgroup} 2>/dev/null | head -1`)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
120 121 122
                .toString()
                .replace(/\n$/, '')

123
  // instead of `/`, docker will end with a container id
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
124 125 126
  if (/\/$/.test(line)) {
    return false
  }
127

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
128 129 130
  return true
}

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

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

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

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

151
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
152

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

157 158
}

159 160 161 162
Object.assign(Config, {
  puppetInstance
})

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

167
export type WatchdogFood = {
168 169
    data: any
  , timeout?: number  // millisecond
Huan (李卓桓)'s avatar
bug fix  
Huan (李卓桓) 已提交
170
  , type?: WatchdogFoodName
171 172
}

173
export type ScanInfo = {
174 175 176 177
  url: string
  code: number
}

178
export type RecommendInfo = {
179 180 181 182 183 184 185
  UserName:   string
  NickName:   string
  Content:    string // request message
  Ticket:     string // a pass token
  VerifyFlag: number
}

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

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
190 191 192
export interface Sleepable {
  sleep(millisecond: number): Promise<void>
}
193

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
194
export { log }