87 lines
2.6 KiB
Ruby
Executable File
87 lines
2.6 KiB
Ruby
Executable File
module Whatsapp::BaileysHandlers::MessagesUpdate
|
|
include Whatsapp::BaileysHandlers::Helpers
|
|
|
|
class MessageNotFoundError < StandardError; end
|
|
|
|
private
|
|
|
|
def process_messages_update
|
|
updates = processed_params[:data]
|
|
updates.each do |update|
|
|
@message = nil
|
|
@raw_message = update
|
|
|
|
next handle_update if incoming?
|
|
|
|
# NOTE: Shared lock with Whatsapp::SendOnWhatsappService
|
|
# Avoids race conditions when sending messages.
|
|
with_baileys_channel_lock_on_outgoing_message(inbox.channel.id) { handle_update }
|
|
end
|
|
end
|
|
|
|
def handle_update
|
|
raise MessageNotFoundError unless find_message_by_source_id(raw_message_id)
|
|
|
|
update_status if @raw_message.dig(:update, :status).present?
|
|
handle_edited_content if @raw_message.dig(:update, :message).present?
|
|
end
|
|
|
|
def update_status
|
|
status = status_mapper
|
|
update_last_seen_at if incoming? && status == 'read'
|
|
@message.update!(status: status) if status.present? && status_transition_allowed?(status)
|
|
end
|
|
|
|
def status_mapper
|
|
# NOTE: Baileys status codes vs. Chatwoot support:
|
|
# - (0) ERROR → (3) failed
|
|
# - (1) PENDING → (0) sent
|
|
# - (2) SERVER_ACK → (0) sent
|
|
# - (3) DELIVERY_ACK → (1) delivered
|
|
# - (4) READ → (2) read
|
|
# - (5) PLAYED → (unsupported: PLAYED)
|
|
# For details: https://github.com/WhiskeySockets/Baileys/blob/v6.7.16/WAProto/index.d.ts#L36694
|
|
status = @raw_message.dig(:update, :status)
|
|
case status
|
|
when 0
|
|
'failed'
|
|
when 1, 2
|
|
'sent'
|
|
when 3
|
|
'delivered'
|
|
when 4
|
|
'read'
|
|
when 5
|
|
Rails.logger.warn 'Baileys unsupported message update status: PLAYED(5)'
|
|
nil
|
|
else
|
|
Rails.logger.warn "Baileys unsupported message update status: #{status}"
|
|
nil
|
|
end
|
|
end
|
|
|
|
def update_last_seen_at
|
|
conversation = @message.conversation
|
|
to_update = { agent_last_seen_at: Time.current }
|
|
to_update[:assignee_last_seen_at] = Time.current if conversation.assignee_id.present?
|
|
|
|
conversation.update_columns(to_update) # rubocop:disable Rails/SkipsModelValidations
|
|
end
|
|
|
|
def status_transition_allowed?(new_status)
|
|
return false if @message.status == 'read'
|
|
return false if @message.status == 'delivered' && new_status == 'sent'
|
|
|
|
true
|
|
end
|
|
|
|
def handle_edited_content
|
|
@raw_message = @raw_message.dig(:update, :message, :editedMessage)
|
|
content = message_content
|
|
|
|
return @message.update!(content: content, is_edited: true, previous_content: @message.content) if content
|
|
|
|
Rails.logger.warn 'No valid message content found in the edit event'
|
|
end
|
|
end
|