config.ts 6.7 KB
Newer Older
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
1
/**
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
2
 *   Wechaty - https://github.com/chatie/wechaty
3
 *
4
 *   @copyright 2016-2017 Huan LI <zixia@zixia.net>
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.
17
 *
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
18
 */
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
import * as fs    from 'fs'
import * as os    from 'os'
import * as path  from 'path'

/**
 * Raven.io
 */
import * as Raven from 'raven'
Raven.disableConsoleAlerts()

Raven
.config(
  process.env.NODE_ENV === 'production'
    && 'https://f6770399ee65459a82af82650231b22c:d8d11b283deb441e807079b8bb2c45cd@sentry.io/179672',
  {
    release: require('../package.json').version,
    tags: {
      git_commit: 'c0deb10c4',
37
      platform:   !!process.env['WECHATY_DOCKER']
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
                  ? 'docker'
                  : os.platform(),
    },
  },
)
.install()

/*
try {
    doSomething(a[0])
} catch (e) {
    Raven.captureException(e)
}

Raven.context(function () {
  doSomething(a[0])
})
 */
56

57 58
import Brolog from 'brolog'
export const log = new Brolog()
59

60
import { Puppet } from './puppet'
61

62
const logLevel = process.env['WECHATY_LOG'] || 'info'
63
if (logLevel) {
64
  log.level(logLevel.toLowerCase() as any)
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
  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
    })
  })
82
}
83

84 85 86 87
export type PuppetName = 'web'
                        | 'android'
                        | 'ios'

88
export interface ConfigSetting {
89

90
  DEFAULT_HEAD: number
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
91
  DEFAULT_PUPPET: PuppetName
92 93 94
  DEFAULT_APIHOST: string
  DEFAULT_PROFILE: string
  DEFAULT_TOKEN:  string
95
  DEFAULT_PROTOCOL: string
96 97 98 99 100

  profile: string
  token: string
  debug: boolean

101
  head: boolean
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
102
  puppet: PuppetName
103 104

  apihost: string
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
105
  validApiHost: (host: string) => boolean
106 107 108

  httpPort: number

109 110 111
  _puppetInstance: Puppet | null
  puppetInstance(): Puppet
  puppetInstance(empty: null): void
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
112
  puppetInstance(instance: Puppet): void
113
  puppetInstance(instance?: Puppet | null): Puppet | void,
114

115 116
  gitVersion(): string | null,
  npmVersion(): string,
117

118
  docker: boolean,
119
}
120 121
/* tslint:disable:variable-name */
/* tslint:disable:no-var-requires */
122
export const config: ConfigSetting = require('../package.json').wechaty
123

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
124 125 126
/**
 * 1. ENVIRONMENT VARIABLES + PACKAGES.JSON (default)
 */
127
Object.assign(config, {
128 129 130
  apihost:    process.env['WECHATY_APIHOST']    || config.DEFAULT_APIHOST,
  head:       ('WECHATY_HEAD' in process.env) ? (!!process.env['WECHATY_HEAD']) : (!!(config.DEFAULT_HEAD)),
  puppet:     process.env['WECHATY_PUPPET']     || config.DEFAULT_PUPPET,
L
lijiarui 已提交
131
  validApiHost,
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
132 133
})

134
function validApiHost(apihost: string): boolean {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
135 136 137 138 139
  if (/^[a-zA-Z0-9\.\-\_]+:?[0-9]*$/.test(apihost)) {
    return true
  }
  throw new Error('validApiHost() fail for ' + apihost)
}
140
validApiHost(config.apihost)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
141

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
142 143 144
/**
 * 2. ENVIRONMENT VARIABLES (only)
 */
145
Object.assign(config, {
146
  // port:       process.env['WECHATY_PORT']     || null, // 0 for disable port
L
lijiarui 已提交
147 148 149
  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 (李卓桓) 已提交
150
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
151

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
152 153 154
/**
 * 3. Service Settings
 */
155
// Object.assign(config, {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
156
  // get PORT form cloud service env, ie: heroku
157 158
  // httpPort: process.env['PORT'] || process.env['WECHATY_PORT'] || config.DEFAULT_PORT,
// })
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
159 160 161 162

/**
 * 4. Envioronment Identify
 */
163
Object.assign(config, {
164
  docker: !!process.env['WECHATY_DOCKER'],
165
  isGlobal:  isWechatyInstalledGlobal(),
166
})
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
167

168 169 170 171 172 173 174 175 176 177
function isWechatyInstalledGlobal() {
  /**
   * TODO:
   * 1. check /node_modules/wechaty
   * 2. return true if exists
   * 3. otherwise return false
   */
   return false
}

178 179 180
/**
 * 5. live setting
 */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
181 182 183 184
function puppetInstance(): Puppet
function puppetInstance(empty: null): void
function puppetInstance(instance: Puppet): void

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

187
  if (typeof instance === 'undefined') {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
188
    if (!this._puppetInstance) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
189
      throw new Error('no puppet instance')
190
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
191
    return this._puppetInstance
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
192 193

  } else if (instance === null) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
194
    log.verbose('Config', 'puppetInstance(null)')
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
195
    this._puppetInstance = null
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
196
    return
197
  }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
198

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
199
  log.verbose('Config', 'puppetInstance(%s)', instance.constructor.name)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
200
  this._puppetInstance = instance
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
201 202
  return

203 204
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
function gitVersion(): string | null {
  const dotGitPath  = path.join(__dirname, '..', '.git') // only for ts-node, not for dist
  // const gitLogArgs  = ['log', '--oneline', '-1']
  // TODO: use git rev-parse HEAD ?
  const gitArgs  = ['rev-parse', 'HEAD']

  try {
    // Make sure this is a Wechaty repository
    fs.statSync(dotGitPath).isDirectory()

    const ss = require('child_process')
                .spawnSync('git', gitArgs, { cwd:  __dirname })

    if (ss.status !== 0) {
      throw new Error(ss.error)
    }

    const revision = ss.stdout
                      .toString()
                      .trim()
                      .slice(0, 7)
    return revision

  } catch (e) { /* fall safe */
    /**
     *  1. .git not exist
     *  2. git log fail
     */
    log.silly('Wechaty', 'version() form development environment is not availble: %s', e.message)
    return null
  }
}

function npmVersion(): string {
  try {
    return require('../package.json').version
  } catch (e) {
    log.error('Wechaty', 'npmVersion() exception %s', e.message)
    Raven.captureException(e)
    return '0.0.0'
  }
}

Object.assign(config, {
  gitVersion,
  npmVersion,
L
lijiarui 已提交
251
  puppetInstance,
252 253
})

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

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
258 259 260
export interface Sleepable {
  sleep(millisecond: number): Promise<void>
}
261

262
export {
263
  Raven,
264 265
}

266
export default config