67 lines
1.8 KiB
Ruby
67 lines
1.8 KiB
Ruby
class Voice::CallStatus::Manager
|
|
pattr_initialize [:conversation!, :call_sid]
|
|
|
|
ALLOWED_STATUSES = %w[ringing in-progress completed no-answer failed].freeze
|
|
TERMINAL_STATUSES = %w[completed no-answer failed].freeze
|
|
|
|
def process_status_update(status, duration: nil, timestamp: nil)
|
|
return unless ALLOWED_STATUSES.include?(status)
|
|
|
|
current_status = conversation.additional_attributes&.dig('call_status')
|
|
return if current_status == status
|
|
|
|
apply_status(status, duration: duration, timestamp: timestamp)
|
|
update_message(status)
|
|
end
|
|
|
|
private
|
|
|
|
def apply_status(status, duration:, timestamp:)
|
|
attrs = (conversation.additional_attributes || {}).dup
|
|
attrs['call_status'] = status
|
|
|
|
if status == 'in-progress'
|
|
attrs['call_started_at'] ||= timestamp || now_seconds
|
|
elsif TERMINAL_STATUSES.include?(status)
|
|
attrs['call_ended_at'] = timestamp || now_seconds
|
|
attrs['call_duration'] = resolved_duration(attrs, duration, timestamp)
|
|
end
|
|
|
|
conversation.update!(
|
|
additional_attributes: attrs,
|
|
last_activity_at: current_time
|
|
)
|
|
end
|
|
|
|
def resolved_duration(attrs, provided_duration, timestamp)
|
|
return provided_duration if provided_duration
|
|
|
|
started_at = attrs['call_started_at']
|
|
return unless started_at && timestamp
|
|
|
|
[timestamp - started_at.to_i, 0].max
|
|
end
|
|
|
|
def update_message(status)
|
|
message = conversation.messages
|
|
.where(content_type: 'voice_call')
|
|
.order(created_at: :desc)
|
|
.first
|
|
return unless message
|
|
|
|
data = (message.content_attributes || {}).dup
|
|
data['data'] ||= {}
|
|
data['data']['status'] = status
|
|
|
|
message.update!(content_attributes: data)
|
|
end
|
|
|
|
def now_seconds
|
|
current_time.to_i
|
|
end
|
|
|
|
def current_time
|
|
@current_time ||= Time.zone.now
|
|
end
|
|
end
|