feat: on whatsapp baileys check (#95)
* feat: on whatsapp baileys check * chore: refactoring * chore: refactoring
This commit is contained in:
parent
c6f9e814c2
commit
99255c199f
@ -93,6 +93,20 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
|
||||
render status: :ok, json: { message: I18n.t('messages.inbox_deletetion_response') }
|
||||
end
|
||||
|
||||
def on_whatsapp
|
||||
params.require(:phone_number)
|
||||
phone_number = params[:phone_number]
|
||||
channel = @inbox.channel
|
||||
|
||||
unless channel.respond_to?(:on_whatsapp)
|
||||
render json: { error: 'Channel does not support whatsapp check' }, status: :unprocessable_entity and return
|
||||
end
|
||||
|
||||
response = channel.on_whatsapp(phone_number)
|
||||
|
||||
render json: response, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_inbox
|
||||
|
||||
@ -122,6 +122,12 @@ class Channel::Whatsapp < ApplicationRecord
|
||||
provider_service.received_messages(conversation.contact.phone_number, messages)
|
||||
end
|
||||
|
||||
def on_whatsapp(phone_number)
|
||||
return unless provider_service.respond_to?(:on_whatsapp)
|
||||
|
||||
provider_service.on_whatsapp(phone_number)
|
||||
end
|
||||
|
||||
delegate :setup_channel_provider, to: :provider_service
|
||||
delegate :send_message, to: :provider_service
|
||||
delegate :send_template, to: :provider_service
|
||||
|
||||
@ -61,4 +61,8 @@ class InboxPolicy < ApplicationPolicy
|
||||
def disconnect_channel_provider?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
||||
def on_whatsapp?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
@ -189,6 +189,22 @@ class Whatsapp::Providers::WhatsappBaileysService < Whatsapp::Providers::BaseSer
|
||||
true
|
||||
end
|
||||
|
||||
def on_whatsapp(phone_number)
|
||||
@phone_number = phone_number
|
||||
|
||||
response = HTTParty.post(
|
||||
"#{provider_url}/connections/#{whatsapp_channel.phone_number}/on-whatsapp",
|
||||
headers: api_headers,
|
||||
body: {
|
||||
jids: [remote_jid]
|
||||
}.to_json
|
||||
)
|
||||
|
||||
raise ProviderUnavailableError unless process_response(response)
|
||||
|
||||
response.parsed_response&.first || { 'jid' => remote_jid, 'exists' => false, 'lid' => nil }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def provider_url
|
||||
@ -255,6 +271,7 @@ class Whatsapp::Providers::WhatsappBaileysService < Whatsapp::Providers::BaseSer
|
||||
response.success?
|
||||
end
|
||||
|
||||
# FIXME: Make this a function with argument, instead of using instance variable
|
||||
def remote_jid
|
||||
"#{@phone_number.delete('+')}@s.whatsapp.net"
|
||||
end
|
||||
@ -306,5 +323,6 @@ class Whatsapp::Providers::WhatsappBaileysService < Whatsapp::Providers::BaseSer
|
||||
:update_presence,
|
||||
:read_messages,
|
||||
:unread_message,
|
||||
:received_messages
|
||||
:received_messages,
|
||||
:on_whatsapp
|
||||
end
|
||||
|
||||
@ -184,6 +184,7 @@ Rails.application.routes.draw do
|
||||
post :setup_channel_provider, on: :member
|
||||
post :disconnect_channel_provider, on: :member
|
||||
delete :avatar, on: :member
|
||||
post :on_whatsapp, on: :member
|
||||
end
|
||||
resources :inbox_members, only: [:create, :show], param: :inbox_id do
|
||||
collection do
|
||||
|
||||
@ -1021,4 +1021,71 @@ RSpec.describe 'Inboxes API', type: :request do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/:account_id/inboxes/:id/on_whatsapp' do
|
||||
let(:channel) { create(:channel_whatsapp, account: account, provider: 'baileys', validate_provider_config: false) }
|
||||
let(:inbox) { channel.inbox }
|
||||
|
||||
context 'when unauthenticated' do
|
||||
it 'returns unauthorized' do
|
||||
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/on_whatsapp"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated' do
|
||||
it 'returns unprocessable entity when channel does not support on_whatsapp' do
|
||||
inbox = create(:inbox, account: account)
|
||||
|
||||
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/on_whatsapp",
|
||||
headers: admin.create_new_auth_token,
|
||||
params: { phone_number: '+123456789' },
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(response.parsed_body['error']).to eq('Channel does not support whatsapp check')
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity when phone_number is not passed' do
|
||||
inbox = create(:inbox, account: account)
|
||||
|
||||
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/on_whatsapp",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(response.parsed_body['error']).to eq('param is missing or the value is empty: phone_number')
|
||||
end
|
||||
|
||||
it 'calls on_whatsapp when supported and returns provider response' do
|
||||
service_double = instance_double(Whatsapp::Providers::WhatsappBaileysService,
|
||||
on_whatsapp: { jid: '123456789@s.whatsapp.net', exists: true, lid: '123@lid' })
|
||||
allow(Whatsapp::Providers::WhatsappBaileysService).to receive(:new)
|
||||
.with(whatsapp_channel: channel)
|
||||
.and_return(service_double)
|
||||
|
||||
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/on_whatsapp",
|
||||
headers: admin.create_new_auth_token,
|
||||
params: { phone_number: '+123456789' },
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
|
||||
it 'calls on_whatsapp when supported and returns default response on no response from provider' do
|
||||
service_double = instance_double(Whatsapp::Providers::WhatsappBaileysService, on_whatsapp: nil)
|
||||
allow(Whatsapp::Providers::WhatsappBaileysService).to receive(:new)
|
||||
.with(whatsapp_channel: channel)
|
||||
.and_return(service_double)
|
||||
|
||||
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/on_whatsapp",
|
||||
headers: admin.create_new_auth_token,
|
||||
params: { phone_number: '+123456789' },
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -295,6 +295,32 @@ RSpec.describe Channel::Whatsapp do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#on_whatsapp' do
|
||||
let(:channel) { create(:channel_whatsapp, provider: 'baileys', validate_provider_config: false, sync_templates: false) }
|
||||
let(:conversation) { create(:conversation) }
|
||||
let(:phone_number) { '+123456789' }
|
||||
|
||||
it 'calls provider service method' do
|
||||
provider_double = instance_double(Whatsapp::Providers::WhatsappBaileysService, on_whatsapp: nil)
|
||||
allow(provider_double).to receive(:on_whatsapp).with(phone_number)
|
||||
allow(Whatsapp::Providers::WhatsappBaileysService).to receive(:new)
|
||||
.with(whatsapp_channel: channel)
|
||||
.and_return(provider_double)
|
||||
|
||||
channel.on_whatsapp(phone_number)
|
||||
|
||||
expect(provider_double).to have_received(:on_whatsapp)
|
||||
end
|
||||
|
||||
it 'does not call method if provider service does not implement it' do
|
||||
channel.update!(provider: 'whatsapp_cloud')
|
||||
|
||||
expect do
|
||||
channel.on_whatsapp(phone_number)
|
||||
end.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe 'callbacks' do
|
||||
describe '#disconnect_channel_provider' do
|
||||
context 'when provider is baileys' do
|
||||
|
||||
@ -642,6 +642,64 @@ describe Whatsapp::Providers::WhatsappBaileysService do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#on_whatsapp' do
|
||||
let(:request_path) { "#{whatsapp_channel.provider_config['provider_url']}/connections/#{whatsapp_channel.phone_number}/on-whatsapp" }
|
||||
let(:phone_number) { '+123456789' }
|
||||
|
||||
context 'when response is successful' do
|
||||
it 'requests whatsapp check' do
|
||||
stub_request(:post, request_path)
|
||||
.with(headers: stub_headers(whatsapp_channel), body: { jids: ["#{phone_number.delete('+')}@s.whatsapp.net"] }.to_json)
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
body: [{ jid: "#{phone_number.delete('+')}@s.whatsapp.net", exists: true, lid: '123@lid' }].to_json
|
||||
)
|
||||
|
||||
response = service.on_whatsapp(phone_number)
|
||||
|
||||
expect(response).to eq({ 'jid' => "#{phone_number.delete('+')}@s.whatsapp.net", 'exists' => true, 'lid' => '123@lid' })
|
||||
end
|
||||
|
||||
it 'returns default check response' do
|
||||
stub_request(:post, request_path)
|
||||
.with(headers: stub_headers(whatsapp_channel), body: { jids: ["#{phone_number.delete('+')}@s.whatsapp.net"] }.to_json)
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
body: [].to_json
|
||||
)
|
||||
|
||||
response = service.on_whatsapp(phone_number)
|
||||
|
||||
expect(response).to eq({ 'jid' => "#{phone_number.delete('+')}@s.whatsapp.net", 'exists' => false, 'lid' => nil })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when response is unsuccessful' do
|
||||
it 'raises ProviderUnavailableError and logs the error' do
|
||||
stub_request(:post, request_path)
|
||||
.with(headers: stub_headers(whatsapp_channel), body: { jids: ["#{phone_number.delete('+')}@s.whatsapp.net"] }.to_json)
|
||||
.to_return(
|
||||
status: 400,
|
||||
body: 'error message',
|
||||
headers: {}
|
||||
)
|
||||
|
||||
stub_request(:post, "#{whatsapp_channel.provider_config['provider_url']}/connections/#{whatsapp_channel.phone_number}")
|
||||
.to_return(status: 200)
|
||||
|
||||
allow(Rails.logger).to receive(:error)
|
||||
|
||||
expect do
|
||||
service.on_whatsapp(phone_number)
|
||||
end.to raise_error(Whatsapp::Providers::WhatsappBaileysService::ProviderUnavailableError)
|
||||
|
||||
expect(Rails.logger).to have_received(:error).with('error message')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when environment variable BAILEYS_PROVIDER_DEFAULT_URL is set' do
|
||||
it 'uses the base url from the environment variable' do
|
||||
stub_const('Whatsapp::Providers::WhatsappBaileysService::DEFAULT_URL', 'http://test.com')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user