fix: incoming document messages with caption (#61)

* fix: update contact creation in messages.update event spec and remove redundant content update test

* fix: enhance message type detection for document messages and improve content retrieval

* fix: add support for edited messages and improve document message handling

* chore: enhance message filtering logic to ignore specific message types

* test: add support for messages with captions in document messages

* test: add handling for edited messages to prevent contact and message creation

* fix: improve message handling by ignoring specific message types

* fix: add support to ignore context messages to prevent contact and message creation

* refactor: organize incoming baileys specs
This commit is contained in:
Cayo P. R. Oliveira 2025-06-04 09:32:22 -03:00 committed by GitHub
parent a3effacc21
commit 8d9f756a03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 17 deletions

View File

@ -45,20 +45,24 @@ module Whatsapp::BaileysHandlers::Helpers # rubocop:disable Metrics/ModuleLength
'audio'
elsif msg.key?(:videoMessage)
'video'
elsif msg.key?(:documentMessage)
elsif msg.key?(:documentMessage) || msg.key?(:documentWithCaptionMessage)
'file'
elsif msg.key?(:stickerMessage)
'sticker'
elsif msg.key?(:reactionMessage)
'reaction'
elsif msg.key?(:editedMessage)
'edited'
elsif msg.key?(:protocolMessage)
'protocol'
elsif msg.key?(:messageContextInfo)
'context'
else
'unsupported'
end
end
def message_content
def message_content # rubocop:disable Metrics/CyclomaticComplexity
case message_type
when 'text'
@raw_message.dig(:message, :conversation) || @raw_message.dig(:message, :extendedTextMessage, :text)
@ -66,6 +70,9 @@ module Whatsapp::BaileysHandlers::Helpers # rubocop:disable Metrics/ModuleLength
@raw_message.dig(:message, :imageMessage, :caption)
when 'video'
@raw_message.dig(:message, :videoMessage, :caption)
when 'file'
@raw_message.dig(:message, :documentMessage, :caption).presence ||
@raw_message.dig(:message, :documentWithCaptionMessage, :message, :documentMessage, :caption)
when 'reaction'
@raw_message.dig(:message, :reactionMessage, :text)
end
@ -90,7 +97,8 @@ module Whatsapp::BaileysHandlers::Helpers # rubocop:disable Metrics/ModuleLength
when 'audio'
@raw_message.dig(:message, :audioMessage, :mimetype)
when 'file'
@raw_message.dig(:message, :documentMessage, :mimetype)
@raw_message.dig(:message, :documentMessage, :mimetype).presence ||
@raw_message.dig(:message, :documentWithCaptionMessage, :message, :documentMessage, :mimetype)
end
end
@ -113,6 +121,11 @@ module Whatsapp::BaileysHandlers::Helpers # rubocop:disable Metrics/ModuleLength
phone_number_from_jid == inbox.channel.phone_number.delete('+')
end
def ignore_message?
message_type.in?(%w[protocol context edited]) ||
(message_type == 'reaction' && message_content.blank?)
end
def message_under_process?
key = format(Redis::RedisKeys::MESSAGE_SOURCE_KEY, id: raw_message_id)
Redis::Alfred.get(key)

View File

@ -22,7 +22,7 @@ module Whatsapp::BaileysHandlers::MessagesUpsert
def handle_message
return if jid_type != 'user'
return if message_type == 'protocol'
return if ignore_message?
return if find_message_by_source_id(raw_message_id) || message_under_process?
cache_message_source_id_in_redis
@ -56,9 +56,6 @@ module Whatsapp::BaileysHandlers::MessagesUpsert
end
def handle_create_message
return if message_type == 'protocol' ||
(message_type == 'reaction' && message_content.blank?)
create_message(attach_media: %w[image file video audio sticker].include?(message_type))
end

View File

@ -200,6 +200,29 @@ describe Whatsapp::IncomingMessageBaileysService do
end
end
context 'when message is context message' do
it 'does not create contact inbox nor message' do
raw_message[:message] = { 'messageContextInfo': { 'deviceListMetadata': {},
'deviceListMetadataVersion': 2,
'messageSecret': '********' } }
described_class.new(inbox: inbox, params: params).perform
expect(inbox.messages).to be_empty
expect(inbox.contact_inboxes).to be_empty
end
end
context 'when message is edited message' do
it 'does not create contact inbox nor message' do
raw_message[:message] = { editedMessage: { message: { protocolMessage: { editedMessage: { documentMessage: 1 } } } } }
described_class.new(inbox: inbox, params: params).perform
expect(inbox.messages).to be_empty
expect(inbox.contact_inboxes).to be_empty
end
end
context 'when message is not from a user' do
it 'does not create a conversation' do
raw_message[:key][:remoteJid] = 'status@broadcast'
@ -407,7 +430,6 @@ describe Whatsapp::IncomingMessageBaileysService do
described_class.new(inbox: inbox, params: params).perform
message = inbox.conversations.last.messages.last
expect(message.content).to eq('Hello from Baileys')
end
@ -418,7 +440,6 @@ describe Whatsapp::IncomingMessageBaileysService do
message = inbox.conversations.last.messages.last
attachment = message.attachments.last
expect(attachment.file_type).to eq('image')
expect(attachment.file.filename.to_s).to eq("image_msg_123_#{Time.current.strftime('%Y%m%d')}.png")
expect(attachment.file.content_type).to eq('image/png')
@ -473,7 +494,6 @@ describe Whatsapp::IncomingMessageBaileysService do
message = inbox.conversations.last.messages.last
attachment = message.attachments.last
expect(attachment.file_type).to eq('video')
expect(attachment.file.filename.to_s).to eq("video_msg_123_#{Time.current.strftime('%Y%m%d')}.mp4")
expect(attachment.file.content_type).to eq('video/mp4')
@ -506,11 +526,30 @@ describe Whatsapp::IncomingMessageBaileysService do
message = inbox.conversations.last.messages.last
attachment = message.attachments.last
expect(attachment.file_type).to eq('file')
expect(attachment.file.filename.to_s).to eq(filename)
expect(attachment.file.content_type).to eq('application/pdf')
end
it 'creates the message with caption' do
params[:data][:messages].first[:message] = {
documentWithCaptionMessage: {
message: {
documentMessage: {
fileName: filename,
caption: 'Hello from Baileys'
}
}
}
}
stub_download
described_class.new(inbox: inbox, params: params).perform
message = inbox.conversations.last.messages.last
expect(message).to be_present
expect(message.content).to eq('Hello from Baileys')
end
end
context 'when message type is audio' do
@ -538,7 +577,6 @@ describe Whatsapp::IncomingMessageBaileysService do
message = inbox.conversations.last.messages.last
attachment = message.attachments.last
expect(attachment.file_type).to eq('audio')
expect(attachment.file.filename.to_s).to eq("audio_msg_123_#{Time.current.strftime('%Y%m%d')}.opus")
expect(attachment.file.content_type).to eq('audio/opus')
@ -570,7 +608,6 @@ describe Whatsapp::IncomingMessageBaileysService do
message = inbox.conversations.last.messages.last
attachment = message.attachments.last
expect(attachment.file_type).to eq('image')
expect(attachment.file.filename.to_s).to eq("image_msg_123_#{Time.current.strftime('%Y%m%d')}.png")
expect(attachment.file.content_type).to eq('image/png')
@ -580,10 +617,9 @@ describe Whatsapp::IncomingMessageBaileysService do
context 'when processing messages.update event' do
let(:conversation) do
agent = create(:user, account: inbox.account, role: :agent)
contact = create(:contact, account: inbox.account)
contact_inbox = create(:contact_inbox, inbox: inbox, contact: contact)
create(:conversation, inbox: inbox, contact_inbox: contact_inbox, assignee_id: agent.id)
contact = create(:contact, account: inbox.account, name: 'John Doe')
contact_inbox = create(:contact_inbox, inbox: inbox, contact: contact, source_id: '5511912345678')
create(:conversation, inbox: inbox, contact_inbox: contact_inbox, assignee_id: contact.id)
end
let!(:message) { create(:message, inbox: inbox, conversation: conversation, source_id: 'msg_123', status: 'sent') }
let(:update_payload) { { key: { id: 'msg_123' }, update: { status: 3 } } }