@badzz88/baileys 8.5.6 → 8.5.8

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 (225) hide show
  1. package/README.md +337 -1055
  2. package/WAProto/WAProto.proto +28 -1189
  3. package/WAProto/fix-imports.js +79 -69
  4. package/WAProto/index.d.ts +71491 -15254
  5. package/WAProto/index.js +126436 -19814
  6. package/engine-requirements.js +8 -15
  7. package/lib/Defaults/index.js +130 -0
  8. package/{src → lib}/Signal/Group/ciphertext-message.js +2 -5
  9. package/lib/Signal/Group/group-session-builder.js +30 -0
  10. package/{src → lib}/Signal/Group/group_cipher.js +11 -11
  11. package/lib/Signal/Group/index.js +12 -0
  12. package/lib/Signal/Group/keyhelper.js +18 -0
  13. package/{src → lib}/Signal/Group/sender-chain-key.js +6 -9
  14. package/{src → lib}/Signal/Group/sender-key-distribution-message.js +6 -9
  15. package/{src → lib}/Signal/Group/sender-key-message.js +9 -12
  16. package/{src → lib}/Signal/Group/sender-key-name.js +2 -5
  17. package/{src → lib}/Signal/Group/sender-key-record.js +8 -11
  18. package/{src → lib}/Signal/Group/sender-key-state.js +6 -9
  19. package/lib/Signal/Group/sender-message-key.js +26 -0
  20. package/{src → lib}/Signal/libsignal.js +131 -155
  21. package/{src → lib}/Signal/lid-mapping.js +27 -23
  22. package/lib/Socket/Client/index.js +3 -0
  23. package/lib/Socket/Client/types.js +11 -0
  24. package/{src → lib}/Socket/Client/websocket.js +11 -18
  25. package/{src → lib}/Socket/business.js +35 -67
  26. package/{src → lib}/Socket/chats.js +294 -550
  27. package/{src → lib}/Socket/communities.js +82 -114
  28. package/lib/Socket/graphql.js +716 -0
  29. package/lib/Socket/groups.js +374 -0
  30. package/lib/Socket/index.js +18 -0
  31. package/lib/Socket/interop.js +463 -0
  32. package/{src → lib}/Socket/luxu.js +120 -82
  33. package/lib/Socket/messages-recv.js +1916 -0
  34. package/lib/Socket/messages-send.js +1436 -0
  35. package/lib/Socket/mex.js +54 -0
  36. package/lib/Socket/newsletter.js +757 -0
  37. package/lib/Socket/privacy.js +318 -0
  38. package/{src → lib}/Socket/socket.js +356 -244
  39. package/lib/Socket/username.js +236 -0
  40. package/lib/Store/index.js +10 -0
  41. package/{src → lib}/Store/keyed-db.js +11 -21
  42. package/lib/Store/make-cache-manager-store.js +85 -0
  43. package/lib/Store/make-in-memory-store.js +244 -0
  44. package/{src → lib}/Store/make-ordered-dictionary.js +19 -25
  45. package/{src → lib}/Store/object-repository.js +11 -5
  46. package/lib/Types/Auth.js +2 -0
  47. package/lib/Types/Bussines.js +2 -0
  48. package/lib/Types/Call.js +2 -0
  49. package/lib/Types/Chat.js +8 -0
  50. package/lib/Types/Contact.js +2 -0
  51. package/lib/Types/Events.js +2 -0
  52. package/lib/Types/GroupMetadata.js +2 -0
  53. package/lib/Types/Label.js +25 -0
  54. package/lib/Types/LabelAssociation.js +7 -0
  55. package/lib/Types/Message.js +11 -0
  56. package/lib/Types/Mex.js +111 -0
  57. package/lib/Types/Product.js +2 -0
  58. package/lib/Types/Signal.js +2 -0
  59. package/lib/Types/Socket.js +3 -0
  60. package/lib/Types/State.js +56 -0
  61. package/lib/Types/USync.js +2 -0
  62. package/lib/Types/index.js +26 -0
  63. package/{src → lib}/Utils/auth-utils.js +91 -43
  64. package/lib/Utils/browser-utils.js +48 -0
  65. package/lib/Utils/business.js +231 -0
  66. package/lib/Utils/chat-utils.js +872 -0
  67. package/lib/Utils/companion-reg-client-utils.js +35 -0
  68. package/lib/Utils/crypto.js +118 -0
  69. package/lib/Utils/decode-wa-message.js +350 -0
  70. package/{src → lib}/Utils/event-buffer.js +81 -39
  71. package/lib/Utils/generics.js +403 -0
  72. package/lib/Utils/history.js +134 -0
  73. package/{src → lib}/Utils/identity-change-handler.js +9 -11
  74. package/lib/Utils/index.js +23 -0
  75. package/lib/Utils/link-preview.js +85 -0
  76. package/lib/Utils/logger.js +3 -0
  77. package/lib/Utils/lt-hash.js +8 -0
  78. package/{src → lib}/Utils/make-mutex.js +7 -10
  79. package/lib/Utils/message-composer.js +273 -0
  80. package/{src → lib}/Utils/message-retry-manager.js +76 -28
  81. package/lib/Utils/messages-media.js +870 -0
  82. package/lib/Utils/messages.js +1337 -0
  83. package/lib/Utils/noise-handler.js +201 -0
  84. package/{src → lib}/Utils/offline-node-processor.js +10 -4
  85. package/{src → lib}/Utils/pre-key-manager.js +27 -11
  86. package/lib/Utils/process-message.js +630 -0
  87. package/{src → lib}/Utils/reporting-utils.js +12 -15
  88. package/lib/Utils/signal.js +201 -0
  89. package/{src → lib}/Utils/stanza-ack.js +12 -4
  90. package/lib/Utils/sticker.js +110 -0
  91. package/{src → lib}/Utils/sync-action-utils.js +14 -10
  92. package/{src → lib}/Utils/tc-token-utils.js +48 -43
  93. package/{src → lib}/Utils/use-multi-file-auth-state.js +35 -25
  94. package/lib/Utils/validate-connection.js +203 -0
  95. package/{src → lib}/WABinary/constants.js +9 -12
  96. package/{src → lib}/WABinary/decode.js +38 -118
  97. package/{src → lib}/WABinary/encode.js +6 -11
  98. package/lib/WABinary/generic-utils.js +204 -0
  99. package/lib/WABinary/index.js +6 -0
  100. package/lib/WABinary/jid-utils.js +98 -0
  101. package/lib/WABinary/types.js +2 -0
  102. package/{src → lib}/WAM/BinaryInfo.js +2 -5
  103. package/{src → lib}/WAM/constants.js +4 -16635
  104. package/{src → lib}/WAM/encode.js +18 -17
  105. package/lib/WAM/index.js +4 -0
  106. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +53 -0
  107. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +43 -0
  108. package/lib/WAUSync/Protocols/USyncContactProtocol.js +54 -0
  109. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  110. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  111. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +58 -0
  112. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +30 -0
  113. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
  114. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +28 -0
  115. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +39 -0
  116. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
  117. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +27 -0
  118. package/lib/WAUSync/Protocols/index.js +12 -0
  119. package/lib/WAUSync/USyncQuery.js +151 -0
  120. package/lib/WAUSync/USyncUser.js +56 -0
  121. package/lib/WAUSync/index.js +3 -0
  122. package/{src → lib}/index.js +16 -51
  123. package/package.json +129 -99
  124. package/LICENSE +0 -21
  125. package/src/Defaults/index.js +0 -186
  126. package/src/Defaults/phonenumber-mcc.json +0 -223
  127. package/src/Signal/Group/group-session-builder.js +0 -86
  128. package/src/Signal/Group/index.js +0 -140
  129. package/src/Signal/Group/keyhelper.js +0 -77
  130. package/src/Signal/Group/sender-message-key.js +0 -29
  131. package/src/Socket/Client/index.js +0 -31
  132. package/src/Socket/Client/types.js +0 -13
  133. package/src/Socket/aigroups.js +0 -221
  134. package/src/Socket/graphql.js +0 -523
  135. package/src/Socket/groups.js +0 -516
  136. package/src/Socket/index.js +0 -31
  137. package/src/Socket/interactive-handler.js +0 -527
  138. package/src/Socket/interop.js +0 -339
  139. package/src/Socket/managed-account.js +0 -98
  140. package/src/Socket/messages-recv.js +0 -2685
  141. package/src/Socket/messages-send.js +0 -2047
  142. package/src/Socket/mex.js +0 -57
  143. package/src/Socket/newsletter.js +0 -455
  144. package/src/Socket/privacy.js +0 -125
  145. package/src/Socket/registration.js +0 -236
  146. package/src/Socket/text-router.js +0 -65
  147. package/src/Socket/username.js +0 -130
  148. package/src/Store/index.js +0 -33
  149. package/src/Store/make-cache-manager-store.js +0 -84
  150. package/src/Store/make-in-memory-store.js +0 -551
  151. package/src/Types/Auth.js +0 -31
  152. package/src/Types/Bussines.js +0 -2
  153. package/src/Types/Call.js +0 -2
  154. package/src/Types/Chat.js +0 -4
  155. package/src/Types/Contact.js +0 -2
  156. package/src/Types/Events.js +0 -2
  157. package/src/Types/GroupMetadata.js +0 -2
  158. package/src/Types/Label.js +0 -26
  159. package/src/Types/LabelAssociation.js +0 -8
  160. package/src/Types/Message.js +0 -93
  161. package/src/Types/Mex.js +0 -112
  162. package/src/Types/Newsletter.js +0 -109
  163. package/src/Types/Product.js +0 -2
  164. package/src/Types/Signal.js +0 -2
  165. package/src/Types/Socket.js +0 -2
  166. package/src/Types/State.js +0 -62
  167. package/src/Types/USync.js +0 -2
  168. package/src/Types/index.js +0 -56
  169. package/src/Utils/browser-utils.js +0 -112
  170. package/src/Utils/business.js +0 -240
  171. package/src/Utils/chat-utils.js +0 -1230
  172. package/src/Utils/command-loader.d.ts +0 -27
  173. package/src/Utils/command-loader.js +0 -89
  174. package/src/Utils/companion-reg-client-utils.js +0 -40
  175. package/src/Utils/consumer-application.js +0 -105
  176. package/src/Utils/crypto.js +0 -118
  177. package/src/Utils/curve25519-js.js +0 -242
  178. package/src/Utils/decode-wa-message.js +0 -529
  179. package/src/Utils/generics.js +0 -483
  180. package/src/Utils/group-history.js +0 -44
  181. package/src/Utils/history.js +0 -232
  182. package/src/Utils/index.js +0 -58
  183. package/src/Utils/jid-display-normalization.js +0 -195
  184. package/src/Utils/link-preview.js +0 -135
  185. package/src/Utils/logger.js +0 -8
  186. package/src/Utils/lt-hash.js +0 -25
  187. package/src/Utils/message-composer.js +0 -471
  188. package/src/Utils/messages-media.js +0 -843
  189. package/src/Utils/messages.js +0 -2817
  190. package/src/Utils/meta-ai-msmsg.js +0 -222
  191. package/src/Utils/native-bridge.js +0 -68
  192. package/src/Utils/noise-handler.js +0 -169
  193. package/src/Utils/process-message.js +0 -950
  194. package/src/Utils/session-pool.d.ts +0 -14
  195. package/src/Utils/session-pool.js +0 -70
  196. package/src/Utils/signal.js +0 -217
  197. package/src/Utils/sticker.d.ts +0 -13
  198. package/src/Utils/sticker.js +0 -123
  199. package/src/Utils/validate-connection.js +0 -209
  200. package/src/Utils/view-once-cache.d.ts +0 -12
  201. package/src/Utils/view-once-cache.js +0 -63
  202. package/src/Utils/voip-rekey.js +0 -22
  203. package/src/WABinary/generic-utils.js +0 -238
  204. package/src/WABinary/index.js +0 -34
  205. package/src/WABinary/jid-utils.js +0 -351
  206. package/src/WABinary/types.js +0 -2
  207. package/src/WAM/index.js +0 -32
  208. package/src/WAUSync/Protocols/USyncBotProfileProtocol.js +0 -53
  209. package/src/WAUSync/Protocols/USyncBusinessProtocol.js +0 -44
  210. package/src/WAUSync/Protocols/USyncContactProtocol.js +0 -55
  211. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +0 -55
  212. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -31
  213. package/src/WAUSync/Protocols/USyncFeatureProtocol.js +0 -54
  214. package/src/WAUSync/Protocols/USyncLIDProtocol.js +0 -32
  215. package/src/WAUSync/Protocols/USyncNewsletterProtocol.js +0 -473
  216. package/src/WAUSync/Protocols/USyncPictureProtocol.js +0 -34
  217. package/src/WAUSync/Protocols/USyncSidelistProtocol.js +0 -29
  218. package/src/WAUSync/Protocols/USyncStatusProtocol.js +0 -42
  219. package/src/WAUSync/Protocols/USyncTextStatusProtocol.js +0 -38
  220. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +0 -28
  221. package/src/WAUSync/Protocols/index.js +0 -40
  222. package/src/WAUSync/USyncQuery.js +0 -126
  223. package/src/WAUSync/USyncUser.js +0 -50
  224. package/src/WAUSync/index.js +0 -32
  225. package/src/antiban.js +0 -4152
@@ -0,0 +1,463 @@
1
+ import { getBinaryNodeChild, getBinaryNodeChildren, S_WHATSAPP_NET } from '../WABinary/index.js'
2
+ import { executeWMexQuery } from './mex.js'
3
+
4
+ /**
5
+ * w:mex query IDs for interop group and privacy operations.
6
+ *
7
+ * Source: whatsapp-android-mex_client_persist_ids.json (WA 2.26.26.4 APK assets)
8
+ */
9
+ const INTEROP_MEX_QUERY_IDS = {
10
+ CREATE_GROUP: '25726817620301611', // GroupsCreateInteropGroup
11
+ LEAVE_GROUP: '25346167795013271', // LeaveInteropGroup
12
+ ADD_PARTICIPANTS: '25732168276369451', // AddParticipantsToInteropGroup
13
+ QUERY_GROUP_INFO: '32734144032867938', // QueryInteropGroupInfo
14
+ PRIVACY_SETTINGS_QUERY: '24849123668112654', // InteropPrivacySettingsQuery
15
+ PRIVACY_SETTINGS_UPDATE: '25421856497452763', // InteropPrivacySettingsUpdate
16
+ PRIVACY_SETTINGS_WITH_CONTACT_LIST: '24913399124998598' // InteropPrivacySettingWithContactListUpdate
17
+ }
18
+
19
+ /**
20
+ * Known integrator IDs (assigned by WhatsApp).
21
+ * BirdyChat → identifier_type="email"
22
+ * Haiket → identifier_type="pn"
23
+ */
24
+ const INTEGRATOR_BIRDYCHAT = 12
25
+ const INTEGRATOR_HAIKET = 13
26
+
27
+ /**
28
+ * TOS trackable results sent by WA on first interop opt-in.
29
+ * 105 = TOS shown, 160 = TOS accepted.
30
+ */
31
+ const TOS_TRACKABLE_ID = '20240306'
32
+ const TOS_RESULT_SHOWN = '105'
33
+ const TOS_RESULT_ACCEPTED = '160'
34
+
35
+ /** Maximum users per batch lookup (enforced server-side too). */
36
+ const INTEROP_BATCH_MAX = 256
37
+
38
+ export const makeInteropSocket = sock => {
39
+ const { query, generateMessageTag, logger, signalRepository } = sock
40
+
41
+ const mexQuery = (variables, queryId, dataPath) =>
42
+ executeWMexQuery(variables, queryId, dataPath, query, generateMessageTag)
43
+
44
+ /**
45
+ * Fetch all available interop integrators from the server.
46
+ */
47
+ const fetchIntegrators = async () => {
48
+ const result = await query({
49
+ tag: 'iq',
50
+ attrs: {
51
+ type: 'get',
52
+ xmlns: 'w:interop',
53
+ to: S_WHATSAPP_NET
54
+ },
55
+ content: [{ tag: 'integrator', attrs: { fetch: 'all' } }]
56
+ })
57
+ const listNode = getBinaryNodeChild(result, 'integrator_list')
58
+ if (!listNode) return []
59
+ const globalOptedIn = listNode.attrs?.opted_in === 'true'
60
+ return getBinaryNodeChildren(listNode, 'integrator').map(node => {
61
+ const featuresNode = getBinaryNodeChild(node, 'features')
62
+ return {
63
+ id: parseInt(node.attrs.id, 10),
64
+ name: node.attrs.name,
65
+ // "active" | "onboarding" | "removed"
66
+ status: node.attrs.status,
67
+ icon: node.attrs.icon,
68
+ // "email" | "pn" | "username"
69
+ identifierType: node.attrs.identifier_type,
70
+ // Whether we are already opted-in to this integrator
71
+ optedIn: node.attrs.opted_in === 'true' || globalOptedIn,
72
+ features: {
73
+ groupMessaging: featuresNode?.attrs?.group_messaging === 'true'
74
+ }
75
+ }
76
+ })
77
+ }
78
+
79
+ /** Send a single TOS trackable item (shown or accepted). */
80
+ const sendTOSTrackable = async (id, result) => {
81
+ await query({
82
+ tag: 'iq',
83
+ attrs: { to: S_WHATSAPP_NET, type: 'set', xmlns: 'tos' },
84
+ content: [{ tag: 'trackable', attrs: { id, result } }]
85
+ })
86
+ }
87
+
88
+ /**
89
+ * Accept TOS for interop.
90
+ * Sends two trackable items: shown (105) then accepted (160).
91
+ */
92
+ const acceptInteropTOS = async () => {
93
+ await sendTOSTrackable(TOS_TRACKABLE_ID, TOS_RESULT_SHOWN)
94
+ await sendTOSTrackable(TOS_TRACKABLE_ID, TOS_RESULT_ACCEPTED)
95
+ }
96
+
97
+ /**
98
+ * Opt in to a list of integrators (by numeric ID).
99
+ */
100
+ const optInIntegrators = async (integratorIds = [INTEGRATOR_BIRDYCHAT, INTEGRATOR_HAIKET]) => {
101
+ await query({
102
+ tag: 'iq',
103
+ attrs: { type: 'set', xmlns: 'w:interop', to: S_WHATSAPP_NET },
104
+ content: [
105
+ {
106
+ tag: 'opt_integrators',
107
+ attrs: {},
108
+ content: [
109
+ {
110
+ tag: 'integrator_list',
111
+ attrs: {},
112
+ content: integratorIds.map(id => ({
113
+ tag: 'integrator',
114
+ attrs: { id: id.toString() }
115
+ }))
116
+ }
117
+ ]
118
+ }
119
+ ]
120
+ })
121
+ }
122
+
123
+ /**
124
+ * Opt out of a list of integrators (by numeric ID).
125
+ */
126
+ const optOutIntegrators = async (integratorIds = [INTEGRATOR_BIRDYCHAT, INTEGRATOR_HAIKET]) => {
127
+ await query({
128
+ tag: 'iq',
129
+ attrs: { type: 'set', xmlns: 'w:interop', to: S_WHATSAPP_NET },
130
+ content: [
131
+ {
132
+ tag: 'opt_out_integrators',
133
+ attrs: {},
134
+ content: [
135
+ {
136
+ tag: 'integrator_list',
137
+ attrs: {},
138
+ content: integratorIds.map(id => ({
139
+ tag: 'integrator',
140
+ attrs: { id: id.toString() }
141
+ }))
142
+ }
143
+ ]
144
+ }
145
+ ]
146
+ })
147
+ }
148
+
149
+ /**
150
+ * Resolve one or more interop users by external ID in a single IQ.
151
+ */
152
+ const resolveInteropUsers = async users => {
153
+ if (!users || users.length === 0) return []
154
+ if (users.length > INTEROP_BATCH_MAX) {
155
+ throw new Error(`resolveInteropUsers: max ${INTEROP_BATCH_MAX} users per request`)
156
+ }
157
+ const result = await query({
158
+ tag: 'iq',
159
+ attrs: { type: 'get', xmlns: 'w:interop', to: S_WHATSAPP_NET },
160
+ content: [
161
+ {
162
+ tag: 'users',
163
+ attrs: {},
164
+ content: users.map(({ externalId, integratorId }) => ({
165
+ tag: 'user',
166
+ attrs: {
167
+ external_id: externalId,
168
+ integrator_id: integratorId.toString()
169
+ }
170
+ }))
171
+ }
172
+ ]
173
+ })
174
+ const usersNode = getBinaryNodeChild(result, 'users')
175
+ if (!usersNode) return []
176
+ return getBinaryNodeChildren(usersNode, 'user').map(userNode => {
177
+ const errorNode = getBinaryNodeChild(userNode, 'error')
178
+ if (errorNode) {
179
+ return {
180
+ externalId: userNode.attrs.external_id,
181
+ integratorId: parseInt(userNode.attrs.integrator_id, 10),
182
+ error: {
183
+ code: parseInt(errorNode.attrs.code, 10),
184
+ text: errorNode.attrs.text
185
+ }
186
+ }
187
+ }
188
+ return {
189
+ jid: userNode.attrs.jid,
190
+ externalId: userNode.attrs.external_id,
191
+ normalizedExternalId: userNode.attrs.normalized_external_id,
192
+ integratorId: parseInt(userNode.attrs.integrator_id, 10)
193
+ }
194
+ })
195
+ }
196
+
197
+ /**
198
+ * Convenience wrapper: resolve a single interop user.
199
+ */
200
+ const resolveInteropUser = async (externalId, integratorId) => {
201
+ const results = await resolveInteropUsers([{ externalId, integratorId }])
202
+ return results[0]?? null
203
+ }
204
+
205
+ /**
206
+ * Get reachability settings for interop contacts.
207
+ */
208
+ const getReachabilitySettings = async () => {
209
+ const result = await query({
210
+ tag: 'iq',
211
+ attrs: { type: 'get', xmlns: 'w:interop', to: S_WHATSAPP_NET },
212
+ content: [{ tag: 'reachability_settings', attrs: {} }]
213
+ })
214
+ const settingsNode = getBinaryNodeChild(result, 'reachability_settings')
215
+ if (!settingsNode) return null
216
+ return {
217
+ enabled: settingsNode.attrs?.enabled,
218
+ users: getBinaryNodeChildren(settingsNode, 'user').map(n => ({
219
+ externalId: n.attrs.external_id,
220
+ integratorId: parseInt(n.attrs.integrator_id, 10),
221
+ jid: n.attrs.jid
222
+ }))
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Set reachability settings (subscribe to presence) for interop contacts.
228
+ */
229
+ const setReachabilitySettings = async (users, enabled = 'true') => {
230
+ await query({
231
+ tag: 'iq',
232
+ attrs: { type: 'set', xmlns: 'w:interop', to: S_WHATSAPP_NET },
233
+ content: [
234
+ {
235
+ tag: 'reachability_settings',
236
+ attrs: { enabled },
237
+ content: users.map(({ externalId, integratorId }) => ({
238
+ tag: 'user',
239
+ attrs: {
240
+ external_id: externalId,
241
+ integrator_id: integratorId.toString()
242
+ }
243
+ }))
244
+ }
245
+ ]
246
+ })
247
+ }
248
+
249
+ /**
250
+ * Block or unblock an interop user via the w:interop blocklist.
251
+ */
252
+ const updateInteropBlockStatus = async (jid, action) => {
253
+ await query({
254
+ tag: 'iq',
255
+ attrs: { type: 'set', xmlns: 'w:interop', to: S_WHATSAPP_NET },
256
+ content: [
257
+ {
258
+ tag: 'blocklist',
259
+ attrs: {},
260
+ content: [{ tag: 'item', attrs: { action, jid } }]
261
+ }
262
+ ]
263
+ })
264
+ }
265
+
266
+ const blockInteropUser = jid => updateInteropBlockStatus(jid, 'block')
267
+ const unblockInteropUser = jid => updateInteropBlockStatus(jid, 'unblock')
268
+
269
+ /**
270
+ * Report an interop contact as spam.
271
+ */
272
+ const reportInteropSpam = async (jid, spamFlow = 'account_info_block') => {
273
+ await query({
274
+ tag: 'iq',
275
+ attrs: { type: 'set', xmlns: 'spam', to: S_WHATSAPP_NET },
276
+ content: [{ tag: 'spam_list', attrs: { jid, spam_flow: spamFlow } }]
277
+ })
278
+ }
279
+
280
+ /**
281
+ * Mark an interop JID as trusted_contact in privacy tokens.
282
+ */
283
+ const trustInteropContact = async jid => {
284
+ const t = Math.floor(Date.now() / 1000).toString()
285
+ await query({
286
+ tag: 'iq',
287
+ attrs: { to: S_WHATSAPP_NET, xmlns: 'privacy', type: 'set' },
288
+ content: [
289
+ {
290
+ tag: 'tokens',
291
+ attrs: {},
292
+ content: [{ tag: 'token', attrs: { jid, type: 'trusted_contact', t } }]
293
+ }
294
+ ]
295
+ })
296
+ }
297
+
298
+ /**
299
+ * Full interop initialization sequence matching WA Web.
300
+ */
301
+ const initInterop = async () => {
302
+ let integrators
303
+ try {
304
+ integrators = await fetchIntegrators()
305
+ } catch (err) {
306
+ logger.warn({ err }, 'interop: failed to fetch integrators')
307
+ return []
308
+ }
309
+ const toOptIn = integrators.filter(i => i.status === 'active' || i.status === 'onboarding')
310
+ if (toOptIn.length === 0) return integrators
311
+ try {
312
+ await acceptInteropTOS()
313
+ } catch (err) {
314
+ logger.warn({ err }, 'interop: failed to accept TOS')
315
+ }
316
+ try {
317
+ await optInIntegrators(toOptIn.map(i => i.id))
318
+ } catch (err) {
319
+ logger.warn({ err }, 'interop: failed to opt-in integrators')
320
+ }
321
+ logger.info({ integrators: toOptIn.map(i => i.name) }, 'interop: initialized')
322
+ return integrators
323
+ }
324
+
325
+ /**
326
+ * Reset the Signal session with an interop contact and force a fresh pkmsg handshake.
327
+ */
328
+ const resetInteropSession = async jid => {
329
+ await signalRepository.deleteSession([jid])
330
+ logger.info({ jid }, '[interop] session reset — next send will use pkmsg')
331
+ }
332
+
333
+ /**
334
+ * Create an interop group via MEX.
335
+ */
336
+ const createInteropGroup = async participants => {
337
+ const result = await mexQuery(
338
+ { input: { participants: participants.map(jid => ({ jid })) } },
339
+ INTEROP_MEX_QUERY_IDS.CREATE_GROUP,
340
+ 'xwa2_interop_group_create'
341
+ )
342
+ logger.info({ participants }, '[interop] group created via MEX')
343
+ return result
344
+ }
345
+
346
+ /**
347
+ * Leave one or more interop groups via MEX.
348
+ */
349
+ const leaveInteropGroup = async jids => {
350
+ const ids = Array.isArray(jids)? jids : [jids]
351
+ const result = await mexQuery(
352
+ { input: { groups_to_leave: ids.map(jid => ({ gid: jid.split('@')[0] })) } },
353
+ INTEROP_MEX_QUERY_IDS.LEAVE_GROUP,
354
+ 'xwa2_interop_group_leave'
355
+ )
356
+ logger.info({ jids: ids }, '[interop] left group(s) via MEX')
357
+ return result
358
+ }
359
+
360
+ /**
361
+ * Add participants to an existing interop group via MEX.
362
+ */
363
+ const addParticipantsToInteropGroup = async (groupJid, participants) => {
364
+ const gid = groupJid.split('@')[0]
365
+ return mexQuery(
366
+ { input: { gid, participants: participants.map(jid => ({ jid })) } },
367
+ INTEROP_MEX_QUERY_IDS.ADD_PARTICIPANTS,
368
+ 'xwa2_interop_add_participants_to_group'
369
+ )
370
+ }
371
+
372
+ /**
373
+ * Query info about an interop group via MEX.
374
+ */
375
+ const queryInteropGroupInfo = async groupJid => {
376
+ const gid = groupJid.split('@')[0]
377
+ return mexQuery({ group_input: { gid } }, INTEROP_MEX_QUERY_IDS.QUERY_GROUP_INFO, 'xwa2_interop_group_query_by_id')
378
+ }
379
+
380
+ /**
381
+ * Update an interop privacy setting via MEX.
382
+ */
383
+ const updateInteropPrivacySetting = async (feature, setting) => {
384
+ return mexQuery(
385
+ { feature, setting },
386
+ INTEROP_MEX_QUERY_IDS.PRIVACY_SETTINGS_UPDATE,
387
+ 'xwa2_interop_privacy_setting_update'
388
+ )
389
+ }
390
+
391
+ /**
392
+ * Update an interop privacy setting with an explicit contact list via MEX.
393
+ */
394
+ const updateInteropPrivacySettingWithContactList = async (
395
+ feature,
396
+ setting,
397
+ contacts,
398
+ contactListType,
399
+ dhash = 'none'
400
+ ) => {
401
+ return mexQuery(
402
+ { feature, setting, contacts, contact_list_type: contactListType, dhash },
403
+ INTEROP_MEX_QUERY_IDS.PRIVACY_SETTINGS_WITH_CONTACT_LIST,
404
+ 'xwa2_interop_privacy_setting_with_contact_list_update'
405
+ )
406
+ }
407
+
408
+ /**
409
+ * Check whether an interop user allows being added to groups (GROUPADD privacy).
410
+ */
411
+ const getInteropGroupAddPrivacy = async (jid, integratorId) => {
412
+ const result = await query({
413
+ tag: 'iq',
414
+ attrs: { type: 'get', xmlns: 'w:interop', to: S_WHATSAPP_NET },
415
+ content: [
416
+ {
417
+ tag: 'privacy',
418
+ attrs: { feature: 'GROUPADD' },
419
+ content: [
420
+ {
421
+ tag: 'user',
422
+ attrs: {
423
+ jid,
424
+ integrator_id: integratorId.toString()
425
+ }
426
+ }
427
+ ]
428
+ }
429
+ ]
430
+ })
431
+ const privacyNode = getBinaryNodeChild(result, 'privacy')
432
+ const userNode = getBinaryNodeChild(privacyNode, 'user')
433
+ return userNode?.attrs?.result === 'allowed'
434
+ }
435
+
436
+ return {
437
+ ...sock,
438
+ fetchIntegrators,
439
+ acceptInteropTOS,
440
+ optInIntegrators,
441
+ optOutIntegrators,
442
+ resolveInteropUser,
443
+ resolveInteropUsers,
444
+ getReachabilitySettings,
445
+ setReachabilitySettings,
446
+ blockInteropUser,
447
+ unblockInteropUser,
448
+ reportInteropSpam,
449
+ trustInteropContact,
450
+ initInterop,
451
+ resetInteropSession,
452
+ createInteropGroup,
453
+ leaveInteropGroup,
454
+ addParticipantsToInteropGroup,
455
+ queryInteropGroupInfo,
456
+ updateInteropPrivacySetting,
457
+ updateInteropPrivacySettingWithContactList,
458
+ getInteropGroupAddPrivacy,
459
+ INTEGRATOR_BIRDYCHAT,
460
+ INTEGRATOR_HAIKET,
461
+ INTEROP_MEX_QUERY_IDS
462
+ }
463
+ }