fix(messages): enhance nullish value checks in message content generation (#2180)
This commit is contained in:
+46
-22
@@ -42,6 +42,13 @@ import {
|
||||
} from './messages-media'
|
||||
import { shouldIncludeReportingToken } from './reporting-utils'
|
||||
|
||||
type ExtractByKey<T, K extends PropertyKey> = T extends Record<K, any> ? T : never
|
||||
type RequireKey<T, K extends keyof T> = T & {
|
||||
[P in K]-?: Exclude<T[P], null | undefined>
|
||||
}
|
||||
|
||||
type WithKey<T, K extends PropertyKey> = T extends unknown ? (K extends keyof T ? RequireKey<T, K> : never) : never
|
||||
|
||||
type MediaUploadData = {
|
||||
media: WAMediaUpload
|
||||
caption?: string
|
||||
@@ -367,12 +374,29 @@ export const generateForwardMessageContent = (message: WAMessage, forceForward?:
|
||||
return content
|
||||
}
|
||||
|
||||
export const hasNonNullishProperty = <K extends PropertyKey>(
|
||||
message: AnyMessageContent,
|
||||
key: K
|
||||
): message is ExtractByKey<AnyMessageContent, K> => {
|
||||
return (
|
||||
typeof message === 'object' &&
|
||||
message !== null &&
|
||||
key in message &&
|
||||
(message as any)[key] !== null &&
|
||||
(message as any)[key] !== undefined
|
||||
)
|
||||
}
|
||||
|
||||
function hasOptionalProperty<T, K extends PropertyKey>(obj: T, key: K): obj is WithKey<T, K> {
|
||||
return typeof obj === 'object' && obj !== null && key in obj && (obj as any)[key] !== null
|
||||
}
|
||||
|
||||
export const generateWAMessageContent = async (
|
||||
message: AnyMessageContent,
|
||||
options: MessageContentGenerationOptions
|
||||
) => {
|
||||
let m: WAMessageContent = {}
|
||||
if ('text' in message) {
|
||||
if (hasNonNullishProperty(message, 'text')) {
|
||||
const extContent = { text: message.text } as WATextMessage
|
||||
|
||||
let urlInfo = message.linkPreview
|
||||
@@ -408,7 +432,7 @@ export const generateWAMessageContent = async (
|
||||
}
|
||||
|
||||
m.extendedTextMessage = extContent
|
||||
} else if ('contacts' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'contacts')) {
|
||||
const contactLen = message.contacts.contacts.length
|
||||
if (!contactLen) {
|
||||
throw new Boom('require atleast 1 contact', { statusCode: 400 })
|
||||
@@ -419,22 +443,22 @@ export const generateWAMessageContent = async (
|
||||
} else {
|
||||
m.contactsArrayMessage = WAProto.Message.ContactsArrayMessage.create(message.contacts)
|
||||
}
|
||||
} else if ('location' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'location')) {
|
||||
m.locationMessage = WAProto.Message.LocationMessage.create(message.location)
|
||||
} else if ('react' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'react')) {
|
||||
if (!message.react.senderTimestampMs) {
|
||||
message.react.senderTimestampMs = Date.now()
|
||||
}
|
||||
|
||||
m.reactionMessage = WAProto.Message.ReactionMessage.create(message.react)
|
||||
} else if ('delete' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'delete')) {
|
||||
m.protocolMessage = {
|
||||
key: message.delete,
|
||||
type: WAProto.Message.ProtocolMessage.Type.REVOKE
|
||||
}
|
||||
} else if ('forward' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'forward')) {
|
||||
m = generateForwardMessageContent(message.forward, message.force)
|
||||
} else if ('disappearingMessagesInChat' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'disappearingMessagesInChat')) {
|
||||
const exp =
|
||||
typeof message.disappearingMessagesInChat === 'boolean'
|
||||
? message.disappearingMessagesInChat
|
||||
@@ -442,7 +466,7 @@ export const generateWAMessageContent = async (
|
||||
: 0
|
||||
: message.disappearingMessagesInChat
|
||||
m = prepareDisappearingMessageSettingContent(exp)
|
||||
} else if ('groupInvite' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'groupInvite')) {
|
||||
m.groupInviteMessage = {}
|
||||
m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode
|
||||
m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration
|
||||
@@ -462,7 +486,7 @@ export const generateWAMessageContent = async (
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ('pin' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'pin')) {
|
||||
m.pinInChatMessage = {}
|
||||
m.messageContextInfo = {}
|
||||
|
||||
@@ -471,7 +495,7 @@ export const generateWAMessageContent = async (
|
||||
m.pinInChatMessage.senderTimestampMs = Date.now()
|
||||
|
||||
m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0
|
||||
} else if ('buttonReply' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'buttonReply')) {
|
||||
switch (message.type) {
|
||||
case 'template':
|
||||
m.templateButtonReplyMessage = {
|
||||
@@ -488,10 +512,10 @@ export const generateWAMessageContent = async (
|
||||
}
|
||||
break
|
||||
}
|
||||
} else if ('ptv' in message && message.ptv) {
|
||||
} else if (hasOptionalProperty(message, 'ptv') && message.ptv) {
|
||||
const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options)
|
||||
m.ptvMessage = videoMessage
|
||||
} else if ('product' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'product')) {
|
||||
const { imageMessage } = await prepareWAMessageMedia({ image: message.product.productImage }, options)
|
||||
m.productMessage = WAProto.Message.ProductMessage.create({
|
||||
...message,
|
||||
@@ -500,9 +524,9 @@ export const generateWAMessageContent = async (
|
||||
productImage: imageMessage
|
||||
}
|
||||
})
|
||||
} else if ('listReply' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'listReply')) {
|
||||
m.listResponseMessage = { ...message.listReply }
|
||||
} else if ('event' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'event')) {
|
||||
m.eventMessage = {}
|
||||
const startTime = Math.floor(message.event.startDate.getTime() / 1000)
|
||||
|
||||
@@ -524,7 +548,7 @@ export const generateWAMessageContent = async (
|
||||
m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed
|
||||
m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false
|
||||
m.eventMessage.location = message.event.location
|
||||
} else if ('poll' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'poll')) {
|
||||
message.poll.selectableCount ||= 0
|
||||
message.poll.toAnnouncementGroup ||= false
|
||||
|
||||
@@ -561,13 +585,13 @@ export const generateWAMessageContent = async (
|
||||
m.pollCreationMessage = pollCreationMessage
|
||||
}
|
||||
}
|
||||
} else if ('sharePhoneNumber' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'sharePhoneNumber')) {
|
||||
m.protocolMessage = {
|
||||
type: proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
||||
}
|
||||
} else if ('requestPhoneNumber' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'requestPhoneNumber')) {
|
||||
m.requestPhoneNumberMessage = {}
|
||||
} else if ('limitSharing' in message) {
|
||||
} else if (hasNonNullishProperty(message, 'limitSharing')) {
|
||||
m.protocolMessage = {
|
||||
type: proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
|
||||
limitSharing: {
|
||||
@@ -581,11 +605,11 @@ export const generateWAMessageContent = async (
|
||||
m = await prepareWAMessageMedia(message, options)
|
||||
}
|
||||
|
||||
if ('viewOnce' in message && !!message.viewOnce) {
|
||||
if (hasOptionalProperty(message, 'viewOnce') && !!message.viewOnce) {
|
||||
m = { viewOnceMessage: { message: m } }
|
||||
}
|
||||
|
||||
if ('mentions' in message && message.mentions?.length) {
|
||||
if (hasOptionalProperty(message, 'mentions') && message.mentions?.length) {
|
||||
const messageType = Object.keys(m)[0]! as Extract<keyof proto.IMessage, MessageWithContextInfo>
|
||||
const key = m[messageType]
|
||||
if ('contextInfo' in key! && !!key.contextInfo) {
|
||||
@@ -597,7 +621,7 @@ export const generateWAMessageContent = async (
|
||||
}
|
||||
}
|
||||
|
||||
if ('edit' in message) {
|
||||
if (hasOptionalProperty(message, 'edit')) {
|
||||
m = {
|
||||
protocolMessage: {
|
||||
key: message.edit,
|
||||
@@ -608,7 +632,7 @@ export const generateWAMessageContent = async (
|
||||
}
|
||||
}
|
||||
|
||||
if ('contextInfo' in message && !!message.contextInfo) {
|
||||
if (hasOptionalProperty(message, 'contextInfo') && !!message.contextInfo) {
|
||||
const messageType = Object.keys(m)[0]! as Extract<keyof proto.IMessage, MessageWithContextInfo>
|
||||
const key = m[messageType]
|
||||
if ('contextInfo' in key! && !!key.contextInfo) {
|
||||
|
||||
Reference in New Issue
Block a user