mirror of
https://github.com/cheveguerra/whatsapp-web.js.git
synced 2026-04-20 20:49:14 +00:00
Add group chat functions, slight refactoring
This commit is contained in:
52
example.js
52
example.js
@@ -1,4 +1,4 @@
|
|||||||
const { Client } = require('./src')
|
const { Client } = require('./index')
|
||||||
|
|
||||||
const client = new Client({puppeteer: {headless: false}});
|
const client = new Client({puppeteer: {headless: false}});
|
||||||
|
|
||||||
@@ -16,16 +16,60 @@ client.on('ready', () => {
|
|||||||
console.log('READY');
|
console.log('READY');
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('message', (msg) => {
|
client.on('message', async msg => {
|
||||||
console.log('MESSAGE RECEIVED', msg);
|
console.log('MESSAGE RECEIVED', msg);
|
||||||
|
|
||||||
if (msg.body == 'ping reply') {
|
if (msg.body == '!ping reply') {
|
||||||
// Send a new message as a reply to the current one
|
// Send a new message as a reply to the current one
|
||||||
msg.reply('pong');
|
msg.reply('pong');
|
||||||
|
|
||||||
} else if (msg.body == 'ping') {
|
} else if (msg.body == '!ping') {
|
||||||
// Send a new message to the same chat
|
// Send a new message to the same chat
|
||||||
client.sendMessage(msg.from, 'pong');
|
client.sendMessage(msg.from, 'pong');
|
||||||
|
|
||||||
|
} else if (msg.body.startsWith('!subject ')) {
|
||||||
|
// Change the group subject
|
||||||
|
let chat = await msg.getChat();
|
||||||
|
if(chat.isGroup) {
|
||||||
|
let newSubject = msg.body.slice(9);
|
||||||
|
chat.setSubject(newSubject);
|
||||||
|
} else {
|
||||||
|
msg.reply('This command can only be used in a group!');
|
||||||
|
}
|
||||||
|
} else if (msg.body.startsWith('!echo ')) {
|
||||||
|
// Replies with the same message
|
||||||
|
msg.reply(msg.body.slice(6));
|
||||||
|
} else if (msg.body.startsWith('!desc ')) {
|
||||||
|
// Change the group description
|
||||||
|
let chat = await msg.getChat();
|
||||||
|
if(chat.isGroup) {
|
||||||
|
let newDescription = msg.body.slice(6);
|
||||||
|
chat.setDescription(newDescription);
|
||||||
|
} else {
|
||||||
|
msg.reply('This command can only be used in a group!');
|
||||||
|
}
|
||||||
|
} else if (msg.body == '!leave') {
|
||||||
|
// Leave the group
|
||||||
|
let chat = await msg.getChat();
|
||||||
|
if(chat.isGroup) {
|
||||||
|
chat.leave();
|
||||||
|
} else {
|
||||||
|
msg.reply('This command can only be used in a group!');
|
||||||
|
}
|
||||||
|
} else if(msg.body == '!groupinfo') {
|
||||||
|
let chat = await msg.getChat();
|
||||||
|
if(chat.isGroup) {
|
||||||
|
msg.reply(`
|
||||||
|
*Group Details*
|
||||||
|
Name: ${chat.name}
|
||||||
|
Description: ${chat.description}
|
||||||
|
Created At: ${chat.createdAt.toString()}
|
||||||
|
Created By: ${chat.owner.user}
|
||||||
|
Participant count: ${chat.participants.length}
|
||||||
|
`);
|
||||||
|
} else {
|
||||||
|
msg.reply('This command can only be used in a group!');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
13
index.js
Normal file
13
index.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Client: require('./src/Client'),
|
||||||
|
|
||||||
|
version: require('./package.json').version,
|
||||||
|
|
||||||
|
// Structures
|
||||||
|
Chat: require('./src/structures/Chat'),
|
||||||
|
PrivateChat: require('./src/structures/PrivateChat'),
|
||||||
|
GroupChat: require('./src/structures/GroupChat'),
|
||||||
|
Message: require('./src/structures/Message')
|
||||||
|
};
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "whatsapp-web.js",
|
"name": "whatsapp-web.js",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Library for interacting with the WhatsApp Web API ",
|
"description": "Library for interacting with the WhatsApp Web API ",
|
||||||
"main": "./src/index.js",
|
"main": "./index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const puppeteer = require('puppeteer');
|
const puppeteer = require('puppeteer');
|
||||||
const Util = require('../util/Util');
|
const Util = require('./util/Util');
|
||||||
const { WhatsWebURL, UserAgent, DefaultOptions, Events } = require('../util/Constants');
|
const { WhatsWebURL, UserAgent, DefaultOptions, Events } = require('./util/Constants');
|
||||||
const { ExposeStore, LoadExtraProps } = require('../util/Injected');
|
const { ExposeStore, LoadExtraProps, LoadCustomSerializers } = require('./util/Injected');
|
||||||
const Chat = require('../models/Chat');
|
const ChatFactory = require('./factories/ChatFactory');
|
||||||
const Message = require('../models/Message')
|
const Chat = require('./structures/Chat');
|
||||||
|
const Message = require('./structures/Message')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starting point for interacting with the WhatsApp Web API
|
* Starting point for interacting with the WhatsApp Web API
|
||||||
@@ -22,6 +23,9 @@ class Client extends EventEmitter {
|
|||||||
this.pupPage = null;
|
this.pupPage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up events and requirements, kicks off authentication request
|
||||||
|
*/
|
||||||
async initialize() {
|
async initialize() {
|
||||||
const browser = await puppeteer.launch(this.options.puppeteer);
|
const browser = await puppeteer.launch(this.options.puppeteer);
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
@@ -43,12 +47,14 @@ class Client extends EventEmitter {
|
|||||||
// Check Store Injection
|
// Check Store Injection
|
||||||
await page.waitForFunction('window.Store != undefined');
|
await page.waitForFunction('window.Store != undefined');
|
||||||
|
|
||||||
// Load extra serialized props
|
//Load extra serialized props
|
||||||
const models = [Chat, Message];
|
const models = [Message];
|
||||||
for (let model of models) {
|
for (let model of models) {
|
||||||
await page.evaluate(LoadExtraProps, model.WAppModel, model.extraFields);
|
await page.evaluate(LoadExtraProps, model.WAppModel, model.extraFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await page.evaluate(LoadCustomSerializers);
|
||||||
|
|
||||||
// Register events
|
// Register events
|
||||||
await page.exposeFunction('onAddMessageEvent', msg => {
|
await page.exposeFunction('onAddMessageEvent', msg => {
|
||||||
if (msg.id.fromMe || !msg.isNewMsg) return;
|
if (msg.id.fromMe || !msg.isNewMsg) return;
|
||||||
@@ -77,26 +83,39 @@ class Client extends EventEmitter {
|
|||||||
await this.pupBrowser.close();
|
await this.pupBrowser.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to a specific chatId
|
||||||
|
* @param {string} chatId
|
||||||
|
* @param {string} message
|
||||||
|
*/
|
||||||
async sendMessage(chatId, message) {
|
async sendMessage(chatId, message) {
|
||||||
await this.pupPage.evaluate((chatId, message) => {
|
await this.pupPage.evaluate((chatId, message) => {
|
||||||
Store.Chat.get(chatId).sendMessage(message);
|
Store.Chat.get(chatId).sendMessage(message);
|
||||||
}, chatId, message)
|
}, chatId, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all current chat instances
|
||||||
|
*/
|
||||||
async getChats() {
|
async getChats() {
|
||||||
let chats = await this.pupPage.evaluate(() => {
|
// let chats = await this.pupPage.evaluate(() => {
|
||||||
return Store.Chat.serialize()
|
// return Store.Chat.serialize()
|
||||||
});
|
// });
|
||||||
|
|
||||||
return chats.map(chatData => new Chat(this, chatData));
|
// return chats.map(chatData => ChatFactory.create(this, chatData));
|
||||||
|
throw new Error('NOT IMPLEMENTED')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get chat instance by ID
|
||||||
|
* @param {string} chatId
|
||||||
|
*/
|
||||||
async getChatById(chatId) {
|
async getChatById(chatId) {
|
||||||
let chat = await this.pupPage.evaluate(chatId => {
|
let chat = await this.pupPage.evaluate(chatId => {
|
||||||
return Store.Chat.get(chatId).serialize();
|
return WWebJS.getChat(chatId);
|
||||||
}, chatId);
|
}, chatId);
|
||||||
|
|
||||||
return new Chat(this, chat);
|
return ChatFactory.create(this, chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
16
src/factories/ChatFactory.js
Normal file
16
src/factories/ChatFactory.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const PrivateChat = require('../structures/PrivateChat');
|
||||||
|
const GroupChat = require('../structures/GroupChat');
|
||||||
|
|
||||||
|
class ChatFactory {
|
||||||
|
static create(client, data) {
|
||||||
|
if(data.isGroup) {
|
||||||
|
return new GroupChat(client, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PrivateChat(client, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ChatFactory;
|
||||||
10
src/index.js
10
src/index.js
@@ -1,10 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
Client: require('./client/Client'),
|
|
||||||
version: require('../package.json').version,
|
|
||||||
|
|
||||||
// Models
|
|
||||||
Chat: require('./models/Chat'),
|
|
||||||
Message: require('./models/Message')
|
|
||||||
};
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a data model
|
* Represents a WhatsApp data structure
|
||||||
*/
|
*/
|
||||||
class Base {
|
class Base {
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
@@ -16,23 +16,18 @@ class Chat extends Base {
|
|||||||
_patch(data) {
|
_patch(data) {
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
|
|
||||||
|
this.name = data.formattedTitle;
|
||||||
this.isGroup = data.isGroup;
|
this.isGroup = data.isGroup;
|
||||||
this.isReadOnly = data.isReadOnly;
|
this.isReadOnly = data.isReadOnly;
|
||||||
this.name = data.name;
|
|
||||||
this.unreadCount = data.unreadCount;
|
this.unreadCount = data.unreadCount;
|
||||||
this.timestamp = data.t;
|
this.timestamp = data.t;
|
||||||
|
|
||||||
|
return super._patch(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(message) {
|
sendMessage(message) {
|
||||||
return this.client.sendMessage(this.id._serialized, message);
|
return this.client.sendMessage(this.id._serialized, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get extraFields() {
|
|
||||||
return [
|
|
||||||
'formattedTitle',
|
|
||||||
'isGroup'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Chat;
|
module.exports = Chat;
|
||||||
166
src/structures/GroupChat.js
Normal file
166
src/structures/GroupChat.js
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Chat = require('./Chat');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Group Chat on WhatsApp
|
||||||
|
* @extends {Chat}
|
||||||
|
*/
|
||||||
|
class GroupChat extends Chat {
|
||||||
|
_patch(data) {
|
||||||
|
this.groupMetadata = data.groupMetadata;
|
||||||
|
|
||||||
|
return super._patch(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the group owner
|
||||||
|
*/
|
||||||
|
get owner() {
|
||||||
|
return this.groupMetadata.owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date at which the group was created
|
||||||
|
*/
|
||||||
|
get createdAt() {
|
||||||
|
return new Date(this.groupMetadata.creation * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the group description
|
||||||
|
*/
|
||||||
|
get description() {
|
||||||
|
return this.groupMetadata.desc;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the group participants
|
||||||
|
*/
|
||||||
|
get participants() {
|
||||||
|
return this.groupMetadata.participants;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a list of participants by ID to the group
|
||||||
|
* @param {Array[string]} participantIds
|
||||||
|
*/
|
||||||
|
async addParticipants(participantIds) {
|
||||||
|
return await this.client.pupPage.evaluate((chatId, participantIds) => {
|
||||||
|
return Store.Wap.addParticipants(chatId, participantIds);
|
||||||
|
}, this.id._serialized, participantIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a list of participants by ID to the group
|
||||||
|
* @param {Array[string]} participantIds
|
||||||
|
*/
|
||||||
|
async removeParticipants(participantIds) {
|
||||||
|
return await this.client.pupPage.evaluate((chatId, participantIds) => {
|
||||||
|
return Store.Wap.removeParticipants(chatId, participantIds);
|
||||||
|
}, this.id._serialized, participantIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Promotes participants by IDs to admins
|
||||||
|
* @param {Array[string]} participantIds
|
||||||
|
*/
|
||||||
|
async promoteParticipants(participantIds) {
|
||||||
|
return await this.client.pupPage.evaluate((chatId, participantIds) => {
|
||||||
|
return Store.Wap.promoteParticipants(chatId, participantIds);
|
||||||
|
}, this.id._serialized, participantIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demotes participants by IDs to regular users
|
||||||
|
* @param {Array[string]} participantIds
|
||||||
|
*/
|
||||||
|
async demoteParticipants(participantIds) {
|
||||||
|
return await this.client.pupPage.evaluate((chatId, participantIds) => {
|
||||||
|
return Store.Wap.demoteParticipants(chatId, participantIds);
|
||||||
|
}, this.id._serialized, participantIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the group subject
|
||||||
|
* @param {string} subject
|
||||||
|
*/
|
||||||
|
async setSubject(subject) {
|
||||||
|
let res = await this.client.pupPage.evaluate((chatId, subject) => {
|
||||||
|
return Store.Chat.get(chatId).setSubject(subject);
|
||||||
|
}, this.id._serialized, subject);
|
||||||
|
|
||||||
|
if(res.status == 200) {
|
||||||
|
this.name = subject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the group description
|
||||||
|
* @param {string} description
|
||||||
|
*/
|
||||||
|
async setDescription(description) {
|
||||||
|
let res = await this.client.pupPage.evaluate((chatId, description) => {
|
||||||
|
return Store.Chat.get(chatId).setGroupDesc(description);
|
||||||
|
}, this.id._serialized, description);
|
||||||
|
|
||||||
|
if (res.status == 200) {
|
||||||
|
this.groupMetadata.desc = description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the invite code for a specific group
|
||||||
|
*/
|
||||||
|
async getInviteCode() {
|
||||||
|
let res = await this.client.pupPage.evaluate(chatId => {
|
||||||
|
return Store.Wap.groupInviteCode(chatId);
|
||||||
|
}, this.id._serialized);
|
||||||
|
|
||||||
|
if (res.status == 200) {
|
||||||
|
return res.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Not authorized')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates the current group invite code and generates a new one
|
||||||
|
*/
|
||||||
|
async revokeInvite() {
|
||||||
|
return await this.client.pupPage.evaluate(chatId => {
|
||||||
|
return Store.Wap.revokeGroupInvite(chatId);
|
||||||
|
}, chatId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object with information about the invite code's group
|
||||||
|
* @param {string} inviteCode
|
||||||
|
*/
|
||||||
|
static async getInviteInfo(inviteCode) {
|
||||||
|
return await this.client.pupPage.evaluate(inviteCode => {
|
||||||
|
return Store.Wap.groupInviteInfo(inviteCode);
|
||||||
|
}, inviteCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins a group with an invite code
|
||||||
|
* @param {string} inviteCode
|
||||||
|
*/
|
||||||
|
static async join(inviteCode) {
|
||||||
|
return await this.client.pupPage.evaluate(inviteCode => {
|
||||||
|
return Store.Wap.acceptGroupInvite(inviteCode);
|
||||||
|
}, inviteCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the bot leave the group
|
||||||
|
*/
|
||||||
|
async leave() {
|
||||||
|
return await this.client.pupPage.evaluate(chatId => {
|
||||||
|
return Store.Wap.leaveGroup(chatId);
|
||||||
|
}, this.id._serialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = GroupChat;
|
||||||
@@ -23,6 +23,8 @@ class Message extends Base {
|
|||||||
this.author = data.author;
|
this.author = data.author;
|
||||||
this.isForwarded = data.isForwarded;
|
this.isForwarded = data.isForwarded;
|
||||||
this.broadcast = data.broadcast;
|
this.broadcast = data.broadcast;
|
||||||
|
|
||||||
|
return super._patch(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
13
src/structures/PrivateChat.js
Normal file
13
src/structures/PrivateChat.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Chat = require('./Chat');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Private Chat on WhatsApp
|
||||||
|
* @extends {Chat}
|
||||||
|
*/
|
||||||
|
class PrivateChat extends Chat {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = PrivateChat;
|
||||||
@@ -56,6 +56,27 @@ exports.LoadExtraProps = (model, props) => {
|
|||||||
Store[model].models[0].__props = Store[model].models[0].__props.concat(props);
|
Store[model].models[0].__props = Store[model].models[0].__props.concat(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.LoadCustomSerializers = () => {
|
||||||
|
window.WWebJS = {};
|
||||||
|
|
||||||
|
window.WWebJS.getChatModel = chat => {
|
||||||
|
let res = chat.serialize();
|
||||||
|
res.isGroup = chat.isGroup;
|
||||||
|
res.formattedTitle = chat.formattedTitle;
|
||||||
|
|
||||||
|
if(chat.groupMetadata) {
|
||||||
|
res.groupMetadata = chat.groupMetadata.serialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.WWebJS.getChat = chatId => {
|
||||||
|
const chat = Store.Chat.get(chatId);
|
||||||
|
return WWebJS.getChatModel(chat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exports.MarkAllRead = () => {
|
exports.MarkAllRead = () => {
|
||||||
let Chats = Store.Chat.models;
|
let Chats = Store.Chat.models;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user