Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MR414N-ID
GitHub Repository: MR414N-ID/botku2
Path: blob/master/node_modules/@adiwajshing/baileys/lib/LegacySocket/messages.js
1129 views
1
"use strict";
2
var __importDefault = (this && this.__importDefault) || function (mod) {
3
return (mod && mod.__esModule) ? mod : { "default": mod };
4
};
5
Object.defineProperty(exports, "__esModule", { value: true });
6
const WAProto_1 = require("../../WAProto");
7
const Defaults_1 = require("../Defaults");
8
const Types_1 = require("../Types");
9
const Utils_1 = require("../Utils");
10
const WABinary_1 = require("../WABinary");
11
const chats_1 = __importDefault(require("./chats"));
12
const STATUS_MAP = {
13
read: Types_1.WAMessageStatus.READ,
14
message: Types_1.WAMessageStatus.DELIVERY_ACK,
15
error: Types_1.WAMessageStatus.ERROR
16
};
17
const makeMessagesSocket = (config) => {
18
const { logger } = config;
19
const sock = (0, chats_1.default)(config);
20
const { ev, ws: socketEvents, query, generateMessageTag, currentEpoch, setQuery, state } = sock;
21
let mediaConn;
22
const refreshMediaConn = async (forceGet = false) => {
23
const media = await mediaConn;
24
if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
25
mediaConn = (async () => {
26
const { media_conn } = await query({
27
json: ['query', 'mediaConn'],
28
requiresPhoneConnection: false,
29
expect200: true
30
});
31
media_conn.fetchDate = new Date();
32
return media_conn;
33
})();
34
}
35
return mediaConn;
36
};
37
const fetchMessagesFromWA = async (jid, count, cursor) => {
38
let key;
39
if (cursor) {
40
key = 'before' in cursor ? cursor.before : cursor.after;
41
}
42
const { content } = await query({
43
json: {
44
tag: 'query',
45
attrs: {
46
epoch: currentEpoch().toString(),
47
type: 'message',
48
jid: jid,
49
kind: !cursor || 'before' in cursor ? 'before' : 'after',
50
count: count.toString(),
51
index: key === null || key === void 0 ? void 0 : key.id,
52
owner: (key === null || key === void 0 ? void 0 : key.fromMe) === false ? 'false' : 'true',
53
}
54
},
55
binaryTag: [Types_1.WAMetric.queryMessages, Types_1.WAFlag.ignore],
56
expect200: false,
57
requiresPhoneConnection: true
58
});
59
if (Array.isArray(content)) {
60
return content.map(data => WAProto_1.proto.WebMessageInfo.decode(data.content));
61
}
62
return [];
63
};
64
const updateMediaMessage = async (message) => {
65
const content = (0, Utils_1.assertMediaContent)(message.message);
66
const response = await query({
67
json: {
68
tag: 'query',
69
attrs: {
70
type: 'media',
71
index: message.key.id,
72
owner: message.key.fromMe ? 'true' : 'false',
73
jid: message.key.remoteJid,
74
epoch: currentEpoch().toString()
75
}
76
},
77
binaryTag: [Types_1.WAMetric.queryMedia, Types_1.WAFlag.ignore],
78
expect200: true,
79
requiresPhoneConnection: true
80
});
81
const attrs = response.attrs;
82
Object.assign(content, attrs); // update message
83
ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
84
return message;
85
};
86
const onMessage = (message, type) => {
87
var _a, _b, _c, _d;
88
const jid = message.key.remoteJid;
89
// store chat updates in this
90
const chatUpdate = {
91
id: jid,
92
};
93
const emitGroupUpdate = (update) => {
94
ev.emit('groups.update', [{ id: jid, ...update }]);
95
};
96
const normalizedContent = (0, Utils_1.normalizeMessageContent)(message.message);
97
const protocolMessage = normalizedContent === null || normalizedContent === void 0 ? void 0 : normalizedContent.protocolMessage;
98
if (!!normalizedContent
99
&& !(normalizedContent === null || normalizedContent === void 0 ? void 0 : normalizedContent.protocolMessage)
100
&& !(normalizedContent === null || normalizedContent === void 0 ? void 0 : normalizedContent.reactionMessage)) {
101
chatUpdate.conversationTimestamp = +(0, Utils_1.toNumber)(message.messageTimestamp);
102
// add to count if the message isn't from me & there exists a message
103
if (!message.key.fromMe) {
104
chatUpdate.unreadCount = 1;
105
const participant = (0, WABinary_1.jidNormalizedUser)(message.participant || jid);
106
ev.emit('presence.update', {
107
id: jid,
108
presences: { [participant]: { lastKnownPresence: 'available' } }
109
});
110
}
111
}
112
if (normalizedContent === null || normalizedContent === void 0 ? void 0 : normalizedContent.reactionMessage) {
113
const reaction = {
114
...normalizedContent.reactionMessage,
115
key: message.key,
116
};
117
ev.emit('messages.reaction', [{ reaction, key: normalizedContent.reactionMessage.key }]);
118
}
119
// if it's a message to delete another message
120
if (protocolMessage) {
121
switch (protocolMessage.type) {
122
case WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE:
123
const key = protocolMessage.key;
124
const messageStubType = Types_1.WAMessageStubType.REVOKE;
125
ev.emit('messages.update', [
126
{
127
// the key of the deleted message is updated
128
update: { message: null, key: message.key, messageStubType },
129
key: key
130
}
131
]);
132
return;
133
case WAProto_1.proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING:
134
chatUpdate.ephemeralSettingTimestamp = message.messageTimestamp;
135
chatUpdate.ephemeralExpiration = protocolMessage.ephemeralExpiration;
136
if ((0, WABinary_1.isJidGroup)(jid)) {
137
emitGroupUpdate({ ephemeralDuration: protocolMessage.ephemeralExpiration || 0 });
138
}
139
break;
140
default:
141
break;
142
}
143
}
144
// check if the message is an action
145
if (message.messageStubType) {
146
const { user } = state.legacy;
147
//let actor = jidNormalizedUser (message.participant)
148
let participants;
149
const emitParticipantsUpdate = (action) => (ev.emit('group-participants.update', { id: jid, participants, action }));
150
switch (message.messageStubType) {
151
case Types_1.WAMessageStubType.CHANGE_EPHEMERAL_SETTING:
152
chatUpdate.ephemeralSettingTimestamp = message.messageTimestamp;
153
chatUpdate.ephemeralExpiration = +message.messageStubParameters[0];
154
if ((0, WABinary_1.isJidGroup)(jid)) {
155
emitGroupUpdate({ ephemeralDuration: +(((_a = message.messageStubParameters) === null || _a === void 0 ? void 0 : _a[0]) || 0) });
156
}
157
break;
158
case Types_1.WAMessageStubType.GROUP_PARTICIPANT_LEAVE:
159
case Types_1.WAMessageStubType.GROUP_PARTICIPANT_REMOVE:
160
participants = message.messageStubParameters.map(WABinary_1.jidNormalizedUser);
161
emitParticipantsUpdate('remove');
162
// mark the chat read only if you left the group
163
if (participants.includes(user.id)) {
164
chatUpdate.readOnly = true;
165
}
166
break;
167
case Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD:
168
case Types_1.WAMessageStubType.GROUP_PARTICIPANT_INVITE:
169
case Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD_REQUEST_JOIN:
170
participants = message.messageStubParameters.map(WABinary_1.jidNormalizedUser);
171
if (participants.includes(user.id)) {
172
chatUpdate.readOnly = null;
173
}
174
emitParticipantsUpdate('add');
175
break;
176
case Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE:
177
const announce = ((_b = message.messageStubParameters) === null || _b === void 0 ? void 0 : _b[0]) === 'on';
178
emitGroupUpdate({ announce });
179
break;
180
case Types_1.WAMessageStubType.GROUP_CHANGE_RESTRICT:
181
const restrict = ((_c = message.messageStubParameters) === null || _c === void 0 ? void 0 : _c[0]) === 'on';
182
emitGroupUpdate({ restrict });
183
break;
184
case Types_1.WAMessageStubType.GROUP_CHANGE_SUBJECT:
185
case Types_1.WAMessageStubType.GROUP_CREATE:
186
chatUpdate.name = (_d = message.messageStubParameters) === null || _d === void 0 ? void 0 : _d[0];
187
emitGroupUpdate({ subject: chatUpdate.name });
188
break;
189
}
190
}
191
if (Object.keys(chatUpdate).length > 1) {
192
ev.emit('chats.update', [chatUpdate]);
193
}
194
ev.emit('messages.upsert', { messages: [message], type });
195
};
196
const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn);
197
/** Query a string to check if it has a url, if it does, return WAUrlInfo */
198
const generateUrlInfo = async (text) => {
199
const response = await query({
200
json: {
201
tag: 'query',
202
attrs: {
203
type: 'url',
204
url: text,
205
epoch: currentEpoch().toString()
206
}
207
},
208
binaryTag: [26, Types_1.WAFlag.ignore],
209
expect200: true,
210
requiresPhoneConnection: false
211
});
212
const urlInfo = { ...response.attrs };
213
if (response && response.content) {
214
urlInfo.jpegThumbnail = response.content;
215
}
216
return urlInfo;
217
};
218
/** Relay (send) a WAMessage; more advanced functionality to send a built WA Message, you may want to stick with sendMessage() */
219
const relayMessage = async (message, { waitForAck } = { waitForAck: true }) => {
220
var _a, _b;
221
const json = {
222
tag: 'action',
223
attrs: { epoch: currentEpoch().toString(), type: 'relay' },
224
content: [
225
{
226
tag: 'message',
227
attrs: {},
228
content: WAProto_1.proto.WebMessageInfo.encode(message).finish()
229
}
230
]
231
};
232
const isMsgToMe = (0, WABinary_1.areJidsSameUser)(message.key.remoteJid, ((_b = (_a = state.legacy) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.id) || '');
233
const flag = isMsgToMe ? Types_1.WAFlag.acknowledge : Types_1.WAFlag.ignore; // acknowledge when sending message to oneself
234
const mID = message.key.id;
235
const finalState = isMsgToMe ? Types_1.WAMessageStatus.READ : Types_1.WAMessageStatus.SERVER_ACK;
236
message.status = Types_1.WAMessageStatus.PENDING;
237
const promise = query({
238
json,
239
binaryTag: [Types_1.WAMetric.message, flag],
240
tag: mID,
241
expect200: true,
242
requiresPhoneConnection: true
243
});
244
if (waitForAck) {
245
await promise;
246
message.status = finalState;
247
}
248
else {
249
const emitUpdate = (status) => {
250
message.status = status;
251
ev.emit('messages.update', [{ key: message.key, update: { status } }]);
252
};
253
promise
254
.then(() => emitUpdate(finalState))
255
.catch(() => emitUpdate(Types_1.WAMessageStatus.ERROR));
256
}
257
if (config.emitOwnEvents) {
258
onMessage(message, 'append');
259
}
260
};
261
// messages received
262
const messagesUpdate = (node, isLatest) => {
263
const messages = (0, WABinary_1.getBinaryNodeMessages)(node);
264
messages.reverse();
265
ev.emit('messages.set', { messages, isLatest });
266
};
267
socketEvents.on('CB:action,add:last', json => messagesUpdate(json, true));
268
socketEvents.on('CB:action,add:unread', json => messagesUpdate(json, false));
269
socketEvents.on('CB:action,add:before', json => messagesUpdate(json, false));
270
// new messages
271
socketEvents.on('CB:action,add:relay,message', (node) => {
272
const msgs = (0, WABinary_1.getBinaryNodeMessages)(node);
273
for (const msg of msgs) {
274
onMessage(msg, 'notify');
275
}
276
});
277
// If a message has been updated
278
// usually called when a video message gets its upload url, or live locations or ciphertext message gets fixed
279
socketEvents.on('CB:action,add:update,message', (node) => {
280
const msgs = (0, WABinary_1.getBinaryNodeMessages)(node);
281
for (const msg of msgs) {
282
onMessage(msg, 'append');
283
}
284
});
285
// message status updates
286
const onMessageStatusUpdate = ({ content }) => {
287
if (Array.isArray(content)) {
288
const updates = [];
289
for (const { attrs: json } of content) {
290
const key = {
291
remoteJid: (0, WABinary_1.jidNormalizedUser)(json.jid),
292
id: json.index,
293
fromMe: json.owner === 'true'
294
};
295
const status = STATUS_MAP[json.type];
296
if (status) {
297
updates.push({ key, update: { status } });
298
}
299
else {
300
logger.warn({ content, key }, 'got unknown status update for message');
301
}
302
}
303
ev.emit('messages.update', updates);
304
}
305
};
306
const onMessageInfoUpdate = ([, attributes]) => {
307
var _a, _b;
308
let ids = attributes.id;
309
if (typeof ids === 'string') {
310
ids = [ids];
311
}
312
let updateKey;
313
switch (attributes.ack.toString()) {
314
case '2':
315
updateKey = 'receiptTimestamp';
316
break;
317
case '3':
318
updateKey = 'readTimestamp';
319
break;
320
case '4':
321
updateKey = 'playedTimestamp';
322
break;
323
default:
324
logger.warn({ attributes }, 'received unknown message info update');
325
return;
326
}
327
const keyPartial = {
328
remoteJid: (0, WABinary_1.jidNormalizedUser)(attributes.to),
329
fromMe: (0, WABinary_1.areJidsSameUser)(attributes.from, ((_b = (_a = state.legacy) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.id) || ''),
330
};
331
const userJid = (0, WABinary_1.jidNormalizedUser)(attributes.participant || attributes.to);
332
const updates = ids.map(id => ({
333
key: { ...keyPartial, id },
334
receipt: {
335
userJid,
336
[updateKey]: +attributes.t
337
}
338
}));
339
ev.emit('message-receipt.update', updates);
340
// for individual messages
341
// it means the message is marked read/delivered
342
if (!(0, WABinary_1.isJidGroup)(keyPartial.remoteJid)) {
343
ev.emit('messages.update', ids.map(id => ({
344
key: { ...keyPartial, id },
345
update: {
346
status: updateKey === 'receiptTimestamp' ? Types_1.WAMessageStatus.DELIVERY_ACK : Types_1.WAMessageStatus.READ
347
}
348
})));
349
}
350
};
351
socketEvents.on('CB:action,add:relay,received', onMessageStatusUpdate);
352
socketEvents.on('CB:action,,received', onMessageStatusUpdate);
353
socketEvents.on('CB:Msg', onMessageInfoUpdate);
354
socketEvents.on('CB:MsgInfo', onMessageInfoUpdate);
355
return {
356
...sock,
357
relayMessage,
358
waUploadToServer,
359
generateUrlInfo,
360
messageInfo: async (jid, messageID) => {
361
const { content } = await query({
362
json: {
363
tag: 'query',
364
attrs: {
365
type: 'message_info',
366
index: messageID,
367
jid: jid,
368
epoch: currentEpoch().toString()
369
}
370
},
371
binaryTag: [Types_1.WAMetric.queryRead, Types_1.WAFlag.ignore],
372
expect200: true,
373
requiresPhoneConnection: true
374
});
375
const info = {};
376
if (Array.isArray(content)) {
377
for (const { tag, content: innerData } of content) {
378
const [{ attrs }] = innerData;
379
const jid = (0, WABinary_1.jidNormalizedUser)(attrs.jid);
380
const recp = info[jid] || { userJid: jid };
381
const date = +attrs.t;
382
switch (tag) {
383
case 'read':
384
recp.readTimestamp = date;
385
break;
386
case 'delivery':
387
recp.receiptTimestamp = date;
388
break;
389
}
390
info[jid] = recp;
391
}
392
}
393
return Object.values(info);
394
},
395
downloadMediaMessage: async (message, type = 'buffer', options = {}) => {
396
try {
397
const result = await (0, Utils_1.downloadMediaMessage)(message, type, options);
398
return result;
399
}
400
catch (error) {
401
if (error.message.includes('404')) { // media needs to be updated
402
logger.info(`updating media of message: ${message.key.id}`);
403
await updateMediaMessage(message);
404
const result = await (0, Utils_1.downloadMediaMessage)(message, type, options);
405
return result;
406
}
407
throw error;
408
}
409
},
410
updateMediaMessage,
411
fetchMessagesFromWA,
412
/** Load a single message specified by the ID */
413
loadMessageFromWA: async (jid, id) => {
414
// load the message before the given message
415
let messages = (await fetchMessagesFromWA(jid, 1, { before: { id, fromMe: true } }));
416
if (!messages[0]) {
417
messages = (await fetchMessagesFromWA(jid, 1, { before: { id, fromMe: false } }));
418
}
419
// the message after the loaded message is the message required
420
const [actual] = await fetchMessagesFromWA(jid, 1, { after: messages[0] && messages[0].key });
421
return actual;
422
},
423
searchMessages: async (txt, inJid, count, page) => {
424
var _a;
425
const node = await query({
426
json: {
427
tag: 'query',
428
attrs: {
429
epoch: currentEpoch().toString(),
430
type: 'search',
431
search: txt,
432
count: count.toString(),
433
page: page.toString(),
434
jid: inJid
435
}
436
},
437
binaryTag: [24, Types_1.WAFlag.ignore],
438
expect200: true
439
}); // encrypt and send off
440
return {
441
last: ((_a = node.attrs) === null || _a === void 0 ? void 0 : _a.last) === 'true',
442
messages: (0, WABinary_1.getBinaryNodeMessages)(node)
443
};
444
},
445
sendMessage: async (jid, content, options = { waitForAck: true }) => {
446
var _a, _b;
447
const userJid = (_b = (_a = state.legacy) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.id;
448
if (typeof content === 'object' &&
449
'disappearingMessagesInChat' in content &&
450
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
451
(0, WABinary_1.isJidGroup)(jid)) {
452
const { disappearingMessagesInChat } = content;
453
const value = typeof disappearingMessagesInChat === 'boolean' ?
454
(disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
455
disappearingMessagesInChat;
456
const tag = generateMessageTag(true);
457
await setQuery([
458
{
459
tag: 'group',
460
attrs: { id: tag, jid, type: 'prop', author: userJid },
461
content: [
462
{ tag: 'ephemeral', attrs: { value: value.toString() } }
463
]
464
}
465
]);
466
}
467
else {
468
const msg = await (0, Utils_1.generateWAMessage)(jid, content, {
469
logger,
470
userJid: userJid,
471
getUrlInfo: generateUrlInfo,
472
upload: waUploadToServer,
473
mediaCache: config.mediaCache,
474
...options,
475
});
476
await relayMessage(msg, { waitForAck: !!options.waitForAck });
477
return msg;
478
}
479
}
480
};
481
};
482
exports.default = makeMessagesSocket;
483
484