From 322f0d19223d2632b823c38627f9e0bd35aacaae Mon Sep 17 00:00:00 2001 From: "Cayo P. R. Oliveira" Date: Fri, 9 May 2025 10:52:07 -0300 Subject: [PATCH] feat: use message is unsupported content attribute (#44) * refactor: simplify message_type method using a hash for message types * refactor: streamline message handling and update unsupported message logic * refactor: simplify create_message method by inlining sender_type and message_type assignments * refactor: simplify message_type method for improved readability and performance * feat: allow is_recorded_audio as boolean * chore: refactor create message + attach media logic * fix: unsupported message templates --------- Co-authored-by: gabrieljablonski --- app/builders/messages/message_builder.rb | 6 +- .../widgets/conversation/Message.vue | 3 + .../i18n/locale/en/conversation.json | 3 +- .../i18n/locale/pt_BR/conversation.json | 3 +- .../incoming_message_baileys_service.rb | 82 +++++++++---------- .../providers/whatsapp_baileys_service.rb | 2 +- .../incoming_message_baileys_service_spec.rb | 12 +-- .../whatsapp_baileys_service_spec.rb | 9 +- 8 files changed, 55 insertions(+), 65 deletions(-) diff --git a/app/builders/messages/message_builder.rb b/app/builders/messages/message_builder.rb index 7a8578fdd..7d34af469 100644 --- a/app/builders/messages/message_builder.rb +++ b/app/builders/messages/message_builder.rb @@ -80,7 +80,11 @@ class Messages::MessageBuilder end def process_metadata(attachment) - { is_recorded_audio: true } if @is_recorded_audio && attachment.original_filename.in?(@is_recorded_audio) + # NOTE: `is_recorded_audio` can be either a boolean or an array of file names. + return unless @is_recorded_audio + return { is_recorded_audio: true } if @is_recorded_audio == true + + { is_recorded_audio: true } if @is_recorded_audio.is_a?(Array) && attachment.original_filename.in?(@is_recorded_audio) end def process_emails diff --git a/app/javascript/dashboard/components/widgets/conversation/Message.vue b/app/javascript/dashboard/components/widgets/conversation/Message.vue index 253eaeaa7..67ecbe92a 100644 --- a/app/javascript/dashboard/components/widgets/conversation/Message.vue +++ b/app/javascript/dashboard/components/widgets/conversation/Message.vue @@ -485,6 +485,9 @@ export default { + diff --git a/app/javascript/dashboard/i18n/locale/en/conversation.json b/app/javascript/dashboard/i18n/locale/en/conversation.json index d1c1fb571..480c5c05a 100644 --- a/app/javascript/dashboard/i18n/locale/en/conversation.json +++ b/app/javascript/dashboard/i18n/locale/en/conversation.json @@ -52,7 +52,8 @@ }, "UPLOADING_ATTACHMENTS": "Uploading attachments...", "REPLIED_TO_STORY": "Replied to your story", - "UNSUPPORTED_MESSAGE": "This message is unsupported. You can view this message on the Facebook / Instagram app.", + "UNSUPPORTED_MESSAGE": "This message is unsupported. You can view this message on the app.", + "UNSUPPORTED_MESSAGE_WHATSAPP": "This message is unsupported. You can view this message on the WhatsApp app.", "UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.", "UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.", "SUCCESS_DELETE_MESSAGE": "Message deleted successfully", diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json b/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json index 6524f9d37..2e086d3c8 100644 --- a/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json +++ b/app/javascript/dashboard/i18n/locale/pt_BR/conversation.json @@ -52,7 +52,8 @@ }, "UPLOADING_ATTACHMENTS": "Enviando anexos...", "REPLIED_TO_STORY": "Respondido ao seu story", - "UNSUPPORTED_MESSAGE": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo Facebook Messenger.", + "UNSUPPORTED_MESSAGE": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo.", + "UNSUPPORTED_MESSAGE_WHATSAPP": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo do WhatsApp.", "UNSUPPORTED_MESSAGE_FACEBOOK": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo Facebook Messenger.", "UNSUPPORTED_MESSAGE_INSTAGRAM": "Esta mensagem não é suportada. Você pode ver esta mensagem no aplicativo do Instagram.", "SUCCESS_DELETE_MESSAGE": "Mensagem excluída com sucesso", diff --git a/app/services/whatsapp/incoming_message_baileys_service.rb b/app/services/whatsapp/incoming_message_baileys_service.rb index b0eb2879f..709534539 100644 --- a/app/services/whatsapp/incoming_message_baileys_service.rb +++ b/app/services/whatsapp/incoming_message_baileys_service.rb @@ -99,17 +99,10 @@ class Whatsapp::IncomingMessageBaileysService < Whatsapp::IncomingMessageBaseSer end def handle_create_message - case message_type - when 'text' - create_message - when 'reaction' - create_message if message_content.present? - when 'image', 'file', 'video', 'audio', 'sticker' - create_message(attach_media: true) - when 'unsupported' - create_unsupported_message - Rails.logger.warn "Baileys unsupported message type: #{message_type}" - end + 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 def jid_type # rubocop:disable Metrics/CyclomaticComplexity @@ -136,34 +129,38 @@ class Whatsapp::IncomingMessageBaileysService < Whatsapp::IncomingMessageBaseSer end end - def message_type # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity + def message_type # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength msg = @raw_message[:message] - - return 'text' if msg.key?(:conversation) || msg.dig(:extendedTextMessage, :text).present? - return 'image' if msg.key?(:imageMessage) - return 'audio' if msg.key?(:audioMessage) - return 'video' if msg.key?(:videoMessage) - return 'file' if msg.key?(:documentMessage) - return 'sticker' if msg.key?(:stickerMessage) - return 'reaction' if msg.key?(:reactionMessage) - return 'protocol' if msg.key?(:protocolMessage) - - 'unsupported' + @message_type ||= if msg.key?(:conversation) || msg.dig(:extendedTextMessage, :text).present? + 'text' + elsif msg.key?(:imageMessage) + 'image' + elsif msg.key?(:audioMessage) + 'audio' + elsif msg.key?(:videoMessage) + 'video' + elsif msg.key?(:documentMessage) + 'file' + elsif msg.key?(:stickerMessage) + 'sticker' + elsif msg.key?(:reactionMessage) + 'reaction' + elsif msg.key?(:protocolMessage) + 'protocol' + else + 'unsupported' + end end def create_message(attach_media: false) - sender = incoming? ? @contact : @inbox.account.account_users.first.user - sender_type = incoming? ? 'Contact' : 'User' - message_type = incoming? ? :incoming : :outgoing - @message = @conversation.messages.build( content: message_content, account_id: @inbox.account_id, inbox_id: @inbox.id, source_id: message_id, - sender: sender, - sender_type: sender_type, - message_type: message_type, + sender: incoming? ? @contact : @inbox.account.account_users.first.user, + sender_type: incoming? ? 'Contact' : 'User', + message_type: incoming? ? :incoming : :outgoing, content_attributes: message_content_attributes ) @@ -173,27 +170,22 @@ class Whatsapp::IncomingMessageBaileysService < Whatsapp::IncomingMessageBaseSer end def message_content_attributes - return unless message_type == 'reaction' - - { - in_reply_to_external_id: @raw_message.dig(:message, :reactionMessage, :key, :id), - is_reaction: true - } + if message_type == 'reaction' + { + in_reply_to_external_id: @raw_message.dig(:message, :reactionMessage, :key, :id), + is_reaction: true + } + elsif message_type == 'unsupported' + { + is_unsupported: true + } + end end def incoming? !@raw_message[:key][:fromMe] end - def create_unsupported_message - create_message - @message.update!( - content: I18n.t('errors.messages.unsupported'), - message_type: 'template', - status: 'failed' - ) - end - def handle_attach_media media = processed_params.dig(:extra, :media) return if media.blank? diff --git a/app/services/whatsapp/providers/whatsapp_baileys_service.rb b/app/services/whatsapp/providers/whatsapp_baileys_service.rb index e3c33b72f..5bd986c66 100644 --- a/app/services/whatsapp/providers/whatsapp_baileys_service.rb +++ b/app/services/whatsapp/providers/whatsapp_baileys_service.rb @@ -40,7 +40,7 @@ class Whatsapp::Providers::WhatsappBaileysService < Whatsapp::Providers::BaseSer elsif message.content.present? @message_content = { text: @message.content } else - message.update!(content: I18n.t('errors.messages.send.unsupported'), status: 'failed') + @message.update!(is_unsupported: true) return end diff --git a/spec/services/whatsapp/incoming_message_baileys_service_spec.rb b/spec/services/whatsapp/incoming_message_baileys_service_spec.rb index ed59fc5a7..a50d56e63 100644 --- a/spec/services/whatsapp/incoming_message_baileys_service_spec.rb +++ b/spec/services/whatsapp/incoming_message_baileys_service_spec.rb @@ -171,17 +171,7 @@ describe Whatsapp::IncomingMessageBaileysService do message = conversation.messages.last expect(message).to be_present - expect(message.content).to eq(I18n.t('errors.messages.unsupported')) - expect(message.message_type).to eq('template') - expect(message.status).to eq('failed') - end - - it 'logs a warning message' do - allow(Rails.logger).to receive(:warn).with('Baileys unsupported message type: unsupported') - - described_class.new(inbox: inbox, params: params).perform - - expect(Rails.logger).to have_received(:warn) + expect(message.is_unsupported).to be(true) end end diff --git a/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb b/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb index 5a96a86ec..4d96f095a 100644 --- a/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb +++ b/spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb @@ -94,14 +94,13 @@ describe Whatsapp::Providers::WhatsappBaileysService do describe '#send_message' do let(:request_path) { "#{whatsapp_channel.provider_config['provider_url']}/connections/#{whatsapp_channel.phone_number}/send-message" } - context 'when message does not have content nor attachments' do + context 'when message is unsupported' do it 'updates the message with content attribute is_unsupported' do - message.update!(content: nil) + unsupported_message = create(:message, content: nil) - service.send_message(test_send_phone_number, message) + service.send_message(test_send_phone_number, unsupported_message) - expect(message.content).to eq(I18n.t('errors.messages.send.unsupported')) - expect(message.status).to eq('failed') + expect(unsupported_message.is_unsupported).to be(true) end end