fix: z-api read message (#165)
* fix: z-api read messages * fix: use threads for parallel requests * feat: use jobs instead * fix: refactor ZapiReadMessageJob to use service method for sending read messages
This commit is contained in:
parent
0f56c51e68
commit
774c168d94
8
app/jobs/channels/whatsapp/zapi_read_message_job.rb
Normal file
8
app/jobs/channels/whatsapp/zapi_read_message_job.rb
Normal file
@ -0,0 +1,8 @@
|
||||
class Channels::Whatsapp::ZapiReadMessageJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(whatsapp_channel, phone, message_source_id)
|
||||
service = Whatsapp::Providers::WhatsappZapiService.new(whatsapp_channel: whatsapp_channel)
|
||||
service.send_read_message(phone, message_source_id)
|
||||
end
|
||||
end
|
||||
@ -81,21 +81,28 @@ class Whatsapp::Providers::WhatsappZapiService < Whatsapp::Providers::BaseServic
|
||||
end
|
||||
|
||||
def read_messages(messages, recipient_id:, **)
|
||||
# NOTE: Z-API will handle marking previous messages as read.
|
||||
last_message = messages.last
|
||||
phone = recipient_id.delete('+')
|
||||
|
||||
messages.each do |message|
|
||||
next if message.source_id.blank?
|
||||
|
||||
Channels::Whatsapp::ZapiReadMessageJob.perform_later(whatsapp_channel, phone, message.source_id)
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def send_read_message(phone, message_source_id)
|
||||
response = HTTParty.post(
|
||||
"#{api_instance_path_with_token}/read-message",
|
||||
headers: api_headers,
|
||||
body: {
|
||||
phone: recipient_id.delete('+'),
|
||||
messageId: last_message.source_id
|
||||
phone: phone,
|
||||
messageId: message_source_id
|
||||
}.to_json
|
||||
)
|
||||
|
||||
raise ProviderUnavailableError unless process_response(response)
|
||||
|
||||
true
|
||||
process_response(response)
|
||||
end
|
||||
|
||||
def on_whatsapp(phone_number)
|
||||
|
||||
71
spec/jobs/channels/whatsapp/zapi_read_message_job_spec.rb
Normal file
71
spec/jobs/channels/whatsapp/zapi_read_message_job_spec.rb
Normal file
@ -0,0 +1,71 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Channels::Whatsapp::ZapiReadMessageJob do
|
||||
let(:whatsapp_channel) do
|
||||
create(:channel_whatsapp,
|
||||
provider: 'zapi',
|
||||
sync_templates: false,
|
||||
validate_provider_config: false,
|
||||
provider_config: {
|
||||
'instance_id' => 'test-instance',
|
||||
'token' => 'test-token',
|
||||
'client_token' => 'test-client-token'
|
||||
})
|
||||
end
|
||||
|
||||
let(:phone) { '551187654321' }
|
||||
let(:message_source_id) { 'msg_123' }
|
||||
let(:api_base_path) { Whatsapp::Providers::WhatsappZapiService::API_BASE_PATH }
|
||||
let(:api_instance_path_with_token) { "#{api_base_path}/instances/test-instance/token/test-token" }
|
||||
|
||||
def stub_headers
|
||||
{
|
||||
'Accept' => '*/*',
|
||||
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
||||
'Content-Type' => 'application/json',
|
||||
'Client-Token' => 'test-client-token',
|
||||
'User-Agent' => 'Ruby'
|
||||
}
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
context 'when response is successful' do
|
||||
it 'sends a read message request to Z-API' do
|
||||
stub_request(:post, "#{api_instance_path_with_token}/read-message")
|
||||
.with(
|
||||
headers: stub_headers,
|
||||
body: {
|
||||
phone: phone,
|
||||
messageId: message_source_id
|
||||
}.to_json
|
||||
)
|
||||
.to_return(status: 200)
|
||||
|
||||
described_class.perform_now(whatsapp_channel, phone, message_source_id)
|
||||
|
||||
expect(a_request(:post, "#{api_instance_path_with_token}/read-message")
|
||||
.with(
|
||||
headers: stub_headers,
|
||||
body: {
|
||||
phone: phone,
|
||||
messageId: message_source_id
|
||||
}.to_json
|
||||
)).to have_been_made.once
|
||||
end
|
||||
end
|
||||
|
||||
context 'when response is unsuccessful' do
|
||||
it 'logs the error' do
|
||||
stub_request(:post, "#{api_instance_path_with_token}/read-message")
|
||||
.with(headers: stub_headers)
|
||||
.to_return(status: 400, body: 'error message')
|
||||
|
||||
allow(Rails.logger).to receive(:error)
|
||||
|
||||
described_class.perform_now(whatsapp_channel, phone, message_source_id)
|
||||
|
||||
expect(Rails.logger).to have_received(:error).with('error message')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -194,37 +194,55 @@ describe Whatsapp::Providers::WhatsappZapiService do
|
||||
end
|
||||
|
||||
describe '#read_messages' do
|
||||
let(:messages) { [create(:message), message] }
|
||||
let(:first_message) { create(:message, source_id: 'msg_first') }
|
||||
let(:second_message) { create(:message, source_id: 'msg_second') }
|
||||
let(:messages) { [first_message, second_message] }
|
||||
|
||||
it 'enqueues a job for each message' do
|
||||
service.read_messages(messages, recipient_id: "+#{test_send_phone_number}")
|
||||
|
||||
expect(Channels::Whatsapp::ZapiReadMessageJob).to have_been_enqueued.with(whatsapp_channel, test_send_phone_number, first_message.source_id)
|
||||
expect(Channels::Whatsapp::ZapiReadMessageJob).to have_been_enqueued.with(whatsapp_channel, test_send_phone_number, second_message.source_id)
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
result = service.read_messages(messages, recipient_id: "+#{test_send_phone_number}")
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#send_read_message' do
|
||||
let(:phone) { test_send_phone_number }
|
||||
let(:message_source_id) { 'msg_123' }
|
||||
|
||||
context 'when response is successful' do
|
||||
it 'marks messages as read by referencing last message id' do
|
||||
it 'sends a read message request to Z-API' do
|
||||
stub_request(:post, "#{api_instance_path_with_token}/read-message")
|
||||
.with(
|
||||
headers: stub_headers,
|
||||
body: {
|
||||
phone: test_send_phone_number,
|
||||
messageId: message.source_id
|
||||
}.to_json
|
||||
body: { phone: phone, messageId: message_source_id }.to_json
|
||||
)
|
||||
.to_return(status: 200)
|
||||
|
||||
result = service.read_messages(messages, recipient_id: "+#{test_send_phone_number}")
|
||||
result = service.send_read_message(phone, message_source_id)
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when response is unsuccessful' do
|
||||
it 'raises ProviderUnavailableError' do
|
||||
it 'logs the error and returns false' do
|
||||
stub_request(:post, "#{api_instance_path_with_token}/read-message")
|
||||
.with(headers: stub_headers)
|
||||
.to_return(status: 400, body: 'error message', headers: {})
|
||||
.to_return(status: 400, body: 'error message')
|
||||
|
||||
allow(Rails.logger).to receive(:error)
|
||||
|
||||
expect do
|
||||
service.read_messages(messages, recipient_id: "+#{test_send_phone_number}")
|
||||
end.to raise_error(Whatsapp::Providers::WhatsappZapiService::ProviderUnavailableError)
|
||||
result = service.send_read_message(phone, message_source_id)
|
||||
|
||||
expect(result).to be(false)
|
||||
expect(Rails.logger).to have_received(:error).with('error message')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user