136 lines
4.1 KiB
Ruby
136 lines
4.1 KiB
Ruby
require 'net/http'
|
|
require 'uri'
|
|
|
|
module Captain
|
|
module Tools
|
|
class ToolRunner
|
|
def self.run(assistant:, tool_key:, inbox:, conversation:, additional_data: {})
|
|
new(assistant, tool_key, inbox, conversation, additional_data).run
|
|
end
|
|
|
|
def initialize(assistant, tool_key, inbox, conversation, additional_data)
|
|
@assistant = assistant
|
|
@tool_key = tool_key
|
|
@inbox = inbox
|
|
@conversation = conversation
|
|
@definition = Captain::Tools::Definitions::ALL[tool_key]
|
|
@config = Captain::ToolConfig.find_by(captain_assistant_id: assistant.id, tool_key: tool_key) ||
|
|
Captain::ToolConfig.find_by(inbox: inbox, account: inbox.account, tool_key: tool_key)
|
|
@contact = conversation.contact
|
|
@additional_data = additional_data
|
|
end
|
|
|
|
def run
|
|
return failed_response('Tool not configured or disabled') unless @config&.is_enabled
|
|
return failed_response('Tool definition not found') unless @definition
|
|
|
|
start_time = Time.current
|
|
result = case @definition[:type]
|
|
when :http then execute_http
|
|
when :webhook then execute_webhook
|
|
else failed_response('Unknown tool type')
|
|
end
|
|
|
|
duration = (Time.current - start_time) * 1000
|
|
result.merge(duration_ms: duration)
|
|
end
|
|
|
|
private
|
|
|
|
def execute_http
|
|
uri = URI(@definition[:url])
|
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
http.use_ssl = uri.scheme == 'https'
|
|
http.read_timeout = 8
|
|
|
|
request = Net::HTTP::Get.new(uri)
|
|
request['PLUG-PLAY-ID'] = @config.plug_play_id
|
|
request['PLUG-PLAY-TOKEN'] = @config.plug_play_token
|
|
|
|
response = http.request(request)
|
|
|
|
if response.is_a?(Net::HTTPSuccess)
|
|
parsed_body = parse_response(response.body)
|
|
{ success: true, body: parsed_body, status: response.code }
|
|
else
|
|
{ success: false, status: response.code, error: 'HTTP Request Failed' }
|
|
end
|
|
rescue StandardError => e
|
|
{ success: false, error: e.message }
|
|
end
|
|
|
|
def execute_webhook
|
|
url = @config.webhook_url
|
|
return failed_response('Webhook URL missing') if url.blank?
|
|
|
|
payload = build_webhook_payload
|
|
|
|
# Specific logic for escalate_human
|
|
if @tool_key == 'escalar_humano'
|
|
# Label logic handles in brain/response service if success
|
|
end
|
|
|
|
response = RestClient::Request.execute(
|
|
method: :post,
|
|
url: url,
|
|
payload: payload.to_json,
|
|
headers: { content_type: :json, accept: :json },
|
|
timeout: 8
|
|
)
|
|
|
|
{ success: true, status: response.code, body: { message: 'Webhook sent' } }
|
|
rescue StandardError => e
|
|
{ success: false, error: e.message }
|
|
end
|
|
|
|
def build_webhook_payload
|
|
base = {
|
|
conversation_id: @conversation.id,
|
|
contact_id: @contact.id,
|
|
event: @tool_key
|
|
}
|
|
|
|
# Specific payloads
|
|
if @tool_key == 'maria_fotos'
|
|
base.merge!(
|
|
suite_category: extract_suite_category || 'Indefinida',
|
|
message: 'User requested photos'
|
|
)
|
|
elsif @tool_key == 'escalar_humano'
|
|
base.merge!(reason: 'User requested human agent')
|
|
end
|
|
|
|
base
|
|
end
|
|
|
|
def extract_suite_category
|
|
# Simple extraction or ask JasmineBrain to help later?
|
|
# For V1, we try to grab from message content or nil
|
|
msg = @additional_data[:message]&.downcase || ''
|
|
return 'Alexa' if msg.include?('alexa')
|
|
return 'Stilo' if msg.include?('stilo')
|
|
return 'Hidromassagem' if msg.include?('hidro')
|
|
|
|
nil
|
|
end
|
|
|
|
def parse_response(body)
|
|
case @tool_key
|
|
when 'status_suites'
|
|
Captain::Tools::Parsers::StatusSuitesParser.parse(body)
|
|
else
|
|
begin
|
|
JSON.parse(body)
|
|
rescue StandardError
|
|
body
|
|
end
|
|
end
|
|
end
|
|
|
|
def failed_response(msg)
|
|
{ success: false, error: msg }
|
|
end
|
|
end
|
|
end
|
|
end
|