chatwoot-develop/enterprise/app/services/captain/reminders/processor.rb
2026-01-12 19:04:39 -03:00

121 lines
3.1 KiB
Ruby

class Captain::Reminders::Processor
def initialize(reminder)
@reminder = reminder
end
def perform
return if @reminder.sent? || @reminder.cancelled?
if @reminder.suite_watchdog?
process_suite_watchdog
else
deliver_message(@reminder.message)
mark_sent
end
rescue StandardError => e
mark_failed(e.message)
end
private
def process_suite_watchdog
return reschedule('Missing suite identifier') if @reminder.suite_identifier.blank?
available = suite_available?
if available
deliver_message(@reminder.message.presence || default_suite_message)
mark_sent
else
reschedule('Suite still occupied')
end
end
def suite_available?
assistant = inbox.captain_assistant
return false unless assistant.present?
tool = Captain::Tools::StatusSuitesTool.new(assistant, conversation: conversation)
result = tool.execute
parsed = begin
JSON.parse(result)
rescue StandardError
{}
end
free_suites = parsed['free'] || []
free_suites.any? { |suite| suite['suite'].to_s == @reminder.suite_identifier.to_s }
end
def deliver_message(content)
raise ArgumentError, 'Message content is required' if content.blank?
target_conversation = conversation || find_or_create_conversation
raise ArgumentError, 'Conversation not found' unless target_conversation.present?
raise ArgumentError, 'Assistant not configured for inbox' unless assistant.present?
Current.executed_by = assistant
Current.account = @reminder.account
processed_content = Captain::MediaInterpolationService.new(account: @reminder.account).interpolate(content)
target_conversation.messages.create!(
message_type: :outgoing,
account_id: @reminder.account_id,
inbox_id: @reminder.inbox_id,
sender: assistant,
content: processed_content
)
end
def find_or_create_conversation
existing = @reminder.contact_inbox.conversations
.where(inbox_id: @reminder.inbox_id)
.where.not(status: :resolved)
.order(created_at: :desc)
.first
return existing if existing.present?
Conversation.create!(
account_id: @reminder.account_id,
inbox_id: @reminder.inbox_id,
contact_id: @reminder.contact_id,
contact_inbox_id: @reminder.contact_inbox_id
)
end
def mark_sent
@reminder.update!(status: :sent, sent_at: Time.current)
end
def mark_failed(message)
@reminder.update!(
status: :failed,
error_message: message,
attempt_count: @reminder.attempt_count + 1
)
end
def reschedule(reason)
@reminder.update!(
scheduled_at: Time.current + @reminder.interval_minutes.to_i.minutes,
attempt_count: @reminder.attempt_count + 1,
error_message: reason
)
end
def default_suite_message
I18n.t('captain.reminders.defaults.suite_available', suite: @reminder.suite_identifier)
end
def conversation
@conversation ||= @reminder.conversation
end
def inbox
@inbox ||= @reminder.inbox
end
def assistant
@assistant ||= inbox.captain_assistant
end
end