feat: Add native support for CSML in agent_bot API (#4913)
This commit is contained in:
@@ -30,6 +30,6 @@ class Api::V1::Accounts::AgentBotsController < Api::V1::Accounts::BaseController
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
params.permit(:name, :description, :outgoing_url)
|
||||
params.permit(:name, :description, :outgoing_url, :bot_type, bot_config: [:csml_content])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<image-bubble
|
||||
v-if="attachment.file_type === 'image' && !hasImageError"
|
||||
:url="attachment.data_url"
|
||||
:thumb="attachment.thumb_url"
|
||||
:thumb="attachment.data_url"
|
||||
:readable-time="readableTime"
|
||||
@error="onImageLoadError"
|
||||
/>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<image-bubble
|
||||
v-if="attachment.file_type === 'image' && !hasImageError"
|
||||
:url="attachment.data_url"
|
||||
:thumb="attachment.thumb_url"
|
||||
:thumb="attachment.data_url"
|
||||
:readable-time="readableTime"
|
||||
@error="onImageLoadError"
|
||||
/>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
class AgentBotJob < WebhookJob
|
||||
queue_as :bots
|
||||
end
|
||||
10
app/jobs/agent_bots/csml_job.rb
Normal file
10
app/jobs/agent_bots/csml_job.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
class AgentBots::CsmlJob < ApplicationJob
|
||||
queue_as :bots
|
||||
|
||||
def perform(event, agent_bot, message)
|
||||
event_data = { message: message }
|
||||
Integrations::Csml::ProcessorService.new(
|
||||
event_name: event, agent_bot: agent_bot, event_data: event_data
|
||||
).perform
|
||||
end
|
||||
end
|
||||
3
app/jobs/agent_bots/webhook_job.rb
Normal file
3
app/jobs/agent_bots/webhook_job.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
class AgentBots::WebhookJob < WebhookJob
|
||||
queue_as :bots
|
||||
end
|
||||
@@ -2,61 +2,80 @@ class AgentBotListener < BaseListener
|
||||
def conversation_resolved(event)
|
||||
conversation = extract_conversation_and_account(event)[0]
|
||||
inbox = conversation.inbox
|
||||
return if inbox.agent_bot_inbox.blank?
|
||||
return unless inbox.agent_bot_inbox.active?
|
||||
return unless connected_agent_bot_exist?(inbox)
|
||||
|
||||
agent_bot = inbox.agent_bot_inbox.agent_bot
|
||||
|
||||
payload = conversation.webhook_data.merge(event: __method__.to_s)
|
||||
AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
|
||||
event_name = __method__.to_s
|
||||
payload = conversation.webhook_data.merge(event: event_name)
|
||||
process_webhook_bot_event(inbox.agent_bot, payload)
|
||||
end
|
||||
|
||||
def conversation_opened(event)
|
||||
conversation = extract_conversation_and_account(event)[0]
|
||||
inbox = conversation.inbox
|
||||
return if inbox.agent_bot_inbox.blank?
|
||||
return unless inbox.agent_bot_inbox.active?
|
||||
return unless connected_agent_bot_exist?(inbox)
|
||||
|
||||
agent_bot = inbox.agent_bot_inbox.agent_bot
|
||||
|
||||
payload = conversation.webhook_data.merge(event: __method__.to_s)
|
||||
AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
|
||||
event_name = __method__.to_s
|
||||
payload = conversation.webhook_data.merge(event: event_name)
|
||||
process_webhook_bot_event(inbox.agent_bot, payload)
|
||||
end
|
||||
|
||||
def message_created(event)
|
||||
message = extract_message_and_account(event)[0]
|
||||
inbox = message.inbox
|
||||
return unless message.webhook_sendable? && inbox.agent_bot_inbox.present?
|
||||
return unless inbox.agent_bot_inbox.active?
|
||||
return unless connected_agent_bot_exist?(inbox)
|
||||
return unless message.webhook_sendable?
|
||||
|
||||
agent_bot = inbox.agent_bot_inbox.agent_bot
|
||||
|
||||
payload = message.webhook_data.merge(event: __method__.to_s)
|
||||
AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
|
||||
method_name = __method__.to_s
|
||||
process_message_event(method_name, inbox.agent_bot, message, event)
|
||||
end
|
||||
|
||||
def message_updated(event)
|
||||
message = extract_message_and_account(event)[0]
|
||||
inbox = message.inbox
|
||||
return unless message.webhook_sendable? && inbox.agent_bot_inbox.present?
|
||||
return unless inbox.agent_bot_inbox.active?
|
||||
return unless connected_agent_bot_exist?(inbox)
|
||||
return unless message.webhook_sendable?
|
||||
|
||||
agent_bot = inbox.agent_bot_inbox.agent_bot
|
||||
|
||||
payload = message.webhook_data.merge(event: __method__.to_s)
|
||||
AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
|
||||
method_name = __method__.to_s
|
||||
process_message_event(method_name, inbox.agent_bot, message, event)
|
||||
end
|
||||
|
||||
def webwidget_triggered(event)
|
||||
contact_inbox = event.data[:contact_inbox]
|
||||
inbox = contact_inbox.inbox
|
||||
return unless connected_agent_bot_exist?(inbox)
|
||||
|
||||
event_name = __method__.to_s
|
||||
payload = contact_inbox.webhook_data.merge(event: event_name)
|
||||
payload[:event_info] = event.data[:event_info]
|
||||
process_webhook_bot_event(inbox.agent_bot, payload)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def connected_agent_bot_exist?(inbox)
|
||||
return if inbox.agent_bot_inbox.blank?
|
||||
return unless inbox.agent_bot_inbox.active?
|
||||
|
||||
agent_bot = inbox.agent_bot_inbox.agent_bot
|
||||
true
|
||||
end
|
||||
|
||||
payload = contact_inbox.webhook_data.merge(event: __method__.to_s)
|
||||
payload[:event_info] = event.data[:event_info]
|
||||
AgentBotJob.perform_later(agent_bot.outgoing_url, payload)
|
||||
def process_message_event(method_name, agent_bot, message, event)
|
||||
case agent_bot.bot_type
|
||||
when 'webhook'
|
||||
payload = message.webhook_data.merge(event: method_name)
|
||||
process_webhook_bot_event(agent_bot, payload)
|
||||
when 'csml'
|
||||
process_csml_bot_event(event.name, agent_bot, message)
|
||||
end
|
||||
end
|
||||
|
||||
def process_webhook_bot_event(agent_bot, payload)
|
||||
return if agent_bot.outgoing_url.blank?
|
||||
|
||||
AgentBots::WebhookJob.perform_later(agent_bot.outgoing_url, payload)
|
||||
end
|
||||
|
||||
def process_csml_bot_event(event, agent_bot, message)
|
||||
AgentBots::CsmlJob.perform_later(event, agent_bot, message)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# Table name: agent_bots
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# bot_config :jsonb
|
||||
# bot_type :integer default(0)
|
||||
# description :string
|
||||
# name :string
|
||||
# outgoing_url :string
|
||||
@@ -27,6 +29,9 @@ class AgentBot < ApplicationRecord
|
||||
has_many :inboxes, through: :agent_bot_inboxes
|
||||
has_many :messages, as: :sender, dependent: :restrict_with_exception
|
||||
belongs_to :account, optional: true
|
||||
enum bot_type: { webhook: 0, csml: 1 }
|
||||
|
||||
validate :validate_agent_bot_config
|
||||
|
||||
def available_name
|
||||
name
|
||||
@@ -48,4 +53,10 @@ class AgentBot < ApplicationRecord
|
||||
type: 'agent_bot'
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_agent_bot_config
|
||||
errors.add(:bot_config, 'Invalid Bot Configuration') unless AgentBots::ValidateBotService.new(agent_bot: self).perform
|
||||
end
|
||||
end
|
||||
|
||||
38
app/services/agent_bots/validate_bot_service.rb
Normal file
38
app/services/agent_bots/validate_bot_service.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
class AgentBots::ValidateBotService
|
||||
pattr_initialize [:agent_bot]
|
||||
def perform
|
||||
return true unless agent_bot.bot_type == 'csml'
|
||||
|
||||
validate_csml_bot
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def csml_client
|
||||
@csml_client ||= CsmlEngine.new
|
||||
end
|
||||
|
||||
def csml_bot_payload
|
||||
{
|
||||
id: agent_bot[:name],
|
||||
name: agent_bot[:name],
|
||||
default_flow: 'Default',
|
||||
flows: [
|
||||
{
|
||||
id: SecureRandom.uuid,
|
||||
name: 'Default',
|
||||
content: agent_bot.bot_config['csml_content'],
|
||||
commands: []
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
def validate_csml_bot
|
||||
response = csml_client.validate(csml_bot_payload)
|
||||
response.blank? || response['valid']
|
||||
rescue StandardError => e
|
||||
ChatwootExceptionTracker.new(e, account: agent_bot).capture_exception
|
||||
false
|
||||
end
|
||||
end
|
||||
@@ -2,5 +2,7 @@ json.id resource.id
|
||||
json.name resource.name
|
||||
json.description resource.description
|
||||
json.outgoing_url resource.outgoing_url
|
||||
json.bot_type resource.bot_type
|
||||
json.bot_config resource.bot_config
|
||||
json.account_id resource.account_id
|
||||
json.access_token resource.access_token if resource.access_token.present?
|
||||
|
||||
Reference in New Issue
Block a user