@@ -22,8 +22,34 @@ import ai.tock.bot.connector.whatsapp.cloud.model.common.TextContent
2222import ai.tock.bot.connector.whatsapp.cloud.model.send.QuickReply
2323import ai.tock.bot.connector.whatsapp.cloud.model.send.message.WhatsAppCloudBotMessage
2424import ai.tock.bot.connector.whatsapp.cloud.model.send.message.WhatsAppCloudBotRecipientType
25- import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.*
25+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.ButtonSubType
26+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.ComponentType
27+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.HeaderParameter
28+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.ImageId
29+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.Language
30+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.ParameterType
31+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.ParametersUrl
32+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.PayloadParameter
33+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.TextParameter
34+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppBotRow
35+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotAction
36+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotActionButton
37+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotActionButtonReply
38+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotActionSection
2639import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotBody
40+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotFooter
41+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotHeaderType
42+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotImage
43+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotImageMessage
44+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotInteractive
45+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotInteractiveHeader
46+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotInteractiveMessage
47+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotInteractiveType
48+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotMediaImage
49+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotTemplate
50+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotTemplateMessage
51+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsAppCloudBotTextMessage
52+ import ai.tock.bot.connector.whatsapp.cloud.model.send.message.content.WhatsappTemplateComponent
2753import ai.tock.bot.definition.IntentAware
2854import ai.tock.bot.definition.Parameters
2955import ai.tock.bot.definition.StoryHandlerDefinition
@@ -37,6 +63,7 @@ import mu.KotlinLogging
3763
3864private val logger = KotlinLogging .logger {}
3965private val errorOnInvalidMessages = booleanProperty(" tock_whatsapp_error_on_invalid_messages" , false )
66+ private val uploadImagesToWhatsapp = booleanProperty(" tock_whatsapp_reupload_images" , true )
4067
4168internal const val WHATS_APP_CONNECTOR_TYPE_ID = " whatsapp_cloud"
4269const val WHATSAPP_BUTTONS_TITLE_MAX_LENGTH = 50
@@ -71,6 +98,19 @@ fun <T : Bus<T>> T.sendToWhatsAppCloud(
7198 return this
7299}
73100
101+ /* *
102+ * Sends an WhatsApp message as last bot answer, only if the [ConnectorType] of the current [BotBus] is [whatsAppCloudConnectorType].
103+ */
104+ fun <T : Bus <T >> T.endForWhatsAppCloud (
105+ messageProvider : T .() -> WhatsAppCloudBotMessage ,
106+ delay : Long = defaultDelay(currentAnswerIndex)
107+ ): T {
108+ if (isCompatibleWith(whatsAppCloudConnectorType)) {
109+ withMessage(messageProvider(this ))
110+ end(delay)
111+ }
112+ return this
113+ }
74114
75115/* *
76116 * Adds a WhatsApp [ConnectorMessage] if the current connector is WhatsApp.
@@ -91,7 +131,6 @@ fun BotBus.whatsAppCloudText(
91131 previewUrl : Boolean = false
92132): WhatsAppCloudBotTextMessage =
93133 WhatsAppCloudBotTextMessage (
94- messagingProduct = " whatsapp" ,
95134 text = TextContent (translate(text).toString()),
96135 recipientType = WhatsAppCloudBotRecipientType .individual,
97136 userId = userId.id,
@@ -101,20 +140,44 @@ fun BotBus.whatsAppCloudText(
101140/* *
102141 * Creates an [Image Message](https://developers.facebook.com/docs/whatsapp/cloud-api/messages/image-messages)
103142 *
104- * @param id the URL of the image
143+ * @param url the URL of the image
144+ * @param caption a caption to display below the image
145+ * @param uploadToWhatsapp if `true`, the image will be uploaded to Meta's servers (recommended)
146+ */
147+ fun BotBus.whatsAppCloudImage (
148+ url : String ,
149+ caption : CharSequence? = null,
150+ uploadToWhatsapp : Boolean = uploadImagesToWhatsapp,
151+ ): WhatsAppCloudBotImageMessage =
152+ WhatsAppCloudBotImageMessage (
153+ image = WhatsAppCloudBotImage .LinkedImage (
154+ url = url,
155+ caption = translate(caption).toString().checkLength(WHATSAPP_IMAGE_CAPTION_MAX_LENGTH ),
156+ uploadToWhatsapp,
157+ ),
158+ recipientType = WhatsAppCloudBotRecipientType .individual,
159+ userId = userId.id,
160+ )
161+
162+ /* *
163+ * Creates an [Image Message](https://developers.facebook.com/docs/whatsapp/cloud-api/messages/image-messages)
164+ *
165+ * @param id a unique ID for the image
166+ * @param imageBytes a byte array containing the image data
105167 * @param caption a caption to display below the image
106168 */
107169fun BotBus.whatsAppCloudImage (
108170 id : String ,
109- link : String? = null ,
171+ imageBytes : ByteArray ,
110172 caption : CharSequence? = null,
173+ mimeType : String = "image/png",
111174): WhatsAppCloudBotImageMessage =
112175 WhatsAppCloudBotImageMessage (
113- messagingProduct = " whatsapp" ,
114- image = WhatsAppCloudBotImage (
176+ image = WhatsAppCloudBotImage .UploadedImage (
115177 id = id,
116- link = link,
117- caption = translate(caption).toString().checkLength(WHATSAPP_IMAGE_CAPTION_MAX_LENGTH )
178+ bytes = imageBytes,
179+ mimeType = mimeType,
180+ caption = translate(caption).toString().checkLength(WHATSAPP_IMAGE_CAPTION_MAX_LENGTH ),
118181 ),
119182 recipientType = WhatsAppCloudBotRecipientType .individual,
120183 userId = userId.id,
@@ -175,7 +238,6 @@ internal fun I18nTranslator.whatsAppCloudReplyButtonMessage(
175238 replies : List <QuickReply >,
176239 header : WhatsAppCloudBotInteractiveHeader ?
177240) = WhatsAppCloudBotInteractiveMessage (
178- messagingProduct = " whatsapp" ,
179241 recipientType = WhatsAppCloudBotRecipientType .individual,
180242 interactive = WhatsAppCloudBotInteractive (
181243 type = WhatsAppCloudBotInteractiveType .button,
@@ -275,7 +337,6 @@ fun I18nTranslator.whatsAppCloudUrlButtonMessage(
275337 header : CharSequence? = null,
276338 footer : CharSequence? = null,
277339): WhatsAppCloudBotInteractiveMessage = WhatsAppCloudBotInteractiveMessage (
278- messagingProduct = " whatsapp" ,
279340 recipientType = WhatsAppCloudBotRecipientType .individual,
280341 interactive = WhatsAppCloudBotInteractive (
281342 type = WhatsAppCloudBotInteractiveType .cta_url,
@@ -407,7 +468,6 @@ fun I18nTranslator.whatsAppCloudListMessage(
407468 footer : CharSequence? = null,
408469): WhatsAppCloudBotInteractiveMessage {
409470 return WhatsAppCloudBotInteractiveMessage (
410- messagingProduct = " whatsapp" ,
411471 recipientType = WhatsAppCloudBotRecipientType .individual,
412472 interactive = WhatsAppCloudBotInteractive (
413473 type = WhatsAppCloudBotInteractiveType .list,
@@ -486,7 +546,6 @@ fun I18nTranslator.whatsAppCloudListSection(title: CharSequence, rows: List<Quic
486546fun I18nTranslator.whatsAppCloudReplyLocationMessage (
487547 text : CharSequence
488548): WhatsAppCloudBotInteractiveMessage = WhatsAppCloudBotInteractiveMessage (
489- messagingProduct = " whatsapp" ,
490549 recipientType = WhatsAppCloudBotRecipientType .individual,
491550 interactive = WhatsAppCloudBotInteractive (
492551 type = WhatsAppCloudBotInteractiveType .location_request_message,
@@ -616,7 +675,7 @@ fun I18nTranslator.whatsAppCloudNlpQuickReply(
616675fun I18nTranslator.whatsAppBuildCloudTemplateMessage (
617676 templateName : String ,
618677 languageCode : String ,
619- components : List <Component >
678+ components : List <WhatsappTemplateComponent >
620679) = whatsAppCloudTemplateMessage(templateName, languageCode, components)
621680
622681/* *
@@ -627,10 +686,9 @@ fun I18nTranslator.whatsAppBuildCloudTemplateMessage(
627686fun I18nTranslator.whatsAppCloudTemplateMessage (
628687 templateName : String ,
629688 languageCode : String ,
630- components : List <Component >
689+ components : List <WhatsappTemplateComponent >
631690): WhatsAppCloudBotTemplateMessage {
632691 return WhatsAppCloudBotTemplateMessage (
633- messagingProduct = " whatsapp" ,
634692 recipientType = WhatsAppCloudBotRecipientType .individual,
635693 template = WhatsAppCloudBotTemplate (
636694 name = templateName,
@@ -645,7 +703,7 @@ fun I18nTranslator.whatsAppCloudTemplateMessage(
645703@Deprecated(" renamed" , ReplaceWith (" whatsAppCloudTemplateMessageCarousel(templateName, components, languageCode)" ))
646704fun I18nTranslator.whatsAppCloudBuildTemplateMessageCarousel (
647705 templateName : String ,
648- components : List <Component .Card >,
706+ components : List <WhatsappTemplateComponent .Card >,
649707 languageCode : String
650708) = whatsAppCloudTemplateMessageCarousel(templateName, components, languageCode)
651709
@@ -656,19 +714,18 @@ fun I18nTranslator.whatsAppCloudBuildTemplateMessageCarousel(
656714 */
657715fun I18nTranslator.whatsAppCloudTemplateMessageCarousel (
658716 templateName : String ,
659- components : List <Component .Card >,
717+ components : List <WhatsappTemplateComponent .Card >,
660718 languageCode : String
661719): WhatsAppCloudBotTemplateMessage {
662720 return WhatsAppCloudBotTemplateMessage (
663- messagingProduct = " whatsapp" ,
664721 recipientType = WhatsAppCloudBotRecipientType .individual,
665722 template = WhatsAppCloudBotTemplate (
666723 name = templateName,
667724 language = Language (
668725 code = languageCode,
669726 ),
670727 components = listOf (
671- Component .Carousel (
728+ WhatsappTemplateComponent .Carousel (
672729 type = ComponentType .CAROUSEL ,
673730 cards = components
674731 )
@@ -677,7 +734,7 @@ fun I18nTranslator.whatsAppCloudTemplateMessageCarousel(
677734 )
678735}
679736
680- fun <T : Bus <T >> T.whatsAppCloudCardCarousel (cardIndex : Int , components : List <Component >): Component .Card {
737+ fun <T : Bus <T >> T.whatsAppCloudCardCarousel (cardIndex : Int , components : List <WhatsappTemplateComponent >): WhatsappTemplateComponent .Card {
681738 return whatsAppCloudTemplateCard(
682739 cardIndex, components
683740 )
@@ -693,8 +750,8 @@ fun <T : Bus<T>> T.whatsAppCloudCardCarousel(cardIndex: Int, components: List<Co
693750 */
694751fun <T : Bus <T >> T.whatsAppCloudTemplateCard (
695752 cardIndex : Int ,
696- components : List <Component >
697- ): Component .Card = Component .Card (
753+ components : List <WhatsappTemplateComponent >
754+ ): WhatsappTemplateComponent .Card = WhatsappTemplateComponent .Card (
698755 cardIndex = cardIndex,
699756 components = components
700757)
@@ -711,7 +768,7 @@ fun <T : Bus<T>> T.whatsAppCloudBodyTemplate(
711768 */
712769fun <T : Bus <T >> T.whatsAppCloudTemplateBody (
713770 parameters : List <TextParameter >
714- ): Component .Body = Component .Body (
771+ ): WhatsappTemplateComponent .Body = WhatsappTemplateComponent .Body (
715772 type = ComponentType .BODY ,
716773 parameters = parameters
717774)
@@ -736,7 +793,7 @@ fun whatsAppCloudButtonTemplate(
736793 index : Int ,
737794 subType : ButtonSubType ,
738795 parameters : List <PayloadParameter >
739- ): Component .Button = Component .Button (
796+ ): WhatsappTemplateComponent .Button = WhatsappTemplateComponent .Button (
740797 type = ComponentType .BUTTON ,
741798 subType = subType,
742799 index = index.toString(),
@@ -747,7 +804,7 @@ fun <T : Bus<T>> T.whatsAppCloudPostbackButton(
747804 index : Int ,
748805 textButton : String ,
749806 payload : String?
750- ): Component .Button = whatsAppCloudButtonTemplate(
807+ ): WhatsappTemplateComponent .Button = whatsAppCloudButtonTemplate(
751808 index, ButtonSubType .QUICK_REPLY , listOf (
752809 whatsAppCloudPayloadParameterTemplate(textButton, payload, ParameterType .PAYLOAD )
753810 )
@@ -768,7 +825,7 @@ fun <T : Bus<T>> T.whatsAppCloudPostbackButton(
768825 targetIntent : IntentAware ,
769826 step : StoryStep <out StoryHandlerDefinition >? = null,
770827 parameters : Parameters = Parameters ()
771- ): Component .Button = whatsAppCloudPostbackButton(
828+ ): WhatsappTemplateComponent .Button = whatsAppCloudPostbackButton(
772829 index = index,
773830 textButton = translate(title).toString(),
774831 // Add an index parameter to ensure that all buttons in the list have unique ids
@@ -779,7 +836,7 @@ fun <T : Bus<T>> T.whatsAppCloudNLPPostbackButton(
779836 index : Int ,
780837 title : CharSequence ,
781838 textToSend : CharSequence = title,
782- ): Component .Button = whatsAppCloudPostbackButton(
839+ ): WhatsappTemplateComponent .Button = whatsAppCloudPostbackButton(
783840 index = index,
784841 textButton = translate(title).toString(),
785842 payload = SendChoice .encodeNlpChoiceId(translate(textToSend).toString()),
@@ -788,7 +845,7 @@ fun <T : Bus<T>> T.whatsAppCloudNLPPostbackButton(
788845fun <T : Bus <T >> T.whatsAppCloudUrlButton (
789846 index : Int ,
790847 textButton : String ,
791- ): Component .Button = whatsAppCloudButtonTemplate(
848+ ): WhatsappTemplateComponent .Button = whatsAppCloudButtonTemplate(
792849 index, ButtonSubType .URL , listOf (
793850 whatsAppCloudPayloadParameterTemplate(textButton, null , ParameterType .TEXT )
794851 )
@@ -813,7 +870,7 @@ fun whatsAppCloudHeaderTemplate(
813870
814871fun whatsAppCloudTemplateImageHeader (
815872 imageId : String
816- ): Component .Header = Component .Header (
873+ ): WhatsappTemplateComponent .Header = WhatsappTemplateComponent .Header (
817874 type = ComponentType .HEADER ,
818875 parameters = listOf (
819876 HeaderParameter .Image (
0 commit comments