feat: Add the ability to receive contact(vCard) on a WhatsApp inbox (#6330)

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
Jacson Santos
2023-02-08 00:36:38 -03:00
committed by GitHub
parent bc96e5ed22
commit 73d14f204e
10 changed files with 296 additions and 80 deletions

View File

@@ -55,33 +55,29 @@ class Whatsapp::IncomingMessageBaseService
def create_messages
return if unprocessable_message_type?(message_type)
@message = @conversation.messages.build(
content: message_content(@processed_params[:messages].first),
account_id: @inbox.account_id,
inbox_id: @inbox.id,
message_type: :incoming,
sender: @contact,
source_id: @processed_params[:messages].first[:id].to_s
)
message = @processed_params[:messages].first
if message_type == 'contacts'
create_contact_messages(message)
else
create_regular_message(message)
end
end
def create_contact_messages(message)
message['contacts'].each do |contact|
create_message(contact)
attach_contact(contact)
@message.save!
end
end
def create_regular_message(message)
create_message(message)
attach_files
attach_location if message_type == 'location'
@message.save!
end
def processed_params
@processed_params ||= params
end
def message_content(message)
# TODO: map interactive messages back to button messages in chatwoot
message.dig(:text, :body) || message.dig(:button, :text) || message.dig(:interactive, :button_reply, :title) ||
message.dig(:interactive, :list_reply, :title)
end
def account
@account ||= inbox.account
end
def set_contact
contact_params = @processed_params[:contacts]&.first
return if contact_params.blank?
@@ -96,15 +92,6 @@ class Whatsapp::IncomingMessageBaseService
@contact = contact_inbox.contact
end
def conversation_params
{
account_id: @inbox.account_id,
inbox_id: @inbox.id,
contact_id: @contact.id,
contact_inbox_id: @contact_inbox.id
}
end
def set_conversation
@conversation = @contact_inbox.conversations.last
return if @conversation
@@ -112,12 +99,8 @@ class Whatsapp::IncomingMessageBaseService
@conversation = ::Conversation.create!(conversation_params)
end
def message_type
@processed_params[:messages].first[:type]
end
def attach_files
return if %w[text button interactive location].include?(message_type)
return if %w[text button interactive location contacts].include?(message_type)
attachment_payload = @processed_params[:messages].first[message_type.to_sym]
@message.content ||= attachment_payload[:caption]
@@ -136,10 +119,6 @@ class Whatsapp::IncomingMessageBaseService
)
end
def download_attachment_file(attachment_payload)
Down.download(inbox.channel.media_url(attachment_payload[:id]), headers: inbox.channel.api_headers)
end
def attach_location
location = @processed_params[:messages].first['location']
location_name = location['name'] ? "#{location['name']}, #{location['address']}" : ''
@@ -152,4 +131,28 @@ class Whatsapp::IncomingMessageBaseService
external_url: location['url']
)
end
def create_message(message)
@message = @conversation.messages.build(
content: message_content(message),
account_id: @inbox.account_id,
inbox_id: @inbox.id,
message_type: :incoming,
sender: @contact,
source_id: message[:id].to_s
)
end
def attach_contact(contact)
phones = contact[:phones]
phones = [{ phone: 'Phone number is not available' }] if phones.blank?
phones.each do |phone|
@message.attachments.new(
account_id: @message.account_id,
file_type: file_content_type(message_type),
fallback_title: phone[:phone].to_s
)
end
end
end

View File

@@ -1,14 +1,49 @@
module Whatsapp::IncomingMessageServiceHelpers
def download_attachment_file(attachment_payload)
Down.download(inbox.channel.media_url(attachment_payload[:id]), headers: inbox.channel.api_headers)
end
def conversation_params
{
account_id: @inbox.account_id,
inbox_id: @inbox.id,
contact_id: @contact.id,
contact_inbox_id: @contact_inbox.id
}
end
def processed_params
@processed_params ||= params
end
def account
@account ||= inbox.account
end
def message_type
@processed_params[:messages].first[:type]
end
def message_content(message)
# TODO: map interactive messages back to button messages in chatwoot
message.dig(:text, :body) ||
message.dig(:button, :text) ||
message.dig(:interactive, :button_reply, :title) ||
message.dig(:interactive, :list_reply, :title) ||
message.dig(:name, :formatted_name)
end
def file_content_type(file_type)
return :image if %w[image sticker].include?(file_type)
return :audio if %w[audio voice].include?(file_type)
return :video if ['video'].include?(file_type)
return :location if ['location'].include?(file_type)
return :contact if ['contacts'].include?(file_type)
:file
end
def unprocessable_message_type?(message_type)
%w[reaction contacts ephemeral unsupported].include?(message_type)
%w[reaction ephemeral unsupported].include?(message_type)
end
end