feat: Add native support for CSML in agent_bot API (#4913)

This commit is contained in:
Pranav Raj S
2022-06-23 19:17:46 +05:30
committed by GitHub
parent f71980bd95
commit b7606e4dd2
26 changed files with 722 additions and 80 deletions

View File

@@ -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

View File

@@ -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"
/>

View File

@@ -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"
/>

View File

@@ -1,3 +0,0 @@
class AgentBotJob < WebhookJob
queue_as :bots
end

View 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

View File

@@ -0,0 +1,3 @@
class AgentBots::WebhookJob < WebhookJob
queue_as :bots
end

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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?