src/main/robot/webwxapi/fun.js
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
}
]
}
}