*group: parse @lids properly when processing group notifications
*This commit is breaking, it changes the format of participants in group-participants.update.
This commit is contained in:
@@ -465,6 +465,7 @@ export const extractCommunityMetadata = (result: BinaryNode) => {
|
|||||||
memberAddMode,
|
memberAddMode,
|
||||||
participants: getBinaryNodeChildren(community, 'participant').map(({ attrs }) => {
|
participants: getBinaryNodeChildren(community, 'participant').map(({ attrs }) => {
|
||||||
return {
|
return {
|
||||||
|
// TODO: IMPLEMENT THE PN/LID FIELDS HERE!!
|
||||||
id: attrs.jid!,
|
id: attrs.jid!,
|
||||||
admin: (attrs.type || null) as GroupParticipant['admin']
|
admin: (attrs.type || null) as GroupParticipant['admin']
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -344,6 +344,7 @@ export const extractGroupMetadata = (result: BinaryNode) => {
|
|||||||
joinApprovalMode: !!getBinaryNodeChild(group, 'membership_approval_mode'),
|
joinApprovalMode: !!getBinaryNodeChild(group, 'membership_approval_mode'),
|
||||||
memberAddMode,
|
memberAddMode,
|
||||||
participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) => {
|
participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) => {
|
||||||
|
// TODO: Store LID MAPPINGS
|
||||||
return {
|
return {
|
||||||
id: attrs.jid!,
|
id: attrs.jid!,
|
||||||
phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
|
phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
|
||||||
|
|||||||
+44
-11
@@ -5,6 +5,8 @@ import Long from 'long'
|
|||||||
import { proto } from '../../WAProto/index.js'
|
import { proto } from '../../WAProto/index.js'
|
||||||
import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT } from '../Defaults'
|
import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT } from '../Defaults'
|
||||||
import type {
|
import type {
|
||||||
|
GroupParticipant,
|
||||||
|
LIDMapping,
|
||||||
MessageReceiptType,
|
MessageReceiptType,
|
||||||
MessageRelayOptions,
|
MessageRelayOptions,
|
||||||
MessageUserReceipt,
|
MessageUserReceipt,
|
||||||
@@ -28,6 +30,7 @@ import {
|
|||||||
derivePairingCodeKey,
|
derivePairingCodeKey,
|
||||||
encodeBigEndian,
|
encodeBigEndian,
|
||||||
encodeSignedDeviceIdentity,
|
encodeSignedDeviceIdentity,
|
||||||
|
extractAddressingContext,
|
||||||
getCallStatusFromNode,
|
getCallStatusFromNode,
|
||||||
getHistoryMsg,
|
getHistoryMsg,
|
||||||
getNextPreKeys,
|
getNextPreKeys,
|
||||||
@@ -51,6 +54,7 @@ import {
|
|||||||
isJidGroup,
|
isJidGroup,
|
||||||
isJidStatusBroadcast,
|
isJidStatusBroadcast,
|
||||||
isLidUser,
|
isLidUser,
|
||||||
|
isPnUser,
|
||||||
jidDecode,
|
jidDecode,
|
||||||
jidNormalizedUser,
|
jidNormalizedUser,
|
||||||
S_WHATSAPP_NET
|
S_WHATSAPP_NET
|
||||||
@@ -550,16 +554,22 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleGroupNotification = (participant: string, child: BinaryNode, msg: Partial<WAMessage>) => {
|
const handleGroupNotification = (fullNode: BinaryNode, child: BinaryNode, msg: Partial<WAMessage>) => {
|
||||||
const participantJid = getBinaryNodeChild(child, 'participant')?.attrs?.jid || participant
|
// TODO: Support PN/LID (Here is only LID now)
|
||||||
// TODO: Add participant LID
|
|
||||||
|
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!
|
||||||
|
|
||||||
switch (child?.tag) {
|
switch (child?.tag) {
|
||||||
case 'create':
|
case 'create':
|
||||||
const metadata = extractGroupMetadata(child)
|
const metadata = extractGroupMetadata(child)
|
||||||
|
|
||||||
msg.messageStubType = WAMessageStubType.GROUP_CREATE
|
msg.messageStubType = WAMessageStubType.GROUP_CREATE
|
||||||
msg.messageStubParameters = [metadata.subject]
|
msg.messageStubParameters = [metadata.subject]
|
||||||
msg.key = { participant: metadata.owner }
|
msg.key = { participant: metadata.owner, participantAlt: metadata.ownerPn }
|
||||||
|
|
||||||
ev.emit('chats.upsert', [
|
ev.emit('chats.upsert', [
|
||||||
{
|
{
|
||||||
@@ -571,7 +581,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
ev.emit('groups.upsert', [
|
ev.emit('groups.upsert', [
|
||||||
{
|
{
|
||||||
...metadata,
|
...metadata,
|
||||||
author: participant
|
author: actingParticipantLid,
|
||||||
|
authorPn: actingParticipantPn
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
break
|
break
|
||||||
@@ -597,12 +608,22 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
const stubType = `GROUP_PARTICIPANT_${child.tag.toUpperCase()}`
|
const stubType = `GROUP_PARTICIPANT_${child.tag.toUpperCase()}`
|
||||||
msg.messageStubType = WAMessageStubType[stubType as keyof typeof WAMessageStubType]
|
msg.messageStubType = WAMessageStubType[stubType as keyof typeof WAMessageStubType]
|
||||||
|
|
||||||
const participants = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid!)
|
const participants = getBinaryNodeChildren(child, 'participant').map(({ attrs }) => {
|
||||||
|
// TODO: Store LID MAPPINGS
|
||||||
|
return {
|
||||||
|
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']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if (
|
if (
|
||||||
participants.length === 1 &&
|
participants.length === 1 &&
|
||||||
// if recv. "remove" message and sender removed themselves
|
// if recv. "remove" message and sender removed themselves
|
||||||
// mark as left
|
// mark as left
|
||||||
areJidsSameUser(participants[0], participant) &&
|
(areJidsSameUser(participants[0]!.id, actingParticipantLid) ||
|
||||||
|
areJidsSameUser(participants[0]!.id, actingParticipantPn)) &&
|
||||||
child.tag === 'remove'
|
child.tag === 'remove'
|
||||||
) {
|
) {
|
||||||
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE
|
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE
|
||||||
@@ -651,12 +672,20 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
break
|
break
|
||||||
case 'created_membership_requests':
|
case 'created_membership_requests':
|
||||||
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD
|
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD
|
||||||
msg.messageStubParameters = [participantJid, 'created', child.attrs.request_method!]
|
msg.messageStubParameters = [
|
||||||
|
{ lid: affectedParticipantLid, pn: affectedParticipantPn } as LIDMapping,
|
||||||
|
'created',
|
||||||
|
child.attrs.request_method!
|
||||||
|
]
|
||||||
break
|
break
|
||||||
case 'revoked_membership_requests':
|
case 'revoked_membership_requests':
|
||||||
const isDenied = areJidsSameUser(participantJid, participant)
|
const isDenied = areJidsSameUser(affectedParticipantLid, actingParticipantLid)
|
||||||
|
// TODO: LIDMAPPING SUPPORT
|
||||||
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD
|
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD
|
||||||
msg.messageStubParameters = [participantJid, isDenied ? 'revoked' : 'rejected']
|
msg.messageStubParameters = [
|
||||||
|
{ lid: affectedParticipantLid, pn: affectedParticipantPn } as LIDMapping,
|
||||||
|
isDenied ? 'revoked' : 'rejected'
|
||||||
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -690,7 +719,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
await handleMexNewsletterNotification(node)
|
await handleMexNewsletterNotification(node)
|
||||||
break
|
break
|
||||||
case 'w:gp2':
|
case 'w:gp2':
|
||||||
handleGroupNotification(node.attrs.participant!, child!, result)
|
// TODO: HANDLE PARTICIPANT_PN
|
||||||
|
handleGroupNotification(node, child!, result)
|
||||||
break
|
break
|
||||||
case 'mediaretry':
|
case 'mediaretry':
|
||||||
const event = decodeMediaRetryNode(node)
|
const event = decodeMediaRetryNode(node)
|
||||||
@@ -1083,10 +1113,13 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
const msg = await processNotification(node)
|
const msg = await processNotification(node)
|
||||||
if (msg) {
|
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 = {
|
msg.key = {
|
||||||
remoteJid,
|
remoteJid,
|
||||||
fromMe,
|
fromMe,
|
||||||
participant: node.attrs.participant,
|
participant: node.attrs.participant,
|
||||||
|
participantAlt,
|
||||||
|
addressingMode,
|
||||||
id: node.attrs.id,
|
id: node.attrs.id,
|
||||||
...(msg.key || {})
|
...(msg.key || {})
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-2
@@ -4,7 +4,13 @@ import type { AuthenticationCreds } from './Auth'
|
|||||||
import type { WACallEvent } from './Call'
|
import type { WACallEvent } from './Call'
|
||||||
import type { Chat, ChatUpdate, PresenceData } from './Chat'
|
import type { Chat, ChatUpdate, PresenceData } from './Chat'
|
||||||
import type { Contact } from './Contact'
|
import type { Contact } from './Contact'
|
||||||
import type { GroupMetadata, ParticipantAction, RequestJoinAction, RequestJoinMethod } from './GroupMetadata'
|
import type {
|
||||||
|
GroupMetadata,
|
||||||
|
GroupParticipant,
|
||||||
|
ParticipantAction,
|
||||||
|
RequestJoinAction,
|
||||||
|
RequestJoinMethod
|
||||||
|
} from './GroupMetadata'
|
||||||
import type { Label } from './Label'
|
import type { Label } from './Label'
|
||||||
import type { LabelAssociation } from './LabelAssociation'
|
import type { LabelAssociation } from './LabelAssociation'
|
||||||
import type { MessageUpsertType, MessageUserReceiptUpdate, WAMessage, WAMessageKey, WAMessageUpdate } from './Message'
|
import type { MessageUpsertType, MessageUserReceiptUpdate, WAMessage, WAMessageKey, WAMessageUpdate } from './Message'
|
||||||
@@ -56,11 +62,19 @@ export type BaileysEventMap = {
|
|||||||
'groups.upsert': GroupMetadata[]
|
'groups.upsert': GroupMetadata[]
|
||||||
'groups.update': Partial<GroupMetadata>[]
|
'groups.update': Partial<GroupMetadata>[]
|
||||||
/** apply an action to participants in a group */
|
/** apply an action to participants in a group */
|
||||||
'group-participants.update': { id: string; author: string; participants: string[]; action: ParticipantAction }
|
'group-participants.update': {
|
||||||
|
id: string
|
||||||
|
author: string
|
||||||
|
authorPn?: string
|
||||||
|
participants: GroupParticipant[]
|
||||||
|
action: ParticipantAction
|
||||||
|
}
|
||||||
'group.join-request': {
|
'group.join-request': {
|
||||||
id: string
|
id: string
|
||||||
author: string
|
author: string
|
||||||
|
authorPn?: string
|
||||||
participant: string
|
participant: string
|
||||||
|
participantPn?: string
|
||||||
action: RequestJoinAction
|
action: RequestJoinAction
|
||||||
method: RequestJoinMethod
|
method: RequestJoinMethod
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export interface GroupMetadata {
|
|||||||
inviteCode?: string
|
inviteCode?: string
|
||||||
/** the person who added you to group or changed some setting in group */
|
/** the person who added you to group or changed some setting in group */
|
||||||
author?: string
|
author?: string
|
||||||
|
authorPn?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WAGroupCreateResponse {
|
export interface WAGroupCreateResponse {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type { CacheStore } from './Socket'
|
|||||||
|
|
||||||
// export the WAMessage Prototypes
|
// export the WAMessage Prototypes
|
||||||
export { proto as WAProto }
|
export { proto as WAProto }
|
||||||
export type WAMessage = proto.IWebMessageInfo & { key: WAMessageKey }
|
export type WAMessage = proto.IWebMessageInfo & { key: WAMessageKey; messageStubParameters?: any }
|
||||||
export type WAMessageContent = proto.IMessage
|
export type WAMessageContent = proto.IMessage
|
||||||
export type WAContactMessage = proto.Message.IContactMessage
|
export type WAContactMessage = proto.Message.IContactMessage
|
||||||
export type WAContactsArrayMessage = proto.Message.IContactsArrayMessage
|
export type WAContactsArrayMessage = proto.Message.IContactsArrayMessage
|
||||||
|
|||||||
@@ -545,7 +545,7 @@ function append<E extends BufferableEvent>(
|
|||||||
const chatId = message.key.remoteJid!
|
const chatId = message.key.remoteJid!
|
||||||
const chat = data.chatUpdates[chatId] || data.chatUpserts[chatId]
|
const chat = data.chatUpdates[chatId] || data.chatUpserts[chatId]
|
||||||
if (
|
if (
|
||||||
isRealMessage(message, '') &&
|
isRealMessage(message) &&
|
||||||
shouldIncrementChatUnread(message) &&
|
shouldIncrementChatUnread(message) &&
|
||||||
typeof chat?.unreadCount === 'number' &&
|
typeof chat?.unreadCount === 'number' &&
|
||||||
chat.unreadCount > 0
|
chat.unreadCount > 0
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import type {
|
|||||||
CacheStore,
|
CacheStore,
|
||||||
Chat,
|
Chat,
|
||||||
GroupMetadata,
|
GroupMetadata,
|
||||||
|
GroupParticipant,
|
||||||
|
LIDMapping,
|
||||||
ParticipantAction,
|
ParticipantAction,
|
||||||
RequestJoinAction,
|
RequestJoinAction,
|
||||||
RequestJoinMethod,
|
RequestJoinMethod,
|
||||||
@@ -101,14 +103,14 @@ export const cleanMessage = (message: WAMessage, meId: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isRealMessage = (message: WAMessage, meId: string) => {
|
// TODO: target:audit AUDIT THIS FUNCTION AGAIN
|
||||||
|
export const isRealMessage = (message: WAMessage) => {
|
||||||
const normalizedContent = normalizeMessageContent(message.message)
|
const normalizedContent = normalizeMessageContent(message.message)
|
||||||
const hasSomeContent = !!getContentType(normalizedContent)
|
const hasSomeContent = !!getContentType(normalizedContent)
|
||||||
return (
|
return (
|
||||||
(!!normalizedContent ||
|
(!!normalizedContent ||
|
||||||
REAL_MSG_STUB_TYPES.has(message.messageStubType!) ||
|
REAL_MSG_STUB_TYPES.has(message.messageStubType!) ||
|
||||||
(REAL_MSG_REQ_ME_STUB_TYPES.has(message.messageStubType!) &&
|
REAL_MSG_REQ_ME_STUB_TYPES.has(message.messageStubType!)) &&
|
||||||
message.messageStubParameters?.some(p => areJidsSameUser(meId, p)))) &&
|
|
||||||
hasSomeContent &&
|
hasSomeContent &&
|
||||||
!normalizedContent?.protocolMessage &&
|
!normalizedContent?.protocolMessage &&
|
||||||
!normalizedContent?.reactionMessage &&
|
!normalizedContent?.reactionMessage &&
|
||||||
@@ -188,7 +190,7 @@ const processMessage = async (
|
|||||||
const { accountSettings } = creds
|
const { accountSettings } = creds
|
||||||
|
|
||||||
const chat: Partial<Chat> = { id: jidNormalizedUser(getChatId(message.key)) }
|
const chat: Partial<Chat> = { id: jidNormalizedUser(getChatId(message.key)) }
|
||||||
const isRealMsg = isRealMessage(message, meId)
|
const isRealMsg = isRealMessage(message)
|
||||||
|
|
||||||
if (isRealMsg) {
|
if (isRealMsg) {
|
||||||
chat.messages = [{ message }]
|
chat.messages = [{ message }]
|
||||||
@@ -362,18 +364,34 @@ const processMessage = async (
|
|||||||
} else if (message.messageStubType) {
|
} else if (message.messageStubType) {
|
||||||
const jid = message.key?.remoteJid!
|
const jid = message.key?.remoteJid!
|
||||||
//let actor = whatsappID (message.participant)
|
//let actor = whatsappID (message.participant)
|
||||||
let participants: string[]
|
let participants: GroupParticipant[]
|
||||||
const emitParticipantsUpdate = (action: ParticipantAction) =>
|
const emitParticipantsUpdate = (action: ParticipantAction) =>
|
||||||
ev.emit('group-participants.update', { id: jid, author: message.participant!, participants, action })
|
ev.emit('group-participants.update', {
|
||||||
|
id: jid,
|
||||||
|
author: message.key.participant!,
|
||||||
|
authorPn: message.key.participantAlt!,
|
||||||
|
participants,
|
||||||
|
action
|
||||||
|
})
|
||||||
const emitGroupUpdate = (update: Partial<GroupMetadata>) => {
|
const emitGroupUpdate = (update: Partial<GroupMetadata>) => {
|
||||||
ev.emit('groups.update', [{ id: jid, ...update, author: message.participant ?? undefined }])
|
ev.emit('groups.update', [
|
||||||
|
{ id: jid, ...update, author: message.key.participant ?? undefined, authorPn: message.key.participantAlt }
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
const emitGroupRequestJoin = (participant: string, action: RequestJoinAction, method: RequestJoinMethod) => {
|
const emitGroupRequestJoin = (participant: LIDMapping, action: RequestJoinAction, method: RequestJoinMethod) => {
|
||||||
ev.emit('group.join-request', { id: jid, author: message.participant!, participant, action, method: method! })
|
ev.emit('group.join-request', {
|
||||||
|
id: jid,
|
||||||
|
author: message.key.participant!,
|
||||||
|
authorPn: message.key.participantAlt!,
|
||||||
|
participant: participant.lid,
|
||||||
|
participantPn: participant.pn,
|
||||||
|
action,
|
||||||
|
method: method!
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const participantsIncludesMe = () => participants.find(jid => areJidsSameUser(meId, jid))
|
const participantsIncludesMe = () => participants.find(jid => areJidsSameUser(meId, jid.phoneNumber)) // ADD SUPPORT FOR LID
|
||||||
|
|
||||||
switch (message.messageStubType) {
|
switch (message.messageStubType) {
|
||||||
case WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER:
|
case WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER:
|
||||||
@@ -438,8 +456,8 @@ const processMessage = async (
|
|||||||
const approvalMode = message.messageStubParameters?.[0]
|
const approvalMode = message.messageStubParameters?.[0]
|
||||||
emitGroupUpdate({ joinApprovalMode: approvalMode === 'on' })
|
emitGroupUpdate({ joinApprovalMode: approvalMode === 'on' })
|
||||||
break
|
break
|
||||||
case WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD:
|
case WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD: // TODO: Add other events
|
||||||
const participant = message.messageStubParameters?.[0] as string
|
const participant = message.messageStubParameters?.[0] as LIDMapping
|
||||||
const action = message.messageStubParameters?.[1] as RequestJoinAction
|
const action = message.messageStubParameters?.[1] as RequestJoinAction
|
||||||
const method = message.messageStubParameters?.[2] as RequestJoinMethod
|
const method = message.messageStubParameters?.[2] as RequestJoinMethod
|
||||||
emitGroupRequestJoin(participant, action, method)
|
emitGroupRequestJoin(participant, action, method)
|
||||||
|
|||||||
Reference in New Issue
Block a user