src/main/robot/webwxapi/fun.js

Summary

Maintainability
A
0 mins
Test Coverage

const { URL } = require('url')

const xml2js = require('xml2js')
const SparkMD5 = require('spark-md5')

const createErr = require('../createErr.js')

// `WU_FILE_${wuFile++}`
let wuFile = 0

const getUserAvatar = str => {
  const arr = str && str.match(/'(\S+?)';/)
  const userAvatar = arr && arr[1]
  return userAvatar ||
    'https://res.wx.qq.com/a/wx_fed/webwx/res/static/img/2KriyDK.png'
}

const getHostAndQuery = str => {
  const arr = str.match(/window.redirect_uri="(\S+?)";/)
  const u = new URL(arr[1])
  const host = u.host
  const query = {
    ticket: u.searchParams.get('ticket'),
    uuid: u.searchParams.get('uuid'),
    lang: u.searchParams.get('lang'),
    scan: u.searchParams.get('scan'),
    fun: 'new',
    version: 'v2'
  }
  return { host, query }
}

const getWebwxDataTicket = cookies => {
  let webwxDataTicket = ''

  for (let i = 0, len = cookies.length; i < len; i++) {
    const cookie = cookies[i]
    const arr = cookie.match(/^webwx_data_ticket=(\S+?);/)
    if (arr) {
      webwxDataTicket = arr[1]
      break
    }
  }

  return webwxDataTicket
}

// webwxuploadmedia
const getFileMd5 = buf => {
  const spark = new SparkMD5.ArrayBuffer()
  spark.append(buf)
  return spark.end()
}
const getWuFile = () => {
  return `WU_FILE_${wuFile++}`
}

const getUploadmediarequest = (BaseRequest, file, Msg, buf) => {
  return {
    UploadType: 2,
    BaseRequest,
    ClientMediaId: file.lastModified,
    TotalLen: file.size,
    StartPos: 0,
    DataLen: file.size,
    MediaType: 4,
    FromUserName: Msg.FromUserName,
    ToUserName: Msg.ToUserName,
    FileMd5: getFileMd5(buf)
  }
}

module.exports = {
  getUUID (str) {
    const arr = str &&
      str.match(/"(\S+?)";$/)
    const uuid = arr && arr[1]
  
    if (uuid) {
      return uuid
    }
  
    throw createErr(900, '获取 uuid 失败')
  },

  getHostAndLoginCode (str) {
    const arr = str && str.match(/window.code=(\d+?);/)
    const code = arr && arr[1]

    if (!code) {
      throw createErr(901, '获取 codes 失败')
    }

    if (code === '201') {
      const userAvatar = getUserAvatar(str)
      return { loginCode: { code, userAvatar } }
    }

    /* istanbul ignore else */
    if (code === '200') {
      const { host, query } = getHostAndQuery(str)
      return { host, loginCode: { code, query } }
    }

    return { loginCode: { code } }
  },

  getWebwxDataTicketFromCookies (cookies) {
    if (cookies && cookies.length) {
      
      const webwxDataTicket = getWebwxDataTicket(cookies)

      /* istanbul ignore else */
      if (webwxDataTicket) {
        return webwxDataTicket
      }
    }

    throw createErr(902, '获取 webwxDataTicket 失败')
  },

  getBaseRequest (str) {
    return new Promise((resolve, reject) => {
      xml2js.parseString(str, {
        explicitArray: false
      }, (err, result) => {
        if (result && result.error && result.error.wxuin) {
          const { wxuin, wxsid, skey, pass_ticket } = result.error

          return resolve({
            BaseRequest: {
              Uin: wxuin,
              Sid: wxsid,
              Skey: skey
            },
            passTicket: pass_ticket
          })
        }
  
        if (err) {
          err.status = 903
          return reject(err)
        }
  
        reject(createErr(904, '获取 BaseRequest 失败'))
      })
    })
  },

  /**
   * 随机字符串产生函数
   */
  getDeviceID () {
    return 'e' + ('' + Math.random().toFixed(15)).substring(2, 17)
  },

  getFormateSyncCheckKey (list) {
    let a = []
    for (let i = 0, len = list.length; i < len; i++) {
      a.push(list[i].Key + '_' + list[i].Val)
    }
  
    return a.join('|')
  },

  getSynccheckResNum (str) {
    const arr =
      str.match(/window.synccheck={retcode:"(\d+)",selector:"(\d+)"}/)
    
    /* istanbul ignore else */
    if (arr) {
      switch (arr[1]) {
        case '0':
          return arr[2]
        case '1100':
          throw createErr(803, '登出微信')
        case '1101':
          throw createErr(804, '其他设备登录web微信')
        case '1102':
          throw createErr(805, '暂时不知道')
      }
    }

    throw createErr(806, '监听心跳失败')
  },

  getFields ({ BaseRequest, webwxDataTicket, file, buf, Msg }) {
    const uploadmediarequest =
      getUploadmediarequest(BaseRequest, file, Msg, buf)
    
    return [
      { name: 'id', value: getWuFile() },
      { name: 'name', value: file.name },
      { name: 'type', value: file.type },
      { name: 'lastModifiedDate',value: file.lastModifiedDate },
      { name: 'size', value: file.size },
      { name: 'mediatype', value: 'pic' },
      { name: 'uploadmediarequest',value: JSON.stringify(uploadmediarequest) },
      { name: 'webwx_data_ticket', value: webwxDataTicket },
      { name: 'pass_ticket', value: 'undefined' },
      {
        name: 'filename',
        filename: file.name,
        type: file.type
      }
    ]
  }
}