plogme 2.1.1 → 2.1.2

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 (147) hide show
  1. package/README.md +115 -0
  2. package/WAProto/WAProto.proto +12 -0
  3. package/WAProto/index.d.ts +12 -0
  4. package/WAProto/index.js +12 -0
  5. package/engine-requirements.js +12 -0
  6. package/lib/Defaults/ban-checker.js +12 -0
  7. package/lib/Defaults/index.js +12 -0
  8. package/lib/Signal/Group/ciphertext-message.js +12 -0
  9. package/lib/Signal/Group/group-session-builder.js +12 -0
  10. package/lib/Signal/Group/group_cipher.js +12 -0
  11. package/lib/Signal/Group/index.js +12 -0
  12. package/lib/Signal/Group/keyhelper.js +12 -0
  13. package/lib/Signal/Group/sender-chain-key.js +12 -0
  14. package/lib/Signal/Group/sender-key-distribution-message.js +12 -0
  15. package/lib/Signal/Group/sender-key-message.js +12 -0
  16. package/lib/Signal/Group/sender-key-name.js +12 -0
  17. package/lib/Signal/Group/sender-key-record.js +12 -0
  18. package/lib/Signal/Group/sender-key-state.js +12 -0
  19. package/lib/Signal/Group/sender-message-key.js +12 -0
  20. package/lib/Signal/libsignal.js +12 -0
  21. package/lib/Signal/lid-mapping.js +12 -0
  22. package/lib/Socket/Client/index.js +12 -0
  23. package/lib/Socket/Client/types.js +12 -0
  24. package/lib/Socket/Client/websocket.js +12 -0
  25. package/lib/Socket/aigroups.js +12 -0
  26. package/lib/Socket/ban-checker.js +12 -0
  27. package/lib/Socket/business.js +12 -0
  28. package/lib/Socket/chats.js +12 -0
  29. package/lib/Socket/communities.js +12 -0
  30. package/lib/Socket/graphql.js +12 -0
  31. package/lib/Socket/groups.js +12 -0
  32. package/lib/Socket/index.js +12 -0
  33. package/lib/Socket/interactive-handler.js +12 -0
  34. package/lib/Socket/interop.js +12 -0
  35. package/lib/Socket/managed-account.js +12 -0
  36. package/lib/Socket/messages-recv.js +12 -0
  37. package/lib/Socket/messages-send.js +307 -6
  38. package/lib/Socket/mex.js +12 -0
  39. package/lib/Socket/newsletter.js +12 -0
  40. package/lib/Socket/privacy.js +12 -0
  41. package/lib/Socket/registration.js +12 -0
  42. package/lib/Socket/socket.js +12 -0
  43. package/lib/Socket/username.js +12 -0
  44. package/lib/Store/index.js +12 -0
  45. package/lib/Store/make-cache-manager-store.js +12 -0
  46. package/lib/Store/make-in-memory-store.js +12 -0
  47. package/lib/Store/make-ordered-dictionary.js +12 -0
  48. package/lib/Store/object-repository.js +12 -0
  49. package/lib/Types/Auth.js +12 -0
  50. package/lib/Types/Bussines.js +12 -0
  51. package/lib/Types/Call.js +12 -0
  52. package/lib/Types/Chat.js +12 -0
  53. package/lib/Types/Contact.js +12 -0
  54. package/lib/Types/Events.js +12 -0
  55. package/lib/Types/GroupMetadata.js +12 -0
  56. package/lib/Types/Label.js +12 -0
  57. package/lib/Types/LabelAssociation.js +12 -0
  58. package/lib/Types/Message.js +12 -0
  59. package/lib/Types/Mex.js +12 -0
  60. package/lib/Types/Product.js +12 -0
  61. package/lib/Types/RichType.js +12 -0
  62. package/lib/Types/Signal.js +12 -0
  63. package/lib/Types/Socket.js +12 -0
  64. package/lib/Types/State.js +12 -0
  65. package/lib/Types/USync.js +12 -0
  66. package/lib/Types/index.js +12 -0
  67. package/lib/Utils/auth-utils.js +12 -0
  68. package/lib/Utils/bot-capabilities.js +12 -0
  69. package/lib/Utils/bot-planning-replay.js +12 -0
  70. package/lib/Utils/browser-utils.js +12 -0
  71. package/lib/Utils/business.js +12 -0
  72. package/lib/Utils/channel-policy.js +12 -0
  73. package/lib/Utils/chat-utils.js +12 -0
  74. package/lib/Utils/companion-reg-client-utils.js +12 -0
  75. package/lib/Utils/consumer-application.js +12 -0
  76. package/lib/Utils/crypto.js +12 -0
  77. package/lib/Utils/decode-wa-message.js +12 -0
  78. package/lib/Utils/event-buffer.js +12 -0
  79. package/lib/Utils/games/miniapp.js +12 -0
  80. package/lib/Utils/games/slot-machine.js +12 -0
  81. package/lib/Utils/games/website-preview.js +12 -0
  82. package/lib/Utils/generics.js +12 -0
  83. package/lib/Utils/group-history.js +12 -0
  84. package/lib/Utils/history.js +12 -0
  85. package/lib/Utils/identity-change-handler.js +12 -0
  86. package/lib/Utils/index.js +12 -0
  87. package/lib/Utils/jid-display-normalization.js +12 -0
  88. package/lib/Utils/link-preview.js +12 -0
  89. package/lib/Utils/logger.js +12 -0
  90. package/lib/Utils/lt-hash.js +12 -0
  91. package/lib/Utils/make-mutex.js +12 -0
  92. package/lib/Utils/message-composer.js +18 -1
  93. package/lib/Utils/message-inspect.js +12 -0
  94. package/lib/Utils/message-retry-manager.js +12 -0
  95. package/lib/Utils/messages-media.js +12 -0
  96. package/lib/Utils/messages.js +77 -4
  97. package/lib/Utils/meta-ai-msmsg.js +12 -0
  98. package/lib/Utils/meta-compositing.js +12 -0
  99. package/lib/Utils/native-flow.js +12 -0
  100. package/lib/Utils/noise-handler.js +12 -0
  101. package/lib/Utils/offline-node-processor.js +12 -0
  102. package/lib/Utils/pre-key-manager.js +12 -0
  103. package/lib/Utils/process-message.js +12 -0
  104. package/lib/Utils/reporting-utils.js +12 -0
  105. package/lib/Utils/rich-message-utils.js +290 -9
  106. package/lib/Utils/signal.js +12 -0
  107. package/lib/Utils/source-grep.js +12 -0
  108. package/lib/Utils/stanza-ack.js +12 -0
  109. package/lib/Utils/sync-action-utils.js +12 -0
  110. package/lib/Utils/tc-token-utils.js +12 -0
  111. package/lib/Utils/use-multi-file-auth-state.js +12 -0
  112. package/lib/Utils/use-single-file-auth-state.js +12 -0
  113. package/lib/Utils/use-sqlite-auth-state.js +12 -0
  114. package/lib/Utils/validate-connection.js +12 -0
  115. package/lib/Utils/view-once-utils.js +12 -0
  116. package/lib/Utils/voip-rekey.js +12 -0
  117. package/lib/Utils/welcome-flow.js +12 -0
  118. package/lib/WABinary/constants.js +12 -0
  119. package/lib/WABinary/decode.js +12 -0
  120. package/lib/WABinary/encode.js +12 -0
  121. package/lib/WABinary/generic-utils.js +12 -0
  122. package/lib/WABinary/index.js +12 -0
  123. package/lib/WABinary/jid-utils.js +12 -0
  124. package/lib/WABinary/types.js +12 -0
  125. package/lib/WAM/BinaryInfo.js +12 -0
  126. package/lib/WAM/constants.js +12 -0
  127. package/lib/WAM/encode.js +12 -0
  128. package/lib/WAM/index.js +12 -0
  129. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +12 -0
  130. package/lib/WAUSync/Protocols/USyncContactProtocol.js +12 -0
  131. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +12 -0
  132. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +12 -0
  133. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +12 -0
  134. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +12 -0
  135. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +12 -0
  136. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +12 -0
  137. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +12 -0
  138. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +12 -0
  139. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +12 -0
  140. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +12 -0
  141. package/lib/WAUSync/Protocols/index.js +12 -0
  142. package/lib/WAUSync/USyncQuery.js +12 -0
  143. package/lib/WAUSync/USyncUser.js +12 -0
  144. package/lib/WAUSync/index.js +12 -0
  145. package/lib/index.d.ts +46 -2
  146. package/lib/index.js +12 -0
  147. package/package.json +9 -2
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/interactive-handler.js
5
+ * About: Interactive handler module for the Plogme WhatsApp protocol client.
6
+ * Important exports: Baron
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { randomBytes } from 'crypto';
2
14
  import { proto } from '../../WAProto/index.js';
3
15
  import {
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/interop.js
5
+ * About: Interop module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeInteropSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { getBinaryNodeChild, getBinaryNodeChildren, S_WHATSAPP_NET } from '../WABinary/index.js';
2
14
  import { executeWMexQuery } from './mex.js';
3
15
 
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/managed-account.js
5
+ * About: Managed account module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeManagedAccountSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { executeWMexQuery } from './mex.js';
2
14
 
3
15
  const MANAGED_ACCOUNT_MEX_IDS = {
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/messages-recv.js
5
+ * About: Messages recv module for the Plogme WhatsApp protocol client.
6
+ * Important exports: buildGroupCallStanza, buildGroupCallCancelStanza, makeMessagesRecvSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import NodeCache from '@cacheable/node-cache';
2
14
  import { Boom } from '@hapi/boom';
3
15
  import { randomBytes } from 'crypto';
@@ -1,9 +1,21 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/messages-send.js
5
+ * About: Messages send module for the Plogme WhatsApp protocol client.
6
+ * Important exports: normalizeStatusJidList, makeMessagesSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import NodeCache from '@cacheable/node-cache';
2
14
  import { Boom } from '@hapi/boom';
3
15
  import { randomBytes, randomUUID } from 'crypto';
4
16
  import { proto } from '../../WAProto/index.js';
5
17
  import { BIZ_BOT_SUPPORT_PAYLOAD, DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
6
- import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, buildLinkPreview, decryptMediaRetryData, DEF_MEDIA_HOST, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, extractImageThumb, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageFromContent, generateWAMessageFromImagePoll, getStatusCodeForMediaRetry, makeWhatsAppFlowButton, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, prepareWAMessageMedia, shouldIncludeBizBinaryNode, unixTimestampSeconds } from '../Utils/index.js';
18
+ import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, buildLinkPreview, decryptMediaRetryData, DEF_MEDIA_HOST, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, extractImageThumb, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageFromContent, generateWAMessageFromImagePoll, generateWAMessageFromLivePhoto, getStatusCodeForMediaRetry, makeWhatsAppFlowButton, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, prepareWAMessageMedia, shouldIncludeBizBinaryNode, unixTimestampSeconds } from '../Utils/index.js';
7
19
  import { getUrlInfo } from '../Utils/link-preview.js';
8
20
  import { prepareRichMenuMessage, prepareA2UIMessage, prepareA2UICommandMenu, prepareAIRichCommandMenu, prepareSocialEntityMessage, prepareInstagramProfileMessage, prepareRichResponseMessage, prepareRichGenerationMessage, prepareCopyToClipboardMessage, prepareRichTextMessage, prepareRichQuoteMessage, prepareRichImageMessage, prepareRichLinkMessage, prepareSocialProfileMessage, prepareUnifiedResponseMessage, prepareRichMapMessage, prepareBotPromptSuggestionsMessage, prepareBotSourcesMessage, prepareRichDynamicMediaMessage, prepareBotPttTranscriptMessage, prepareGridImageMessage, prepareVerticalAlbumMessage, prepareVideoGridMessage, prepareHtmlMessage, prepareRichHtmlMessage, buildRichLabelMessage, attachBotVerificationProofs, hasVerifiableProofs } from '../Utils/rich-message-utils.js';
9
21
  import { generateSlotMachineHtml } from '../Utils/games/slot-machine.js';
@@ -1118,6 +1130,44 @@ export const makeMessagesSocket = (config) => {
1118
1130
  ...sendOptions
1119
1131
  });
1120
1132
  };
1133
+ const sendLivePhoto = async (jid, content, quoted, sendOptions = {}) => {
1134
+ const userJid = authState.creds.me?.id;
1135
+ const {
1136
+ relayOptions: callerRelayOptions = {},
1137
+ photo_live: _photoLive,
1138
+ photoLive: _photoLiveCamel,
1139
+ thumbnail: _thumbnail,
1140
+ image: _image,
1141
+ videoThumbnail: _videoThumbnail,
1142
+ motionPhotoPresentationOffsetMs: _motionOffset,
1143
+ presentationOffsetMs: _presentationOffset,
1144
+ ...transportOptions
1145
+ } = sendOptions;
1146
+ const mediaOptions = {
1147
+ logger,
1148
+ userJid,
1149
+ upload: waUploadToServer,
1150
+ mediaCache: config.mediaCache,
1151
+ options: config.options,
1152
+ ...transportOptions,
1153
+ ...(quoted ? { quoted } : {})
1154
+ };
1155
+ return generateWAMessageFromLivePhoto(jid, content, async (message, relayOpts, fullMessage) => {
1156
+ await relayMessage(jid, message, {
1157
+ ...transportOptions,
1158
+ ...callerRelayOptions,
1159
+ useCachedGroupMetadata: sendOptions.useCachedGroupMetadata,
1160
+ statusJidList: sendOptions.statusJidList,
1161
+ statusPrivacy: sendOptions.statusPrivacy,
1162
+ messageId: relayOpts.messageId
1163
+ });
1164
+ if (config.emitOwnEvents && fullMessage) {
1165
+ process.nextTick(async () => {
1166
+ await messageMutex.mutex(() => upsertMessage(fullMessage, 'append'));
1167
+ });
1168
+ }
1169
+ }, mediaOptions);
1170
+ };
1121
1171
  const getMessageType = (message) => {
1122
1172
  if (!message)
1123
1173
  return 'text';
@@ -1348,26 +1398,37 @@ export const makeMessagesSocket = (config) => {
1348
1398
  await relayRichMessage(jid, fullMsg, options);
1349
1399
  return fullMsg;
1350
1400
  },
1351
- sendCarousel: async (jid, cards, options = {}) => {
1401
+ sendCarousel: async (jid, cards, quotedOrOptions = {}, maybeOptions = undefined) => {
1352
1402
  if (!Array.isArray(cards) || cards.length === 0) {
1353
1403
  throw new Boom('sendCarousel requires a non-empty card array', { statusCode: 400 });
1354
1404
  }
1405
+ // Support both Plogme's original (jid, cards, options) form and
1406
+ // the compatibility form used by working carousel helpers:
1407
+ // (jid, cards, quoted, options).
1408
+ const hasQuotedSignature = maybeOptions !== undefined;
1409
+ const quoted = hasQuotedSignature ? quotedOrOptions : undefined;
1410
+ const options = hasQuotedSignature ? (maybeOptions || {}) : (quotedOrOptions || {});
1355
1411
  const normalizedCards = cards.map(card => ({
1356
1412
  ...card,
1357
1413
  text: card.text ?? card.body?.text,
1358
1414
  caption: card.caption ?? card.body?.text,
1359
1415
  footer: card.footer?.text ?? card.footer,
1360
1416
  buttons: card.buttons ?? card.nativeFlowMessage?.buttons,
1417
+ ...(card.header?.imageMessage ? { image: typeof card.header.imageMessage === 'string' ? { url: card.header.imageMessage } : card.header.imageMessage } : {}),
1418
+ ...(card.header?.videoMessage ? { video: typeof card.header.videoMessage === 'string' ? { url: card.header.videoMessage } : card.header.videoMessage } : {}),
1361
1419
  ...(card.media?.image ? { image: card.media.image } : {}),
1362
1420
  ...(card.media?.video ? { video: card.media.video } : {}),
1363
- ...(card.media?.document ? { document: card.media.document } : {})
1421
+ ...(card.media?.document ? { document: card.media.document } : {}),
1422
+ ...(card.header?.title ? { title: card.title ?? card.header.title } : {}),
1423
+ ...(card.header?.subtitle ? { subtitle: card.subtitle ?? card.header.subtitle } : {}),
1424
+ ...(card.nativeFlowMessage?.buttons ? { nativeFlow: card.nativeFlow || card.nativeFlowMessage.buttons } : {})
1364
1425
  }));
1365
- const { text, footer, ...messageOptions } = options;
1426
+ const { text, content, footer, ...messageOptions } = options;
1366
1427
  const fullMsg = await generateWAMessage(jid, {
1367
1428
  ...messageOptions,
1368
1429
  cards: normalizedCards,
1369
1430
  ...(options.carouselCardType != null ? { carouselCardType: options.carouselCardType } : {}),
1370
- ...(text !== undefined ? { text } : {}),
1431
+ ...((text ?? content) !== undefined ? { text: text ?? content } : {}),
1371
1432
  ...(footer !== undefined ? { footer } : {})
1372
1433
  }, {
1373
1434
  logger,
@@ -1376,11 +1437,244 @@ export const makeMessagesSocket = (config) => {
1376
1437
  mediaCache: config.mediaCache,
1377
1438
  options: config.options,
1378
1439
  ...options,
1440
+ ...(quoted ? { quoted } : {}),
1379
1441
  messageId: options.messageId || generateMessageIDV2(jid)
1380
1442
  });
1381
1443
  await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, ...options });
1382
1444
  return fullMsg;
1383
1445
  },
1446
+ /** Send legacy reply buttons with an optional single media or location header. */
1447
+ replyButton: async (jid, buttons, quotedOrOptions = {}, maybeOptions = undefined) => {
1448
+ if (!jid) throw new Boom('replyButton requires a target JID', { statusCode: 400 });
1449
+ if (!Array.isArray(buttons) || buttons.length === 0) {
1450
+ throw new Boom('replyButton requires at least one button', { statusCode: 400 });
1451
+ }
1452
+ const hasQuotedSignature = !!(quotedOrOptions?.key && quotedOrOptions?.message);
1453
+ const quoted = hasQuotedSignature ? quotedOrOptions : undefined;
1454
+ const options = hasQuotedSignature ? (maybeOptions || {}) : (maybeOptions || quotedOrOptions || {});
1455
+ const normalizeButton = (button, index) => {
1456
+ if (!button || typeof button !== 'object') {
1457
+ throw new Boom(`replyButton button ${index + 1} must be an object`, { statusCode: 400 });
1458
+ }
1459
+ const label = button.text || button.buttonText || button.displayText || `Option ${index + 1}`;
1460
+ if (button.sections) {
1461
+ return {
1462
+ name: 'single_select',
1463
+ paramsJson: JSON.stringify({ title: label, sections: button.sections })
1464
+ };
1465
+ }
1466
+ if (button.name) {
1467
+ return {
1468
+ ...button,
1469
+ paramsJson: typeof button.paramsJson === 'string'
1470
+ ? button.paramsJson
1471
+ : JSON.stringify(button.params || {})
1472
+ };
1473
+ }
1474
+ if (button.url) {
1475
+ return {
1476
+ name: 'cta_url',
1477
+ paramsJson: JSON.stringify({
1478
+ display_text: label,
1479
+ url: button.url,
1480
+ merchant_url: button.merchantUrl || button.url
1481
+ })
1482
+ };
1483
+ }
1484
+ if (button.call || button.phoneNumber) {
1485
+ return {
1486
+ name: 'cta_call',
1487
+ paramsJson: JSON.stringify({ display_text: label, phone_number: button.call || button.phoneNumber })
1488
+ };
1489
+ }
1490
+ if (button.copy || button.copyCode) {
1491
+ return {
1492
+ name: 'cta_copy',
1493
+ paramsJson: JSON.stringify({ display_text: label, copy_code: button.copy || button.copyCode })
1494
+ };
1495
+ }
1496
+ const id = button.command || button.id || button.buttonId;
1497
+ if (!id) throw new Boom(`replyButton button ${index + 1} needs an id, command, or native-flow action`, { statusCode: 400 });
1498
+ return { text: label, id, ...(button.type != null ? { type: button.type } : {}) };
1499
+ };
1500
+ const location = options.location;
1501
+ const documentOptions = options.document && typeof options.document === 'object' ? options.document : {};
1502
+ const media = options.media ?? options.image ?? options.video ?? options.document?.url;
1503
+ const hasExplicitMedia = options.image != null || options.video != null || options.document != null || options.media != null;
1504
+ if (location && hasExplicitMedia) {
1505
+ throw new Boom('replyButton accepts one header attachment; choose either location or media', { statusCode: 400 });
1506
+ }
1507
+ if (hasExplicitMedia && media == null) {
1508
+ throw new Boom('replyButton media header requires an image, video, or document source', { statusCode: 400 });
1509
+ }
1510
+ const content = { buttons: buttons.map(normalizeButton) };
1511
+ if (options.footer !== undefined) content.footer = options.footer;
1512
+ if (options.title !== undefined) content.title = options.title;
1513
+ const text = options.text ?? options.caption ?? '';
1514
+ if (location) {
1515
+ content.location = {
1516
+ ...location,
1517
+ ...(location.description && !location.address ? { address: location.description } : {})
1518
+ };
1519
+ content.caption = text;
1520
+ }
1521
+ else if (hasExplicitMedia) {
1522
+ const source = media == null ? options.document : media;
1523
+ const sourceName = String(options.filename || documentOptions.filename || (typeof source === 'string' ? source : source?.url || '')).toLowerCase();
1524
+ const mimeType = options.mimetype || documentOptions.mimetype || source?.mimetype || '';
1525
+ const extension = sourceName.split(/[?#]/)[0].split('.').pop();
1526
+ let mediaType = options.mediaType || (options.document ? 'document' : options.video ? 'video' : undefined);
1527
+ if (!mediaType) {
1528
+ mediaType = mimeType.startsWith('video/') || ['mp4', 'mov', 'm4v', '3gp'].includes(extension) ? 'video' : 'image';
1529
+ }
1530
+ if (!['image', 'video', 'document'].includes(mediaType)) {
1531
+ throw new Boom('replyButton mediaType must be image, video, or document', { statusCode: 400 });
1532
+ }
1533
+ const mediaInput = typeof source === 'string' ? { url: source } : source;
1534
+ content[mediaType] = mediaInput;
1535
+ if (mediaType === 'document') {
1536
+ content.fileName = options.filename || documentOptions.filename || 'file';
1537
+ if (mimeType) content.mimetype = mimeType;
1538
+ }
1539
+ content.caption = text;
1540
+ }
1541
+ else {
1542
+ content.text = text;
1543
+ }
1544
+ const {
1545
+ text: _text, caption: _caption, footer: _footer, title: _title,
1546
+ location: _location, media: _media, image: _image, video: _video,
1547
+ document: _document, filename: _filename, mimetype: _mimetype,
1548
+ mediaType: _mediaType, sendOptions: nestedSendOptions = {},
1549
+ ...transportOptions
1550
+ } = options;
1551
+ return socket.sendMessage(jid, content, {
1552
+ ...transportOptions,
1553
+ ...nestedSendOptions,
1554
+ ...(quoted ? { quoted } : {})
1555
+ });
1556
+ },
1557
+ /** Send a motion photo from its video and optional still image/thumbnail. */
1558
+ sendPhotoLive: async (jid, content, quoted, options = {}) => {
1559
+ if (!jid) throw new Boom('sendPhotoLive requires a target JID', { statusCode: 400 });
1560
+ return sendLivePhoto(jid, content, quoted, options);
1561
+ },
1562
+ /** Send a file; `photo_live: true` pairs a still with its motion-video child. */
1563
+ sendFile: async (jid, media, filename = '', caption = '', quoted, options = {}) => {
1564
+ if (!jid) throw new Boom('sendFile requires a target JID', { statusCode: 400 });
1565
+ if (options.photo_live || options.photoLive) {
1566
+ return sendLivePhoto(jid, {
1567
+ video: media,
1568
+ image: options.image,
1569
+ thumbnail: options.thumbnail,
1570
+ videoThumbnail: options.videoThumbnail,
1571
+ caption,
1572
+ motionPhotoPresentationOffsetMs: options.motionPhotoPresentationOffsetMs ?? options.presentationOffsetMs
1573
+ }, quoted, options);
1574
+ }
1575
+ const sourceName = String(filename || options.fileName || (typeof media === 'string' ? media : media?.url || '')).toLowerCase();
1576
+ const extension = sourceName.split(/[?#]/)[0].split('.').pop();
1577
+ const mimeType = options.mimetype || media?.mimetype || '';
1578
+ const mediaType = options.mediaType || (options.document ? 'document' : mimeType.startsWith('image/') ? 'image' : mimeType.startsWith('video/') ? 'video' : mimeType.startsWith('audio/') ? 'audio' : ['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic'].includes(extension) ? 'image' : ['mp4', 'mov', 'm4v', '3gp', 'webm'].includes(extension) ? 'video' : ['mp3', 'ogg', 'opus', 'wav', 'm4a', 'aac'].includes(extension) ? 'audio' : 'document');
1579
+ if (!['image', 'video', 'audio', 'document'].includes(mediaType)) {
1580
+ throw new Boom('sendFile mediaType must be image, video, audio, or document', { statusCode: 400 });
1581
+ }
1582
+ const source = typeof media === 'string' ? { url: media } : media;
1583
+ const message = {
1584
+ [mediaType]: source,
1585
+ caption,
1586
+ ...(filename || options.fileName ? { fileName: filename || options.fileName } : {}),
1587
+ ...(mimeType ? { mimetype: mimeType } : {}),
1588
+ ...(mediaType === 'audio' && options.ptt ? { ptt: true } : {})
1589
+ };
1590
+ const { photo_live: _photoLive, photoLive: _photoLiveCamel, thumbnail: _thumbnail, ...sendOptions } = options;
1591
+ return socket.sendMessage(jid, message, {
1592
+ ...sendOptions,
1593
+ ...(quoted ? { quoted } : {})
1594
+ });
1595
+ },
1596
+ /** Send or edit a textual progress bar; pass messageKey to update in place. */
1597
+ sendProgress: async (jid, text, quotedOrOptions = {}, maybeOptions = undefined) => {
1598
+ if (!jid) throw new Boom('sendProgress requires a target JID', { statusCode: 400 });
1599
+ const hasQuotedSignature = !!(quotedOrOptions?.key && quotedOrOptions?.message);
1600
+ const quoted = hasQuotedSignature ? quotedOrOptions : undefined;
1601
+ const options = hasQuotedSignature ? (maybeOptions || {}) : (maybeOptions || quotedOrOptions || {});
1602
+ const progress = Number(options.progress ?? 0);
1603
+ if (!Number.isFinite(progress) || progress < 0 || progress > 100) {
1604
+ throw new Boom('sendProgress progress must be between 0 and 100', { statusCode: 400 });
1605
+ }
1606
+ const width = Math.max(4, Math.min(40, Math.floor(Number(options.width) || 12)));
1607
+ const percent = Math.round(progress);
1608
+ const filled = Math.round(width * percent / 100);
1609
+ const bar = `[${'█'.repeat(filled)}${'░'.repeat(width - filled)}] ${percent}%`;
1610
+ const content = { text: `${String(text || '')}${text ? '\n' : ''}${bar}` };
1611
+ const messageKey = options.messageKey || options.editKey;
1612
+ if (messageKey) content.edit = messageKey;
1613
+ const {
1614
+ progress: _progress, width: _width, messageKey: _messageKey, editKey: _editKey,
1615
+ sendOptions: nestedSendOptions = {}, ...sendOptions
1616
+ } = options;
1617
+ return socket.sendMessage(jid, content, {
1618
+ ...sendOptions,
1619
+ ...nestedSendOptions,
1620
+ ...(quoted ? { quoted } : {})
1621
+ });
1622
+ },
1623
+ /** Send text with a custom external preview card (thumbnail, title, URL and attribution). */
1624
+ sendMessageModify: async (jid, text, quotedOrOptions = {}, maybeOptions = undefined) => {
1625
+ if (!jid) throw new Boom('sendMessageModify requires a target JID', { statusCode: 400 });
1626
+ const hasQuotedSignature = !!(quotedOrOptions?.key && quotedOrOptions?.message);
1627
+ const quoted = hasQuotedSignature ? quotedOrOptions : undefined;
1628
+ const options = hasQuotedSignature ? (maybeOptions || {}) : (maybeOptions || quotedOrOptions || {});
1629
+ const thumbnail = options.thumbnail;
1630
+ const thumbnailSource = typeof thumbnail === 'string' ? thumbnail : thumbnail?.url;
1631
+ const thumbnailUrl = thumbnailSource && /^https?:\/\//i.test(thumbnailSource)
1632
+ ? thumbnailSource
1633
+ : options.thumbnailUrl || options.originalImageUrl;
1634
+ let thumbnailBuffer;
1635
+ if (Buffer.isBuffer(thumbnail) || thumbnail instanceof Uint8Array) {
1636
+ thumbnailBuffer = Buffer.from(thumbnail);
1637
+ }
1638
+ else if (typeof thumbnailSource === 'string' && !/^https?:\/\//i.test(thumbnailSource)) {
1639
+ try {
1640
+ thumbnailBuffer = (await extractImageThumb(thumbnailSource, 192)).buffer;
1641
+ }
1642
+ catch (error) {
1643
+ throw new Boom(`sendMessageModify could not read thumbnail: ${error.message}`, { statusCode: 400 });
1644
+ }
1645
+ }
1646
+ const externalAdReply = {
1647
+ title: options.title || '',
1648
+ body: options.description || options.body || '',
1649
+ mediaType: thumbnailBuffer || thumbnailUrl ? 1 : 0,
1650
+ ...(thumbnailBuffer ? { thumbnail: thumbnailBuffer } : {}),
1651
+ ...(thumbnailUrl ? { thumbnailUrl, originalImageUrl: thumbnailUrl } : {}),
1652
+ ...(options.url ? { mediaUrl: options.url, sourceUrl: options.url } : {}),
1653
+ showAdAttribution: options.ads ?? false,
1654
+ renderLargerThumbnail: options.largeThumb ?? options.largeThumbnail ?? true
1655
+ };
1656
+ const message = {
1657
+ text: String(text ?? ''),
1658
+ externalAdReply,
1659
+ ...(options.icon ? { favicon: typeof options.icon === 'string' ? { url: options.icon } : options.icon } : {})
1660
+ };
1661
+ const {
1662
+ title: _title, description: _description, body: _body, url: _url,
1663
+ thumbnail: _thumbnailValue, thumbnailUrl: _thumbnailUrl,
1664
+ originalImageUrl: _originalImageUrl, icon: _icon,
1665
+ ads: _ads, largeThumb: _largeThumb, largeThumbnail: _largeThumbnail,
1666
+ ratio: _ratio, type: _type, sendOptions: nestedSendOptions = {},
1667
+ ...transportOptions
1668
+ } = options;
1669
+ return socket.sendMessage(jid, message, {
1670
+ ...transportOptions,
1671
+ ...nestedSendOptions,
1672
+ ...(quoted ? { quoted } : {})
1673
+ });
1674
+ },
1675
+ /** Compatibility alias for sendMessageModify. */
1676
+ sendMessageModifyV2: async (jid, text, quotedOrOptions = {}, maybeOptions = undefined) =>
1677
+ socket.sendMessageModify(jid, text, quotedOrOptions, maybeOptions),
1384
1678
  sendLatex: async (jid, quoted, options = {}) => {
1385
1679
  const { message, messageId } = generateLatexContent(quoted, { expressions: [], ...options });
1386
1680
  const fullMsg = generateWAMessageFromContent(jid, message, {
@@ -1496,7 +1790,7 @@ export const makeMessagesSocket = (config) => {
1496
1790
  await relayMessage(jid, message, relayOptions);
1497
1791
  return msgId;
1498
1792
  },
1499
- // Additive Nexus-compatible AI-rich helpers. Existing Gen4/table/grid/carousel APIs remain unchanged.
1793
+ // Additive New-compatible AI-rich helpers. Existing Gen4/table/grid/carousel APIs remain unchanged.
1500
1794
  sendRichMedia: async (jid, content = {}, quoted, options = {}) => {
1501
1795
  const contentMessage = prepareRichResponseMessage({ ...content, noDonation: options.noDonation ?? true });
1502
1796
  const generated = generateWAMessageFromContent(jid, contentMessage, {
@@ -1509,6 +1803,13 @@ export const makeMessagesSocket = (config) => {
1509
1803
  await relayRichMessage(jid, generated, options);
1510
1804
  return { ...generated, messageId: generated.key.id };
1511
1805
  },
1806
+ /**
1807
+ * Send native Plogme rich media with the additive New compatibility field
1808
+ * compatibility sections enabled. The native serializer is retained.
1809
+ */
1810
+ sendNewRichMedia: async (jid, content = {}, quoted, options = {}) => {
1811
+ return socket.sendRichMedia(jid, { ...content, compatibility: 'both' }, quoted, options);
1812
+ },
1512
1813
  /**
1513
1814
  * Send a native AI image/video generation card. The returned messageId
1514
1815
  * is required by updateRichGeneration() for an in-place edit.
package/lib/Socket/mex.js CHANGED
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/mex.js
5
+ * About: Mex module for the Plogme WhatsApp protocol client.
6
+ * Important exports: executeWMexQuery
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { Boom } from '@hapi/boom';
2
14
  import { getBinaryNodeChild, S_WHATSAPP_NET } from '../WABinary/index.js';
3
15
  const wMexQuery = (variables, queryId, query, generateMessageTag) => {
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/newsletter.js
5
+ * About: Newsletter module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeNewsletterSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { Boom } from '@hapi/boom';
2
14
  import { proto } from '../../WAProto/index.js';
3
15
  import { QueryIds, XWAPaths } from '../Types/index.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/privacy.js
5
+ * About: Privacy module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makePrivacySocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { executeWMexQuery } from './mex.js';
2
14
 
3
15
  /**
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/registration.js
5
+ * About: Registration module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeRegistrationSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { executeWMexQuery } from './mex.js';
2
14
 
3
15
  const REGISTRATION_MEX_IDS = {
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/socket.js
5
+ * About: Socket module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { Boom } from '@hapi/boom';
2
14
  import { randomBytes } from 'crypto';
3
15
  import { URL } from 'url';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Socket/username.js
5
+ * About: Username module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeUsernameSocket
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { randomUUID } from 'crypto';
2
14
  import { executeWMexQuery } from './mex.js';
3
15
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Store/index.js
5
+ * About: Store module for the Plogme WhatsApp protocol client.
6
+ * Important exports: No public exports detected; module side effects or declarations are local.
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  export * from './make-cache-manager-store.js';
2
14
  export * from './make-in-memory-store.js';
3
15
  export * from './make-ordered-dictionary.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Store/make-cache-manager-store.js
5
+ * About: Make cache manager store module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeCacheManagerAuthState
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  import { createCache } from 'cache-manager';
2
14
  import { proto } from '../../WAProto/index.js';
3
15
  import { BufferJSON, initAuthCreds } from '../Utils/index.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Store/make-in-memory-store.js
5
+ * About: Make in memory store module for the Plogme WhatsApp protocol client.
6
+ * Important exports: waChatKey, waMessageID, waLabelAssociationKey, makeInMemoryStore
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  /**
2
14
  * Lia@Note 03-02-26 [WIP]
3
15
  * Manually converted to ESM and modified by me
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Store/make-ordered-dictionary.js
5
+ * About: Make ordered dictionary module for the Plogme WhatsApp protocol client.
6
+ * Important exports: makeOrderedDictionary
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  export function makeOrderedDictionary(idGetter) {
2
14
  const array = [];
3
15
  const dict = {};
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Store/object-repository.js
5
+ * About: Object repository module for the Plogme WhatsApp protocol client.
6
+ * Important exports: ObjectRepository
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  export class ObjectRepository {
2
14
  constructor(entities = {}) {
3
15
  this.entityMap = new Map(Object.entries(entities));
package/lib/Types/Auth.js CHANGED
@@ -1 +1,13 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Types/Auth.js
5
+ * About: Auth module for the Plogme WhatsApp protocol client.
6
+ * Important exports: No public exports detected; module side effects or declarations are local.
7
+ * Directions: Import the listed exports and preserve protocol, validation, and compatibility invariants when modifying.
8
+ *
9
+ * Copyright and attribution notice.
10
+ * Do not copy, reproduce, redistribute, modify, or create derivative works
11
+ * from this source without explicit written permission.
12
+ */
1
13
  export {};