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 6015f95c1..2e425f3cd 100644 --- a/app/adapters/whats_app_adapter/three_sixty_dialog_outbound.rb +++ b/app/adapters/whats_app_adapter/three_sixty_dialog_outbound.rb @@ -112,10 +112,8 @@ def send_message_template(recipient, message) end def send_message(recipient, message) - files = message.files - - if files.present? - WhatsAppAdapter::ThreeSixtyDialogOutbound::File.perform_later(message_id: message.id) if files.present? + if message.files.present? + WhatsAppAdapter::ThreeSixtyDialogOutbound::File.perform_later(message_id: message.id) else 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 33b5b97b6..82852eae7 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 @@ -8,8 +8,6 @@ class File < ApplicationJob # rubocop:disable Metrics/AbcSize def perform(message_id:) @message = Message.find(message_id) - organization = Organization.find(message.organization.id) - @recipient = message.recipient unless caption_it? @@ -19,7 +17,7 @@ def perform(message_id:) message.request.external_file_ids.each do |file_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' } + headers = { 'D360-API-KEY' => message.organization.three_sixty_dialog_client_api_key, 'Content-Type' => 'application/json' } request = Net::HTTP::Post.new(url.to_s, headers) body = payload(file_id) body[:image][:caption] = message.text if caption_it? diff --git a/app/controllers/whats_app/three_sixty_dialog_webhook_controller.rb b/app/controllers/whats_app/three_sixty_dialog_webhook_controller.rb index 7632f00d1..1689a03f1 100644 --- a/app/controllers/whats_app/three_sixty_dialog_webhook_controller.rb +++ b/app/controllers/whats_app/three_sixty_dialog_webhook_controller.rb @@ -7,8 +7,8 @@ class ThreeSixtyDialogWebhookController < ApplicationController def message head :ok - handle_error(@components[:statuses].first[:errors].first) and return if @components[:statuses]&.first[:errors].present? - return if @components[:statuses].present? # TODO: Handle statuses + handle_statuses and return if @components[:statuses].present? # TODO: Handle statuses + handle_errors(@components[:errors]) and return if @components[:errors].present? WhatsAppAdapter::ThreeSixtyDialog::ProcessWebhookJob.perform_later(organization_id: @organization.id, components: @components) end @@ -24,8 +24,8 @@ def message_params entry: [:id, { changes: [:field, { value: [:messaging_product, - { metadata: %i[display_phone_number phone_number_id] }, - { contacts: [:wa_id, { profile: [:name] }], + { metadata: %i[display_phone_number phone_number_id], + contacts: [:wa_id, { profile: [:name] }], messages: [:from, :id, :type, :timestamp, { text: [:body] }, { button: %i[payload text] }, { image: %i[id mime_type sha256 caption] }, { voice: %i[id mime_type sha256] }, @@ -38,16 +38,26 @@ def message_params { context: %i[from id] }], statuses: [:id, :status, :timestamp, :expiration_timestamp, :recipient_id, { conversation: [:id, { origin: [:type] }] }, - { pricing: %i[billable pricing_model category], - errors: [:code, :title, :message, :href, { error_data: [:details] }] }] }] + { pricing: %i[billable pricing_model category] }, + { errors: [:code, :title, :message, :href, { error_data: [:details] }] }], + errors: [:code, :title, :message, :href, { error_data: [:details] }] }] }] }]) end - def handle_error(error) - exception = WhatsAppAdapter::ThreeSixtyDialogError.new(error_code: error[:code], message: error[:title]) - ErrorNotifier.report(exception, context: { details: error[:error_data][:details] }) + def handle_statuses + statuses = @components[:statuses] + statuses.each do |status| + handle_errors(status[:errors]) if status[:errors] + end + end + + def handle_errors(errors) + errors.each do |error| + exception = WhatsAppAdapter::ThreeSixtyDialogError.new(error_code: error[:code], message: error[:title]) + ErrorNotifier.report(exception, context: { details: error[:error_data][:details] }) + end end end end diff --git a/spec/adapters/whats_app_adapter/three_sixty_dialog_outbound_spec.rb b/spec/adapters/whats_app_adapter/three_sixty_dialog_outbound_spec.rb index 4d5aa17cc..87c20572b 100644 --- a/spec/adapters/whats_app_adapter/three_sixty_dialog_outbound_spec.rb +++ b/spec/adapters/whats_app_adapter/three_sixty_dialog_outbound_spec.rb @@ -123,12 +123,14 @@ end context 'contributor has sent a reply within 24 hours' do - before { create(:message, sender: contributor) } + before do + create(:message, sender: contributor) + end it 'enqueues a File job with file, contributor, text' do expect do subject.call - end.to(have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialog::UploadFileJob).on_queue('default').with do |params| + end.to(have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialogOutbound::File).on_queue('default').with do |params| expect(params[:message_id]).to eq(message.id) 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 1dc731ad7..334ad0d9c 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 @@ -78,6 +78,17 @@ end describe 'with no external id' do + let(:base_uri) { 'https://waba-v2.360dialog.io' } + let(:external_file_id) { '545466424653131' } + + before do + latest_message.request.update!(external_file_ids: [external_file_id]) + allow(ENV).to receive(:fetch).with( + 'THREE_SIXTY_DIALOG_WHATS_APP_REST_API_ENDPOINT', 'https://stoplight.io/mocks/360dialog/360dialog-partner-api/24588693' + ).and_return(base_uri) + stub_request(:post, "#{base_uri}/messages").to_return(status: 200, body: { messages: [id: 'some_external_id'] }.to_json) + end + it 'enqueues a job to send the latest received message' do expect do subject.call @@ -86,26 +97,32 @@ ) end + it 'updates the message with the external id' do + perform_enqueued_jobs(only: WhatsAppAdapter::ThreeSixtyDialogOutbound::Text) do + expect { subject.call }.to (change { latest_message.reload.external_id }).from(nil).to('some_external_id') + end + end + context 'message with file, no text' do let(:message_file) do [create(:file, message: latest_message, attachment: Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/files/matt.jpeg'), 'image/jpeg'))] end - let(:external_file_id) { '545466424653131' } before do latest_message.update!(text: '', files: message_file) - allow(ENV).to receive(:fetch).with( - 'THREE_SIXTY_DIALOG_WHATS_APP_REST_API_ENDPOINT', 'https://stoplight.io/mocks/360dialog/360dialog-partner-api/24588693' - ).and_return('https://waba-v2.360dialog.io') end it 'enqueues a job to send the file' do - expect { subject.call }.to have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialog::UploadFileJob) - .and have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialogOutbound::File).with({ - message_id: latest_message.id, - file_id: external_file_id - }) + expect { subject.call }.to have_enqueued_job( + WhatsAppAdapter::ThreeSixtyDialogOutbound::File + ).with({ message_id: latest_message.id }) + end + + it 'updates the message with the external id' do + perform_enqueued_jobs(only: WhatsAppAdapter::ThreeSixtyDialogOutbound::File) do + expect { subject.call }.to (change { latest_message.reload.external_id }).from(nil).to('some_external_id') + end end context 'message with file and text' do @@ -116,17 +133,23 @@ it 'enqueues a job to upload the file' do expect do subject.call - end.to have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialog::UploadFileJob).on_queue('default').with( + end.to have_enqueued_job(WhatsAppAdapter::ThreeSixtyDialogOutbound::File).on_queue('default').with( message_id: latest_message.id ) end - it 'enqueues a job to send out the text' 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 }) - ) + context 'given the text is greater than 1024' do + before { latest_message.update!(text: Faker::Lorem.characters(number: 1025)) } + + it 'enqueues a job to send out the text' do + perform_enqueued_jobs(only: WhatsAppAdapter::ThreeSixtyDialogOutbound::File) 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 end end end diff --git a/spec/jobs/whats_app_adapter/three_sixty_dialog/upload_file_job_spec.rb b/spec/services/whats_app_adapter/three_sixty_dialog/upload_file_service_spec.rb similarity index 63% rename from spec/jobs/whats_app_adapter/three_sixty_dialog/upload_file_job_spec.rb rename to spec/services/whats_app_adapter/three_sixty_dialog/upload_file_service_spec.rb index c2894c0c4..3ba3d3d62 100644 --- a/spec/jobs/whats_app_adapter/three_sixty_dialog/upload_file_job_spec.rb +++ b/spec/services/whats_app_adapter/three_sixty_dialog/upload_file_service_spec.rb @@ -2,9 +2,9 @@ require 'rails_helper' -RSpec.describe WhatsAppAdapter::ThreeSixtyDialog::UploadFileJob do - describe '#perform_later(message_id:)' do - subject { -> { described_class.new.perform(message_id: message.id) } } +RSpec.describe WhatsAppAdapter::ThreeSixtyDialog::UploadFileService do + describe '#call(request_id:)' do + subject { -> { described_class.call(request_id: message.request.id) } } let(:organization) { create(:organization, three_sixty_dialog_client_api_key: 'valid_api_key') } let(:message) { create(:message, request: create(:request, :with_file, organization: organization)) } @@ -17,12 +17,7 @@ end it 'schedules a job to send out the message with the file', vcr: { cassette_name: :three_sixty_dialog_upload_file_job } do - expect { subject.call }.to have_enqueued_job( - WhatsAppAdapter::ThreeSixtyDialogOutbound::File - ).with({ - message_id: message.id, - file_id: external_file_id - }) + expect { subject.call }.to (change { message.reload.request.external_file_ids }).from([]).to([external_file_id]) end end end