@hbmodsofc/baileys 1.5.0 → 1.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/WAProto/index.js +19671 -152026
- package/engine-requirements.js +4 -4
- package/lib/Defaults/index.d.ts +12 -8
- package/lib/Defaults/index.js +90 -124
- package/lib/Signal/Group/group_cipher.d.ts +0 -1
- package/lib/Signal/Group/group_cipher.js +28 -39
- package/lib/Signal/Group/sender-chain-key.d.ts +1 -1
- package/lib/Signal/Group/sender-chain-key.js +9 -2
- package/lib/Signal/Group/sender-key-distribution-message.js +3 -3
- package/lib/Signal/Group/sender-key-message.js +3 -3
- package/lib/Signal/Group/sender-key-state.d.ts +4 -4
- package/lib/Signal/Group/sender-key-state.js +47 -16
- package/lib/Signal/libsignal.d.ts +7 -3
- package/lib/Signal/libsignal.js +224 -39
- package/lib/Signal/lid-mapping.d.ts +26 -0
- package/lib/Signal/lid-mapping.js +146 -0
- package/lib/Socket/Client/index.d.ts +2 -3
- package/lib/Socket/Client/index.js +2 -3
- package/lib/Socket/Client/{abstract-socket-client.d.ts → types.d.ts} +1 -3
- package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +1 -1
- package/lib/Socket/Client/{web-socket-client.js → websocket.js} +10 -16
- package/lib/Socket/business.d.ts +94 -78
- package/lib/Socket/business.js +130 -11
- package/lib/Socket/chats.d.ts +63 -233
- package/lib/Socket/chats.js +234 -184
- package/lib/Socket/communities.d.ts +232 -0
- package/lib/Socket/communities.js +402 -0
- package/lib/Socket/groups.d.ts +62 -41
- package/lib/Socket/groups.js +76 -64
- package/lib/Socket/index.d.ts +129 -83
- package/lib/Socket/index.js +13 -6
- package/lib/Socket/messages-recv.d.ts +59 -48
- package/lib/Socket/messages-recv.js +516 -371
- package/lib/Socket/messages-send.d.ts +86 -67
- package/lib/Socket/messages-send.js +1091 -1
- package/lib/Socket/mex.d.ts +2 -0
- package/lib/Socket/mex.js +45 -0
- package/lib/Socket/newsletter.d.ts +76 -64
- package/lib/Socket/newsletter.js +184 -1
- package/lib/Socket/socket.d.ts +19 -13
- package/lib/Socket/socket.js +805 -1
- package/lib/Types/Auth.d.ts +4 -10
- package/lib/Types/Bussines.d.ts +24 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Call.d.ts +1 -1
- package/lib/Types/Chat.d.ts +29 -9
- package/lib/Types/Chat.js +7 -1
- package/lib/Types/Contact.d.ts +5 -1
- package/lib/Types/Events.d.ts +55 -14
- package/lib/Types/GroupMetadata.d.ts +15 -5
- package/lib/Types/Label.d.ts +11 -0
- package/lib/Types/Label.js +1 -1
- package/lib/Types/LabelAssociation.js +1 -1
- package/lib/Types/Message.d.ts +75 -49
- package/lib/Types/Message.js +10 -7
- package/lib/Types/Newsletter.d.ts +129 -98
- package/lib/Types/Newsletter.js +33 -38
- package/lib/Types/Product.d.ts +1 -1
- package/lib/Types/Signal.d.ts +29 -1
- package/lib/Types/Socket.d.ts +48 -22
- package/lib/Types/State.d.ts +13 -2
- package/lib/Types/State.js +12 -0
- package/lib/Types/USync.d.ts +1 -1
- package/lib/Types/index.d.ts +10 -3
- package/lib/Types/index.js +2 -2
- package/lib/Utils/auth-utils.d.ts +3 -3
- package/lib/Utils/auth-utils.js +378 -102
- package/lib/Utils/baileys-event-stream.js +1 -1
- package/lib/Utils/business.d.ts +2 -2
- package/lib/Utils/business.js +19 -13
- package/lib/Utils/chat-utils.d.ts +21 -22
- package/lib/Utils/chat-utils.js +201 -154
- package/lib/Utils/crypto.d.ts +18 -19
- package/lib/Utils/crypto.js +78 -37
- package/lib/Utils/decode-wa-message.d.ts +34 -7
- package/lib/Utils/decode-wa-message.js +138 -66
- package/lib/Utils/event-buffer.d.ts +6 -8
- package/lib/Utils/event-buffer.js +81 -43
- package/lib/Utils/generics.d.ts +27 -27
- package/lib/Utils/generics.js +128 -133
- package/lib/Utils/history.d.ts +9 -5
- package/lib/Utils/history.js +17 -23
- package/lib/Utils/index.d.ts +2 -0
- package/lib/Utils/index.js +2 -0
- package/lib/Utils/lidToJid-test.d.ts +11 -0
- package/lib/Utils/lidToJid-test.js +27 -0
- package/lib/Utils/link-preview.d.ts +4 -4
- package/lib/Utils/link-preview.js +40 -12
- package/lib/Utils/logger.d.ts +11 -3
- package/lib/Utils/lt-hash.d.ts +8 -8
- package/lib/Utils/lt-hash.js +23 -24
- package/lib/Utils/make-mutex.d.ts +2 -2
- package/lib/Utils/make-mutex.js +3 -2
- package/lib/Utils/message-retry-manager.d.ts +81 -0
- package/lib/Utils/message-retry-manager.js +152 -0
- package/lib/Utils/messages-media.d.ts +37 -41
- package/lib/Utils/messages-media.js +252 -368
- package/lib/Utils/messages.d.ts +13 -15
- package/lib/Utils/messages.js +274 -261
- package/lib/Utils/noise-handler.d.ts +13 -15
- package/lib/Utils/noise-handler.js +20 -26
- package/lib/Utils/process-message.d.ts +9 -8
- package/lib/Utils/process-message.js +157 -93
- package/lib/Utils/signal.d.ts +6 -5
- package/lib/Utils/signal.js +37 -29
- package/lib/Utils/use-multi-file-auth-state.d.ts +1 -2
- package/lib/Utils/use-multi-file-auth-state.js +12 -7
- package/lib/Utils/validate-connection.d.ts +5 -6
- package/lib/Utils/validate-connection.js +39 -97
- package/lib/WABinary/constants.d.ts +24 -27
- package/lib/WABinary/constants.js +1276 -13
- package/lib/WABinary/decode.d.ts +3 -4
- package/lib/WABinary/decode.js +28 -14
- package/lib/WABinary/encode.d.ts +1 -2
- package/lib/WABinary/encode.js +134 -147
- package/lib/WABinary/generic-utils.d.ts +4 -7
- package/lib/WABinary/generic-utils.js +40 -125
- package/lib/WABinary/jid-utils.d.ts +13 -8
- package/lib/WABinary/jid-utils.js +27 -16
- package/lib/WAM/BinaryInfo.d.ts +2 -11
- package/lib/WAM/constants.d.ts +3 -2
- package/lib/WAM/constants.js +2252 -2359
- package/lib/WAM/encode.d.ts +1 -2
- package/lib/WAM/encode.js +8 -11
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +2 -2
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +3 -4
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -2
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +5 -5
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -2
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +5 -5
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -2
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +5 -6
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +2 -2
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +1 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +4 -3
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +11 -3
- package/lib/WAUSync/USyncQuery.d.ts +2 -2
- package/lib/WAUSync/USyncQuery.js +19 -15
- package/lib/WAUSync/USyncUser.d.ts +5 -5
- package/lib/WAUSync/index.d.ts +1 -1
- package/lib/WAUSync/index.js +1 -1
- package/package.json +102 -102
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Signal/Group/queue-job.d.ts +0 -1
- package/lib/Signal/Group/queue-job.js +0 -57
- package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/hbmods.d.ts +0 -253
- package/lib/Socket/hbmods.js +0 -1
- package/lib/Socket/registration.d.ts +0 -267
- package/lib/Socket/registration.js +0 -166
- package/lib/Socket/usync.d.ts +0 -36
- package/lib/Socket/usync.js +0 -70
- /package/lib/Socket/Client/{abstract-socket-client.js → types.js} +0 -0
|
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.makeMessagesRecvSocket = void 0;
|
|
7
|
+
const node_cache_1 = __importDefault(require("@cacheable/node-cache"));
|
|
7
8
|
const boom_1 = require("@hapi/boom");
|
|
8
9
|
const crypto_1 = require("crypto");
|
|
9
|
-
const
|
|
10
|
-
const WAProto_1 = require("../../WAProto");
|
|
10
|
+
const index_js_1 = require("../../WAProto/index.js");
|
|
11
11
|
const Defaults_1 = require("../Defaults");
|
|
12
12
|
const Types_1 = require("../Types");
|
|
13
13
|
const Utils_1 = require("../Utils");
|
|
@@ -16,49 +16,208 @@ const WABinary_1 = require("../WABinary");
|
|
|
16
16
|
const groups_1 = require("./groups");
|
|
17
17
|
const messages_send_1 = require("./messages-send");
|
|
18
18
|
const makeMessagesRecvSocket = (config) => {
|
|
19
|
-
const {
|
|
20
|
-
logger,
|
|
21
|
-
retryRequestDelayMs,
|
|
22
|
-
maxMsgRetryCount,
|
|
23
|
-
getMessage,
|
|
24
|
-
shouldIgnoreJid
|
|
25
|
-
} = config;
|
|
19
|
+
const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid, enableAutoSessionRecreation } = config;
|
|
26
20
|
const sock = (0, messages_send_1.makeMessagesSocket)(config);
|
|
27
|
-
const {
|
|
28
|
-
ev,
|
|
29
|
-
authState,
|
|
30
|
-
ws,
|
|
31
|
-
processingMutex,
|
|
32
|
-
signalRepository,
|
|
33
|
-
query,
|
|
34
|
-
upsertMessage,
|
|
35
|
-
resyncAppState,
|
|
36
|
-
groupMetadata,
|
|
37
|
-
onUnexpectedError,
|
|
38
|
-
assertSessions,
|
|
39
|
-
sendNode,
|
|
40
|
-
relayMessage,
|
|
41
|
-
sendReceipt,
|
|
42
|
-
uploadPreKeys,
|
|
43
|
-
createParticipantNodes,
|
|
44
|
-
getUSyncDevices,
|
|
45
|
-
sendPeerDataOperationMessage
|
|
46
|
-
} = sock;
|
|
21
|
+
const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, messageRetryManager } = sock;
|
|
47
22
|
/** this mutex ensures that each retryRequest will wait for the previous one to finish */
|
|
48
23
|
const retryMutex = (0, make_mutex_1.makeMutex)();
|
|
49
|
-
const msgRetryCache = config.msgRetryCounterCache ||
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
24
|
+
const msgRetryCache = config.msgRetryCounterCache ||
|
|
25
|
+
new node_cache_1.default({
|
|
26
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
27
|
+
useClones: false
|
|
28
|
+
});
|
|
29
|
+
const callOfferCache = config.callOfferCache ||
|
|
30
|
+
new node_cache_1.default({
|
|
31
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.CALL_OFFER, // 5 mins
|
|
32
|
+
useClones: false
|
|
33
|
+
});
|
|
34
|
+
const placeholderResendCache = config.placeholderResendCache ||
|
|
35
|
+
new node_cache_1.default({
|
|
36
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
37
|
+
useClones: false
|
|
38
|
+
});
|
|
61
39
|
let sendActiveReceipts = false;
|
|
40
|
+
const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
|
|
41
|
+
if (!authState.creds.me?.id) {
|
|
42
|
+
throw new boom_1.Boom('Not authenticated');
|
|
43
|
+
}
|
|
44
|
+
const pdoMessage = {
|
|
45
|
+
historySyncOnDemandRequest: {
|
|
46
|
+
chatJid: oldestMsgKey.remoteJid,
|
|
47
|
+
oldestMsgFromMe: oldestMsgKey.fromMe,
|
|
48
|
+
oldestMsgId: oldestMsgKey.id,
|
|
49
|
+
oldestMsgTimestampMs: oldestMsgTimestamp,
|
|
50
|
+
onDemandMsgCount: count
|
|
51
|
+
},
|
|
52
|
+
peerDataOperationRequestType: index_js_1.proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
|
|
53
|
+
};
|
|
54
|
+
return sendPeerDataOperationMessage(pdoMessage);
|
|
55
|
+
};
|
|
56
|
+
const requestPlaceholderResend = async (messageKey) => {
|
|
57
|
+
if (!authState.creds.me?.id) {
|
|
58
|
+
throw new boom_1.Boom('Not authenticated');
|
|
59
|
+
}
|
|
60
|
+
if (placeholderResendCache.get(messageKey?.id)) {
|
|
61
|
+
logger.debug({ messageKey }, 'already requested resend');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
placeholderResendCache.set(messageKey?.id, true);
|
|
66
|
+
}
|
|
67
|
+
await (0, Utils_1.delay)(5000);
|
|
68
|
+
if (!placeholderResendCache.get(messageKey?.id)) {
|
|
69
|
+
logger.debug({ messageKey }, 'message received while resend requested');
|
|
70
|
+
return 'RESOLVED';
|
|
71
|
+
}
|
|
72
|
+
const pdoMessage = {
|
|
73
|
+
placeholderMessageResendRequest: [
|
|
74
|
+
{
|
|
75
|
+
messageKey
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
peerDataOperationRequestType: index_js_1.proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
|
|
79
|
+
};
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
if (placeholderResendCache.get(messageKey?.id)) {
|
|
82
|
+
logger.debug({ messageKey }, 'PDO message without response after 15 seconds. Phone possibly offline');
|
|
83
|
+
placeholderResendCache.del(messageKey?.id);
|
|
84
|
+
}
|
|
85
|
+
}, 15000);
|
|
86
|
+
return sendPeerDataOperationMessage(pdoMessage);
|
|
87
|
+
};
|
|
88
|
+
// Handles mex newsletter notifications
|
|
89
|
+
const handleMexNewsletterNotification = async (node) => {
|
|
90
|
+
const mexNode = (0, WABinary_1.getBinaryNodeChild)(node, 'mex');
|
|
91
|
+
if (!mexNode?.content) {
|
|
92
|
+
logger.warn({ node }, 'Invalid mex newsletter notification');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
let data;
|
|
96
|
+
try {
|
|
97
|
+
data = JSON.parse(mexNode.content.toString());
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
logger.error({ err: error, node }, 'Failed to parse mex newsletter notification');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const operation = data?.operation;
|
|
104
|
+
const updates = data?.updates;
|
|
105
|
+
if (!updates || !operation) {
|
|
106
|
+
logger.warn({ data }, 'Invalid mex newsletter notification content');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
logger.info({ operation, updates }, 'got mex newsletter notification');
|
|
110
|
+
switch (operation) {
|
|
111
|
+
case 'NotificationNewsletterUpdate':
|
|
112
|
+
for (const update of updates) {
|
|
113
|
+
if (update.jid && update.settings && Object.keys(update.settings).length > 0) {
|
|
114
|
+
ev.emit('newsletter-settings.update', {
|
|
115
|
+
id: update.jid,
|
|
116
|
+
update: update.settings
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
case 'NotificationNewsletterAdminPromote':
|
|
122
|
+
for (const update of updates) {
|
|
123
|
+
if (update.jid && update.user) {
|
|
124
|
+
ev.emit('newsletter-participants.update', {
|
|
125
|
+
id: update.jid,
|
|
126
|
+
author: node.attrs.from,
|
|
127
|
+
user: update.user,
|
|
128
|
+
new_role: 'ADMIN',
|
|
129
|
+
action: 'promote'
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
default:
|
|
135
|
+
logger.info({ operation, data }, 'Unhandled mex newsletter notification');
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
// Handles newsletter notifications
|
|
140
|
+
const handleNewsletterNotification = async (node) => {
|
|
141
|
+
const from = node.attrs.from;
|
|
142
|
+
const child = (0, WABinary_1.getAllBinaryNodeChildren)(node)[0];
|
|
143
|
+
const author = node.attrs.participant;
|
|
144
|
+
logger.info({ from, child }, 'got newsletter notification');
|
|
145
|
+
switch (child.tag) {
|
|
146
|
+
case 'reaction':
|
|
147
|
+
const reactionUpdate = {
|
|
148
|
+
id: from,
|
|
149
|
+
server_id: child.attrs.message_id,
|
|
150
|
+
reaction: {
|
|
151
|
+
code: (0, WABinary_1.getBinaryNodeChildString)(child, 'reaction'),
|
|
152
|
+
count: 1
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
ev.emit('newsletter.reaction', reactionUpdate);
|
|
156
|
+
break;
|
|
157
|
+
case 'view':
|
|
158
|
+
const viewUpdate = {
|
|
159
|
+
id: from,
|
|
160
|
+
server_id: child.attrs.message_id,
|
|
161
|
+
count: parseInt(child.content?.toString() || '0', 10)
|
|
162
|
+
};
|
|
163
|
+
ev.emit('newsletter.view', viewUpdate);
|
|
164
|
+
break;
|
|
165
|
+
case 'participant':
|
|
166
|
+
const participantUpdate = {
|
|
167
|
+
id: from,
|
|
168
|
+
author,
|
|
169
|
+
user: child.attrs.jid,
|
|
170
|
+
action: child.attrs.action,
|
|
171
|
+
new_role: child.attrs.role
|
|
172
|
+
};
|
|
173
|
+
ev.emit('newsletter-participants.update', participantUpdate);
|
|
174
|
+
break;
|
|
175
|
+
case 'update':
|
|
176
|
+
const settingsNode = (0, WABinary_1.getBinaryNodeChild)(child, 'settings');
|
|
177
|
+
if (settingsNode) {
|
|
178
|
+
const update = {};
|
|
179
|
+
const nameNode = (0, WABinary_1.getBinaryNodeChild)(settingsNode, 'name');
|
|
180
|
+
if (nameNode?.content)
|
|
181
|
+
update.name = nameNode.content.toString();
|
|
182
|
+
const descriptionNode = (0, WABinary_1.getBinaryNodeChild)(settingsNode, 'description');
|
|
183
|
+
if (descriptionNode?.content)
|
|
184
|
+
update.description = descriptionNode.content.toString();
|
|
185
|
+
ev.emit('newsletter-settings.update', {
|
|
186
|
+
id: from,
|
|
187
|
+
update
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
case 'message':
|
|
192
|
+
const plaintextNode = (0, WABinary_1.getBinaryNodeChild)(child, 'plaintext');
|
|
193
|
+
if (plaintextNode?.content) {
|
|
194
|
+
try {
|
|
195
|
+
const contentBuf = typeof plaintextNode.content === 'string'
|
|
196
|
+
? Buffer.from(plaintextNode.content, 'binary')
|
|
197
|
+
: Buffer.from(plaintextNode.content);
|
|
198
|
+
const messageProto = index_js_1.proto.Message.decode(contentBuf);
|
|
199
|
+
const fullMessage = index_js_1.proto.WebMessageInfo.create({
|
|
200
|
+
key: {
|
|
201
|
+
remoteJid: from,
|
|
202
|
+
id: child.attrs.message_id || child.attrs.server_id,
|
|
203
|
+
fromMe: false
|
|
204
|
+
},
|
|
205
|
+
message: messageProto,
|
|
206
|
+
messageTimestamp: +child.attrs.t
|
|
207
|
+
});
|
|
208
|
+
await upsertMessage(fullMessage, 'append');
|
|
209
|
+
logger.info('Processed plaintext newsletter message');
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
logger.error({ error }, 'Failed to decode plaintext newsletter message');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
default:
|
|
217
|
+
logger.warn({ node }, 'Unknown newsletter notification');
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
62
221
|
const sendMessageAck = async ({ tag, attrs, content }, errorCode) => {
|
|
63
222
|
const stanza = {
|
|
64
223
|
tag: 'ack',
|
|
@@ -67,7 +226,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
67
226
|
to: attrs.from,
|
|
68
227
|
class: tag
|
|
69
228
|
}
|
|
70
|
-
}
|
|
229
|
+
};
|
|
71
230
|
if (!!errorCode) {
|
|
72
231
|
stanza.attrs.error = errorCode.toString();
|
|
73
232
|
}
|
|
@@ -77,141 +236,111 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
77
236
|
if (!!attrs.recipient) {
|
|
78
237
|
stanza.attrs.recipient = attrs.recipient;
|
|
79
238
|
}
|
|
80
|
-
if (!!attrs.type &&
|
|
239
|
+
if (!!attrs.type &&
|
|
240
|
+
(tag !== 'message' || (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable') || errorCode !== 0)) {
|
|
81
241
|
stanza.attrs.type = attrs.type;
|
|
82
242
|
}
|
|
83
243
|
if (tag === 'message' && (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable')) {
|
|
84
244
|
stanza.attrs.from = authState.creds.me.id;
|
|
85
245
|
}
|
|
86
|
-
logger.debug({
|
|
87
|
-
recv: {
|
|
88
|
-
tag,
|
|
89
|
-
attrs
|
|
90
|
-
},
|
|
91
|
-
sent: stanza.attrs }, 'sent ack');
|
|
246
|
+
logger.debug({ recv: { tag, attrs }, sent: stanza.attrs }, 'sent ack');
|
|
92
247
|
await sendNode(stanza);
|
|
93
248
|
};
|
|
94
|
-
const offerCall = async (toJid, isVideo = false) => {
|
|
95
|
-
const callId = (0, crypto_1.randomBytes)(16).toString('hex').toUpperCase().substring(0, 64);
|
|
96
|
-
const offerContent = [];
|
|
97
|
-
offerContent.push({
|
|
98
|
-
tag: 'audio',
|
|
99
|
-
attrs: {
|
|
100
|
-
enc: 'opus',
|
|
101
|
-
rate: '16000'
|
|
102
|
-
}, content: undefined
|
|
103
|
-
});
|
|
104
|
-
offerContent.push({
|
|
105
|
-
tag: 'audio',
|
|
106
|
-
attrs: {
|
|
107
|
-
enc: 'opus',
|
|
108
|
-
rate: '8000'
|
|
109
|
-
}, content: undefined
|
|
110
|
-
});
|
|
111
|
-
if (isVideo) {
|
|
112
|
-
offerContent.push({
|
|
113
|
-
tag: 'video',
|
|
114
|
-
attrs: {
|
|
115
|
-
orientation: '0',
|
|
116
|
-
'screen_width': '1920',
|
|
117
|
-
'screen_height': '1080',
|
|
118
|
-
'device_orientation': '0',
|
|
119
|
-
enc: 'vp8',
|
|
120
|
-
dec: 'vp8',
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
offerContent.push({
|
|
125
|
-
tag: 'net',
|
|
126
|
-
attrs: {
|
|
127
|
-
medium: '3'
|
|
128
|
-
}, content: undefined
|
|
129
|
-
});
|
|
130
|
-
offerContent.push({
|
|
131
|
-
tag: 'capability',
|
|
132
|
-
attrs: {
|
|
133
|
-
ver: '1'
|
|
134
|
-
}, content: new Uint8Array([1, 4, 255, 131, 207, 4]) });
|
|
135
|
-
offerContent.push({
|
|
136
|
-
tag: 'encopt',
|
|
137
|
-
attrs: {
|
|
138
|
-
keygen: '2'
|
|
139
|
-
}, content: undefined
|
|
140
|
-
})
|
|
141
|
-
const encKey = (0, crypto_1.randomBytes)(32);
|
|
142
|
-
const devices = (await getUSyncDevices([toJid], true, false)).map(({ user, device }) => (0, WABinary_1.jidEncode)(user, 's.whatsapp.net', device));
|
|
143
|
-
await assertSessions(devices, true);
|
|
144
|
-
const { nodes: destinations, shouldIncludeDeviceIdentity } = await createParticipantNodes(devices, {
|
|
145
|
-
call: {
|
|
146
|
-
callKey: encKey
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
offerContent.push({ tag: 'destination', attrs: {}, content: destinations });
|
|
150
|
-
if (shouldIncludeDeviceIdentity) {
|
|
151
|
-
offerContent.push({
|
|
152
|
-
tag: 'device-identity',
|
|
153
|
-
attrs: {},
|
|
154
|
-
content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
const stanza = ({
|
|
158
|
-
tag: 'call',
|
|
159
|
-
attrs: {
|
|
160
|
-
to: toJid,
|
|
161
|
-
},
|
|
162
|
-
content: [{
|
|
163
|
-
tag: 'offer',
|
|
164
|
-
attrs: {
|
|
165
|
-
'call-id': callId,
|
|
166
|
-
'call-creator': authState.creds.me.id,
|
|
167
|
-
},
|
|
168
|
-
content: offerContent,
|
|
169
|
-
}],
|
|
170
|
-
});
|
|
171
|
-
await query(stanza);
|
|
172
|
-
return {
|
|
173
|
-
callId,
|
|
174
|
-
toJid,
|
|
175
|
-
isVideo,
|
|
176
|
-
};
|
|
177
|
-
};
|
|
178
249
|
const rejectCall = async (callId, callFrom) => {
|
|
179
|
-
const stanza =
|
|
250
|
+
const stanza = {
|
|
180
251
|
tag: 'call',
|
|
181
252
|
attrs: {
|
|
182
253
|
from: authState.creds.me.id,
|
|
183
|
-
to: callFrom
|
|
254
|
+
to: callFrom
|
|
184
255
|
},
|
|
185
|
-
content: [
|
|
256
|
+
content: [
|
|
257
|
+
{
|
|
186
258
|
tag: 'reject',
|
|
187
259
|
attrs: {
|
|
188
260
|
'call-id': callId,
|
|
189
261
|
'call-creator': callFrom,
|
|
190
|
-
count: '0'
|
|
262
|
+
count: '0'
|
|
191
263
|
},
|
|
192
|
-
content: undefined
|
|
193
|
-
}
|
|
194
|
-
|
|
264
|
+
content: undefined
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
};
|
|
195
268
|
await query(stanza);
|
|
196
269
|
};
|
|
197
270
|
const sendRetryRequest = async (node, forceIncludeKeys = false) => {
|
|
198
271
|
const { fullMessage } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
|
|
199
272
|
const { key: msgKey } = fullMessage;
|
|
200
273
|
const msgId = msgKey.id;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
274
|
+
if (messageRetryManager) {
|
|
275
|
+
// Check if we've exceeded max retries using the new system
|
|
276
|
+
if (messageRetryManager.hasExceededMaxRetries(msgId)) {
|
|
277
|
+
logger.debug({ msgId }, 'reached retry limit with new retry manager, clearing');
|
|
278
|
+
messageRetryManager.markRetryFailed(msgId);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Increment retry count using new system
|
|
282
|
+
const retryCount = messageRetryManager.incrementRetryCount(msgId);
|
|
283
|
+
// Use the new retry count for the rest of the logic
|
|
284
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
285
|
+
msgRetryCache.set(key, retryCount);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
// Fallback to old system
|
|
289
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
290
|
+
let retryCount = (await msgRetryCache.get(key)) || 0;
|
|
291
|
+
if (retryCount >= maxMsgRetryCount) {
|
|
292
|
+
logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
|
|
293
|
+
msgRetryCache.del(key);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
retryCount += 1;
|
|
297
|
+
await msgRetryCache.set(key, retryCount);
|
|
207
298
|
}
|
|
208
|
-
|
|
209
|
-
msgRetryCache.
|
|
299
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
300
|
+
const retryCount = (await msgRetryCache.get(key)) || 1;
|
|
210
301
|
const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
302
|
+
const fromJid = node.attrs.from;
|
|
303
|
+
// Check if we should recreate the session
|
|
304
|
+
let shouldRecreateSession = false;
|
|
305
|
+
let recreateReason = '';
|
|
306
|
+
if (enableAutoSessionRecreation && messageRetryManager) {
|
|
307
|
+
try {
|
|
308
|
+
// Check if we have a session with this JID
|
|
309
|
+
const sessionId = signalRepository.jidToSignalProtocolAddress(fromJid);
|
|
310
|
+
const hasSession = await signalRepository.validateSession(fromJid);
|
|
311
|
+
const result = messageRetryManager.shouldRecreateSession(fromJid, retryCount, hasSession.exists);
|
|
312
|
+
shouldRecreateSession = result.recreate;
|
|
313
|
+
recreateReason = result.reason;
|
|
314
|
+
if (shouldRecreateSession) {
|
|
315
|
+
logger.info({ fromJid, retryCount, reason: recreateReason }, 'recreating session for retry');
|
|
316
|
+
// Delete existing session to force recreation
|
|
317
|
+
await authState.keys.set({ session: { [sessionId]: null } });
|
|
318
|
+
forceIncludeKeys = true;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
logger.warn({ error, fromJid }, 'failed to check session recreation');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (retryCount <= 2) {
|
|
326
|
+
// Use new retry manager for phone requests if available
|
|
327
|
+
if (messageRetryManager) {
|
|
328
|
+
// Schedule phone request with delay (like whatsmeow)
|
|
329
|
+
messageRetryManager.schedulePhoneRequest(msgId, async () => {
|
|
330
|
+
try {
|
|
331
|
+
const msgId = await requestPlaceholderResend(msgKey);
|
|
332
|
+
logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId} (scheduled)`);
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
logger.warn({ error, msgId }, 'failed to send scheduled phone request');
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
// Fallback to immediate request
|
|
341
|
+
const msgId = await requestPlaceholderResend(msgKey);
|
|
342
|
+
logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
|
|
343
|
+
}
|
|
215
344
|
}
|
|
216
345
|
const deviceIdentity = (0, Utils_1.encodeSignedDeviceIdentity)(account, true);
|
|
217
346
|
await authState.keys.transaction(async () => {
|
|
@@ -245,7 +374,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
245
374
|
if (node.attrs.participant) {
|
|
246
375
|
receipt.attrs.participant = node.attrs.participant;
|
|
247
376
|
}
|
|
248
|
-
if (retryCount > 1 || forceIncludeKeys) {
|
|
377
|
+
if (retryCount > 1 || forceIncludeKeys || shouldRecreateSession) {
|
|
249
378
|
const { update, preKeys } = await (0, Utils_1.getNextPreKeys)(authState, 1);
|
|
250
379
|
const [keyId] = Object.keys(preKeys);
|
|
251
380
|
const key = preKeys[+keyId];
|
|
@@ -265,7 +394,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
265
394
|
}
|
|
266
395
|
await sendNode(receipt);
|
|
267
396
|
logger.info({ msgAttrs: node.attrs, retryCount }, 'sent retry receipt');
|
|
268
|
-
});
|
|
397
|
+
}, authState?.creds?.me?.id || 'sendRetryRequest');
|
|
269
398
|
};
|
|
270
399
|
const handleEncryptNotification = async (node) => {
|
|
271
400
|
const from = node.attrs.from;
|
|
@@ -291,29 +420,33 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
291
420
|
}
|
|
292
421
|
};
|
|
293
422
|
const handleGroupNotification = (participant, child, msg) => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
switch (child
|
|
423
|
+
const participantJid = (0, WABinary_1.getBinaryNodeChild)(child, 'participant')?.attrs?.jid || participant;
|
|
424
|
+
// TODO: Add participant LID
|
|
425
|
+
switch (child?.tag) {
|
|
297
426
|
case 'create':
|
|
298
427
|
const metadata = (0, groups_1.extractGroupMetadata)(child);
|
|
299
428
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CREATE;
|
|
300
429
|
msg.messageStubParameters = [metadata.subject];
|
|
301
430
|
msg.key = { participant: metadata.owner };
|
|
302
|
-
ev.emit('chats.upsert', [
|
|
431
|
+
ev.emit('chats.upsert', [
|
|
432
|
+
{
|
|
303
433
|
id: metadata.id,
|
|
304
434
|
name: metadata.subject,
|
|
305
|
-
conversationTimestamp: metadata.creation
|
|
306
|
-
}
|
|
307
|
-
|
|
435
|
+
conversationTimestamp: metadata.creation
|
|
436
|
+
}
|
|
437
|
+
]);
|
|
438
|
+
ev.emit('groups.upsert', [
|
|
439
|
+
{
|
|
308
440
|
...metadata,
|
|
309
441
|
author: participant
|
|
310
|
-
}
|
|
442
|
+
}
|
|
443
|
+
]);
|
|
311
444
|
break;
|
|
312
445
|
case 'ephemeral':
|
|
313
446
|
case 'not_ephemeral':
|
|
314
447
|
msg.message = {
|
|
315
448
|
protocolMessage: {
|
|
316
|
-
type:
|
|
449
|
+
type: index_js_1.proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
317
450
|
ephemeralExpiration: +(child.attrs.expiration || 0)
|
|
318
451
|
}
|
|
319
452
|
};
|
|
@@ -345,19 +478,19 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
345
478
|
msg.messageStubParameters = [child.attrs.subject];
|
|
346
479
|
break;
|
|
347
480
|
case 'description':
|
|
348
|
-
const description = (
|
|
481
|
+
const description = (0, WABinary_1.getBinaryNodeChild)(child, 'body')?.content?.toString();
|
|
349
482
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
|
|
350
483
|
msg.messageStubParameters = description ? [description] : undefined;
|
|
351
484
|
break;
|
|
352
485
|
case 'announcement':
|
|
353
486
|
case 'not_announcement':
|
|
354
487
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
|
|
355
|
-
msg.messageStubParameters = [
|
|
488
|
+
msg.messageStubParameters = [child.tag === 'announcement' ? 'on' : 'off'];
|
|
356
489
|
break;
|
|
357
490
|
case 'locked':
|
|
358
491
|
case 'unlocked':
|
|
359
492
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_RESTRICT;
|
|
360
|
-
msg.messageStubParameters = [
|
|
493
|
+
msg.messageStubParameters = [child.tag === 'locked' ? 'on' : 'off'];
|
|
361
494
|
break;
|
|
362
495
|
case 'invite':
|
|
363
496
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
|
|
@@ -386,57 +519,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
386
519
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
|
387
520
|
msg.messageStubParameters = [participantJid, isDenied ? 'revoked' : 'rejected'];
|
|
388
521
|
break;
|
|
389
|
-
break;
|
|
390
|
-
default:
|
|
391
|
-
// console.log("BAILEYS-DEBUG:", JSON.stringify({ ...child, content: Buffer.isBuffer(child.content) ? child.content.toString() : child.content, participant }, null, 2))
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
const handleNewsletterNotification = (id, node) => {
|
|
395
|
-
const messages = (0, WABinary_1.getBinaryNodeChild)(node, 'messages');
|
|
396
|
-
const message = (0, WABinary_1.getBinaryNodeChild)(messages, 'message');
|
|
397
|
-
const serverId = message.attrs.server_id;
|
|
398
|
-
const reactionsList = (0, WABinary_1.getBinaryNodeChild)(message, 'reactions');
|
|
399
|
-
const viewsList = (0, WABinary_1.getBinaryNodeChildren)(message, 'views_count');
|
|
400
|
-
if (reactionsList) {
|
|
401
|
-
const reactions = (0, WABinary_1.getBinaryNodeChildren)(reactionsList, 'reaction');
|
|
402
|
-
if (reactions.length === 0) {
|
|
403
|
-
ev.emit('newsletter.reaction', { id, 'server_id': serverId, reaction: { removed: true } });
|
|
404
|
-
}
|
|
405
|
-
reactions.forEach(item => {
|
|
406
|
-
var _a, _b;
|
|
407
|
-
ev.emit('newsletter.reaction', { id, 'server_id': serverId, reaction: { code: (_a = item.attrs) === null || _a === void 0 ? void 0 : _a.code, count: +((_b = item.attrs) === null || _b === void 0 ? void 0 : _b.count) } });
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
if (viewsList.length) {
|
|
411
|
-
viewsList.forEach(item => {
|
|
412
|
-
ev.emit('newsletter.view', { id, 'server_id': serverId, count: +item.attrs.count });
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
};
|
|
416
|
-
const handleMexNewsletterNotification = (id, node) => {
|
|
417
|
-
var _a;
|
|
418
|
-
const operation = node === null || node === void 0 ? void 0 : node.attrs.op_name;
|
|
419
|
-
const content = JSON.parse((_a = node === null || node === void 0 ? void 0 : node.content) === null || _a === void 0 ? void 0 : _a.toString());
|
|
420
|
-
let contentPath;
|
|
421
|
-
if (operation === Types_1.MexOperations.PROMOTE || operation === Types_1.MexOperations.DEMOTE) {
|
|
422
|
-
let action;
|
|
423
|
-
if (operation === Types_1.MexOperations.PROMOTE) {
|
|
424
|
-
action = 'promote';
|
|
425
|
-
contentPath = content.data[Types_1.XWAPaths.PROMOTE];
|
|
426
|
-
}
|
|
427
|
-
if (operation === Types_1.MexOperations.DEMOTE) {
|
|
428
|
-
action = 'demote';
|
|
429
|
-
contentPath = content.data[Types_1.XWAPaths.DEMOTE];
|
|
430
|
-
}
|
|
431
|
-
ev.emit('newsletter-participants.update', { id, author: contentPath.actor.pn, user: contentPath.user.pn, new_role: contentPath.user_new_role, action });
|
|
432
|
-
}
|
|
433
|
-
if (operation === Types_1.MexOperations.UPDATE) {
|
|
434
|
-
contentPath = content.data[Types_1.XWAPaths.METADATA_UPDATE];
|
|
435
|
-
ev.emit('newsletter-settings.update', { id, update: contentPath.thread_metadata.settings });
|
|
436
522
|
}
|
|
437
523
|
};
|
|
438
524
|
const processNotification = async (node) => {
|
|
439
|
-
var _a, _b;
|
|
440
525
|
const result = {};
|
|
441
526
|
const [child] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
|
|
442
527
|
const nodeType = node.attrs.type;
|
|
@@ -456,10 +541,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
456
541
|
}
|
|
457
542
|
break;
|
|
458
543
|
case 'newsletter':
|
|
459
|
-
handleNewsletterNotification(node
|
|
544
|
+
await handleNewsletterNotification(node);
|
|
460
545
|
break;
|
|
461
546
|
case 'mex':
|
|
462
|
-
handleMexNewsletterNotification(node
|
|
547
|
+
await handleMexNewsletterNotification(node);
|
|
463
548
|
break;
|
|
464
549
|
case 'w:gp2':
|
|
465
550
|
handleGroupNotification(node.attrs.participant, child, result);
|
|
@@ -473,10 +558,12 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
473
558
|
break;
|
|
474
559
|
case 'devices':
|
|
475
560
|
const devices = (0, WABinary_1.getBinaryNodeChildren)(child, 'device');
|
|
476
|
-
if ((0, WABinary_1.areJidsSameUser)(child.attrs.jid, authState.creds.me.id)
|
|
477
|
-
|
|
478
|
-
|
|
561
|
+
if ((0, WABinary_1.areJidsSameUser)(child.attrs.jid, authState.creds.me.id) ||
|
|
562
|
+
(0, WABinary_1.areJidsSameUser)(child.attrs.lid, authState.creds.me.lid)) {
|
|
563
|
+
const deviceData = devices.map(d => ({ id: d.attrs.jid, lid: d.attrs.lid }));
|
|
564
|
+
logger.info({ deviceData }, 'my own devices changed');
|
|
479
565
|
}
|
|
566
|
+
//TODO: drop a new event, add hashes
|
|
480
567
|
break;
|
|
481
568
|
case 'server_sync':
|
|
482
569
|
const update = (0, WABinary_1.getBinaryNodeChild)(node, 'collection');
|
|
@@ -488,20 +575,22 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
488
575
|
case 'picture':
|
|
489
576
|
const setPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'set');
|
|
490
577
|
const delPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'delete');
|
|
491
|
-
ev.emit('contacts.update', [
|
|
492
|
-
|
|
578
|
+
ev.emit('contacts.update', [
|
|
579
|
+
{
|
|
580
|
+
id: (0, WABinary_1.jidNormalizedUser)(node?.attrs?.from) || (setPicture || delPicture)?.attrs?.hash || '',
|
|
493
581
|
imgUrl: setPicture ? 'changed' : 'removed'
|
|
494
|
-
}
|
|
582
|
+
}
|
|
583
|
+
]);
|
|
495
584
|
if ((0, WABinary_1.isJidGroup)(from)) {
|
|
496
585
|
const node = setPicture || delPicture;
|
|
497
586
|
result.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ICON;
|
|
498
587
|
if (setPicture) {
|
|
499
588
|
result.messageStubParameters = [setPicture.attrs.id];
|
|
500
589
|
}
|
|
501
|
-
result.participant = node
|
|
590
|
+
result.participant = node?.attrs.author;
|
|
502
591
|
result.key = {
|
|
503
|
-
...result.key || {},
|
|
504
|
-
participant: setPicture
|
|
592
|
+
...(result.key || {}),
|
|
593
|
+
participant: setPicture?.attrs.author
|
|
505
594
|
};
|
|
506
595
|
}
|
|
507
596
|
break;
|
|
@@ -515,8 +604,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
515
604
|
...authState.creds.accountSettings,
|
|
516
605
|
defaultDisappearingMode: {
|
|
517
606
|
ephemeralExpiration: newDuration,
|
|
518
|
-
ephemeralSettingTimestamp: timestamp
|
|
519
|
-
}
|
|
607
|
+
ephemeralSettingTimestamp: timestamp
|
|
608
|
+
}
|
|
520
609
|
}
|
|
521
610
|
});
|
|
522
611
|
}
|
|
@@ -524,7 +613,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
524
613
|
const blocklists = (0, WABinary_1.getBinaryNodeChildren)(child, 'item');
|
|
525
614
|
for (const { attrs } of blocklists) {
|
|
526
615
|
const blocklist = [attrs.jid];
|
|
527
|
-
const type =
|
|
616
|
+
const type = attrs.action === 'block' ? 'add' : 'remove';
|
|
528
617
|
ev.emit('blocklist.update', { blocklist, type });
|
|
529
618
|
}
|
|
530
619
|
}
|
|
@@ -542,7 +631,11 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
542
631
|
salt: linkCodeSalt,
|
|
543
632
|
info: 'link_code_pairing_key_bundle_encryption_key'
|
|
544
633
|
});
|
|
545
|
-
const encryptPayload = Buffer.concat([
|
|
634
|
+
const encryptPayload = Buffer.concat([
|
|
635
|
+
Buffer.from(authState.creds.signedIdentityKey.public),
|
|
636
|
+
primaryIdentityPublicKey,
|
|
637
|
+
random
|
|
638
|
+
]);
|
|
546
639
|
const encryptIv = (0, crypto_1.randomBytes)(12);
|
|
547
640
|
const encrypted = (0, Utils_1.aesEncryptGCM)(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0));
|
|
548
641
|
const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]);
|
|
@@ -562,7 +655,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
562
655
|
tag: 'link_code_companion_reg',
|
|
563
656
|
attrs: {
|
|
564
657
|
jid: authState.creds.me.id,
|
|
565
|
-
stage: 'companion_finish'
|
|
658
|
+
stage: 'companion_finish'
|
|
566
659
|
},
|
|
567
660
|
content: [
|
|
568
661
|
{
|
|
@@ -605,33 +698,79 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
605
698
|
}
|
|
606
699
|
return data instanceof Buffer ? data : Buffer.from(data);
|
|
607
700
|
}
|
|
608
|
-
const willSendMessageAgain = (id, participant) => {
|
|
701
|
+
const willSendMessageAgain = async (id, participant) => {
|
|
609
702
|
const key = `${id}:${participant}`;
|
|
610
|
-
const retryCount = msgRetryCache.get(key) || 0;
|
|
703
|
+
const retryCount = (await msgRetryCache.get(key)) || 0;
|
|
611
704
|
return retryCount < maxMsgRetryCount;
|
|
612
705
|
};
|
|
613
|
-
const updateSendMessageAgainCount = (id, participant) => {
|
|
706
|
+
const updateSendMessageAgainCount = async (id, participant) => {
|
|
614
707
|
const key = `${id}:${participant}`;
|
|
615
|
-
const newValue = (msgRetryCache.get(key) || 0) + 1;
|
|
616
|
-
msgRetryCache.set(key, newValue);
|
|
708
|
+
const newValue = ((await msgRetryCache.get(key)) || 0) + 1;
|
|
709
|
+
await msgRetryCache.set(key, newValue);
|
|
617
710
|
};
|
|
618
711
|
const sendMessagesAgain = async (key, ids, retryNode) => {
|
|
619
|
-
var _a;
|
|
620
|
-
// todo: implement a cache to store the last 256 sent messages (copy whatsmeow)
|
|
621
|
-
const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id })));
|
|
622
712
|
const remoteJid = key.remoteJid;
|
|
623
713
|
const participant = key.participant || remoteJid;
|
|
714
|
+
const retryCount = +retryNode.attrs.count || 1;
|
|
715
|
+
// Try to get messages from cache first, then fallback to getMessage
|
|
716
|
+
const msgs = [];
|
|
717
|
+
for (const id of ids) {
|
|
718
|
+
let msg;
|
|
719
|
+
// Try to get from retry cache first if enabled
|
|
720
|
+
if (messageRetryManager) {
|
|
721
|
+
const cachedMsg = messageRetryManager.getRecentMessage(remoteJid, id);
|
|
722
|
+
if (cachedMsg) {
|
|
723
|
+
msg = cachedMsg.message;
|
|
724
|
+
logger.debug({ jid: remoteJid, id }, 'found message in retry cache');
|
|
725
|
+
// Mark retry as successful since we found the message
|
|
726
|
+
messageRetryManager.markRetrySuccess(id);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
// Fallback to getMessage if not found in cache
|
|
730
|
+
if (!msg) {
|
|
731
|
+
msg = await getMessage({ ...key, id });
|
|
732
|
+
if (msg) {
|
|
733
|
+
logger.debug({ jid: remoteJid, id }, 'found message via getMessage');
|
|
734
|
+
// Also mark as successful if found via getMessage
|
|
735
|
+
if (messageRetryManager) {
|
|
736
|
+
messageRetryManager.markRetrySuccess(id);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
msgs.push(msg);
|
|
741
|
+
}
|
|
624
742
|
// if it's the primary jid sending the request
|
|
625
743
|
// just re-send the message to everyone
|
|
626
744
|
// prevents the first message decryption failure
|
|
627
|
-
const sendToAll = !(
|
|
628
|
-
|
|
745
|
+
const sendToAll = !(0, WABinary_1.jidDecode)(participant)?.device;
|
|
746
|
+
// Check if we should recreate session for this retry
|
|
747
|
+
let shouldRecreateSession = false;
|
|
748
|
+
let recreateReason = '';
|
|
749
|
+
if (enableAutoSessionRecreation && messageRetryManager) {
|
|
750
|
+
try {
|
|
751
|
+
const sessionId = signalRepository.jidToSignalProtocolAddress(participant);
|
|
752
|
+
const hasSession = await signalRepository.validateSession(participant);
|
|
753
|
+
const result = messageRetryManager.shouldRecreateSession(participant, retryCount, hasSession.exists);
|
|
754
|
+
shouldRecreateSession = result.recreate;
|
|
755
|
+
recreateReason = result.reason;
|
|
756
|
+
if (shouldRecreateSession) {
|
|
757
|
+
logger.info({ participant, retryCount, reason: recreateReason }, 'recreating session for outgoing retry');
|
|
758
|
+
await authState.keys.set({ session: { [sessionId]: null } });
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
catch (error) {
|
|
762
|
+
logger.warn({ error, participant }, 'failed to check session recreation for outgoing retry');
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
await assertSessions([participant], shouldRecreateSession);
|
|
629
766
|
if ((0, WABinary_1.isJidGroup)(remoteJid)) {
|
|
630
767
|
await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
|
|
631
768
|
}
|
|
632
|
-
logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
|
|
769
|
+
logger.debug({ participant, sendToAll, shouldRecreateSession, recreateReason }, 'forced new session for retry recp');
|
|
633
770
|
for (const [i, msg] of msgs.entries()) {
|
|
634
|
-
if (
|
|
771
|
+
if (!ids[i])
|
|
772
|
+
continue;
|
|
773
|
+
if (msg && (await willSendMessageAgain(ids[i], participant))) {
|
|
635
774
|
updateSendMessageAgainCount(ids[i], participant);
|
|
636
775
|
const msgRelayOpts = { messageId: ids[i] };
|
|
637
776
|
if (sendToAll) {
|
|
@@ -651,10 +790,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
651
790
|
}
|
|
652
791
|
};
|
|
653
792
|
const handleReceipt = async (node) => {
|
|
654
|
-
var _a, _b;
|
|
655
793
|
const { attrs, content } = node;
|
|
656
794
|
const isLid = attrs.from.includes('lid');
|
|
657
|
-
const isNodeFromMe = (0, WABinary_1.areJidsSameUser)(attrs.participant || attrs.from, isLid ?
|
|
795
|
+
const isNodeFromMe = (0, WABinary_1.areJidsSameUser)(attrs.participant || attrs.from, isLid ? authState.creds.me?.lid : authState.creds.me?.id);
|
|
658
796
|
const remoteJid = !isNodeFromMe || (0, WABinary_1.isJidGroup)(attrs.from) ? attrs.from : attrs.recipient;
|
|
659
797
|
const fromMe = !attrs.recipient || ((attrs.type === 'retry' || attrs.type === 'sender') && isNodeFromMe);
|
|
660
798
|
const key = {
|
|
@@ -678,14 +816,12 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
678
816
|
processingMutex.mutex(async () => {
|
|
679
817
|
const status = (0, Utils_1.getStatusFromReceiptType)(attrs.type);
|
|
680
818
|
if (typeof status !== 'undefined' &&
|
|
681
|
-
(
|
|
682
819
|
// basically, we only want to know when a message from us has been delivered to/read by the other person
|
|
683
820
|
// or another device of ours has read some messages
|
|
684
|
-
status >=
|
|
685
|
-
!isNodeFromMe)) {
|
|
821
|
+
(status >= index_js_1.proto.WebMessageInfo.Status.SERVER_ACK || !isNodeFromMe)) {
|
|
686
822
|
if ((0, WABinary_1.isJidGroup)(remoteJid) || (0, WABinary_1.isJidStatusBroadcast)(remoteJid)) {
|
|
687
823
|
if (attrs.participant) {
|
|
688
|
-
const updateKey = status ===
|
|
824
|
+
const updateKey = status === index_js_1.proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
|
|
689
825
|
ev.emit('message-receipt.update', ids.map(id => ({
|
|
690
826
|
key: { ...key, id },
|
|
691
827
|
receipt: {
|
|
@@ -706,14 +842,15 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
706
842
|
// correctly set who is asking for the retry
|
|
707
843
|
key.participant = key.participant || attrs.from;
|
|
708
844
|
const retryNode = (0, WABinary_1.getBinaryNodeChild)(node, 'retry');
|
|
709
|
-
if (willSendMessageAgain(ids[0], key.participant)) {
|
|
845
|
+
if (ids[0] && key.participant && (await willSendMessageAgain(ids[0], key.participant))) {
|
|
710
846
|
if (key.fromMe) {
|
|
711
847
|
try {
|
|
848
|
+
updateSendMessageAgainCount(ids[0], key.participant);
|
|
712
849
|
logger.debug({ attrs, key }, 'recv retry request');
|
|
713
850
|
await sendMessagesAgain(key, ids, retryNode);
|
|
714
851
|
}
|
|
715
852
|
catch (error) {
|
|
716
|
-
logger.error({ key, ids, trace: error.stack }, 'error in sending message again');
|
|
853
|
+
logger.error({ key, ids, trace: error instanceof Error ? error.stack : 'Unknown error' }, 'error in sending message again');
|
|
717
854
|
}
|
|
718
855
|
}
|
|
719
856
|
else {
|
|
@@ -741,7 +878,6 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
741
878
|
try {
|
|
742
879
|
await Promise.all([
|
|
743
880
|
processingMutex.mutex(async () => {
|
|
744
|
-
var _a;
|
|
745
881
|
const msg = await processNotification(node);
|
|
746
882
|
if (msg) {
|
|
747
883
|
const fromMe = (0, WABinary_1.areJidsSameUser)(node.attrs.participant || remoteJid, authState.creds.me.id);
|
|
@@ -752,9 +888,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
752
888
|
id: node.attrs.id,
|
|
753
889
|
...(msg.key || {})
|
|
754
890
|
};
|
|
755
|
-
|
|
891
|
+
msg.participant ?? (msg.participant = node.attrs.participant);
|
|
756
892
|
msg.messageTimestamp = +node.attrs.t;
|
|
757
|
-
const fullMsg =
|
|
893
|
+
const fullMsg = index_js_1.proto.WebMessageInfo.create(msg);
|
|
758
894
|
await upsertMessage(fullMsg, 'append');
|
|
759
895
|
}
|
|
760
896
|
})
|
|
@@ -765,7 +901,6 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
765
901
|
}
|
|
766
902
|
};
|
|
767
903
|
const handleMessage = async (node) => {
|
|
768
|
-
var _a, _b, _c;
|
|
769
904
|
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
|
|
770
905
|
logger.debug({ key: node.attrs.key }, 'ignored message');
|
|
771
906
|
await sendMessageAck(node);
|
|
@@ -775,83 +910,129 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
775
910
|
// TODO: temporary fix for crashes and issues resulting of failed msmsg decryption
|
|
776
911
|
if (encNode && encNode.attrs.type === 'msmsg') {
|
|
777
912
|
logger.debug({ key: node.attrs.key }, 'ignored msmsg');
|
|
778
|
-
await sendMessageAck(node);
|
|
913
|
+
await sendMessageAck(node, Utils_1.NACK_REASONS.MissingMessageSecret);
|
|
779
914
|
return;
|
|
780
915
|
}
|
|
781
916
|
let response;
|
|
782
917
|
if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable') && !encNode) {
|
|
783
918
|
await sendMessageAck(node);
|
|
784
919
|
const { key } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '').fullMessage;
|
|
785
|
-
response = await requestPlaceholderResend(key);
|
|
920
|
+
response = await requestPlaceholderResend(key); // TODO: DEPRECATE THIS LOGIC AND PASS IT OFF TO THE RETRY MANAGER
|
|
786
921
|
if (response === 'RESOLVED') {
|
|
787
922
|
return;
|
|
788
923
|
}
|
|
789
924
|
logger.debug('received unavailable message, acked and requested resend from phone');
|
|
790
925
|
}
|
|
791
926
|
else {
|
|
792
|
-
if (placeholderResendCache.get(node.attrs.id)) {
|
|
793
|
-
placeholderResendCache.del(node.attrs.id);
|
|
927
|
+
if (await placeholderResendCache.get(node.attrs.id)) {
|
|
928
|
+
await placeholderResendCache.del(node.attrs.id);
|
|
794
929
|
}
|
|
795
930
|
}
|
|
796
931
|
const { fullMessage: msg, category, author, decrypt } = (0, Utils_1.decryptMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
|
|
797
|
-
if (response &&
|
|
932
|
+
if (response && msg?.messageStubParameters?.[0] === Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT) {
|
|
798
933
|
msg.messageStubParameters = [Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT, response];
|
|
799
934
|
}
|
|
800
|
-
if (
|
|
801
|
-
|
|
935
|
+
if (msg.message?.protocolMessage?.type === index_js_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER &&
|
|
936
|
+
node.attrs.sender_pn) {
|
|
937
|
+
const lid = (0, WABinary_1.jidNormalizedUser)(node.attrs.from), pn = (0, WABinary_1.jidNormalizedUser)(node.attrs.sender_pn);
|
|
938
|
+
ev.emit('lid-mapping.update', { lid, pn });
|
|
939
|
+
await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
|
|
940
|
+
}
|
|
941
|
+
const alt = msg.key.participantAlt || msg.key.remoteJidAlt;
|
|
942
|
+
// store new mappings we didn't have before
|
|
943
|
+
if (!!alt) {
|
|
944
|
+
const altServer = (0, WABinary_1.jidDecode)(alt)?.server;
|
|
945
|
+
if (altServer === 'lid') {
|
|
946
|
+
if (typeof (await signalRepository.lidMapping.getPNForLID(alt)) === 'string') {
|
|
947
|
+
await signalRepository.lidMapping.storeLIDPNMappings([
|
|
948
|
+
{ lid: alt, pn: msg.key.participant || msg.key.remoteJid }
|
|
949
|
+
]);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
if (typeof (await signalRepository.lidMapping.getLIDForPN(alt)) === 'string') {
|
|
954
|
+
await signalRepository.lidMapping.storeLIDPNMappings([
|
|
955
|
+
{ lid: msg.key.participant || msg.key.remoteJid, pn: alt }
|
|
956
|
+
]);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
if (msg.key?.remoteJid && msg.key?.id && messageRetryManager) {
|
|
961
|
+
messageRetryManager.addRecentMessage(msg.key.remoteJid, msg.key.id, msg.message);
|
|
962
|
+
logger.debug({
|
|
963
|
+
jid: msg.key.remoteJid,
|
|
964
|
+
id: msg.key.id
|
|
965
|
+
}, 'Added message to recent cache for retry receipts');
|
|
802
966
|
}
|
|
803
967
|
try {
|
|
804
968
|
await Promise.all([
|
|
805
969
|
processingMutex.mutex(async () => {
|
|
806
|
-
var _a, _b, _c, _d, _e, _f;
|
|
807
970
|
await decrypt();
|
|
808
971
|
// message failed to decrypt
|
|
809
|
-
if (msg.messageStubType ===
|
|
810
|
-
if (
|
|
972
|
+
if (msg.messageStubType === index_js_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
|
|
973
|
+
if (msg?.messageStubParameters?.[0] === Utils_1.MISSING_KEYS_ERROR_TEXT) {
|
|
811
974
|
return sendMessageAck(node, Utils_1.NACK_REASONS.ParsingError);
|
|
812
975
|
}
|
|
976
|
+
const errorMessage = msg?.messageStubParameters?.[0] || '';
|
|
977
|
+
const isPreKeyError = errorMessage.includes('PreKey');
|
|
978
|
+
logger.debug(`[handleMessage] Attempting retry request for failed decryption`);
|
|
979
|
+
// Handle both pre-key and normal retries in single mutex
|
|
813
980
|
retryMutex.mutex(async () => {
|
|
814
|
-
|
|
981
|
+
try {
|
|
982
|
+
if (!ws.isOpen) {
|
|
983
|
+
logger.debug({ node }, 'Connection closed, skipping retry');
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
815
986
|
if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable')) {
|
|
987
|
+
logger.debug('Message unavailable, skipping retry');
|
|
816
988
|
return;
|
|
817
989
|
}
|
|
990
|
+
// Handle pre-key errors with upload and delay
|
|
991
|
+
if (isPreKeyError) {
|
|
992
|
+
logger.info({ error: errorMessage }, 'PreKey error detected, uploading and retrying');
|
|
993
|
+
try {
|
|
994
|
+
logger.debug('Uploading pre-keys for error recovery');
|
|
995
|
+
await uploadPreKeys(5);
|
|
996
|
+
logger.debug('Waiting for server to process new pre-keys');
|
|
997
|
+
await (0, Utils_1.delay)(1000);
|
|
998
|
+
}
|
|
999
|
+
catch (uploadErr) {
|
|
1000
|
+
logger.error({ uploadErr }, 'Pre-key upload failed, proceeding with retry anyway');
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
818
1003
|
const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
|
|
819
1004
|
await sendRetryRequest(node, !encNode);
|
|
820
1005
|
if (retryRequestDelayMs) {
|
|
821
1006
|
await (0, Utils_1.delay)(retryRequestDelayMs);
|
|
822
1007
|
}
|
|
823
1008
|
}
|
|
824
|
-
|
|
825
|
-
logger.
|
|
1009
|
+
catch (err) {
|
|
1010
|
+
logger.error({ err, isPreKeyError }, 'Failed to handle retry, attempting basic retry');
|
|
1011
|
+
// Still attempt retry even if pre-key upload failed
|
|
1012
|
+
try {
|
|
1013
|
+
const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
|
|
1014
|
+
await sendRetryRequest(node, !encNode);
|
|
1015
|
+
}
|
|
1016
|
+
catch (retryErr) {
|
|
1017
|
+
logger.error({ retryErr }, 'Failed to send retry after error handling');
|
|
1018
|
+
}
|
|
826
1019
|
}
|
|
827
1020
|
});
|
|
828
1021
|
}
|
|
829
1022
|
else {
|
|
830
1023
|
// no type in the receipt => message delivered
|
|
831
1024
|
let type = undefined;
|
|
832
|
-
if ((_b = msg.key.participant) === null || _b === void 0 ? void 0 : _b.endsWith('@lid')) {
|
|
833
|
-
msg.key.participant = node.attrs.participant_pn || authState.creds.me.id;
|
|
834
|
-
}
|
|
835
|
-
if ((0, WABinary_1.isJidGroup)(msg.key.remoteJid) && ((_f = (_e = (_d = (_c = msg.message) === null || _c === void 0 ? void 0 : _c.extendedTextMessage) === null || _d === void 0 ? void 0 : _d.contextInfo) === null || _e === void 0 ? void 0 : _e.participant) === null || _f === void 0 ? void 0 : _f.endsWith('@lid'))) {
|
|
836
|
-
if (msg.message.extendedTextMessage.contextInfo) {
|
|
837
|
-
const metadata = await groupMetadata(msg.key.remoteJid);
|
|
838
|
-
const sender = msg.message.extendedTextMessage.contextInfo.participant;
|
|
839
|
-
const found = metadata.participants.find(p => p.id === sender);
|
|
840
|
-
msg.message.extendedTextMessage.contextInfo.participant = (found === null || found === void 0 ? void 0 : found.jid) || sender;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
if (!(0, WABinary_1.isJidGroup)(msg.key.remoteJid) && (0, WABinary_1.isLidUser)(msg.key.remoteJid)) {
|
|
844
|
-
msg.key.remoteJid = node.attrs.sender_pn || node.attrs.peer_recipient_pn;
|
|
845
|
-
}
|
|
846
1025
|
let participant = msg.key.participant;
|
|
847
|
-
if (category === 'peer') {
|
|
1026
|
+
if (category === 'peer') {
|
|
1027
|
+
// special peer message
|
|
848
1028
|
type = 'peer_msg';
|
|
849
1029
|
}
|
|
850
|
-
else if (msg.key.fromMe) {
|
|
1030
|
+
else if (msg.key.fromMe) {
|
|
1031
|
+
// message was sent by us from a different device
|
|
851
1032
|
type = 'sender';
|
|
852
1033
|
// need to specially handle this case
|
|
853
|
-
if ((0, WABinary_1.
|
|
854
|
-
participant = author;
|
|
1034
|
+
if ((0, WABinary_1.isLidUser)(msg.key.remoteJid) || (0, WABinary_1.isLidUser)(msg.key.remoteJidAlt)) {
|
|
1035
|
+
participant = author; // TODO: investigate sending receipts to LIDs and not PNs
|
|
855
1036
|
}
|
|
856
1037
|
}
|
|
857
1038
|
else if (!sendActiveReceipts) {
|
|
@@ -875,75 +1056,46 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
875
1056
|
logger.error({ error, node }, 'error in handling message');
|
|
876
1057
|
}
|
|
877
1058
|
};
|
|
878
|
-
const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
|
|
879
|
-
var _a;
|
|
880
|
-
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
881
|
-
throw new boom_1.Boom('Not authenticated');
|
|
882
|
-
}
|
|
883
|
-
const pdoMessage = {
|
|
884
|
-
historySyncOnDemandRequest: {
|
|
885
|
-
chatJid: oldestMsgKey.remoteJid,
|
|
886
|
-
oldestMsgFromMe: oldestMsgKey.fromMe,
|
|
887
|
-
oldestMsgId: oldestMsgKey.id,
|
|
888
|
-
oldestMsgTimestampMs: oldestMsgTimestamp,
|
|
889
|
-
onDemandMsgCount: count
|
|
890
|
-
},
|
|
891
|
-
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
|
|
892
|
-
};
|
|
893
|
-
return sendPeerDataOperationMessage(pdoMessage);
|
|
894
|
-
};
|
|
895
|
-
const requestPlaceholderResend = async (messageKey) => {
|
|
896
|
-
var _a;
|
|
897
|
-
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
898
|
-
throw new boom_1.Boom('Not authenticated');
|
|
899
|
-
}
|
|
900
|
-
if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
|
901
|
-
logger.debug({ messageKey }, 'already requested resend');
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
else {
|
|
905
|
-
placeholderResendCache.set(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id, true);
|
|
906
|
-
}
|
|
907
|
-
await (0, Utils_1.delay)(5000);
|
|
908
|
-
if (!placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
|
909
|
-
logger.debug({ messageKey }, 'message received while resend requested');
|
|
910
|
-
return 'RESOLVED';
|
|
911
|
-
}
|
|
912
|
-
const pdoMessage = {
|
|
913
|
-
placeholderMessageResendRequest: [{
|
|
914
|
-
messageKey
|
|
915
|
-
}],
|
|
916
|
-
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
|
|
917
|
-
};
|
|
918
|
-
setTimeout(() => {
|
|
919
|
-
if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
|
920
|
-
logger.debug({ messageKey }, 'PDO message without response after 15 seconds. Phone possibly offline');
|
|
921
|
-
placeholderResendCache.del(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id);
|
|
922
|
-
}
|
|
923
|
-
}, 15000);
|
|
924
|
-
return sendPeerDataOperationMessage(pdoMessage);
|
|
925
|
-
};
|
|
926
1059
|
const handleCall = async (node) => {
|
|
1060
|
+
let status;
|
|
927
1061
|
const { attrs } = node;
|
|
928
1062
|
const [infoChild] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
|
|
1063
|
+
if (!infoChild) {
|
|
1064
|
+
throw new boom_1.Boom('Missing call info in call node');
|
|
1065
|
+
}
|
|
929
1066
|
const callId = infoChild.attrs['call-id'];
|
|
930
1067
|
const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
|
|
931
|
-
|
|
1068
|
+
status = (0, Utils_1.getCallStatusFromNode)(infoChild);
|
|
1069
|
+
if ((0, WABinary_1.isLidUser)(from) && infoChild.tag === 'relaylatency') {
|
|
1070
|
+
const verify = await callOfferCache.get(callId);
|
|
1071
|
+
if (!verify) {
|
|
1072
|
+
status = 'offer';
|
|
1073
|
+
const callLid = {
|
|
1074
|
+
chatId: attrs.from,
|
|
1075
|
+
from,
|
|
1076
|
+
id: callId,
|
|
1077
|
+
date: new Date(+attrs.t * 1000),
|
|
1078
|
+
offline: !!attrs.offline,
|
|
1079
|
+
status
|
|
1080
|
+
};
|
|
1081
|
+
await callOfferCache.set(callId, callLid);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
932
1084
|
const call = {
|
|
933
1085
|
chatId: attrs.from,
|
|
934
1086
|
from,
|
|
935
1087
|
id: callId,
|
|
936
1088
|
date: new Date(+attrs.t * 1000),
|
|
937
1089
|
offline: !!attrs.offline,
|
|
938
|
-
status
|
|
1090
|
+
status
|
|
939
1091
|
};
|
|
940
1092
|
if (status === 'offer') {
|
|
941
1093
|
call.isVideo = !!(0, WABinary_1.getBinaryNodeChild)(infoChild, 'video');
|
|
942
1094
|
call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
|
|
943
1095
|
call.groupJid = infoChild.attrs['group-jid'];
|
|
944
|
-
callOfferCache.set(call.id, call);
|
|
1096
|
+
await callOfferCache.set(call.id, call);
|
|
945
1097
|
}
|
|
946
|
-
const existingCall = callOfferCache.get(call.id);
|
|
1098
|
+
const existingCall = await callOfferCache.get(call.id);
|
|
947
1099
|
// use existing call info to populate this event
|
|
948
1100
|
if (existingCall) {
|
|
949
1101
|
call.isVideo = existingCall.isVideo;
|
|
@@ -951,34 +1103,26 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
951
1103
|
}
|
|
952
1104
|
// delete data once call has ended
|
|
953
1105
|
if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
|
|
954
|
-
callOfferCache.del(call.id);
|
|
1106
|
+
await callOfferCache.del(call.id);
|
|
955
1107
|
}
|
|
956
1108
|
ev.emit('call', [call]);
|
|
957
1109
|
await sendMessageAck(node);
|
|
958
1110
|
};
|
|
959
1111
|
const handleBadAck = async ({ attrs }) => {
|
|
960
|
-
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id
|
|
961
|
-
//
|
|
962
|
-
//
|
|
963
|
-
//
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
if (msg) {
|
|
975
|
-
await relayMessage(key.remoteJid, msg, { messageId: key.id, useUserDevicesCache: false });
|
|
976
|
-
msgRetryCache.set(cacheKey, retryCount + 1);
|
|
977
|
-
}
|
|
978
|
-
else {
|
|
979
|
-
logger.warn({ attrs }, 'could not send message again, as it was not found');
|
|
980
|
-
}
|
|
981
|
-
}
|
|
1112
|
+
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
|
|
1113
|
+
// WARNING: REFRAIN FROM ENABLING THIS FOR NOW. IT WILL CAUSE A LOOP
|
|
1114
|
+
// // current hypothesis is that if pash is sent in the ack
|
|
1115
|
+
// // it means -- the message hasn't reached all devices yet
|
|
1116
|
+
// // we'll retry sending the message here
|
|
1117
|
+
// if(attrs.phash) {
|
|
1118
|
+
// logger.info({ attrs }, 'received phash in ack, resending message...')
|
|
1119
|
+
// const msg = await getMessage(key)
|
|
1120
|
+
// if(msg) {
|
|
1121
|
+
// await relayMessage(key.remoteJid!, msg, { messageId: key.id!, useUserDevicesCache: false })
|
|
1122
|
+
// } else {
|
|
1123
|
+
// logger.warn({ attrs }, 'could not send message again, as it was not found')
|
|
1124
|
+
// }
|
|
1125
|
+
// }
|
|
982
1126
|
// error in acknowledgement,
|
|
983
1127
|
// device could not display the message
|
|
984
1128
|
if (attrs.error) {
|
|
@@ -988,9 +1132,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
988
1132
|
key,
|
|
989
1133
|
update: {
|
|
990
1134
|
status: Types_1.WAMessageStatus.ERROR,
|
|
991
|
-
messageStubParameters: [
|
|
992
|
-
attrs.error
|
|
993
|
-
]
|
|
1135
|
+
messageStubParameters: [attrs.error]
|
|
994
1136
|
}
|
|
995
1137
|
}
|
|
996
1138
|
]);
|
|
@@ -1003,8 +1145,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1003
1145
|
await execTask();
|
|
1004
1146
|
ev.flush();
|
|
1005
1147
|
function execTask() {
|
|
1006
|
-
return exec(node, false)
|
|
1007
|
-
.catch(err => onUnexpectedError(err, identifier));
|
|
1148
|
+
return exec(node, false).catch(err => onUnexpectedError(err, identifier));
|
|
1008
1149
|
}
|
|
1009
1150
|
};
|
|
1010
1151
|
const makeOfflineNodeProcessor = () => {
|
|
@@ -1062,10 +1203,12 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1062
1203
|
processNode('notification', node, 'handling notification', handleNotification);
|
|
1063
1204
|
});
|
|
1064
1205
|
ws.on('CB:ack,class:message', (node) => {
|
|
1065
|
-
handleBadAck(node)
|
|
1066
|
-
.catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1206
|
+
handleBadAck(node).catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1067
1207
|
});
|
|
1068
1208
|
ev.on('call', ([call]) => {
|
|
1209
|
+
if (!call) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1069
1212
|
// missed call + group call notification message generation
|
|
1070
1213
|
if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
|
|
1071
1214
|
const msg = {
|
|
@@ -1074,11 +1217,13 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1074
1217
|
id: call.id,
|
|
1075
1218
|
fromMe: false
|
|
1076
1219
|
},
|
|
1077
|
-
messageTimestamp: (0, Utils_1.unixTimestampSeconds)(call.date)
|
|
1220
|
+
messageTimestamp: (0, Utils_1.unixTimestampSeconds)(call.date)
|
|
1078
1221
|
};
|
|
1079
1222
|
if (call.status === 'timeout') {
|
|
1080
1223
|
if (call.isGroup) {
|
|
1081
|
-
msg.messageStubType = call.isVideo
|
|
1224
|
+
msg.messageStubType = call.isVideo
|
|
1225
|
+
? Types_1.WAMessageStubType.CALL_MISSED_GROUP_VIDEO
|
|
1226
|
+
: Types_1.WAMessageStubType.CALL_MISSED_GROUP_VOICE;
|
|
1082
1227
|
}
|
|
1083
1228
|
else {
|
|
1084
1229
|
msg.messageStubType = call.isVideo ? Types_1.WAMessageStubType.CALL_MISSED_VIDEO : Types_1.WAMessageStubType.CALL_MISSED_VOICE;
|
|
@@ -1087,7 +1232,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1087
1232
|
else {
|
|
1088
1233
|
msg.message = { call: { callKey: Buffer.from(call.id) } };
|
|
1089
1234
|
}
|
|
1090
|
-
const protoMsg =
|
|
1235
|
+
const protoMsg = index_js_1.proto.WebMessageInfo.create(msg);
|
|
1091
1236
|
upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
|
|
1092
1237
|
}
|
|
1093
1238
|
});
|
|
@@ -1102,9 +1247,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1102
1247
|
sendMessageAck,
|
|
1103
1248
|
sendRetryRequest,
|
|
1104
1249
|
rejectCall,
|
|
1105
|
-
offerCall,
|
|
1106
1250
|
fetchMessageHistory,
|
|
1107
1251
|
requestPlaceholderResend,
|
|
1252
|
+
messageRetryManager
|
|
1108
1253
|
};
|
|
1109
1254
|
};
|
|
1110
1255
|
exports.makeMessagesRecvSocket = makeMessagesRecvSocket;
|