@vielhuber/wahelper 1.8.1 → 1.8.3

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 (2) hide show
  1. package/package.json +1 -1
  2. package/wahelper-daemon.js +115 -30
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielhuber/wahelper",
3
- "version": "1.8.1",
3
+ "version": "1.8.3",
4
4
  "description": "Lightweight whatsapp integration layer.",
5
5
  "main": "wahelper.js",
6
6
  "files": [
@@ -4,7 +4,9 @@ import makeWASocket, {
4
4
  useMultiFileAuthState,
5
5
  DisconnectReason,
6
6
  downloadMediaMessage,
7
+ extractMessageContent,
7
8
  fetchLatestBaileysVersion,
9
+ normalizeMessageContent,
8
10
  Browsers
9
11
  } from 'baileys';
10
12
  import P from 'pino';
@@ -306,6 +308,13 @@ export default class wahelperDaemon {
306
308
  fromMe = messages__value.key?.fromMe ? 1 : 0,
307
309
  timestamp = messages__value.messageTimestamp;
308
310
 
311
+ // status posts and newsletter items are not conversations. they carry
312
+ // their author in remoteJidAlt, so without this they would be stored
313
+ // as a regular one-to-one message from that contact.
314
+ if (chatId === 'status@broadcast' || chatId?.endsWith('@newsletter')) {
315
+ continue;
316
+ }
317
+
309
318
  if (timestamp !== undefined && timestamp !== null) {
310
319
  timestamp = Number(timestamp);
311
320
  if (isNaN(timestamp)) {
@@ -352,46 +361,122 @@ export default class wahelperDaemon {
352
361
  this.log(messages__value);
353
362
  continue;
354
363
  }
355
- if (from === 'status') {
356
- continue;
357
- }
358
364
 
359
365
  let content = null,
360
366
  mediaFilename = null,
361
367
  mediaData = null,
362
368
  mediaBufferInput = null;
363
369
 
364
- if (messages__value.message?.conversation) {
365
- content = messages__value.message.conversation;
366
- } else if (messages__value.message?.extendedTextMessage?.text) {
367
- content = messages__value.message.extendedTextMessage.text;
368
- } else if (messages__value.message?.imageMessage) {
369
- content = messages__value.message.imageMessage.caption || null;
370
+ // disappearing, view-once, edited and document-with-caption messages wrap
371
+ // the real payload one or more levels deep — unwrap once so every branch
372
+ // below sees the same shape
373
+ let payload = normalizeMessageContent(messages__value.message);
374
+ let mediaMessage = { key: messages__value.key, message: payload };
375
+
376
+ if (payload?.conversation) {
377
+ content = payload.conversation;
378
+ } else if (payload?.extendedTextMessage?.text) {
379
+ content = payload.extendedTextMessage.text;
380
+ } else if (payload?.imageMessage) {
381
+ content = payload.imageMessage.caption || null;
370
382
  mediaFilename = id + '.jpg';
371
- mediaBufferInput = messages__value;
372
- } else if (messages__value.message?.stickerMessage) {
373
- content = messages__value.message.stickerMessage.caption || null;
383
+ mediaBufferInput = mediaMessage;
384
+ } else if (payload?.stickerMessage) {
385
+ content = payload.stickerMessage.caption || null;
374
386
  mediaFilename = id + '.webp';
375
- mediaBufferInput = messages__value;
376
- } else if (messages__value.message?.videoMessage) {
377
- content = messages__value.message.videoMessage.caption || null;
387
+ mediaBufferInput = mediaMessage;
388
+ } else if (payload?.videoMessage) {
389
+ content = payload.videoMessage.caption || null;
378
390
  mediaFilename = id + '.mp4';
379
- mediaBufferInput = messages__value;
380
- } else if (messages__value.message?.documentMessage) {
381
- content = messages__value.message.documentMessage.caption || null;
382
- mediaFilename = messages__value.message.documentMessage.fileName || id + '.bin';
383
- mediaBufferInput = messages__value;
384
- } else if (messages__value.message?.documentWithCaptionMessage) {
385
- content =
386
- messages__value.message.documentWithCaptionMessage.message.documentMessage.caption || null;
387
- mediaFilename =
388
- messages__value.message.documentWithCaptionMessage.message.documentMessage.fileName ||
389
- id + '.bin';
390
- mediaBufferInput = messages__value.message.documentWithCaptionMessage;
391
- } else if (messages__value.message?.audioMessage) {
392
- content = messages__value.message.audioMessage.caption || null;
391
+ mediaBufferInput = mediaMessage;
392
+ } else if (payload?.ptvMessage) {
393
+ // a video note is a videoMessage under a different key, and baileys'
394
+ // media downloader has no path for "ptv" — hand it the video it is
395
+ content = payload.ptvMessage.caption || null;
396
+ mediaFilename = id + '.mp4';
397
+ mediaBufferInput = { key: messages__value.key, message: { videoMessage: payload.ptvMessage } };
398
+ } else if (payload?.documentMessage) {
399
+ content = payload.documentMessage.caption || null;
400
+ mediaFilename = payload.documentMessage.fileName || id + '.bin';
401
+ mediaBufferInput = mediaMessage;
402
+ } else if (payload?.audioMessage) {
403
+ content = payload.audioMessage.caption || null;
393
404
  mediaFilename = id + '.ogg';
394
- mediaBufferInput = messages__value;
405
+ mediaBufferInput = mediaMessage;
406
+ } else if (
407
+ payload?.pollCreationMessage ||
408
+ payload?.pollCreationMessageV2 ||
409
+ payload?.pollCreationMessageV3 ||
410
+ payload?.pollCreationMessageV4
411
+ ) {
412
+ // a poll is a turn of its own: without it a reader cannot tell that a
413
+ // question was already answered by putting it to a vote
414
+ let poll =
415
+ payload.pollCreationMessage ||
416
+ payload.pollCreationMessageV2 ||
417
+ payload.pollCreationMessageV3 ||
418
+ payload.pollCreationMessageV4;
419
+ content =
420
+ '[Poll] ' +
421
+ (poll.name || '') +
422
+ (poll.options || []).map(option => '\n- ' + (option.optionName || '')).join('');
423
+ } else if (payload?.pollUpdateMessage) {
424
+ // the vote itself is encrypted against the poll, but the fact that
425
+ // somebody voted is the part that says "this was answered"
426
+ content = '[Poll vote] on message ' + (payload.pollUpdateMessage.pollCreationMessageKey?.id || '');
427
+ } else if (payload?.reactionMessage?.text) {
428
+ // an emoji reaction counts as having replied; an empty text means the
429
+ // reaction was withdrawn and carries nothing worth storing
430
+ content =
431
+ '[Reaction] ' +
432
+ payload.reactionMessage.text +
433
+ ' to message ' +
434
+ (payload.reactionMessage.key?.id || '');
435
+ } else if (payload?.locationMessage) {
436
+ content =
437
+ '[Location] ' +
438
+ [
439
+ payload.locationMessage.name,
440
+ payload.locationMessage.address,
441
+ payload.locationMessage.degreesLatitude + ', ' + payload.locationMessage.degreesLongitude,
442
+ payload.locationMessage.comment
443
+ ]
444
+ .filter(part => part !== null && part !== undefined && part !== '')
445
+ .join(' | ');
446
+ } else if (payload?.liveLocationMessage) {
447
+ content =
448
+ '[Live location] ' +
449
+ payload.liveLocationMessage.degreesLatitude +
450
+ ', ' +
451
+ payload.liveLocationMessage.degreesLongitude +
452
+ (payload.liveLocationMessage.caption ? ' | ' + payload.liveLocationMessage.caption : '');
453
+ } else if (payload?.contactMessage) {
454
+ content =
455
+ '[Contact] ' +
456
+ (payload.contactMessage.displayName || '') +
457
+ (payload.contactMessage.vcard ? '\n' + payload.contactMessage.vcard : '');
458
+ } else if (payload?.contactsArrayMessage) {
459
+ content =
460
+ '[Contacts] ' +
461
+ (payload.contactsArrayMessage.contacts || [])
462
+ .map(contact => contact.displayName || '')
463
+ .filter(name => name !== '')
464
+ .join(', ');
465
+ } else if (payload?.groupInviteMessage) {
466
+ content =
467
+ '[Group invite] ' +
468
+ (payload.groupInviteMessage.groupName || payload.groupInviteMessage.groupJid || '') +
469
+ (payload.groupInviteMessage.caption ? '\n' + payload.groupInviteMessage.caption : '');
470
+ } else if (payload?.eventMessage) {
471
+ content =
472
+ '[Event] ' +
473
+ (payload.eventMessage.isCanceled === true ? '(canceled) ' : '') +
474
+ (payload.eventMessage.name || '') +
475
+ (payload.eventMessage.description ? '\n' + payload.eventMessage.description : '');
476
+ } else if (extractMessageContent(payload)?.conversation) {
477
+ // buttons, lists and templates carry their text one wrapper deeper;
478
+ // baileys already knows where, so ask it instead of unpacking each one
479
+ content = extractMessageContent(payload).conversation;
395
480
  } else {
396
481
  continue;
397
482
  }