@yannajah/baileys 0.0.0-stage → 1.0.0

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 (145) hide show
  1. package/LICENSE +23 -0
  2. package/LICENSE.jexkcode +21 -0
  3. package/README.md +41 -2
  4. package/THIRD_PARTY_NOTICES.md +15 -0
  5. package/WAProto/index.d.ts +16922 -0
  6. package/WAProto/index.js +122451 -0
  7. package/engine-requirements.js +10 -0
  8. package/lib/Defaults/baileys-version.json +3 -0
  9. package/lib/Defaults/index.js +156 -0
  10. package/lib/Defaults/phonenumber-mcc.json +223 -0
  11. package/lib/Signal/Group/ciphertext-message.js +15 -0
  12. package/lib/Signal/Group/group-session-builder.js +64 -0
  13. package/lib/Signal/Group/group_cipher.js +96 -0
  14. package/lib/Signal/Group/index.js +57 -0
  15. package/lib/Signal/Group/keyhelper.js +55 -0
  16. package/lib/Signal/Group/queue-job.js +57 -0
  17. package/lib/Signal/Group/sender-chain-key.js +34 -0
  18. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  19. package/lib/Signal/Group/sender-key-message.js +69 -0
  20. package/lib/Signal/Group/sender-key-name.js +51 -0
  21. package/lib/Signal/Group/sender-key-record.js +53 -0
  22. package/lib/Signal/Group/sender-key-state.js +99 -0
  23. package/lib/Signal/Group/sender-message-key.js +29 -0
  24. package/lib/Signal/libsignal.js +174 -0
  25. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  26. package/lib/Socket/Client/index.js +19 -0
  27. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  28. package/lib/Socket/Client/web-socket-client.js +87 -0
  29. package/lib/Socket/business.js +260 -0
  30. package/lib/Socket/chats.js +1002 -0
  31. package/lib/Socket/clutch-handler.d.ts +27 -0
  32. package/lib/Socket/clutch-handler.js +880 -0
  33. package/lib/Socket/groups.js +317 -0
  34. package/lib/Socket/index.js +97 -0
  35. package/lib/Socket/messages-recv.js +1154 -0
  36. package/lib/Socket/messages-send.js +946 -0
  37. package/lib/Socket/newsletter.js +411 -0
  38. package/lib/Socket/registration.js +166 -0
  39. package/lib/Socket/socket.js +688 -0
  40. package/lib/Socket/usync.js +70 -0
  41. package/lib/Store/index.js +10 -0
  42. package/lib/Store/make-cache-manager-store.js +83 -0
  43. package/lib/Store/make-in-memory-store.js +457 -0
  44. package/lib/Store/make-ordered-dictionary.js +81 -0
  45. package/lib/Store/object-repository.js +27 -0
  46. package/lib/Types/Auth.js +2 -0
  47. package/lib/Types/Call.js +2 -0
  48. package/lib/Types/Chat.js +4 -0
  49. package/lib/Types/Contact.js +2 -0
  50. package/lib/Types/Events.js +2 -0
  51. package/lib/Types/GroupMetadata.js +2 -0
  52. package/lib/Types/Label.js +27 -0
  53. package/lib/Types/LabelAssociation.js +9 -0
  54. package/lib/Types/Message.js +10 -0
  55. package/lib/Types/Mex.d.ts +2 -0
  56. package/lib/Types/Mex.js +98 -0
  57. package/lib/Types/Newsletter.js +41 -0
  58. package/lib/Types/Product.js +2 -0
  59. package/lib/Types/Signal.js +2 -0
  60. package/lib/Types/Socket.js +2 -0
  61. package/lib/Types/State.js +2 -0
  62. package/lib/Types/USync.js +2 -0
  63. package/lib/Types/index.js +43 -0
  64. package/lib/Utils/MessageBuilder.d.ts +215 -0
  65. package/lib/Utils/MessageBuilder.js +4001 -0
  66. package/lib/Utils/a2ui.d.ts +202 -0
  67. package/lib/Utils/a2ui.js +770 -0
  68. package/lib/Utils/auth-utils.js +206 -0
  69. package/lib/Utils/baileys-event-stream.js +63 -0
  70. package/lib/Utils/bot-signature.d.ts +22 -0
  71. package/lib/Utils/bot-signature.js +125 -0
  72. package/lib/Utils/business.js +234 -0
  73. package/lib/Utils/channel-manager.d.ts +39 -0
  74. package/lib/Utils/channel-manager.js +312 -0
  75. package/lib/Utils/chat-utils.js +729 -0
  76. package/lib/Utils/crypto.js +151 -0
  77. package/lib/Utils/decode-wa-message.js +198 -0
  78. package/lib/Utils/event-buffer.js +514 -0
  79. package/lib/Utils/extras.d.ts +449 -0
  80. package/lib/Utils/extras.js +1377 -0
  81. package/lib/Utils/generics.js +574 -0
  82. package/lib/Utils/history.js +96 -0
  83. package/lib/Utils/html-app.d.ts +39 -0
  84. package/lib/Utils/html-app.js +307 -0
  85. package/lib/Utils/index.d.ts +23 -0
  86. package/lib/Utils/index.js +51 -0
  87. package/lib/Utils/link-preview.js +93 -0
  88. package/lib/Utils/logger.js +7 -0
  89. package/lib/Utils/lt-hash.js +51 -0
  90. package/lib/Utils/make-mutex.js +43 -0
  91. package/lib/Utils/message-retry-manager.d.ts +42 -0
  92. package/lib/Utils/message-retry-manager.js +309 -0
  93. package/lib/Utils/messages-media.js +861 -0
  94. package/lib/Utils/messages.js +1085 -0
  95. package/lib/Utils/metaai.d.ts +438 -0
  96. package/lib/Utils/metaai.js +911 -0
  97. package/lib/Utils/mini-app.d.ts +93 -0
  98. package/lib/Utils/mini-app.js +453 -0
  99. package/lib/Utils/modern-messages.d.ts +150 -0
  100. package/lib/Utils/modern-messages.js +498 -0
  101. package/lib/Utils/native-flow.d.ts +14 -0
  102. package/lib/Utils/native-flow.js +122 -0
  103. package/lib/Utils/newsletter-status.d.ts +163 -0
  104. package/lib/Utils/newsletter-status.js +695 -0
  105. package/lib/Utils/noise-handler.js +155 -0
  106. package/lib/Utils/payment-messages.d.ts +59 -0
  107. package/lib/Utils/payment-messages.js +164 -0
  108. package/lib/Utils/process-message.js +334 -0
  109. package/lib/Utils/reporting-utils.d.ts +12 -0
  110. package/lib/Utils/reporting-utils.js +271 -0
  111. package/lib/Utils/scheduled-message.d.ts +82 -0
  112. package/lib/Utils/scheduled-message.js +126 -0
  113. package/lib/Utils/signal.js +153 -0
  114. package/lib/Utils/spr.d.ts +26 -0
  115. package/lib/Utils/spr.js +525 -0
  116. package/lib/Utils/status-stickers.d.ts +78 -0
  117. package/lib/Utils/status-stickers.js +275 -0
  118. package/lib/Utils/telegram-adapter.d.ts +28 -0
  119. package/lib/Utils/telegram-adapter.js +285 -0
  120. package/lib/Utils/use-multi-file-auth-state.js +153 -0
  121. package/lib/Utils/validate-connection.js +235 -0
  122. package/lib/WABinary/constants.js +40 -0
  123. package/lib/WABinary/decode.js +252 -0
  124. package/lib/WABinary/encode.js +265 -0
  125. package/lib/WABinary/generic-utils.js +178 -0
  126. package/lib/WABinary/index.js +21 -0
  127. package/lib/WABinary/jid-utils.js +81 -0
  128. package/lib/WABinary/types.js +2 -0
  129. package/lib/WAM/BinaryInfo.js +13 -0
  130. package/lib/WAM/constants.js +15350 -0
  131. package/lib/WAM/encode.js +155 -0
  132. package/lib/WAM/index.js +19 -0
  133. package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
  134. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  135. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  136. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  137. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
  138. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  139. package/lib/WAUSync/Protocols/index.js +20 -0
  140. package/lib/WAUSync/USyncQuery.js +89 -0
  141. package/lib/WAUSync/USyncUser.js +26 -0
  142. package/lib/WAUSync/index.js +19 -0
  143. package/lib/index.d.ts +20 -0
  144. package/lib/index.js +99 -0
  145. package/package.json +110 -4
@@ -0,0 +1,911 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /* Upstream notices and license: see LICENSE and THIRD_PARTY_NOTICES.md. */
4
+ const { AddonActionType } = require("./extras");
5
+ const { generateWAMessageFromContent } = require("./messages");
6
+ const { BOT_SIGNATURE_USE_CASE_WA_BOT_MSG, verifyBotSignature } = require("./bot-signature");
7
+ let _AIRichMeta;
8
+ function getAIRich() {
9
+ if (!_AIRichMeta) {
10
+ _AIRichMeta = require("./MessageBuilder").AIRich;
11
+ }
12
+ return _AIRichMeta;
13
+ }
14
+ const AIRich = new Proxy(class {}, {
15
+ get(target, prop) {
16
+ const cls = getAIRich();
17
+ if (prop === "SECTION_TYPENAME") return cls?.SECTION_TYPENAME || "GenAIUnifiedResponseSection";
18
+ if (prop === "UNIFIED_RESPONSE_TYPENAME") return cls?.UNIFIED_RESPONSE_TYPENAME || "GenAIUnifiedResponse";
19
+ return cls ? cls[prop] : undefined;
20
+ },
21
+ construct(target, args) {
22
+ const cls = getAIRich();
23
+ return new cls(...args);
24
+ }
25
+ });
26
+
27
+ const MapQueryStatus = exports.MapQueryStatus = Object.freeze({ FETCHING: 'FETCHING', FETCHED: 'FETCHED', FAILED: 'FAILED' })
28
+ const MapItemMarkerType = exports.MapItemMarkerType = Object.freeze({ PIN: 'PIN', RADIUS: 'RADIUS' })
29
+ const PlaceDetailsItemType = exports.PlaceDetailsItemType = Object.freeze({ PLACE: 'PLACE', MARKETPLACE_LISTING: 'MARKETPLACE_LISTING' })
30
+ const PlaceOpeningStatus = exports.PlaceOpeningStatus = Object.freeze({ OPEN: 'OPEN', CLOSED: 'CLOSED' })
31
+ const PlacePriceLevel = exports.PlacePriceLevel = Object.freeze({ CHEAP: 'CHEAP', MODERATE: 'MODERATE', EXPENSIVE: 'EXPENSIVE', SPLURGE: 'SPLURGE' })
32
+
33
+ const ClippyArtifactType = exports.ClippyArtifactType = Object.freeze({ MINI_APP: 'MINI_APP', STATIC_HTML: 'STATIC_HTML' })
34
+
35
+ const SportsLeague = exports.SportsLeague = Object.freeze({ NFL: 'NFL', EURO: 'EURO', WORLD_CUP: 'WORLD_CUP' })
36
+ const SportsGameStatus = exports.SportsGameStatus = Object.freeze({ SCHEDULED: 'SCHEDULED', LIVE: 'LIVE', FINAL: 'FINAL' })
37
+ const SportsSeasonType = exports.SportsSeasonType = Object.freeze({ PRESEASON: 'PRESEASON', REGULAR: 'REGULAR', POSTSEASON: 'POSTSEASON' })
38
+
39
+ const CompactEntityType = exports.CompactEntityType = Object.freeze({
40
+ PERSON: 'PERSON',
41
+ PAGE: 'PAGE',
42
+ GROUP: 'GROUP',
43
+ INSTAGRAM_ACCOUNT: 'INSTAGRAM_ACCOUNT',
44
+ CALENDAR_EVENT: 'CALENDAR_EVENT'
45
+ })
46
+ const CompactEntityActionType = exports.CompactEntityActionType = Object.freeze({
47
+ FOLLOW: 'FOLLOW',
48
+ UNFOLLOW: 'UNFOLLOW',
49
+ JOIN: 'JOIN',
50
+ LEAVE: 'LEAVE',
51
+ MESSAGE: 'MESSAGE',
52
+ VIEW_DETAILS: 'VIEW_DETAILS'
53
+ })
54
+
55
+ const ActionListRowType = exports.ActionListRowType = Object.freeze({ ACTION: 'ACTION', NAVIGATION: 'NAVIGATION' })
56
+
57
+ const SocialEntityItemType = exports.SocialEntityItemType = Object.freeze({
58
+ FB_PROFILE: 'FB_PROFILE',
59
+ FB_PAGE: 'FB_PAGE',
60
+ FB_GROUP: 'FB_GROUP',
61
+ IG_PROFILE: 'IG_PROFILE',
62
+ THREADS_PROFILE: 'THREADS_PROFILE'
63
+ })
64
+
65
+ const SourceApp = exports.SourceApp = Object.freeze({ FACEBOOK: 'FACEBOOK', INSTAGRAM: 'INSTAGRAM', THREADS: 'THREADS' })
66
+ const PostType = exports.PostType = Object.freeze({ PAGE_POST: 'PAGE_POST', GROUP_POST: 'GROUP_POST' })
67
+ const PostOrientation = exports.PostOrientation = Object.freeze({ PORTRAIT: 'PORTRAIT', LANDSCAPE: 'LANDSCAPE' })
68
+ const ProductSourceType = exports.ProductSourceType = Object.freeze({ CATALOG: 'CATALOG', MARKETPLACE: 'MARKETPLACE' })
69
+
70
+ const SearchPlannerStepStatus = exports.SearchPlannerStepStatus = Object.freeze({
71
+ PLANNED: 'PLANNED',
72
+ IN_PROGRESS: 'IN_PROGRESS',
73
+ COMPLETED: 'COMPLETED',
74
+ STOPPED: 'STOPPED'
75
+ })
76
+ const OrchestratorSearchEngine = exports.OrchestratorSearchEngine = Object.freeze({
77
+ BING: 'BING',
78
+ BRAVE: 'BRAVE',
79
+ GOOGLE: 'GOOGLE',
80
+ HELP_CENTER: 'HELP_CENTER',
81
+ IN_HOUSE: 'IN_HOUSE',
82
+ KSS: 'KSS',
83
+ MASE: 'MASE'
84
+ })
85
+
86
+ const ProfessionalConsentStatus = exports.ProfessionalConsentStatus = Object.freeze({ ALLOWED: 'ALLOWED', NEEDS_CONSENT: 'NEEDS_CONSENT' })
87
+
88
+ const AccountLinkingIntegration = exports.AccountLinkingIntegration = Object.freeze({
89
+ APPLE_HEALTH: 'APPLE_HEALTH',
90
+ GMAIL: 'GMAIL',
91
+ GOOGLE_CALENDAR: 'GOOGLE_CALENDAR',
92
+ GOOGLE_CONTACTS: 'GOOGLE_CONTACTS',
93
+ GOOGLE_DRIVE: 'GOOGLE_DRIVE',
94
+ GOOGLE_HEALTH_CONNECT: 'GOOGLE_HEALTH_CONNECT',
95
+ OUTLOOK_CALENDAR: 'OUTLOOK_CALENDAR',
96
+ OUTLOOK_CONTACTS: 'OUTLOOK_CONTACTS',
97
+ OUTLOOK_MAIL: 'OUTLOOK_MAIL'
98
+ })
99
+ const AccountLinkingStatus = exports.AccountLinkingStatus = Object.freeze({ INITIATED: 'INITIATED', LINKED: 'LINKED', UNLINKED: 'UNLINKED' })
100
+
101
+ const CalendarEventOperation = exports.CalendarEventOperation = Object.freeze({ CREATE: 'CREATE', UPDATE: 'UPDATE', DELETE: 'DELETE' })
102
+ const CalendarEventState = exports.CalendarEventState = Object.freeze({ PENDING: 'PENDING', CONFIRMED: 'CONFIRMED', CANCELLED: 'CANCELLED' })
103
+ const WidgetCtaKind = exports.WidgetCtaKind = Object.freeze({ CONFIRM: 'CONFIRM', CANCEL: 'CANCEL', OTHER: 'OTHER' })
104
+ const WidgetCtaState = exports.WidgetCtaState = Object.freeze({ PENDING: 'PENDING', CONFIRMED: 'CONFIRMED', CANCELLED: 'CANCELLED' })
105
+
106
+ const MultipleResponseLayoutType = exports.MultipleResponseLayoutType = Object.freeze({ IN_THREAD: 'IN_THREAD', BOTTOM_SHEET: 'BOTTOM_SHEET' })
107
+
108
+ const ThreadSurfingEntityType = exports.ThreadSurfingEntityType = Object.freeze({
109
+ CELEBRITY: 'CELEBRITY',
110
+ INFO_TERM: 'INFO_TERM',
111
+ MOVIE: 'MOVIE',
112
+ RESTAURANT: 'RESTAURANT',
113
+ SPORTS_TEAM: 'SPORTS_TEAM',
114
+ TV_SHOWS: 'TV_SHOWS'
115
+ })
116
+ const ThreadSurfingActionType = exports.ThreadSurfingActionType = Object.freeze({ AI_LOOKUP: 'AI_LOOKUP', CONTEXTUAL_MENU: 'CONTEXTUAL_MENU' })
117
+
118
+ const MediaShape = exports.MediaShape = Object.freeze({ CIRCLE: 'CIRCLE', SQUARE: 'SQUARE', VERTICAL: 'VERTICAL' })
119
+ const MediaHorizontalAlignment = exports.MediaHorizontalAlignment = Object.freeze({ START: 'START', END: 'END' })
120
+ const MediaVerticalAlignment = exports.MediaVerticalAlignment = Object.freeze({ TOP: 'TOP', CENTER: 'CENTER' })
121
+ const AddonActionAlignment = exports.AddonActionAlignment = Object.freeze({ START: 'START', END: 'END' })
122
+ const ImageAssetQueryStatus = exports.ImageAssetQueryStatus = Object.freeze({ FETCHING: 'FETCHING', FETCHED: 'FETCHED', FAILED: 'FAILED' })
123
+
124
+ const CodeBlockType = exports.CodeBlockType = Object.freeze({
125
+ DEFAULT: 'DEFAULT',
126
+ COMMENT: 'COMMENT',
127
+ KEYWORD: 'KEYWORD',
128
+ METHOD: 'METHOD',
129
+ NUMBER: 'NUMBER',
130
+ STR: 'STR'
131
+ })
132
+
133
+ const FollowUpSuggestionCategory = exports.FollowUpSuggestionCategory = Object.freeze({
134
+ ADD: 'ADD',
135
+ ANIMATE: 'ANIMATE',
136
+ FRAME: 'FRAME',
137
+ LIGHT: 'LIGHT',
138
+ OTHER: 'OTHER',
139
+ RETOUCH: 'RETOUCH',
140
+ SCENE: 'SCENE',
141
+ STYLE: 'STYLE'
142
+ })
143
+
144
+ const InformTreatmentRenderingType = exports.InformTreatmentRenderingType = Object.freeze({
145
+ GEOBLOCK: 'GEOBLOCK',
146
+ MEDIA_LABEL: 'MEDIA_LABEL',
147
+ POST_COVER: 'POST_COVER',
148
+ POST_LABEL: 'POST_LABEL',
149
+ WARNING_SCREENS: 'WARNING_SCREENS'
150
+ })
151
+
152
+ const UnifiedResponseSectionType = exports.UnifiedResponseSectionType = Object.freeze({ REASONING: 'REASONING', RESPONDING: 'RESPONDING' })
153
+ const UnifiedResponseMessageGroupKind = exports.UnifiedResponseMessageGroupKind = Object.freeze({ COMMENTARY: 'COMMENTARY', PRIMARY_RESPONSE: 'PRIMARY_RESPONSE' })
154
+
155
+ const trimEmpty = (object) => {
156
+ for (const key of Object.keys(object)) {
157
+ if (object[key] === undefined) {
158
+ delete object[key]
159
+ }
160
+ }
161
+ return object
162
+ }
163
+
164
+ const typed = (typename, fields) => trimEmpty({ ...fields, __typename: typename })
165
+
166
+ const layoutSection = (name, data, viewModelFields = {}) => {
167
+ const section = AIRich.newLayout(name, data)
168
+ Object.assign(section.view_model, trimEmpty({ ...viewModelFields }))
169
+ return section
170
+ }
171
+
172
+ const url = (value, fallback) => (value === undefined ? undefined : { url: value, url_fallback: fallback ?? value })
173
+
174
+ const customSection = exports.customSection = (typename, fields = {}, { layout = 'Single' } = {}) => {
175
+ if (typeof typename !== 'string' || !typename) {
176
+ throw new TypeError('customSection needs a __typename, that is the only thing the client dispatches on')
177
+ }
178
+ return AIRich.newLayout(layout, typed(typename, fields))
179
+ }
180
+
181
+ const placeItem = exports.placeItem = ({
182
+ id,
183
+ name,
184
+ description,
185
+ imageUrl,
186
+ itemType = PlaceDetailsItemType.PLACE,
187
+ categoryId,
188
+ categoryName,
189
+ priceLevel,
190
+ openingStatus,
191
+ openingHours,
192
+ rating,
193
+ latitude,
194
+ longitude,
195
+ streetAddress,
196
+ street,
197
+ locality,
198
+ region,
199
+ country,
200
+ postalCode,
201
+ timezone,
202
+ marketplace
203
+ } = {}) => typed('GenAIPlaceDetailsItem', {
204
+ id: id === undefined ? undefined : String(id),
205
+ name,
206
+ description,
207
+ image_url: imageUrl,
208
+ item_type: itemType,
209
+ category: categoryId === undefined && categoryName === undefined
210
+ ? undefined
211
+ : typed('GenAIPlaceDetailsItemCategory', { category_id: categoryId, display_name: categoryName }),
212
+ price_level: priceLevel,
213
+ opening_status: openingStatus,
214
+ opening_hours: openingHours?.map(hours => typed('GenAIPlaceDetailsItemOpeningHours', {
215
+ day: hours.day,
216
+ time: hours.time,
217
+ open: hours.open === undefined ? undefined : typed('GenAIPlaceDetailsItemOpeningHoursTime', { time: hours.open }),
218
+ close: hours.close === undefined ? undefined : typed('GenAIPlaceDetailsItemOpeningHoursTime', { time: hours.close })
219
+ })),
220
+ rating: rating === undefined ? undefined : typed('GenAIPlaceDetailsItemRating', { avg_rating: Number(rating) }),
221
+ address: trimEmpty({
222
+ latitude,
223
+ longitude,
224
+ street_address: streetAddress,
225
+ street,
226
+ locality,
227
+ region,
228
+ country,
229
+ postal_code: postalCode,
230
+ timezone
231
+ }),
232
+ marketplace_metadata: marketplace === undefined
233
+ ? undefined
234
+ : typed('GenAIMarketplaceMetadata', {
235
+ price: marketplace.price,
236
+ sale_price: marketplace.salePrice,
237
+ is_unavailable: marketplace.unavailable
238
+ })
239
+ })
240
+
241
+ const mapSection = exports.mapSection = ({ items = [], motivation, staticMapUrl, staticMapDarkUrl, queryStatus = MapQueryStatus.FETCHED } = {}) =>
242
+ AIRich.newLayout('Single', typed('GenAIMapPrimitive', {
243
+ map_query_status: queryStatus,
244
+ static_map: staticMapUrl === undefined
245
+ ? undefined
246
+ : typed('GenAIMapItemStaticMap', { default_url: staticMapUrl, dark_theme_url: staticMapDarkUrl ?? staticMapUrl }),
247
+ items,
248
+ motivation
249
+ }))
250
+
251
+ const locationPermissionSection = exports.locationPermissionSection = (placeholder = '') =>
252
+ AIRich.newLayout('Single', typed('GenAILocationPermissionPrimitive', { placeholder }))
253
+
254
+ const timestampPlaceholderSection = exports.timestampPlaceholderSection = (placeholder = '') =>
255
+ AIRich.newLayout('Single', typed('GenAITimestampPlaceholderPrimitive', { placeholder }))
256
+
257
+ const sportsTeam = (team = {}) => typed('GenAISportsTeam', {
258
+ name: team.name,
259
+ abbreviation: team.abbreviation,
260
+ country_code: team.countryCode,
261
+ icon: team.icon === undefined ? undefined : typed('GenAISportsTeamIcon', { image: url(team.icon, team.iconFallback) })
262
+ })
263
+
264
+ const sportsRecord = (record) => (record === undefined
265
+ ? undefined
266
+ : typed('GenAISportsTeamRecord', { wins: record.wins, losses: record.losses, ties: record.ties }))
267
+
268
+ const sportsSection = exports.sportsSection = ({
269
+ gameId,
270
+ league = SportsLeague.NFL,
271
+ status = SportsGameStatus.SCHEDULED,
272
+ statusDetail,
273
+ startTime,
274
+ venue,
275
+ group,
276
+ groupName,
277
+ homeTeam,
278
+ awayTeam,
279
+ homeScore,
280
+ awayScore,
281
+ homeRecord,
282
+ awayRecord,
283
+ seasonType,
284
+ week,
285
+ contentTypename = 'GenAIAmericanFootballGameContent'
286
+ } = {}) => {
287
+ if (!gameId) {
288
+ throw new TypeError('sportsSection requires gameId, the widget is keyed on it')
289
+ }
290
+ return AIRich.newLayout('Single', typed('GenAISportsWidgetPrimitive', {
291
+ game_id: String(gameId),
292
+ league,
293
+ status,
294
+ status_detail: statusDetail,
295
+ start_time_utc_seconds: startTime === undefined ? undefined : Number(startTime),
296
+ venue: venue === undefined
297
+ ? undefined
298
+ : typed('GenAISportsVenue', { name: venue.name, city: venue.city, state: venue.state, country: venue.country }),
299
+ group: group === undefined && groupName === undefined
300
+ ? undefined
301
+ : typed('GenAISportsGroup', { group_name: groupName ?? group }),
302
+ content: typed(contentTypename, {
303
+ home_team: homeTeam === undefined ? undefined : sportsTeam(homeTeam),
304
+ away_team: awayTeam === undefined ? undefined : sportsTeam(awayTeam),
305
+ home_score: homeScore,
306
+ away_score: awayScore,
307
+ home_record: sportsRecord(homeRecord),
308
+ away_record: sportsRecord(awayRecord),
309
+ season_type: seasonType,
310
+ week
311
+ })
312
+ }))
313
+ }
314
+
315
+ const videoSection = exports.videoSection = ({
316
+ postId,
317
+ title,
318
+ url: reelsUrl,
319
+ thumbnailUrl,
320
+ creator,
321
+ avatarUrl,
322
+ contentHash,
323
+ likes,
324
+ comments,
325
+ shares,
326
+ isVerified,
327
+ sourceApp,
328
+ progressiveUrls = [],
329
+ dashManifests = []
330
+ } = {}) => AIRich.newLayout('Single', typed('GenAIVideoPrimitive', {
331
+ post_id: postId === undefined ? undefined : String(postId),
332
+ reels_title: title,
333
+ reels_url: reelsUrl,
334
+ thumbnail_url: thumbnailUrl,
335
+ creator,
336
+ avatar_url: avatarUrl,
337
+ content_hash: contentHash,
338
+ likes_count: likes,
339
+ comments_count: comments,
340
+ shares_count: shares,
341
+ is_verified: isVerified,
342
+ source_app: sourceApp,
343
+ video_delivery_response: typed('GenAIVideoDeliveryResponse', {
344
+ progressive_urls: progressiveUrls.map(value => typed('GenAIProgressiveUrlResponse', { progressive_url: value })),
345
+ dash_manifests: dashManifests.map(value => typed('GenAIDashManifestResponse', { manifest_xml: value }))
346
+ })
347
+ }))
348
+
349
+ const reminderSection = exports.reminderSection = ({
350
+ reminderId,
351
+ title,
352
+ triggerType,
353
+ triggerTime,
354
+ createTime,
355
+ isDeleted,
356
+ thumbnailUrl,
357
+ fullSizeUrl,
358
+ mediaKey
359
+ } = {}) => {
360
+ if (!reminderId) {
361
+ throw new TypeError('reminderSection requires reminderId')
362
+ }
363
+ return AIRich.newLayout('Single', typed('GenAIReminderPrimitive', {
364
+ reminder_id: String(reminderId),
365
+ title,
366
+ trigger_type: triggerType,
367
+ trigger_time: triggerTime,
368
+ create_time: createTime,
369
+ is_deleted: isDeleted,
370
+ thumbnail_url: thumbnailUrl,
371
+ full_size_url: fullSizeUrl,
372
+ reminder_media_key: mediaKey
373
+ }))
374
+ }
375
+
376
+ const commentSection = exports.commentSection = ({
377
+ text,
378
+ url: commentUrl,
379
+ actorName,
380
+ profileImage,
381
+ subtitle,
382
+ likes,
383
+ replies,
384
+ isVerified
385
+ } = {}) => AIRich.newLayout('Single', typed('GenAICommentPrimitive', {
386
+ comment_text: text,
387
+ comment_url: commentUrl,
388
+ actor_name: actorName,
389
+ profile_image: profileImage,
390
+ subtitle,
391
+ likes_count: likes,
392
+ replies_count: replies,
393
+ is_verified: isVerified
394
+ }))
395
+
396
+ const compactEntitySection = exports.compactEntitySection = ({
397
+ title,
398
+ subtitle,
399
+ secondarySubtitle,
400
+ image,
401
+ entityId,
402
+ entityUrl,
403
+ entityType = CompactEntityType.PERSON,
404
+ actionType,
405
+ isVerified
406
+ } = {}) => AIRich.newLayout('Single', typed('GenAICompactEntityPrimitive', {
407
+ title,
408
+ subtitle,
409
+ secondary_subtitle: secondarySubtitle,
410
+ image,
411
+ entity_id: entityId === undefined ? undefined : String(entityId),
412
+ entity_url: entityUrl,
413
+ entity_type: entityType,
414
+ action_type: actionType,
415
+ is_verified: isVerified
416
+ }))
417
+
418
+ const actionListRow = exports.actionListRow = ({ title, subtitle, action, icon, url: rowUrl, rowType = ActionListRowType.ACTION } = {}) =>
419
+ typed('GenAIActionListRow', {
420
+ title,
421
+ subtitle,
422
+ action,
423
+ icon,
424
+ url: rowUrl,
425
+ row_type: rowType
426
+ })
427
+
428
+ const actionListSection = exports.actionListSection = (rows = []) =>
429
+ AIRich.newLayout('Single', typed('GenAIActionListPrimitive', { rows }))
430
+
431
+ const plannerFields = ({ sources = [], steps = [], queryUrl, queryFavicon, searchEngine, facepileFavicons = [], responseId } = {}) => ({
432
+ response_id: responseId,
433
+ sources,
434
+ steps,
435
+ query_url: queryUrl,
436
+ query_favicon: queryFavicon,
437
+ search_engine: searchEngine,
438
+ facepile_favicons: facepileFavicons
439
+ })
440
+
441
+ const plannerStep = exports.plannerStep = ({ title, instruction, status = SearchPlannerStepStatus.PLANNED } = {}) =>
442
+ typed('GenAISearchPlannerStep', {
443
+ title,
444
+ status,
445
+ instruction: instruction === undefined
446
+ ? undefined
447
+ : typed('GenAISearchPlannerInstruction', { text: instruction })
448
+ })
449
+
450
+ const searchPlannerSection = exports.searchPlannerSection = (options = {}) =>
451
+ AIRich.newLayout('Single', typed('GenAISearchPlannerStepsPrimitive', plannerFields(options)))
452
+
453
+ const searchResultV2Section = exports.searchResultV2Section = (options = {}) =>
454
+ AIRich.newLayout('Single', typed('GenAISearchResultV2Primitive', plannerFields(options)))
455
+
456
+ const plannerSnippetSection = exports.plannerSnippetSection = ({ header, currentStep, totalSteps, status = SearchPlannerStepStatus.IN_PROGRESS } = {}) =>
457
+ AIRich.newLayout('Single', typed('GenAISearchPlannerStepSnippetPrimitive', {
458
+ header,
459
+ current_step: currentStep,
460
+ total_steps: totalSteps,
461
+ status
462
+ }))
463
+
464
+ const chainOfThoughtSection = exports.chainOfThoughtSection = ({ header, subtitle, plannerState, imageArtifacts, text } = {}) =>
465
+ AIRich.newLayout('Single', typed('GenAIChainOfThoughtStepPrimitive', {
466
+ header,
467
+ subtitle,
468
+ planner_state: plannerState,
469
+ image_artifacts: imageArtifacts,
470
+ markdown_text: text === undefined ? undefined : typed('GenAIChainOfThoughtStepMarkdownText', { text })
471
+ }))
472
+
473
+ const searchAdSection = exports.searchAdSection = ({ storyId, actorName, actorImageUrl, imageUrl, message } = {}) =>
474
+ AIRich.newLayout('Single', typed('GenAISearchAdPrimitive', {
475
+ story_id: storyId === undefined ? undefined : String(storyId),
476
+ actor_name: actorName,
477
+ actor_image_url: actorImageUrl,
478
+ image_url: imageUrl,
479
+ message
480
+ }))
481
+
482
+ const transparencySignal = exports.transparencySignal = ({ id, signalType, value, memory } = {}) =>
483
+ typed('GenAIP13nUiSignalValue', {
484
+ id: id === undefined ? undefined : String(id),
485
+ signal_type: signalType,
486
+ value,
487
+ memory
488
+ })
489
+
490
+ const transparencySection = exports.transparencySection = ({ annotation, signals = [], responseId } = {}) =>
491
+ AIRich.newLayout('Single', typed('GenAIP13NTransparencyPrimitive', {
492
+ annotation,
493
+ signals: typed('GenAIP13nUiSignals', { signals }),
494
+ response_id: responseId
495
+ }))
496
+
497
+ const professionalConsentSection = exports.professionalConsentSection = ({
498
+ title,
499
+ body,
500
+ status = ProfessionalConsentStatus.NEEDS_CONSENT,
501
+ providerLabel,
502
+ providerIconUrl,
503
+ ctaLabel,
504
+ allowedLabel,
505
+ allowedCtaLabel,
506
+ allowedProviderLabel,
507
+ allowedDescription,
508
+ description,
509
+ primaryLabel,
510
+ secondaryLabel,
511
+ subtitle,
512
+ originalPrompt,
513
+ learnMoreLabel,
514
+ learnMoreUrl
515
+ } = {}) => AIRich.newLayout('Single', typed('GenAIProfessionalConsentPrimitive', {
516
+ title,
517
+ body,
518
+ subtitle,
519
+ description,
520
+ status,
521
+ provider_label: providerLabel,
522
+ provider_icon_url: providerIconUrl,
523
+ cta_label: ctaLabel,
524
+ allowed_label: allowedLabel,
525
+ allowed_cta_label: allowedCtaLabel,
526
+ allowed_provider_label: allowedProviderLabel,
527
+ allowed_description: allowedDescription,
528
+ primary_label: primaryLabel,
529
+ secondary_label: secondaryLabel,
530
+ original_prompt: originalPrompt,
531
+ learn_more_label: learnMoreLabel,
532
+ learn_more_url: learnMoreUrl
533
+ }))
534
+
535
+ const accountLinkingApp = exports.accountLinkingApp = ({ label, integrationFbid, integrationSlug, iconUrl } = {}) =>
536
+ typed('GenAI3PAccountLinkingBottomsheetAppItem', {
537
+ label,
538
+ integration_fbid: integrationFbid === undefined ? undefined : String(integrationFbid),
539
+ integration_slug: integrationSlug,
540
+ icon_url: iconUrl
541
+ })
542
+
543
+ const accountLinkingSection = exports.accountLinkingSection = ({
544
+ title,
545
+ subtitle,
546
+ imageUrl,
547
+ ctaLabel,
548
+ ctaUrl,
549
+ originalPrompt,
550
+ integrationType = AccountLinkingIntegration.GOOGLE_CALENDAR,
551
+ integrationStatus = AccountLinkingStatus.UNLINKED,
552
+ integrationId,
553
+ apps
554
+ } = {}) => AIRich.newLayout('Single', typed('GenAI3PAccountLinkingUpsellPrimitive', {
555
+ title,
556
+ subtitle,
557
+ image_url: imageUrl,
558
+ cta_label: ctaLabel,
559
+ cta_url: ctaUrl,
560
+ original_prompt: originalPrompt,
561
+ integration_type: integrationType,
562
+ integration_status: integrationStatus,
563
+ integration_id: integrationId === undefined ? undefined : String(integrationId),
564
+ bottomsheet: apps === undefined ? undefined : typed('GenAI3PAccountLinkingBottomsheet', { apps })
565
+ }))
566
+
567
+ const calendarEvent = exports.calendarEvent = ({
568
+ title,
569
+ startTime,
570
+ endTime,
571
+ location,
572
+ description,
573
+ recurrenceText,
574
+ deeplink,
575
+ attendees = []
576
+ } = {}) => typed('GenAI3PExtCalendarEventItem', {
577
+ title,
578
+ start_time: startTime,
579
+ end_time: endTime,
580
+ location,
581
+ description,
582
+ recurrence_text: recurrenceText,
583
+ deeplink,
584
+ attendees: attendees.map(attendee => typed('GenAI3PExtCalendarAttendee', {
585
+ email: attendee.email,
586
+ display_name: attendee.displayName ?? attendee.name
587
+ }))
588
+ })
589
+
590
+ const calendarWidgetSection = exports.calendarWidgetSection = ({ title, iconUrls = [], sections = [], ctas = [], toast } = {}) =>
591
+ AIRich.newLayout('Single', typed('GenAI3PExtWidgetPrimitive', {
592
+ header: typed('GenAI3PExtWidgetStandardHeader', { title, leading_items: iconUrls }),
593
+ sections: sections.map(section => typed('GenAI3PExtCalendarDateSection', {
594
+ date: section.date,
595
+ events: typed('GenAI3PExtCalendarEventList', { events: section.events ?? [] })
596
+ })),
597
+ ctas: ctas.map(cta => typed('GenAI3PExtWidgetCTA', {
598
+ label: cta.label,
599
+ kind: cta.kind ?? WidgetCtaKind.CONFIRM,
600
+ state: cta.state ?? WidgetCtaState.PENDING,
601
+ tool_call_id: cta.toolCallId,
602
+ tool_name: cta.toolName,
603
+ analytics_action: cta.analyticsAction
604
+ })),
605
+ toast: toast === undefined ? undefined : typed('GenAI3PExtWidgetToast', { label: toast })
606
+ }))
607
+
608
+ const chainingSuggestionSection = exports.chainingSuggestionSection = ({ promptText, title, imageUri, externalConversationId, topic, cardId } = {}) =>
609
+ AIRich.newLayout('Single', typed('GenAIChainingSuggestionPrimitive', {
610
+ prompt_text: promptText,
611
+ title,
612
+ image_uri: imageUri,
613
+ external_conversation_id: externalConversationId,
614
+ topic,
615
+ card_id: cardId
616
+ }))
617
+
618
+ const mediaItem = exports.mediaItem = ({
619
+ previewUrl,
620
+ fullUrl,
621
+ darkPreviewUrl,
622
+ darkFullUrl,
623
+ source,
624
+ contentHash,
625
+ assetQueryStatus = ImageAssetQueryStatus.FETCHED,
626
+ followUpPills = []
627
+ } = {}) => typed('GenAIMediaItem', {
628
+ preview_image: url(previewUrl),
629
+ full_image: url(fullUrl),
630
+ dark_mode_preview_image: url(darkPreviewUrl),
631
+ dark_mode_full_image: url(darkFullUrl),
632
+ source,
633
+ content_hash: contentHash,
634
+ asset_query_status: assetQueryStatus,
635
+ follow_up_pills: followUpPills.map(pill => typed('GenAIFollowUpSuggestionPillPrimitive', {
636
+ prompt_text: typeof pill === 'string' ? pill : pill.promptText,
637
+ category: typeof pill === 'string' ? FollowUpSuggestionCategory.OTHER : pill.category ?? FollowUpSuggestionCategory.OTHER
638
+ }))
639
+ })
640
+
641
+ const mediaGridSection = exports.mediaGridSection = (items = []) => AIRich.newLayout('Grid', items)
642
+
643
+ const contextualSourcesSection = exports.contextualSourcesSection = (sources = []) =>
644
+ AIRich.newLayout('Single', typed('GenAIContextualSourcesViewModel', {
645
+ contextual_sources: sources.map(source => trimEmpty({
646
+ uri: source.uri ?? source.url,
647
+ display_name: source.displayName ?? source.title,
648
+ favicon_uri: source.favicon
649
+ }))
650
+ }))
651
+
652
+ const threadSurfingItem = exports.threadSurfingItem = ({ entity, entityType = ThreadSurfingEntityType.INFO_TERM, prompts = [] } = {}) =>
653
+ typed('GenAIThreadSurfingItem', {
654
+ entity,
655
+ entity_type: entityType,
656
+ prompts: prompts.map((prompt, index) => typed('GenAIThreadSurfingPrompt', {
657
+ prompt: typeof prompt === 'string' ? prompt : prompt.prompt,
658
+ prompt_id: typeof prompt === 'string' ? String(index) : String(prompt.promptId ?? index)
659
+ }))
660
+ })
661
+
662
+ const socialEntityItem = exports.socialEntityItem = ({ entityId, name, fullName, pictureUrl, entityUrl, entityType, isVerified } = {}) =>
663
+ typed('GenAISocialEntityItem', {
664
+ entity_id: entityId === undefined ? undefined : String(entityId),
665
+ entity_name: name,
666
+ entity_full_name: fullName,
667
+ entity_picture_url: pictureUrl,
668
+ entity_url: entityUrl,
669
+ entity_type: entityType,
670
+ is_verified: isVerified
671
+ })
672
+
673
+ const placeEntityItem = exports.placeEntityItem = ({ placeId, name, imageUrl, motivation } = {}) =>
674
+ typed('GenAIPlaceEntityItem', {
675
+ place_id: placeId === undefined ? undefined : String(placeId),
676
+ name,
677
+ image_url: imageUrl,
678
+ motivation
679
+ })
680
+
681
+ const productEntityItem = exports.productEntityItem = ({
682
+ productId,
683
+ title,
684
+ productUrl,
685
+ imageUrl,
686
+ additionalImages = [],
687
+ price,
688
+ salePrice,
689
+ brand,
690
+ sourceType = ProductSourceType.CATALOG,
691
+ isUnavailable,
692
+ adTrackingCode
693
+ } = {}) => typed('GenAIProductEntityItem', {
694
+ product_id: productId === undefined ? undefined : String(productId),
695
+ title,
696
+ product_url: productUrl,
697
+ image: url(imageUrl),
698
+ additional_images: additionalImages.map(value => url(value)),
699
+ price,
700
+ sale_price: salePrice,
701
+ brand,
702
+ source_type: sourceType,
703
+ is_unavailable: isUnavailable,
704
+ ad_tracking_code: adTrackingCode
705
+ })
706
+
707
+ const sideBySideSurveyItem = exports.sideBySideSurveyItem = ({
708
+ surveyId,
709
+ threadId,
710
+ botId,
711
+ responseOtid,
712
+ responseTimestampMs,
713
+ simonSessionFbid,
714
+ tessaSessionFbid,
715
+ testArmName
716
+ } = {}) => typed('GenAISideBySideSurveyItem', {
717
+ survey_id: surveyId === undefined ? undefined : String(surveyId),
718
+ thread_id: threadId === undefined ? undefined : String(threadId),
719
+ bot_id: botId === undefined ? undefined : String(botId),
720
+ response_otid: responseOtid,
721
+ response_timestamp_ms: responseTimestampMs,
722
+ simon_session_fbid: simonSessionFbid,
723
+ tessa_session_fbid: tessaSessionFbid,
724
+ test_arm_name: testArmName
725
+ })
726
+
727
+ const multipleResponseSection = exports.multipleResponseSection = (responses = [], { layoutType = MultipleResponseLayoutType.IN_THREAD, survey } = {}) =>
728
+ layoutSection('MultipleResponse', responses, { layout_type: layoutType, survey_metadata: survey })
729
+
730
+ const bloomCardSection = exports.bloomCardSection = (primitives = []) => AIRich.newLayout('IGSuggestedBloomCard', primitives)
731
+
732
+ const ADDON_ACTION_UNSUPPORTED_PRIMITIVES = Object.freeze(['GenAIFooterActionPrimitive'])
733
+
734
+ const addonActionSection = exports.addonActionSection = (primitives = [], { actionType, alignment = AddonActionAlignment.END } = {}) => {
735
+ if (!Object.values(AddonActionType).includes(actionType)) {
736
+ throw new TypeError('addonActionSection actionType must be one of ' + Object.values(AddonActionType).join(', '))
737
+ }
738
+ if (!Array.isArray(primitives) || primitives.length === 0) {
739
+ throw new TypeError('addonActionSection needs at least one overlay button primitive; an empty AddonAction overlay force-closes the recipient')
740
+ }
741
+ for (const primitive of primitives) {
742
+ if (primitive && ADDON_ACTION_UNSUPPORTED_PRIMITIVES.includes(primitive.__typename)) {
743
+ throw new TypeError('addonActionSection cannot render ' + primitive.__typename + '; AddonAction is an overlay whose buttons need a label or icon, and this primitive leaves the button empty so the recipient force-closes. Forward a real Meta AI AddonAction with forwardRichResponse instead of synthesizing one')
744
+ }
745
+ }
746
+ return layoutSection('AddonAction', primitives, { addon_action_type: actionType, addon_action_alignment: alignment })
747
+ }
748
+
749
+ const QuotaUpsellMeterUsageType = exports.QuotaUpsellMeterUsageType = Object.freeze({ META_AI_THINK_HARD: 'META_AI_THINK_HARD' })
750
+
751
+ const quotaUpsellButton = exports.quotaUpsellButton = ({ label, action, deeplink } = {}) =>
752
+ typed('GenAIMetaSubsQuotaUpsellButton', { label, action, deeplink })
753
+
754
+ const quotaUpsellSection = exports.quotaUpsellSection = ({ title, body, bodyLine1, bodyLine2, meterUsageType, benefitType, buttons = [] } = {}) =>
755
+ AIRich.newLayout('Single', typed('GenAIMetaSubsQuotaUpsellPrimitive', {
756
+ title,
757
+ body,
758
+ body_line1: bodyLine1,
759
+ body_line2: bodyLine2,
760
+ meter_usage_type: meterUsageType,
761
+ benefit_type: benefitType,
762
+ buttons: buttons.length ? buttons : undefined
763
+ }))
764
+
765
+ const quizQuestion = exports.quizQuestion = ({ question, options = [], correctIndices = [], explanation, hints = [] } = {}) =>
766
+ typed('GenAIQuizQuestion', {
767
+ question,
768
+ options: options.length ? options : undefined,
769
+ correct_indices: correctIndices.length ? correctIndices : undefined,
770
+ explanation,
771
+ hints: hints.length ? hints : undefined
772
+ })
773
+
774
+ const quizSection = exports.quizSection = ({ title, subject, questions = [] } = {}) =>
775
+ AIRich.newLayout('Single', typed('GenAIQuizPrimitive', {
776
+ title,
777
+ subject,
778
+ questions: questions.map(question => (question && question.__typename ? question : quizQuestion(question)))
779
+ }))
780
+
781
+ const actionGroupButton = exports.actionGroupButton = ({ actionId, clientActionId, label, deeplink, deeplinkUrl, androidDeeplinkUrl } = {}) =>
782
+ typed('GenAIActionButton', {
783
+ action_id: actionId,
784
+ client_action_id: clientActionId,
785
+ label,
786
+ deeplink,
787
+ deeplink_url: deeplinkUrl,
788
+ android_deeplink_url: androidDeeplinkUrl
789
+ })
790
+
791
+ const actionGroupSection = exports.actionGroupSection = ({ groupId, recommendedActionId, buttons = [] } = {}) =>
792
+ AIRich.newLayout('Single', typed('GenAIActionGroupPrimitive', {
793
+ group_id: groupId,
794
+ recommended_action_id: recommendedActionId,
795
+ buttons: buttons.map(button => (button && button.__typename ? button : actionGroupButton(button)))
796
+ }))
797
+
798
+ const fusedComparisonCta = exports.fusedComparisonCta = ({ label, uri } = {}) =>
799
+ typed('GenAIFusedComparisonCTA', { label, uri })
800
+
801
+ const fusedComparisonColumn = exports.fusedComparisonColumn = ({ productId, title, productUrl, merchant, image, price, originalPrice, cta } = {}) =>
802
+ typed('GenAIFusedComparisonColumn', {
803
+ product_id: productId === undefined ? undefined : String(productId),
804
+ title,
805
+ product_url: productUrl,
806
+ merchant,
807
+ image,
808
+ price,
809
+ original_price: originalPrice,
810
+ cta: cta && cta.__typename ? cta : cta ? fusedComparisonCta(cta) : undefined
811
+ })
812
+
813
+ const fusedComparisonRow = exports.fusedComparisonRow = ({ label, cells = [] } = {}) =>
814
+ typed('GenAIFusedComparisonRow', {
815
+ label,
816
+ cells: cells.length ? cells : undefined
817
+ })
818
+
819
+ const fusedComparisonSection = exports.fusedComparisonSection = ({ columns = [], rows = [], labelColumnIndex, pinLabelColumn } = {}) =>
820
+ AIRich.newLayout('Single', typed('GenAIFusedComparisonTablePrimitive', {
821
+ columns: columns.map(column => (column && column.__typename ? column : fusedComparisonColumn(column))),
822
+ rows: rows.map(row => (row && row.__typename ? row : fusedComparisonRow(row))),
823
+ label_column_index: labelColumnIndex,
824
+ pin_label_column: pinLabelColumn
825
+ }))
826
+
827
+ const toBytes = (value) => {
828
+ if (value === undefined || value === null) {
829
+ return undefined
830
+ }
831
+ if (Buffer.isBuffer(value)) {
832
+ return Buffer.from(value)
833
+ }
834
+ if (value instanceof Uint8Array) {
835
+ return Buffer.from(value)
836
+ }
837
+ return Buffer.from(String(value), 'base64')
838
+ }
839
+
840
+ const richResponseOf = (msg) => {
841
+ const message = msg?.message ?? msg
842
+ if (!message) {
843
+ return { message: undefined, richResponseMessage: undefined }
844
+ }
845
+ const inner = message.botForwardedMessage?.message ?? message.botForwardedMessage ?? message
846
+ return { message, richResponseMessage: inner?.richResponseMessage }
847
+ }
848
+
849
+ const readSignedRichResponse = exports.readSignedRichResponse = (msg) => {
850
+ const { message, richResponseMessage } = richResponseOf(msg)
851
+ if (!richResponseMessage) {
852
+ return null
853
+ }
854
+ const botMetadata = message.messageContextInfo?.botMetadata
855
+ const proofs = botMetadata?.verificationMetadata?.proofs ?? []
856
+ const proof = proofs.find(item => Number(item?.useCase) === BOT_SIGNATURE_USE_CASE_WA_BOT_MSG)
857
+ const data = toBytes(richResponseMessage.unifiedResponse?.data)
858
+ return {
859
+ richResponseMessage,
860
+ botMetadata,
861
+ botJid: richResponseMessage.contextInfo?.forwardedAiBotMessageInfo?.botJid,
862
+ unifiedResponseBytes: data,
863
+ proof,
864
+ hasProof: !!(proof?.signature?.length && proof?.certificateChain?.length && data?.length)
865
+ }
866
+ }
867
+
868
+ const verifyRichResponseSignature = exports.verifyRichResponseSignature = (msg, { at } = {}) => {
869
+ const signed = readSignedRichResponse(msg)
870
+ if (!signed) {
871
+ return { status: 'failed', reason: 'not a rich response' }
872
+ }
873
+ return verifyBotSignature({
874
+ botJid: signed.botJid,
875
+ unifiedResponseBytes: signed.unifiedResponseBytes,
876
+ proof: signed.proof,
877
+ at
878
+ })
879
+ }
880
+
881
+ const forwardRichResponse = exports.forwardRichResponse = async (sock, jid, msg, { quoted, contextInfo, messageId, additionalNodes = [], forwardWrapper = true, ...options } = {}) => {
882
+ const signed = readSignedRichResponse(msg)
883
+ if (!signed) {
884
+ throw new TypeError('forwardRichResponse needs a message carrying a richResponseMessage')
885
+ }
886
+ const { richResponseMessage, botMetadata } = signed
887
+ const relayed = {
888
+ ...structuredClone(richResponseMessage),
889
+ unifiedResponse: signed.unifiedResponseBytes === undefined
890
+ ? richResponseMessage.unifiedResponse
891
+ : { data: signed.unifiedResponseBytes },
892
+ contextInfo: {
893
+ ...structuredClone(richResponseMessage.contextInfo ?? {}),
894
+ ...(contextInfo ?? {}),
895
+ ...(quoted
896
+ ? {
897
+ stanzaId: quoted.key?.id ?? quoted.id,
898
+ participant: quoted.key?.participant ?? quoted.participant ?? quoted.key?.remoteJid,
899
+ quotedMessage: quoted.message ?? quoted
900
+ }
901
+ : {})
902
+ }
903
+ }
904
+ const content = {
905
+ ...(botMetadata ? { messageContextInfo: structuredClone(msg?.message?.messageContextInfo ?? msg?.messageContextInfo ?? {}) } : {}),
906
+ ...AIRich.wrapRichResponse(relayed, forwardWrapper)
907
+ }
908
+ const built = generateWAMessageFromContent(jid, content, { messageId, ...options })
909
+ await sock.relayMessage(jid, built.message, { messageId: built.key.id, additionalNodes })
910
+ return built
911
+ }