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/Utils/rich-message-utils.js
5
+ * About: Rich message utils module for the Plogme WhatsApp protocol client.
6
+ * Important exports: tokenizeCode, normalizeNewReel, normalizeNewRichImage, prepareNewRichMediaCompatibility, toUnified, buildImaginePrimitive, prepareRichGenerationMessage, buildAdditionalBotMetadataContext; …
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@Changes 09-04-26 [WIP]
3
15
  * Adds support for tables and code blocks with richResponseMessage (wrapped inside botForwardedMessage).
@@ -11,6 +23,7 @@ import { LANGUAGE_KEYWORDS } from '../WABinary/constants.js';
11
23
  import { CodeHighlightType, RichSubMessageType } from '../Types/RichType.js';
12
24
  import { proto } from '../../WAProto/index.js';
13
25
  import { unixTimestampSeconds } from './generics.js';
26
+ import { generateTableContent } from './message-composer.js';
14
27
  const NOOP = new Set([]);
15
28
  export const tokenizeCode = (code, language = 'javascript') => {
16
29
  const keywords = LANGUAGE_KEYWORDS[language] || NOOP;
@@ -88,6 +101,54 @@ const buildRichImagePrimitive = (image = {}, expiration = String(Date.now() + 30
88
101
  primitive.dark_mode_full_image = media(darkFullUrl, darkWidth, darkHeight);
89
102
  return primitive;
90
103
  };
104
+
105
+ /** Normalize the field names used by New compatibility's Meta/reels helpers. */
106
+ export const normalizeNewReel = (reel = {}) => ({
107
+ reels_url: reel.videoUrl || reel.video_url || reel.reels_url || reel.reelsUrl || reel.url || '',
108
+ thumbnail_url: reel.thumbnailUrl || reel.thumbnail_url || reel.thumbnail || '',
109
+ creator: reel.creator || reel.username || reel.title || '',
110
+ avatar_url: reel.profileIconUrl || reel.avatar_url || reel.avatar || reel.icon || '',
111
+ reels_title: reel.title || reel.reels_title || reel.reelsTitle || '',
112
+ likes_count: reel.likesCount ?? reel.likes_count ?? reel.likes ?? 0,
113
+ comments_count: reel.commentsCount ?? reel.comments_count ?? reel.comments ?? 0,
114
+ shares_count: reel.sharesCount ?? reel.shares_count ?? reel.shares ?? 0,
115
+ view_count: reel.viewCount ?? reel.view_count ?? reel.views ?? 0,
116
+ reel_source: reel.reelSource || reel.reel_source || reel.source || 'IG',
117
+ is_verified: !!(reel.isVerified ?? reel.is_verified ?? reel.verified),
118
+ orientation: reel.orientation || reel.ratio || 'LANDSCAPE',
119
+ post_type: reel.postType || reel.post_type || 'VIDEO',
120
+ is_carousel: reel.isCarousel ?? reel.is_carousel ?? false
121
+ });
122
+
123
+ /** Build the New-compatible image/post shape without replacing native image data. */
124
+ export const normalizeNewRichImage = (image = {}) => ({
125
+ thumbnail_url: image.thumbnailUrl || image.thumbnail_url || image.thumbnail || image.previewUrl || image.preview_url || '',
126
+ image_url: image.imageUrl || image.image_url || image.fullUrl || image.full_url || image.url || '',
127
+ source_url: image.sourceUrl || image.source_url || image.url || '',
128
+ title: image.title || image.caption || '',
129
+ creator: image.creator || image.username || '',
130
+ avatar_url: image.profileIconUrl || image.avatar_url || image.avatar || '',
131
+ is_verified: !!(image.isVerified ?? image.is_verified ?? image.verified),
132
+ post_caption: image.postCaption || image.post_caption || image.caption || '',
133
+ likes_count: image.likesCount ?? image.likes_count ?? image.likes ?? 0,
134
+ comments_count: image.commentsCount ?? image.comments_count ?? image.comments ?? 0,
135
+ shares_count: image.sharesCount ?? image.shares_count ?? image.shares ?? 0,
136
+ orientation: image.orientation || image.ratio || 'LANDSCAPE',
137
+ post_type: image.postType || image.post_type || 'IMAGE',
138
+ is_carousel: image.isCarousel ?? image.is_carousel ?? false
139
+ });
140
+
141
+ /** Create the second New-shaped representation beside native AIRich sections. */
142
+ export const prepareNewRichMediaCompatibility = (content = {}) => {
143
+ const reels = (Array.isArray(content.reels) ? content.reels : []).map(normalizeNewReel);
144
+ const images = (Array.isArray(content.images) ? content.images : content.image ? [content.image] : []).map(normalizeNewRichImage);
145
+ const posts = (Array.isArray(content.posts) ? content.posts : content.post ? [content.post] : []).map(normalizeNewRichImage);
146
+ const sections = [];
147
+ if (reels.length) sections.push({ view_model: { primitives: reels.map(item => ({ ...item, __typename: 'GenAIReelPrimitive' })), __typename: 'GenAIHScrollLayoutViewModel' } });
148
+ if (images.length) sections.push({ view_model: { primitives: images.map(item => ({ ...item, __typename: 'GenAIImagePrimitive' })), __typename: 'GenAIHScrollLayoutViewModel' } });
149
+ if (posts.length) sections.push({ view_model: { primitives: posts.map(item => ({ ...item, __typename: 'GenAIPostPrimitive' })), __typename: 'GenAIHScrollLayoutViewModel' } });
150
+ return { compatibility: 'new-rich-media', reels, images, posts, sections };
151
+ };
91
152
  // Lia@Changes 09-04-26 --- Inject buffer into unifiedResponse.data to support proper rendering of rich messages (ex: tables and code blocks)
92
153
  export const toUnified = (submessages, uuid) => ({
93
154
  response_id: uuid || randomUUID(),
@@ -1388,8 +1449,8 @@ const buildRichHtmlScreen = (options = {}) => {
1388
1449
  };
1389
1450
  };
1390
1451
 
1391
- export const prepareRichResponseMessage = (content) => {
1392
- const { alignment, code, contentText, disclaimerText, footerText, headerText, html, richHtml, trustedSources, imageText, inlineImage, inlineVideo, items, language, latex, links, noDonation, noHeading, posts, products, reels, sources: sourceInputs, suggested, richResponse, table, tapLinkUrl, title, verificationMetadata, sections: rawSections, richSections, copyButton, copyToClipboard, copyText, copyLabel, richText, quote, richImage, richLinks, richMap, map, dynamicMedia, richDynamicMedia, socialEntity, socialProfile, richMenu, airichCommandMenu, unifiedResponse, gridImages, verticalAlbum, videoGrid, richGeneration, richLabel, suggestedPrompt, botSources, botPttTranscript } = content;
1452
+ const prepareRichResponseMessageFixedOrder = (content) => {
1453
+ const { alignment, code, compatibility, contentText, disclaimerText, footerText, headerText, html, richHtml, trustedSources, imageText, image, images, inlineImage, inlineVideo, items, language, latex, links, noDonation, noHeading, posts, products, reels, sources: sourceInputs, suggested, richResponse, table, tapLinkUrl, title, verificationMetadata, sections: rawSections, richSections, copyButton, copyToClipboard, copyText, copyLabel, richText, quote, richImage, richLinks, richMap, map, dynamicMedia, richDynamicMedia, socialEntity, socialProfile, richMenu, airichCommandMenu, unifiedResponse, gridImages, verticalAlbum, videoGrid, richGeneration, richLabel, suggestedPrompt, botSources, botPttTranscript } = content;
1393
1454
  let submessages = [];
1394
1455
  const extraSections = [];
1395
1456
  if (Array.isArray(richResponse)) {
@@ -1547,11 +1608,11 @@ export const prepareRichResponseMessage = (content) => {
1547
1608
  view_model: {
1548
1609
  primitive: buildImaginePrimitive({
1549
1610
  mediaType: 'video',
1550
- url: video?.url || video?.videoUrl || '',
1551
- mimeType: video?.mimeType || video?.mime_type || 'video/mp4',
1552
- fileLength: video?.fileLength || video?.file_length || 0,
1553
- duration: video?.duration || 0,
1554
- thumbnail: video?.thumbnail,
1611
+ url: video?.url || video?.videoUrl || video?.video_url || '',
1612
+ mimeType: video?.mimeType || video?.mime_type || video?.mimetype || 'video/mp4',
1613
+ fileLength: video?.fileLength ?? video?.file_length ?? video?.filesize ?? 0,
1614
+ duration: video?.duration ?? 0,
1615
+ thumbnail: video?.thumbnail || video?.thumbnailUrl || video?.thumbnail_url,
1555
1616
  status: video?.status || 'READY'
1556
1617
  }),
1557
1618
  __typename: 'GenAISingleLayoutViewModel'
@@ -1687,14 +1748,14 @@ export const prepareRichResponseMessage = (content) => {
1687
1748
  messageText: 'SUGGESTED_PROMPT'
1688
1749
  });
1689
1750
  }
1690
- if (table) {
1751
+ if (Array.isArray(table)) {
1691
1752
  submessages.push({
1692
1753
  messageType: RichSubMessageType.TABLE,
1693
1754
  tableMetadata: {
1694
1755
  title,
1695
1756
  rows: table.map((items, index) => ({
1696
1757
  isHeading: !noHeading && index == 0,
1697
- items
1758
+ items: Array.isArray(items) ? items.map(String) : [String(items)]
1698
1759
  }))
1699
1760
  }
1700
1761
  });
@@ -1734,6 +1795,16 @@ export const prepareRichResponseMessage = (content) => {
1734
1795
  const uuid = randomUUID();
1735
1796
  const unified = toUnified(submessages, uuid);
1736
1797
  unified.sections = [...unified.sections.filter(Boolean), ...extraSections];
1798
+ if (compatibility === 'new-rich-media' || compatibility === 'both') {
1799
+ const compatible = prepareNewRichMediaCompatibility({ reels, images: images || (inlineImage ? [inlineImage] : image ? [image] : []), posts });
1800
+ unified.sections.push(...compatible.sections);
1801
+ unified.new_rich_media = {
1802
+ compatibility: compatible.compatibility,
1803
+ reels: compatible.reels,
1804
+ images: compatible.images,
1805
+ posts: compatible.posts
1806
+ };
1807
+ }
1737
1808
  if (richHtmlScreen) unified.embedded_screens = [richHtmlScreen.embeddedScreen];
1738
1809
 
1739
1810
  // Compose the remaining AIRich convenience formats as sections. These
@@ -1888,6 +1959,216 @@ const decodePreparedUnified = (prepared) => {
1888
1959
  }
1889
1960
  };
1890
1961
 
1962
+ /**
1963
+ * Compose each rich fragment in the order its key appears in the caller's
1964
+ * object. The fixed-order renderer remains the single source of wire formats;
1965
+ * this wrapper only orders independently rendered sections before combining
1966
+ * them into one AIRich response.
1967
+ */
1968
+ export const prepareRichResponseMessage = (content = {}) => {
1969
+ if (!content || typeof content !== 'object' || Array.isArray(content)) {
1970
+ throw new Boom('rich response content must be an object', { statusCode: 400 });
1971
+ }
1972
+ const submessages = [];
1973
+ const sections = [];
1974
+ const embeddedScreens = [];
1975
+ const mergedBotMetadata = {};
1976
+ const compatibility = content.compatibility === 'new-rich-media' || content.compatibility === 'both';
1977
+ let compatibilityAdded = false;
1978
+ let newRichMedia;
1979
+
1980
+ const appendPrepared = (prepared) => {
1981
+ const unified = decodePreparedUnified(prepared);
1982
+ if (Array.isArray(unified?.sections)) sections.push(...unified.sections.filter(Boolean));
1983
+ if (Array.isArray(unified?.embedded_screens)) embeddedScreens.push(...unified.embedded_screens);
1984
+ const richResponse = prepared?.botForwardedMessage?.message?.richResponseMessage;
1985
+ if (Array.isArray(richResponse?.submessages)) submessages.push(...richResponse.submessages);
1986
+ const botMetadata = prepared?.messageContextInfo?.botMetadata;
1987
+ if (botMetadata) Object.assign(mergedBotMetadata, botMetadata);
1988
+ };
1989
+
1990
+ const appendField = (key, value) => {
1991
+ const fragment = { noDonation: true, verificationMetadata: content.verificationMetadata };
1992
+ switch (key) {
1993
+ case 'text':
1994
+ fragment.contentText = value;
1995
+ break;
1996
+ case 'table':
1997
+ appendTableValue(value);
1998
+ return;
1999
+ case 'code':
2000
+ fragment.code = value;
2001
+ fragment.language = content.language;
2002
+ break;
2003
+ case 'inlineImage':
2004
+ fragment.inlineImage = value;
2005
+ fragment.imageText = content.imageText;
2006
+ fragment.alignment = content.alignment;
2007
+ fragment.tapLinkUrl = content.tapLinkUrl;
2008
+ break;
2009
+ case 'html':
2010
+ fragment.html = value;
2011
+ fragment.trustedSources = content.trustedSources;
2012
+ break;
2013
+ case 'richHtml':
2014
+ fragment.richHtml = value;
2015
+ fragment.trustedSources = content.trustedSources;
2016
+ break;
2017
+ case 'richTable':
2018
+ appendTableValue(value);
2019
+ return;
2020
+ case 'tables':
2021
+ if (Array.isArray(value)) value.forEach(appendTableValue);
2022
+ return;
2023
+ case 'richResponse': {
2024
+ if (!Array.isArray(value)) break;
2025
+ for (const item of value) {
2026
+ if (item?.inlineVideo) appendField('inlineVideo', item.inlineVideo);
2027
+ else if (Object.hasOwn(item || {}, 'table')) appendField('table', item.table);
2028
+ else if (item?.posts) appendField('posts', item.posts);
2029
+ else if (item?.products) appendField('products', item.products);
2030
+ else if (item?.suggested) appendField('suggested', item.suggested);
2031
+ else appendPrepared(prepareRichResponseMessageFixedOrder({
2032
+ richResponse: [item],
2033
+ noDonation: true,
2034
+ verificationMetadata: content.verificationMetadata
2035
+ }));
2036
+ }
2037
+ return;
2038
+ }
2039
+ case 'contentItemsGroup':
2040
+ Object.assign(fragment, value);
2041
+ break;
2042
+ default:
2043
+ fragment[key] = value;
2044
+ }
2045
+ appendPrepared(prepareRichResponseMessageFixedOrder(fragment));
2046
+ };
2047
+
2048
+ const appendSimpleTable = (tableRows) => {
2049
+ const normalizedRows = tableRows.map(row => Array.isArray(row) ? row : [row]);
2050
+ appendPrepared(prepareRichResponseMessageFixedOrder({
2051
+ table: normalizedRows,
2052
+ title: content.title,
2053
+ noHeading: content.noHeading,
2054
+ noDonation: true,
2055
+ verificationMetadata: content.verificationMetadata
2056
+ }));
2057
+ };
2058
+
2059
+ const appendRichTable = (table) => {
2060
+ if (!table || typeof table !== 'object' || Array.isArray(table)) return;
2061
+ const richTable = generateTableContent(
2062
+ String(table.title ?? ''),
2063
+ Array.isArray(table.headers) ? table.headers : [],
2064
+ Array.isArray(table.rows) ? table.rows : [],
2065
+ undefined,
2066
+ { headerText: table.headerText, footer: table.footer }
2067
+ );
2068
+ const richResponse = richTable?.message?.botForwardedMessage?.message?.richResponseMessage;
2069
+ if (Array.isArray(richResponse?.submessages)) submessages.push(...richResponse.submessages);
2070
+ };
2071
+
2072
+ const appendTableValue = (table) => {
2073
+ if (Array.isArray(table)) {
2074
+ appendSimpleTable(table);
2075
+ return;
2076
+ }
2077
+ if (!table || typeof table !== 'object') return;
2078
+ if (Array.isArray(table.headers) && Array.isArray(table.rows)) {
2079
+ appendRichTable(table);
2080
+ }
2081
+ else if (Array.isArray(table.rows)) {
2082
+ appendSimpleTable([...(Array.isArray(table.headers) ? [table.headers] : []), ...table.rows]);
2083
+ }
2084
+ };
2085
+
2086
+ const appendCompatibility = () => {
2087
+ if (compatibilityAdded || !compatibility) return;
2088
+ compatibilityAdded = true;
2089
+ const compatible = prepareNewRichMediaCompatibility({
2090
+ reels: content.reels,
2091
+ images: content.images || (content.image ? [content.image] : []),
2092
+ posts: content.posts
2093
+ });
2094
+ if (!compatible.sections.length) return;
2095
+ sections.push(...compatible.sections);
2096
+ newRichMedia = {
2097
+ compatibility: compatible.compatibility,
2098
+ reels: compatible.reels,
2099
+ images: compatible.images,
2100
+ posts: compatible.posts
2101
+ };
2102
+ };
2103
+
2104
+ const nonRenderableKeys = new Set([
2105
+ 'alignment', 'compatibility', 'copyLabel', 'disclaimerText',
2106
+ 'image', 'images', 'language', 'noDonation', 'noHeading', 'title',
2107
+ 'tapLinkUrl', 'trustedSources', 'verificationMetadata'
2108
+ ]);
2109
+ const renderableKeys = new Set([
2110
+ 'headerText', 'contentText', 'text', 'footerText', 'code', 'table', 'richTable', 'tables', 'items', 'reels',
2111
+ 'inlineImage', 'inlineVideo', 'latex', 'links', 'sources', 'posts', 'products', 'suggested',
2112
+ 'html', 'richHtml', 'richResponse', 'copyButton', 'copyToClipboard', 'copyText',
2113
+ 'richText', 'quote', 'richImage', 'richLinks', 'richMap', 'map', 'dynamicMedia',
2114
+ 'richDynamicMedia', 'socialEntity', 'socialProfile', 'richMenu', 'airichCommandMenu',
2115
+ 'unifiedResponse', 'gridImages', 'verticalAlbum', 'videoGrid', 'richGeneration',
2116
+ 'richLabel', 'suggestedPrompt', 'botSources', 'botPttTranscript', 'sections', 'richSections'
2117
+ ]);
2118
+ const inputEntries = Object.entries(content);
2119
+ const entries = [
2120
+ ...inputEntries.filter(([key]) => key === 'headerText'),
2121
+ ...inputEntries.filter(([key]) => key !== 'headerText' && key !== 'footerText'),
2122
+ ...inputEntries.filter(([key]) => key === 'footerText')
2123
+ ];
2124
+ for (let index = 0; index < entries.length; index++) {
2125
+ const [key, value] = entries[index];
2126
+ if (['reels', 'images', 'image', 'posts'].includes(key)) appendCompatibility();
2127
+ if (key === 'items' || key === 'reels') {
2128
+ const grouped = {};
2129
+ let nextIndex = index;
2130
+ while (nextIndex < entries.length && ['items', 'reels'].includes(entries[nextIndex][0])) {
2131
+ const [groupKey, groupValue] = entries[nextIndex];
2132
+ grouped[groupKey] = groupValue;
2133
+ nextIndex++;
2134
+ }
2135
+ if (Object.hasOwn(grouped, 'reels')) appendCompatibility();
2136
+ appendField('contentItemsGroup', grouped);
2137
+ index = nextIndex - 1;
2138
+ continue;
2139
+ }
2140
+ if (!renderableKeys.has(key) || nonRenderableKeys.has(key)) continue;
2141
+ appendField(key, value);
2142
+ }
2143
+
2144
+ if (content.noDonation !== true) {
2145
+ appendPrepared(prepareRichResponseMessageFixedOrder({ links: [], noDonation: false }));
2146
+ }
2147
+
2148
+ const responseId = randomUUID();
2149
+ const unified = {
2150
+ response_id: responseId,
2151
+ sections,
2152
+ ...(embeddedScreens.length ? { embedded_screens: embeddedScreens } : {}),
2153
+ ...(newRichMedia ? { new_rich_media: newRichMedia } : {})
2154
+ };
2155
+ const richResponseMessage = proto.AIRichResponseMessage.create({
2156
+ submessages,
2157
+ messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
2158
+ unifiedResponse: { data: Buffer.from(JSON.stringify(unified)) },
2159
+ contextInfo: { isForwarded: true, forwardingScore: 1, forwardedAiBotMessageInfo: { botJid: '867051314767696@bot' }, forwardOrigin: 4 }
2160
+ });
2161
+ const message = wrapToBotForwardedMessage(richResponseMessage, content.verificationMetadata);
2162
+ const botMetadata = message.messageContextInfo.botMetadata;
2163
+ Object.assign(botMetadata, mergedBotMetadata);
2164
+ if (content.disclaimerText) botMetadata.messageDisclaimerText = content.disclaimerText;
2165
+ botMetadata.botResponseId = responseId;
2166
+ const { sources, mediaDetailsMetadataList } = buildAdditionalBotMetadataContext(submessages);
2167
+ if (sources.length > 0) botMetadata.richResponseSourcesMetadata = { sources };
2168
+ if (mediaDetailsMetadataList.length > 0) botMetadata.unifiedResponseMutation = { mediaDetailsMetadataList };
2169
+ return message;
2170
+ };
2171
+
1891
2172
  /** Merge any prepared AIRich helper into a single PLOGME response. */
1892
2173
  const appendPreparedRichContent = (target, prepared) => {
1893
2174
  const unified = decodePreparedUnified(prepared);
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/signal.js
5
+ * About: Signal module for the Plogme WhatsApp protocol client.
6
+ * Important exports: createSignalIdentity, getPreKeys, generateOrGetPreKeys, xmppSignedPreKey, xmppPreKey, extractE2ESessionFromRetryReceipt, parseAndInjectE2ESessions, extractDeviceJids; …
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 { KEY_BUNDLE_TYPE } from '../Defaults/index.js';
2
14
  import { assertNodeErrorFree, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildUInt, getServerFromDomainType, jidDecode, S_WHATSAPP_NET, WAJIDDomains } from '../WABinary/index.js';
3
15
  import { Curve, generateSignalPubKey } from './crypto.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/source-grep.js
5
+ * About: Source grep module for the Plogme WhatsApp protocol client.
6
+ * Important exports: grepSource
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 fs from 'node:fs';
2
14
  import path from 'node:path';
3
15
  import { fileURLToPath } from 'node:url';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/stanza-ack.js
5
+ * About: Stanza ack module for the Plogme WhatsApp protocol client.
6
+ * Important exports: buildAckStanza
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
  * Builds an ACK stanza for a received node.
3
15
  * Pure function -- no I/O, no side effects.
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/sync-action-utils.js
5
+ * About: Sync action utils module for the Plogme WhatsApp protocol client.
6
+ * Important exports: processContactAction, emitSyncActionResults
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 { proto } from '../../WAProto/index.js';
2
14
  import { isLidUser, isPnUser } from '../WABinary/index.js';
3
15
  /**
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/tc-token-utils.js
5
+ * About: Tc token utils module for the Plogme WhatsApp protocol client.
6
+ * Important exports: TC_TOKEN_INDEX_KEY, readTcTokenIndex, buildMergedTcTokenIndexWrite, isTcTokenExpired, shouldSendNewTcToken, resolveTcTokenJid, resolveIssuanceJid, buildTcTokenFromJid; …
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, isHostedLidUser, isHostedPnUser, isJidMetaAI, isLidUser, isPnUser, jidNormalizedUser } from '../WABinary/index.js';
2
14
  // Same phone-number pattern as WABinary's isJidBot, applied against the user
3
15
  // part so the check is invariant to @c.us ↔ @s.whatsapp.net normalization.
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/use-multi-file-auth-state.js
5
+ * About: Use multi file auth state module for the Plogme WhatsApp protocol client.
6
+ * Important exports: useMultiFileAuthState
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 { Mutex } from 'async-mutex';
2
14
  import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises';
3
15
  import { join } from 'path';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/use-single-file-auth-state.js
5
+ * About: Use single file auth state module for the Plogme WhatsApp protocol client.
6
+ * Important exports: useSingleFileAuthState
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 { readFile, rename, stat, writeFile } from 'fs/promises';
2
14
  import { DEFAULT_CACHE_TTLS } from '../Defaults/index.js';
3
15
  import { proto } from '../../WAProto/index.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/use-sqlite-auth-state.js
5
+ * About: Use sqlite auth state module for the Plogme WhatsApp protocol client.
6
+ * Important exports: useSqliteAuthState
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 { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises';
2
14
  import { join } from 'path';
3
15
  import { proto } from '../../WAProto/index.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/validate-connection.js
5
+ * About: Validate connection module for the Plogme WhatsApp protocol client.
6
+ * Important exports: generateLoginNode, generateRegistrationNode, configureSuccessfulPairing, encodeSignedDeviceIdentity
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 { createHash } from 'crypto';
3
15
  import { proto } from '../../WAProto/index.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/view-once-utils.js
5
+ * About: View once utils module for the Plogme WhatsApp protocol client.
6
+ * Important exports: isViewOnceMessage, extractViewOnceContent, getViewOnceMediaType, getViewOnceMediaContent, downloadViewOnceMedia, createRegularMessageFromViewOnce, shouldAutoDecryptViewOnce, shouldDeleteViewOnce; …
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
  * View-Once Message Utilities
3
15
  *
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/voip-rekey.js
5
+ * About: Voip rekey module for the Plogme WhatsApp protocol client.
6
+ * Important exports: decodeE2eRekeyPayload
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 { proto } from '../../WAProto/index.js';
2
14
 
3
15
  const REKEY_TYPE_NAMES = {
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/Utils/welcome-flow.js
5
+ * About: Welcome flow module for the Plogme WhatsApp protocol client.
6
+ * Important exports: createWelcomeFlow
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@Changes [WIP]
3
15
  * Welcome Flow — Meta Business-style startup template.
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/WABinary/constants.js
5
+ * About: Constants module for the Plogme WhatsApp protocol client.
6
+ * Important exports: TAGS, DOUBLE_BYTE_TOKENS, SINGLE_BYTE_TOKENS, TOKEN_MAP, CPP_KEYWORDS, CSS_KEYWORDS, GO_KEYWORDS, HTML_KEYWORDS; …
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 const TAGS = {
2
14
  LIST_EMPTY: 0,
3
15
  DICTIONARY_0: 236,
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/WABinary/decode.js
5
+ * About: Decode module for the Plogme WhatsApp protocol client.
6
+ * Important exports: decompressingIfRequired, decodeDecompressedBinaryNode, decodeBinaryNode
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 { promisify } from 'util';
2
14
  import { inflate } from 'zlib';
3
15
  import * as constants from './constants.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/WABinary/encode.js
5
+ * About: Encode module for the Plogme WhatsApp protocol client.
6
+ * Important exports: encodeBinaryNode
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 * as constants from './constants.js';
2
14
  import { jidDecode } from './jid-utils.js';
3
15
  export const encodeBinaryNode = (node, opts = constants, buffer = [0]) => {
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/WABinary/generic-utils.js
5
+ * About: Generic utils module for the Plogme WhatsApp protocol client.
6
+ * Important exports: getBinaryNodeChildren, getBinaryNodeChild, getAllBinaryNodeChildren, getBinaryNodeChildBuffer, getBinaryNodeChildString, getBinaryNodeChildUInt, assertNodeErrorFree, reduceBinaryNodeToDictionary; …
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 { proto } from '../../WAProto/index.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/WABinary/index.js
5
+ * About: WABinary 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 './encode.js';
2
14
  export * from './decode.js';
3
15
  export * from './generic-utils.js';
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @crysnpvax
3
+ *
4
+ * File: lib/WABinary/jid-utils.js
5
+ * About: Jid utils module for the Plogme WhatsApp protocol client.
6
+ * Important exports: S_WHATSAPP_NET, OFFICIAL_BIZ_JID, SERVER_JID, PSA_WID, STORIES_JID, META_AI_JID, WAJIDDomains, getServerFromDomainType; …
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 const S_WHATSAPP_NET = '@s.whatsapp.net';
2
14
  export const OFFICIAL_BIZ_JID = '16505361212@c.us';
3
15
  export const SERVER_JID = 'server@c.us';