@badzz88/baileys 8.4.6 → 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 (250) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1055 -337
  3. package/WAProto/WAProto.proto +850 -32
  4. package/WAProto/index.d.ts +4913 -25
  5. package/WAProto/index.js +14074 -98
  6. package/package.json +96 -131
  7. package/src/Defaults/index.js +201 -0
  8. package/src/Defaults/phonenumber-mcc.json +223 -0
  9. package/src/Signal/Group/ciphertext-message.js +15 -0
  10. package/src/Signal/Group/group-session-builder.js +92 -0
  11. package/src/Signal/Group/group_cipher.js +89 -0
  12. package/src/Signal/Group/index.js +136 -0
  13. package/src/Signal/Group/keyhelper.js +73 -0
  14. package/src/Signal/Group/sender-chain-key.js +32 -0
  15. package/src/Signal/Group/sender-key-distribution-message.js +66 -0
  16. package/src/Signal/Group/sender-key-message.js +69 -0
  17. package/src/Signal/Group/sender-key-name.js +50 -0
  18. package/src/Signal/Group/sender-key-record.js +44 -0
  19. package/src/Signal/Group/sender-key-state.js +97 -0
  20. package/src/Signal/Group/sender-message-key.js +30 -0
  21. package/src/Signal/libsignal.js +470 -0
  22. package/src/Signal/lid-mapping.js +262 -0
  23. package/src/Socket/Client/index.js +30 -0
  24. package/src/Socket/Client/types.js +13 -0
  25. package/src/Socket/Client/websocket.js +62 -0
  26. package/src/Socket/aigroups.js +240 -0
  27. package/src/Socket/business.js +422 -0
  28. package/src/Socket/chats.js +2374 -0
  29. package/src/Socket/communities.js +580 -0
  30. package/src/Socket/graphql.js +915 -0
  31. package/src/Socket/groups.js +812 -0
  32. package/src/Socket/index.js +37 -0
  33. package/src/Socket/interactive-handler.js +579 -0
  34. package/src/Socket/interop.js +566 -0
  35. package/src/Socket/managed-account.js +214 -0
  36. package/src/Socket/messages-recv.js +3012 -0
  37. package/src/Socket/messages-send.js +2163 -0
  38. package/{lib → src}/Socket/mex.js +11 -5
  39. package/src/Socket/newsletter.js +1057 -0
  40. package/src/Socket/privacy.js +452 -0
  41. package/src/Socket/registration.js +434 -0
  42. package/src/Socket/socket.js +1079 -0
  43. package/src/Socket/text-router.js +67 -0
  44. package/src/Socket/username.js +234 -0
  45. package/src/Store/index.js +36 -0
  46. package/src/Store/make-cache-manager-store.js +90 -0
  47. package/src/Store/make-in-memory-store.js +506 -0
  48. package/src/Store/make-ordered-dictionary.js +81 -0
  49. package/src/Store/object-repository.js +29 -0
  50. package/src/Types/Auth.js +38 -0
  51. package/src/Types/Bussines.js +2 -0
  52. package/src/Types/Call.js +2 -0
  53. package/src/Types/Chat.js +4 -0
  54. package/src/Types/Contact.js +2 -0
  55. package/src/Types/Events.js +2 -0
  56. package/src/Types/GroupMetadata.js +2 -0
  57. package/src/Types/Label.js +27 -0
  58. package/src/Types/LabelAssociation.js +9 -0
  59. package/src/Types/Message.js +95 -0
  60. package/src/Types/Newsletter.js +152 -0
  61. package/src/Types/Product.js +2 -0
  62. package/src/Types/Signal.js +2 -0
  63. package/src/Types/Socket.js +2 -0
  64. package/src/Types/State.js +70 -0
  65. package/src/Types/USync.js +2 -0
  66. package/src/Types/index.js +54 -0
  67. package/src/Utils/auth-utils.js +306 -0
  68. package/src/Utils/browser-utils.js +114 -0
  69. package/src/Utils/business.js +247 -0
  70. package/src/Utils/chat-utils.js +1272 -0
  71. package/src/Utils/consumer-application.js +107 -0
  72. package/src/Utils/crypto.js +125 -0
  73. package/src/Utils/decode-wa-message.js +808 -0
  74. package/src/Utils/event-buffer.js +586 -0
  75. package/src/Utils/generics.js +640 -0
  76. package/src/Utils/group-history.js +60 -0
  77. package/src/Utils/history.js +244 -0
  78. package/src/Utils/identity-change-handler.js +52 -0
  79. package/src/Utils/index.js +53 -0
  80. package/src/Utils/jid-display-normalization.js +218 -0
  81. package/src/Utils/link-preview.js +143 -0
  82. package/src/Utils/logger.js +9 -0
  83. package/src/Utils/lt-hash.js +10 -0
  84. package/src/Utils/make-mutex.js +36 -0
  85. package/src/Utils/message-composer.js +479 -0
  86. package/src/Utils/message-inspect.js +400 -0
  87. package/src/Utils/message-retry-manager.js +231 -0
  88. package/src/Utils/messages-media.js +943 -0
  89. package/src/Utils/messages.js +2490 -0
  90. package/src/Utils/meta-ai-msmsg.js +133 -0
  91. package/src/Utils/noise-handler.js +194 -0
  92. package/src/Utils/offline-node-processor.js +42 -0
  93. package/src/Utils/pre-key-manager.js +107 -0
  94. package/src/Utils/process-message.js +1047 -0
  95. package/src/Utils/reporting-utils.js +262 -0
  96. package/src/Utils/signal.js +192 -0
  97. package/src/Utils/stanza-ack.js +74 -0
  98. package/src/Utils/sync-action-utils.js +54 -0
  99. package/src/Utils/tc-token-utils.js +161 -0
  100. package/src/Utils/use-multi-file-auth-state.js +121 -0
  101. package/src/Utils/validate-connection.js +248 -0
  102. package/src/Utils/voip-rekey.js +22 -0
  103. package/src/WABinary/constants.js +1304 -0
  104. package/src/WABinary/decode.js +377 -0
  105. package/src/WABinary/encode.js +58 -0
  106. package/src/WABinary/generic-utils.js +148 -0
  107. package/src/WABinary/index.js +33 -0
  108. package/src/WABinary/jid-utils.js +374 -0
  109. package/src/WABinary/types.js +2 -0
  110. package/src/WAM/BinaryInfo.js +13 -0
  111. package/src/WAM/constants.js +39486 -0
  112. package/src/WAM/encode.js +142 -0
  113. package/src/WAM/index.js +31 -0
  114. package/src/WAUSync/Protocols/USyncBotProfileProtocol.js +55 -0
  115. package/src/WAUSync/Protocols/USyncBusinessProtocol.js +100 -0
  116. package/src/WAUSync/Protocols/USyncContactProtocol.js +60 -0
  117. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +65 -0
  118. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -0
  119. package/src/WAUSync/Protocols/USyncFeatureProtocol.js +74 -0
  120. package/src/WAUSync/Protocols/USyncLIDProtocol.js +31 -0
  121. package/src/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
  122. package/src/WAUSync/Protocols/USyncSidelistProtocol.js +29 -0
  123. package/src/WAUSync/Protocols/USyncStatusProtocol.js +44 -0
  124. package/src/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
  125. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +28 -0
  126. package/src/WAUSync/Protocols/index.js +40 -0
  127. package/src/WAUSync/USyncBackoff.js +31 -0
  128. package/src/WAUSync/USyncQuery.js +204 -0
  129. package/src/WAUSync/USyncUser.js +58 -0
  130. package/src/WAUSync/index.js +32 -0
  131. package/src/antiban.js +4726 -0
  132. package/{lib → src}/index.js +48 -16
  133. package/lib/Defaults/baileys-version.json +0 -3
  134. package/lib/Defaults/index.js +0 -137
  135. package/lib/Defaults/phonenumber-mcc.json +0 -223
  136. package/lib/Signal/Group/Protocols.js +0 -269
  137. package/lib/Signal/Group/ciphertext-message.js +0 -12
  138. package/lib/Signal/Group/group-session-builder.js +0 -30
  139. package/lib/Signal/Group/group_cipher.js +0 -82
  140. package/lib/Signal/Group/index.js +0 -12
  141. package/lib/Signal/Group/keyhelper.js +0 -18
  142. package/lib/Signal/Group/queue-job.js +0 -57
  143. package/lib/Signal/Group/sender-chain-key.js +0 -26
  144. package/lib/Signal/Group/sender-key-distribution-message.js +0 -63
  145. package/lib/Signal/Group/sender-key-message.js +0 -66
  146. package/lib/Signal/Group/sender-key-name.js +0 -48
  147. package/lib/Signal/Group/sender-key-record.js +0 -41
  148. package/lib/Signal/Group/sender-key-state.js +0 -84
  149. package/lib/Signal/Group/sender-message-key.js +0 -26
  150. package/lib/Signal/libsignal.js +0 -432
  151. package/lib/Signal/lid-mapping.js +0 -277
  152. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  153. package/lib/Socket/Client/index.js +0 -3
  154. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  155. package/lib/Socket/Client/types.js +0 -11
  156. package/lib/Socket/Client/web-socket-client.js +0 -62
  157. package/lib/Socket/Client/websocket.js +0 -54
  158. package/lib/Socket/business.js +0 -379
  159. package/lib/Socket/chats.js +0 -1193
  160. package/lib/Socket/communities.js +0 -431
  161. package/lib/Socket/community.js +0 -392
  162. package/lib/Socket/dugong.js +0 -637
  163. package/lib/Socket/groups.js +0 -374
  164. package/lib/Socket/index.js +0 -12
  165. package/lib/Socket/luxu.js +0 -387
  166. package/lib/Socket/messages-recv.js +0 -1916
  167. package/lib/Socket/messages-send.js +0 -1459
  168. package/lib/Socket/newsletter.js +0 -253
  169. package/lib/Socket/registration.js +0 -167
  170. package/lib/Socket/socket.js +0 -950
  171. package/lib/Socket/username.js +0 -146
  172. package/lib/Socket/usync.js +0 -69
  173. package/lib/Store/index.js +0 -10
  174. package/lib/Store/keyed-db.js +0 -108
  175. package/lib/Store/make-cache-manager-store.js +0 -85
  176. package/lib/Store/make-in-memory-store.js +0 -198
  177. package/lib/Store/make-ordered-dictionary.js +0 -75
  178. package/lib/Store/object-repository.js +0 -32
  179. package/lib/Types/Auth.js +0 -2
  180. package/lib/Types/Bussines.js +0 -2
  181. package/lib/Types/Call.js +0 -2
  182. package/lib/Types/Chat.js +0 -8
  183. package/lib/Types/Contact.js +0 -2
  184. package/lib/Types/Events.js +0 -2
  185. package/lib/Types/GroupMetadata.js +0 -2
  186. package/lib/Types/Label.js +0 -25
  187. package/lib/Types/LabelAssociation.js +0 -7
  188. package/lib/Types/Message.js +0 -11
  189. package/lib/Types/Mex.js +0 -37
  190. package/lib/Types/Newsletter.js +0 -38
  191. package/lib/Types/Product.js +0 -2
  192. package/lib/Types/Signal.js +0 -2
  193. package/lib/Types/Socket.js +0 -3
  194. package/lib/Types/State.js +0 -56
  195. package/lib/Types/USync.js +0 -2
  196. package/lib/Types/index.js +0 -26
  197. package/lib/Utils/auth-utils.js +0 -302
  198. package/lib/Utils/baileys-event-stream.js +0 -63
  199. package/lib/Utils/browser-utils.js +0 -48
  200. package/lib/Utils/business.js +0 -231
  201. package/lib/Utils/chat-utils.js +0 -873
  202. package/lib/Utils/companion-reg-client-utils.js +0 -35
  203. package/lib/Utils/crypto.js +0 -118
  204. package/lib/Utils/decode-wa-message.js +0 -350
  205. package/lib/Utils/event-buffer.js +0 -622
  206. package/lib/Utils/generics.js +0 -399
  207. package/lib/Utils/history.js +0 -134
  208. package/lib/Utils/identity-change-handler.js +0 -50
  209. package/lib/Utils/index.js +0 -23
  210. package/lib/Utils/link-preview.js +0 -85
  211. package/lib/Utils/logger.js +0 -3
  212. package/lib/Utils/lt-hash.js +0 -8
  213. package/lib/Utils/make-mutex.js +0 -33
  214. package/lib/Utils/message-composer.js +0 -273
  215. package/lib/Utils/message-retry-manager.js +0 -265
  216. package/lib/Utils/messages-media.js +0 -788
  217. package/lib/Utils/messages.js +0 -1260
  218. package/lib/Utils/noise-handler.js +0 -201
  219. package/lib/Utils/offline-node-processor.js +0 -40
  220. package/lib/Utils/pre-key-manager.js +0 -106
  221. package/lib/Utils/process-message.js +0 -630
  222. package/lib/Utils/reporting-utils.js +0 -258
  223. package/lib/Utils/signal.js +0 -202
  224. package/lib/Utils/stanza-ack.js +0 -38
  225. package/lib/Utils/sync-action-utils.js +0 -49
  226. package/lib/Utils/tc-token-utils.js +0 -163
  227. package/lib/Utils/use-multi-file-auth-state.js +0 -121
  228. package/lib/Utils/validate-connection.js +0 -204
  229. package/lib/WABinary/constants.js +0 -1301
  230. package/lib/WABinary/decode.js +0 -262
  231. package/lib/WABinary/encode.js +0 -220
  232. package/lib/WABinary/generic-utils.js +0 -204
  233. package/lib/WABinary/index.js +0 -6
  234. package/lib/WABinary/jid-utils.js +0 -98
  235. package/lib/WABinary/types.js +0 -2
  236. package/lib/WAM/BinaryInfo.js +0 -10
  237. package/lib/WAM/constants.js +0 -22853
  238. package/lib/WAM/encode.js +0 -150
  239. package/lib/WAM/index.js +0 -4
  240. package/lib/WAUSync/Protocols/USyncContactProtocol.js +0 -52
  241. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +0 -54
  242. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -27
  243. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +0 -38
  244. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
  245. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -51
  246. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -29
  247. package/lib/WAUSync/Protocols/index.js +0 -6
  248. package/lib/WAUSync/USyncQuery.js +0 -98
  249. package/lib/WAUSync/USyncUser.js +0 -31
  250. 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