Skip to content

Instantly share code, notes, and snippets.

@PurpShell
Last active December 30, 2022 21:59
Show Gist options
  • Save PurpShell/d7065ad2945f50fecd63a1f6f57b43c4 to your computer and use it in GitHub Desktop.
Save PurpShell/d7065ad2945f50fecd63a1f6f57b43c4 to your computer and use it in GitHub Desktop.
Message Collector for WWebJS v1
const { Message } = require('whatsapp-web.js');
// Message Collectors / Wait for Message
class MessageCollection {
// Internal object to temporarily store msgs
#msgs = {};
// Is the client event handler binded?
isBinded = false;
client = null;
constructor(client) {
this.client = client;
this.bind();
}
/** Ran by default */
bind() {
if (!this.isBinded) this.isBinded = true;
const listener = this.client && this.client?.listeners("messages.upsert").find(a => a === this.#handleMessage);
if (listener) {
throw new Error('Multiple MessageCollection instances for one Client shouldn\'t be made. Instead only make one instance and then use its functions.');
}
this.client.on("message", this.#handleMessage);
}
/** Unbind the client event handler */
unbind() {
this.client.off("message", this.#handleMessage);
}
/**
* Function to cancel all concurrent jobs
*/
cancelAll() {
for (const job in this.#msgs) {
clearTimeout(this.#msgs[job].timeout);
this.#msgs[job].reject(new Error("Job canceled"));
this.#msgs[job].resolve(this.#msgs[job].msgs);
delete this.#msgs[job];
}
}
/** A function to wait for messages
* @param {Object} options - Wait for message options
* @param {?number} options.timeout - Timeout in milliseconds, defaults to 30 seconds
* @param {?string} options.jid - Only wait for messages from this ID
* @param {?number} options.maxMsgs - Maximum number of messages to collect (defaults to 1)
* @param {?(msg: Message) => true | false} options.filterFunction Filter results gathered, will only run on results after the other options.
* @returns {Array<Message>} Array of messages collected
*/
async waitForMessages(options) {
// Bind the event listener
if (this.isBinded == false) this.bind();
// Assigning default options
const { timeout = 30 * 1000, jid = '', maxMsgs = 1, filterFunction = () => true } = options;
return new Promise((resolve, reject) => {
// Id for the object entry ({0: {timeout, ....}})
const identifier = Object.keys(this.#msgs).length;
const cancel = () => {
delete this.#msgs[identifier];
}
// Adding a job
this.#msgs[identifier] = {
timeout: setTimeout(() => {
if (this.#msgs[identifier]?.msgs?.length < 1) {
resolve([]);
} else {
resolve(this.#msgs[identifier]?.msgs);
}
cancel();
}, timeout),
msgs: [],
filterFunction: (message) => {
if (maxMsgs > 1) {
if (maxMsgs >= this.#msgs[identifier]?.msgs?.length) {
resolve(this.#msgs[identifier].msgs);
clearTimeout(this.#msgs[identifier].timeout);
cancel();
}
if (jid.length > 0) {
if (jid == message.from) {
if (filterFunction() === true) {
// No function was provided
this.#msgs[identifier].msgs.push(message);
} else {
const result = filterFunction(message);
if (result === true) {
this.#msgs[identifier].msgs.push(message);
}
}
}
}
}
},
resolve,
reject
};
});
}
// Internal event handler
#handleMessage(msg) {
// Unbind the event listener when there are no active jobs
if (Object.keys(this.#msgs).length === 0) this.unbind();
for (const job in this.#msgs) {
const { filterFunction } = this.#msgs[job];
filterFunction(msg);
}
}
}
// Exporting the module
export default MessageCollection;
// good old JS support
module.exports = MessageCollection;
@PurpShell
Copy link
Author

PurpShell commented Aug 19, 2022

Example (Node.js 12+):

import MessageCollector from 'MessageCollector.js';
// or require syntax
const MessageCollector = require('MessageCollector.js');

// Initiate the collector
const collector = new MessageCollector(client);


collector.waitForMessage({ jid: '12335345@g.us', maxMsgs: 5, timeout: 15000, filterFunction: (msg) => msg.body.startsWith('test') }); // Wait for at most 5 messages from 12335345@g.us that begin with test until the 15 second timeout runs out

collector.cancelAll() // cancels any instances of the above, will throw an error and return the messages collected so far

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment