message-media.ts 4.3 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
 *
 */
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
9
import {
10 11
  Config,
  log,
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
12
}                     from './config'
13 14 15 16 17
import {
  AppMsgType,
  Message,
  MsgType,
}                     from './message'
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
18 19 20
import { UtilLib }    from './util-lib'
import { PuppetWeb }  from './puppet-web/puppet-web'
import { Bridge }     from './puppet-web/bridge'
21

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

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

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

35
    try {
36 37
      await super.ready()

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

        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
            case AppMsgType.URL:
              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 (李卓桓) 已提交
77
              this.dumpRaw()
78 79 80 81 82 83 84 85 86 87
              throw e
          }
          break

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

88 89 90
        default:
          throw new Error('not support message type for MediaMessage')
      }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
91

92 93 94 95 96 97 98 99
      if (!url) {
        if (!this.obj.url) {
          throw new Error('no obj.url')
        }
        url = this.obj.url
      }

      this.obj.url = url
100

101
    } catch (e) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
102 103
      log.warn('MediaMessage', 'ready() exception: %s', e.message)
      throw e
104
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
105
  }
106

107
  private ext(): string {
108
    switch (this.type()) {
109 110
      case MsgType.EMOTICON:
        return 'gif'
111

112 113
      case MsgType.IMAGE:
        return 'jpg'
114

115 116 117
      case MsgType.VIDEO:
      case MsgType.MICROVIDEO:
        return 'mp4'
118

119 120
      case MsgType.VOICE:
        return 'mp3'
121

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
      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')
    }

    let filename  = this.rawObj.FileName || this.rawObj.MediaId || this.rawObj.MsgId

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

153 154 155 156 157 158 159 160
  // 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
  //   })
  // }

161 162 163
  public async readyStream(): Promise<NodeJS.ReadableStream> {
    try {
      await this.ready()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
164
      // FIXME: decoupling needed
165
      const cookies = await (Config.puppetInstance() as PuppetWeb).browser.readCookie()
166 167 168
      if (!this.obj.url) {
        throw new Error('no url')
      }
169 170 171
      return UtilLib.urlStream(this.obj.url, cookies)
    } catch (e) {
      log.warn('MediaMessage', 'stream() exception: %s', e.stack)
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
172
      throw e
173
    }
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
174 175
  }
}