提交 cbd3ff0b 编写于 作者: Huan (李卓桓)'s avatar Huan (李卓桓)

fight with login success

上级 225c569a
......@@ -65,7 +65,8 @@ export class Bridge extends EventEmitter {
private readonly padchatRpc: PadchatRpc
private autoData : AutoDataType
private loginQrCode?: string
private loginScanQrCode? : string
private loginScanStatus? : number
private loginTimer?: NodeJS.Timer
......@@ -114,9 +115,11 @@ export class Bridge extends EventEmitter {
await this.loadAutoData()
await this.restoreLogin()
const restoreSucceed = await this.restoreLogin()
this.startLogin()
if (!restoreSucceed) {
this.startLogin()
}
this.state.on(true)
}
......@@ -130,7 +133,8 @@ export class Bridge extends EventEmitter {
this.saveAutoData()
this.emit('login', this.selfId = username)
this.selfId = username
this.emit('login', this.selfId)
}
public logout(): void {
......@@ -149,7 +153,8 @@ export class Bridge extends EventEmitter {
clearTimeout(this.loginTimer)
this.loginTimer = undefined
}
this.loginQrCode = undefined
this.loginScanQrCode = undefined
this.loginScanStatus = undefined
}
protected async startLogin(): Promise<void> {
......@@ -169,14 +174,23 @@ export class Bridge extends EventEmitter {
/**
* 2. Wait user response
*/
let lastStatus = WXCheckQRCodeStatus.Unknown
let loop = true
while (loop) {
let waitUser = true
while (waitUser) {
const result = await this.padchatRpc.WXCheckQRCode()
if (lastStatus !== result.status && this.loginQrCode) {
lastStatus = result.status
this.emit('scan', this.loginQrCode, result.status)
if (this.loginScanStatus !== result.status && this.loginScanQrCode) {
this.loginScanStatus = result.status
this.emit(
'scan',
this.loginScanQrCode,
this.loginScanStatus,
)
}
if (result.expired_time && result.expired_time < 10) {
// result.expire_time is second
// emit new qrcode before the old one expired
waitUser = false
}
switch (result.status) {
......@@ -205,29 +219,38 @@ export class Bridge extends EventEmitter {
case WXCheckQRCodeStatus.Timeout:
log.silly('PuppetPadchatBridge', 'checkQrcode: Timeout')
this.loginQrCode = undefined
loop = false
this.loginScanQrCode = undefined
this.loginScanStatus = undefined
waitUser = false
break
case WXCheckQRCodeStatus.Cancel:
log.silly('PuppetPadchatBridge', 'user cancel')
this.loginQrCode = undefined
loop = false
this.loginScanQrCode = undefined
this.loginScanStatus = undefined
waitUser = false
break
default:
throw new Error('unknown status: ' + result.status)
log.warn('PadchatBridge', 'startLogin() unknown WXCheckQRCodeStatus: ' + result.status)
this.loginScanQrCode = undefined
this.loginScanStatus = undefined
waitUser = false
break
}
await new Promise(r => setTimeout(r, 1000))
}
await this.emitLoginQrCode()
this.loginTimer = setTimeout(this.startLogin.bind(this), 1000)
this.loginTimer = setTimeout(() => {
this.loginTimer = undefined
this.startLogin()
}, 1000)
return
}
protected async restoreLogin(): Promise<void> {
protected async restoreLogin(): Promise<boolean> {
/**
* 1. The following `if/else` block: emit qrcode or send login request to the user.
*/
......@@ -243,8 +266,8 @@ export class Bridge extends EventEmitter {
/**
* 1.1 Auto Login Success, return username as the result
*/
this.selfId = autoLoginResult.user_name
return
this.login(autoLoginResult.user_name)
return true
} else {
/**
......@@ -266,13 +289,13 @@ export class Bridge extends EventEmitter {
await this.emitLoginQrCode()
}
}
return
return false
}
protected async emitLoginQrCode(): Promise<void> {
log.verbose('PuppetPadchatBridge', `emitLoginQrCode()`)
if (this.loginQrCode) {
if (this.loginScanQrCode) {
throw new Error('qrcode exist')
}
......@@ -284,10 +307,13 @@ export class Bridge extends EventEmitter {
const qrCodeText = await pfHelper.imageBase64ToQrCode(result.qr_code)
this.loginScanQrCode = qrCodeText
this.loginScanStatus = WXCheckQRCodeStatus.WaitScan
this.emit(
'scan',
this.loginQrCode = qrCodeText,
0,
this.loginScanQrCode,
this.loginScanStatus,
)
}
......@@ -310,13 +336,14 @@ export class Bridge extends EventEmitter {
protected async loadAutoData(): Promise<void> {
log.verbose('PuppetPadchatBridge', `loadAutoData()`)
const autoData: AutoDataType = await this.options.memory.get(AUTO_DATA_SLOT)
this.autoData = { ...autoData || {} }
this.autoData = {
...await this.options.memory.get(AUTO_DATA_SLOT),
}
// Check for 62 data, if has, then use WXLoadWxDat
if (autoData.wxData) {
if (this.autoData.wxData) {
log.silly('PuppetPadchatBridge', `start(), get 62 data`)
await this.padchatRpc.WXLoadWxDat(autoData.wxData)
await this.padchatRpc.WXLoadWxDat(this.autoData.wxData)
}
}
......@@ -346,13 +373,12 @@ export class Bridge extends EventEmitter {
public async syncContactsAndRooms(): Promise<void> {
log.verbose('PuppetPadchatBridge', `syncContactsAndRooms()`)
let cont = true
// const syncContactMap = new Map<string, PadchatContactPayload>()
// const syncRoomMap = new Map<string, PadchatRoomPayload>()
// let contactIdList: string[] = []
// let roomIdList: string[] = []
while (cont && this.state.on() && this.selfId) {
while (this.state.on() && this.selfId) {
log.silly('PuppetPadchatBridge', `syncContactsAndRooms() while()`)
const syncContactList = await this.padchatRpc.WXSyncContact()
......@@ -375,29 +401,27 @@ export class Bridge extends EventEmitter {
),
)
syncContactList
.forEach(syncContact => {
for (const syncContact of syncContactList) {
if (syncContact.continue === PadchatContinue.Go) {
if (syncContact.msg_type === PadchatContactMsgType.Contact) {
console.log('syncContact:', syncContact.user_name, syncContact.nick_name)
if (pfHelper.isRoomId(syncContact.user_name)) { // /@chatroom$/.test(syncContact.user_name)) {
this.cacheRoomRawPayload[syncContact.user_name] = syncContact as PadchatRoomPayload
// syncRoomMap.set(syncContact.user_name, syncContact as PadchatRoomPayload)
} else if (syncContact.user_name) {
} else if (pfHelper.isContactId(syncContact.user_name)) {
this.cacheContactRawPayload[syncContact.user_name] = syncContact as PadchatContactPayload
// syncContactMap.set(syncContact.user_name, syncContact as PadchatContactPayload)
} else {
throw new Error('no user_name')
throw new Error('id is neither room nor contact')
}
}
} else {
log.info('PuppetPadchatBridge', 'syncContactsAndRooms() sync contact done!')
cont = false
return
log.verbose('PuppetPadchatBridge', 'syncContactsAndRooms() sync contact done!')
break
}
})
log.silly('PuppetPadchatBridge', `syncContactsAndRooms(), continue to load via WXSyncContact ...`)
}
log.verbose('PuppetPadchatBridge', `syncContactsAndRooms(), continue to load via WXSyncContact ...`)
}
// contactIdList = contactIdList.filter(id => !!id)
......
......@@ -12,6 +12,8 @@ import {
// JsonRpcPayloadError,
// JsonRpcParamsSchemaByName,
JsonRpcParamsSchemaByPositional,
parse,
} from 'json-rpc-peer'
// import { MemoryCard } from 'memory-card'
......@@ -83,23 +85,36 @@ export class PadchatRpc extends EventEmitter {
await this.initWebSocket()
await this.initJsonRpcPeer()
await this.init()
await this.WXInitialize()
}
protected async initJsonRpcPeer(): Promise<void> {
log.verbose('PadchatRpc', 'initJsonRpcPeer()')
if (!this.socket) {
throw new Error('socket had not been opened yet!')
}
this.jsonRpc.on('data', (payload: JsonRpcPayloadRequest) => {
this.jsonRpc.on('data', (buffer: string | Buffer) => {
log.silly('PadchatRpc', 'initJsonRpcPeer() jsonRpc.on(data)')
if (!this.socket) {
throw new Error('no web socket')
}
console.log('jsonRpc.on(data) = ', payload.type, ', ', typeof payload, ': ', payload)
const text = String(buffer)
const payload = parse(text) as JsonRpcPayloadRequest
log.silly('PadchatRpc', 'initJsonRpcPeer() jsonRpc.on(data) buffer="%s"', text)
/**
* A Gateway at here:
*
* 1. Convert Payload format from JsonRpc to Padchat, then
* 2. Send payload to padchat server
*
*/
const encodedParam = (payload.params as JsonRpcParamsSchemaByPositional).map(encodeURIComponent)
const message: PadchatRpcRequest = {
......@@ -109,6 +124,8 @@ export class PadchatRpc extends EventEmitter {
param: encodedParam,
}
log.silly('PadchatRpc', 'initJsonRpcPeer() jsonRpc.on(data) converted to padchat payload="%s"', JSON.stringify(message))
this.socket.send(JSON.stringify(message))
})
}
......@@ -215,12 +232,12 @@ export class PadchatRpc extends EventEmitter {
// })
}
protected onServer(payload: PadchatPayload) {
console.log('server payload:', payload)
log.verbose('PuppetPadchatBridge', 'onWebSocket(%s)',
JSON.stringify(payload).substr(0, 140),
log.verbose('PuppetPadchatBridge', 'onServer(payload.length=%d)',
JSON.stringify(payload).length,
)
// console.log('server payload:', payload)
// check logout:
if (payload.type === PadchatPayloadType.Logout) {
// this.emit('logout', this.selfId())
......@@ -282,42 +299,46 @@ export class PadchatRpc extends EventEmitter {
})
}
protected onServerPadchat(payload: PadchatPayload) {
console.log('onServerMessagePadChat:', payload)
protected onServerPadchat(padchatPayload: PadchatPayload) {
log.verbose('PuppetPadchatBridge', 'onServerPadchat({apiName="%s", msgId="%s", ...})',
padchatPayload.apiName,
padchatPayload.msgId,
)
// padchatPayload:
// {
// "apiName": "WXHeartBeat",
// "data": "%7B%22status%22%3A0%2C%22message%22%3A%22ok%22%7D",
// "msgId": "abc231923912983",
// "userId": "test"
// }
log.silly('PuppetPadchatBridge', 'onServerPadchat(%s)', JSON.stringify(padchatPayload).substr(0, 500))
// check logout:
if (payload.type === PadchatPayloadType.Logout) {
if (padchatPayload.type === PadchatPayloadType.Logout) {
// this.emit('logout', this.selfId())
this.emit('logout')
}
log.silly('PuppetPadchatBridge', 'return apiName: %s, msgId: %s', payload.apiName, payload.msgId)
let result: any
if (payload.data) {
result = JSON.parse(decodeURIComponent(payload.data))
if (padchatPayload.data) {
result = JSON.parse(decodeURIComponent(padchatPayload.data))
} else {
log.silly('PuppetPadchatBridge', 'onServerMessagePadchat() discard empty payload.data for apiName: %s', payload.apiName)
log.silly('PuppetPadchatBridge', 'onServerMessagePadchat() discard empty payload.data for apiName: %s', padchatPayload.apiName)
result = {}
}
const jsonRpcResponse: JsonRpcPayloadResponse = {
id: payload.msgId,
id: padchatPayload.msgId,
jsonrpc: '2.0',
result: result,
type: 'response',
}
this.jsonRpc.write(jsonRpcResponse)
const responseText = JSON.stringify(jsonRpcResponse)
log.silly('PuppetPadchatBridge', 'onServerPadchat() converted to JsonRpc payload="%s"', responseText.substr(0, 500))
// rawWebSocketData:
// {
// "apiName": "WXHeartBeat",
// "data": "%7B%22status%22%3A0%2C%22message%22%3A%22ok%22%7D",
// "msgId": "abc231923912983",
// "userId": "test"
// }
this.jsonRpc.write(responseText)
// if (resolverDict[msgId]) {
// const resolve = resolverDict[msgId]
......
......@@ -141,32 +141,32 @@ export class PuppetPadchat extends Puppet {
// feed the dog, heartbeat the puppet.
// puppet.emit('heartbeat', food.data)
const feedAfterTenSeconds = async () => {
this.bridge.WXHeartBeat()
.then(() => {
this.emit('watchdog', {
data: 'WXHeartBeat()',
})
})
.catch(e => {
log.warn('PuppetPadchat', 'initWatchdogForPuppet() feedAfterTenSeconds rejected: %s', e && e.message || '')
})
}
setTimeout(feedAfterTenSeconds, 15 * 1000)
// const feedAfterTenSeconds = async () => {
// this.bridge.WXHeartBeat()
// .then(() => {
// this.emit('watchdog', {
// data: 'WXHeartBeat()',
// })
// })
// .catch(e => {
// log.warn('PuppetPadchat', 'initWatchdogForPuppet() feedAfterTenSeconds rejected: %s', e && e.message || '')
// })
// }
// setTimeout(feedAfterTenSeconds, 15 * 1000)
})
// this.watchdog.on('reset', async (food, timeout) => {
// log.warn('PuppetPadchat', 'initWatchdogForPuppet() dog.on(reset) last food:%s, timeout:%s',
// food.data, timeout)
this.watchdog.on('reset', async (food, timeout) => {
log.warn('PuppetPadchat', 'initWatchdogForPuppet() dog.on(reset) last food:%s, timeout:%s',
food.data, timeout)
// try {
// await this.stop()
// await this.start()
// } catch (e) {
// puppet.emit('error', e)
// }
// })
})
this.emit('watchdog', {
data: 'inited',
......
......@@ -707,7 +707,7 @@ export class Wechaty extends Accessory implements Sayable {
await this.puppet.start()
} catch (e) {
// console.log(e)
console.error(e)
log.error('Wechaty', 'start() exception: %s', e && e.message)
Raven.captureException(e)
throw e
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册