121 lines
3.1 KiB
Ruby
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
|