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