fix(zapi): first connection issues, and merge existing contact on received message (#138)
* fix(zapi): pairing issues on first connection * fix(zapi): handle existing contact when receiving new message * refactor: simplify logic
This commit is contained in:
parent
16d7e68176
commit
63a2c70667
@ -2,7 +2,7 @@ class Channels::Whatsapp::ZapiQrCodeJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(whatsapp_channel, attempt = 1)
|
||||
return if attempt == 1 && whatsapp_channel.provider_connection['connection'] != 'close'
|
||||
return if attempt == 1 && whatsapp_channel.provider_connection.present? && whatsapp_channel.provider_connection['connection'] != 'close'
|
||||
return if attempt > 1 && whatsapp_channel.provider_connection['connection'] != 'connecting'
|
||||
|
||||
if attempt > 3
|
||||
|
||||
@ -46,7 +46,9 @@ class Whatsapp::Providers::WhatsappZapiService < Whatsapp::Providers::BaseServic
|
||||
|
||||
raise ProviderUnavailableError unless process_response(response)
|
||||
|
||||
Channels::Whatsapp::ZapiQrCodeJob.perform_later(whatsapp_channel) if whatsapp_channel.provider_connection['connection'] == 'close'
|
||||
if whatsapp_channel.provider_connection.blank? || whatsapp_channel.provider_connection['connection'] == 'close'
|
||||
Channels::Whatsapp::ZapiQrCodeJob.perform_later(whatsapp_channel)
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
@ -73,12 +73,18 @@ module Whatsapp::ZapiHandlers::ReceivedCallback # rubocop:disable Metrics/Module
|
||||
|
||||
def set_contact
|
||||
push_name = contact_name
|
||||
source_id = @raw_message[:chatLid].to_s.gsub(/[^\d]/, '')
|
||||
identifier = @raw_message[:chatLid]
|
||||
|
||||
contact_attributes = { name: push_name, identifier: @raw_message[:chatLid] }
|
||||
contact_attributes[:phone_number] = "+#{@raw_message[:phone]}" unless @raw_message[:phone].ends_with?('@lid')
|
||||
contact_attributes = { name: push_name, identifier: identifier }
|
||||
|
||||
unless @raw_message[:phone].ends_with?('@lid')
|
||||
contact_attributes[:phone_number] = "+#{@raw_message[:phone]}"
|
||||
update_existing_contact_inbox(@raw_message[:phone], source_id, identifier)
|
||||
end
|
||||
|
||||
contact_inbox = ::ContactInboxWithContactBuilder.new(
|
||||
source_id: @raw_message[:chatLid].to_s.gsub(/[^\d]/, ''),
|
||||
source_id: source_id,
|
||||
inbox: inbox,
|
||||
contact_attributes: contact_attributes
|
||||
).perform
|
||||
@ -91,6 +97,18 @@ module Whatsapp::ZapiHandlers::ReceivedCallback # rubocop:disable Metrics/Module
|
||||
try_update_contact_avatar
|
||||
end
|
||||
|
||||
def update_existing_contact_inbox(phone, source_id, identifier)
|
||||
# NOTE: This is useful when we create a new contact manually, so we don't have information about contact LID;
|
||||
# With this, when we receive a message from that contact, we can link it properly.
|
||||
existing_contact_inbox = inbox.contact_inboxes.find_by(source_id: phone)
|
||||
return unless existing_contact_inbox
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
existing_contact_inbox.update!(source_id: source_id)
|
||||
existing_contact_inbox.contact.update!(identifier: identifier)
|
||||
end
|
||||
end
|
||||
|
||||
def update_contact_phone_number
|
||||
return if @contact.phone_number.present?
|
||||
return if @raw_message[:phone].ends_with?('@lid')
|
||||
|
||||
@ -37,6 +37,18 @@ RSpec.describe Channels::Whatsapp::ZapiQrCodeJob do
|
||||
described_class.perform_now(whatsapp_channel, 2)
|
||||
end
|
||||
|
||||
it 'fetches QR code and schedules next attempt on first attempt with blank connection' do
|
||||
allow(zapi_service).to receive(:qr_code_image).and_return('data:image/png;base64,test-qr-code')
|
||||
|
||||
expect(described_class).to receive(:set).with(wait: 30.seconds).and_call_original
|
||||
expect do
|
||||
described_class.perform_now(whatsapp_channel, 1)
|
||||
end.to have_enqueued_job(described_class).with(whatsapp_channel, 2)
|
||||
|
||||
expect(whatsapp_channel.reload.provider_connection['connection']).to eq('connecting')
|
||||
expect(whatsapp_channel.provider_connection['qr_data_url']).to eq('data:image/png;base64,test-qr-code')
|
||||
end
|
||||
|
||||
it 'fetches QR code and schedules next attempt on first attempt with close connection' do
|
||||
whatsapp_channel.update_provider_connection!(connection: 'close')
|
||||
allow(zapi_service).to receive(:qr_code_image).and_return('data:image/png;base64,test-qr-code')
|
||||
|
||||
@ -70,6 +70,18 @@ describe Whatsapp::Providers::WhatsappZapiService do
|
||||
expect(service.setup_channel_provider).to be(true)
|
||||
end
|
||||
|
||||
it 'schedules QR code job when connection is blank' do
|
||||
whatsapp_channel.update!(provider_connection: {})
|
||||
|
||||
stub_request(:put, "#{api_instance_path_with_token}/update-every-webhooks")
|
||||
.with(headers: stub_headers)
|
||||
.to_return(status: 200)
|
||||
|
||||
service.setup_channel_provider
|
||||
|
||||
expect(Channels::Whatsapp::ZapiQrCodeJob).to have_been_enqueued.with(whatsapp_channel)
|
||||
end
|
||||
|
||||
it 'schedules QR code job when connection is closed' do
|
||||
whatsapp_channel.update!(provider_connection: { 'connection' => 'close' })
|
||||
|
||||
|
||||
@ -376,6 +376,59 @@ describe Whatsapp::ZapiHandlers::ReceivedCallback do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when contact_inbox exists with phone as source_id (manual creation)' do
|
||||
let!(:existing_contact) do
|
||||
create(:contact,
|
||||
account: inbox.account,
|
||||
identifier: nil,
|
||||
phone_number: '+5511987654321',
|
||||
name: 'Manually Created Contact')
|
||||
end
|
||||
let!(:existing_contact_inbox) do
|
||||
create(:contact_inbox,
|
||||
inbox: inbox,
|
||||
contact: existing_contact,
|
||||
source_id: '5511987654321')
|
||||
end
|
||||
let(:params) do
|
||||
base_params.merge(
|
||||
phone: '5511987654321',
|
||||
chatLid: '123456789@lid'
|
||||
)
|
||||
end
|
||||
|
||||
it 'updates existing contact_inbox source_id from phone to LID' do
|
||||
service.perform
|
||||
|
||||
expect(existing_contact_inbox.reload.source_id).to eq('123456789')
|
||||
end
|
||||
|
||||
it 'updates existing contact identifier with LID' do
|
||||
service.perform
|
||||
|
||||
expect(existing_contact.reload.identifier).to eq('123456789@lid')
|
||||
end
|
||||
|
||||
it 'does not create a new contact_inbox' do
|
||||
expect do
|
||||
service.perform
|
||||
end.not_to change(ContactInbox, :count)
|
||||
end
|
||||
|
||||
it 'does not create a new contact' do
|
||||
expect do
|
||||
service.perform
|
||||
end.not_to change(Contact, :count)
|
||||
end
|
||||
|
||||
it 'reuses the existing contact for message' do
|
||||
service.perform
|
||||
|
||||
message = Message.last
|
||||
expect(message.sender).to eq(existing_contact)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when handling avatar' do
|
||||
let(:params) do
|
||||
base_params.merge(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user