From e7c31f9270e2dabe7d7178131db1945264e61ecb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Feb 2026 03:50:36 +0000 Subject: [PATCH 1/3] fix: revert defensive null checks in signal.ts that prevented Signal session creation The previous PRs (124-129) replaced non-null assertions (!) with defensive null checks + continue statements in parseAndInjectE2ESessions and extractDeviceJids. This caused ALL prekey bundles to be silently skipped because the continue statements would trigger whenever any sub-field appeared missing (even though WhatsApp always sends complete bundles). Result: no Signal sessions were created after QR scan, causing "SessionError: No sessions" when trying to send messages. Reverted to the original Baileys pattern using non-null assertions, which matches the upstream reference (infinitezap/Teste_InfiniteAPI). https://claude.ai/code/session_01XaA7GwNaB6azTHFYQ8WEpB --- src/Utils/signal.ts | 50 ++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/src/Utils/signal.ts b/src/Utils/signal.ts index 6900743b..fcc9d814 100644 --- a/src/Utils/signal.ts +++ b/src/Utils/signal.ts @@ -88,18 +88,14 @@ export const xmppPreKey = (pair: KeyPair, id: number): BinaryNode => ({ }) export const parseAndInjectE2ESessions = async (node: BinaryNode, repository: SignalRepositoryWithLIDStore) => { - const extractKey = (key: BinaryNode) => { - if (!key) return undefined - const keyId = getBinaryNodeChildUInt(key, 'id', 3) - const publicKeyBuf = getBinaryNodeChildBuffer(key, 'value') - const signature = getBinaryNodeChildBuffer(key, 'signature') - if (keyId === undefined || !publicKeyBuf || !signature) return undefined - return { - keyId, - publicKey: generateSignalPubKey(publicKeyBuf), - signature - } - } + const extractKey = (key: BinaryNode) => + key + ? { + keyId: getBinaryNodeChildUInt(key, 'id', 3)!, + publicKey: generateSignalPubKey(getBinaryNodeChildBuffer(key, 'value')!), + signature: getBinaryNodeChildBuffer(key, 'signature')! + } + : undefined const nodes = getBinaryNodeChildren(getBinaryNodeChild(node, 'list'), 'user') for (const node of nodes) { assertNodeErrorFree(node) @@ -115,26 +111,20 @@ export const parseAndInjectE2ESessions = async (node: BinaryNode, repository: Si for (const nodesChunk of chunks) { for (const node of nodesChunk) { - const signedKey = getBinaryNodeChild(node, 'skey') - const key = getBinaryNodeChild(node, 'key') - const identity = getBinaryNodeChildBuffer(node, 'identity') - const jid = node.attrs.jid - if (!signedKey || !key || !identity || !jid) continue + const signedKey = getBinaryNodeChild(node, 'skey')! + const key = getBinaryNodeChild(node, 'key')! + const identity = getBinaryNodeChildBuffer(node, 'identity')! + const jid = node.attrs.jid! const registrationId = getBinaryNodeChildUInt(node, 'registration', 4) - if (registrationId === undefined) continue - - const signedPreKey = extractKey(signedKey) - const preKey = extractKey(key) - if (!signedPreKey || !preKey) continue await repository.injectE2ESession({ jid, session: { - registrationId, + registrationId: registrationId!, identityKey: generateSignalPubKey(identity), - signedPreKey, - preKey + signedPreKey: extractKey(signedKey)!, + preKey: extractKey(key)! } }) } @@ -147,18 +137,14 @@ export const extractDeviceJids = ( myLid: string, excludeZeroDevices: boolean ) => { - const myJidDecoded = jidDecode(myJid) - if (!myJidDecoded) return [] - - const { user: myUser, device: myDevice } = myJidDecoded + const { user: myUser, device: myDevice } = jidDecode(myJid)! const extracted: FullJid[] = [] for (const userResult of result) { const { devices, id } = userResult as { devices: ParsedDeviceInfo; id: string } - const decoded = jidDecode(id) - if (!decoded) continue - const { user, server } = decoded + const decoded = jidDecode(id)!, + { user, server } = decoded let { domainType } = decoded const deviceList = devices?.deviceList as DeviceListData[] if (!Array.isArray(deviceList)) continue From 48b63565b67366b082a22702a41d54822d0de5d8 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Feb 2026 10:10:56 +0000 Subject: [PATCH 2/3] fix: revert ?? '' and defensive null checks across Socket files PRs 124-129 replaced TypeScript non-null assertions (!) with optional chaining (?.) and empty string defaults (?? ''). While defensive programming is usually good, in Signal protocol and WhatsApp binary node handling code these changes caused: - Malformed JIDs with empty user components (e.g. @s.whatsapp.net) - Silent device enumeration failures (messages skip recipients) - Wrong own-device detection (message routing errors) - Broken prekey count handling (prekey uploads silently skipped) - Wrong retry count tracking in Signal protocol These empty-string defaults are dangerous because Signal session lookups fail for malformed JIDs, causing "SessionError: No sessions". Reverted to original Baileys pattern using non-null assertions (!) which match the upstream reference (infinitezap/Teste_InfiniteAPI). Files fixed: messages-send.ts, messages-recv.ts, socket.ts, chats.ts, groups.ts, communities.ts, business.ts https://claude.ai/code/session_01XaA7GwNaB6azTHFYQ8WEpB --- src/Socket/business.ts | 2 +- src/Socket/chats.ts | 4 +- src/Socket/communities.ts | 8 +-- src/Socket/groups.ts | 12 ++--- src/Socket/messages-recv.ts | 98 ++++++++++++++++--------------------- src/Socket/messages-send.ts | 41 ++++++++-------- src/Socket/socket.ts | 30 +++--------- 7 files changed, 81 insertions(+), 114 deletions(-) diff --git a/src/Socket/business.ts b/src/Socket/business.ts index 23392b23..d67fdd40 100644 --- a/src/Socket/business.ts +++ b/src/Socket/business.ts @@ -118,7 +118,7 @@ export const makeBusinessSocket = (config: SocketConfig) => { content: [ { tag: 'cover_photo', - attrs: { id: String(fbid), op: 'update', token: meta_hmac ?? '', ts: String(ts) } + attrs: { id: String(fbid), op: 'update', token: meta_hmac!, ts: String(ts) } } ] } diff --git a/src/Socket/chats.ts b/src/Socket/chats.ts index f8ac807f..759227b1 100644 --- a/src/Socket/chats.ts +++ b/src/Socket/chats.ts @@ -1107,8 +1107,8 @@ export const makeChatsSocket = (config: SocketConfig) => { ev.emit('messages.upsert', { messages: [msg], type }) if (!!msg.pushName) { - let jid = msg.key.fromMe ? (authState.creds.me?.id ?? '') : msg.key.participant || msg.key.remoteJid - jid = jidNormalizedUser(jid ?? '') + let jid = msg.key.fromMe ? authState.creds.me!.id : msg.key.participant || msg.key.remoteJid + jid = jidNormalizedUser(jid!) if (!msg.key.fromMe) { ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName! }]) diff --git a/src/Socket/communities.ts b/src/Socket/communities.ts index 9691be1a..0c78397b 100644 --- a/src/Socket/communities.ts +++ b/src/Socket/communities.ts @@ -358,13 +358,13 @@ export const makeCommunitiesSocket = (config: SocketConfig) => { communityAcceptInviteV4: ev.createBufferedFunction( async (key: string | WAMessageKey, inviteMessage: proto.Message.IGroupInviteMessage) => { key = typeof key === 'string' ? { remoteJid: key } : key - const results = await communityQuery(inviteMessage.groupJid ?? '', 'set', [ + const results = await communityQuery(inviteMessage.groupJid!, 'set', [ { tag: 'accept', attrs: { - code: inviteMessage.inviteCode ?? '', + code: inviteMessage.inviteCode!, expiration: (inviteMessage.inviteExpiration ?? 0).toString(), - admin: key.remoteJid ?? '' + admin: key.remoteJid! } } ]) @@ -475,7 +475,7 @@ export const extractCommunityMetadata = (result: BinaryNode) => { participants: getBinaryNodeChildren(community, 'participant').map(({ attrs }) => { return { // TODO: IMPLEMENT THE PN/LID FIELDS HERE!! - id: attrs.jid ?? '', + id: attrs.jid!, admin: (attrs.type || null) as GroupParticipant['admin'] } }), diff --git a/src/Socket/groups.ts b/src/Socket/groups.ts index 7517328c..33194e27 100644 --- a/src/Socket/groups.ts +++ b/src/Socket/groups.ts @@ -225,12 +225,12 @@ export const makeGroupsSocket = (config: SocketConfig) => { groupAcceptInviteV4: ev.createBufferedFunction( async (key: string | WAMessageKey, inviteMessage: proto.Message.IGroupInviteMessage) => { key = typeof key === 'string' ? { remoteJid: key } : key - const results = await groupQuery(inviteMessage.groupJid ?? '', 'set', [ + const results = await groupQuery(inviteMessage.groupJid!, 'set', [ { tag: 'accept', attrs: { - code: inviteMessage.inviteCode ?? '', - expiration: String(inviteMessage.inviteExpiration ?? ''), + code: inviteMessage.inviteCode!, + expiration: inviteMessage.inviteExpiration!.toString(), admin: key.remoteJid! } } @@ -316,14 +316,14 @@ export const extractGroupMetadata = (result: BinaryNode) => { descId = descChild.attrs.id } - const groupId = (group.attrs.id ?? '').includes('@') ? (group.attrs.id ?? '') : jidEncode(group.attrs.id ?? '', 'g.us') + const groupId = group.attrs.id!.includes('@') ? group.attrs.id! : jidEncode(group.attrs.id!, 'g.us') const eph = getBinaryNodeChild(group, 'ephemeral')?.attrs.expiration const memberAddMode = getBinaryNodeChildString(group, 'member_add_mode') === 'all_member_add' const metadata: GroupMetadata = { id: groupId, notify: group.attrs.notify, addressingMode: group.attrs.addressing_mode === 'lid' ? WAMessageAddressingMode.LID : WAMessageAddressingMode.PN, - subject: group.attrs.subject ?? '', + subject: group.attrs.subject!, subjectOwner: group.attrs.s_o, subjectOwnerPn: group.attrs.s_o_pn, subjectTime: +(group.attrs.s_t ?? '0'), @@ -347,7 +347,7 @@ export const extractGroupMetadata = (result: BinaryNode) => { participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) => { // TODO: Store LID MAPPINGS return { - id: attrs.jid ?? '', + id: attrs.jid!, phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined, lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined, admin: (attrs.type || null) as GroupParticipant['admin'] diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 6c6a3efa..5f68675a 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -156,17 +156,16 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { throw new Boom('Not authenticated') } - const msgId = messageKey?.id ?? '' - if (await placeholderResendCache.get(msgId)) { + if (await placeholderResendCache.get(messageKey?.id!)) { logger.debug({ messageKey }, 'already requested resend') return } else { - await placeholderResendCache.set(msgId, true) + await placeholderResendCache.set(messageKey?.id!, true) } await delay(2000) - if (!(await placeholderResendCache.get(msgId))) { + if (!(await placeholderResendCache.get(messageKey?.id!))) { logger.debug({ messageKey }, 'message received while resend requested') return 'RESOLVED' } @@ -181,9 +180,9 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } setTimeout(async () => { - if (await placeholderResendCache.get(msgId)) { + if (await placeholderResendCache.get(messageKey?.id!)) { logger.debug({ messageKey }, 'PDO message without response after 8 seconds. Phone possibly offline') - await placeholderResendCache.del(msgId) + await placeholderResendCache.del(messageKey?.id!) } }, 8_000) @@ -234,7 +233,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { if (update.jid && update.user) { ev.emit('newsletter-participants.update', { id: update.jid, - author: node.attrs.from ?? '', + author: node.attrs.from!, user: update.user, new_role: 'ADMIN', action: 'promote' @@ -252,10 +251,9 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { // Handles newsletter notifications const handleNewsletterNotification = async (node: BinaryNode) => { - const from = node.attrs.from ?? '' - const child = getAllBinaryNodeChildren(node)[0] - if (!child) return - const author = node.attrs.participant ?? '' + const from = node.attrs.from! + const child = getAllBinaryNodeChildren(node)[0]! + const author = node.attrs.participant! logger.info({ from, child }, 'got newsletter notification') @@ -263,7 +261,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { case 'reaction': const reactionUpdate = { id: from, - server_id: child.attrs.message_id ?? '', + server_id: child.attrs.message_id!, reaction: { code: getBinaryNodeChildString(child, 'reaction'), count: 1 @@ -275,7 +273,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { case 'view': const viewUpdate = { id: from, - server_id: child.attrs.message_id ?? '', + server_id: child.attrs.message_id!, count: parseInt(child.content?.toString() || '0', 10) } ev.emit('newsletter.view', viewUpdate) @@ -285,9 +283,9 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const participantUpdate = { id: from, author, - user: child.attrs.jid ?? '', - action: child.attrs.action ?? '', - new_role: child.attrs.role ?? '' + user: child.attrs.jid!, + action: child.attrs.action!, + new_role: child.attrs.role! } ev.emit('newsletter-participants.update', participantUpdate) break @@ -347,8 +345,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const stanza: BinaryNode = { tag: 'ack', attrs: { - id: attrs.id ?? '', - to: attrs.from ?? '', + id: attrs.id!, + to: attrs.from!, class: tag } } @@ -407,16 +405,9 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } const sendRetryRequest = async (node: BinaryNode, forceIncludeKeys = false) => { - const meId = authState.creds.me?.id - if (!meId) throw new Boom('Not authenticated', { statusCode: 401 }) - const meLid = authState.creds.me?.lid || '' - const { fullMessage } = decodeMessageNode(node, meId, meLid) + const { fullMessage } = decodeMessageNode(node, authState.creds.me!.id, authState.creds.me!.lid || '') const { key: msgKey } = fullMessage - const msgId = msgKey.id - if (!msgId) { - logger.debug({ node }, 'missing message id in retry request') - return - } + const msgId = msgKey.id! if (messageRetryManager) { // Check if we've exceeded max retries using the new system @@ -454,7 +445,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const retryCount = (await msgRetryCache.get(key)) || 1 const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds - const fromJid = node.attrs.from ?? '' + const fromJid = node.attrs.from! // Check if we should recreate the session let shouldRecreateSession = false @@ -519,15 +510,15 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { attrs: { id: msgId, type: 'retry', - to: node.attrs.from ?? '' + to: node.attrs.from! }, content: [ { tag: 'retry', attrs: { count: retryCount.toString(), - id: node.attrs.id ?? '', - t: node.attrs.t ?? '', + id: node.attrs.id!, + t: node.attrs.t!, v: '1', // ADD ERROR FIELD error: '0' @@ -553,19 +544,16 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const { update, preKeys } = await getNextPreKeys(authState, 1) const [keyId] = Object.keys(preKeys) - if (!keyId) throw new Boom('No pre-keys available') - const key = preKeys[+keyId] - if (!key) throw new Boom('Pre-key not found') + const key = preKeys[+keyId!] - const content = receipt.content as BinaryNode[] - if (!content) throw new Boom('Receipt content missing') + const content = receipt.content! as BinaryNode[] content.push({ tag: 'keys', attrs: {}, content: [ { tag: 'type', attrs: {}, content: Buffer.from(KEY_BUNDLE_TYPE) }, { tag: 'identity', attrs: {}, content: identityKey.public }, - xmppPreKey(key, +keyId), + xmppPreKey(key!, +keyId!), xmppSignedPreKey(signedPreKey), { tag: 'device-identity', attrs: {}, content: deviceIdentity } ] @@ -584,9 +572,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const from = node.attrs.from if (from === S_WHATSAPP_NET) { const countChild = getBinaryNodeChild(node, 'count') - const countVal = countChild?.attrs?.value - if (!countVal) return - const count = +countVal + const count = +countChild!.attrs.value! const shouldUploadMorePreKeys = count < MIN_PREKEY_COUNT logger.debug({ count, shouldUploadMorePreKeys }, 'recv pre-key count') @@ -651,7 +637,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } break case 'modify': - const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid ?? '').filter(Boolean) + const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid!) msg.messageStubParameters = oldNumber || [] msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER break @@ -666,7 +652,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const participants = getBinaryNodeChildren(child, 'participant').map(({ attrs }) => { // TODO: Store LID MAPPINGS return { - id: attrs.jid ?? '', + id: attrs.jid!, phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined, lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined, admin: (attrs.type || null) as GroupParticipant['admin'] @@ -688,7 +674,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { break case 'subject': msg.messageStubType = WAMessageStubType.GROUP_CHANGE_SUBJECT - msg.messageStubParameters = [child.attrs.subject ?? ''] + msg.messageStubParameters = [child.attrs.subject!] break case 'description': const description = getBinaryNodeChild(child, 'body')?.content?.toString() @@ -707,7 +693,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { break case 'invite': msg.messageStubType = WAMessageStubType.GROUP_CHANGE_INVITE_LINK - msg.messageStubParameters = [child.attrs.code ?? ''] + msg.messageStubParameters = [child.attrs.code!] break case 'member_add_mode': const addMode = child.content @@ -721,7 +707,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const approvalMode = getBinaryNodeChild(child, 'group_join') if (approvalMode) { msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE - msg.messageStubParameters = [approvalMode.attrs.state ?? ''] + msg.messageStubParameters = [approvalMode.attrs.state!] } break @@ -730,7 +716,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { msg.messageStubParameters = [ JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipantPn }), 'created', - child.attrs.request_method ?? '' + child.attrs.request_method! ] break case 'revoked_membership_requests': @@ -760,8 +746,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { break case 'w:gp2': // TODO: HANDLE PARTICIPANT_PN - if (!child) break - handleGroupNotification(node, child, result) + handleGroupNotification(node, child!, result) break case 'mediaretry': const event = decodeMediaRetryNode(node) @@ -771,11 +756,10 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { await handleEncryptNotification(node) break case 'devices': - if (!child) break const devices = getBinaryNodeChildren(child, 'device') if ( - areJidsSameUser(child.attrs.jid, authState.creds.me?.id) || - areJidsSameUser(child.attrs.lid, authState.creds.me?.lid) + areJidsSameUser(child!.attrs.jid, authState.creds.me!.id) || + areJidsSameUser(child!.attrs.lid, authState.creds.me!.lid) ) { const deviceData = devices.map(d => ({ id: d.attrs.jid, lid: d.attrs.lid })) logger.info({ deviceData }, 'my own devices changed') @@ -840,7 +824,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const blocklists = getBinaryNodeChildren(child, 'item') for (const { attrs } of blocklists) { - const blocklist = [attrs.jid ?? ''] + const blocklist = [attrs.jid!] const type = attrs.action === 'block' ? 'add' : 'remove' ev.emit('blocklist.update', { blocklist, type }) } @@ -890,7 +874,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { { tag: 'link_code_companion_reg', attrs: { - jid: authState.creds.me?.id ?? '', + jid: authState.creds.me!.id, stage: 'companion_finish' }, content: [ @@ -1092,7 +1076,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const handleReceipt = async (node: BinaryNode) => { const { attrs, content } = node - const isLid = (attrs.from ?? '').includes('lid') + const isLid = attrs.from!.includes('lid') const isNodeFromMe = areJidsSameUser( attrs.participant || attrs.from, isLid ? authState.creds.me?.lid : authState.creds.me?.id @@ -1198,7 +1182,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { notificationMutex.mutex(async () => { const msg = await processNotification(node) if (msg) { - const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me?.id ?? '') + const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me!.id) const { senderAlt: participantAlt, addressingMode } = extractAddressingContext(node) msg.key = { remoteJid, @@ -1242,7 +1226,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { category, author, decrypt - } = decryptMessageNode(node, authState.creds.me?.id ?? '', authState.creds.me?.lid || '', signalRepository, logger) + } = decryptMessageNode(node, authState.creds.me!.id, authState.creds.me!.lid || '', signalRepository, logger) const alt = msg.key.participantAlt || msg.key.remoteJidAlt // Handle LID/PN mappings with hybrid approach: @@ -1527,7 +1511,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { // JID normalization moved BEFORE mutex acquisition (line 1273) to prevent race conditions // cleanMessage still runs inside mutex to ensure atomic message processing - cleanMessage(msg, authState.creds.me?.id ?? '', authState.creds.me?.lid ?? '') + cleanMessage(msg, authState.creds.me!.id, authState.creds.me!.lid!) await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify') diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index 3d74a320..22dfdf0b 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -131,11 +131,11 @@ export const makeMessagesSocket = (config: SocketConfig) => { // TODO: explore full length of data that whatsapp provides const node: MediaConnInfo = { hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({ - hostname: attrs.hostname ?? '', - maxContentLengthBytes: +(attrs.maxContentLengthBytes ?? 0) + hostname: attrs.hostname!, + maxContentLengthBytes: +attrs.maxContentLengthBytes! })), - auth: mediaConnNode.attrs.auth ?? '', - ttl: +(mediaConnNode.attrs.ttl ?? 0), + auth: mediaConnNode.attrs.auth!, + ttl: +mediaConnNode.attrs.ttl!, fetchDate: new Date() } logger.debug('fetched media conn') @@ -163,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' @@ -268,11 +268,10 @@ 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, @@ -567,8 +566,8 @@ export const makeMessagesSocket = (config: SocketConfig) => { let msgToEncrypt = patchedMessage if (dsmMessage) { - const targetUser = jidDecode(jid)?.user ?? '' - const ownPnUser = jidDecode(meId)?.user ?? '' + const { user: targetUser } = jidDecode(jid)! + const { user: ownPnUser } = jidDecode(meId)! const ownLidUser = meLidUser const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser) @@ -1081,7 +1080,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation') } - const ownUser = jidDecode(ownId)?.user ?? '' + const { user: ownUser } = jidDecode(ownId)! if (!participant) { const patchedForReporting = await patchMessageBeforeSending(message, [jid]) reportingMessage = Array.isArray(patchedForReporting) @@ -1099,7 +1098,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, @@ -1115,8 +1114,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) @@ -1135,8 +1134,8 @@ export const makeMessagesSocket = (config: SocketConfig) => { const allRecipients: string[] = [] const meRecipients: string[] = [] const otherRecipients: string[] = [] - const mePnUser = jidDecode(meId)?.user ?? '' - const meLidUser = meLid ? (jidDecode(meLid)?.user ?? null) : null + const { user: mePnUser } = jidDecode(meId)! + const { user: meLidUser } = meLid ? jidDecode(meLid)! : { user: null } // Carousel in DSM wrapper causes error 479 on own devices const isCarouselMsg = isCarouselMessage(message) @@ -1212,7 +1211,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { attrs: { v: '2', type, - count: (participant?.count ?? 0).toString() + count: participant!.count.toString() }, content: encryptedContent }) @@ -1636,7 +1635,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { throw new Boom('Missing media key for update', { statusCode: 400 }) } - const meId = authState.creds.me?.id ?? '' + const meId = authState.creds.me!.id const node = encryptMediaRetryRequest(message.key, mediaKey, meId) let error: Error | undefined = undefined @@ -1713,7 +1712,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { options: MiscMessageGenerationOptions = {} ): Promise => { const startTime = Date.now() - const userJid = authState.creds.me?.id ?? '' + const userJid = authState.creds.me!.id const { medias, @@ -1868,7 +1867,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { // Relay the message await relayMessage(jid, mediaMsg.message, { - messageId: mediaMsg.key.id ?? '', + messageId: mediaMsg.key.id!, useCachedGroupMetadata: options.useCachedGroupMetadata }) @@ -1997,7 +1996,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { ) } - const userJid = authState.creds.me?.id ?? '' + const userJid = authState.creds.me!.id // Special path for carousel: call relayMessage directly with plain JS object // This matches Pastorini's working approach: diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index 0b4f779b..0b1a9563 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -609,12 +609,8 @@ export const makeSocket = (config: SocketConfig) => { }, content: [{ tag: 'count', attrs: {} }] }) - const countChild = getBinaryNodeChild(result, 'count') - if (!countChild) { - return 0 - } - - return +(countChild.attrs.value ?? 0) + const countChild = getBinaryNodeChild(result, 'count')! + return +countChild.attrs.value! } // Pre-key upload state management @@ -1364,7 +1360,7 @@ export const makeSocket = (config: SocketConfig) => { attrs: { to: S_WHATSAPP_NET, type: 'result', - id: stanza.attrs.id ?? '' + id: stanza.attrs.id! } } await sendNode(iq) @@ -1443,9 +1439,7 @@ export const makeSocket = (config: SocketConfig) => { logger.info('opened connection to WA') clearTimeout(qrTimer) // will never happen in all likelyhood -- but just in case WA sends success on first try - if (authState.creds.me) { - ev.emit('creds.update', { me: { ...authState.creds.me, lid: node.attrs.lid } }) - } + ev.emit('creds.update', { me: { ...authState.creds.me!, lid: node.attrs.lid } }) ev.emit('connection.update', { connection: 'open' }) @@ -1468,23 +1462,13 @@ export const makeSocket = (config: SocketConfig) => { const myLID = node.attrs.lid process.nextTick(async () => { try { - const me = authState.creds.me - if (!me) { - return - } - - const myPN = me.id + const myPN = authState.creds.me!.id // Store our own LID-PN mapping await signalRepository.lidMapping.storeLIDPNMappings([{ lid: myLID, pn: myPN }]) // Create device list for our own user (needed for bulk migration) - const decoded = jidDecode(myPN) - if (!decoded) { - return - } - - const { user, device } = decoded + const { user, device } = jidDecode(myPN)! await authState.keys.set({ 'device-list': { [user]: [device?.toString() || '0'] @@ -1572,7 +1556,7 @@ export const makeSocket = (config: SocketConfig) => { logger.debug({ name }, 'updated pushName') sendNode({ tag: 'presence', - attrs: { name: name ?? '' } + attrs: { name: name! } }).catch(err => { logger.warn({ trace: err.stack }, 'error in sending presence update on name change') }) From 2a9d9a0a52c8a3050682debcfe459f68df9f0a7e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Feb 2026 13:56:33 +0000 Subject: [PATCH 3/3] fix: revert remaining ?? '' patterns across Utils, WABinary, Signal, and WAUSync files Completes the comprehensive revert of defensive null coalescing patterns introduced in PRs 124-129. These patterns (e.g. `value ?? ''`) silently produced empty strings instead of failing fast, causing subtle bugs like malformed JIDs and broken Signal session lookups. Files: libsignal.ts, messages-recv.ts, chat-utils.ts, generics.ts, history.ts, messages-media.ts, messages.ts, process-message.ts, validate-connection.ts, jid-utils.ts, UsyncBotProfileProtocol.ts https://claude.ai/code/session_01XaA7GwNaB6azTHFYQ8WEpB --- src/Signal/libsignal.ts | 2 +- src/Socket/messages-recv.ts | 18 ++++---- src/Utils/chat-utils.ts | 16 ++++---- src/Utils/generics.ts | 2 +- src/Utils/history.ts | 4 +- src/Utils/messages-media.ts | 10 ++--- src/Utils/messages.ts | 2 +- src/Utils/process-message.ts | 41 +++++++++---------- src/Utils/validate-connection.ts | 2 +- src/WABinary/jid-utils.ts | 6 +-- .../Protocols/UsyncBotProfileProtocol.ts | 22 +++++----- 11 files changed, 61 insertions(+), 64 deletions(-) diff --git a/src/Signal/libsignal.ts b/src/Signal/libsignal.ts index fb4099b2..93fadafc 100644 --- a/src/Signal/libsignal.ts +++ b/src/Signal/libsignal.ts @@ -708,7 +708,7 @@ function signalStorage( if (domainType === WAJIDDomains.LID || domainType === WAJIDDomains.HOSTED_LID) return id - const pnJid = `${user ?? ''}${device !== '0' ? `:${device}` : ''}@${domainType === WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}` + const pnJid = `${user!}${device !== '0' ? `:${device}` : ''}@${domainType === WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}` const lidForPN = await lidMapping.getLIDForPN(pnJid) if (lidForPN) { diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 5f68675a..7656e38b 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -324,7 +324,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { fromMe: false // TODO: is this really true though }, message: messageProto, - messageTimestamp: +(child.attrs.t ?? 0) + messageTimestamp: +child.attrs.t! }).toJSON() as WAMessage await upsertMessage(fullMessage, 'append') logger.info('Processed plaintext newsletter message') @@ -601,8 +601,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { const actingParticipantLid = fullNode.attrs.participant const actingParticipantPn = fullNode.attrs.participant_pn - const affectedParticipantLid = getBinaryNodeChild(child, 'participant')?.attrs?.jid || actingParticipantLid || '' - const affectedParticipantPn = getBinaryNodeChild(child, 'participant')?.attrs?.phone_number || actingParticipantPn || '' + const affectedParticipantLid = getBinaryNodeChild(child, 'participant')?.attrs?.jid || actingParticipantLid! + const affectedParticipantPn = getBinaryNodeChild(child, 'participant')?.attrs?.phone_number || actingParticipantPn! switch (child?.tag) { case 'create': @@ -663,8 +663,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { participants.length === 1 && // if recv. "remove" message and sender removed themselves // mark as left - (areJidsSameUser(participants[0]?.id, actingParticipantLid) || - areJidsSameUser(participants[0]?.id, actingParticipantPn)) && + (areJidsSameUser(participants[0]!.id, actingParticipantLid) || + areJidsSameUser(participants[0]!.id, actingParticipantPn)) && child.tag === 'remove' ) { msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE @@ -805,9 +805,9 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { break case 'account_sync': - if (child?.tag === 'disappearing_mode') { - const newDuration = +(child.attrs.duration ?? '0') - const timestamp = +(child.attrs.t ?? '0') + if (child!.tag === 'disappearing_mode') { + const newDuration = +child!.attrs.duration! + const timestamp = +child!.attrs.t! logger.info({ newDuration }, 'updated account disappearing mode') @@ -820,7 +820,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } } }) - } else if (child?.tag === 'blocklist') { + } else if (child!.tag === 'blocklist') { const blocklists = getBinaryNodeChildren(child, 'item') for (const { attrs } of blocklists) { diff --git a/src/Utils/chat-utils.ts b/src/Utils/chat-utils.ts index ff872a26..6ea8ebf3 100644 --- a/src/Utils/chat-utils.ts +++ b/src/Utils/chat-utils.ts @@ -470,7 +470,7 @@ export const decodeSyncdSnapshot = async ( areMutationsRequired ? mutation => { const index = mutation.syncAction.index?.toString() - mutationMap[index ?? ''] = mutation + mutationMap[index!] = mutation } : () => {}, validateMacs @@ -558,7 +558,7 @@ export const decodePatches = async ( shouldMutate ? mutation => { const index = mutation.syncAction.index?.toString() - mutationMap[index ?? ''] = mutation + mutationMap[index!] = mutation } : () => {}, true @@ -689,7 +689,7 @@ export const chatModificationToAppPatch = (mod: ChatModification, jid: string) = messageTimestamp: timestamp } }, - index: ['deleteMessageForMe', jid, key.id ?? '', key.fromMe ? '1' : '0', '0'], + index: ['deleteMessageForMe', jid, key.id!, key.fromMe ? '1' : '0', '0'], type: 'regular_high', apiVersion: 3, operation: OP.SET @@ -896,7 +896,7 @@ export const processSyncAction = ( { id, muteEndTime: action.muteAction?.muted ? toNumber(action.muteAction.muteEndTimestamp) : null, - conditional: getChatUpdateConditional(id ?? '', undefined) + conditional: getChatUpdateConditional(id!, undefined) } ]) } else if (action?.archiveChatAction || type === 'archive' || type === 'unarchive') { @@ -925,7 +925,7 @@ export const processSyncAction = ( { id, archived: isArchived, - conditional: getChatUpdateConditional(id ?? '', msgRange) + conditional: getChatUpdateConditional(id!, msgRange) } ]) } else if (action?.markChatAsReadAction) { @@ -939,7 +939,7 @@ export const processSyncAction = ( { id, unreadCount: isNullUpdate ? null : !!markReadAction?.read ? 0 : -1, - conditional: getChatUpdateConditional(id ?? '', markReadAction?.messageRange) + conditional: getChatUpdateConditional(id!, markReadAction?.messageRange) } ]) } else if (action?.deleteMessageForMeAction || type === 'deleteMessageForMe') { @@ -965,7 +965,7 @@ export const processSyncAction = ( { id, pinned: action.pinAction?.pinned ? toNumber(action.timestamp) : null, - conditional: getChatUpdateConditional(id ?? '', undefined) + conditional: getChatUpdateConditional(id!, undefined) } ]) } else if (action?.unarchiveChatsSetting) { @@ -990,7 +990,7 @@ export const processSyncAction = ( ]) } else if (action?.deleteChatAction || type === 'deleteChat') { if (!isInitialSync) { - ev.emit('chats.delete', [id ?? '']) + ev.emit('chats.delete', [id!]) } } else if (action?.labelEditAction) { const { name, color, deleted, predefinedId } = action.labelEditAction diff --git a/src/Utils/generics.ts b/src/Utils/generics.ts index 249914dc..03bbb5dc 100644 --- a/src/Utils/generics.ts +++ b/src/Utils/generics.ts @@ -343,7 +343,7 @@ const STATUS_MAP: { [_: string]: proto.WebMessageInfo.Status } = { * @param type type from receipt */ export const getStatusFromReceiptType = (type: string | undefined) => { - const status = STATUS_MAP[type ?? ''] + const status = STATUS_MAP[type!] if (typeof type === 'undefined') { return proto.WebMessageInfo.Status.DELIVERY_ACK } diff --git a/src/Utils/history.ts b/src/Utils/history.ts index 0394b02a..d5d6183a 100644 --- a/src/Utils/history.ts +++ b/src/Utils/history.ts @@ -294,7 +294,7 @@ export const processHistoryMessage = (item: proto.IHistorySync, logger?: ILogger case proto.HistorySync.HistorySyncType.FULL: case proto.HistorySync.HistorySyncType.ON_DEMAND: for (const chat of (item.conversations ?? []) as Chat[]) { - const chatId = chat.id ?? '' + const chatId = chat.id! // Source 2: Extract LID-PN mapping from conversation object // This handles cases where the mapping isn't in phoneNumberToLidMappings @@ -371,7 +371,7 @@ export const processHistoryMessage = (item: proto.IHistorySync, logger?: ILogger break case proto.HistorySync.HistorySyncType.PUSH_NAME: for (const c of (item.pushnames ?? [])) { - contacts.push({ id: c.id ?? '', notify: c.pushname ?? '' }) + contacts.push({ id: c.id!, notify: c.pushname! }) } break diff --git a/src/Utils/messages-media.ts b/src/Utils/messages-media.ts index 6533d7b2..5271c54a 100644 --- a/src/Utils/messages-media.ts +++ b/src/Utils/messages-media.ts @@ -317,7 +317,7 @@ export const getStream = async (item: WAMediaUpload, opts?: RequestInit & { maxC const urlStr = item.url.toString() if (urlStr.startsWith('data:')) { - const buffer = Buffer.from(urlStr.split(',')[1] ?? '', 'base64') + const buffer = Buffer.from(urlStr.split(',')[1]!, 'base64') return { stream: toReadable(buffer), type: 'buffer' } as const } @@ -532,7 +532,7 @@ export const downloadContentFromMessage = async ( opts: MediaDownloadOptions = {} ) => { const isValidMediaUrl = url?.startsWith('https://mmg.whatsapp.net/') - const downloadUrl = isValidMediaUrl ? url : getUrlFromDirectPath(directPath ?? '') + const downloadUrl = isValidMediaUrl ? url : getUrlFromDirectPath(directPath!) if (!downloadUrl) { throw new Boom('No valid media URL or directPath present in message', { statusCode: 400 }) } @@ -656,7 +656,7 @@ export function extensionForMediaMessage(message: WAMessageContent) { extension = '.jpeg' } else { const messageContent = message[type] as WAGenericMediaMessage - extension = getExtension(messageContent.mimetype ?? '') ?? '' + extension = getExtension(messageContent.mimetype!)! } return extension @@ -864,8 +864,8 @@ export const getWAUploadToServer = ( if (result?.url || result?.direct_path) { urls = { - mediaUrl: result.url ?? '', - directPath: result.direct_path ?? '', + mediaUrl: result.url!, + directPath: result.direct_path!, meta_hmac: result.meta_hmac, fbid: result.fbid, ts: result.ts diff --git a/src/Utils/messages.ts b/src/Utils/messages.ts index 4e5f71d9..e2a8e2bc 100644 --- a/src/Utils/messages.ts +++ b/src/Utils/messages.ts @@ -1770,7 +1770,7 @@ export const generateWAMessageFromContent = ( const innerContent = innerMessage[key as Exclude] const contextInfo: proto.IContextInfo = (innerContent && typeof innerContent === 'object' && 'contextInfo' in innerContent && (innerContent as Record).contextInfo as proto.IContextInfo) || {} - contextInfo.participant = jidNormalizedUser(participant ?? '') + contextInfo.participant = jidNormalizedUser(participant!) contextInfo.stanzaId = quoted.key.id contextInfo.quotedMessage = quotedMsg diff --git a/src/Utils/process-message.ts b/src/Utils/process-message.ts index bf6f256f..a3604860 100644 --- a/src/Utils/process-message.ts +++ b/src/Utils/process-message.ts @@ -59,24 +59,22 @@ const REAL_MSG_REQ_ME_STUB_TYPES = new Set([WAMessageStubType.GROUP_PARTICIPANT_ /** Cleans a received message to further processing */ export const cleanMessage = (message: WAMessage, meId: string, meLid: string) => { // ensure remoteJid and participant doesn't have device or agent in it - const remoteJid = message.key.remoteJid ?? '' - if (isHostedPnUser(remoteJid) || isHostedLidUser(remoteJid)) { + if (isHostedPnUser(message.key.remoteJid!) || isHostedLidUser(message.key.remoteJid!)) { message.key.remoteJid = jidEncode( - jidDecode(remoteJid)?.user ?? '', - isHostedPnUser(remoteJid) ? 's.whatsapp.net' : 'lid' + jidDecode(message.key?.remoteJid!)?.user!, + isHostedPnUser(message.key.remoteJid!) ? 's.whatsapp.net' : 'lid' ) } else { - message.key.remoteJid = jidNormalizedUser(remoteJid) + message.key.remoteJid = jidNormalizedUser(message.key.remoteJid!) } - const participantJid = message.key.participant ?? '' - if (isHostedPnUser(participantJid) || isHostedLidUser(participantJid)) { + if (isHostedPnUser(message.key.participant!) || isHostedLidUser(message.key.participant!)) { message.key.participant = jidEncode( - jidDecode(participantJid)?.user ?? '', - isHostedPnUser(participantJid) ? 's.whatsapp.net' : 'lid' + jidDecode(message.key.participant!)?.user!, + isHostedPnUser(message.key.participant!) ? 's.whatsapp.net' : 'lid' ) } else { - message.key.participant = jidNormalizedUser(participantJid) + message.key.participant = jidNormalizedUser(message.key.participant!) } const content = normalizeMessageContent(message.message) @@ -102,8 +100,8 @@ export const cleanMessage = (message: WAMessage, meId: string, meLid: string) => // if the sender believed the message being reacted to is not from them // we've to correct the key to be from them, or some other participant msgKey.fromMe = !msgKey.fromMe - ? areJidsSameUser(msgKey.participant || (msgKey.remoteJid ?? ''), meId) || - areJidsSameUser(msgKey.participant || (msgKey.remoteJid ?? ''), meLid) + ? areJidsSameUser(msgKey.participant || (msgKey.remoteJid!), meId) || + areJidsSameUser(msgKey.participant || (msgKey.remoteJid!), meLid) : // if the message being reacted to, was from them // fromMe automatically becomes false false @@ -177,12 +175,11 @@ export const shouldIncrementChatUnread = (message: WAMessage) => !message.key.fr * Typically -- that'll be the remoteJid, but for broadcasts, it'll be the participant */ export const getChatId = ({ remoteJid, participant, fromMe }: WAMessageKey) => { - const jid = remoteJid ?? '' - if (isJidBroadcast(jid) && !isJidStatusBroadcast(jid) && !fromMe) { - return participant ?? '' + if (isJidBroadcast(remoteJid!) && !isJidStatusBroadcast(remoteJid!) && !fromMe) { + return participant! } - return jid + return remoteJid! } type PollContext = { @@ -478,7 +475,7 @@ const processMessage = async ( ev.emit('messages.upsert', { messages: [webMessageInfo as WAMessage], type: 'notify', - requestId: response.stanzaId ?? '' + requestId: response.stanzaId! }) } } @@ -517,10 +514,10 @@ const processMessage = async ( const labelAssociationMsg = protocolMsg.memberLabel if (labelAssociationMsg?.label) { ev.emit('group.member-tag.update', { - groupId: chat.id ?? '', + groupId: chat.id!, label: labelAssociationMsg.label, - participant: message.key.participant ?? '', - participantAlt: message.key.participantAlt ?? '', + participant: message.key.participant!, + participantAlt: message.key.participantAlt!, messageTimestamp: Number(message.messageTimestamp) }) } @@ -578,7 +575,7 @@ const processMessage = async ( const meIdNormalised = jidNormalizedUser(meId) // all jids need to be PN - const eventCreatorKey = creationMsgKey.participant || (creationMsgKey.remoteJid ?? '') + const eventCreatorKey = creationMsgKey.participant || (creationMsgKey.remoteJid!) const eventCreatorPn = isLidUser(eventCreatorKey) ? await signalRepository.lidMapping.getPNForLID(eventCreatorKey) : eventCreatorKey @@ -600,7 +597,7 @@ const processMessage = async ( const responseMsg = decryptEventResponse(encEventResponse, { eventEncKey, eventCreatorJid, - eventMsgId: creationMsgKey.id ?? '', + eventMsgId: creationMsgKey.id!, responderJid }) diff --git a/src/Utils/validate-connection.ts b/src/Utils/validate-connection.ts index 6b1f3e13..8e4c73b9 100644 --- a/src/Utils/validate-connection.ts +++ b/src/Utils/validate-connection.ts @@ -237,7 +237,7 @@ export const configureSuccessfulPairing = ( content: [ { tag: 'device-identity', - attrs: { 'key-index': String(deviceIdentity.keyIndex ?? '') }, + attrs: { 'key-index': deviceIdentity.keyIndex!.toString() }, content: accountEnc } ] diff --git a/src/WABinary/jid-utils.ts b/src/WABinary/jid-utils.ts index 34dd447c..0c42456f 100644 --- a/src/WABinary/jid-utils.ts +++ b/src/WABinary/jid-utils.ts @@ -63,7 +63,7 @@ export const jidDecode = (jid: string | undefined): FullJid | undefined => { const userCombined = jid.slice(0, sepIdx) const [userAgent, device] = userCombined.split(':') - const [user, agent] = (userAgent ?? '').split('_') + const [user, agent] = userAgent!.split('_') let domainType = WAJIDDomains.WHATSAPP if (server === 'lid') { @@ -78,7 +78,7 @@ export const jidDecode = (jid: string | undefined): FullJid | undefined => { return { server: server as JidServer, - user: user ?? '', + user: user!, domainType, device: device ? +device : undefined } @@ -114,7 +114,7 @@ export const isAnyPnUser = (jid: string | undefined) => const botRegexp = /^1313555\d{4}$|^131655500\d{2}$/ -export const isJidBot = (jid: string | undefined) => jid && botRegexp.test(jid.split('@')[0] ?? '') && jid.endsWith('@c.us') +export const isJidBot = (jid: string | undefined) => jid && botRegexp.test(jid.split('@')[0]!) && jid.endsWith('@c.us') export const jidNormalizedUser = (jid: string | undefined) => { const result = jidDecode(jid) diff --git a/src/WAUSync/Protocols/UsyncBotProfileProtocol.ts b/src/WAUSync/Protocols/UsyncBotProfileProtocol.ts index 6435c6eb..fa999008 100644 --- a/src/WAUSync/Protocols/UsyncBotProfileProtocol.ts +++ b/src/WAUSync/Protocols/UsyncBotProfileProtocol.ts @@ -35,7 +35,7 @@ export class USyncBotProfileProtocol implements USyncQueryProtocol { return { tag: 'bot', attrs: {}, - content: [{ tag: 'profile', attrs: { persona_id: user.personaId ?? '' } }] + content: [{ tag: 'profile', attrs: { persona_id: user.personaId! } }] } } @@ -51,24 +51,24 @@ export class USyncBotProfileProtocol implements USyncQueryProtocol { for (const command of getBinaryNodeChildren(commandsNode, 'command')) { commands.push({ - name: getBinaryNodeChildString(command, 'name') ?? '', - description: getBinaryNodeChildString(command, 'description') ?? '' + name: getBinaryNodeChildString(command, 'name')!, + description: getBinaryNodeChildString(command, 'description')! }) } for (const prompt of getBinaryNodeChildren(promptsNode, 'prompt')) { - prompts.push(`${getBinaryNodeChildString(prompt, 'emoji') ?? ''} ${getBinaryNodeChildString(prompt, 'text') ?? ''}`) + prompts.push(`${getBinaryNodeChildString(prompt, 'emoji')!} ${getBinaryNodeChildString(prompt, 'text')!}`) } return { isDefault: !!getBinaryNodeChild(profile, 'default'), - jid: node.attrs.jid ?? '', - name: getBinaryNodeChildString(profile, 'name') ?? '', - attributes: getBinaryNodeChildString(profile, 'attributes') ?? '', - description: getBinaryNodeChildString(profile, 'description') ?? '', - category: getBinaryNodeChildString(profile, 'category') ?? '', - personaId: profile?.attrs['persona_id'] ?? '', - commandsDescription: getBinaryNodeChildString(commandsNode, 'description') ?? '', + jid: node.attrs.jid!, + name: getBinaryNodeChildString(profile, 'name')!, + attributes: getBinaryNodeChildString(profile, 'attributes')!, + description: getBinaryNodeChildString(profile, 'description')!, + category: getBinaryNodeChildString(profile, 'category')!, + personaId: profile!.attrs['persona_id']!, + commandsDescription: getBinaryNodeChildString(commandsNode, 'description')!, commands, prompts }