Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/services/whatsapp/conversation_sync_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ def create_echo_media_attachment(message, echo_data, media_data, attachment_file

message.attachments.build(
file_type: file_type.to_s,
fallback_title: filename,
file: {
io: attachment_file,
filename: filename,
Expand Down
33 changes: 18 additions & 15 deletions app/services/whatsapp/evolution_go_handlers/messages_upsert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -410,20 +410,20 @@ def file_content_type
end

def message_type_from_media
# Convert Evolution Go MediaType to message_type like Evolution v2
media_type = @evolution_go_info[:MediaType]
media_type = @evolution_go_info&.dig(:MediaType)

case media_type
when 'image'
'image'
when 'video'
'video'
when 'audio', 'ptt' # PTT (push-to-talk) is audio in Evolution v2
'audio'
when 'document'
'file'
else
'file'
if media_type.blank?
struct_type = message_type
media_type = struct_type == 'file' ? 'document' : struct_type
end

case media_type&.downcase
when 'image' then 'image'
when 'video' then 'video'
when 'audio', 'ptt' then 'audio'
when 'document', 'file' then 'file'
when 'sticker' then 'sticker'
else 'file'
end
end

Expand Down Expand Up @@ -453,7 +453,7 @@ def configure_audio_metadata(attachment)
end

def audio_voice_note?
@evolution_go_info[:MediaType] == 'ptt'
@evolution_go_info&.dig(:MediaType) == 'ptt'
end

def create_attachment(attachment_file)
Expand All @@ -468,7 +468,10 @@ def create_attachment(attachment_file)
content_type: final_content_type
)

attachment = @message.attachments.build(file_type: file_content_type.to_s)
attachment = @message.attachments.build(
file_type: file_content_type.to_s,
fallback_title: generate_filename_with_extension
)
attachment.file.attach(blob)

configure_audio_metadata(attachment) if audio_voice_note?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ def create_attachment(attachment_file)
content_type: final_content_type
)

attachment = @message.attachments.build(file_type: file_content_type.to_s)
attachment = @message.attachments.build(
file_type: file_content_type.to_s,
fallback_title: generate_filename_with_extension
)
attachment.file.attach(blob)

configure_audio_metadata(attachment) if audio_voice_note?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ def attach_file(message, content)

message.attachments.new(
file_type: file_content_type(file_type_key),
fallback_title: (File.basename(URI.parse(content[:fileUrl].to_s).path) rescue File.basename(content[:fileUrl].to_s)).presence,
file: { io: io, filename: File.basename(io.path), content_type: mime_type }
)

Expand Down
1 change: 1 addition & 0 deletions app/services/whatsapp/incoming_message_zapi_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ def attach_file(message, file_url, file_type, mime_type, filename = nil)

message.attachments.new(
file_type: file_content_type(file_type),
fallback_title: filename,
file: {
io: io,
filename: filename,
Expand Down
145 changes: 145 additions & 0 deletions spec/services/whatsapp/evolution_go_handlers/messages_upsert_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# frozen_string_literal: true

begin
require 'rails_helper'
rescue LoadError
RSpec.describe 'Whatsapp::EvolutionGoHandlers::MessagesUpsert' do
it 'has spec scaffold ready' do
skip 'rails_helper is not available in this workspace snapshot'
end
end
end

return unless defined?(Rails)

RSpec.describe Whatsapp::EvolutionGoHandlers::MessagesUpsert do
let(:host_class) do
Class.new do
include Whatsapp::EvolutionGoHandlers::MessagesUpsert

attr_writer :evolution_go_info, :evolution_go_message

def initialize(info: nil, message: nil)
@evolution_go_info = info
@evolution_go_message = message
end
end
end

subject(:service) { host_class.new(info: info, message: evo_message) }

let(:evo_message) { {} }
let(:info) { nil }

describe '#message_type_from_media' do
context 'when @evolution_go_info is nil' do
let(:info) { nil }

context 'and message struct is videoMessage' do
let(:evo_message) { { videoMessage: {} } }

it 'returns video' do
expect(service.send(:message_type_from_media)).to eq('video')
end
end

context 'and message struct is imageMessage' do
let(:evo_message) { { imageMessage: {} } }

it 'returns image' do
expect(service.send(:message_type_from_media)).to eq('image')
end
end

context 'and message struct is documentMessage' do
let(:evo_message) { { documentMessage: {} } }

it 'returns file' do
expect(service.send(:message_type_from_media)).to eq('file')
end
end

context 'and message struct is audioMessage' do
let(:evo_message) { { audioMessage: {} } }

it 'returns audio' do
expect(service.send(:message_type_from_media)).to eq('audio')
end
end

context 'and message struct is stickerMessage' do
let(:evo_message) { { stickerMessage: {} } }

it 'returns sticker' do
expect(service.send(:message_type_from_media)).to eq('sticker')
end
end
end

context 'when MediaType is blank string' do
let(:info) { { MediaType: '' } }
let(:evo_message) { { videoMessage: {} } }

it 'falls back to struct-based detection and returns video' do
expect(service.send(:message_type_from_media)).to eq('video')
end
end

context 'when MediaType is present' do
let(:evo_message) { {} }

it 'returns image for MediaType=image' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'image' })
expect(service.send(:message_type_from_media)).to eq('image')
end

it 'returns video for MediaType=video' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'video' })
expect(service.send(:message_type_from_media)).to eq('video')
end

it 'returns audio for MediaType=audio' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'audio' })
expect(service.send(:message_type_from_media)).to eq('audio')
end

it 'returns audio for MediaType=ptt' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'ptt' })
expect(service.send(:message_type_from_media)).to eq('audio')
end

it 'returns file for MediaType=document' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'document' })
expect(service.send(:message_type_from_media)).to eq('file')
end

it 'returns sticker for MediaType=sticker' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'sticker' })
expect(service.send(:message_type_from_media)).to eq('sticker')
end

it 'returns file for unknown MediaType' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'unknown_type' })
expect(service.send(:message_type_from_media)).to eq('file')
end
end
end

describe '#audio_voice_note?' do
it 'returns false without raising when @evolution_go_info is nil' do
service.instance_variable_set(:@evolution_go_info, nil)
expect { service.send(:audio_voice_note?) }.not_to raise_error
expect(service.send(:audio_voice_note?)).to be(false)
end

it 'returns true when MediaType is ptt' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'ptt' })
expect(service.send(:audio_voice_note?)).to be(true)
end

it 'returns false when MediaType is audio' do
service.instance_variable_set(:@evolution_go_info, { MediaType: 'audio' })
expect(service.send(:audio_voice_note?)).to be(false)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,13 @@ def log_base64_error(*); end
processor.create_attachment(tempfile)
end

it 'builds the attachment with the resolved file_content_type' do
it 'builds the attachment with file_type and fallback_title' do
allow(ActiveStorage::Blob).to receive(:create_and_upload!).and_return(fake_blob)

expect(attachments_relation).to receive(:build).with(file_type: 'image').and_return(built_attachment)
expect(attachments_relation).to receive(:build).with(
file_type: 'image',
fallback_title: 'msg-1.jpg'
).and_return(built_attachment)

processor.create_attachment(tempfile)
end
Expand Down