@codexverified/baileys 2.7.5

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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -0
  3. package/WAProto/V +1 -0
  4. package/WAProto/WAProto.proto +8051 -0
  5. package/WAProto/index.js +289292 -0
  6. package/engine-requirements.js +13 -0
  7. package/lib/Defaults/index.js +158 -0
  8. package/lib/Signal/Group/ciphertext-message.js +11 -0
  9. package/lib/Signal/Group/group-session-builder.js +29 -0
  10. package/lib/Signal/Group/group_cipher.js +81 -0
  11. package/lib/Signal/Group/index.js +11 -0
  12. package/lib/Signal/Group/keyhelper.js +17 -0
  13. package/lib/Signal/Group/sender-chain-key.js +25 -0
  14. package/lib/Signal/Group/sender-key-distribution-message.js +62 -0
  15. package/lib/Signal/Group/sender-key-message.js +65 -0
  16. package/lib/Signal/Group/sender-key-name.js +47 -0
  17. package/lib/Signal/Group/sender-key-record.js +40 -0
  18. package/lib/Signal/Group/sender-key-state.js +83 -0
  19. package/lib/Signal/Group/sender-message-key.js +25 -0
  20. package/lib/Signal/libsignal.js +428 -0
  21. package/lib/Signal/lid-mapping.js +280 -0
  22. package/lib/Socket/Client/index.js +2 -0
  23. package/lib/Socket/Client/types.js +10 -0
  24. package/lib/Socket/Client/websocket.js +53 -0
  25. package/lib/Socket/aigroups.js +315 -0
  26. package/lib/Socket/business.js +407 -0
  27. package/lib/Socket/chats.js +1831 -0
  28. package/lib/Socket/communities.js +431 -0
  29. package/lib/Socket/graphql.js +899 -0
  30. package/lib/Socket/groups.js +549 -0
  31. package/lib/Socket/index.js +79 -0
  32. package/lib/Socket/interactive-handler.js +600 -0
  33. package/lib/Socket/interop.js +563 -0
  34. package/lib/Socket/managed-account.js +208 -0
  35. package/lib/Socket/messages-recv.js +2144 -0
  36. package/lib/Socket/messages-send.js +2030 -0
  37. package/lib/Socket/mex.js +41 -0
  38. package/lib/Socket/newsletter.js +226 -0
  39. package/lib/Socket/privacy.js +446 -0
  40. package/lib/Socket/registration.js +428 -0
  41. package/lib/Socket/socket.js +1017 -0
  42. package/lib/Socket/username.js +229 -0
  43. package/lib/Store/index.js +4 -0
  44. package/lib/Store/make-cache-manager-store.js +89 -0
  45. package/lib/Store/make-in-memory-store.js +420 -0
  46. package/lib/Store/make-ordered-dictionary.js +78 -0
  47. package/lib/Store/object-repository.js +23 -0
  48. package/lib/Types/Auth.js +1 -0
  49. package/lib/Types/Bussines.js +1 -0
  50. package/lib/Types/Call.js +1 -0
  51. package/lib/Types/Chat.js +7 -0
  52. package/lib/Types/Contact.js +1 -0
  53. package/lib/Types/Events.js +1 -0
  54. package/lib/Types/GroupMetadata.js +1 -0
  55. package/lib/Types/Label.js +24 -0
  56. package/lib/Types/LabelAssociation.js +6 -0
  57. package/lib/Types/Message.js +17 -0
  58. package/lib/Types/Mex.js +39 -0
  59. package/lib/Types/Product.js +1 -0
  60. package/lib/Types/RichType.js +22 -0
  61. package/lib/Types/Signal.js +1 -0
  62. package/lib/Types/Socket.js +2 -0
  63. package/lib/Types/State.js +48 -0
  64. package/lib/Types/USync.js +1 -0
  65. package/lib/Types/index.js +25 -0
  66. package/lib/Utils/auth-utils.js +301 -0
  67. package/lib/Utils/bot-planning-replay.js +169 -0
  68. package/lib/Utils/browser-utils.js +28 -0
  69. package/lib/Utils/business.js +230 -0
  70. package/lib/Utils/chat-utils.js +885 -0
  71. package/lib/Utils/companion-reg-client-utils.js +32 -0
  72. package/lib/Utils/consumer-application.js +102 -0
  73. package/lib/Utils/crypto.js +117 -0
  74. package/lib/Utils/decode-wa-message.js +484 -0
  75. package/lib/Utils/event-buffer.js +589 -0
  76. package/lib/Utils/generics.js +388 -0
  77. package/lib/Utils/group-history.js +56 -0
  78. package/lib/Utils/history.js +130 -0
  79. package/lib/Utils/identity-change-handler.js +48 -0
  80. package/lib/Utils/index.js +34 -0
  81. package/lib/Utils/jid-display-normalization.js +209 -0
  82. package/lib/Utils/link-preview.js +84 -0
  83. package/lib/Utils/logger.js +2 -0
  84. package/lib/Utils/lt-hash.js +7 -0
  85. package/lib/Utils/make-mutex.js +32 -0
  86. package/lib/Utils/message-composer.js +467 -0
  87. package/lib/Utils/message-inspect.js +67 -0
  88. package/lib/Utils/message-retry-manager.js +241 -0
  89. package/lib/Utils/messages-media.js +1006 -0
  90. package/lib/Utils/messages.js +1851 -0
  91. package/lib/Utils/meta-ai-msmsg.js +130 -0
  92. package/lib/Utils/meta-compositing.js +194 -0
  93. package/lib/Utils/noise-handler.js +200 -0
  94. package/lib/Utils/offline-node-processor.js +39 -0
  95. package/lib/Utils/pre-key-manager.js +105 -0
  96. package/lib/Utils/process-message.js +527 -0
  97. package/lib/Utils/reporting-utils.js +257 -0
  98. package/lib/Utils/rich-message-utils.js +439 -0
  99. package/lib/Utils/signal.js +200 -0
  100. package/lib/Utils/stanza-ack.js +37 -0
  101. package/lib/Utils/sync-action-utils.js +47 -0
  102. package/lib/Utils/tc-token-utils.js +162 -0
  103. package/lib/Utils/use-multi-file-auth-state.js +120 -0
  104. package/lib/Utils/use-single-file-auth-state.js +96 -0
  105. package/lib/Utils/use-sqlite-auth-state.js +108 -0
  106. package/lib/Utils/validate-connection.js +206 -0
  107. package/lib/Utils/voip-rekey.js +20 -0
  108. package/lib/Utils/welcome-flow.js +217 -0
  109. package/lib/WABinary/constants.js +1463 -0
  110. package/lib/WABinary/decode.js +261 -0
  111. package/lib/WABinary/encode.js +219 -0
  112. package/lib/WABinary/generic-utils.js +227 -0
  113. package/lib/WABinary/index.js +5 -0
  114. package/lib/WABinary/jid-utils.js +95 -0
  115. package/lib/WABinary/types.js +1 -0
  116. package/lib/WAM/BinaryInfo.js +9 -0
  117. package/lib/WAM/constants.js +22852 -0
  118. package/lib/WAM/encode.js +149 -0
  119. package/lib/WAM/index.js +3 -0
  120. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +96 -0
  121. package/lib/WAUSync/Protocols/USyncContactProtocol.js +56 -0
  122. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +53 -0
  123. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
  124. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +70 -0
  125. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +28 -0
  126. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +25 -0
  127. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
  128. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +34 -0
  129. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +24 -0
  130. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
  131. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
  132. package/lib/WAUSync/Protocols/index.js +12 -0
  133. package/lib/WAUSync/USyncQuery.js +201 -0
  134. package/lib/WAUSync/USyncUser.js +54 -0
  135. package/lib/WAUSync/index.js +3 -0
  136. package/lib/antiban.cjs +4726 -0
  137. package/lib/index.d.ts +286 -0
  138. package/lib/index.js +18 -0
  139. package/package.json +121 -0
@@ -0,0 +1,549 @@
1
+ import { Boom } from '@hapi/boom';
2
+ import { proto } from '../../WAProto/index.js';
3
+ import { WAMessageAddressingMode, WAMessageStubType } from '../Types/index.js';
4
+ import { generateMessageIDV2, unixTimestampSeconds } from '../Utils/index.js';
5
+ import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString, isJidGroup, isLidUser, isPnUser, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
6
+ import { makeChatsSocket } from './chats.js';
7
+
8
+ export const buildReportNode = (jid, messageKeys = []) => ({
9
+ tag: 'spam_list',
10
+ attrs: {},
11
+ content: [{
12
+ tag: 'spam',
13
+ attrs: { jid },
14
+ content: messageKeys.map(key => {
15
+ if (!key?.id) {
16
+ throw new Boom('Every reported message key must include an id', { statusCode: 400 });
17
+ }
18
+ return {
19
+ tag: 'message',
20
+ attrs: {
21
+ id: key.id,
22
+ ...(key.fromMe !== undefined ? { from_me: key.fromMe ? 'true' : 'false' } : {}),
23
+ ...(key.participant ? { participant: jidNormalizedUser(key.participant) } : {})
24
+ }
25
+ };
26
+ })
27
+ }]
28
+ });
29
+
30
+ export const buildGroupStatusRevokeMessage = (jid, key) => ({
31
+ groupStatusMessageV2: {
32
+ message: {
33
+ protocolMessage: {
34
+ key: {
35
+ remoteJid: jid,
36
+ fromMe: key.fromMe ?? true,
37
+ id: key.id,
38
+ ...(key.participant ? { participant: jidNormalizedUser(key.participant) } : {})
39
+ },
40
+ type: proto.Message.ProtocolMessage.Type.REVOKE
41
+ }
42
+ }
43
+ }
44
+ });
45
+
46
+ export const makeGroupsSocket = (config) => {
47
+ const sock = makeChatsSocket(config);
48
+ const { authState, ev, query, relayMessage, updateBlockStatus, upsertMessage } = sock;
49
+ const reportJid = async (jid, messageKeys = []) => query({
50
+ tag: 'iq',
51
+ attrs: { type: 'set', xmlns: 'spam', to: S_WHATSAPP_NET },
52
+ content: [buildReportNode(jid, messageKeys)]
53
+ });
54
+ const groupQuery = async (jid, type, content) => query({
55
+ tag: 'iq',
56
+ attrs: {
57
+ type,
58
+ xmlns: 'w:g2',
59
+ to: jid
60
+ },
61
+ content
62
+ });
63
+ const persistParticipantLidMappings = async (participantLists) => {
64
+ const pairs = [];
65
+ for (const participants of participantLists) {
66
+ for (const p of participants || []) {
67
+ if (p.phoneNumber)
68
+ pairs.push({ lid: p.id, pn: p.phoneNumber });
69
+ else if (p.lid)
70
+ pairs.push({ lid: p.lid, pn: p.id });
71
+ }
72
+ }
73
+ if (!pairs.length)
74
+ return;
75
+ try {
76
+ await sock.signalRepository.lidMapping.storeLIDPNMappings(pairs);
77
+ }
78
+ catch (error) {
79
+ sock.logger?.warn?.({ error }, 'failed to store LID/PN mappings from group metadata');
80
+ }
81
+ };
82
+ const groupMetadata = async (jid) => {
83
+ const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }]);
84
+ const metadata = extractGroupMetadata(result);
85
+ persistParticipantLidMappings([metadata.participants]).catch(() => { });
86
+ return metadata;
87
+ };
88
+ /**
89
+ * Acknowledge a group. Ported from WhatsApp Web's WASmaxGroupsAcknowledgeGroupRPC
90
+ * (`<iq to=jid xmlns=w:g2 type=set><ack/></iq>`).
91
+ */
92
+ const groupAcknowledge = async (jid) => {
93
+ await groupQuery(jid, 'set', [{ tag: 'ack', attrs: {} }]);
94
+ };
95
+ /**
96
+ * Get the participants of a community's linked/sub groups. Ported from
97
+ * WhatsApp Web's WASmaxGroupsGetLinkedGroupsParticipantsRPC.
98
+ * @returns {Promise<Array<{ jid: string, phoneNumber?: string }>>}
99
+ */
100
+ const groupGetLinkedParticipants = async (jid) => {
101
+ const result = await groupQuery(jid, 'get', [{ tag: 'linked_groups_participants', attrs: {} }]);
102
+ const node = getBinaryNodeChild(result, 'linked_groups_participants');
103
+ return getBinaryNodeChildren(node, 'participant').map(p => ({
104
+ jid: p.attrs.jid,
105
+ phoneNumber: p.attrs.phone_number || p.attrs.pn || undefined
106
+ }));
107
+ };
108
+ /**
109
+ * Join a community's linked/sub group (may raise a membership approval request).
110
+ * Ported from WhatsApp Web's WASmaxGroupsJoinLinkedGroupRPC.
111
+ * @param {string} parentJid community/parent group to address
112
+ * @param {string} linkedGroupJid linked/sub group to join
113
+ * @param {string} [type]
114
+ */
115
+ const groupJoinLinked = async (parentJid, linkedGroupJid, type) => {
116
+ const result = await groupQuery(parentJid, 'set', [
117
+ { tag: 'join_linked_group', attrs: { jid: linkedGroupJid, ...(type ? { type } : {}) } }
118
+ ]);
119
+ return { approvalRequested: !!getBinaryNodeChild(result, 'membership_approval_request') };
120
+ };
121
+ /**
122
+ * Batch-fetch group profile pictures via w:g2. Ported from WhatsApp Web's
123
+ * WASmaxGroupsGetGroupProfilePicturesRPC.
124
+ * @param {string[]} jids group jids
125
+ * @param {'preview' | 'image'} [type]
126
+ */
127
+ const getGroupProfilePictures = async (jids, type = 'preview') => {
128
+ const result = await groupQuery(S_WHATSAPP_NET, 'get', [
129
+ {
130
+ tag: 'pictures',
131
+ attrs: {},
132
+ content: jids.map(id => ({ tag: 'picture', attrs: { id, type } }))
133
+ }
134
+ ]);
135
+ return getBinaryNodeChildren(result, 'picture').map(pic => ({
136
+ jid: pic.attrs.id || pic.attrs.jid,
137
+ type: pic.attrs.type,
138
+ directPath: pic.attrs['direct_path'],
139
+ url: pic.attrs.url
140
+ }));
141
+ };
142
+ /**
143
+ * Create a sub-group suggestion for a community. Ported from WhatsApp Web's
144
+ * WASmaxGroupsCreateSubGroupSuggestionRPC. The suggestion body (new vs existing
145
+ * groups) is caller-provided.
146
+ * @param {string} parentJid community/parent group to address
147
+ * @param {Array<{ tag: string, attrs?: object, content?: any }>} suggestion child node(s)
148
+ */
149
+ const groupCreateSubGroupSuggestion = async (parentJid, suggestion) => {
150
+ await groupQuery(parentJid, 'set', [{ tag: 'sub_group_suggestion', attrs: {}, content: suggestion }]);
151
+ };
152
+ /**
153
+ * Approve, reject, or cancel sub-group suggestions for a community. Ported from
154
+ * WhatsApp Web's WASmaxGroupsSubGroupSuggestionsActionRPC.
155
+ * approve/reject address suggestions by creator jid; cancel addresses them by
156
+ * the suggested group's jid.
157
+ * @param {string} parentJid community/parent group to address
158
+ * @param {'approve' | 'reject' | 'cancel'} action
159
+ * @param {Array<{ creator?: string, jid?: string }>} suggestions
160
+ */
161
+ const groupSubGroupSuggestionsAction = async (parentJid, action, suggestions) => {
162
+ await groupQuery(parentJid, 'set', [
163
+ {
164
+ tag: 'sub_group_suggestions_action',
165
+ attrs: {},
166
+ content: [
167
+ {
168
+ tag: action,
169
+ attrs: {},
170
+ content: suggestions.map(s => ({
171
+ tag: 'sub_group_suggestion',
172
+ attrs: action === 'cancel' ? { jid: s.jid } : { creator: s.creator }
173
+ }))
174
+ }
175
+ ]
176
+ }
177
+ ]);
178
+ };
179
+ const groupFetchAllParticipating = async () => {
180
+ const result = await query({
181
+ tag: 'iq',
182
+ attrs: {
183
+ to: '@g.us',
184
+ xmlns: 'w:g2',
185
+ type: 'get'
186
+ },
187
+ content: [
188
+ {
189
+ tag: 'participating',
190
+ attrs: {},
191
+ content: [
192
+ { tag: 'participants', attrs: {} },
193
+ { tag: 'description', attrs: {} }
194
+ ]
195
+ }
196
+ ]
197
+ });
198
+ const data = {};
199
+ const groupsChild = getBinaryNodeChild(result, 'groups');
200
+ if (groupsChild) {
201
+ const groups = getBinaryNodeChildren(groupsChild, 'group');
202
+ for (const groupNode of groups) {
203
+ const meta = extractGroupMetadata({
204
+ tag: 'result',
205
+ attrs: {},
206
+ content: [groupNode]
207
+ });
208
+ data[meta.id] = meta;
209
+ }
210
+ }
211
+ // TODO: properly parse LID / PN DATA
212
+ sock.ev.emit('groups.update', Object.values(data));
213
+ return data;
214
+ };
215
+ sock.ws.on('CB:ib,,dirty', async (node) => {
216
+ const { attrs } = getBinaryNodeChild(node, 'dirty');
217
+ if (attrs.type !== 'groups') {
218
+ return;
219
+ }
220
+ await groupFetchAllParticipating();
221
+ await sock.cleanDirtyBits('groups');
222
+ });
223
+ return {
224
+ ...sock,
225
+ groupQuery,
226
+ groupMetadata,
227
+ groupAcknowledge,
228
+ groupGetLinkedParticipants,
229
+ groupJoinLinked,
230
+ getGroupProfilePictures,
231
+ groupCreateSubGroupSuggestion,
232
+ groupSubGroupSuggestionsAction,
233
+ groupCreate: async (subject, participants) => {
234
+ const key = generateMessageIDV2();
235
+ const result = await groupQuery('@g.us', 'set', [
236
+ {
237
+ tag: 'create',
238
+ attrs: {
239
+ subject,
240
+ key
241
+ },
242
+ content: participants.map(jid => ({
243
+ tag: 'participant',
244
+ attrs: { jid }
245
+ }))
246
+ }
247
+ ]);
248
+ return extractGroupMetadata(result);
249
+ },
250
+ groupLeave: async (id) => {
251
+ await groupQuery('@g.us', 'set', [
252
+ {
253
+ tag: 'leave',
254
+ attrs: {},
255
+ content: [{ tag: 'group', attrs: { id } }]
256
+ }
257
+ ]);
258
+ },
259
+ groupUpdateSubject: async (jid, subject) => {
260
+ await groupQuery(jid, 'set', [
261
+ {
262
+ tag: 'subject',
263
+ attrs: {},
264
+ content: Buffer.from(subject, 'utf-8')
265
+ }
266
+ ]);
267
+ },
268
+ groupRequestParticipantsList: async (jid) => {
269
+ const result = await groupQuery(jid, 'get', [
270
+ {
271
+ tag: 'membership_approval_requests',
272
+ attrs: {}
273
+ }
274
+ ]);
275
+ const node = getBinaryNodeChild(result, 'membership_approval_requests');
276
+ const participants = getBinaryNodeChildren(node, 'membership_approval_request');
277
+ return participants.map(v => v.attrs);
278
+ },
279
+ groupRequestParticipantsUpdate: async (jid, participants, action) => {
280
+ const result = await groupQuery(jid, 'set', [
281
+ {
282
+ tag: 'membership_requests_action',
283
+ attrs: {},
284
+ content: [
285
+ {
286
+ tag: action,
287
+ attrs: {},
288
+ content: participants.map(jid => ({
289
+ tag: 'participant',
290
+ attrs: { jid }
291
+ }))
292
+ }
293
+ ]
294
+ }
295
+ ]);
296
+ const node = getBinaryNodeChild(result, 'membership_requests_action');
297
+ const nodeAction = getBinaryNodeChild(node, action);
298
+ const participantsAffected = getBinaryNodeChildren(nodeAction, 'participant');
299
+ return participantsAffected.map(p => {
300
+ return { status: p.attrs.error || '200', jid: p.attrs.jid };
301
+ });
302
+ },
303
+ groupParticipantsUpdate: async (jid, participants, action) => {
304
+ const result = await groupQuery(jid, 'set', [
305
+ {
306
+ tag: action,
307
+ attrs: {},
308
+ content: participants.map(jid => ({
309
+ tag: 'participant',
310
+ attrs: { jid }
311
+ }))
312
+ }
313
+ ]);
314
+ const node = getBinaryNodeChild(result, action);
315
+ const participantsAffected = getBinaryNodeChildren(node, 'participant');
316
+ return participantsAffected.map(p => {
317
+ return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p };
318
+ });
319
+ },
320
+ groupUpdateDescription: async (jid, description) => {
321
+ const metadata = await groupMetadata(jid);
322
+ const prev = metadata.descId ?? null;
323
+ await groupQuery(jid, 'set', [
324
+ {
325
+ tag: 'description',
326
+ attrs: {
327
+ ...(description ? { id: generateMessageIDV2() } : { delete: 'true' }),
328
+ ...(prev ? { prev } : {})
329
+ },
330
+ content: description ? [{ tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') }] : undefined
331
+ }
332
+ ]);
333
+ },
334
+ groupInviteCode: async (jid) => {
335
+ const result = await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }]);
336
+ const inviteNode = getBinaryNodeChild(result, 'invite');
337
+ return inviteNode?.attrs.code;
338
+ },
339
+ groupRevokeInvite: async (jid) => {
340
+ const result = await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }]);
341
+ const inviteNode = getBinaryNodeChild(result, 'invite');
342
+ return inviteNode?.attrs.code;
343
+ },
344
+ groupAcceptInvite: async (code) => {
345
+ const results = await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }]);
346
+ const result = getBinaryNodeChild(results, 'group');
347
+ return result?.attrs.jid;
348
+ },
349
+ /**
350
+ * revoke a v4 invite for someone
351
+ * @param groupJid group jid
352
+ * @param invitedJid jid of person you invited
353
+ * @returns true if successful
354
+ */
355
+ groupRevokeInviteV4: async (groupJid, invitedJid) => {
356
+ const result = await groupQuery(groupJid, 'set', [
357
+ { tag: 'revoke', attrs: {}, content: [{ tag: 'participant', attrs: { jid: invitedJid } }] }
358
+ ]);
359
+ return !!result;
360
+ },
361
+ /**
362
+ * accept a GroupInviteMessage
363
+ * @param key the key of the invite message, or optionally only provide the jid of the person who sent the invite
364
+ * @param inviteMessage the message to accept
365
+ */
366
+ groupAcceptInviteV4: ev.createBufferedFunction(async (key, inviteMessage) => {
367
+ key = typeof key === 'string' ? { remoteJid: key } : key;
368
+ const results = await groupQuery(inviteMessage.groupJid, 'set', [
369
+ {
370
+ tag: 'accept',
371
+ attrs: {
372
+ code: inviteMessage.inviteCode,
373
+ expiration: inviteMessage.inviteExpiration.toString(),
374
+ admin: key.remoteJid
375
+ }
376
+ }
377
+ ]);
378
+ // if we have the full message key
379
+ // update the invite message to be expired
380
+ if (key.id) {
381
+ // create new invite message that is expired
382
+ inviteMessage = proto.Message.GroupInviteMessage.fromObject(inviteMessage);
383
+ inviteMessage.inviteExpiration = 0;
384
+ inviteMessage.inviteCode = '';
385
+ ev.emit('messages.update', [
386
+ {
387
+ key,
388
+ update: {
389
+ message: {
390
+ groupInviteMessage: inviteMessage
391
+ }
392
+ }
393
+ }
394
+ ]);
395
+ }
396
+ // generate the group add message
397
+ await upsertMessage({
398
+ key: {
399
+ remoteJid: inviteMessage.groupJid,
400
+ id: generateMessageIDV2(sock.user?.id),
401
+ fromMe: false,
402
+ participant: key.remoteJid
403
+ },
404
+ messageStubType: WAMessageStubType.GROUP_PARTICIPANT_ADD,
405
+ messageStubParameters: [JSON.stringify(authState.creds.me)],
406
+ participant: key.remoteJid,
407
+ messageTimestamp: unixTimestampSeconds()
408
+ }, 'notify');
409
+ return results.attrs.from;
410
+ }),
411
+ groupGetInviteInfo: async (code) => {
412
+ const results = await groupQuery('@g.us', 'get', [{ tag: 'invite', attrs: { code } }]);
413
+ return extractGroupMetadata(results);
414
+ },
415
+ groupToggleEphemeral: async (jid, ephemeralExpiration) => {
416
+ const content = ephemeralExpiration
417
+ ? { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } }
418
+ : { tag: 'not_ephemeral', attrs: {} };
419
+ await groupQuery(jid, 'set', [content]);
420
+ },
421
+ groupSettingUpdate: async (jid, setting) => {
422
+ await groupQuery(jid, 'set', [{ tag: setting, attrs: {} }]);
423
+ },
424
+ groupMemberAddMode: async (jid, mode) => {
425
+ await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }]);
426
+ },
427
+ groupJoinApprovalMode: async (jid, mode) => {
428
+ await groupQuery(jid, 'set', [
429
+ { tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state: mode } }] }
430
+ ]);
431
+ },
432
+ groupFetchAllParticipating,
433
+ /** Report a contact to WhatsApp, then block it after the report succeeds. */
434
+ reportContact: async (jid, messageKeys = []) => {
435
+ const normalizedJid = jidNormalizedUser(jid);
436
+ if (!isPnUser(normalizedJid) && !isLidUser(normalizedJid)) {
437
+ throw new Boom('reportContact requires a valid contact JID', { statusCode: 400 });
438
+ }
439
+ const reportResult = await reportJid(normalizedJid, messageKeys);
440
+ await updateBlockStatus(normalizedJid, 'block');
441
+ return reportResult;
442
+ },
443
+ /** Report a group to WhatsApp, then leave it after the report succeeds. */
444
+ reportGroup: async (jid, messageKeys = []) => {
445
+ if (!isJidGroup(jid)) {
446
+ throw new Boom('reportGroup requires a valid group JID', { statusCode: 400 });
447
+ }
448
+ const reportResult = await reportJid(jid, messageKeys);
449
+ await groupQuery('@g.us', 'set', [{
450
+ tag: 'leave',
451
+ attrs: {},
452
+ content: [{ tag: 'group', attrs: { id: jid } }]
453
+ }]);
454
+ return reportResult;
455
+ },
456
+ /** Revoke a previously sent group status using its original message key. */
457
+ deleteGroupStatus: async (jid, key) => {
458
+ if (!isJidGroup(jid)) {
459
+ throw new Boom('deleteGroupStatus requires a valid group JID', { statusCode: 400 });
460
+ }
461
+ if (!key?.id) {
462
+ throw new Boom('deleteGroupStatus requires a message key with an id', { statusCode: 400 });
463
+ }
464
+ if (key.remoteJid && key.remoteJid !== jid) {
465
+ throw new Boom('The group status key does not belong to the target group', { statusCode: 400 });
466
+ }
467
+ return relayMessage(
468
+ jid,
469
+ buildGroupStatusRevokeMessage(jid, key),
470
+ { messageId: generateMessageIDV2(authState.creds.me?.id) }
471
+ );
472
+ }
473
+ };
474
+ };
475
+ export const extractGroupMetadata = (result) => {
476
+ const group = getBinaryNodeChild(result, 'group');
477
+ if (!group) {
478
+ // Mirror WAWeb: surface server/client errors with their code+text instead of crashing.
479
+ const errorNode = getBinaryNodeChild(result, 'error');
480
+ if (errorNode) {
481
+ const code = errorNode.attrs.code ? +errorNode.attrs.code : 500;
482
+ const text = errorNode.attrs.text || 'group metadata query failed';
483
+ throw new Boom(text, { statusCode: code, data: errorNode });
484
+ }
485
+ throw new Boom('Invalid group metadata response: missing <group> node', { data: result });
486
+ }
487
+ if (!group.attrs.id) {
488
+ throw new Boom('Invalid group metadata response: missing group id', { data: group });
489
+ }
490
+ const descChild = getBinaryNodeChild(group, 'description');
491
+ let desc;
492
+ let descId;
493
+ let descOwner;
494
+ let descOwnerPn;
495
+ let descOwnerUsername;
496
+ let descTime;
497
+ if (descChild) {
498
+ desc = getBinaryNodeChildString(descChild, 'body');
499
+ descOwner = descChild.attrs.participant ? jidNormalizedUser(descChild.attrs.participant) : undefined;
500
+ descOwnerPn = descChild.attrs.participant_pn ? jidNormalizedUser(descChild.attrs.participant_pn) : undefined;
501
+ descOwnerUsername = descChild.attrs.participant_username || undefined;
502
+ descTime = +descChild.attrs.t;
503
+ descId = descChild.attrs.id;
504
+ }
505
+ const groupId = group.attrs.id.includes('@') ? group.attrs.id : jidEncode(group.attrs.id, 'g.us');
506
+ const eph = getBinaryNodeChild(group, 'ephemeral')?.attrs.expiration;
507
+ const memberAddMode = getBinaryNodeChildString(group, 'member_add_mode') === 'all_member_add';
508
+ const metadata = {
509
+ id: groupId,
510
+ notify: group.attrs.notify,
511
+ addressingMode: group.attrs.addressing_mode === 'lid' ? WAMessageAddressingMode.LID : WAMessageAddressingMode.PN,
512
+ subject: group.attrs.subject,
513
+ subjectOwner: group.attrs.s_o,
514
+ subjectOwnerPn: group.attrs.s_o_pn,
515
+ subjectOwnerUsername: group.attrs.s_o_username,
516
+ subjectTime: +group.attrs.s_t,
517
+ size: group.attrs.size ? +group.attrs.size : getBinaryNodeChildren(group, 'participant').length,
518
+ creation: +group.attrs.creation,
519
+ owner: group.attrs.creator ? jidNormalizedUser(group.attrs.creator) : undefined,
520
+ ownerPn: group.attrs.creator_pn ? jidNormalizedUser(group.attrs.creator_pn) : undefined,
521
+ ownerUsername: group.attrs.creator_username || undefined,
522
+ owner_country_code: group.attrs.creator_country_code,
523
+ desc,
524
+ descId,
525
+ descOwner,
526
+ descOwnerPn,
527
+ descOwnerUsername,
528
+ descTime,
529
+ linkedParent: getBinaryNodeChild(group, 'linked_parent')?.attrs.jid || undefined,
530
+ restrict: !!getBinaryNodeChild(group, 'locked'),
531
+ announce: !!getBinaryNodeChild(group, 'announcement'),
532
+ isCommunity: !!getBinaryNodeChild(group, 'parent'),
533
+ isCommunityAnnounce: !!getBinaryNodeChild(group, 'default_sub_group'),
534
+ joinApprovalMode: !!getBinaryNodeChild(group, 'membership_approval_mode'),
535
+ memberAddMode,
536
+ participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) => {
537
+ // TODO: Store LID MAPPINGS
538
+ return {
539
+ id: attrs.jid,
540
+ phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
541
+ lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined,
542
+ username: attrs.participant_username || attrs.username || undefined,
543
+ admin: (attrs.type || null)
544
+ };
545
+ }),
546
+ ephemeralDuration: eph ? +eph : undefined
547
+ };
548
+ return metadata;
549
+ };
@@ -0,0 +1,79 @@
1
+ import { DEFAULT_CONNECTION_CONFIG } from '../Defaults/index.js';
2
+ //
3
+ // ANTI-BAN / ANTI-SPAM LAYER COMMENTED OUT ON REQUEST (temporary).
4
+ // The bundled antiban layer (lib/antiban.cjs) wraps every socket and
5
+ // rate-limits/warm-ups sends, printing "[baileys-antiban]" spam to the
6
+ // console and throwing "[baileys-antiban] Message blocked: ..." once the
7
+ // daily warm-up limit is hit. To re-enable, uncomment the three lines
8
+ // below (and the wrap block in makeWASocket).
9
+ //
10
+ // import { createRequire } from 'node:module';
11
+ // // Load the bundled antiban layer via createRequire so no CJS file is part
12
+ // // of the ESM module graph (keeps require(esm) namespace population working
13
+ // // on Node versions where it is still experimental)
14
+ // const nodeRequire = createRequire(import.meta.url);
15
+ // const { wrapSocket } = nodeRequire('../antiban.cjs');
16
+ //
17
+ import { makeCommunitiesSocket } from './communities.js';
18
+ import { makeInteropSocket } from './interop.js';
19
+ import { makePrivacySocket } from './privacy.js';
20
+ import { makeRegistrationSocket } from './registration.js';
21
+ import { makeManagedAccountSocket } from './managed-account.js';
22
+ import { makeGraphQLSocket } from './graphql.js';
23
+
24
+ // export the last socket layer
25
+ const makeWASocket = (config) => {
26
+ // CODEX branding banner
27
+ // Printed once per process when a socket is created.
28
+ if (!globalThis.__codexBannerShown) {
29
+ globalThis.__codexBannerShown = true;
30
+ const yellow = '\x1b[93m'; // bright / light yellow
31
+ const dim = '\x1b[2m';
32
+ const reset = '\x1b[0m';
33
+ const logo = [
34
+ ' ',
35
+ ' ',
36
+ ' ',
37
+ ' ',
38
+ ' ',
39
+ ' '
40
+ ].join('\\n');
41
+ console.log(
42
+ '\\n' + yellow + logo + reset + '\\n' +
43
+ dim + ' CODEX TECHNOLOGY a premium Baileys developed and built by Dev Codex' + reset + '\\n'
44
+ );
45
+ }
46
+ const userExplicitSyncFlag = typeof config?.syncFullHistory === 'boolean';
47
+ const initialFullSyncDone = !!config?.auth?.creds?.initialFullSyncDone;
48
+ const effectiveSyncFullHistory = userExplicitSyncFlag ? config.syncFullHistory : !initialFullSyncDone;
49
+ const newConfig = {
50
+ ...DEFAULT_CONNECTION_CONFIG,
51
+ ...config,
52
+ syncFullHistory: effectiveSyncFullHistory
53
+ };
54
+ newConfig.logger?.debug?.(
55
+ { initialFullSyncDone, effectiveSyncFullHistory, userExplicitSyncFlag },
56
+ 'computed syncFullHistory policy'
57
+ );
58
+
59
+ const baseSock = makeCommunitiesSocket(newConfig);
60
+ const interopSock = makeInteropSocket(baseSock);
61
+ const privacySock = makePrivacySocket(interopSock);
62
+ const registrationSock = makeRegistrationSocket(privacySock);
63
+ const managedSock = makeManagedAccountSocket(registrationSock);
64
+ const sock = makeGraphQLSocket(managedSock);
65
+
66
+ //
67
+ // ANTI-BAN / ANTI-SPAM LAYER COMMENTED OUT ON REQUEST (temporary).
68
+ // Previously:
69
+ // // Auto-wrap with antiban if available (config.antiban = false to opt-out)
70
+ // if (wrapSocket && config?.antiban !== false) {
71
+ // const antibanConfig = config?.antiban || 'aggressive';
72
+ // return wrapSocket(sock, antibanConfig);
73
+ // }
74
+ // The socket is returned unwrapped no rate limiting, no warm-up
75
+ // blocking, and no "[baileys-antiban]" console output.
76
+ //
77
+ return sock;
78
+ };
79
+ export default makeWASocket;