UNPKG

@juzi/wechaty-puppet-whatsapp

Version:
180 lines 7.65 kB
/* eslint-disable no-case-declarations */ import * as PUPPET from '@juzi/wechaty-puppet'; import { MIN_BATTERY_VALUE_FOR_LOGOUT, DEFAULT_TIMEOUT, log, STRINGS, LANGUAGE, } from '../../config.js'; import { WA_ERROR_TYPE } from '../../exception/error-type.js'; import WAError from '../../exception/whatsapp-error.js'; import { WAState, } from '../../schema/whatsapp-interface.js'; import WhatsAppBase from '../whatsapp-base.js'; import { batchProcess, isContactId, isRoomId, sleep, } from '../../helper/miscellaneous.js'; const PRE = 'LoginEventHandler'; export default class LoginEventHandler extends WhatsAppBase { loadingData = false; qrcodeOrLoginCheckTimer; hasLogin = false; lastQRCodeTime = Date.now(); onQRCode(qrcode) { log.info(PRE, `onQRCode(${qrcode})`); // NOTE: This event will not be fired if a session is specified. this.lastQRCodeTime = Date.now(); this.hasLogin = false; this.emit('scan', { qrcode, status: PUPPET.types.ScanStatus.Waiting, timestamp: Date.now() }); this.checkQRCodeOrLoginEvent(); } checkQRCodeOrLoginEvent() { if (this.qrcodeOrLoginCheckTimer) { return; } this.qrcodeOrLoginCheckTimer = setInterval(() => { if (!this.hasLogin && Date.now() > this.lastQRCodeTime + 2 * 60 * 1000) { this.emit('error', 'can not get scan or login event more than 2 mins'); } }, 25 * 1000); } clearQrcodeOrLoginCheckTimer() { if (!this.qrcodeOrLoginCheckTimer) { return; } clearInterval(this.qrcodeOrLoginCheckTimer); } async onAuthenticated() { log.info(PRE, 'onAuthenticated()'); } async onAuthFailure(message) { log.warn(PRE, 'auth_failure: %s', message); // avoid reuse invalid session data await this.clearSession(); } async onWhatsAppReady() { log.verbose(PRE, 'onWhatsAppReady()'); if (this.hasLogin) { log.info(PRE, 'onWhatsAppReady() already login, skip'); return; } this.hasLogin = true; this.clearQrcodeOrLoginCheckTimer(); const whatsapp = this.getWhatsAppClient(); try { this.botId = whatsapp.info.wid._serialized; await this.manager.initCache(this.botId); } catch (error) { throw WAError(WA_ERROR_TYPE.ERR_INIT, `Can not get bot id from WhatsApp client, current state: ${await whatsapp.getState()}`, JSON.stringify(error)); } await this.onLogin(); const contactOrRoomList = await this.manager.syncContactOrRoomList(); await this.onReady(contactOrRoomList); this.manager.startSchedule(); } async onLogin() { log.verbose(PRE, 'onLogin()'); const whatsapp = this.getWhatsAppClient(); log.info(PRE, `WhatsApp Client Info: ${JSON.stringify(whatsapp.info)}`); const cacheManager = await this.manager.getCacheManager(); const botSelf = await this.manager.requestManager.getContactById(this.botId); await cacheManager.setContactOrRoomRawPayload(this.botId, { ...botSelf, avatar: await this.manager.requestManager.getAvatarUrl(this.botId), }); this.emit('login', this.botId); log.info(PRE, `onLogin(${this.botId}})`); } async onReady(contactOrRoomList) { log.verbose(PRE, 'onReady()'); if (this.loadingData) { log.verbose(PRE, 'onReady() loading data are under process.'); return; } this.loadingData = true; let friendCount = 0; let contactCount = 0; let roomCount = 0; const cacheManager = await this.manager.getCacheManager(); const batchSize = 100; await batchProcess(batchSize, contactOrRoomList, async (contactOrRoom) => { const contactOrRoomId = contactOrRoom.id._serialized; const avatar = await contactOrRoom.getProfilePicUrl(); const contactWithAvatar = Object.assign(contactOrRoom, { avatar }); if (isContactId(contactOrRoomId)) { contactCount++; if (contactOrRoom.isMyContact) { friendCount++; } await cacheManager.setContactOrRoomRawPayload(contactOrRoomId, contactWithAvatar); } else if (isRoomId(contactOrRoomId)) { let memberList = []; try { memberList = await this.manager.syncRoomMemberList(contactOrRoomId); } catch (error) { log.warn(PRE, `syncRoomMemberList(${contactOrRoomId}) failed, ${JSON.stringify(error)}`); } if (memberList.length > 0) { roomCount++; await cacheManager.setContactOrRoomRawPayload(contactOrRoomId, contactWithAvatar); } else { await cacheManager.deleteContactOrRoom(contactOrRoomId); await cacheManager.deleteRoomMemberIdList(contactOrRoomId); return; } } else { log.warn(PRE, `Unknown contact type: ${JSON.stringify(contactOrRoom)}`); } await this.manager.processHistoryMessages(contactOrRoom); }); log.info(PRE, `onReady() all contacts and rooms are ready, friendCount: ${friendCount} contactCount: ${contactCount} roomCount: ${roomCount}`); await sleep(15 * 1000); this.emit('ready'); this.loadingData = false; } async onLogout(reason = STRINGS[LANGUAGE].LOGOUT_REASON.DEFAULT) { log.verbose(PRE, `onLogout(${reason})`); await this.clearSession(); this.hasLogin = false; this.manager.stopSchedule(); this.emit('logout', this.getBotId(), reason); this.baseStop(); if (!this.getWhatsAppClient().pupPage) { await this.getWhatsAppClient().initialize(); } } async onChangeState(state) { log.info(PRE, `onChangeState(${JSON.stringify(state)})`); if (!this.botId) { throw WAError(WA_ERROR_TYPE.ERR_INIT, 'No login bot id.'); } switch (state) { case WAState.TIMEOUT: this.pendingLogoutEmitTimer = setTimeout(() => { this.emit('logout', this.getBotId(), STRINGS[LANGUAGE].LOGOUT_REASON.NETWORK_TIMEOUT_IN_PHONE); this.pendingLogoutEmitTimer = undefined; }, DEFAULT_TIMEOUT.TIMEOUT_WAIT_CONNECTED); break; case WAState.CONNECTED: this.clearPendingLogoutEmitTimer(); this.emit('login', this.botId); this.loadingData = false; const contactOrRoomList = await this.manager.syncContactOrRoomList(); await this.onReady(contactOrRoomList); break; default: break; } } /** * unsupported events * leave logs to for further dev */ async onChangeBattery(batteryInfo) { log.verbose(PRE, `onChangeBattery(${JSON.stringify(batteryInfo)})`); if (!this.botId) { throw WAError(WA_ERROR_TYPE.ERR_INIT, 'No login bot id.'); } if (batteryInfo.battery <= MIN_BATTERY_VALUE_FOR_LOGOUT && !batteryInfo.plugged) { this.emit('logout', this.botId, STRINGS[LANGUAGE].LOGOUT_REASON.BATTERY_LOWER_IN_PHONE); } } } //# sourceMappingURL=login-event-handler.js.map