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
|
queue_as :default
|
||||||
|
|
||||||
def perform(whatsapp_channel, attempt = 1)
|
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'
|
return if attempt > 1 && whatsapp_channel.provider_connection['connection'] != 'connecting'
|
||||||
|
|
||||||
if attempt > 3
|
if attempt > 3
|
||||||
|
|||||||
@ -46,7 +46,9 @@ class Whatsapp::Providers::WhatsappZapiService < Whatsapp::Providers::BaseServic
|
|||||||
|
|
||||||
raise ProviderUnavailableError unless process_response(response)
|
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
|
true
|
||||||
end
|
end
|
||||||
|
|||||||
@ -73,12 +73,18 @@ module Whatsapp::ZapiHandlers::ReceivedCallback # rubocop:disable Metrics/Module
|
|||||||
|
|
||||||
def set_contact
|
def set_contact
|
||||||
push_name = contact_name
|
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 = { name: push_name, identifier: identifier }
|
||||||
contact_attributes[:phone_number] = "+#{@raw_message[:phone]}" unless @raw_message[:phone].ends_with?('@lid')
|
|
||||||
|
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(
|
contact_inbox = ::ContactInboxWithContactBuilder.new(
|
||||||
source_id: @raw_message[:chatLid].to_s.gsub(/[^\d]/, ''),
|
source_id: source_id,
|
||||||
inbox: inbox,
|
inbox: inbox,
|
||||||
contact_attributes: contact_attributes
|
contact_attributes: contact_attributes
|
||||||
).perform
|
).perform
|
||||||
@ -91,6 +97,18 @@ module Whatsapp::ZapiHandlers::ReceivedCallback # rubocop:disable Metrics/Module
|
|||||||
try_update_contact_avatar
|
try_update_contact_avatar
|
||||||
end
|
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
|
def update_contact_phone_number
|
||||||
return if @contact.phone_number.present?
|
return if @contact.phone_number.present?
|
||||||
return if @raw_message[:phone].ends_with?('@lid')
|
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)
|
described_class.perform_now(whatsapp_channel, 2)
|
||||||
end
|
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
|
it 'fetches QR code and schedules next attempt on first attempt with close connection' do
|
||||||
whatsapp_channel.update_provider_connection!(connection: 'close')
|
whatsapp_channel.update_provider_connection!(connection: 'close')
|
||||||
allow(zapi_service).to receive(:qr_code_image).and_return('data:image/png;base64,test-qr-code')
|
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)
|
expect(service.setup_channel_provider).to be(true)
|
||||||
end
|
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
|
it 'schedules QR code job when connection is closed' do
|
||||||
whatsapp_channel.update!(provider_connection: { 'connection' => 'close' })
|
whatsapp_channel.update!(provider_connection: { 'connection' => 'close' })
|
||||||
|
|
||||||
|
|||||||
@ -376,6 +376,59 @@ describe Whatsapp::ZapiHandlers::ReceivedCallback do
|
|||||||
end
|
end
|
||||||
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
|
context 'when handling avatar' do
|
||||||
let(:params) do
|
let(:params) do
|
||||||
base_params.merge(
|
base_params.merge(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user