message-media.ts 4.2 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 77 78 79 80 81 82 83 84 85 86

        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)
              throw e
          }
          break

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

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

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

      this.obj.url = url
99

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

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

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

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

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

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
      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
148
    }
149
    return filename
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
150 151
  }

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

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