@juzi/wechaty-puppet-whatsapp
Version:
Wechaty Puppet for WhatsApp
302 lines • 11.5 kB
JavaScript
/**
* Wechaty - https://github.com/chatie/wechaty
*
* @copyright 2016-2018 Huan LI <zixia@zixia.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import * as PUPPET from '@juzi/wechaty-puppet';
import { log } from '@juzi/wechaty-puppet';
import { VERSION, } from './config.js';
import Manager from './manager.js';
import WAError from './exception/whatsapp-error.js';
import { WA_ERROR_TYPE } from './exception/error-type.js';
import { EventName } from './schema/event-name.js';
import { RequestPool } from './request/request-pool.js';
import { contactSelfQRCode, contactSelfName, contactSelfSignature } from './puppet-mixin/contact-self.js';
import { contactAlias, contactPhone, contactCorporationRemark, contactDescription, contactList, contactAvatar, contactRawPayloadParser, contactRawPayload } from './puppet-mixin/contact.js';
import { conversationReadMark } from './puppet-mixin/conversation.js';
import { friendshipRawPayload, friendshipRawPayloadParser, friendshipSearchPhone, friendshipSearchWeixin, friendshipAdd, friendshipAccept, friendshipSearchHandle } from './puppet-mixin/friendship.js';
import { messageContact, messageImage, messageRecall, messageFile, messageUrl, messageMiniProgram, messageSendText, messageSendFile, messageSendContact, messageSendUrl, messageSendMiniProgram, messageForward, messageRawPayloadParser, messageRawPayload, messagePost, messageSendChannel, messageChannel, messageSendLocation, messageLocation } from './puppet-mixin/message.js';
import { roomRawPayloadParser, roomRawPayload, roomList, roomDel, roomAvatar, roomAdd, roomTopic, roomCreate, roomQuit, roomQRCode, roomMemberList, roomMemberRawPayload, roomMemberRawPayloadParser, roomAnnounce, roomInvitationAccept, roomInvitationRawPayload, roomInvitationRawPayloadParser } from './puppet-mixin/room.js';
import { tagContactTagAdd, tagContactTagList, tagContactTagRemove, tagGroupAdd, tagGroupDelete, tagGroupList, tagGroupTagList, tagTagAdd, tagTagContactList, tagTagDelete, tagTagList } from './puppet-mixin/tag.js';
const PRE = 'PuppetWhatsapp';
class PuppetWhatsapp extends PUPPET.Puppet {
options;
static VERSION = VERSION;
manager;
constructor(options = {}) {
super(options);
this.options = options;
log.verbose(PRE, 'constructor()');
this.manager = new Manager(this.options);
}
version() {
return VERSION;
}
async onStart() {
log.verbose(PRE, 'onStart()');
let whatsapp;
try {
whatsapp = await this.startManager(this.manager);
}
catch (err) {
log.error(PRE, `Can not start whatsapp, error: ${err.message}`);
throw WAError(WA_ERROR_TYPE.ERR_INIT, `Can not start whatsapp, error: ${err.message}`);
}
/**
* Huan(202102): Wait for Puppeteer to be inited before resolve start() for robust state management
*/
const future = new Promise(resolve => {
function check() {
if (whatsapp.pupBrowser) {
resolve();
}
else {
setTimeout(check, 100);
}
}
check();
});
return Promise.race([
future,
this.state.stable('inactive'),
]);
}
async startManager(manager) {
manager.on({
dirty: data => {
this.emit('dirty', data);
},
error: this.onError.bind(this),
friendship: this.onFriendship.bind(this),
heartbeat: data => this.emit('heartbeat', {
data,
}),
login: this.onLogin.bind(this),
logout: this.onLogout.bind(this),
message: this.onMessage.bind(this),
ready: this.onReady.bind(this),
reset: this.onReset.bind(this),
'room-invite': this.onRoomInvite.bind(this),
'room-join': this.onRoomJoin.bind(this),
'room-leave': this.onRoomLeave.bind(this),
'room-topic': this.onRoomTopic.bind(this),
'room-announce': this.onRoomAnnounce.bind(this),
scan: this.onScan.bind(this),
});
const memory = this.memory;
const whatsapp = await this.manager.start(memory);
return whatsapp;
}
async onStop() {
log.verbose(PRE, 'onStop()');
try {
await this.stopManager();
}
catch (err) {
log.error(PRE, `Can not stop, error: ${err.message}`);
}
}
async stopManager() {
this.manager.off('*');
await this.manager.stop();
}
/**
* Event section: onXXX
*/
async onLogin(wxid) {
log.verbose(PRE, 'onLogin(%s)', wxid);
if (this.isLoggedIn) {
log.warn(PRE, 'onLogin(%s) already login? NOOP', wxid);
return;
}
log.info(PRE, `${EventName.LOGIN}, ${wxid}`);
await super.login(wxid);
// no need to emit login since super.login will do that
// this.emit('login', { contactId: wxid })
}
async onLogout(wxid, message) {
log.verbose(PRE, 'onLogout(%s, %s)', wxid, message);
if (!this.isLoggedIn) {
log.warn(PRE, 'onLogout(%s) already logged out?', wxid);
}
log.info(PRE, `${EventName.LOGOUT}, ${wxid}`);
const requestPool = RequestPool.Instance;
requestPool.clearPool();
this.emit('logout', { contactId: wxid, data: message });
}
async onMessage(message) {
log.verbose(PRE, 'onMessage(%s)', JSON.stringify(message));
this.emit('message', message);
}
async onScan(payload) {
log.verbose(PRE, 'onScan(%s)', JSON.stringify(payload));
log.info(PRE, `${EventName.SCAN}`);
this.emit('scan', payload);
}
async onError(e) {
log.info(PRE, `${EventName.ERROR}, ${e}`);
this.emit('error', {
data: e,
});
}
async onReset(reason) {
log.info(PRE, `${EventName.RESET}, ${reason}`);
this.emit('reset', { data: reason });
}
async onFriendship(payload) {
const friendshipPayload = await this.friendshipRawPayload(payload.friendshipId);
if (friendshipPayload.type === PUPPET.types.Friendship.Receive) {
// 收到好友请求暂不冒泡,直接接受
await this.friendshipAccept(payload.friendshipId);
return;
}
this.emit('friendship', payload);
}
async onRoomJoin(payload) {
const roomId = payload.roomId;
await this.dirtyPayload(PUPPET.types.Payload.Room, roomId);
this.emit('room-join', payload);
}
async onRoomLeave(payload) {
const roomId = payload.roomId;
await this.dirtyPayload(PUPPET.types.Payload.Room, roomId);
this.emit('room-leave', payload);
}
async onRoomTopic(payload) {
const roomId = payload.roomId;
await this.dirtyPayload(PUPPET.types.Payload.Room, roomId);
this.emit('room-topic', payload);
}
async onRoomInvite(payload) {
this.emit('room-invite', payload);
}
async onRoomAnnounce(payload) {
const roomId = payload.roomId;
await this.dirtyPayload(PUPPET.types.Payload.Room, roomId);
this.emit('room-announce', payload);
}
async onReady() {
log.verbose(PRE, 'onReady()');
log.info(PRE, `${EventName.READY}`);
this.emit('ready', { data: 'ready' });
}
/**
* Override Methods
*/
async logout() {
await super.logout();
if (!this.isLoggedIn) {
log.verbose(PRE, 'logout() do nothing');
return;
}
return this.manager.logout();
}
ding(data) {
log.silly(PRE, 'ding(%s)', data || '');
setTimeout(() => this.emit('dong', { data: data || '' }), 1000);
}
/**
* ContactSelf
*/
contactSelfQRCode = contactSelfQRCode;
contactSelfName = contactSelfName;
contactSelfSignature = contactSelfSignature;
/**
* Contact
*/
contactAlias = contactAlias;
contactPhone = contactPhone;
contactCorporationRemark = contactCorporationRemark;
contactDescription = contactDescription;
contactList = contactList;
contactAvatar = contactAvatar;
contactRawPayloadParser = contactRawPayloadParser;
contactRawPayload = contactRawPayload;
/**
* Conversation
*/
conversationReadMark = conversationReadMark;
/**
* Message
*/
// FIXME: need to implement in wechaty-puppet
messagePost = messagePost;
messageContact = messageContact;
messageImage = messageImage;
messageRecall = messageRecall;
messageFile = messageFile;
messageUrl = messageUrl;
messageMiniProgram = messageMiniProgram;
messageChannel = messageChannel;
messageSendText = messageSendText;
messageSendFile = messageSendFile;
messageSendContact = messageSendContact;
messageSendUrl = messageSendUrl;
messageSendMiniProgram = messageSendMiniProgram;
messageSendChannel = messageSendChannel;
messageSendLocation = messageSendLocation;
messageLocation = messageLocation;
messageForward = messageForward;
messageRawPayloadParser = messageRawPayloadParser;
messageRawPayload = messageRawPayload;
/**
* Room
*/
roomRawPayloadParser = roomRawPayloadParser;
roomRawPayload = roomRawPayload;
roomList = roomList;
roomDel = roomDel;
roomAvatar = roomAvatar;
roomAdd = roomAdd;
roomTopic = roomTopic;
roomCreate = roomCreate;
roomQuit = roomQuit;
roomQRCode = roomQRCode;
roomMemberList = roomMemberList;
roomMemberRawPayload = roomMemberRawPayload;
roomMemberRawPayloadParser = roomMemberRawPayloadParser;
roomAnnounce = roomAnnounce;
roomInvitationAccept = roomInvitationAccept;
roomInvitationRawPayload = roomInvitationRawPayload;
roomInvitationRawPayloadParser = roomInvitationRawPayloadParser;
/**
* Friendship
*/
friendshipRawPayload = friendshipRawPayload;
friendshipRawPayloadParser = friendshipRawPayloadParser;
friendshipSearchPhone = friendshipSearchPhone;
friendshipSearchWeixin = friendshipSearchWeixin;
friendshipSearchHandle = friendshipSearchHandle;
friendshipAdd = friendshipAdd;
friendshipAccept = friendshipAccept;
/**
* Tag
*/
tagContactTagAdd = tagContactTagAdd;
tagContactTagRemove = tagContactTagRemove;
tagContactTagList = tagContactTagList;
tagGroupAdd = tagGroupAdd;
tagGroupDelete = tagGroupDelete;
tagGroupList = tagGroupList;
tagGroupTagList = tagGroupTagList;
tagTagAdd = tagTagAdd;
tagTagDelete = tagTagDelete;
tagTagList = tagTagList;
tagTagContactList = tagTagContactList;
}
export { PuppetWhatsapp };
export default PuppetWhatsapp;
//# sourceMappingURL=puppet-whatsapp.js.map