message-media.ts 4.6 KB
Newer Older
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
1 2 3 4 5 6 7 8
/**
 *
 * wechaty: Wechat for Bot. and for human who talk to bot/robot
 *
 * Licenst: ISC
 * https://github.com/zixia/wechaty
 *
 */
9 10
import * as moment from 'moment'

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
11
import {
12 13
  Config,
  log,
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
14
}                     from './config'
15 16 17 18 19
import {
  AppMsgType,
  Message,
  MsgType,
}                     from './message'
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
20 21 22
import { UtilLib }    from './util-lib'
import { PuppetWeb }  from './puppet-web/puppet-web'
import { Bridge }     from './puppet-web/bridge'
23

24
export class MediaMessage extends Message {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
25
  private bridge: Bridge
26

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
27 28
  constructor(rawObj) {
    super(rawObj)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
29
    // FIXME: decoupling needed
30
    this.bridge = (Config.puppetInstance() as PuppetWeb)
31
                        .bridge
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
32
  }
33 34

  public async ready(): Promise<void> {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
35 36
    log.silly('MediaMessage', 'ready()')

37
    try {
38 39
      await super.ready()

40
      let url: string|null = null
41
      switch (this.type()) {
42
        case MsgType.EMOTICON:
43 44
          url = await this.bridge.getMsgEmoticon(this.id)
          break
45
        case MsgType.IMAGE:
46 47
          url = await this.bridge.getMsgImg(this.id)
          break
48 49
        case MsgType.VIDEO:
        case MsgType.MICROVIDEO:
50 51
          url = await this.bridge.getMsgVideo(this.id)
          break
52
        case MsgType.VOICE:
53 54
          url = await this.bridge.getMsgVoice(this.id)
          break
55 56 57 58 59 60 61 62 63 64 65 66 67

        case MsgType.APP:
          if (!this.rawObj) {
            throw new Error('no rawObj')
          }
          switch (this.typeApp()) {
            case AppMsgType.ATTACH:
              if (!this.rawObj.MMAppMsgDownloadUrl) {
                throw new Error('no MMAppMsgDownloadUrl')
              }
              // had set in Message
              // url = this.rawObj.MMAppMsgDownloadUrl
              break
68

69
            case AppMsgType.URL:
70
            case AppMsgType.READER_TYPE:
71 72 73 74 75 76 77 78 79 80
              if (!this.rawObj.Url) {
                throw new Error('no Url')
              }
              // had set in Message
              // url = this.rawObj.Url
              break

            default:
              const e = new Error('ready() unsupported typeApp(): ' + this.typeApp())
              log.warn('MediaMessage', e.message)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
81
              this.dumpRaw()
82 83 84 85 86 87 88 89 90 91
              throw e
          }
          break

        case MsgType.TEXT:
          if (this.typeSub() === MsgType.LOCATION) {
            url = await this.bridge.getMsgPublicLinkImg(this.id)
          }
          break

92 93 94
        default:
          throw new Error('not support message type for MediaMessage')
      }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
95

96 97 98 99 100 101 102 103
      if (!url) {
        if (!this.obj.url) {
          throw new Error('no obj.url')
        }
        url = this.obj.url
      }

      this.obj.url = url
104

105
    } catch (e) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
106 107
      log.warn('MediaMessage', 'ready() exception: %s', e.message)
      throw e
108
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
109
  }
110

111
  private ext(): string {
112
    switch (this.type()) {
113 114
      case MsgType.EMOTICON:
        return 'gif'
115

116 117
      case MsgType.IMAGE:
        return 'jpg'
118

119 120 121
      case MsgType.VIDEO:
      case MsgType.MICROVIDEO:
        return 'mp4'
122

123 124
      case MsgType.VOICE:
        return 'mp3'
125

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
      case MsgType.APP:
        switch (this.typeApp()) {
          case AppMsgType.URL:
            return 'url' // XXX
        }
        break

      case MsgType.TEXT:
        if (this.typeSub() === MsgType.LOCATION) {
          return 'jpg'
        }
        break
    }
    throw new Error('not support type: ' + this.type())
  }

  public filename(): string {
    if (!this.rawObj) {
      throw new Error('no rawObj')
    }

147 148 149 150 151 152 153 154
    const objFileName = this.rawObj.FileName || this.rawObj.MediaId || this.rawObj.MsgId

    let filename  = moment().format('YYYY-MM-DD HH:mm:ss')
                    + ' #' + this._counter
                    + ' ' + this.getSenderString()
                    + ' ' + objFileName

    filename = filename.replace(/ /g, '_')
155 156 157 158 159

    const re = /\.[a-z0-9]{1,7}$/i
    if (!re.test(filename)) {
      const ext = this.rawObj.MMAppMsgFileExt || this.ext()
      filename += '.' + ext
160
    }
161
    return filename
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
162 163
  }

164 165 166 167 168 169 170 171
  // private getMsgImg(id: string): Promise<string> {
  //   return this.bridge.getMsgImg(id)
  //   .catch(e => {
  //     log.warn('MediaMessage', 'getMsgImg(%d) exception: %s', id, e.message)
  //     throw e
  //   })
  // }

172 173 174
  public async readyStream(): Promise<NodeJS.ReadableStream> {
    try {
      await this.ready()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
175
      // FIXME: decoupling needed
176
      const cookies = await (Config.puppetInstance() as PuppetWeb).browser.readCookie()
177 178 179
      if (!this.obj.url) {
        throw new Error('no url')
      }
180 181 182
      return UtilLib.urlStream(this.obj.url, cookies)
    } catch (e) {
      log.warn('MediaMessage', 'stream() exception: %s', e.stack)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
183
      throw e
184
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
185 186
  }
}