@areumtecnologia/wasockets 1.1.5 → 2.0.0-alpha.1

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.
@@ -119,6 +119,76 @@ const makeCommunitiesSocket = (config) => {
119
119
  await cleanDirtyBits('groups')
120
120
  })
121
121
 
122
+ const communityRequestParticipantsUpdate = async (jid, participants, action) => {
123
+ const result = await communityQuery(jid, 'set', [
124
+ {
125
+ tag: 'membership_requests_action',
126
+ attrs: {},
127
+ content: [
128
+ {
129
+ tag: action,
130
+ attrs: {},
131
+ content: participants.map(jid => ({
132
+ tag: 'participant',
133
+ attrs: { jid }
134
+ }))
135
+ }
136
+ ]
137
+ }
138
+ ])
139
+
140
+ const node = getBinaryNodeChild(result, 'membership_requests_action')
141
+ const nodeAction = getBinaryNodeChild(node, action)
142
+ const participantsAffected = getBinaryNodeChildren(nodeAction, 'participant')
143
+
144
+ return participantsAffected.map(p => {
145
+ return { status: p.attrs.error || '200', jid: p.attrs.jid }
146
+ })
147
+ }
148
+
149
+ const communityFetchLinkedGroups = async (jid) => {
150
+ let communityJid = jid
151
+ let isCommunity = false
152
+
153
+ // Try to determine if it is a subgroup or a community
154
+ const metadata = await groupMetadata(jid)
155
+
156
+ if (metadata.linkedParent) {
157
+ // It is a subgroup, get the community jid
158
+ communityJid = metadata.linkedParent
159
+ } else {
160
+ // It is a community
161
+ isCommunity = true
162
+ }
163
+
164
+ // Fetch all subgroups of the community
165
+ const result = await communityQuery(communityJid, 'get', [{ tag: 'sub_groups', attrs: {} }])
166
+ const linkedGroupsData = []
167
+ const subGroupsNode = getBinaryNodeChild(result, 'sub_groups')
168
+
169
+ if (subGroupsNode) {
170
+ const groupNodes = getBinaryNodeChildren(subGroupsNode, 'group')
171
+
172
+ for (const groupNode of groupNodes) {
173
+ const isDefault = groupNode.attrs.default_sub_group === 'true' || !!getBinaryNodeChild(groupNode, 'default_sub_group')
174
+ linkedGroupsData.push({
175
+ id: groupNode.attrs.id ? jidEncode(groupNode.attrs.id, 'g.us') : undefined,
176
+ subject: groupNode.attrs.subject || '',
177
+ creation: groupNode.attrs.creation ? Number(groupNode.attrs.creation) : undefined,
178
+ owner: groupNode.attrs.creator ? jidNormalizedUser(groupNode.attrs.creator) : undefined,
179
+ size: groupNode.attrs.size ? Number(groupNode.attrs.size) : undefined,
180
+ isDefaultSubGroup: isDefault
181
+ })
182
+ }
183
+ }
184
+
185
+ return {
186
+ communityJid,
187
+ isCommunity,
188
+ linkedGroups: linkedGroupsData
189
+ }
190
+ }
191
+
122
192
  return {
123
193
  ...suki,
124
194
  communityQuery,
@@ -225,46 +295,15 @@ const makeCommunitiesSocket = (config) => {
225
295
  }
226
296
  ])
227
297
  },
228
- communityFetchLinkedGroups: async (jid) => {
229
- let communityJid = jid
230
- let isCommunity = false
231
-
232
- // Try to determine if it is a subgroup or a community
233
- const metadata = await groupMetadata(jid)
234
-
235
- if (metadata.linkedParent) {
236
- // It is a subgroup, get the community jid
237
- communityJid = metadata.linkedParent
238
- }
239
-
240
- else {
241
- // It is a community
242
- isCommunity = true
243
- }
244
-
245
- // Fetch all subgroups of the community
246
- const result = await communityQuery(communityJid, 'get', [{ tag: 'sub_groups', attrs: {} }])
247
- const linkedGroupsData = []
248
- const subGroupsNode = getBinaryNodeChild(result, 'sub_groups')
249
-
250
- if (subGroupsNode) {
251
- const groupNodes = getBinaryNodeChildren(subGroupsNode, 'group')
252
-
253
- for (const groupNode of groupNodes) {
254
- linkedGroupsData.push({
255
- id: groupNode.attrs.id ? jidEncode(groupNode.attrs.id, 'g.us') : undefined,
256
- subject: groupNode.attrs.subject || '',
257
- creation: groupNode.attrs.creation ? Number(groupNode.attrs.creation) : undefined,
258
- owner: groupNode.attrs.creator ? jidNormalizedUser(groupNode.attrs.creator) : undefined,
259
- size: groupNode.attrs.size ? Number(groupNode.attrs.size) : undefined
260
- })
261
- }
262
- }
263
-
298
+ communityFetchLinkedGroups,
299
+ communityFetchSubGroups: async (jid) => {
300
+ const data = await communityFetchLinkedGroups(jid)
301
+ const defaultSubGroup = data.linkedGroups.find(g => g.isDefaultSubGroup) || null
302
+ const subGroups = data.linkedGroups.filter(g => !g.isDefaultSubGroup)
264
303
  return {
265
- communityJid,
266
- isCommunity,
267
- linkedGroups: linkedGroupsData
304
+ ...data,
305
+ defaultSubGroup,
306
+ subGroups
268
307
  }
269
308
  },
270
309
  communityRequestParticipantsList: async (jid) => {
@@ -280,32 +319,7 @@ const makeCommunitiesSocket = (config) => {
280
319
 
281
320
  return participants.map(v => v.attrs)
282
321
  },
283
- communityRequestParticipantsUpdate: async (jid, participants, action) => {
284
- const result = await communityQuery(jid, 'set', [
285
- {
286
- tag: 'membership_requests_action',
287
- attrs: {},
288
- content: [
289
- {
290
- tag: action,
291
- attrs: {},
292
- content: participants.map(jid => ({
293
- tag: 'participant',
294
- attrs: { jid }
295
- }))
296
- }
297
- ]
298
- }
299
- ])
300
-
301
- const node = getBinaryNodeChild(result, 'membership_requests_action')
302
- const nodeAction = getBinaryNodeChild(node, action)
303
- const participantsAffected = getBinaryNodeChildren(nodeAction, 'participant')
304
-
305
- return participantsAffected.map(p => {
306
- return { status: p.attrs.error || '200', jid: p.attrs.jid }
307
- })
308
- },
322
+ communityRequestParticipantsUpdate,
309
323
  communityParticipantsUpdate: async (jid, participants, action) => {
310
324
  const result = await communityQuery(jid, 'set', [
311
325
  {
@@ -442,10 +456,53 @@ const makeCommunitiesSocket = (config) => {
442
456
  await communityQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }])
443
457
  },
444
458
  communityJoinApprovalMode: async (jid, mode) => {
459
+ const state = (mode === true || mode === 'on') ? 'on' : (mode === false || mode === 'off' ? 'off' : mode)
445
460
  await communityQuery(jid, 'set', [
446
- { tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'community_join', attrs: { state: mode } }] }
461
+ { tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'community_join', attrs: { state } }] }
447
462
  ])
448
463
  },
464
+ communityMembershipApprovalMode: async (jid, mode) => {
465
+ const state = (mode === true || mode === 'on') ? 'on' : 'off'
466
+ await communityQuery(jid, 'set', [
467
+ { tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'community_join', attrs: { state } }] }
468
+ ])
469
+ },
470
+ communityApprovePendingParticipants: async (jid, participants) => {
471
+ const list = Array.isArray(participants) ? participants : [participants]
472
+ return communityRequestParticipantsUpdate(jid, list, 'approve')
473
+ },
474
+ communityRejectPendingParticipants: async (jid, participants) => {
475
+ const list = Array.isArray(participants) ? participants : [participants]
476
+ return communityRequestParticipantsUpdate(jid, list, 'reject')
477
+ },
478
+ communityUpdatePermissions: async (jid, policies = {}) => {
479
+ const results = {}
480
+ if (typeof policies.announce === 'boolean') {
481
+ await communityQuery(jid, 'set', [{ tag: policies.announce ? 'announcement' : 'not_announcement', attrs: {} }])
482
+ results.announce = policies.announce
483
+ }
484
+ if (typeof policies.restrict === 'boolean') {
485
+ await communityQuery(jid, 'set', [{ tag: policies.restrict ? 'locked' : 'unlocked', attrs: {} }])
486
+ results.restrict = policies.restrict
487
+ }
488
+ if (policies.memberAddMode) {
489
+ await communityQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: policies.memberAddMode }])
490
+ results.memberAddMode = policies.memberAddMode
491
+ }
492
+ if (typeof policies.approvalMode !== 'undefined') {
493
+ const state = (policies.approvalMode === true || policies.approvalMode === 'on') ? 'on' : 'off'
494
+ await communityQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'community_join', attrs: { state } }] }])
495
+ results.approvalMode = state
496
+ }
497
+ if (typeof policies.ephemeral !== 'undefined') {
498
+ const content = policies.ephemeral ?
499
+ { tag: 'ephemeral', attrs: { expiration: policies.ephemeral.toString() } } :
500
+ { tag: 'not_ephemeral', attrs: {} }
501
+ await communityQuery(jid, 'set', [content])
502
+ results.ephemeral = policies.ephemeral
503
+ }
504
+ return results
505
+ },
449
506
  communityFetchAllParticipating
450
507
  }
451
508
  }
@@ -489,12 +546,12 @@ const extractCommunityMetadata = (result) => {
489
546
  memberAddMode,
490
547
  participants: getBinaryNodeChildren(community, 'participant').map(({ attrs }) => {
491
548
  return {
492
- id: mode === WAMessageAddressingMode.LID ? community.phone_number : attrs.jid,
493
- lid: mode === WAMessageAddressingMode.LID ? community.jid : attrs.lid,
549
+ id: mode === WAMessageAddressingMode.LID ? attrs.phone_number : attrs.jid,
550
+ lid: mode === WAMessageAddressingMode.LID ? attrs.jid : attrs.lid,
494
551
  admin: (attrs.type || null),
495
552
  }
496
553
  }),
497
- ephemeralDuration: eph ? Number(ph) : undefined,
554
+ ephemeralDuration: eph ? Number(eph) : undefined,
498
555
  addressingMode: mode
499
556
  }
500
557
 
@@ -40,8 +40,16 @@ const makeGroupsSocket = (config) => {
40
40
  }))
41
41
 
42
42
  const groupMetadata = async (jid) => {
43
+ if (config.cachedGroupMetadata) {
44
+ const cached = await config.cachedGroupMetadata(jid)
45
+ if (cached) return cached
46
+ }
43
47
  const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }])
44
- return extractGroupMetadata(result)
48
+ const metadata = extractGroupMetadata(result)
49
+ if (config.cachedGroupMetadata?.set && metadata) {
50
+ config.cachedGroupMetadata.set(jid, metadata)
51
+ }
52
+ return metadata
45
53
  }
46
54
 
47
55
  const groupFetchAllParticipating = async () => {
@@ -79,6 +87,14 @@ const makeGroupsSocket = (config) => {
79
87
  }
80
88
  }
81
89
 
90
+ if (config.cachedGroupMetadata?.set) {
91
+ for (const meta of Object.values(data)) {
92
+ if (meta?.id) {
93
+ config.cachedGroupMetadata.set(meta.id, meta)
94
+ }
95
+ }
96
+ }
97
+
82
98
  suki.ev.emit('groups.update', Object.values(data))
83
99
  return data
84
100
  }
@@ -93,6 +109,31 @@ const makeGroupsSocket = (config) => {
93
109
  await cleanDirtyBits('groups')
94
110
  })
95
111
 
112
+ const groupRequestParticipantsUpdate = async (jid, participants, action) => {
113
+ const result = await groupQuery(jid, 'set', [{
114
+ tag: 'membership_requests_action',
115
+ attrs: {},
116
+ content: [
117
+ {
118
+ tag: action,
119
+ attrs: {},
120
+ content: participants.map(jid => ({
121
+ tag: 'participant',
122
+ attrs: { jid }
123
+ }))
124
+ }
125
+ ]
126
+ }])
127
+
128
+ const node = getBinaryNodeChild(result, 'membership_requests_action')
129
+ const nodeAction = getBinaryNodeChild(node, action)
130
+ const participantsAffected = getBinaryNodeChildren(nodeAction, 'participant')
131
+
132
+ return participantsAffected.map(p => {
133
+ return { status: p.attrs.error || '200', jid: p.attrs.jid }
134
+ })
135
+ }
136
+
96
137
  return {
97
138
  ...suki,
98
139
  groupQuery,
@@ -117,6 +158,7 @@ const makeGroupsSocket = (config) => {
117
158
  return extractGroupMetadata(result)
118
159
  },
119
160
  groupLeave: async (id) => {
161
+ config.cachedGroupMetadata?.delete?.(id)
120
162
  await groupQuery('@g.us', 'set', [
121
163
  {
122
164
  tag: 'leave',
@@ -128,6 +170,7 @@ const makeGroupsSocket = (config) => {
128
170
  ])
129
171
  },
130
172
  groupUpdateSubject: async (jid, subject) => {
173
+ config.cachedGroupMetadata?.delete?.(jid)
131
174
  await groupQuery(jid, 'set', [
132
175
  {
133
176
  tag: 'subject',
@@ -149,30 +192,7 @@ const makeGroupsSocket = (config) => {
149
192
 
150
193
  return participants.map(v => v.attrs)
151
194
  },
152
- groupRequestParticipantsUpdate: async (jid, participants, action) => {
153
- const result = await groupQuery(jid, 'set', [{
154
- tag: 'membership_requests_action',
155
- attrs: {},
156
- content: [
157
- {
158
- tag: action,
159
- attrs: {},
160
- content: participants.map(jid => ({
161
- tag: 'participant',
162
- attrs: { jid }
163
- }))
164
- }
165
- ]
166
- }])
167
-
168
- const node = getBinaryNodeChild(result, 'membership_requests_action')
169
- const nodeAction = getBinaryNodeChild(node, action)
170
- const participantsAffected = getBinaryNodeChildren(nodeAction, 'participant')
171
-
172
- return participantsAffected.map(p => {
173
- return { status: p.attrs.error || '200', jid: p.attrs.jid }
174
- })
175
- },
195
+ groupRequestParticipantsUpdate,
176
196
  groupParticipantsUpdate: async (jid, participants, action) => {
177
197
  const result = await groupQuery(jid, 'set', [
178
198
  {
@@ -187,11 +207,13 @@ const makeGroupsSocket = (config) => {
187
207
  const node = getBinaryNodeChild(result, action)
188
208
  const participantsAffected = getBinaryNodeChildren(node, 'participant')
189
209
 
210
+ config.cachedGroupMetadata?.delete?.(jid)
190
211
  return participantsAffected.map(p => {
191
212
  return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p }
192
213
  })
193
214
  },
194
215
  groupUpdateDescription: async (jid, description) => {
216
+ config.cachedGroupMetadata?.delete?.(jid)
195
217
  const metadata = await groupMetadata(jid)
196
218
  const prev = metadata.descId ? metadata.descId : null
197
219
 
@@ -300,13 +322,68 @@ const makeGroupsSocket = (config) => {
300
322
  await groupQuery(jid, 'set', [content])
301
323
  },
302
324
  groupSettingUpdate: async (jid, setting) => {
325
+ config.cachedGroupMetadata?.delete?.(jid)
303
326
  await groupQuery(jid, 'set', [{ tag: setting, attrs: {} }])
304
327
  },
305
328
  groupMemberAddMode: async (jid, mode) => {
329
+ config.cachedGroupMetadata?.delete?.(jid)
306
330
  await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }])
307
331
  },
308
332
  groupJoinApprovalMode: async (jid, mode) => {
309
- await groupQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state: mode } }] }])
333
+ config.cachedGroupMetadata?.delete?.(jid)
334
+ const state = (mode === true || mode === 'on') ? 'on' : (mode === false || mode === 'off' ? 'off' : mode)
335
+ await groupQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state } }] }])
336
+ },
337
+ groupMembershipApprovalMode: async (jid, mode) => {
338
+ const state = (mode === true || mode === 'on') ? 'on' : 'off'
339
+ await groupQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state } }] }])
340
+ },
341
+ groupApprovePendingParticipants: async (jid, participants) => {
342
+ const list = Array.isArray(participants) ? participants : [participants]
343
+ return groupRequestParticipantsUpdate(jid, list, 'approve')
344
+ },
345
+ groupRejectPendingParticipants: async (jid, participants) => {
346
+ const list = Array.isArray(participants) ? participants : [participants]
347
+ return groupRequestParticipantsUpdate(jid, list, 'reject')
348
+ },
349
+ groupUpdatePermissions: async (jid, policies = {}) => {
350
+ config.cachedGroupMetadata?.delete?.(jid)
351
+ const results = {}
352
+ if (typeof policies.announce === 'boolean') {
353
+ await groupQuery(jid, 'set', [{ tag: policies.announce ? 'announcement' : 'not_announcement', attrs: {} }])
354
+ results.announce = policies.announce
355
+ }
356
+ if (typeof policies.restrict === 'boolean') {
357
+ await groupQuery(jid, 'set', [{ tag: policies.restrict ? 'locked' : 'unlocked', attrs: {} }])
358
+ results.restrict = policies.restrict
359
+ }
360
+ if (policies.memberAddMode) {
361
+ await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: policies.memberAddMode }])
362
+ results.memberAddMode = policies.memberAddMode
363
+ }
364
+ if (typeof policies.approvalMode !== 'undefined') {
365
+ const state = (policies.approvalMode === true || policies.approvalMode === 'on') ? 'on' : 'off'
366
+ await groupQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state } }] }])
367
+ results.approvalMode = state
368
+ }
369
+ if (typeof policies.ephemeral !== 'undefined') {
370
+ const content = policies.ephemeral ?
371
+ { tag: 'ephemeral', attrs: { expiration: policies.ephemeral.toString() } } :
372
+ { tag: 'not_ephemeral', attrs: {} }
373
+ await groupQuery(jid, 'set', [content])
374
+ results.ephemeral = policies.ephemeral
375
+ }
376
+ return results
377
+ },
378
+ groupGetAdminJids: async (jid) => {
379
+ const metadata = await groupMetadata(jid)
380
+ return (metadata.participants || [])
381
+ .filter(p => !!p.admin)
382
+ .map(p => p.id)
383
+ },
384
+ groupGetParticipants: async (jid) => {
385
+ const metadata = await groupMetadata(jid)
386
+ return metadata.participants || []
310
387
  },
311
388
  groupFetchAllParticipating
312
389
  }
@@ -2,11 +2,12 @@
2
2
 
3
3
  Object.defineProperty(exports, "__esModule", { value: true })
4
4
 
5
- const { DEFAULT_CONNECTION_CONFIG } = require("../Defaults/connection")
5
+ const { DEFAULT_CONNECTION_CONFIG, createGroupMetadataCache } = require("../Defaults/connection")
6
6
  const { makeCommunitiesSocket } = require("./community")
7
+ const { PluginManager } = require("../Plugins")
7
8
 
8
9
  // export the last socket layer
9
- const makeWASocket = (config) => {
10
+ const makeWASocket = (config = {}) => {
10
11
  const newConfig = {
11
12
  ...DEFAULT_CONNECTION_CONFIG,
12
13
  ...config
@@ -18,7 +19,30 @@ const makeWASocket = (config) => {
18
19
  newConfig.shouldSyncHistoryMessage = () => !!newConfig.syncFullHistory
19
20
  }
20
21
 
21
- return makeCommunitiesSocket(newConfig)
22
+ if (!config.cachedGroupMetadata && newConfig.enableGroupCache) {
23
+ newConfig.cachedGroupMetadata = createGroupMetadataCache()
24
+ }
25
+
26
+ const sock = makeCommunitiesSocket(newConfig)
27
+ const pluginManager = new PluginManager(sock)
28
+
29
+ sock.plugins = pluginManager
30
+ sock.use = (plugin, options) => {
31
+ pluginManager.use(plugin, options)
32
+ return sock
33
+ }
34
+ sock.registerMiddleware = (hook, fn) => pluginManager.registerMiddleware(hook, fn)
35
+ sock.hasPlugin = (name) => pluginManager.hasPlugin(name)
36
+ sock.listPlugins = () => pluginManager.listPlugins()
37
+
38
+ // Auto-install plugins passed in configuration
39
+ if (Array.isArray(config.plugins)) {
40
+ for (const p of config.plugins) {
41
+ sock.use(p)
42
+ }
43
+ }
44
+
45
+ return sock
22
46
  }
23
47
 
24
48
  exports.default = makeWASocket
@@ -302,6 +302,46 @@ const makeMessagesRecvSocket = (config) => {
302
302
  await query(stanza)
303
303
  }
304
304
 
305
+ const acceptCall = async (callId, callFrom) => {
306
+ const stanza = ({
307
+ tag: 'call',
308
+ attrs: {
309
+ from: authState.creds.me.id,
310
+ to: callFrom,
311
+ },
312
+ content: [{
313
+ tag: 'accept',
314
+ attrs: {
315
+ 'call-id': callId,
316
+ 'call-creator': callFrom,
317
+ },
318
+ content: undefined,
319
+ }],
320
+ })
321
+
322
+ await query(stanza)
323
+ }
324
+
325
+ const terminateCall = async (callId, callFrom) => {
326
+ const stanza = ({
327
+ tag: 'call',
328
+ attrs: {
329
+ from: authState.creds.me.id,
330
+ to: callFrom,
331
+ },
332
+ content: [{
333
+ tag: 'terminate',
334
+ attrs: {
335
+ 'call-id': callId,
336
+ 'call-creator': callFrom,
337
+ },
338
+ content: undefined,
339
+ }],
340
+ })
341
+
342
+ await query(stanza)
343
+ }
344
+
305
345
  const sendRetryRequest = async (node, forceIncludeKeys = false) => {
306
346
  const { fullMessage } = decodeMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '')
307
347
  const { key: msgKey } = fullMessage
@@ -1633,6 +1673,8 @@ const makeMessagesRecvSocket = (config) => {
1633
1673
  sendRetryRequest,
1634
1674
  offerCall,
1635
1675
  rejectCall,
1676
+ acceptCall,
1677
+ terminateCall,
1636
1678
  fetchMessageHistory,
1637
1679
  requestPlaceholderResend,
1638
1680
  messageRetryManager