Restructure omni services and add Chatwoot research snapshot

This commit is contained in:
Ruslan Bakiev
2026-02-21 11:11:27 +07:00
parent edea7a0034
commit b73babbbf6
7732 changed files with 978203 additions and 32 deletions

View File

@@ -0,0 +1,37 @@
# frozen_string_literal: true
class Integrations::Facebook::DeliveryStatus
pattr_initialize [:params!]
def perform
return if facebook_channel.blank?
return unless conversation
process_delivery_status if params.delivery_watermark
process_read_status if params.read_watermark
end
private
def process_delivery_status
timestamp = Time.zone.at(params.delivery_watermark.to_i).to_datetime.utc
::Conversations::UpdateMessageStatusJob.perform_later(conversation.id, timestamp, :delivered)
end
def process_read_status
timestamp = Time.zone.at(params.read_watermark.to_i).to_datetime.utc
::Conversations::UpdateMessageStatusJob.perform_later(conversation.id, timestamp, :read)
end
def contact
::ContactInbox.find_by(source_id: params.sender_id)&.contact
end
def conversation
@conversation ||= ::Conversation.find_by(contact_id: contact.id) if contact.present?
end
def facebook_channel
@facebook_channel ||= Channel::FacebookPage.find_by(page_id: params.recipient_id)
end
end

View File

@@ -0,0 +1,44 @@
# frozen_string_literal: true
class Integrations::Facebook::MessageCreator
attr_reader :response
def initialize(response)
@response = response
end
def perform
# begin
if agent_message_via_echo?
create_agent_message
else
create_contact_message
end
# rescue => e
# ChatwootExceptionTracker.new(e).capture_exception
# end
end
private
def agent_message_via_echo?
# TODO : check and remove send_from_chatwoot_app if not working
response.echo? && !response.sent_from_chatwoot_app?
# this means that it is an agent message from page, but not sent from chatwoot.
# User can send from fb page directly on mobile / web messenger, so this case should be handled as agent message
end
def create_agent_message
Channel::FacebookPage.where(page_id: response.sender_id).each do |page|
mb = Messages::Facebook::MessageBuilder.new(response, page.inbox, outgoing_echo: true)
mb.perform
end
end
def create_contact_message
Channel::FacebookPage.where(page_id: response.recipient_id).each do |page|
mb = Messages::Facebook::MessageBuilder.new(response, page.inbox)
mb.perform
end
end
end

View File

@@ -0,0 +1,89 @@
# frozen_string_literal: true
class Integrations::Facebook::MessageParser
def initialize(response_json)
@response = JSON.parse(response_json)
@messaging = @response['messaging'] || @response['standby']
end
def sender_id
@messaging.dig('sender', 'id')
end
def recipient_id
@messaging.dig('recipient', 'id')
end
def time_stamp
@messaging['timestamp']
end
def content
@messaging.dig('message', 'text')
end
def sequence
@messaging.dig('message', 'seq')
end
def attachments
@messaging.dig('message', 'attachments')
end
def identifier
@messaging.dig('message', 'mid')
end
def delivery
@messaging['delivery']
end
def read
@messaging['read']
end
def read_watermark
read&.dig('watermark')
end
def delivery_watermark
delivery&.dig('watermark')
end
def echo?
@messaging.dig('message', 'is_echo')
end
# TODO : i don't think the payload contains app_id. if not remove
def app_id
@messaging.dig('message', 'app_id')
end
# TODO : does this work ?
def sent_from_chatwoot_app?
app_id && app_id == GlobalConfigService.load('FB_APP_ID', '').to_i
end
def in_reply_to_external_id
@messaging.dig('message', 'reply_to', 'mid')
end
end
# Sample Response
# {
# "sender":{
# "id":"USER_ID"
# },
# "recipient":{
# "id":"PAGE_ID"
# },
# "timestamp":1458692752478,
# "message":{
# "mid":"mid.1457764197618:41d102a3e1ae206a38",
# "seq":73,
# "text":"hello, world!",
# "quick_reply": {
# "payload": "DEVELOPER_DEFINED_PAYLOAD"
# }
# }
# }