lid, wip: Support LIDs in Baileys (#1747)

* lid-mapping: get missing lid from usync

* lid-mapping, jid-utils: change to isPnUser and store multiple mappings

* process-message: parse protocolMsg mapping, and store from new msgs

* types: lid-mapping event, addressing enum, alt, contact, group types

* validate, decode: use lid for identity, better logic

* lid: final commit

* linting

* linting

* linting

* linting

* misc: fix testing and also remove version json

* lint: IDE fucking up lint

* lid-mapping: fix build error on NPM

* message-retry: fix proto import
This commit is contained in:
Rajeh Taher
2025-09-08 10:03:28 +03:00
committed by GitHub
parent ca22ae5f9c
commit 20693a59d0
27 changed files with 630 additions and 405 deletions
+29 -31
View File
@@ -6,14 +6,12 @@ import {
type BinaryNode,
isJidBroadcast,
isJidGroup,
isJidMetaIa,
isJidMetaAI,
isJidNewsletter,
isJidStatusBroadcast,
isJidUser,
isLidUser,
jidDecode,
jidEncode,
jidNormalizedUser
isPnUser,
transferDevice
} from '../WABinary'
import { unpadRandomMax16 } from './generics'
import type { ILogger } from './logger'
@@ -23,17 +21,7 @@ const getDecryptionJid = async (sender: string, repository: SignalRepository): P
return sender
}
const lidMapping = repository.getLIDMappingStore()
const normalizedSender = jidNormalizedUser(sender)
const lidForPN = await lidMapping.getLIDForPN(normalizedSender)
if (lidForPN?.includes('@lid')) {
const senderDecoded = jidDecode(sender)
const deviceId = senderDecoded?.device || 0
return jidEncode(jidDecode(lidForPN)!.user, 'lid', deviceId)
}
return sender
return (await repository.getLIDMappingStore().getLIDForPN(sender))!
}
const storeMappingFromEnvelope = async (
@@ -45,7 +33,7 @@ const storeMappingFromEnvelope = async (
): Promise<void> => {
const { senderAlt } = extractAddressingContext(stanza)
if (senderAlt && isLidUser(senderAlt) && isJidUser(sender) && decryptionJid === sender) {
if (senderAlt && isLidUser(senderAlt) && isPnUser(sender) && decryptionJid === sender) {
try {
await repository.storeLIDPNMapping(senderAlt, sender)
logger.debug({ sender, senderAlt }, 'Stored LID mapping from envelope')
@@ -95,14 +83,23 @@ export const extractAddressingContext = (stanza: BinaryNode) => {
let senderAlt: string | undefined
let recipientAlt: string | undefined
const sender = stanza.attrs.participant || stanza.attrs.from
if (addressingMode === 'lid') {
// Message is LID-addressed: sender is LID, extract corresponding PN
senderAlt = stanza.attrs.participant_pn || stanza.attrs.sender_pn
// without device data
senderAlt = stanza.attrs.participant_pn || stanza.attrs.sender_pn || stanza.attrs.peer_recipient_pn
recipientAlt = stanza.attrs.recipient_pn
// with device data
if (sender && senderAlt) senderAlt = transferDevice(sender, senderAlt)
} else {
// Message is PN-addressed: sender is PN, extract corresponding LID
senderAlt = stanza.attrs.participant_lid || stanza.attrs.sender_lid
// without device data
senderAlt = stanza.attrs.participant_lid || stanza.attrs.sender_lid || stanza.attrs.peer_recipient_lid
recipientAlt = stanza.attrs.recipient_lid
//with device data
if (sender && senderAlt) senderAlt = transferDevice(sender, senderAlt)
}
return {
@@ -126,11 +123,13 @@ export function decodeMessageNode(stanza: BinaryNode, meId: string, meLid: strin
const participant: string | undefined = stanza.attrs.participant
const recipient: string | undefined = stanza.attrs.recipient
const addressingContext = extractAddressingContext(stanza)
const isMe = (jid: string) => areJidsSameUser(jid, meId)
const isMeLid = (jid: string) => areJidsSameUser(jid, meLid)
if (isJidUser(from) || isLidUser(from)) {
if (recipient && !isJidMetaIa(recipient)) {
if (isPnUser(from) || isLidUser(from)) {
if (recipient && !isJidMetaAI(recipient)) {
if (!isMe(from!) && !isMeLid(from!)) {
throw new Boom('receipient present, but msg not from me', { data: stanza })
}
@@ -177,13 +176,11 @@ export function decodeMessageNode(stanza: BinaryNode, meId: string, meLid: strin
const key: WAMessageKey = {
remoteJid: chatId,
remoteJidAlt: !isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
fromMe,
id: msgId,
senderLid: stanza?.attrs?.sender_lid,
senderPn: stanza?.attrs?.sender_pn || stanza?.attrs?.peer_recipient_pn,
participant,
participantPn: stanza?.attrs?.participant_pn,
participantLid: stanza?.attrs?.participant_lid,
participantAlt: isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
...(msgType === 'newsletter' && stanza.attrs.server_id ? { server_id: stanza.attrs.server_id } : {})
}
@@ -228,7 +225,7 @@ export const decryptMessageNode = (
}
if (tag === 'unavailable' && attrs.type === 'view_once') {
fullMessage.key.isViewOnce = true
fullMessage.key.isViewOnce = true // TODO: remove from here and add a STUB TYPE
}
if (tag !== 'enc' && tag !== 'plaintext') {
@@ -243,6 +240,12 @@ export const decryptMessageNode = (
let msgBuffer: Uint8Array
const user = isPnUser(sender) ? sender : author // TODO: flaky logic
const decryptionJid = await getDecryptionJid(user, repository)
if (tag !== 'plaintext') {
await storeMappingFromEnvelope(stanza, user, decryptionJid, repository, logger)
}
try {
const e2eType = tag === 'plaintext' ? 'plaintext' : attrs.type
@@ -256,16 +259,11 @@ export const decryptMessageNode = (
break
case 'pkmsg':
case 'msg':
const user = isJidUser(sender) ? sender : author
const decryptionJid = await getDecryptionJid(user, repository)
msgBuffer = await repository.decryptMessage({
jid: decryptionJid,
type: e2eType,
ciphertext: content
})
await storeMappingFromEnvelope(stanza, user, decryptionJid, repository, logger)
break
case 'plaintext':
msgBuffer = content