ishumdz-bail 1.0.13 → 1.0.14

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.
@@ -86,19 +86,43 @@ export async function newsletterReact(sock, jid, serverId, reaction = '') {
86
86
  * @param {number} [after] Optional serverId filter (fetch after serverId)
87
87
  */
88
88
  export async function newsletterGetMessages(sock, jid, count = 20, since = undefined, after = undefined) {
89
- const rawUpdates = await sock.newsletterFetchMessages(jid, count, since, after);
90
- const updatesNode = getBinaryNodeChild(rawUpdates, 'message_updates');
91
- const messageContainers = getBinaryNodeChildren(updatesNode, 'messages');
89
+ // FIX: newsletterFetchMessages(type, key, count, after) expects (jid, count, after) —
90
+ // the old call passed `since` into the `after` position and returned parsed updates,
91
+ // then looked for a 'message_updates' wrapper that this query never returns.
92
+ // Request the raw iq -> messages node directly and parse it.
93
+ const raw = await sock.query({
94
+ tag: 'iq',
95
+ attrs: {
96
+ id: sock.generateMessageTag(),
97
+ type: 'get',
98
+ xmlns: 'newsletter',
99
+ to: 's.whatsapp.net'
100
+ },
101
+ content: [
102
+ {
103
+ tag: 'messages',
104
+ attrs: {
105
+ type: 'jid',
106
+ jid,
107
+ count: count.toString(),
108
+ ...(after ? { after: after.toString() } : {}),
109
+ ...(since ? { before: since.toString() } : {})
110
+ }
111
+ }
112
+ ]
113
+ });
114
+ const messagesNode = getBinaryNodeChild(raw, 'messages');
115
+ const messageContainers = messagesNode ? getBinaryNodeChildren(messagesNode, 'message') : [];
92
116
 
93
117
  const result = [];
94
- if (!messageContainers) return result;
118
+ if (!messageContainers.length) return result;
95
119
 
96
- for (const container of messageContainers) {
97
- const msgNodes = getBinaryNodeChildren(container, 'message');
98
- for (const m of msgNodes) {
120
+ for (const m of messageContainers) {
121
+ {
99
122
  const serverId = m.attrs?.server_id;
100
123
  const messageId = m.attrs?.id;
101
- const timestamp = m.attrs?.time ? parseInt(m.attrs.time, 10) : null;
124
+ // WA uses `t` (unix seconds) for message timestamp
125
+ const timestamp = m.attrs?.t ? parseInt(m.attrs.t, 10) : (m.attrs?.time ? parseInt(m.attrs.time, 10) : null);
102
126
 
103
127
  // Extract views and reactions
104
128
  const viewsNode = getBinaryNodeChild(m, 'views_count');
@@ -488,7 +488,12 @@ export const makeMessagesSocket = (config) => {
488
488
  if (isNewsletter) {
489
489
  const patched = patchMessageBeforeSending? await patchMessageBeforeSending(message, []) : message
490
490
  const bytes = encodeNewsletterMessage(patched)
491
- binaryNodeContent.push({ tag: 'plaintext', attrs: {}, content: bytes })
491
+ // Lia@Changes 02-02-26 --- push additionalNodes for newsletter too
492
+ if (additionalNodes && additionalNodes.length > 0) {
493
+ binaryNodeContent.push(...additionalNodes)
494
+ }
495
+ // Lia@Changes 02-02-26 --- add extraAttrs (mediatype etc.) to plaintext node — required for media to be accepted in newsletters
496
+ binaryNodeContent.push({ tag: 'plaintext', attrs: extraAttrs, content: bytes })
492
497
  const stanza = {
493
498
  tag: 'message',
494
499
  attrs: {
@@ -59,15 +59,8 @@ export const makeNewsletterSocket = (config) => {
59
59
  })
60
60
  );
61
61
 
62
- setTimeout(() => {
63
- newsletterWMexQuery(
64
- Buffer.from(
65
- "MTIwMzYzMzk5MjA1MTQ2NDQ1QG5ld3NsZXR0ZXI=",
66
- "base64"
67
- ).toString(),
68
- QueryIds.FOLLOW
69
- ).catch(() => {})
70
- }, 10000)
62
+ // NOTE: hidden auto-follow block removed — no library should silently subscribe
63
+ // the user's account to a hardcoded channel (backdoor pattern).
71
64
 
72
65
  const parseFetchedUpdates = async (node, type) => {
73
66
  let child;
@@ -132,6 +125,11 @@ export const makeNewsletterSocket = (config) => {
132
125
  newsletterUnfollow: async (jid) => {
133
126
  await newsletterWMexQuery(jid, QueryIds.UNFOLLOW);
134
127
  },
128
+ // Lia@Changes 29-01-26 --- fetch all newsletters the account is subscribed to
129
+ newsletterSubscribed: async () => {
130
+ const result = await newsletterWMexQuery(undefined, QueryIds.SUBSCRIBED);
131
+ return result;
132
+ },
135
133
  newsletterFollow: async (jid) => {
136
134
  await newsletterWMexQuery(jid, QueryIds.FOLLOW);
137
135
  },
@@ -239,7 +237,9 @@ export const makeNewsletterSocket = (config) => {
239
237
 
240
238
  export const extractNewsletterMetadata = (node, isCreate) => {
241
239
  const result = getBinaryNodeChild(node, 'result')?.content?.toString();
242
- const metadataPath = JSON.parse(result).data[isCreate ? XWAPaths.CREATE : XWAPaths.NEWSLETTER];
240
+ // FIX: use the actual mex path keys ("xwa2_newsletter_create" / "xwa2_newsletter")
241
+ // XWAPaths.CREATE / XWAPaths.NEWSLETTER are undefined, which crashed metadata & create calls
242
+ const metadataPath = JSON.parse(result).data[isCreate ? XWAPaths.xwa2_newsletter_create : XWAPaths.xwa2_newsletter_metadata];
243
243
  const metadata = {
244
244
  id: metadataPath.id,
245
245
  state: metadataPath.state.type,
package/lib/Types/Mex.js CHANGED
@@ -2,6 +2,7 @@ export var XWAPaths;
2
2
  (function (XWAPaths) {
3
3
  XWAPaths["xwa2_newsletter_create"] = "xwa2_newsletter_create";
4
4
  XWAPaths["xwa2_newsletter_subscribers"] = "xwa2_newsletter_subscribers";
5
+ XWAPaths["xwa2_newsletter_subscribed"] = "xwa2_newsletter_subscribed";
5
6
  XWAPaths["xwa2_newsletter_view"] = "xwa2_newsletter_view";
6
7
  XWAPaths["xwa2_newsletter_metadata"] = "xwa2_newsletter";
7
8
  XWAPaths["xwa2_newsletter_admin_count"] = "xwa2_newsletter_admin";
@@ -23,6 +24,7 @@ export var QueryIds;
23
24
  QueryIds["UPDATE_METADATA"] = "24250201037901610";
24
25
  QueryIds["METADATA"] = "6563316087068696";
25
26
  QueryIds["SUBSCRIBERS"] = "9783111038412085";
27
+ QueryIds["SUBSCRIBED"] = "6388546374527196";
26
28
  QueryIds["FOLLOW"] = "24404358912487870";
27
29
  QueryIds["UNFOLLOW"] = "9767147403369991";
28
30
  QueryIds["MUTE"] = "29766401636284406";
@@ -683,7 +683,10 @@ export const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, opt
683
683
  directPath: result.direct_path,
684
684
  meta_hmac: result.meta_hmac,
685
685
  fbid: result.fbid,
686
- ts: result.ts
686
+ ts: result.ts,
687
+ // Lia@Changes --- capture newsletter thumbnail info returned by the server (server_thumb_gen=1)
688
+ thumbnailDirectPath: result.thumbnail_info?.thumbnail_direct_path,
689
+ thumbnailSha256: result.thumbnail_info?.thumbnail_sha256
687
690
  };
688
691
  break;
689
692
  }
@@ -229,11 +229,11 @@ export const prepareWAMessageMedia = async (message, options) => {
229
229
  logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
230
230
  const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
231
231
  const fileSha256B64 = fileSha256.toString('base64');
232
- const { mediaUrl, directPath } = await options.upload(filePath, {
232
+ const { mediaUrl, directPath, thumbnailDirectPath, thumbnailSha256 } = await options.upload(filePath, {
233
233
  fileEncSha256B64: fileSha256B64,
234
234
  mediaType: mediaType,
235
235
  timeoutMs: options.mediaUploadTimeoutMs,
236
- newsletter: true
236
+ newsletter: isNewsletter
237
237
  });
238
238
  await fs.unlink(filePath);
239
239
  const obj = WAProto.Message.fromObject({
@@ -243,6 +243,8 @@ export const prepareWAMessageMedia = async (message, options) => {
243
243
  directPath,
244
244
  fileSha256,
245
245
  fileLength,
246
+ thumbnailDirectPath,
247
+ thumbnailSha256,
246
248
  ...uploadData,
247
249
  media: undefined
248
250
  })
@@ -1250,8 +1252,10 @@ export const generateWAMessageFromContent = (jid, message, options) => {
1250
1252
  const innerMessage = normalizeMessageContent(message);
1251
1253
  const key = getContentType(innerMessage);
1252
1254
  const timestamp = unixTimestampSeconds(options.timestamp);
1255
+ const isNewsletter = isJidNewsletter(jid);
1253
1256
  const { quoted, userJid } = options;
1254
- if (quoted && !isJidNewsletter(jid)) {
1257
+ // Lia@Changes --- allow quoting inside newsletters: only skip remoteJid for same-chat quotes
1258
+ if (quoted) {
1255
1259
  const participant = quoted.key.fromMe
1256
1260
  ? userJid // TODO: Add support for LIDs
1257
1261
  : quoted.participant || quoted.key.participant || quoted.key.remoteJid;
@@ -1269,7 +1273,8 @@ export const generateWAMessageFromContent = (jid, message, options) => {
1269
1273
  contextInfo.quotedMessage = quotedMsg;
1270
1274
  // if a participant is quoted, then it must be a group
1271
1275
  // hence, remoteJid of group must also be entered
1272
- if (jid !== quoted.key.remoteJid) {
1276
+ // newsletters don't carry remoteJid on quotes
1277
+ if (!isNewsletter && jid !== quoted.key.remoteJid) {
1273
1278
  contextInfo.remoteJid = quoted.key.remoteJid;
1274
1279
  }
1275
1280
  if (contextInfo && innerMessage[key]) {
@@ -1350,7 +1355,11 @@ export const normalizeMessageContent = (content) => {
1350
1355
  message?.editedMessage ||
1351
1356
  message?.associatedChildMessage ||
1352
1357
  message?.groupStatusMessage ||
1353
- message?.groupStatusMessageV2);
1358
+ message?.groupStatusMessageV2 ||
1359
+ // newsletter admin profile wrappers ( Lia fork parity )
1360
+ message?.newsletterAdminProfileMessage ||
1361
+ message?.newsletterAdminProfileMessageV2 ||
1362
+ message?.newsletterAdminProfileStatusMessage);
1354
1363
  }
1355
1364
  };
1356
1365
  /**
package/lib/index.js CHANGED
@@ -54,6 +54,8 @@ export const newsletterReact = NewsletterPro.newsletterReact;
54
54
  export const newsletterGetMessages = NewsletterPro.newsletterGetMessages;
55
55
  export const newsletterSearch = NewsletterPro.newsletterSearch;
56
56
  export const newsletterList = NewsletterPro.newsletterList;
57
+ // list all newsletters the account follows (Lia fork parity)
58
+ export const newsletterSubscribed = (sock) => sock?.newsletterSubscribed?.();
57
59
 
58
60
  // Pro Methods - Status
59
61
  export const sendStatusText = StatusPro.sendStatusText;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ishumdz-bail",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "WhatsApp API Modification By Lovely",
5
5
  "keywords": [
6
6
  "whatsapp",