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