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/chats.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 Types_1 = require("../Types");
7
const Utils_1 = require("../Utils");
8
const generics_1 = require("../Utils/generics");
9
const WABinary_1 = require("../WABinary");
10
const auth_1 = __importDefault(require("./auth"));
11
const makeChatsSocket = (config) => {
12
const { logger } = config;
13
const sock = (0, auth_1.default)(config);
14
const { ev, ws: socketEvents, currentEpoch, setQuery, query, sendNode, state } = sock;
15
const chatsDebounceTimeout = (0, generics_1.debouncedTimeout)(10000, () => sendChatsQuery(1));
16
const sendChatsQuery = (epoch) => (sendNode({
17
json: {
18
tag: 'query',
19
attrs: { type: 'chat', epoch: epoch.toString() }
20
},
21
binaryTag: [Types_1.WAMetric.queryChat, Types_1.WAFlag.ignore]
22
}));
23
const profilePictureUrl = async (jid, timeoutMs) => {
24
const response = await query({
25
json: ['query', 'ProfilePicThumb', jid],
26
expect200: false,
27
requiresPhoneConnection: false,
28
timeoutMs
29
});
30
return response.eurl;
31
};
32
const executeChatModification = (node) => {
33
const { attrs: attributes } = node;
34
const updateType = attributes.type;
35
const jid = (0, WABinary_1.jidNormalizedUser)(attributes === null || attributes === void 0 ? void 0 : attributes.jid);
36
switch (updateType) {
37
case 'delete':
38
ev.emit('chats.delete', [jid]);
39
break;
40
case 'clear':
41
if (node.content) {
42
const ids = node.content.map(({ attrs }) => attrs.index);
43
ev.emit('messages.delete', { keys: ids.map(id => ({ id, remoteJid: jid })) });
44
}
45
else {
46
ev.emit('messages.delete', { jid, all: true });
47
}
48
break;
49
case 'archive':
50
ev.emit('chats.update', [{ id: jid, archive: true }]);
51
break;
52
case 'unarchive':
53
ev.emit('chats.update', [{ id: jid, archive: false }]);
54
break;
55
case 'pin':
56
ev.emit('chats.update', [{ id: jid, pin: attributes.pin ? +attributes.pin : null }]);
57
break;
58
case 'star':
59
case 'unstar':
60
const starred = updateType === 'star';
61
const updates = node.content.map(({ attrs }) => ({
62
key: {
63
remoteJid: jid,
64
id: attrs.index,
65
fromMe: attrs.owner === 'true'
66
},
67
update: { starred }
68
}));
69
ev.emit('messages.update', updates);
70
break;
71
case 'mute':
72
if (attributes.mute === '0') {
73
ev.emit('chats.update', [{ id: jid, mute: null }]);
74
}
75
else {
76
ev.emit('chats.update', [{ id: jid, mute: +attributes.mute }]);
77
}
78
break;
79
default:
80
logger.warn({ node }, 'received unrecognized chat update');
81
break;
82
}
83
};
84
const applyingPresenceUpdate = (update) => {
85
const id = (0, WABinary_1.jidNormalizedUser)(update.id);
86
const participant = (0, WABinary_1.jidNormalizedUser)(update.participant || update.id);
87
const presence = {
88
lastSeen: update.t ? +update.t : undefined,
89
lastKnownPresence: update.type
90
};
91
return { id, presences: { [participant]: presence } };
92
};
93
const chatRead = async (fromMessage, count) => {
94
await setQuery([
95
{
96
tag: 'read',
97
attrs: {
98
jid: fromMessage.remoteJid,
99
count: count.toString(),
100
index: fromMessage.id,
101
owner: fromMessage.fromMe ? 'true' : 'false'
102
}
103
}
104
], [Types_1.WAMetric.read, Types_1.WAFlag.ignore]);
105
if (config.emitOwnEvents) {
106
ev.emit('chats.update', [{ id: fromMessage.remoteJid, unreadCount: count < 0 ? -1 : 0 }]);
107
}
108
};
109
ev.on('connection.update', async ({ connection }) => {
110
if (connection !== 'open') {
111
return;
112
}
113
try {
114
await Promise.all([
115
sendNode({
116
json: { tag: 'query', attrs: { type: 'contacts', epoch: '1' } },
117
binaryTag: [Types_1.WAMetric.queryContact, Types_1.WAFlag.ignore]
118
}),
119
sendNode({
120
json: { tag: 'query', attrs: { type: 'status', epoch: '1' } },
121
binaryTag: [Types_1.WAMetric.queryStatus, Types_1.WAFlag.ignore]
122
}),
123
sendNode({
124
json: { tag: 'query', attrs: { type: 'quick_reply', epoch: '1' } },
125
binaryTag: [Types_1.WAMetric.queryQuickReply, Types_1.WAFlag.ignore]
126
}),
127
sendNode({
128
json: { tag: 'query', attrs: { type: 'label', epoch: '1' } },
129
binaryTag: [Types_1.WAMetric.queryLabel, Types_1.WAFlag.ignore]
130
}),
131
sendNode({
132
json: { tag: 'query', attrs: { type: 'emoji', epoch: '1' } },
133
binaryTag: [Types_1.WAMetric.queryEmoji, Types_1.WAFlag.ignore]
134
}),
135
sendNode({
136
json: {
137
tag: 'action',
138
attrs: { type: 'set', epoch: '1' },
139
content: [
140
{ tag: 'presence', attrs: { type: 'available' } }
141
]
142
},
143
binaryTag: [Types_1.WAMetric.presence, Types_1.WAFlag.available]
144
})
145
]);
146
chatsDebounceTimeout.start();
147
logger.debug('sent init queries');
148
}
149
catch (error) {
150
logger.error(`error in sending init queries: ${error}`);
151
}
152
});
153
socketEvents.on('CB:response,type:chat', async ({ content: data }) => {
154
chatsDebounceTimeout.cancel();
155
if (Array.isArray(data)) {
156
const contacts = [];
157
const chats = data.map(({ attrs }) => {
158
const id = (0, WABinary_1.jidNormalizedUser)(attrs.jid);
159
if (attrs.name) {
160
contacts.push({ id, name: attrs.name });
161
}
162
return {
163
id: (0, WABinary_1.jidNormalizedUser)(attrs.jid),
164
conversationTimestamp: attrs.t ? +attrs.t : undefined,
165
unreadCount: +attrs.count,
166
archive: attrs.archive === 'true' ? true : undefined,
167
pin: attrs.pin ? +attrs.pin : undefined,
168
mute: attrs.mute ? +attrs.mute : undefined,
169
notSpam: !(attrs.spam === 'true'),
170
name: attrs.name,
171
ephemeralExpiration: attrs.ephemeral ? +attrs.ephemeral : undefined,
172
ephemeralSettingTimestamp: attrs.eph_setting_ts ? +attrs.eph_setting_ts : undefined,
173
readOnly: attrs.read_only === 'true' ? true : undefined,
174
};
175
});
176
logger.info(`got ${chats.length} chats, extracted ${contacts.length} contacts with name`);
177
ev.emit('chats.set', { chats, isLatest: true });
178
}
179
});
180
// got all contacts from phone
181
socketEvents.on('CB:response,type:contacts', async ({ content: data }) => {
182
if (Array.isArray(data)) {
183
const contacts = data.map(({ attrs }) => {
184
return {
185
id: (0, WABinary_1.jidNormalizedUser)(attrs.jid),
186
name: attrs.name,
187
notify: attrs.notify,
188
verifiedName: attrs.verify === '2' ? attrs.vname : undefined
189
};
190
});
191
logger.info(`got ${contacts.length} contacts`);
192
ev.emit('contacts.set', { contacts, isLatest: true });
193
}
194
});
195
// status updates
196
socketEvents.on('CB:Status,status', json => {
197
const id = (0, WABinary_1.jidNormalizedUser)(json[1].id);
198
ev.emit('contacts.update', [{ id, status: json[1].status }]);
199
});
200
// User Profile Name Updates
201
socketEvents.on('CB:Conn,pushname', json => {
202
const { legacy, connection } = state;
203
const { user } = legacy;
204
if (connection === 'open' && json[1].pushname !== user.name) {
205
user.name = json[1].pushname;
206
ev.emit('connection.update', { legacy: { ...legacy, user } });
207
}
208
});
209
// read updates
210
socketEvents.on('CB:action,,read', async ({ content }) => {
211
if (Array.isArray(content)) {
212
const { attrs } = content[0];
213
const update = {
214
id: (0, WABinary_1.jidNormalizedUser)(attrs.jid)
215
};
216
if (attrs.type === 'false') {
217
update.unreadCount = -1;
218
}
219
else {
220
update.unreadCount = 0;
221
}
222
ev.emit('chats.update', [update]);
223
}
224
});
225
socketEvents.on('CB:Cmd,type:picture', async (json) => {
226
json = json[1];
227
const id = (0, WABinary_1.jidNormalizedUser)(json.jid);
228
const imgUrl = await profilePictureUrl(id).catch(() => '');
229
ev.emit('contacts.update', [{ id, imgUrl }]);
230
});
231
// chat archive, pin etc.
232
socketEvents.on('CB:action,,chat', ({ content }) => {
233
if (Array.isArray(content)) {
234
const [node] = content;
235
executeChatModification(node);
236
}
237
});
238
socketEvents.on('CB:action,,user', (json) => {
239
if (Array.isArray(json.content)) {
240
const user = json.content[0].attrs;
241
if (user.id) {
242
user.id = (0, WABinary_1.jidNormalizedUser)(user.id);
243
//ev.emit('contacts.upsert', [user])
244
}
245
else {
246
logger.warn({ json }, 'recv unknown action');
247
}
248
}
249
});
250
// presence updates
251
socketEvents.on('CB:Presence', json => {
252
const update = applyingPresenceUpdate(json[1]);
253
ev.emit('presence.update', update);
254
});
255
// blocklist updates
256
socketEvents.on('CB:Blocklist', json => {
257
json = json[1];
258
const blocklist = json.blocklist;
259
ev.emit('blocklist.set', { blocklist });
260
});
261
socketEvents.on('ws-close', () => {
262
chatsDebounceTimeout.cancel();
263
});
264
return {
265
...sock,
266
sendChatsQuery,
267
profilePictureUrl,
268
chatRead,
269
/**
270
* Modify a given chat (archive, pin etc.)
271
* @param jid the ID of the person/group you are modifiying
272
*/
273
chatModify: async (modification, jid, chatInfo, timestampNow) => {
274
const chatAttrs = { jid: jid };
275
let data = undefined;
276
timestampNow = timestampNow || (0, generics_1.unixTimestampSeconds)();
277
const getIndexKey = (list) => {
278
var _a, _b, _c;
279
if (Array.isArray(list)) {
280
return list[list.length - 1].key;
281
}
282
return (_c = (_a = list.messages) === null || _a === void 0 ? void 0 : _a[((_b = list.messages) === null || _b === void 0 ? void 0 : _b.length) - 1]) === null || _c === void 0 ? void 0 : _c.key;
283
};
284
if ('archive' in modification) {
285
chatAttrs.type = modification.archive ? 'archive' : 'unarchive';
286
}
287
else if ('pin' in modification) {
288
chatAttrs.type = 'pin';
289
if (modification.pin) {
290
chatAttrs.pin = timestampNow.toString();
291
}
292
else {
293
chatAttrs.previous = chatInfo.pin.toString();
294
}
295
}
296
else if ('mute' in modification) {
297
chatAttrs.type = 'mute';
298
if (modification.mute) {
299
chatAttrs.mute = (timestampNow + modification.mute).toString();
300
}
301
else {
302
chatAttrs.previous = chatInfo.mute.toString();
303
}
304
}
305
else if ('clear' in modification) {
306
chatAttrs.type = 'clear';
307
chatAttrs.modify_tag = Math.round(Math.random() * 1000000).toString();
308
if (modification.clear !== 'all') {
309
data = modification.clear.messages.map(({ id, fromMe }) => ({
310
tag: 'item',
311
attrs: { owner: (!!fromMe).toString(), index: id }
312
}));
313
}
314
}
315
else if ('star' in modification) {
316
chatAttrs.type = modification.star.star ? 'star' : 'unstar';
317
data = modification.star.messages.map(({ id, fromMe }) => ({
318
tag: 'item',
319
attrs: { owner: (!!fromMe).toString(), index: id }
320
}));
321
}
322
else if ('markRead' in modification) {
323
const indexKey = getIndexKey(modification.lastMessages);
324
return chatRead(indexKey, modification.markRead ? 0 : -1);
325
}
326
else if ('delete' in modification) {
327
chatAttrs.type = 'delete';
328
}
329
if ('lastMessages' in modification) {
330
const indexKey = getIndexKey(modification.lastMessages);
331
if (indexKey) {
332
chatAttrs.index = indexKey.id;
333
chatAttrs.owner = indexKey.fromMe ? 'true' : 'false';
334
}
335
}
336
const node = { tag: 'chat', attrs: chatAttrs, content: data };
337
const response = await setQuery([node], [Types_1.WAMetric.chat, Types_1.WAFlag.ignore]);
338
if (config.emitOwnEvents) {
339
// apply it and emit events
340
executeChatModification(node);
341
}
342
return response;
343
},
344
/**
345
* Query whether a given number is registered on WhatsApp
346
* @param str phone number/jid you want to check for
347
* @returns undefined if the number doesn't exists, otherwise the correctly formatted jid
348
*/
349
onWhatsApp: async (str) => {
350
const { status, jid, biz } = await query({
351
json: ['query', 'exist', str],
352
requiresPhoneConnection: false
353
});
354
if (status === 200) {
355
return {
356
exists: true,
357
jid: (0, WABinary_1.jidNormalizedUser)(jid),
358
isBusiness: biz
359
};
360
}
361
},
362
/**
363
* Tell someone about your presence -- online, typing, offline etc.
364
* @param jid the ID of the person/group who you are updating
365
* @param type your presence
366
*/
367
sendPresenceUpdate: (type, toJid) => (sendNode({
368
binaryTag: [Types_1.WAMetric.presence, Types_1.WAFlag[type]],
369
json: {
370
tag: 'action',
371
attrs: { epoch: currentEpoch().toString(), type: 'set' },
372
content: [
373
{
374
tag: 'presence',
375
attrs: { type: type, to: toJid }
376
}
377
]
378
}
379
})),
380
/**
381
* Request updates on the presence of a user
382
* this returns nothing, you'll receive updates in chats.update event
383
* */
384
presenceSubscribe: async (jid) => (sendNode({ json: ['action', 'presence', 'subscribe', jid] })),
385
/** Query the status of the person (see groupMetadata() for groups) */
386
getStatus: async (jid) => {
387
const status = await query({ json: ['query', 'Status', jid], requiresPhoneConnection: false });
388
return status;
389
},
390
setStatus: async (status) => {
391
const response = await setQuery([
392
{
393
tag: 'status',
394
attrs: {},
395
content: Buffer.from(status, 'utf-8')
396
}
397
]);
398
ev.emit('contacts.update', [{ id: state.legacy.user.id, status }]);
399
return response;
400
},
401
/** Updates business profile. */
402
updateBusinessProfile: async (profile) => {
403
var _a;
404
if ((_a = profile.business_hours) === null || _a === void 0 ? void 0 : _a.config) {
405
profile.business_hours.business_config = profile.business_hours.config;
406
delete profile.business_hours.config;
407
}
408
const json = ['action', 'editBusinessProfile', { ...profile, v: 2 }];
409
await query({ json, expect200: true, requiresPhoneConnection: true });
410
},
411
updateProfileName: async (name) => {
412
const response = (await setQuery([
413
{
414
tag: 'profile',
415
attrs: { name }
416
}
417
]));
418
if (config.emitOwnEvents) {
419
const user = { ...state.legacy.user, name };
420
ev.emit('connection.update', { legacy: {
421
...state.legacy, user
422
} });
423
ev.emit('contacts.update', [{ id: user.id, name }]);
424
}
425
return response;
426
},
427
/**
428
* Update the profile picture
429
* @param jid
430
* @param img
431
*/
432
async updateProfilePicture(jid, imgBuffer) {
433
var _a;
434
jid = (0, WABinary_1.jidNormalizedUser)(jid);
435
const { img } = await (0, Utils_1.generateProfilePicture)(imgBuffer);
436
const tag = this.generateMessageTag();
437
const query = {
438
tag: 'picture',
439
attrs: { jid: jid, id: tag, type: 'set' },
440
content: [
441
{ tag: 'image', attrs: {}, content: img },
442
{ tag: 'preview', attrs: {}, content: img }
443
]
444
};
445
const user = (_a = state.legacy) === null || _a === void 0 ? void 0 : _a.user;
446
const { eurl } = await this.setQuery([query], [Types_1.WAMetric.picture, 136], tag);
447
if (config.emitOwnEvents) {
448
if (jid === (user === null || user === void 0 ? void 0 : user.id)) {
449
user.imgUrl = eurl;
450
ev.emit('connection.update', {
451
legacy: {
452
...state.legacy,
453
user
454
}
455
});
456
}
457
ev.emit('contacts.update', [{ id: jid, imgUrl: eurl }]);
458
}
459
},
460
/**
461
* Add or remove user from blocklist
462
* @param jid the ID of the person who you are blocking/unblocking
463
* @param type type of operation
464
*/
465
blockUser: async (jid, type = 'add') => {
466
const json = {
467
tag: 'block',
468
attrs: { type },
469
content: [{ tag: 'user', attrs: { jid } }]
470
};
471
await setQuery([json], [Types_1.WAMetric.block, Types_1.WAFlag.ignore]);
472
if (config.emitOwnEvents) {
473
ev.emit('blocklist.update', { blocklist: [jid], type });
474
}
475
},
476
/**
477
* Query Business Profile (Useful for VCards)
478
* @param jid Business Jid
479
* @returns profile object or undefined if not business account
480
*/
481
getBusinessProfile: async (jid) => {
482
jid = (0, WABinary_1.jidNormalizedUser)(jid);
483
const { profiles: [{ profile, wid }] } = await query({
484
json: [
485
'query', 'businessProfile',
486
[{ 'wid': jid.replace('@s.whatsapp.net', '@c.us') }],
487
84
488
],
489
expect200: true,
490
requiresPhoneConnection: false,
491
});
492
return {
493
...profile,
494
wid: (0, WABinary_1.jidNormalizedUser)(wid)
495
};
496
}
497
};
498
};
499
exports.default = makeChatsSocket;
500
501