Skip to content

Commit

Permalink
feat: listen to group events (pedroslopez#90)
Browse files Browse the repository at this point in the history
This allows you to listen for user joins or leaves, description updates, subject updates, picture updates, and group settings updates.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
  • Loading branch information
aliyss and pedroslopez authored Mar 1, 2020
1 parent 588dc93 commit 48b9ae1
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 2 deletions.
17 changes: 17 additions & 0 deletions example.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,23 @@ client.on('message_ack', (msg, ack) => {
}
});

client.on('group_join', (notification) => {
// User has joined or been added to the group.
console.log('join', notification);
notification.reply('User joined.');
});

client.on('group_leave', (notification) => {
// User has left or been kicked from the group.
console.log('leave', notification);
notification.reply('User left.');
});

client.on('group_update', (notification) => {
// Group picture, subject or description has been updated.
console.log('update', notification);
});

client.on('disconnected', (reason) => {
console.log('Client was logged out', reason);
});
Expand Down
15 changes: 13 additions & 2 deletions src/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ const { WhatsWebURL, UserAgent, DefaultOptions, Events, WAState } = require('./u
const { ExposeStore, LoadUtils } = require('./util/Injected');
const ChatFactory = require('./factories/ChatFactory');
const ContactFactory = require('./factories/ContactFactory');
const { ClientInfo, Message, MessageMedia, Location } = require('./structures');

const { ClientInfo, Message, MessageMedia, Location, GroupNotification } = require('./structures');
/**
* Starting point for interacting with the WhatsApp Web API
* @extends {EventEmitter}
Expand Down Expand Up @@ -146,6 +145,18 @@ class Client extends EventEmitter {
await page.exposeFunction('onAddMessageEvent', msg => {
if (!msg.isNewMsg) return;

if (msg.type === 'gp2') {
const notification = new GroupNotification(this, msg);
if (msg.subtype === 'add' || msg.subtype === 'invite') {
this.emit(Events.GROUP_JOIN, notification);
} else if (msg.subtype === 'remove' || msg.subtype === 'leave') {
this.emit(Events.GROUP_LEAVE, notification);
} else {
this.emit(Events.GROUP_UPDATE, notification);
}
return;
}

const message = new Message(this, msg);

/**
Expand Down
104 changes: 104 additions & 0 deletions src/structures/GroupNotification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';

const Base = require('./Base');

/**
* Represents a GroupNotification on WhatsApp
* @extends {Base}
*/
class GroupNotification extends Base {
constructor(client, data) {
super(client);

if(data) this._patch(data);
}

_patch(data) {
/**
* ID that represents the groupNotification
* @type {object}
*/
this.id = data.id;

/**
* Extra content
* @type {string}
*/
this.body = data.body || '';

/**
* GroupNotification type
* @type {GroupNotificationTypes}
*/
this.type = data.subtype;

/**
* Unix timestamp for when the groupNotification was created
* @type {number}
*/
this.timestamp = data.t;

/**
* ID for the Chat that this groupNotification was sent for.
*
* @type {string}
*/
this.chatId = typeof (data.to) === 'object' ? data.to._serialized : data.to;

/**
* ContactId for the user that produced the GroupNotification.
* @type {string}
*/
this.author = typeof (data.author) === 'object' ? data.author._serialized : data.author;

/**
* Contact IDs for the users that were affected by this GroupNotification.
* @type {Array<string>}
*/
this.recipientIds = [];

if (data.recipients) {
this.recipientIds = data.recipients;
}

return super._patch(data);
}

/**
* Returns the Chat this groupNotification was sent in
* @returns {Promise<Chat>}
*/
getChat() {
return this.client.getChatById(this.chatId);
}

/**
* Returns the Contact this GroupNotification was produced by
* @returns {Promise<Contact>}
*/
getContact() {
return this.client.getContactById(this.author);
}

/**
* Returns the Contacts affected by this GroupNotification.
* @returns {Promise<Array<Contact>>}
*/
async getRecipients() {
return await Promise.all(this.recipientIds.map(async m => await this.client.getContactById(m)));
}

/**
* Sends a message to the same chat this GroupNotification was produced in.
*
* @param {string|MessageMedia|Location} content
* @param {object} options
* @returns {Promise<Message>}
*/
async reply(content, options={}) {
return this.client.sendMessage(this.chatId, content, options);
}

}

module.exports = GroupNotification;
20 changes: 20 additions & 0 deletions src/util/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ exports.Events = {
MESSAGE_REVOKED_EVERYONE: 'message_revoke_everyone',
MESSAGE_REVOKED_ME: 'message_revoke_me',
MESSAGE_ACK: 'message_ack',
GROUP_JOIN: 'group_join',
GROUP_LEAVE: 'group_leave',
GROUP_UPDATE: 'group_update',
QR_RECEIVED: 'qr',
DISCONNECTED: 'disconnected',
STATE_CHANGED: 'change_state',
Expand All @@ -61,6 +64,23 @@ exports.MessageTypes = {
UNKNOWN: 'unknown'
};

/**
* Group notification types
* @readonly
* @enum {string}
*/
exports.GroupNotificationTypes = {
ADD: 'add',
INVITE: 'invite',
REMOVE: 'remove',
LEAVE: 'leave',
SUBJECT: 'subject',
DESCRIPTION: 'description',
PICTURE: 'picture',
ANNOUNCE: 'announce',
RESTRICT: 'restrict',
};

/**
* Chat types
* @readonly
Expand Down

0 comments on commit 48b9ae1

Please sign in to comment.