diff --git a/app/javascript/dashboard/components-next/message/bubbles/Unsupported.vue b/app/javascript/dashboard/components-next/message/bubbles/Unsupported.vue index be67f85ca34..5f654473832 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Unsupported.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/Unsupported.vue @@ -6,9 +6,12 @@ import BaseBubble from './Base.vue'; const { inboxId } = useMessageContext(); -const { isAFacebookInbox, isAnInstagramChannel, isATiktokChannel } = useInbox( - inboxId.value -); +const { + isAFacebookInbox, + isAnInstagramChannel, + isATiktokChannel, + isAWhatsAppChannel, +} = useInbox(inboxId.value); const unsupportedMessageKey = computed(() => { if (isAFacebookInbox.value) @@ -16,6 +19,8 @@ const unsupportedMessageKey = computed(() => { if (isAnInstagramChannel.value) return 'CONVERSATION.UNSUPPORTED_MESSAGE_INSTAGRAM'; if (isATiktokChannel.value) return 'CONVERSATION.UNSUPPORTED_MESSAGE_TIKTOK'; + if (isAWhatsAppChannel.value) + return 'CONVERSATION.UNSUPPORTED_MESSAGE_WHATSAPP'; return 'CONVERSATION.UNSUPPORTED_MESSAGE'; }); diff --git a/app/javascript/dashboard/i18n/locale/en/conversation.json b/app/javascript/dashboard/i18n/locale/en/conversation.json index c7017608d02..f0ff6811a61 100644 --- a/app/javascript/dashboard/i18n/locale/en/conversation.json +++ b/app/javascript/dashboard/i18n/locale/en/conversation.json @@ -62,6 +62,7 @@ "UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.", "UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.", "UNSUPPORTED_MESSAGE_TIKTOK": "This message is unsupported. You can view this message on the TikTok app.", + "UNSUPPORTED_MESSAGE_WHATSAPP": "This message is unsupported. You can view this message on the WhatsApp app.", "SUCCESS_DELETE_MESSAGE": "Message deleted successfully", "FAIL_DELETE_MESSSAGE": "Couldn't delete message! Try again", "NO_RESPONSE": "No response", diff --git a/app/services/whatsapp/incoming_message_base_service.rb b/app/services/whatsapp/incoming_message_base_service.rb index 82aa7ab18ba..722ac3e4d06 100644 --- a/app/services/whatsapp/incoming_message_base_service.rb +++ b/app/services/whatsapp/incoming_message_base_service.rb @@ -67,6 +67,8 @@ class Whatsapp::IncomingMessageBaseService def create_messages message = messages_data.first + return create_unsupported_message(message) if message_type == 'unsupported' + log_error(message) && return if error_webhook_event?(message) process_in_reply_to(message) @@ -74,6 +76,18 @@ class Whatsapp::IncomingMessageBaseService message_type == 'contacts' ? create_contact_messages(message) : create_regular_message(message) end + # WhatsApp delivers messages it cannot render (e.g. coexistence companion-device syncs that + # fail with error 131060) as type: unsupported with no content. We still persist a placeholder + # so the contact/conversation isn't created "headless" and agents know to check the WhatsApp app. + def create_unsupported_message(message) + log_error(message) if error_webhook_event?(message) + process_in_reply_to(message) + create_message(message, source_id: message[:id]) + @message.content = I18n.t('conversations.messages.whatsapp.unsupported_message') + @message.content_attributes = @message.content_attributes.merge(is_unsupported: true) + @message.save! + end + def create_contact_messages(message) message['contacts'].each do |contact| # Pass source_id from parent message since contact objects don't have :id diff --git a/app/services/whatsapp/incoming_message_service_helpers.rb b/app/services/whatsapp/incoming_message_service_helpers.rb index 8ec8842689b..27a85447978 100644 --- a/app/services/whatsapp/incoming_message_service_helpers.rb +++ b/app/services/whatsapp/incoming_message_service_helpers.rb @@ -44,7 +44,7 @@ module Whatsapp::IncomingMessageServiceHelpers end def unprocessable_message_type?(message_type) - %w[reaction ephemeral unsupported request_welcome].include?(message_type) + %w[reaction ephemeral request_welcome].include?(message_type) end def processed_waid(waid) diff --git a/config/locales/en.yml b/config/locales/en.yml index 18b721caf2e..b11a4fdae31 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -258,6 +258,7 @@ en: whatsapp: list_button_label: 'Choose an item' call_permission_request_body: 'We would like to call you regarding your conversation.' + unsupported_message: 'This message is unavailable.' voice_call: twilio: 'Voice Call' whatsapp: 'WhatsApp Call' diff --git a/spec/services/whatsapp/incoming_message_service_spec.rb b/spec/services/whatsapp/incoming_message_service_spec.rb index dbaea621c26..fe6b179c147 100644 --- a/spec/services/whatsapp/incoming_message_service_spec.rb +++ b/spec/services/whatsapp/incoming_message_service_spec.rb @@ -206,7 +206,7 @@ describe Whatsapp::IncomingMessageService do expect(whatsapp_channel.inbox.messages.count).to eq(0) end - it 'ignores type unsupported and does not create ghost conversation' do + it 'stores type unsupported as a placeholder message so the conversation is not headless' do params = { 'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }], 'messages' => [{ @@ -217,9 +217,12 @@ describe Whatsapp::IncomingMessageService do }.with_indifferent_access described_class.new(inbox: whatsapp_channel.inbox, params: params).perform - expect(whatsapp_channel.inbox.conversations.count).to eq(0) - expect(Contact.count).to eq(0) - expect(whatsapp_channel.inbox.messages.count).to eq(0) + expect(whatsapp_channel.inbox.conversations.count).to eq(1) + expect(Contact.count).to eq(1) + expect(whatsapp_channel.inbox.messages.count).to eq(1) + message = whatsapp_channel.inbox.messages.last + expect(message.content).to eq('This message is unavailable.') + expect(message.content_attributes['is_unsupported']).to be(true) end end