Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,7 @@ declare namespace WAWebJS {
): Promise<Message>;

/** Send a reaction to a specific messageId */
sendReaction(
messageId: string,
reaction: string,
): Promise<void>;
sendReaction(messageId: string, reaction: string): Promise<void>;

/** Sends a channel admin invitation to a user, allowing them to become an admin of the channel */
sendChannelAdminInvite(
Expand Down
37 changes: 23 additions & 14 deletions src/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -1234,7 +1234,8 @@ class Client extends EventEmitter {
const parentMsgKey = reaction.reactionParentKey;
const timestamp = reaction.reactionTimestamp / 1000;
const sender = reaction.author ?? reaction.from;
const senderUserJid = sender._serialized;
const senderUserJid =
sender._serialized || sender.$1;

return {
...reaction,
Expand Down Expand Up @@ -1262,14 +1263,15 @@ class Client extends EventEmitter {
const parentMsgKey = vote.pollUpdateParentKey;
const timestamp = vote.t / 1000;
const sender = vote.author ?? vote.from;
const senderUserJid = sender._serialized;
const senderUserJid =
sender._serialized || sender.$1;

let parentMessage = Msg.get(
parentMsgKey._serialized,
parentMsgKey._serialized || parentMsgKey.$1,
);
if (!parentMessage) {
const fetched = await Msg.getMessagesById([
parentMsgKey._serialized,
parentMsgKey._serialized || parentMsgKey.$1,
]);
parentMessage = fetched?.messages?.[0] || null;
}
Expand Down Expand Up @@ -1898,7 +1900,7 @@ class Client extends EventEmitter {
.joinGroupViaInvite(inviteCode);
}, inviteCode);

return res.gid._serialized;
return res.gid._serialized || res.gid.$1;
}

/**
Expand Down Expand Up @@ -2442,7 +2444,8 @@ class Client extends EventEmitter {
(participant.wid = window
.require('WAWebApiContact')
.getPhoneNumber(participant.wid));
const participantId = participant.wid._serialized;
const participantId =
participant.wid._serialized || participant.wid.$1;
const statusCode = participant.error || 200;

if (autoSendInviteV4 && statusCode === 403) {
Expand All @@ -2458,7 +2461,8 @@ class Client extends EventEmitter {
(await window
.require('WAWebCollections')
.Chat.find(participant.wid)),
createGroupResult.wid._serialized,
createGroupResult.wid._serialized ||
createGroupResult.wid.$1,
createGroupResult.subject,
participant.invite_code,
participant.invite_code_exp,
Expand Down Expand Up @@ -2932,7 +2936,7 @@ class Client extends EventEmitter {
let chatIds = window
.require('WAWebCollections')
.Blocklist.getModelsArray()
.map((a) => a.id._serialized);
.map((a) => a.id._serialized || a.id.$1);
return Promise.all(
chatIds.map((id) => window.WWebJS.getContact(id)),
);
Expand Down Expand Up @@ -2993,7 +2997,9 @@ class Client extends EventEmitter {
);
const chats = window
.require('WAWebCollections')
.Chat.filter((e) => chatIds.includes(e.id._serialized));
.Chat.filter((e) =>
chatIds.includes(e.id._serialized || e.id.$1),
);

let actions = labels.map((label) => ({
id: label.id,
Expand Down Expand Up @@ -3374,8 +3380,8 @@ class Client extends EventEmitter {
await window.WWebJS.enforceLidAndPnRetrieval(userId);

return {
lid: lid?._serialized,
pn: phone?._serialized,
lid: lid?._serialized || lid?.$1,
pn: phone?._serialized || phone?.$1,
};
}),
);
Expand Down Expand Up @@ -3446,9 +3452,12 @@ class Client extends EventEmitter {

if (!serialized) return null;

serialized.chatId = window
.require('WAWebJidToWid')
.userJidToUserWid(serialized.chatJid)._serialized;
serialized.chatId = (() => {
const _w = window
.require('WAWebJidToWid')
.userJidToUserWid(serialized.chatJid);
return _w._serialized || _w.$1;
})();
delete serialized.chatJid;

return serialized;
Expand Down
14 changes: 14 additions & 0 deletions src/structures/Base.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ class Base {
_patch(data) {
return data;
}

/**
* Normalizes a WhatsApp ID object so that `_serialized` is always defined.
* WhatsApp Web changed `_serialized` to `$1` in July 2026. This ensures
* backward compatibility so all downstream code can continue using `_serialized`.
* @param {object} id
* @returns {object}
*/
static _normalizeId(id) {
if (id && id._serialized == null && id.$1 != null) {
return Object.assign({}, id, { _serialized: id.$1 });
}
return id;
}
}

module.exports = Base;
2 changes: 1 addition & 1 deletion src/structures/Broadcast.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Broadcast extends Base {
* ID that represents the chat
* @type {object}
*/
this.id = data.id;
this.id = Base._normalizeId(data.id);

/**
* Unix timestamp of last status
Expand Down
2 changes: 1 addition & 1 deletion src/structures/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Channel extends Base {
* ID that represents the channel
* @type {ChannelId}
*/
this.id = data.id;
this.id = Base._normalizeId(data.id);

/**
* Title of the channel
Expand Down
2 changes: 1 addition & 1 deletion src/structures/Chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Chat extends Base {
* ID that represents the chat
* @type {object}
*/
this.id = data.id;
this.id = Base._normalizeId(data.id);

/**
* Title of the chat
Expand Down
2 changes: 1 addition & 1 deletion src/structures/ClientInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ClientInfo extends Base {
* Current user ID
* @type {object}
*/
this.wid = data.wid;
this.wid = Base._normalizeId(data.wid);

/**
* @type {object}
Expand Down
4 changes: 2 additions & 2 deletions src/structures/Contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Contact extends Base {
* ID that represents the contact
* @type {ContactId}
*/
this.id = data.id;
this.id = Base._normalizeId(data.id);

/**
* Contact's phone number
Expand Down Expand Up @@ -196,7 +196,7 @@ class Contact extends Base {

contact = await window
.require('WAWebCollections')
.Contact.find(lid._serialized);
.Contact.find(lid._serialized || lid.$1);
}
await window
.require('WAWebBlockContactAction')
Expand Down
22 changes: 13 additions & 9 deletions src/structures/GroupChat.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ class GroupChat extends Chat {
};

for (let pWid of participantWids) {
const pId = pWid._serialized;
const pId = pWid._serialized || pWid.$1;
pWid =
pWid.server === 'lid'
? window
Expand All @@ -170,7 +170,11 @@ class GroupChat extends Chat {
isInviteV4Sent: false,
};

if (groupParticipants.some((p) => p._serialized === pId)) {
if (
groupParticipants.some(
(p) => (p._serialized || p.$1) === pId,
)
) {
participantData[pId].code = 409;
participantData[pId].message = errorCodes[409];
continue;
Expand Down Expand Up @@ -223,7 +227,7 @@ class GroupChat extends Chat {
.require('WAWebChatSendMessages')
.sendGroupInviteMessage(
userChat,
group.id._serialized,
group.id._serialized || group.id.$1,
groupName,
rpcResult.inviteV4Code,
rpcResult.inviteV4CodeExp,
Expand Down Expand Up @@ -274,10 +278,10 @@ class GroupChat extends Chat {

return (
chat.groupMetadata.participants.get(
lid?._serialized,
lid?._serialized || lid?.$1,
) ||
chat.groupMetadata.participants.get(
phone?._serialized,
phone?._serialized || phone?.$1,
)
);
}),
Expand Down Expand Up @@ -312,10 +316,10 @@ class GroupChat extends Chat {

return (
chat.groupMetadata.participants.get(
lid?._serialized,
lid?._serialized || lid?.$1,
) ||
chat.groupMetadata.participants.get(
phone?._serialized,
phone?._serialized || phone?.$1,
)
);
}),
Expand Down Expand Up @@ -350,10 +354,10 @@ class GroupChat extends Chat {

return (
chat.groupMetadata.participants.get(
lid?._serialized,
lid?._serialized || lid?.$1,
) ||
chat.groupMetadata.participants.get(
phone?._serialized,
phone?._serialized || phone?.$1,
)
);
}),
Expand Down
6 changes: 3 additions & 3 deletions src/structures/GroupNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class GroupNotification extends Base {
* ID that represents the groupNotification
* @type {object}
*/
this.id = data.id;
this.id = Base._normalizeId(data.id);

/**
* Extra content
Expand All @@ -45,7 +45,7 @@ class GroupNotification extends Base {
*/
this.chatId =
typeof data.id.remote === 'object'
? data.id.remote._serialized
? data.id.remote._serialized || data.id.remote.$1
: data.id.remote;

/**
Expand All @@ -54,7 +54,7 @@ class GroupNotification extends Base {
*/
this.author =
typeof data.author === 'object'
? data.author._serialized
? data.author._serialized || data.author.$1
: data.author;

/**
Expand Down
18 changes: 10 additions & 8 deletions src/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class Message extends Base {
* ID that represents the message
* @type {object}
*/
this.id = data.id;
// Normalize id: WhatsApp Web changed _serialized to $1 in 2026-07 update.
// Keep _serialized always populated for backward compatibility.
this.id = Base._normalizeId(data.id);

/**
* ACK status for the message
Expand Down Expand Up @@ -75,7 +77,7 @@ class Message extends Base {
*/
this.from =
typeof data.from === 'object' && data.from !== null
? data.from._serialized
? data.from._serialized || data.from.$1
: data.from;

/**
Expand All @@ -87,7 +89,7 @@ class Message extends Base {
*/
this.to =
typeof data.to === 'object' && data.to !== null
? data.to._serialized
? data.to._serialized || data.to.$1
: data.to;

/**
Expand All @@ -96,7 +98,7 @@ class Message extends Base {
*/
this.author =
typeof data.author === 'object' && data.author !== null
? data.author._serialized
? data.author._serialized || data.author.$1
: data.author;

/**
Expand Down Expand Up @@ -211,13 +213,13 @@ class Message extends Base {
groupName: data.inviteGrpName,
fromId:
typeof data.from === 'object' &&
'_serialized' in data.from
? data.from._serialized
(data.from._serialized || data.from.$1)
? data.from._serialized || data.from.$1
: data.from,
toId:
typeof data.to === 'object' &&
'_serialized' in data.to
? data.to._serialized
(data.to._serialized || data.to.$1)
? data.to._serialized || data.to.$1
: data.to,
}
: undefined;
Expand Down
Loading
Loading