ishumdz-bail 1.0.14 → 1.0.15

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.
@@ -492,14 +492,22 @@ export const makeMessagesSocket = (config) => {
492
492
  if (additionalNodes && additionalNodes.length > 0) {
493
493
  binaryNodeContent.push(...additionalNodes)
494
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 })
495
+ // Channel updates MUST use an EMPTY plaintext attrs object and stanza
496
+ // type 'text' — verified against 120363427391054075@newsletter:
497
+ // { mediatype: 'image' } + type 'image' -> silently dropped
498
+ // { mediatype: 'image' } + type 'text' -> dropped
499
+ // {} + type 'image' -> dropped
500
+ // {} + type 'text' -> DELIVERED
501
+ // The real type lives inside the encoded newsletter protobuf
502
+ // (imageMessage / documentMessage / ...), so the stanza stays
503
+ // 'text' and no extra plaintext attrs are attached.
504
+ binaryNodeContent.push({ tag: 'plaintext', attrs: {}, content: bytes })
497
505
  const stanza = {
498
506
  tag: 'message',
499
507
  attrs: {
500
508
  to: jid,
501
509
  id: msgId,
502
- type: getMessageType(message),
510
+ type: 'text',
503
511
  ...(additionalAttributes || {})
504
512
  },
505
513
  content: binaryNodeContent
@@ -226,25 +226,57 @@ export const prepareWAMessageMedia = async (message, options) => {
226
226
  }
227
227
  const isNewsletter = !!options.jid && isJidNewsletter(options.jid);
228
228
  if (isNewsletter) {
229
+ // Channel media follows the @zanta/baileys proven method: the file is
230
+ // uploaded RAW (server-opaque, no mediaKey / AES handshake) and the
231
+ // message carries only url, directPath, fileSha256 and fileLength.
232
+ //
233
+ // The critical detail is that `newsletter: true` is deliberately NOT
234
+ // passed to options.upload(). Passing it selects
235
+ // NEWSLETTER_MEDIA_PATH_MAP (/newsletter/newsletter-audio, plus
236
+ // &server_thumb_gen=1), which returns a /m1/v/t24/... directPath that the
237
+ // channel client cannot use for playback — the post renders but never
238
+ // plays, or the client falls back to the "your version of WhatsApp
239
+ // doesn't support this update" placeholder. Omitting the flag keeps the
240
+ // standard MEDIA_PATH_MAP (/mms/audio) upload, which is what the working
241
+ // channel-media implementation actually does.
229
242
  logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
230
243
  const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
231
244
  const fileSha256B64 = fileSha256.toString('base64');
232
- const { mediaUrl, directPath, thumbnailDirectPath, thumbnailSha256 } = await options.upload(filePath, {
245
+ const { mediaUrl, directPath } = await options.upload(filePath, {
233
246
  fileEncSha256B64: fileSha256B64,
234
247
  mediaType: mediaType,
235
- timeoutMs: options.mediaUploadTimeoutMs,
236
- newsletter: isNewsletter
248
+ // Channel media MUST go up on the newsletter path (/newsletter/newsletter-*).
249
+ // On the plain /mms/* path a channel post streams for playback but a
250
+ // full download comes back truncated — the channel media service only
251
+ // resolves newsletter-path directPaths. This is also what upstream
252
+ // ishumdz-bail does; the flag was the one thing lost in the port.
253
+ newsletter: true,
254
+ timeoutMs: options.mediaUploadTimeoutMs
237
255
  });
256
+ // Additive on top of the @zanta method: build the inline jpegThumbnail
257
+ // from the raw file we still have on disk. Channel clients render the
258
+ // bubble straight from this inline thumbnail, so skipping it makes an
259
+ // otherwise-valid image post look broken. Non-fatal — a failure here
260
+ // just means the client has to fetch the full image.
261
+ if ((mediaType === 'image' || mediaType === 'video') && typeof uploadData.jpegThumbnail === 'undefined') {
262
+ try {
263
+ const { thumbnail, originalImageDimensions } = await generateThumbnail(filePath, mediaType, options);
264
+ uploadData.jpegThumbnail = thumbnail;
265
+ if (!uploadData.width && originalImageDimensions) {
266
+ uploadData.width = originalImageDimensions.width;
267
+ uploadData.height = originalImageDimensions.height;
268
+ }
269
+ } catch (e) {
270
+ logger?.warn({ err: e?.message }, 'newsletter thumbnail generation failed');
271
+ }
272
+ }
238
273
  await fs.unlink(filePath);
239
274
  const obj = WAProto.Message.fromObject({
240
- // todo: add more support here
241
275
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
242
276
  url: mediaUrl,
243
277
  directPath,
244
278
  fileSha256,
245
279
  fileLength,
246
- thumbnailDirectPath,
247
- thumbnailSha256,
248
280
  ...uploadData,
249
281
  media: undefined
250
282
  })
@@ -262,6 +294,7 @@ export const prepareWAMessageMedia = async (message, options) => {
262
294
  }
263
295
  return obj;
264
296
  }
297
+
265
298
  const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
266
299
  const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
267
300
  const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true && typeof uploadData.waveform === 'undefined';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ishumdz-bail",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "WhatsApp API Modification By Lovely",
5
5
  "keywords": [
6
6
  "whatsapp",