fix(types): remove non-null assertions across 14 files
Files fixed: - messages-recv.ts: 58 assertions → null guards, meId extraction, optional chaining - process-message.ts: 38 assertions → remoteJid/participant guards, proto field checks - chat-utils.ts: 31 assertions → proto field validation with Boom errors - messages-send.ts: 20 assertions → meId extraction, participant guards - chats.ts: 15 assertions → me guard, firstChild guard, jid guards - messages.ts: 14 assertions → originalFilePath guard, key guards - groups.ts: 12 assertions → attrs fallbacks with ?? - validate-connection.ts: 9 assertions → grouped proto field validation - generics.ts: 1 assertion → versionLine guard - history.ts: 2 assertions → key guards - libsignal.ts: 1 assertion → deviceId guard - sender-key-message.ts: 3 assertions → proto guards - UsyncBotProfileProtocol.ts: 2 assertions → attrs guards - example.ts: 3 assertions → optional chaining https://claude.ai/code/session_01E2cfX1N3sJgCJBTvzGazSG
This commit is contained in:
+40
-26
@@ -126,15 +126,16 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
},
|
||||
content: [{ tag: 'media_conn', attrs: {} }]
|
||||
})
|
||||
const mediaConnNode = getBinaryNodeChild(result, 'media_conn')!
|
||||
const mediaConnNode = getBinaryNodeChild(result, 'media_conn')
|
||||
if (!mediaConnNode) throw new Boom('Missing media_conn node')
|
||||
// TODO: explore full length of data that whatsapp provides
|
||||
const node: MediaConnInfo = {
|
||||
hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
|
||||
hostname: attrs.hostname!,
|
||||
maxContentLengthBytes: +attrs.maxContentLengthBytes!
|
||||
hostname: attrs.hostname ?? '',
|
||||
maxContentLengthBytes: +(attrs.maxContentLengthBytes ?? 0)
|
||||
})),
|
||||
auth: mediaConnNode.attrs.auth!,
|
||||
ttl: +mediaConnNode.attrs.ttl!,
|
||||
auth: mediaConnNode.attrs.auth ?? '',
|
||||
ttl: +(mediaConnNode.attrs.ttl ?? 0),
|
||||
fetchDate: new Date()
|
||||
}
|
||||
logger.debug('fetched media conn')
|
||||
@@ -162,7 +163,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
const node: BinaryNode = {
|
||||
tag: 'receipt',
|
||||
attrs: {
|
||||
id: messageIds[0]!
|
||||
id: messageIds[0] ?? ''
|
||||
}
|
||||
}
|
||||
const isReadReceipt = type === 'read' || type === 'read-self'
|
||||
@@ -171,8 +172,9 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
|
||||
if (!participant) throw new Boom('Missing participant for sender receipt')
|
||||
node.attrs.recipient = jid
|
||||
node.attrs.to = participant!
|
||||
node.attrs.to = participant
|
||||
} else {
|
||||
node.attrs.to = jid
|
||||
if (participant) {
|
||||
@@ -266,10 +268,11 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
for (const { jid, user } of jidsWithUser) {
|
||||
if (!user) continue
|
||||
if (useCache) {
|
||||
const devices =
|
||||
mgetDevices?.[user!] ||
|
||||
(userDevicesCache.mget ? undefined : ((await userDevicesCache.get(user!)) as FullJid[]))
|
||||
mgetDevices?.[user] ||
|
||||
(userDevicesCache.mget ? undefined : ((await userDevicesCache.get(user)) as FullJid[]))
|
||||
if (devices) {
|
||||
const devicesWithJid = devices.map(d => ({
|
||||
...d,
|
||||
@@ -324,10 +327,14 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
}
|
||||
}
|
||||
|
||||
const meId = authState.creds.me?.id
|
||||
if (!meId) throw new Boom('Not authenticated', { statusCode: 401 })
|
||||
const meLid = authState.creds.me?.lid || ''
|
||||
|
||||
const extracted = extractDeviceJids(
|
||||
result?.list,
|
||||
authState.creds.me!.id,
|
||||
authState.creds.me!.lid!,
|
||||
meId,
|
||||
meLid,
|
||||
ignoreZeroDevices
|
||||
)
|
||||
const deviceMap: { [_: string]: FullJid[] } = {}
|
||||
@@ -547,7 +554,8 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
: recipientJids.map(jid => ({ recipientJid: jid, message: patched }))
|
||||
|
||||
let shouldIncludeDeviceIdentity = false
|
||||
const meId = authState.creds.me!.id
|
||||
const meId = authState.creds.me?.id
|
||||
if (!meId) throw new Boom('Not authenticated', { statusCode: 401 })
|
||||
const meLid = authState.creds.me?.lid
|
||||
const meLidUser = meLid ? jidDecode(meLid)?.user : null
|
||||
|
||||
@@ -559,8 +567,8 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
let msgToEncrypt = patchedMessage
|
||||
|
||||
if (dsmMessage) {
|
||||
const { user: targetUser } = jidDecode(jid)!
|
||||
const { user: ownPnUser } = jidDecode(meId)!
|
||||
const targetUser = jidDecode(jid)?.user ?? ''
|
||||
const ownPnUser = jidDecode(meId)?.user ?? ''
|
||||
const ownLidUser = meLidUser
|
||||
|
||||
const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser)
|
||||
@@ -816,13 +824,16 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
statusJidList
|
||||
}: MessageRelayOptions
|
||||
) => {
|
||||
const meId = authState.creds.me!.id
|
||||
const meId = authState.creds.me?.id
|
||||
if (!meId) throw new Boom('Not authenticated', { statusCode: 401 })
|
||||
const meLid = authState.creds.me?.lid
|
||||
const isRetryResend = Boolean(participant?.jid)
|
||||
let shouldIncludeDeviceIdentity = isRetryResend
|
||||
const statusJid = 'status@broadcast'
|
||||
|
||||
const { user, server } = jidDecode(jid)!
|
||||
const jidDecoded = jidDecode(jid)
|
||||
if (!jidDecoded) throw new Boom('Invalid JID')
|
||||
const { user, server } = jidDecoded
|
||||
const isGroup = server === 'g.us'
|
||||
const isStatus = jid === statusJid
|
||||
const isLid = server === 'lid'
|
||||
@@ -910,7 +921,9 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
additionalAttributes = { ...additionalAttributes, device_fanout: 'false' }
|
||||
}
|
||||
|
||||
const { user, device } = jidDecode(participant.jid)!
|
||||
const participantDecoded = jidDecode(participant.jid)
|
||||
if (!participantDecoded) throw new Boom('Invalid participant JID')
|
||||
const { user, device } = participantDecoded
|
||||
devices.push({
|
||||
user,
|
||||
device,
|
||||
@@ -1068,7 +1081,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation')
|
||||
}
|
||||
|
||||
const { user: ownUser } = jidDecode(ownId)!
|
||||
const ownUser = jidDecode(ownId)?.user ?? ''
|
||||
if (!participant) {
|
||||
const patchedForReporting = await patchMessageBeforeSending(message, [jid])
|
||||
reportingMessage = Array.isArray(patchedForReporting)
|
||||
@@ -1086,7 +1099,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
|
||||
if (user !== ownUser) {
|
||||
const ownUserServer = isLid ? 'lid' : 's.whatsapp.net'
|
||||
const ownUserForAddressing = isLid && meLid ? jidDecode(meLid)!.user : jidDecode(meId)!.user
|
||||
const ownUserForAddressing = isLid && meLid ? (jidDecode(meLid)?.user ?? '') : (jidDecode(meId)?.user ?? '')
|
||||
|
||||
devices.push({
|
||||
user: ownUserForAddressing,
|
||||
@@ -1102,8 +1115,8 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
// Use conversation-appropriate sender identity
|
||||
const senderIdentity =
|
||||
isLid && meLid
|
||||
? jidEncode(jidDecode(meLid)?.user!, 'lid', undefined)
|
||||
: jidEncode(jidDecode(meId)?.user!, 's.whatsapp.net', undefined)
|
||||
? jidEncode(jidDecode(meLid)?.user ?? '', 'lid', undefined)
|
||||
: jidEncode(jidDecode(meId)?.user ?? '', 's.whatsapp.net', undefined)
|
||||
|
||||
// Enumerate devices for sender and target with consistent addressing
|
||||
const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false)
|
||||
@@ -1122,8 +1135,8 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
const allRecipients: string[] = []
|
||||
const meRecipients: string[] = []
|
||||
const otherRecipients: string[] = []
|
||||
const { user: mePnUser } = jidDecode(meId)!
|
||||
const { user: meLidUser } = meLid ? jidDecode(meLid)! : { user: null }
|
||||
const mePnUser = jidDecode(meId)?.user ?? ''
|
||||
const meLidUser = meLid ? (jidDecode(meLid)?.user ?? null) : null
|
||||
|
||||
// Carousel in DSM wrapper causes error 479 on own devices
|
||||
const isCarouselMsg = isCarouselMessage(message)
|
||||
@@ -1172,10 +1185,11 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
if (isRetryResend) {
|
||||
if (!participant) throw new Boom('Missing participant for retry resend')
|
||||
// Only check for regular LID users, NOT hosted LID users
|
||||
// Hosted LID users should use meId for comparison, not meLid
|
||||
const isParticipantLid = isLidUser(participant!.jid)
|
||||
const isMe = areJidsSameUser(participant!.jid, isParticipantLid ? meLid : meId)
|
||||
const isParticipantLid = isLidUser(participant.jid)
|
||||
const isMe = areJidsSameUser(participant.jid, isParticipantLid ? meLid : meId)
|
||||
|
||||
// Skip DSM for carousel - own devices reject it with error 479
|
||||
const usesDSM = isMe && !isCarouselMessage(message)
|
||||
@@ -1190,7 +1204,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
||||
|
||||
const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
|
||||
data: encodedMessageToSend,
|
||||
jid: participant!.jid
|
||||
jid: participant.jid
|
||||
})
|
||||
|
||||
binaryNodeContent.push({
|
||||
|
||||
Reference in New Issue
Block a user