feat: Add Instagram Channel (#2955)
This commit is contained in:
@@ -4,10 +4,11 @@
|
||||
# based on this we are showing "not sent from chatwoot" message in frontend
|
||||
# Hence there is no need to set user_id in message for outgoing echo messages.
|
||||
|
||||
class Messages::Facebook::MessageBuilder
|
||||
class Messages::Facebook::MessageBuilder < Messages::Messenger::MessageBuilder
|
||||
attr_reader :response
|
||||
|
||||
def initialize(response, inbox, outgoing_echo: false)
|
||||
super()
|
||||
@response = response
|
||||
@inbox = inbox
|
||||
@outgoing_echo = outgoing_echo
|
||||
@@ -47,30 +48,12 @@ class Messages::Facebook::MessageBuilder
|
||||
|
||||
def build_message
|
||||
@message = conversation.messages.create!(message_params)
|
||||
|
||||
@attachments.each do |attachment|
|
||||
process_attachment(attachment)
|
||||
end
|
||||
end
|
||||
|
||||
def process_attachment(attachment)
|
||||
return if attachment['type'].to_sym == :template
|
||||
|
||||
attachment_obj = @message.attachments.new(attachment_params(attachment).except(:remote_file_url))
|
||||
attachment_obj.save!
|
||||
attach_file(attachment_obj, attachment_params(attachment)[:remote_file_url]) if attachment_params(attachment)[:remote_file_url]
|
||||
end
|
||||
|
||||
def attach_file(attachment, file_url)
|
||||
attachment_file = Down.download(
|
||||
file_url
|
||||
)
|
||||
attachment.file.attach(
|
||||
io: attachment_file,
|
||||
filename: attachment_file.original_filename,
|
||||
content_type: attachment_file.content_type
|
||||
)
|
||||
end
|
||||
|
||||
def ensure_contact_avatar
|
||||
return if contact_params[:remote_avatar_url].blank?
|
||||
return if @contact.avatar.attached?
|
||||
@@ -89,28 +72,6 @@ class Messages::Facebook::MessageBuilder
|
||||
))
|
||||
end
|
||||
|
||||
def attachment_params(attachment)
|
||||
file_type = attachment['type'].to_sym
|
||||
params = { file_type: file_type, account_id: @message.account_id }
|
||||
|
||||
if [:image, :file, :audio, :video].include? file_type
|
||||
params.merge!(file_type_params(attachment))
|
||||
elsif file_type == :location
|
||||
params.merge!(location_params(attachment))
|
||||
elsif file_type == :fallback
|
||||
params.merge!(fallback_params(attachment))
|
||||
end
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def file_type_params(attachment)
|
||||
{
|
||||
external_url: attachment['payload']['url'],
|
||||
remote_file_url: attachment['payload']['url']
|
||||
}
|
||||
end
|
||||
|
||||
def location_params(attachment)
|
||||
lat = attachment['payload']['coordinates']['lat']
|
||||
long = attachment['payload']['coordinates']['long']
|
||||
|
||||
150
app/builders/messages/instagram/message_builder.rb
Normal file
150
app/builders/messages/instagram/message_builder.rb
Normal file
@@ -0,0 +1,150 @@
|
||||
# This class creates both outgoing messages from chatwoot and echo outgoing messages based on the flag `outgoing_echo`
|
||||
# Assumptions
|
||||
# 1. Incase of an outgoing message which is echo, source_id will NOT be nil,
|
||||
# based on this we are showing "not sent from chatwoot" message in frontend
|
||||
# Hence there is no need to set user_id in message for outgoing echo messages.
|
||||
|
||||
class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder
|
||||
attr_reader :messaging
|
||||
|
||||
def initialize(messaging, inbox, outgoing_echo: false)
|
||||
super()
|
||||
@messaging = messaging
|
||||
@inbox = inbox
|
||||
@outgoing_echo = outgoing_echo
|
||||
end
|
||||
|
||||
def perform
|
||||
return if @inbox.channel.reauthorization_required?
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
build_message
|
||||
end
|
||||
rescue Koala::Facebook::AuthenticationError
|
||||
@inbox.channel.authorization_error!
|
||||
raise
|
||||
rescue StandardError => e
|
||||
Sentry.capture_exception(e)
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attachments
|
||||
@messaging[:message][:attachments] || {}
|
||||
end
|
||||
|
||||
def message_type
|
||||
@outgoing_echo ? :outgoing : :incoming
|
||||
end
|
||||
|
||||
def message_source_id
|
||||
@outgoing_echo ? recipient_id : sender_id
|
||||
end
|
||||
|
||||
def sender_id
|
||||
@messaging[:sender][:id]
|
||||
end
|
||||
|
||||
def recipient_id
|
||||
@messaging[:recipient][:id]
|
||||
end
|
||||
|
||||
def message
|
||||
@messaging[:message]
|
||||
end
|
||||
|
||||
def contact
|
||||
@contact ||= @inbox.contact_inboxes.find_by(source_id: message_source_id)&.contact
|
||||
end
|
||||
|
||||
def conversation
|
||||
@conversation ||= Conversation.find_by(conversation_params) || build_conversation
|
||||
end
|
||||
|
||||
def message_content
|
||||
@messaging[:message][:text]
|
||||
end
|
||||
|
||||
def content_attributes
|
||||
{ message_id: @messaging[:message][:mid] }
|
||||
end
|
||||
|
||||
def build_message
|
||||
return if @outgoing_echo && already_sent_from_chatwoot?
|
||||
|
||||
@message = conversation.messages.create!(message_params)
|
||||
|
||||
attachments.each do |attachment|
|
||||
process_attachment(attachment)
|
||||
end
|
||||
end
|
||||
|
||||
def build_conversation
|
||||
@contact_inbox ||= contact.contact_inboxes.find_by!(source_id: message_source_id)
|
||||
Conversation.create!(conversation_params.merge(
|
||||
contact_inbox_id: @contact_inbox.id
|
||||
))
|
||||
end
|
||||
|
||||
def conversation_params
|
||||
{
|
||||
account_id: @inbox.account_id,
|
||||
inbox_id: @inbox.id,
|
||||
contact_id: contact.id,
|
||||
additional_attributes: {
|
||||
type: 'instagram_direct_message'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def message_params
|
||||
{
|
||||
account_id: conversation.account_id,
|
||||
inbox_id: conversation.inbox_id,
|
||||
message_type: message_type,
|
||||
source_id: message_source_id,
|
||||
content: message_content,
|
||||
content_attributes: content_attributes,
|
||||
sender: @outgoing_echo ? nil : contact
|
||||
}
|
||||
end
|
||||
|
||||
def already_sent_from_chatwoot?
|
||||
cw_message = conversation.messages.where(
|
||||
source_id: nil,
|
||||
message_type: 'outgoing',
|
||||
content: message_content,
|
||||
private: false,
|
||||
status: :sent
|
||||
).first
|
||||
cw_message.update(content_attributes: content_attributes) if cw_message.present?
|
||||
cw_message.present?
|
||||
end
|
||||
|
||||
### Sample response
|
||||
# {
|
||||
# "object": "instagram",
|
||||
# "entry": [
|
||||
# {
|
||||
# "id": "<IGID>",// ig id of the business
|
||||
# "time": 1569262486134,
|
||||
# "messaging": [
|
||||
# {
|
||||
# "sender": {
|
||||
# "id": "<IGSID>"
|
||||
# },
|
||||
# "recipient": {
|
||||
# "id": "<IGID>"
|
||||
# },
|
||||
# "timestamp": 1569262485349,
|
||||
# "message": {
|
||||
# "mid": "<MESSAGE_ID>",
|
||||
# "text": "<MESSAGE_CONTENT>"
|
||||
# }
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# ],
|
||||
# }
|
||||
end
|
||||
42
app/builders/messages/messenger/message_builder.rb
Normal file
42
app/builders/messages/messenger/message_builder.rb
Normal file
@@ -0,0 +1,42 @@
|
||||
class Messages::Messenger::MessageBuilder
|
||||
def process_attachment(attachment)
|
||||
return if attachment['type'].to_sym == :template
|
||||
|
||||
attachment_obj = @message.attachments.new(attachment_params(attachment).except(:remote_file_url))
|
||||
attachment_obj.save!
|
||||
attach_file(attachment_obj, attachment_params(attachment)[:remote_file_url]) if attachment_params(attachment)[:remote_file_url]
|
||||
end
|
||||
|
||||
def attach_file(attachment, file_url)
|
||||
attachment_file = Down.download(
|
||||
file_url
|
||||
)
|
||||
attachment.file.attach(
|
||||
io: attachment_file,
|
||||
filename: attachment_file.original_filename,
|
||||
content_type: attachment_file.content_type
|
||||
)
|
||||
end
|
||||
|
||||
def attachment_params(attachment)
|
||||
file_type = attachment['type'].to_sym
|
||||
params = { file_type: file_type, account_id: @message.account_id }
|
||||
|
||||
if [:image, :file, :audio, :video].include? file_type
|
||||
params.merge!(file_type_params(attachment))
|
||||
elsif file_type == :location
|
||||
params.merge!(location_params(attachment))
|
||||
elsif file_type == :fallback
|
||||
params.merge!(fallback_params(attachment))
|
||||
end
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def file_type_params(attachment)
|
||||
{
|
||||
external_url: attachment['payload']['url'],
|
||||
remote_file_url: attachment['payload']['url']
|
||||
}
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user