feat+fix: send vote messages & vote update event (#3913)

* add send vote function

* Update index.d.ts

* fix and add required modules

* fix poll update in group chat

* adjustments to improvements

* add example usages

* fix eslint

---------

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
This commit is contained in:
RendyCraft047 2025-11-10 02:37:51 +07:00 • committed by GitHub
commit 0c36613cc7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 51 additions and 11 deletions

View file

@ -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');
}

4
index.d.ts vendored
View file

@ -1210,6 +1210,10 @@ declare namespace WAWebJS {
* Once the event is canceled, it can not be edited.
*/
editScheduledEvent: (editedEventObject: Event) => Promise<Message | null>,
/**
* Send votes to the poll message
*/
vote: (selectedOptions: Array<string>) => Promise<void>,
}
/** ID that represents a message */

View file

@ -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);

View file

@ -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<string>} 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;

View file

@ -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'),

View file

@ -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,