@badzz88/baileys 8.4.7 → 8.4.9

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 (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1055 -337
  3. package/WAProto/WAProto.proto +347 -6
  4. package/WAProto/fix-import.js +38 -0
  5. package/WAProto/fix-imports.js +86 -85
  6. package/WAProto/index.d.ts +4913 -25
  7. package/WAProto/index.js +14074 -98
  8. package/package.json +50 -90
  9. package/src/Defaults/index.js +201 -0
  10. package/src/Defaults/phonenumber-mcc.json +223 -0
  11. package/src/Signal/Group/ciphertext-message.js +15 -0
  12. package/src/Signal/Group/group-session-builder.js +92 -0
  13. package/src/Signal/Group/group_cipher.js +89 -0
  14. package/src/Signal/Group/index.js +136 -0
  15. package/src/Signal/Group/keyhelper.js +73 -0
  16. package/src/Signal/Group/sender-chain-key.js +32 -0
  17. package/src/Signal/Group/sender-key-distribution-message.js +66 -0
  18. package/src/Signal/Group/sender-key-message.js +69 -0
  19. package/src/Signal/Group/sender-key-name.js +50 -0
  20. package/src/Signal/Group/sender-key-record.js +44 -0
  21. package/src/Signal/Group/sender-key-state.js +97 -0
  22. package/src/Signal/Group/sender-message-key.js +30 -0
  23. package/src/Signal/libsignal.js +470 -0
  24. package/src/Signal/lid-mapping.js +262 -0
  25. package/src/Socket/Client/index.js +30 -0
  26. package/src/Socket/Client/types.js +13 -0
  27. package/src/Socket/Client/websocket.js +62 -0
  28. package/src/Socket/aigroups.js +240 -0
  29. package/src/Socket/business.js +422 -0
  30. package/src/Socket/chats.js +2374 -0
  31. package/src/Socket/communities.js +580 -0
  32. package/src/Socket/graphql.js +915 -0
  33. package/src/Socket/groups.js +812 -0
  34. package/src/Socket/index.js +37 -0
  35. package/src/Socket/interactive-handler.js +579 -0
  36. package/src/Socket/interop.js +566 -0
  37. package/src/Socket/managed-account.js +214 -0
  38. package/src/Socket/messages-recv.js +3012 -0
  39. package/src/Socket/messages-send.js +2163 -0
  40. package/{lib → src}/Socket/mex.js +11 -5
  41. package/src/Socket/newsletter.js +1057 -0
  42. package/src/Socket/privacy.js +452 -0
  43. package/src/Socket/registration.js +434 -0
  44. package/src/Socket/socket.js +1079 -0
  45. package/src/Socket/text-router.js +67 -0
  46. package/src/Socket/username.js +234 -0
  47. package/src/Store/index.js +36 -0
  48. package/src/Store/make-cache-manager-store.js +90 -0
  49. package/src/Store/make-in-memory-store.js +506 -0
  50. package/src/Store/make-ordered-dictionary.js +81 -0
  51. package/src/Store/object-repository.js +29 -0
  52. package/src/Types/Auth.js +38 -0
  53. package/src/Types/Bussines.js +2 -0
  54. package/src/Types/Call.js +2 -0
  55. package/src/Types/Chat.js +4 -0
  56. package/src/Types/Contact.js +2 -0
  57. package/src/Types/Events.js +2 -0
  58. package/src/Types/GroupMetadata.js +2 -0
  59. package/src/Types/Label.js +27 -0
  60. package/src/Types/LabelAssociation.js +9 -0
  61. package/src/Types/Message.js +95 -0
  62. package/src/Types/Newsletter.js +152 -0
  63. package/src/Types/Product.js +2 -0
  64. package/src/Types/Signal.js +2 -0
  65. package/src/Types/Socket.js +2 -0
  66. package/src/Types/State.js +70 -0
  67. package/src/Types/USync.js +2 -0
  68. package/src/Types/index.js +54 -0
  69. package/src/Utils/auth-utils.js +306 -0
  70. package/src/Utils/browser-utils.js +114 -0
  71. package/src/Utils/business.js +247 -0
  72. package/src/Utils/chat-utils.js +1272 -0
  73. package/src/Utils/consumer-application.js +107 -0
  74. package/src/Utils/crypto.js +125 -0
  75. package/src/Utils/decode-wa-message.js +808 -0
  76. package/src/Utils/event-buffer.js +586 -0
  77. package/src/Utils/generics.js +640 -0
  78. package/src/Utils/group-history.js +60 -0
  79. package/src/Utils/history.js +244 -0
  80. package/src/Utils/identity-change-handler.js +52 -0
  81. package/src/Utils/index.js +53 -0
  82. package/src/Utils/jid-display-normalization.js +218 -0
  83. package/src/Utils/link-preview.js +143 -0
  84. package/src/Utils/logger.js +9 -0
  85. package/src/Utils/lt-hash.js +10 -0
  86. package/src/Utils/make-mutex.js +36 -0
  87. package/src/Utils/message-composer.js +479 -0
  88. package/src/Utils/message-inspect.js +400 -0
  89. package/src/Utils/message-retry-manager.js +231 -0
  90. package/src/Utils/messages-media.js +943 -0
  91. package/src/Utils/messages.js +2490 -0
  92. package/src/Utils/meta-ai-msmsg.js +133 -0
  93. package/src/Utils/noise-handler.js +194 -0
  94. package/src/Utils/offline-node-processor.js +42 -0
  95. package/src/Utils/pre-key-manager.js +107 -0
  96. package/src/Utils/process-message.js +1047 -0
  97. package/src/Utils/reporting-utils.js +262 -0
  98. package/src/Utils/signal.js +192 -0
  99. package/src/Utils/stanza-ack.js +74 -0
  100. package/src/Utils/sync-action-utils.js +54 -0
  101. package/src/Utils/tc-token-utils.js +161 -0
  102. package/src/Utils/use-multi-file-auth-state.js +121 -0
  103. package/src/Utils/validate-connection.js +248 -0
  104. package/src/Utils/voip-rekey.js +22 -0
  105. package/src/WABinary/constants.js +1304 -0
  106. package/src/WABinary/decode.js +377 -0
  107. package/src/WABinary/encode.js +58 -0
  108. package/src/WABinary/generic-utils.js +148 -0
  109. package/src/WABinary/index.js +33 -0
  110. package/src/WABinary/jid-utils.js +374 -0
  111. package/src/WABinary/types.js +2 -0
  112. package/src/WAM/BinaryInfo.js +13 -0
  113. package/src/WAM/constants.js +39486 -0
  114. package/src/WAM/encode.js +142 -0
  115. package/src/WAM/index.js +31 -0
  116. package/src/WAUSync/Protocols/USyncBotProfileProtocol.js +55 -0
  117. package/src/WAUSync/Protocols/USyncBusinessProtocol.js +100 -0
  118. package/src/WAUSync/Protocols/USyncContactProtocol.js +60 -0
  119. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +65 -0
  120. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -0
  121. package/src/WAUSync/Protocols/USyncFeatureProtocol.js +74 -0
  122. package/src/WAUSync/Protocols/USyncLIDProtocol.js +31 -0
  123. package/src/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
  124. package/src/WAUSync/Protocols/USyncSidelistProtocol.js +29 -0
  125. package/src/WAUSync/Protocols/USyncStatusProtocol.js +44 -0
  126. package/src/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
  127. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +28 -0
  128. package/src/WAUSync/Protocols/index.js +40 -0
  129. package/src/WAUSync/USyncBackoff.js +31 -0
  130. package/src/WAUSync/USyncQuery.js +204 -0
  131. package/src/WAUSync/USyncUser.js +58 -0
  132. package/src/WAUSync/index.js +32 -0
  133. package/src/antiban.js +4726 -0
  134. package/{lib → src}/index.js +48 -15
  135. package/lib/Defaults/index.js +0 -130
  136. package/lib/Signal/Group/ciphertext-message.js +0 -12
  137. package/lib/Signal/Group/group-session-builder.js +0 -30
  138. package/lib/Signal/Group/group_cipher.js +0 -82
  139. package/lib/Signal/Group/index.js +0 -12
  140. package/lib/Signal/Group/keyhelper.js +0 -18
  141. package/lib/Signal/Group/sender-chain-key.js +0 -26
  142. package/lib/Signal/Group/sender-key-distribution-message.js +0 -63
  143. package/lib/Signal/Group/sender-key-message.js +0 -66
  144. package/lib/Signal/Group/sender-key-name.js +0 -48
  145. package/lib/Signal/Group/sender-key-record.js +0 -41
  146. package/lib/Signal/Group/sender-key-state.js +0 -84
  147. package/lib/Signal/Group/sender-message-key.js +0 -26
  148. package/lib/Signal/libsignal.js +0 -431
  149. package/lib/Signal/lid-mapping.js +0 -277
  150. package/lib/Socket/Client/index.js +0 -3
  151. package/lib/Socket/Client/types.js +0 -11
  152. package/lib/Socket/Client/websocket.js +0 -54
  153. package/lib/Socket/business.js +0 -379
  154. package/lib/Socket/chats.js +0 -1193
  155. package/lib/Socket/communities.js +0 -431
  156. package/lib/Socket/groups.js +0 -374
  157. package/lib/Socket/index.js +0 -12
  158. package/lib/Socket/luxu.js +0 -386
  159. package/lib/Socket/messages-recv.js +0 -1916
  160. package/lib/Socket/messages-send.js +0 -1453
  161. package/lib/Socket/newsletter.js +0 -251
  162. package/lib/Socket/socket.js +0 -980
  163. package/lib/Socket/username.js +0 -146
  164. package/lib/Store/index.js +0 -10
  165. package/lib/Store/keyed-db.js +0 -108
  166. package/lib/Store/make-cache-manager-store.js +0 -85
  167. package/lib/Store/make-in-memory-store.js +0 -198
  168. package/lib/Store/make-ordered-dictionary.js +0 -75
  169. package/lib/Store/object-repository.js +0 -32
  170. package/lib/Types/Auth.js +0 -2
  171. package/lib/Types/Bussines.js +0 -2
  172. package/lib/Types/Call.js +0 -2
  173. package/lib/Types/Chat.js +0 -8
  174. package/lib/Types/Contact.js +0 -2
  175. package/lib/Types/Events.js +0 -2
  176. package/lib/Types/GroupMetadata.js +0 -2
  177. package/lib/Types/Label.js +0 -25
  178. package/lib/Types/LabelAssociation.js +0 -7
  179. package/lib/Types/Message.js +0 -11
  180. package/lib/Types/Mex.js +0 -37
  181. package/lib/Types/Product.js +0 -2
  182. package/lib/Types/Signal.js +0 -2
  183. package/lib/Types/Socket.js +0 -3
  184. package/lib/Types/State.js +0 -56
  185. package/lib/Types/USync.js +0 -2
  186. package/lib/Types/index.js +0 -26
  187. package/lib/Utils/auth-utils.js +0 -302
  188. package/lib/Utils/browser-utils.js +0 -49
  189. package/lib/Utils/business.js +0 -231
  190. package/lib/Utils/chat-utils.js +0 -872
  191. package/lib/Utils/companion-reg-client-utils.js +0 -35
  192. package/lib/Utils/crypto.js +0 -118
  193. package/lib/Utils/decode-wa-message.js +0 -350
  194. package/lib/Utils/event-buffer.js +0 -622
  195. package/lib/Utils/generics.js +0 -403
  196. package/lib/Utils/history.js +0 -134
  197. package/lib/Utils/identity-change-handler.js +0 -50
  198. package/lib/Utils/index.js +0 -23
  199. package/lib/Utils/link-preview.js +0 -85
  200. package/lib/Utils/logger.js +0 -3
  201. package/lib/Utils/lt-hash.js +0 -8
  202. package/lib/Utils/make-mutex.js +0 -33
  203. package/lib/Utils/message-composer.js +0 -273
  204. package/lib/Utils/message-retry-manager.js +0 -265
  205. package/lib/Utils/messages-media.js +0 -788
  206. package/lib/Utils/messages.js +0 -1260
  207. package/lib/Utils/noise-handler.js +0 -201
  208. package/lib/Utils/offline-node-processor.js +0 -40
  209. package/lib/Utils/pre-key-manager.js +0 -106
  210. package/lib/Utils/process-message.js +0 -630
  211. package/lib/Utils/reporting-utils.js +0 -258
  212. package/lib/Utils/signal.js +0 -201
  213. package/lib/Utils/stanza-ack.js +0 -38
  214. package/lib/Utils/sync-action-utils.js +0 -49
  215. package/lib/Utils/tc-token-utils.js +0 -163
  216. package/lib/Utils/use-multi-file-auth-state.js +0 -121
  217. package/lib/Utils/validate-connection.js +0 -203
  218. package/lib/WABinary/constants.js +0 -1301
  219. package/lib/WABinary/decode.js +0 -262
  220. package/lib/WABinary/encode.js +0 -220
  221. package/lib/WABinary/generic-utils.js +0 -204
  222. package/lib/WABinary/index.js +0 -6
  223. package/lib/WABinary/jid-utils.js +0 -98
  224. package/lib/WABinary/types.js +0 -2
  225. package/lib/WAM/BinaryInfo.js +0 -10
  226. package/lib/WAM/constants.js +0 -22853
  227. package/lib/WAM/encode.js +0 -150
  228. package/lib/WAM/index.js +0 -4
  229. package/lib/WAUSync/Protocols/USyncContactProtocol.js +0 -52
  230. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +0 -54
  231. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -27
  232. package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +0 -263
  233. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +0 -38
  234. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
  235. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -51
  236. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -29
  237. package/lib/WAUSync/Protocols/index.js +0 -6
  238. package/lib/WAUSync/USyncQuery.js +0 -98
  239. package/lib/WAUSync/USyncUser.js +0 -31
  240. package/lib/WAUSync/index.js +0 -4
@@ -0,0 +1,812 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.extractGroupMetadata = exports.makeGroupsSocket = void 0
4
+ const index_js_1 = require('../../WAProto/index.js')
5
+ const Types_1 = require('../Types')
6
+ const Utils_1 = require('../Utils')
7
+ const WABinary_1 = require('../WABinary')
8
+ const chats_1 = require('./chats')
9
+ const mex_1 = require('./mex')
10
+
11
+ const GROUP_MEX_QUERY_IDS = {
12
+ QUERY_INFO: '25530136513328492', // QueryGroupInfo
13
+ QUERY_INFO_BY_CODE: '24576337542042464', // QueryGroupInfoByCode
14
+ QUERY_BATCH: '26440064815661176', // QueryBatchGetGroups
15
+ QUERY_INVITE_LINK: '24558418350455204', // QueryInviteLink
16
+ QUERY_PARTICIPATING: '26664341543184776', // QueryParticipatingGroups
17
+ QUERY_SUGGESTED: '26012055225051916', // QuerySuggestedGroups
18
+ QUERY_LINKED: '25629003043401452', // QueryLinkedGroupInfo
19
+ QUERY_SUBGROUPS: '25554052094203120', // QuerySubgroups
20
+ ADD_PARTICIPANTS_V2: '32627550323510250', // AddParticipantsToGroupV2
21
+ ADD_PARTICIPANTS_V3: '26581073158212628', // AddParticipantsToGroupsV3
22
+ SET_PROPERTY: '24688994337458820', // SetGroupProperty
23
+ RESET_INVITE_LINK: '24812851838367452', // SetGroupResetInviteLink
24
+ CREATE_INVITE_CODE: '25207706598901440', // CreateInviteCode
25
+ CREATE_GROUP: '32341779532133480', // CreateGroup
26
+ ALLOW_NON_ADMIN_GROUP_CREATION: '32024438593867696', // AllowNonAdminGroupCreation
27
+ GET_INVITE_INFO: '24745668928467084', // GetInviteInfo
28
+ GET_PRE_REG_ADD_REQUESTS: '25018599251091280', // GetPreRegGroupAddRequestsQuery
29
+ GET_SUGGESTED_CONTACTS: '27208468032086900', // GetSuggestedContacts
30
+ STORE_INVITES_SMS: '25508574885415376', // GroupsStoreInvitesSMSMutation
31
+ LOG_SERVER_SENT_INVITE: '26580640204871220', // LogServerSentInviteIntent
32
+ QUERY_ONLINE_STATUS: '24599444653063564', // QueryOnlineStatusFromPDP
33
+ QUERY_ONLINE_STATUS_LAST_SEEN: '24653084284365540' // QueryOnlineStatusLastSeenFromPDP
34
+ }
35
+
36
+ const makeGroupsSocket = config => {
37
+ const sock = (0, chats_1.makeChatsSocket)(config)
38
+ const { authState, ev, query, generateMessageTag, upsertMessage } = sock
39
+ const groupQuery = async (jid, type, content) =>
40
+ query({
41
+ tag: 'iq',
42
+ attrs: {
43
+ type,
44
+ xmlns: 'w:g2',
45
+ to: jid
46
+ },
47
+ content
48
+ })
49
+ // Group metadata carries authoritative LID<->PN pairs for free (per-participant
50
+ // jid + phone_number/lid attrs). Persist them so the rest of the app can resolve
51
+ // PN<->LID without a separate usync round trip.
52
+ const persistParticipantLidMappings = async participantLists => {
53
+ const pairs = []
54
+ for (const participants of participantLists) {
55
+ for (const p of participants || []) {
56
+ if (p.phoneNumber) pairs.push({ lid: p.id, pn: p.phoneNumber })
57
+ else if (p.lid) pairs.push({ lid: p.lid, pn: p.id })
58
+ }
59
+ }
60
+ if (!pairs.length) return
61
+ try {
62
+ await sock.signalRepository.lidMapping.storeLIDPNMappings(pairs)
63
+ } catch (error) {
64
+ sock.logger?.warn?.({ error }, 'failed to store LID/PN mappings from group metadata')
65
+ }
66
+ }
67
+
68
+ const mexQuery = (variables, queryId, dataPath) =>
69
+ (0, mex_1.executeWMexQuery)(variables, queryId, dataPath, query, generateMessageTag)
70
+ const groupMetadata = async jid => {
71
+ const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }])
72
+ const metadata = (0, exports.extractGroupMetadata)(result)
73
+ persistParticipantLidMappings([metadata.participants]).catch(() => {})
74
+ return metadata
75
+ }
76
+ /**
77
+ * Acknowledge a group. Ported from WhatsApp Web's WASmaxGroupsAcknowledgeGroupRPC
78
+ * (`<iq to=jid xmlns=w:g2 type=set><ack/></iq>`).
79
+ */
80
+ const groupAcknowledge = async jid => {
81
+ await groupQuery(jid, 'set', [{ tag: 'ack', attrs: {} }])
82
+ }
83
+ /**
84
+ * Get the participants of a community's linked/sub groups. Ported from
85
+ * WhatsApp Web's WASmaxGroupsGetLinkedGroupsParticipantsRPC.
86
+ * @returns {Promise<Array<{ jid: string, phoneNumber?: string }>>}
87
+ */
88
+ const groupGetLinkedParticipants = async jid => {
89
+ const result = await groupQuery(jid, 'get', [{ tag: 'linked_groups_participants', attrs: {} }])
90
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'linked_groups_participants')
91
+ return (0, WABinary_1.getBinaryNodeChildren)(node, 'participant').map(p => ({
92
+ jid: p.attrs.jid,
93
+ phoneNumber: p.attrs.phone_number || p.attrs.pn || undefined
94
+ }))
95
+ }
96
+ /**
97
+ * Join a community's linked/sub group (may raise a membership approval request).
98
+ * Ported from WhatsApp Web's WASmaxGroupsJoinLinkedGroupRPC.
99
+ * @param {string} parentJid community/parent group to address
100
+ * @param {string} linkedGroupJid linked/sub group to join
101
+ * @param {string} [type]
102
+ */
103
+ const groupJoinLinked = async (parentJid, linkedGroupJid, type) => {
104
+ const result = await groupQuery(parentJid, 'set', [
105
+ { tag: 'join_linked_group', attrs: { jid: linkedGroupJid, ...(type ? { type } : {}) } }
106
+ ])
107
+ return { approvalRequested: !!(0, WABinary_1.getBinaryNodeChild)(result, 'membership_approval_request') }
108
+ }
109
+ /**
110
+ * Batch-fetch group profile pictures via w:g2. Ported from WhatsApp Web's
111
+ * WASmaxGroupsGetGroupProfilePicturesRPC. NOTE: untested against live WhatsApp —
112
+ * for a single group prefer profilePictureUrl().
113
+ * @param {string[]} jids group jids
114
+ * @param {'preview' | 'image'} [type]
115
+ */
116
+ const getGroupProfilePictures = async (jids, type = 'preview') => {
117
+ const result = await groupQuery(WABinary_1.S_WHATSAPP_NET, 'get', [
118
+ {
119
+ tag: 'pictures',
120
+ attrs: {},
121
+ content: jids.map(id => ({ tag: 'picture', attrs: { id, type } }))
122
+ }
123
+ ])
124
+ return (0, WABinary_1.getBinaryNodeChildren)(result, 'picture').map(pic => ({
125
+ jid: pic.attrs.id || pic.attrs.jid,
126
+ type: pic.attrs.type,
127
+ directPath: pic.attrs['direct_path'],
128
+ url: pic.attrs.url
129
+ }))
130
+ }
131
+ /**
132
+ * Create a sub-group suggestion for a community. Ported from WhatsApp Web's
133
+ * WASmaxGroupsCreateSubGroupSuggestionRPC. The suggestion body (new vs existing
134
+ * groups) is caller-provided. NOTE: untested against live WhatsApp.
135
+ * @param {string} parentJid community/parent group to address
136
+ * @param {Array<{ tag: string, attrs?: object, content?: any }>} suggestion child node(s)
137
+ */
138
+ const groupCreateSubGroupSuggestion = async (parentJid, suggestion) => {
139
+ await groupQuery(parentJid, 'set', [{ tag: 'sub_group_suggestion', attrs: {}, content: suggestion }])
140
+ }
141
+ /**
142
+ * Approve, reject, or cancel sub-group suggestions for a community. Ported from
143
+ * WhatsApp Web's WASmaxGroupsSubGroupSuggestionsActionRPC.
144
+ * approve/reject address suggestions by creator jid; cancel addresses them by
145
+ * the suggested group's jid (WASmaxOutGroupsSubGroupSuggestionsActionRequest).
146
+ * @param {string} parentJid community/parent group to address
147
+ * @param {'approve' | 'reject' | 'cancel'} action
148
+ * @param {Array<{ creator?: string, jid?: string }>} suggestions
149
+ */
150
+ const groupSubGroupSuggestionsAction = async (parentJid, action, suggestions) => {
151
+ await groupQuery(parentJid, 'set', [
152
+ {
153
+ tag: 'sub_group_suggestions_action',
154
+ attrs: {},
155
+ content: [
156
+ {
157
+ tag: action,
158
+ attrs: {},
159
+ content: suggestions.map(s => ({
160
+ tag: 'sub_group_suggestion',
161
+ attrs: action === 'cancel' ? { jid: s.jid } : { creator: s.creator }
162
+ }))
163
+ }
164
+ ]
165
+ }
166
+ ])
167
+ }
168
+ const groupFetchAllParticipating = async () => {
169
+ const result = await query({
170
+ tag: 'iq',
171
+ attrs: {
172
+ to: '@g.us',
173
+ xmlns: 'w:g2',
174
+ type: 'get'
175
+ },
176
+ content: [
177
+ {
178
+ tag: 'participating',
179
+ attrs: {},
180
+ content: [
181
+ { tag: 'participants', attrs: {} },
182
+ { tag: 'description', attrs: {} }
183
+ ]
184
+ }
185
+ ]
186
+ })
187
+ const data = {}
188
+ const groupsChild = (0, WABinary_1.getBinaryNodeChild)(result, 'groups')
189
+ if (groupsChild) {
190
+ const groups = (0, WABinary_1.getBinaryNodeChildren)(groupsChild, 'group')
191
+ for (const groupNode of groups) {
192
+ const meta = (0, exports.extractGroupMetadata)({
193
+ tag: 'result',
194
+ attrs: {},
195
+ content: [groupNode]
196
+ })
197
+ data[meta.id] = meta
198
+ }
199
+ }
200
+ const allGroups = Object.values(data)
201
+ persistParticipantLidMappings(allGroups.map(g => g.participants)).catch(() => {})
202
+ sock.ev.emit('groups.update', allGroups)
203
+ return data
204
+ }
205
+ sock.ws.on('CB:ib,,dirty', async node => {
206
+ const { attrs } = (0, WABinary_1.getBinaryNodeChild)(node, 'dirty')
207
+ if (attrs.type !== 'groups') {
208
+ return
209
+ }
210
+ await groupFetchAllParticipating()
211
+ await sock.cleanDirtyBits('groups')
212
+ })
213
+ return {
214
+ ...sock,
215
+ groupMetadata,
216
+ groupAcknowledge,
217
+ groupGetLinkedParticipants,
218
+ groupJoinLinked,
219
+ getGroupProfilePictures,
220
+ groupCreateSubGroupSuggestion,
221
+ groupSubGroupSuggestionsAction,
222
+ groupCreate: async (subject, participants) => {
223
+ const key = (0, Utils_1.generateMessageIDV2)()
224
+ const result = await groupQuery('@g.us', 'set', [
225
+ {
226
+ tag: 'create',
227
+ attrs: {
228
+ subject,
229
+ key
230
+ },
231
+ content: participants.map(jid => ({
232
+ tag: 'participant',
233
+ attrs: { jid }
234
+ }))
235
+ }
236
+ ])
237
+ return (0, exports.extractGroupMetadata)(result)
238
+ },
239
+ groupLeave: async id => {
240
+ await groupQuery('@g.us', 'set', [
241
+ {
242
+ tag: 'leave',
243
+ attrs: {},
244
+ content: [{ tag: 'group', attrs: { id } }]
245
+ }
246
+ ])
247
+ },
248
+ groupUpdateSubject: async (jid, subject) => {
249
+ await groupQuery(jid, 'set', [
250
+ {
251
+ tag: 'subject',
252
+ attrs: {},
253
+ content: Buffer.from(subject, 'utf-8')
254
+ }
255
+ ])
256
+ },
257
+ groupRequestParticipantsList: async jid => {
258
+ const result = await groupQuery(jid, 'get', [
259
+ {
260
+ tag: 'membership_approval_requests',
261
+ attrs: {}
262
+ }
263
+ ])
264
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'membership_approval_requests')
265
+ const participants = (0, WABinary_1.getBinaryNodeChildren)(node, 'membership_approval_request')
266
+ return participants.map(v => v.attrs)
267
+ },
268
+ groupRequestParticipantsUpdate: async (jid, participants, action) => {
269
+ const result = await groupQuery(jid, 'set', [
270
+ {
271
+ tag: 'membership_requests_action',
272
+ attrs: {},
273
+ content: [
274
+ {
275
+ tag: action,
276
+ attrs: {},
277
+ content: participants.map(jid => ({
278
+ tag: 'participant',
279
+ attrs: { jid }
280
+ }))
281
+ }
282
+ ]
283
+ }
284
+ ])
285
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'membership_requests_action')
286
+ const nodeAction = (0, WABinary_1.getBinaryNodeChild)(node, action)
287
+ const participantsAffected = (0, WABinary_1.getBinaryNodeChildren)(nodeAction, 'participant')
288
+ return participantsAffected.map(p => {
289
+ return { status: p.attrs.error || '200', jid: p.attrs.jid }
290
+ })
291
+ },
292
+ groupParticipantsUpdate: async (jid, participants, action) => {
293
+ const result = await groupQuery(jid, 'set', [
294
+ {
295
+ tag: action,
296
+ attrs: {},
297
+ content: participants.map(jid => ({
298
+ tag: 'participant',
299
+ attrs: { jid }
300
+ }))
301
+ }
302
+ ])
303
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, action)
304
+ const participantsAffected = (0, WABinary_1.getBinaryNodeChildren)(node, 'participant')
305
+ return participantsAffected.map(p => {
306
+ return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p }
307
+ })
308
+ },
309
+ groupUpdateDescription: async (jid, description) => {
310
+ const metadata = await groupMetadata(jid)
311
+ const prev = metadata.descId ?? null
312
+ await groupQuery(jid, 'set', [
313
+ {
314
+ tag: 'description',
315
+ attrs: {
316
+ ...(description ? { id: (0, Utils_1.generateMessageIDV2)() } : { delete: 'true' }),
317
+ ...(prev ? { prev } : {})
318
+ },
319
+ content: description ? [{ tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') }] : undefined
320
+ }
321
+ ])
322
+ },
323
+ groupInviteCode: async jid => {
324
+ const result = await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }])
325
+ const inviteNode = (0, WABinary_1.getBinaryNodeChild)(result, 'invite')
326
+ return inviteNode?.attrs.code
327
+ },
328
+ groupRevokeInvite: async jid => {
329
+ const result = await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }])
330
+ const inviteNode = (0, WABinary_1.getBinaryNodeChild)(result, 'invite')
331
+ return inviteNode?.attrs.code
332
+ },
333
+ groupAcceptInvite: async code => {
334
+ const results = await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }])
335
+ const result = (0, WABinary_1.getBinaryNodeChild)(results, 'group')
336
+ return result?.attrs.jid
337
+ },
338
+ /**
339
+ * revoke a v4 invite for someone
340
+ * @param groupJid group jid
341
+ * @param invitedJid jid of person you invited
342
+ * @returns true if successful
343
+ */
344
+ groupRevokeInviteV4: async (groupJid, invitedJid) => {
345
+ const result = await groupQuery(groupJid, 'set', [
346
+ { tag: 'revoke', attrs: {}, content: [{ tag: 'participant', attrs: { jid: invitedJid } }] }
347
+ ])
348
+ return !!result
349
+ },
350
+ /**
351
+ * accept a GroupInviteMessage
352
+ * @param key the key of the invite message, or optionally only provide the jid of the person who sent the invite
353
+ * @param inviteMessage the message to accept
354
+ */
355
+ groupAcceptInviteV4: ev.createBufferedFunction(async (key, inviteMessage) => {
356
+ key = typeof key === 'string' ? { remoteJid: key } : key
357
+ const results = await groupQuery(inviteMessage.groupJid, 'set', [
358
+ {
359
+ tag: 'accept',
360
+ attrs: {
361
+ code: inviteMessage.inviteCode,
362
+ expiration: inviteMessage.inviteExpiration.toString(),
363
+ admin: key.remoteJid
364
+ }
365
+ }
366
+ ])
367
+ // if we have the full message key
368
+ // update the invite message to be expired
369
+ if (key.id) {
370
+ // create new invite message that is expired
371
+ inviteMessage = index_js_1.proto.Message.GroupInviteMessage.fromObject(inviteMessage)
372
+ inviteMessage.inviteExpiration = 0
373
+ inviteMessage.inviteCode = ''
374
+ ev.emit('messages.update', [
375
+ {
376
+ key,
377
+ update: {
378
+ message: {
379
+ groupInviteMessage: inviteMessage
380
+ }
381
+ }
382
+ }
383
+ ])
384
+ }
385
+ // generate the group add message
386
+ await upsertMessage(
387
+ {
388
+ key: {
389
+ remoteJid: inviteMessage.groupJid,
390
+ id: (0, Utils_1.generateMessageIDV2)(sock.user?.id),
391
+ fromMe: false,
392
+ participant: key.remoteJid
393
+ },
394
+ messageStubType: Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD,
395
+ messageStubParameters: [JSON.stringify(authState.creds.me)],
396
+ participant: key.remoteJid,
397
+ messageTimestamp: (0, Utils_1.unixTimestampSeconds)()
398
+ },
399
+ 'notify'
400
+ )
401
+ return results.attrs.from
402
+ }),
403
+ groupGetInviteInfo: async code => {
404
+ const results = await groupQuery('@g.us', 'get', [{ tag: 'invite', attrs: { code } }])
405
+ return (0, exports.extractGroupMetadata)(results)
406
+ },
407
+ groupToggleEphemeral: async (jid, ephemeralExpiration) => {
408
+ const content = ephemeralExpiration
409
+ ? { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } }
410
+ : { tag: 'not_ephemeral', attrs: {} }
411
+ await groupQuery(jid, 'set', [content])
412
+ },
413
+ groupSettingUpdate: async (jid, setting) => {
414
+ await groupQuery(jid, 'set', [{ tag: setting, attrs: {} }])
415
+ },
416
+ groupMemberAddMode: async (jid, mode) => {
417
+ await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }])
418
+ },
419
+ groupJoinApprovalMode: async (jid, mode) => {
420
+ await groupQuery(jid, 'set', [
421
+ { tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state: mode } }] }
422
+ ])
423
+ },
424
+ /**
425
+ * Get past participants of a group (left/removed members)
426
+ */
427
+ groupGetPastParticipants: async jid => {
428
+ const result = await groupQuery(jid, 'get', [{ tag: 'past_participants', attrs: {} }])
429
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'past_participants')
430
+ if (!node) return []
431
+ const participants = (0, WABinary_1.getBinaryNodeChildren)(node, 'past_participant')
432
+ return participants.map(p => ({
433
+ jid: p.attrs.jid,
434
+ leaveReason: p.attrs.reason,
435
+ leaveTimestamp: p.attrs.t ? Number(p.attrs.t) : undefined
436
+ }))
437
+ },
438
+ /**
439
+ * Create a subgroup within a community
440
+ */
441
+ groupCreateSubgroup: async (communityJid, subject, participants = []) => {
442
+ const key = (0, Utils_1.generateMessageIDV2)()
443
+ const result = await groupQuery('@g.us', 'set', [
444
+ {
445
+ tag: 'create',
446
+ attrs: { subject, key },
447
+ content: [
448
+ ...participants.map(jid => ({ tag: 'participant', attrs: { jid } })),
449
+ { tag: 'linked_parent', attrs: { jid: communityJid } }
450
+ ]
451
+ }
452
+ ])
453
+ return (0, exports.extractGroupMetadata)(result)
454
+ },
455
+ /**
456
+ * Link an existing group to a community
457
+ */
458
+ groupLinkToCommunity: async (communityJid, groupJid) => {
459
+ await groupQuery(communityJid, 'set', [
460
+ {
461
+ tag: 'links',
462
+ attrs: {},
463
+ content: [
464
+ { tag: 'link', attrs: { link_type: 'sub_group' }, content: [{ tag: 'group', attrs: { jid: groupJid } }] }
465
+ ]
466
+ }
467
+ ])
468
+ },
469
+ /**
470
+ * Unlink a group from a community
471
+ */
472
+ groupUnlinkFromCommunity: async (communityJid, groupJid) => {
473
+ await groupQuery(communityJid, 'set', [
474
+ {
475
+ tag: 'unlinks',
476
+ attrs: {},
477
+ content: [
478
+ { tag: 'unlink', attrs: { link_type: 'sub_group' }, content: [{ tag: 'group', attrs: { jid: groupJid } }] }
479
+ ]
480
+ }
481
+ ])
482
+ },
483
+ /**
484
+ * Set a member label/tag in a group
485
+ * @param jid group JID
486
+ * @param participantJid participant JID to label
487
+ * @param label the label string ('' to remove)
488
+ */
489
+ groupSetMemberLabel: async (jid, participantJid, label) => {
490
+ await groupQuery(jid, 'set', [
491
+ {
492
+ tag: 'member_add_mode',
493
+ attrs: {},
494
+ content: [
495
+ {
496
+ tag: 'participant',
497
+ attrs: { jid: participantJid, label: label || '' }
498
+ }
499
+ ]
500
+ }
501
+ ])
502
+ },
503
+ /**
504
+ * Get community-linked subgroups for a community JID
505
+ */
506
+ groupGetLinkedSubgroups: async communityJid => {
507
+ const result = await groupQuery(communityJid, 'get', [{ tag: 'links', attrs: { link_type: 'sub_group' } }])
508
+ const linksNode = (0, WABinary_1.getBinaryNodeChild)(result, 'links')
509
+ if (!linksNode) return []
510
+ return (0, WABinary_1.getBinaryNodeChildren)(linksNode, 'link')
511
+ .map(link => {
512
+ const group = (0, WABinary_1.getBinaryNodeChild)(link, 'group')
513
+ return { jid: group?.attrs?.jid, linkType: link.attrs?.link_type }
514
+ })
515
+ .filter(l => !!l.jid)
516
+ },
517
+ groupFetchAllParticipating,
518
+
519
+ // ── MEX queries (JSON responses) ──────────────────────────────────────
520
+
521
+ /**
522
+ * Fetch group info via MEX (richer than IQ — includes invite link, LID addressing, etc.)
523
+ * @param {string} jid - Group JID
524
+ */
525
+ groupQueryInfo: jid => mexQuery({ group_id: jid }, GROUP_MEX_QUERY_IDS.QUERY_INFO, 'xwa2_group_query_by_id'),
526
+
527
+ /**
528
+ * Fetch group info by invite code via MEX.
529
+ * @param {string} code - Group invite code (without the link prefix)
530
+ */
531
+ groupQueryInfoByCode: code =>
532
+ mexQuery(
533
+ { group_input: { invite_code: code } },
534
+ GROUP_MEX_QUERY_IDS.QUERY_INFO_BY_CODE,
535
+ 'xwa2_group_query_by_id'
536
+ ),
537
+
538
+ /**
539
+ * Fetch multiple groups at once via MEX.
540
+ * @param {string[]} jids - Array of group JIDs
541
+ */
542
+ groupQueryBatch: jids =>
543
+ mexQuery(
544
+ { groups_input: jids.map(group_id => ({ group_id })) },
545
+ GROUP_MEX_QUERY_IDS.QUERY_BATCH,
546
+ 'xwa2_group_query_batch'
547
+ ),
548
+
549
+ /**
550
+ * Fetch invite link info via MEX (includes expiration, creator, etc.)
551
+ * @param {string} jid - Group JID
552
+ */
553
+ groupQueryInviteLink: jid =>
554
+ mexQuery({ group_input: { group_id: jid } }, GROUP_MEX_QUERY_IDS.QUERY_INVITE_LINK, 'xwa2_group_query_by_id'),
555
+
556
+ /**
557
+ * Fetch all groups the current user is participating in via MEX.
558
+ * Returns richer data than the IQ-based groupFetchAllParticipating.
559
+ */
560
+ groupQueryParticipating: () =>
561
+ mexQuery({}, GROUP_MEX_QUERY_IDS.QUERY_PARTICIPATING, 'xwa2_group_query_participating'),
562
+
563
+ /**
564
+ * Fetch suggested groups (community sub-group suggestions) via MEX.
565
+ * @param {string} communityJid - Community JID to get suggestions for
566
+ */
567
+ groupQuerySuggested: communityJid =>
568
+ mexQuery(
569
+ { group_input: { group_id: communityJid } },
570
+ GROUP_MEX_QUERY_IDS.QUERY_SUGGESTED,
571
+ 'xwa2_group_query_by_id'
572
+ ),
573
+
574
+ /**
575
+ * Fetch linked subgroup info for a community group via MEX.
576
+ * @param {string} jid - Group or community JID
577
+ */
578
+ groupQueryLinked: jid =>
579
+ mexQuery({ group_input: { group_id: jid } }, GROUP_MEX_QUERY_IDS.QUERY_LINKED, 'xwa2_group_query_by_id'),
580
+
581
+ /**
582
+ * Fetch subgroups of a community via MEX.
583
+ * @param {string} communityJid - Community JID
584
+ */
585
+ groupQuerySubgroups: communityJid =>
586
+ mexQuery(
587
+ { group_input: { group_id: communityJid } },
588
+ GROUP_MEX_QUERY_IDS.QUERY_SUBGROUPS,
589
+ 'xwa2_group_query_by_id'
590
+ ),
591
+
592
+ /**
593
+ * Add participants to a group via MEX (V2 — supports LID, privacy metadata).
594
+ * Falls back to the IQ-based groupParticipantsUpdate for older servers.
595
+ * @param {string} jid - Group JID
596
+ * @param {string[]} participants - Array of JIDs to add
597
+ */
598
+ groupAddParticipantsMex: (jid, participants) =>
599
+ mexQuery(
600
+ { group_id: jid, participants: participants.map(p => ({ user_jid: p })) },
601
+ GROUP_MEX_QUERY_IDS.ADD_PARTICIPANTS_V2,
602
+ 'xwa2_group_add_participants'
603
+ ),
604
+
605
+ /**
606
+ * Set a group property via MEX.
607
+ * Known properties: member_add_mode, membership_approval_mode_enabled, member_share_group_history_mode
608
+ * @param {string} jid - Group JID
609
+ * @param {string} property - Property name
610
+ * @param {*} value - Property value
611
+ */
612
+ groupSetProperty: (jid, property, value) =>
613
+ mexQuery({ group_id: jid, [property]: value }, GROUP_MEX_QUERY_IDS.SET_PROPERTY, 'xwa2_group_update_property'),
614
+
615
+ /**
616
+ * Reset a group's invite link via MEX (generates new code, invalidates old one).
617
+ * @param {string} jid - Group JID
618
+ */
619
+ groupResetInviteLinkMex: jid =>
620
+ mexQuery({ group_jid: jid }, GROUP_MEX_QUERY_IDS.RESET_INVITE_LINK, 'xwa2_group_reset_invite_link'),
621
+
622
+ /**
623
+ * Create a group via MEX.
624
+ * Confirmed from CreateGroup mutation — input: { subject, participants: [{jid}] }
625
+ * @param {string} subject - Group name
626
+ * @param {string[]} participantJids
627
+ */
628
+ groupCreateMex: (subject, participantJids) =>
629
+ mexQuery(
630
+ { input: { subject, participants: participantJids.map(jid => ({ jid })) } },
631
+ GROUP_MEX_QUERY_IDS.CREATE_GROUP,
632
+ 'xwa2_group_create'
633
+ ),
634
+
635
+ /**
636
+ * Allow non-admin community members to create subgroups.
637
+ * @param {string} communityJid - Community JID
638
+ * @param {boolean} allow
639
+ */
640
+ groupAllowNonAdminCreation: (communityJid, allow) =>
641
+ mexQuery(
642
+ { group_jid: communityJid, allow_non_admin_sub_group_creation: allow },
643
+ GROUP_MEX_QUERY_IDS.ALLOW_NON_ADMIN_GROUP_CREATION,
644
+ 'xwa2_group_allow_non_admin_creation'
645
+ ),
646
+
647
+ /**
648
+ * Get info about a group invite link (before joining).
649
+ * @param {string} inviteCode - The raw invite code (not full URL)
650
+ */
651
+ groupGetInviteInfo: inviteCode =>
652
+ mexQuery({ invite_code: inviteCode }, GROUP_MEX_QUERY_IDS.GET_INVITE_INFO, 'xwa2_group_get_invite_info'),
653
+
654
+ /**
655
+ * Fetch pending add requests for pre-registration group invites.
656
+ * @param {string} jid - Group JID
657
+ */
658
+ groupPreRegAddRequests: jid =>
659
+ mexQuery({ group_jid: jid }, GROUP_MEX_QUERY_IDS.GET_PRE_REG_ADD_REQUESTS, 'xwa2_group_pre_reg_add_requests'),
660
+
661
+ /**
662
+ * Get suggested contacts to add to a group.
663
+ * @param {string} jid - Group JID
664
+ */
665
+ groupSuggestedContacts: jid =>
666
+ mexQuery({ group_jid: jid }, GROUP_MEX_QUERY_IDS.GET_SUGGESTED_CONTACTS, 'xwa2_group_suggested_contacts'),
667
+
668
+ /**
669
+ * Store SMS invite links for a group.
670
+ * @param {string} jid - Group JID
671
+ * @param {{ phone: string, inviteCode: string }[]} invites
672
+ */
673
+ groupStoreInvitesSms: (jid, invites) =>
674
+ mexQuery(
675
+ { group_jid: jid, invites: invites.map(({ phone, inviteCode }) => ({ phone, invite_code: inviteCode })) },
676
+ GROUP_MEX_QUERY_IDS.STORE_INVITES_SMS,
677
+ 'xwa2_group_store_invites_sms'
678
+ ),
679
+
680
+ /**
681
+ * Log a server-sent invite intent (analytics).
682
+ * @param {string} jid - Group JID
683
+ * @param {string} inviteCode
684
+ */
685
+ groupLogServerSentInvite: (jid, inviteCode) =>
686
+ mexQuery(
687
+ { group_jid: jid, invite_code: inviteCode },
688
+ GROUP_MEX_QUERY_IDS.LOG_SERVER_SENT_INVITE,
689
+ 'xwa2_group_log_server_sent_invite'
690
+ ),
691
+
692
+ /**
693
+ * Query online status of users from PDP.
694
+ * @param {string[]} jids - User JIDs
695
+ */
696
+ queryOnlineStatus: jids => mexQuery({ jids }, GROUP_MEX_QUERY_IDS.QUERY_ONLINE_STATUS, 'xwa2_query_online_status'),
697
+
698
+ /**
699
+ * Query online status and last seen of users from PDP.
700
+ * @param {string[]} jids - User JIDs
701
+ */
702
+ queryOnlineStatusLastSeen: jids =>
703
+ mexQuery({ jids }, GROUP_MEX_QUERY_IDS.QUERY_ONLINE_STATUS_LAST_SEEN, 'xwa2_query_online_status_last_seen'),
704
+
705
+ GROUP_MEX_QUERY_IDS
706
+ }
707
+ }
708
+ exports.makeGroupsSocket = makeGroupsSocket
709
+ const extractGroupMetadata = result => {
710
+ const group = (0, WABinary_1.getBinaryNodeChild)(result, 'group')
711
+ const descChild = (0, WABinary_1.getBinaryNodeChild)(group, 'description')
712
+ let desc
713
+ let descId
714
+ let descOwner
715
+ let descOwnerPn
716
+ let descOwnerUsername
717
+ let descTime
718
+ if (descChild) {
719
+ desc = (0, WABinary_1.getBinaryNodeChildString)(descChild, 'body')
720
+ descOwner = descChild.attrs.participant ? (0, WABinary_1.jidNormalizedUser)(descChild.attrs.participant) : undefined
721
+ descOwnerPn = descChild.attrs.participant_pn
722
+ ? (0, WABinary_1.jidNormalizedUser)(descChild.attrs.participant_pn)
723
+ : undefined
724
+ descOwnerUsername = descChild.attrs.participant_username || undefined
725
+ descTime = +descChild.attrs.t
726
+ descId = descChild.attrs.id
727
+ }
728
+ const groupId = group.attrs.id.includes('@') ? group.attrs.id : (0, WABinary_1.jidEncode)(group.attrs.id, 'g.us')
729
+ const eph = (0, WABinary_1.getBinaryNodeChild)(group, 'ephemeral')?.attrs.expiration
730
+ const memberAddMode = (0, WABinary_1.getBinaryNodeChildString)(group, 'member_add_mode') === 'all_member_add'
731
+ const linkedParentNode = (0, WABinary_1.getBinaryNodeChild)(group, 'linked_parent')
732
+ const communityMemberAddGroupNode = (0, WABinary_1.getBinaryNodeChild)(group, 'allow_non_admin_sub_group_creation')
733
+ const subGroupVisibilityNode = (0, WABinary_1.getBinaryNodeChild)(group, 'sub_groups_list')
734
+ const membershipApprovalNode = (0, WABinary_1.getBinaryNodeChild)(group, 'membership_approval_mode')
735
+ const capiNode = (0, WABinary_1.getBinaryNodeChild)(group, 'capi')
736
+ const appealStatusNode = (0, WABinary_1.getBinaryNodeChild)(group, 'appeal_status')
737
+ const defaultSubGroupNode = (0, WABinary_1.getBinaryNodeChild)(group, 'default_sub_group')
738
+ const generalChatNode = (0, WABinary_1.getBinaryNodeChild)(group, 'general_chat')
739
+ const hiddenGroupNode = (0, WABinary_1.getBinaryNodeChild)(group, 'hidden_group')
740
+ const metadata = {
741
+ id: groupId,
742
+ notify: group.attrs.notify,
743
+ addressingMode:
744
+ group.attrs.addressing_mode === 'lid' ? Types_1.WAMessageAddressingMode.LID : Types_1.WAMessageAddressingMode.PN,
745
+ subject: group.attrs.subject,
746
+ subjectOwner: group.attrs.s_o,
747
+ subjectOwnerPn: group.attrs.s_o_pn,
748
+ subjectOwnerUsername: group.attrs.s_o_username,
749
+ subjectTime: +group.attrs.s_t,
750
+ size: group.attrs.size ? +group.attrs.size : (0, WABinary_1.getBinaryNodeChildren)(group, 'participant').length,
751
+ creation: +group.attrs.creation,
752
+ owner: group.attrs.creator ? (0, WABinary_1.jidNormalizedUser)(group.attrs.creator) : undefined,
753
+ ownerPn: group.attrs.creator_pn ? (0, WABinary_1.jidNormalizedUser)(group.attrs.creator_pn) : undefined,
754
+ ownerUsername: group.attrs.creator_username || undefined,
755
+ owner_country_code: group.attrs.creator_country_code,
756
+ desc,
757
+ descId,
758
+ descOwner,
759
+ descOwnerPn,
760
+ descOwnerUsername,
761
+ descTime,
762
+ linkedParent: linkedParentNode?.attrs.jid || undefined,
763
+ restrict: !!(0, WABinary_1.getBinaryNodeChild)(group, 'locked'),
764
+ announce: !!(0, WABinary_1.getBinaryNodeChild)(group, 'announcement'),
765
+ isCommunity: !!(0, WABinary_1.getBinaryNodeChild)(group, 'parent'),
766
+ isCommunityAnnounce: !!(0, WABinary_1.getBinaryNodeChild)(group, 'default_sub_group'),
767
+ joinApprovalMode: !!membershipApprovalNode,
768
+ memberAddMode,
769
+ memberShareHistoryMode:
770
+ (0, WABinary_1.getBinaryNodeChildString)(group, 'member_share_group_history_mode') || undefined,
771
+ memberLinkMode: (0, WABinary_1.getBinaryNodeChildString)(group, 'member_link_mode') || undefined,
772
+ limitSharing: !!(0, WABinary_1.getBinaryNodeChild)(group, 'limit_sharing_enabled'),
773
+ communityMemberAddGroupMode: communityMemberAddGroupNode?.attrs.state || undefined,
774
+ capiCreatedGroup: !!capiNode || undefined,
775
+ appealStatus: appealStatusNode?.attrs.type || undefined,
776
+ isSubGroupHidden: group.attrs.sub_group_visibility === 'hidden' || undefined,
777
+ membershipApprovalMode: group.attrs.membership_approval_mode || undefined,
778
+ joinPermissions: group.attrs.join_permissions || undefined,
779
+ isDefaultSubgroup: !!defaultSubGroupNode || undefined,
780
+ isGeneralSubgroup: !!generalChatNode || undefined,
781
+ isHiddenSubgroup: !!hiddenGroupNode || undefined,
782
+ participants: (0, WABinary_1.getBinaryNodeChildren)(group, 'participant').map(({ attrs }) => {
783
+ // extractGroupMetadata is sync and has no socket in scope to persist with;
784
+ // callers (groupMetadata, groupFetchAllParticipating) persist the LID/PN
785
+ // pairs surfaced here via persistParticipantLidMappings.
786
+ return {
787
+ id: attrs.jid,
788
+ phoneNumber:
789
+ (0, WABinary_1.isLidUser)(attrs.jid) && (0, WABinary_1.isPnUser)(attrs.phone_number)
790
+ ? attrs.phone_number
791
+ : undefined,
792
+ lid: (0, WABinary_1.isPnUser)(attrs.jid) && (0, WABinary_1.isLidUser)(attrs.lid) ? attrs.lid : undefined,
793
+ username: attrs.participant_username || attrs.username || undefined,
794
+ admin: attrs.type || null,
795
+ memberLabel: attrs.label || undefined,
796
+ memberLabelTimestamp: attrs.label_ts ? +attrs.label_ts : undefined,
797
+ isBanned: attrs.error === '402' || attrs.ban === 'true' || undefined,
798
+ uuid: attrs.uuid || attrs.participant_uuid || undefined
799
+ }
800
+ }),
801
+ bannedParticipants: (0, WABinary_1.getBinaryNodeChildren)(group, 'participant')
802
+ .filter(({ attrs }) => attrs.error === '402' || attrs.ban === 'true')
803
+ .map(({ attrs }) => ({
804
+ id: attrs.jid,
805
+ phoneNumber: attrs.phone_number || undefined,
806
+ lid: attrs.lid || undefined
807
+ })),
808
+ ephemeralDuration: eph ? +eph : undefined
809
+ }
810
+ return metadata
811
+ }
812
+ exports.extractGroupMetadata = extractGroupMetadata