diff --git a/app/adapters/whats_app_adapter/three_sixty_dialog_inbound.rb b/app/adapters/whats_app_adapter/three_sixty_dialog_inbound.rb index 0f1e4f3a2..5326edabd 100644 --- a/app/adapters/whats_app_adapter/three_sixty_dialog_inbound.rb +++ b/app/adapters/whats_app_adapter/three_sixty_dialog_inbound.rb @@ -67,7 +67,7 @@ def initialize_message(whats_app_message) trigger(REQUEST_FOR_MORE_INFO, sender) if request_for_more_info?(text) trigger(UNSUBSCRIBE_CONTRIBUTOR, sender) if unsubscribe_text?(text) trigger(RESUBSCRIBE_CONTRIBUTOR, sender) if resubscribe_text?(text) - trigger(REQUEST_TO_RECEIVE_MESSAGE, sender) if request_to_receive_message?(sender, text) + trigger(REQUEST_TO_RECEIVE_MESSAGE, sender, message) if request_to_receive_message?(sender, text) message = Message.new(text: text, sender: sender) message.raw_data.attach( diff --git a/app/adapters/whats_app_adapter/three_sixty_dialog_outbound.rb b/app/adapters/whats_app_adapter/three_sixty_dialog_outbound.rb index e906e2312..bb490958f 100644 --- a/app/adapters/whats_app_adapter/three_sixty_dialog_outbound.rb +++ b/app/adapters/whats_app_adapter/three_sixty_dialog_outbound.rb @@ -118,7 +118,8 @@ def send_message(recipient, message) WhatsAppAdapter::ThreeSixtyDialogOutbound::Text.perform_later(organization_id: message.organization.id, payload: text_payload( recipient, message.text - )) + ), + message_id: message.id) else files.each do |_file| WhatsAppAdapter::ThreeSixtyDialog::UploadFileJob.perform_later(message_id: message.id) diff --git a/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/file.rb b/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/file.rb index 67a239b62..d85885066 100644 --- a/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/file.rb +++ b/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/file.rb @@ -6,7 +6,7 @@ class File < ApplicationJob queue_as :default def perform(message_id:, file_id:) - message = Message.find(message_id) + @message = Message.find(message_id) organization = Organization.find(message.organization.id) @recipient = message.recipient @@ -26,7 +26,7 @@ def perform(message_id:, file_id:) private - attr_reader :recipient, :file_id + attr_reader :recipient, :file_id, :message def payload { @@ -41,10 +41,11 @@ def payload end def handle_response(response) - case response.code.to_i - when 200 - Rails.logger.debug 'Great!' - when 400..599 + case response + when Net::HTTPSuccess + external_id = JSON.parse(response.body)['messages'].first['id'] + message.update!(external_id: external_id) + when Net::HTTPClientError, Net::HTTPServerError exception = WhatsAppAdapter::ThreeSixtyDialogError.new(error_code: response.code, message: response.body) ErrorNotifier.report(exception) end diff --git a/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/text.rb b/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/text.rb index 536ad7b5a..58e6f641e 100644 --- a/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/text.rb +++ b/app/adapters/whats_app_adapter/three_sixty_dialog_outbound/text.rb @@ -5,8 +5,9 @@ class ThreeSixtyDialogOutbound class Text < ApplicationJob queue_as :default - def perform(organization_id:, payload:) + def perform(organization_id:, payload:, message_id: nil) organization = Organization.find(organization_id) + @message = Message.find(message_id) if message_id url = URI.parse("#{ENV.fetch('THREE_SIXTY_DIALOG_WHATS_APP_REST_API_ENDPOINT', 'https://stoplight.io/mocks/360dialog/360dialog-partner-api/24588693')}/messages") headers = { 'D360-API-KEY' => organization.three_sixty_dialog_client_api_key, 'Content-Type' => 'application/json' } @@ -21,13 +22,16 @@ def perform(organization_id:, payload:) ErrorNotifier.report(e) end + attr_reader :message + private def handle_response(response) - case response.code.to_i - when 201 - Rails.logger.debug 'Great!' - when 400..599 + case response + when Net::HTTPSuccess + external_id = JSON.parse(response.body)['messages'].first['id'] + message&.update!(external_id: external_id) + when Net::HTTPClientError, Net::HTTPServerError exception = WhatsAppAdapter::ThreeSixtyDialogError.new(error_code: response.code, message: response.body) ErrorNotifier.report(exception) end diff --git a/app/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job.rb b/app/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job.rb index 77b367505..556f382c0 100644 --- a/app/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job.rb +++ b/app/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job.rb @@ -17,8 +17,8 @@ def perform(organization_id:, components:) handle_request_for_more_info(contributor, organization) end - adapter.on(WhatsAppAdapter::ThreeSixtyDialogInbound::REQUEST_TO_RECEIVE_MESSAGE) do |contributor| - handle_request_to_receive_message(contributor) + adapter.on(WhatsAppAdapter::ThreeSixtyDialogInbound::REQUEST_TO_RECEIVE_MESSAGE) do |contributor, whats_app_message| + handle_request_to_receive_message(contributor, whats_app_message) end adapter.on(WhatsAppAdapter::ThreeSixtyDialogInbound::UNSUPPORTED_CONTENT) do |contributor| @@ -43,10 +43,11 @@ def handle_unknown_contributor(whats_app_phone_number) ErrorNotifier.report(exception) end - def handle_request_to_receive_message(contributor) + def handle_request_to_receive_message(contributor, whats_app_message) contributor.update!(whats_app_message_template_responded_at: Time.current, whats_app_message_template_sent_at: nil) - - WhatsAppAdapter::ThreeSixtyDialogOutbound.send!(contributor.received_messages.first) + external_id = whats_app_message.dig(:context, :id) + message = Message.find_by(external_id: external_id) if external_id + WhatsAppAdapter::ThreeSixtyDialogOutbound.send!(message || contributor.received_messages.first) end def handle_request_for_more_info(contributor, organization) diff --git a/spec/adapters/whats_app_adapter/three_sixty_dialog_inbound_spec.rb b/spec/adapters/whats_app_adapter/three_sixty_dialog_inbound_spec.rb index 2cdaaec36..3e2b58315 100644 --- a/spec/adapters/whats_app_adapter/three_sixty_dialog_inbound_spec.rb +++ b/spec/adapters/whats_app_adapter/three_sixty_dialog_inbound_spec.rb @@ -477,5 +477,39 @@ end end end + + describe 'REQUEST_TO_RECEIVE_MESSAGE' do + let(:request_to_receive_message_callback) { spy('request_to_receive_message_callback') } + + before do + adapter.on(WhatsAppAdapter::ThreeSixtyDialogInbound::REQUEST_TO_RECEIVE_MESSAGE) do |contributor, message| + request_to_receive_message_callback.call(contributor, message) + end + end + + subject do + adapter.consume(organization, whats_app_message) + request_to_receive_message_callback + end + + before do + create(:message, external_id: 'some_external_id') + whats_app_message[:messages].first[:context] = { id: 'some_external_id' } + end + + describe 'with no WhatsApp template sent' do + it 'does not trigger the callback' do + expect(subject).not_to have_received(:call) + end + end + + describe 'with a WhatsApp template sent' do + before { contributor.update!(whats_app_message_template_sent_at: 1.hour.ago) } + + it 'triggered the callback' do + expect(subject).to have_received(:call) + end + end + end end end diff --git a/spec/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job_spec.rb b/spec/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job_spec.rb index ea817853d..0ce097ee5 100644 --- a/spec/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job_spec.rb +++ b/spec/jobs/whats_app_adapter/three_sixty_dialog/process_webhook_job_spec.rb @@ -58,11 +58,7 @@ } } end - let(:latest_message) { contributor.received_messages.first.text } - - before do - create(:message, :outbound, request: request, recipient: contributor) - end + let!(:latest_message) { create(:message, :outbound, request: request, recipient: contributor) } context 'no message template sent' do it 'creates a messsage' do @@ -72,20 +68,44 @@ context 'responding to template' do before { contributor.update(whats_app_message_template_sent_at: Time.current) } - let(:text) { latest_message } + let(:text) { latest_message.text } context 'request to receive latest message' do - it 'enqueues a job to send the latest received message' do - expect do - subject.call - end.to have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialogOutbound::Text).on_queue('default').with(text_payload) - end - it 'marks that contributor has responded to template message' do expect { subject.call }.to change { contributor.reload.whats_app_message_template_responded_at }.from(nil).to(kind_of(ActiveSupport::TimeWithZone)) end + + describe 'with no external id' do + it 'enqueues a job to send the latest received message' do + expect do + subject.call + end.to have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialogOutbound::Text).on_queue('default').with( + text_payload.merge({ message_id: latest_message.id }) + ) + end + end + + describe 'with an external id' do + let(:previous_message) do + create(:message, :outbound, request: request, recipient: contributor, created_at: 2.days.ago, external_id: 'some_external_id') + end + let(:text) { previous_message.text } + + before do + previous_message + components[:messages].first[:context] = { id: 'some_external_id' } + end + + it 'sends out the message with that external id' do + expect do + subject.call + end.to have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialogOutbound::Text).on_queue('default').with( + text_payload.merge({ message_id: previous_message.id }) + ) + end + end end end