diff --git a/app/services/whatsapp/incoming_message_base_service.rb b/app/services/whatsapp/incoming_message_base_service.rb index 2d3b4efd3..f057fadbd 100644 --- a/app/services/whatsapp/incoming_message_base_service.rb +++ b/app/services/whatsapp/incoming_message_base_service.rb @@ -19,7 +19,13 @@ class Whatsapp::IncomingMessageBaseService private def process_messages - # message allready exists so we don't need to process + # We don't support reactions & ephemeral message now, we need to skip processing the message + # if the webhook event is a reaction or an ephermal message or an unsupported message. + return if unprocessable_message_type?(message_type) + + # Multiple webhook event can be received against the same message due to misconfigurations in the Meta + # business manager account. While we have not found the core reason yet, the following line ensure that + # there are no duplicate messages created. return if find_message_by_source_id(@processed_params[:messages].first[:id]) || message_under_process? cache_message_source_id_in_redis @@ -49,8 +55,6 @@ class Whatsapp::IncomingMessageBaseService end def create_messages - return if unprocessable_message_type?(message_type) - message = @processed_params[:messages].first log_error(message) && return if error_webhook_event?(message) diff --git a/app/services/whatsapp/incoming_message_service_helpers.rb b/app/services/whatsapp/incoming_message_service_helpers.rb index 76a31576e..c5474314b 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].include?(message_type) + %w[reaction ephemeral unsupported request_welcome].include?(message_type) end def brazil_phone_number?(phone_number) diff --git a/spec/jobs/webhooks/whatsapp_events_job_spec.rb b/spec/jobs/webhooks/whatsapp_events_job_spec.rb index 8a7e783ad..1b7ec172f 100644 --- a/spec/jobs/webhooks/whatsapp_events_job_spec.rb +++ b/spec/jobs/webhooks/whatsapp_events_job_spec.rb @@ -146,6 +146,61 @@ RSpec.describe Webhooks::WhatsappEventsJob do end.not_to change(Message, :count) end + it 'ignore reaction type message, would not create contact if the reaction is the first event' do + other_channel = create(:channel_whatsapp, phone_number: '+1987654', provider: 'whatsapp_cloud', sync_templates: false, + validate_provider_config: false) + wb_params = { + phone_number: channel.phone_number, + object: 'whatsapp_business_account', + entry: [{ + changes: [{ + value: { + contacts: [{ profile: { name: 'Test Test' }, wa_id: '1111981136571' }], + messages: [{ + from: '1111981136571', reaction: { emoji: '👍' }, timestamp: '1664799904', type: 'reaction' + }], + metadata: { + phone_number_id: other_channel.provider_config['phone_number_id'], + display_phone_number: other_channel.phone_number.delete('+') + } + } + }] + }] + }.with_indifferent_access + expect do + Whatsapp::IncomingMessageWhatsappCloudService.new(inbox: other_channel.inbox, params: wb_params).perform + end.not_to change(Contact, :count) + end + + it 'ignore request_welcome type message, would not create contact or conversation' do + other_channel = create(:channel_whatsapp, phone_number: '+1987654', provider: 'whatsapp_cloud', sync_templates: false, + validate_provider_config: false) + wb_params = { + phone_number: channel.phone_number, + object: 'whatsapp_business_account', + entry: [{ + changes: [{ + value: { + messages: [{ + from: '1111981136571', timestamp: '1664799904', type: 'request_welcome' + }], + metadata: { + phone_number_id: other_channel.provider_config['phone_number_id'], + display_phone_number: other_channel.phone_number.delete('+') + } + } + }] + }] + }.with_indifferent_access + expect do + Whatsapp::IncomingMessageWhatsappCloudService.new(inbox: other_channel.inbox, params: wb_params).perform + end.not_to change(Contact, :count) + + expect do + Whatsapp::IncomingMessageWhatsappCloudService.new(inbox: other_channel.inbox, params: wb_params).perform + end.not_to change(Conversation, :count) + end + it 'will not enque Whatsapp::IncomingMessageWhatsappCloudService when invalid phone number id' do other_channel = create(:channel_whatsapp, phone_number: '+1987654', provider: 'whatsapp_cloud', sync_templates: false, validate_provider_config: false) diff --git a/spec/services/whatsapp/incoming_message_service_spec.rb b/spec/services/whatsapp/incoming_message_service_spec.rb index 114faf953..0bcbf2a3e 100644 --- a/spec/services/whatsapp/incoming_message_service_spec.rb +++ b/spec/services/whatsapp/incoming_message_service_spec.rb @@ -81,7 +81,7 @@ describe Whatsapp::IncomingMessageService do end context 'when unsupported message types' do - it 'ignores type ephemeral' do + it 'ignores type ephemeral and does not create ghost conversation' do params = { 'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }], 'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa', 'text' => { 'body' => 'Test' }, @@ -89,12 +89,12 @@ describe Whatsapp::IncomingMessageService do }.with_indifferent_access described_class.new(inbox: whatsapp_channel.inbox, params: params).perform - expect(whatsapp_channel.inbox.conversations.count).not_to eq(0) - expect(Contact.all.first.name).to eq('Sojan Jose') + expect(whatsapp_channel.inbox.conversations.count).to eq(0) + expect(Contact.count).to eq(0) expect(whatsapp_channel.inbox.messages.count).to eq(0) end - it 'ignores type unsupported' do + it 'ignores type unsupported and does not create ghost conversation' do params = { 'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }], 'messages' => [{ @@ -105,8 +105,8 @@ describe Whatsapp::IncomingMessageService do }.with_indifferent_access described_class.new(inbox: whatsapp_channel.inbox, params: params).perform - expect(whatsapp_channel.inbox.conversations.count).not_to eq(0) - expect(Contact.all.first.name).to eq('Sojan Jose') + expect(whatsapp_channel.inbox.conversations.count).to eq(0) + expect(Contact.count).to eq(0) expect(whatsapp_channel.inbox.messages.count).to eq(0) end end