feat(baileys): add reply context handling (#196)
This commit is contained in:
parent
0de6001b97
commit
b5d3250a2a
@ -67,9 +67,9 @@ class Whatsapp::Providers::WhatsappBaileysService < Whatsapp::Providers::BaseSer
|
||||
if @message.content_attributes[:is_reaction]
|
||||
@message_content = reaction_message_content
|
||||
elsif @message.attachments.present?
|
||||
@message_content = attachment_message_content
|
||||
@message_content = attachment_message_content.merge(reply_context)
|
||||
elsif @message.outgoing_content.present?
|
||||
@message_content = { text: @message.outgoing_content }
|
||||
@message_content = { text: @message.outgoing_content }.merge(reply_context)
|
||||
else
|
||||
@message.update!(is_unsupported: true)
|
||||
return
|
||||
@ -304,6 +304,45 @@ class Whatsapp::Providers::WhatsappBaileysService < Whatsapp::Providers::BaseSer
|
||||
}
|
||||
end
|
||||
|
||||
def reply_context
|
||||
reply_to_external_id = @message.content_attributes[:in_reply_to_external_id]
|
||||
return {} if reply_to_external_id.blank?
|
||||
|
||||
reply_to_message = @message.conversation.messages.find_by(source_id: reply_to_external_id)
|
||||
return {} unless reply_to_message
|
||||
|
||||
{
|
||||
quotedMessage: {
|
||||
key: {
|
||||
id: reply_to_external_id,
|
||||
remoteJid: remote_jid,
|
||||
fromMe: reply_to_message.message_type == 'outgoing'
|
||||
},
|
||||
message: quoted_message_content(reply_to_message)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def quoted_message_content(message)
|
||||
if message.attachments.present?
|
||||
attachment = message.attachments.first
|
||||
case attachment.file_type
|
||||
when 'image'
|
||||
{ imageMessage: { caption: message.content } }
|
||||
when 'video'
|
||||
{ videoMessage: { caption: message.content } }
|
||||
when 'audio'
|
||||
{ audioMessage: {} }
|
||||
when 'file'
|
||||
{ documentMessage: { caption: message.content, fileName: attachment.file.filename.to_s } }
|
||||
else
|
||||
{ conversation: message.content.to_s }
|
||||
end
|
||||
else
|
||||
{ conversation: message.content.to_s }
|
||||
end
|
||||
end
|
||||
|
||||
def attachment_message_content # rubocop:disable Metrics/MethodLength
|
||||
attachment = @message.attachments.first
|
||||
buffer = attachment_to_base64(attachment)
|
||||
|
||||
@ -437,6 +437,146 @@ describe Whatsapp::Providers::WhatsappBaileysService do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is a reply to another message' do
|
||||
let(:inbox) { whatsapp_channel.inbox }
|
||||
let(:account_user) { create(:account_user, account: inbox.account) }
|
||||
let(:contact) { create(:contact, account: inbox.account, name: 'John Doe', phone_number: "+#{test_send_phone_number}") }
|
||||
let(:conversation) do
|
||||
contact_inbox = create(:contact_inbox, inbox: inbox, contact: contact, source_id: test_send_phone_number)
|
||||
create(:conversation, inbox: inbox, contact_inbox: contact_inbox)
|
||||
end
|
||||
|
||||
it 'sends text reply to outgoing message with quotedMessage' do
|
||||
original_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user,
|
||||
message_type: 'outgoing', source_id: 'original_msg_123', content: 'Original text')
|
||||
reply_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user,
|
||||
content: 'Reply text', content_attributes: { in_reply_to_external_id: original_message.source_id })
|
||||
|
||||
stub_request(:post, request_path)
|
||||
.with(
|
||||
headers: stub_headers(whatsapp_channel),
|
||||
body: {
|
||||
jid: test_send_jid,
|
||||
messageContent: {
|
||||
text: 'Reply text',
|
||||
quotedMessage: {
|
||||
key: {
|
||||
id: 'original_msg_123',
|
||||
remoteJid: test_send_jid,
|
||||
fromMe: true
|
||||
},
|
||||
message: { conversation: 'Original text' }
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
)
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
body: result_body.to_json
|
||||
)
|
||||
|
||||
result = service.send_message(test_send_phone_number, reply_message)
|
||||
|
||||
expect(result).to eq('msg_123')
|
||||
end
|
||||
|
||||
it 'sends text reply to incoming message with quotedMessage' do
|
||||
original_message = create(:message, inbox: inbox, conversation: conversation, sender: contact,
|
||||
message_type: 'incoming', source_id: 'incoming_msg_456', content: 'Incoming text')
|
||||
reply_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user,
|
||||
content: 'Reply to incoming', content_attributes: { in_reply_to_external_id: original_message.source_id })
|
||||
|
||||
stub_request(:post, request_path)
|
||||
.with(
|
||||
headers: stub_headers(whatsapp_channel),
|
||||
body: {
|
||||
jid: test_send_jid,
|
||||
messageContent: {
|
||||
text: 'Reply to incoming',
|
||||
quotedMessage: {
|
||||
key: {
|
||||
id: 'incoming_msg_456',
|
||||
remoteJid: test_send_jid,
|
||||
fromMe: false
|
||||
},
|
||||
message: { conversation: 'Incoming text' }
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
)
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
body: result_body.to_json
|
||||
)
|
||||
|
||||
result = service.send_message(test_send_phone_number, reply_message)
|
||||
|
||||
expect(result).to eq('msg_123')
|
||||
end
|
||||
|
||||
it 'sends reply to message with image attachment' do
|
||||
original_message = create(:message, inbox: inbox, conversation: conversation, sender: contact,
|
||||
message_type: 'incoming', source_id: 'image_msg_789', content: 'Check this image')
|
||||
original_message.attachments.create!(account_id: original_message.account_id, file_type: 'image',
|
||||
file: { io: StringIO.new('fake'), filename: 'image.png' })
|
||||
|
||||
reply_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user,
|
||||
content: 'Nice image!', content_attributes: { in_reply_to_external_id: original_message.source_id })
|
||||
|
||||
stub_request(:post, request_path)
|
||||
.with(
|
||||
headers: stub_headers(whatsapp_channel),
|
||||
body: {
|
||||
jid: test_send_jid,
|
||||
messageContent: {
|
||||
text: 'Nice image!',
|
||||
quotedMessage: {
|
||||
key: {
|
||||
id: 'image_msg_789',
|
||||
remoteJid: test_send_jid,
|
||||
fromMe: false
|
||||
},
|
||||
message: { imageMessage: { caption: 'Check this image' } }
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
)
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
body: result_body.to_json
|
||||
)
|
||||
|
||||
result = service.send_message(test_send_phone_number, reply_message)
|
||||
|
||||
expect(result).to eq('msg_123')
|
||||
end
|
||||
|
||||
it 'sends message without quotedMessage when in_reply_to_external_id is blank' do
|
||||
regular_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user, content: 'Regular message')
|
||||
|
||||
stub_request(:post, request_path)
|
||||
.with(
|
||||
headers: stub_headers(whatsapp_channel),
|
||||
body: {
|
||||
jid: test_send_jid,
|
||||
messageContent: { text: 'Regular message' }
|
||||
}.to_json
|
||||
)
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
body: result_body.to_json
|
||||
)
|
||||
|
||||
result = service.send_message(test_send_phone_number, regular_message)
|
||||
|
||||
expect(result).to eq('msg_123')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when request is unsuccessful' do
|
||||
it 'raises ProviderUnavailableError' do
|
||||
stub_request(:post, request_path)
|
||||
|
||||
@ -441,6 +441,84 @@ describe Whatsapp::Providers::WhatsappZapiService do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is a reply to another message' do
|
||||
let(:inbox) { whatsapp_channel.inbox }
|
||||
let(:account_user) { create(:account_user, account: inbox.account) }
|
||||
let(:contact) { create(:contact, account: inbox.account, name: 'John Doe', phone_number: "+#{test_send_phone_number}") }
|
||||
let(:conversation) do
|
||||
contact_inbox = create(:contact_inbox, inbox: inbox, contact: contact, source_id: test_send_phone_number)
|
||||
create(:conversation, inbox: inbox, contact_inbox: contact_inbox)
|
||||
end
|
||||
|
||||
it 'sends text reply with messageId parameter' do
|
||||
original_message = create(:message, inbox: inbox, conversation: conversation, sender: contact,
|
||||
message_type: 'incoming', source_id: 'original_zapi_msg_123', content: 'Original text')
|
||||
reply_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user,
|
||||
content: 'Reply text', content_attributes: { in_reply_to_external_id: original_message.source_id })
|
||||
|
||||
stub_request(:post, request_path)
|
||||
.with(
|
||||
headers: stub_headers,
|
||||
body: {
|
||||
phone: test_send_phone_number,
|
||||
message: 'Reply text',
|
||||
messageId: 'original_zapi_msg_123'
|
||||
}.to_json
|
||||
)
|
||||
.to_return(status: 200, body: result_body.to_json, headers: { 'Content-Type' => 'application/json' })
|
||||
|
||||
result = service.send_message("+#{test_send_phone_number}", reply_message)
|
||||
|
||||
expect(result).to eq('msg_123')
|
||||
end
|
||||
|
||||
it 'sends image reply with messageId parameter' do
|
||||
base64_image = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='
|
||||
buffer = "data:image/png;base64,#{base64_image}"
|
||||
|
||||
original_message = create(:message, inbox: inbox, conversation: conversation, sender: contact,
|
||||
message_type: 'incoming', source_id: 'original_zapi_img_456', content: 'Check this')
|
||||
reply_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user,
|
||||
content: 'Nice!', content_attributes: { in_reply_to_external_id: original_message.source_id })
|
||||
reply_message.attachments.create!(account_id: reply_message.account_id, file_type: 'image',
|
||||
file: { io: StringIO.new(Base64.decode64(base64_image)), filename: 'reply.png' })
|
||||
|
||||
stub_request(:post, "#{api_instance_path_with_token}/send-image")
|
||||
.with(
|
||||
headers: stub_headers,
|
||||
body: {
|
||||
phone: test_send_phone_number,
|
||||
image: buffer,
|
||||
caption: 'Nice!',
|
||||
messageId: 'original_zapi_img_456'
|
||||
}.to_json
|
||||
)
|
||||
.to_return(status: 200, body: result_body.to_json, headers: { 'Content-Type' => 'application/json' })
|
||||
|
||||
result = service.send_message("+#{test_send_phone_number}", reply_message)
|
||||
|
||||
expect(result).to eq('msg_123')
|
||||
end
|
||||
|
||||
it 'sends message without messageId when in_reply_to_external_id is blank' do
|
||||
regular_message = create(:message, inbox: inbox, conversation: conversation, sender: account_user, content: 'Regular message')
|
||||
|
||||
stub_request(:post, request_path)
|
||||
.with(
|
||||
headers: stub_headers,
|
||||
body: {
|
||||
phone: test_send_phone_number,
|
||||
message: 'Regular message'
|
||||
}.to_json
|
||||
)
|
||||
.to_return(status: 200, body: result_body.to_json, headers: { 'Content-Type' => 'application/json' })
|
||||
|
||||
result = service.send_message("+#{test_send_phone_number}", regular_message)
|
||||
|
||||
expect(result).to eq('msg_123')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is an image file' do
|
||||
let(:base64_image) { 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=' }
|
||||
let(:buffer) { "data:image/png;base64,#{base64_image}" }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user