@nerxa/socketon 0.0.0-stage → 1.21.1

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