This commit is contained in:
Alan Mosko
2023-01-11 23:58:29 -03:00
parent 5041be776e
commit 78f04d8714
18 changed files with 405 additions and 253 deletions

View File

@@ -1,5 +1,6 @@
import { Boom } from '@hapi/boom'
import axios from 'axios'
import { randomBytes } from 'crypto'
import { promises as fs } from 'fs'
import { Logger } from 'pino'
import { proto } from '../../WAProto'
@@ -26,6 +27,7 @@ import {
import { isJidGroup, jidNormalizedUser } from '../WABinary'
import { generateMessageID, unixTimestampSeconds } from './generics'
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, MediaDownloadOptions } from './messages-media'
import { comparePollMessage, decryptPollMessageRaw } from './messages-poll'
type MediaUploadData = {
media: WAMediaUpload
@@ -375,6 +377,37 @@ export const generateWAMessageContent = async(
})
} else if('listReply' in message) {
m.listResponseMessage = { ...message.listReply }
} else if('poll' in message) {
if(typeof message.poll.selectableCount !== 'number') {
message.poll.selectableCount = 0
}
if(!Array.isArray(message.poll.values)) {
throw new Boom('Invalid poll values', { statusCode: 400 })
}
if(message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
throw new Boom(
`poll.selectableCount in poll should be between 0 and ${
message.poll.values.length
} or equal to the items length`, { statusCode: 400 }
)
}
// link: https://github.com/adiwajshing/Baileys/pull/2290#issuecomment-1304413425
m.messageContextInfo = {
messageSecret: randomBytes(32), // encKey
}
m.pollCreationMessage = WAProto.Message.PollCreationMessage.fromObject({
name: message.poll.name,
selectableOptionsCount: message.poll.selectableCount,
options: message.poll.values.map(
value => WAProto.Message.PollCreationMessage.Option.fromObject({
optionName: value,
}),
),
})
} else {
m = await prepareWAMessageMedia(
message,
@@ -569,31 +602,13 @@ export const getContentType = (content: WAProto.IMessage | undefined) => {
* @returns
*/
export const normalizeMessageContent = (content: WAMessageContent | null | undefined): WAMessageContent | undefined => {
if(!content) {
return undefined
}
// set max iterations to prevent an infinite loop
for(let i = 0;i < 5;i++) {
const inner = getFutureProofMessage(content)
if(!inner) {
break
}
content = inner.message
}
return content!
function getFutureProofMessage(message: typeof content) {
return (
message?.ephemeralMessage
|| message?.viewOnceMessage
|| message?.documentWithCaptionMessage
|| message?.viewOnceMessageV2
|| message?.editedMessage
)
}
content = content?.ephemeralMessage?.message?.viewOnceMessage?.message ||
content?.ephemeralMessage?.message ||
content?.viewOnceMessage?.message ||
content?.documentWithCaptionMessage?.message ||
content ||
undefined
return content
}
/**
@@ -790,3 +805,49 @@ export const assertMediaContent = (content: proto.IMessage | null | undefined) =
return mediaContent
}
/**
* Decrypt/Get Poll Update Message Values
* @param msg Full message info contains PollUpdateMessage, you can use `msg`
* @param pollCreationData An object contains `encKey` (used to decrypt the poll message), `sender` (used to create decryption key), and `options` (you should fill it with poll options, e.g. Apple, Orange, etc...)
* @param withSelectedOptions Get user's selected options condition, set it to true if you want get the results.
* @return {Promise<{ hash: string[] } | { hash: string[], selectedOptions: string[] }>} Property `hash` is an array which contains selected options hash, you can use `comparePollMessage` to compare it with original values. Property `selectedOptions` is an array, and the results is from `comparePollMessage` function.
*/
export const getPollUpdateMessage = async(
msg: WAProto.IWebMessageInfo,
pollCreationData: { encKey: Uint8Array; sender: string; options: string[]; },
withSelectedOptions: boolean = false,
): Promise<{ hash: string[] } | { hash: string[]; selectedOptions: string[] }> => {
if(!msg.message?.pollUpdateMessage || !pollCreationData?.encKey) {
throw new Boom('Missing pollUpdateMessage, or encKey', { statusCode: 400 })
}
pollCreationData.sender = msg.message?.pollUpdateMessage?.pollCreationMessageKey?.participant || pollCreationData.sender
if(!pollCreationData.sender?.length) {
throw new Boom('Missing sender', { statusCode: 400 })
}
let hash = await decryptPollMessageRaw(
pollCreationData.encKey, // encKey
msg.message?.pollUpdateMessage?.vote?.encPayload!, // enc payload
msg.message?.pollUpdateMessage?.vote?.encIv!, // enc iv
jidNormalizedUser(pollCreationData.sender), // sender
msg.message?.pollUpdateMessage?.pollCreationMessageKey?.id!, // poll id
jidNormalizedUser(
msg.key.remoteJid?.endsWith('@g.us') ?
(msg.key.participant || msg.participant)! : msg.key.remoteJid!
), // voter
)
if(hash.length === 1 && !hash[0].length) {
hash = []
}
return withSelectedOptions ? {
hash,
selectedOptions: await comparePollMessage(
pollCreationData.options || [],
hash,
)
} : { hash }
}