diff --git a/example.js b/example.js index b7e5dc6..65314ba 100644 --- a/example.js +++ b/example.js @@ -365,7 +365,7 @@ client.on('message', async msg => { let list = new List('List body', 'btnText', sections, 'Title', 'footer'); client.sendMessage(msg.from, list); } else if (msg.body === '!reaction') { - msg.react('👍'); + await msg.react('👍'); } else if (msg.body === '!sendpoll') { /** By default the poll is created as a single choice poll: */ await msg.reply(new Poll('Winter or Summer?', ['Winter', 'Summer'])); @@ -382,11 +382,20 @@ client.on('message', async msg => { ] }) ); + } else if (msg.body === '!vote') { + if (msg.hasQuotedMsg) { + const quotedMsg = await msg.getQuotedMessage(); + if (quotedMsg.type === 'poll_creation') { + await quotedMsg.vote(msg.body.replace('!vote', '')); + } else { + msg.reply('Can only be used on poll messages'); + } + } } else if (msg.body === '!edit') { if (msg.hasQuotedMsg) { const quotedMsg = await msg.getQuotedMessage(); if (quotedMsg.fromMe) { - quotedMsg.edit(msg.body.replace('!edit', '')); + await quotedMsg.edit(msg.body.replace('!edit', '')); } else { msg.reply('I can only edit my own messages'); } diff --git a/index.d.ts b/index.d.ts index 9bb7870..6e25c1c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1210,6 +1210,10 @@ declare namespace WAWebJS { * Once the event is canceled, it can not be edited. */ editScheduledEvent: (editedEventObject: Event) => Promise, + /** + * Send votes to the poll message + */ + vote: (selectedOptions: Array) => Promise, } /** ID that represents a message */ diff --git a/src/Client.js b/src/Client.js index a2437d1..9cc3375 100644 --- a/src/Client.js +++ b/src/Client.js @@ -6,7 +6,7 @@ const moduleRaid = require('@pedroslopez/moduleraid/moduleraid'); const Util = require('./util/Util'); const InterfaceController = require('./util/InterfaceController'); -const { WhatsWebURL, DefaultOptions, Events, WAState } = require('./util/Constants'); +const { WhatsWebURL, DefaultOptions, Events, WAState, MessageTypes } = require('./util/Constants'); const { ExposeAuthStore } = require('./util/Injected/AuthStore/AuthStore'); const { ExposeStore } = require('./util/Injected/Store'); const { ExposeLegacyAuthStore } = require('./util/Injected/AuthStore/LegacyAuthStore'); @@ -2425,7 +2425,7 @@ class Client extends EventEmitter { async getPollVotes(messageId) { const msg = await this.getMessageById(messageId); if (!msg) return []; - if (msg.type != 'poll_creation') throw 'Invalid usage! Can only be used with a pollCreation message'; + if (msg.type != MessageTypes.POLL_CREATION) throw 'Invalid usage! Can only be used with a pollCreation message'; const pollVotes = await this.pupPage.evaluate( async (msg) => { const msgKey = window.Store.MsgKey.fromString(msg.id._serialized); diff --git a/src/structures/Message.js b/src/structures/Message.js index 4c43aee..c07842b 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -749,6 +749,32 @@ class Message extends Base { async getPollVotes() { return await this.client.getPollVotes(this.id._serialized); } + + /** + * Send votes to the poll message + * @param {Array} selectedOptions Array of options selected. + * @returns {Promise} + */ + async vote(selectedOptions) { + if (this.type != MessageTypes.POLL_CREATION) throw 'Invalid usage! Can only be used with a pollCreation message'; + + await this.client.pupPage.evaluate(async (messageId, votes) => { + if (!messageId) return null; + if (!Array.isArray(votes)) votes = [votes]; + let localIdSet = new Set(); + const msg = + window.Store.Msg.get(messageId) || (await window.Store.Msg.getMessagesById([messageId]))?.messages?.[0]; + if (!msg) return null; + + msg.pollOptions.forEach(a => { + for (const option of votes) { + if (a.name === option) localIdSet.add(a.localId); + } + }); + + await window.Store.PollsSendVote.sendVote(msg, localIdSet); + }, this.id._serialized, selectedOptions); + } } module.exports = Message; diff --git a/src/util/Injected/Store.js b/src/util/Injected/Store.js index efeebfb..13b1e89 100644 --- a/src/util/Injected/Store.js +++ b/src/util/Injected/Store.js @@ -103,7 +103,8 @@ exports.ExposeStore = () => { window.Store.FindOrCreateChat = window.require('WAWebFindChatAction'); window.Store.CustomerNoteUtils = window.require('WAWebNoteAction'); window.Store.BusinessGatingUtils = window.require('WAWebBizGatingUtils'); - window.Store.PollsVotesSchema = require('WAWebPollsVotesSchema'); + window.Store.PollsVotesSchema = window.require('WAWebPollsVotesSchema'); + window.Store.PollsSendVote = window.require('WAWebPollsSendVoteMsgAction'); window.Store.Settings = { ...window.require('WAWebUserPrefsGeneral'), diff --git a/src/util/Injected/Utils.js b/src/util/Injected/Utils.js index 54f9caf..4182808 100644 --- a/src/util/Injected/Utils.js +++ b/src/util/Injected/Utils.js @@ -92,15 +92,15 @@ exports.LoadUtils = () => { delete options.location; } - let _pollOptions = {}; + let pollOptions = {}; if (options.poll) { - const { pollName, pollOptions } = options.poll; + const { pollName, pollOptions: _pollOptions } = options.poll; const { allowMultipleAnswers, messageSecret } = options.poll.options; - _pollOptions = { + pollOptions = { kind: 'pollCreation', type: 'poll_creation', pollName: pollName, - pollOptions: pollOptions, + pollOptions: _pollOptions, pollSelectableOptionsCount: allowMultipleAnswers ? 0 : 1, messageSecret: Array.isArray(messageSecret) && messageSecret.length === 32 @@ -264,7 +264,7 @@ exports.LoadUtils = () => { id: newMsgKey, ack: 0, body: content, - from: meUser, + from: from, to: chat.id, local: true, self: 'out', @@ -276,7 +276,7 @@ exports.LoadUtils = () => { ...(mediaOptions.toJSON ? mediaOptions.toJSON() : {}), ...quotedMsgOptions, ...locationOptions, - ..._pollOptions, + ...pollOptions, ...eventOptions, ...vcardOptions, ...buttonOptions,