fix: Duplicate conversations and contacts WA and Brazil numbers (#6222)
Resolves issue when receiving a message from Brazil Whatsapp number. Fixes: #5840 Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
@@ -84,8 +84,10 @@ class Whatsapp::IncomingMessageBaseService
|
|||||||
contact_params = @processed_params[:contacts]&.first
|
contact_params = @processed_params[:contacts]&.first
|
||||||
return if contact_params.blank?
|
return if contact_params.blank?
|
||||||
|
|
||||||
|
waid = processed_waid(contact_params[:wa_id])
|
||||||
|
|
||||||
contact_inbox = ::ContactInboxWithContactBuilder.new(
|
contact_inbox = ::ContactInboxWithContactBuilder.new(
|
||||||
source_id: contact_params[:wa_id],
|
source_id: waid,
|
||||||
inbox: inbox,
|
inbox: inbox,
|
||||||
contact_attributes: { name: contact_params.dig(:profile, :name), phone_number: "+#{@processed_params[:messages].first[:from]}" }
|
contact_attributes: { name: contact_params.dig(:profile, :name), phone_number: "+#{@processed_params[:messages].first[:from]}" }
|
||||||
).perform
|
).perform
|
||||||
|
|||||||
@@ -47,6 +47,38 @@ module Whatsapp::IncomingMessageServiceHelpers
|
|||||||
%w[reaction ephemeral unsupported].include?(message_type)
|
%w[reaction ephemeral unsupported].include?(message_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def brazil_phone_number?(phone_number)
|
||||||
|
phone_number.match(/^55/)
|
||||||
|
end
|
||||||
|
|
||||||
|
# ref: https://github.com/chatwoot/chatwoot/issues/5840
|
||||||
|
def normalised_brazil_mobile_number(phone_number)
|
||||||
|
# DDD : Area codes in Brazil are popularly known as "DDD codes" (códigos DDD) or simply "DDD", from the initials of "direct distance dialing"
|
||||||
|
# https://en.wikipedia.org/wiki/Telephone_numbers_in_Brazil
|
||||||
|
ddd = phone_number[2, 2]
|
||||||
|
# Remove country code and DDD to obtain the number
|
||||||
|
number = phone_number[4, phone_number.length - 4]
|
||||||
|
normalised_number = "55#{ddd}#{number}"
|
||||||
|
# insert 9 to convert the number to the new mobile number format
|
||||||
|
normalised_number = "55#{ddd}9#{number}" if normalised_number.length != 13
|
||||||
|
normalised_number
|
||||||
|
end
|
||||||
|
|
||||||
|
def processed_waid(waid)
|
||||||
|
# in case of Brazil, we need to do additional processing
|
||||||
|
# https://github.com/chatwoot/chatwoot/issues/5840
|
||||||
|
if brazil_phone_number?(waid)
|
||||||
|
# check if there is an existing contact inbox with the normalised waid
|
||||||
|
# We will create conversation against it
|
||||||
|
contact_inbox = inbox.contact_inboxes.find_by(source_id: normalised_brazil_mobile_number(waid))
|
||||||
|
|
||||||
|
# if there is no contact inbox with the waid without 9,
|
||||||
|
# We will create contact inboxes and contacts with the number 9 added
|
||||||
|
waid = contact_inbox.source_id if contact_inbox.present?
|
||||||
|
end
|
||||||
|
waid
|
||||||
|
end
|
||||||
|
|
||||||
def error_webhook_event?(message)
|
def error_webhook_event?(message)
|
||||||
message.key?('errors')
|
message.key?('errors')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ describe Whatsapp::IncomingMessageService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
let!(:whatsapp_channel) { create(:channel_whatsapp, sync_templates: false) }
|
let!(:whatsapp_channel) { create(:channel_whatsapp, sync_templates: false) }
|
||||||
|
let(:wa_id) { '2423423243' }
|
||||||
let!(:params) do
|
let!(:params) do
|
||||||
{
|
{
|
||||||
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => wa_id }],
|
||||||
'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa', 'text' => { 'body' => 'Test' },
|
'messages' => [{ 'from' => wa_id, 'id' => 'SDFADSf23sfasdafasdfa', 'text' => { 'body' => 'Test' },
|
||||||
'timestamp' => '1633034394', 'type' => 'text' }]
|
'timestamp' => '1633034394', 'type' => 'text' }]
|
||||||
}.with_indifferent_access
|
}.with_indifferent_access
|
||||||
end
|
end
|
||||||
@@ -246,5 +247,66 @@ describe Whatsapp::IncomingMessageService do
|
|||||||
expect(contact_attachments.fallback_title).to eq('+1 (415) 341-8386')
|
expect(contact_attachments.fallback_title).to eq('+1 (415) 341-8386')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# ref: https://github.com/chatwoot/chatwoot/issues/5840
|
||||||
|
describe 'When the incoming waid is a brazilian number in new format with 9 included' do
|
||||||
|
let(:wa_id) { '5541988887777' }
|
||||||
|
|
||||||
|
it 'creates appropriate conversations, message and contacts if contact does not exit' do
|
||||||
|
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.messages.first.content).to eq('Test')
|
||||||
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'appends to existing contact if contact inbox exists' do
|
||||||
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
|
||||||
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
||||||
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||||
|
# no new conversation should be created
|
||||||
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
||||||
|
# message appended to the last conversation
|
||||||
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'When incoming waid is a brazilian number in old format without the 9 included' do
|
||||||
|
let(:wa_id) { '554188887777' }
|
||||||
|
|
||||||
|
context 'when a contact inbox exists in the old format without 9 included' do
|
||||||
|
it 'appends to existing contact' do
|
||||||
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
|
||||||
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
||||||
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||||
|
# no new conversation should be created
|
||||||
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
||||||
|
# message appended to the last conversation
|
||||||
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a contact inbox exists in the new format with 9 included' do
|
||||||
|
it 'appends to existing contact' do
|
||||||
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: '5541988887777')
|
||||||
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
||||||
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
||||||
|
# no new conversation should be created
|
||||||
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
||||||
|
# message appended to the last conversation
|
||||||
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a contact inbox does not exist in the new format with 9 included' do
|
||||||
|
it 'creates contact inbox with the incoming waid' do
|
||||||
|
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.messages.first.content).to eq('Test')
|
||||||
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user