xip 0.0.1 → 2.0.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +116 -0
- data/.gitignore +12 -0
- data/CHANGELOG.md +135 -0
- data/Gemfile +4 -1
- data/Gemfile.lock +65 -15
- data/LICENSE +6 -4
- data/README.md +51 -1
- data/VERSION +1 -0
- data/bin/xip +3 -11
- data/lib/xip.rb +1 -3
- data/lib/xip/base.rb +189 -0
- data/lib/xip/cli.rb +273 -0
- data/lib/xip/cli_base.rb +24 -0
- data/lib/xip/commands/command.rb +13 -0
- data/lib/xip/commands/console.rb +74 -0
- data/lib/xip/commands/server.rb +63 -0
- data/lib/xip/configuration.rb +56 -0
- data/lib/xip/controller/callbacks.rb +63 -0
- data/lib/xip/controller/catch_all.rb +84 -0
- data/lib/xip/controller/controller.rb +274 -0
- data/lib/xip/controller/dev_jumps.rb +40 -0
- data/lib/xip/controller/dynamic_delay.rb +61 -0
- data/lib/xip/controller/helpers.rb +128 -0
- data/lib/xip/controller/interrupt_detect.rb +99 -0
- data/lib/xip/controller/messages.rb +283 -0
- data/lib/xip/controller/nlp.rb +49 -0
- data/lib/xip/controller/replies.rb +281 -0
- data/lib/xip/controller/unrecognized_message.rb +61 -0
- data/lib/xip/core_ext.rb +5 -0
- data/lib/xip/core_ext/numeric.rb +10 -0
- data/lib/xip/core_ext/string.rb +18 -0
- data/lib/xip/dispatcher.rb +68 -0
- data/lib/xip/errors.rb +55 -0
- data/lib/xip/flow/base.rb +69 -0
- data/lib/xip/flow/specification.rb +56 -0
- data/lib/xip/flow/state.rb +82 -0
- data/lib/xip/generators/builder.rb +41 -0
- data/lib/xip/generators/builder/.gitignore +30 -0
- data/lib/xip/generators/builder/Gemfile +19 -0
- data/lib/xip/generators/builder/Procfile.dev +2 -0
- data/lib/xip/generators/builder/README.md +9 -0
- data/lib/xip/generators/builder/Rakefile +2 -0
- data/lib/xip/generators/builder/bot/controllers/bot_controller.rb +55 -0
- data/lib/xip/generators/builder/bot/controllers/catch_alls_controller.rb +21 -0
- data/lib/xip/generators/builder/bot/controllers/concerns/.keep +0 -0
- data/lib/xip/generators/builder/bot/controllers/goodbyes_controller.rb +9 -0
- data/lib/xip/generators/builder/bot/controllers/hellos_controller.rb +9 -0
- data/lib/xip/generators/builder/bot/controllers/interrupts_controller.rb +9 -0
- data/lib/xip/generators/builder/bot/controllers/unrecognized_messages_controller.rb +9 -0
- data/lib/xip/generators/builder/bot/helpers/bot_helper.rb +2 -0
- data/lib/xip/generators/builder/bot/models/bot_record.rb +3 -0
- data/lib/xip/generators/builder/bot/models/concerns/.keep +0 -0
- data/lib/xip/generators/builder/bot/replies/catch_alls/level1.yml +2 -0
- data/lib/xip/generators/builder/bot/replies/goodbyes/say_goodbye.yml +2 -0
- data/lib/xip/generators/builder/bot/replies/hellos/say_hello.yml +2 -0
- data/lib/xip/generators/builder/config.ru +4 -0
- data/lib/xip/generators/builder/config/boot.rb +6 -0
- data/lib/xip/generators/builder/config/database.yml +25 -0
- data/lib/xip/generators/builder/config/environment.rb +2 -0
- data/lib/xip/generators/builder/config/flow_map.rb +25 -0
- data/lib/xip/generators/builder/config/initializers/autoload.rb +8 -0
- data/lib/xip/generators/builder/config/initializers/inflections.rb +16 -0
- data/lib/xip/generators/builder/config/puma.rb +25 -0
- data/lib/xip/generators/builder/config/services.yml +35 -0
- data/lib/xip/generators/builder/config/sidekiq.yml +3 -0
- data/lib/xip/generators/builder/db/seeds.rb +7 -0
- data/lib/xip/generators/generate.rb +39 -0
- data/lib/xip/generators/generate/flow/controllers/controller.tt +7 -0
- data/lib/xip/generators/generate/flow/helpers/helper.tt +3 -0
- data/lib/xip/generators/generate/flow/replies/ask_example.tt +9 -0
- data/lib/xip/helpers/redis.rb +40 -0
- data/lib/xip/jobs.rb +9 -0
- data/lib/xip/lock.rb +82 -0
- data/lib/xip/logger.rb +9 -3
- data/lib/xip/migrations/configurator.rb +73 -0
- data/lib/xip/migrations/generators.rb +16 -0
- data/lib/xip/migrations/railtie_config.rb +14 -0
- data/lib/xip/migrations/tasks.rb +43 -0
- data/lib/xip/nlp/client.rb +21 -0
- data/lib/xip/nlp/result.rb +56 -0
- data/lib/xip/reloader.rb +89 -0
- data/lib/xip/reply.rb +36 -0
- data/lib/xip/scheduled_reply.rb +18 -0
- data/lib/xip/server.rb +63 -0
- data/lib/xip/service_message.rb +17 -0
- data/lib/xip/service_reply.rb +44 -0
- data/lib/xip/services/base_client.rb +24 -0
- data/lib/xip/services/base_message_handler.rb +27 -0
- data/lib/xip/services/base_reply_handler.rb +72 -0
- data/lib/xip/services/jobs/handle_message_job.rb +21 -0
- data/lib/xip/session.rb +203 -0
- data/lib/xip/version.rb +7 -1
- data/logo.svg +17 -0
- data/spec/configuration_spec.rb +93 -0
- data/spec/controller/callbacks_spec.rb +217 -0
- data/spec/controller/catch_all_spec.rb +154 -0
- data/spec/controller/controller_spec.rb +889 -0
- data/spec/controller/dynamic_delay_spec.rb +70 -0
- data/spec/controller/helpers_spec.rb +119 -0
- data/spec/controller/interrupt_detect_spec.rb +171 -0
- data/spec/controller/messages_spec.rb +744 -0
- data/spec/controller/nlp_spec.rb +93 -0
- data/spec/controller/replies_spec.rb +694 -0
- data/spec/controller/unrecognized_message_spec.rb +168 -0
- data/spec/dispatcher_spec.rb +79 -0
- data/spec/flow/flow_spec.rb +82 -0
- data/spec/flow/state_spec.rb +109 -0
- data/spec/helpers/redis_spec.rb +77 -0
- data/spec/lock_spec.rb +100 -0
- data/spec/nlp/client_spec.rb +23 -0
- data/spec/nlp/result_spec.rb +57 -0
- data/spec/replies/hello.yml.erb +15 -0
- data/spec/replies/messages/say_hola.yml+facebook.erb +6 -0
- data/spec/replies/messages/say_hola.yml+twilio.erb +6 -0
- data/spec/replies/messages/say_hola.yml.erb +6 -0
- data/spec/replies/messages/say_howdy_with_dynamic.yml +79 -0
- data/spec/replies/messages/say_msgs_without_breaks.yml +4 -0
- data/spec/replies/messages/say_offer.yml +6 -0
- data/spec/replies/messages/say_offer_with_dynamic.yml +6 -0
- data/spec/replies/messages/say_oi.yml.erb +15 -0
- data/spec/replies/messages/say_randomize_speech.yml +10 -0
- data/spec/replies/messages/say_randomize_text.yml +10 -0
- data/spec/replies/messages/say_yo.yml +6 -0
- data/spec/replies/messages/say_yo.yml+twitter +6 -0
- data/spec/replies/messages/sub1/sub2/say_nested.yml +10 -0
- data/spec/reply_spec.rb +61 -0
- data/spec/scheduled_reply_spec.rb +23 -0
- data/spec/service_reply_spec.rb +92 -0
- data/spec/session_spec.rb +366 -0
- data/spec/spec_helper.rb +22 -66
- data/spec/support/alternate_helpers/foo_helper.rb +5 -0
- data/spec/support/controllers/vaders_controller.rb +24 -0
- data/spec/support/helpers/fun/games_helper.rb +7 -0
- data/spec/support/helpers/fun/pdf_helper.rb +7 -0
- data/spec/support/helpers/standalone_helper.rb +5 -0
- data/spec/support/helpers_typo/users_helper.rb +2 -0
- data/spec/support/nlp_clients/dialogflow.rb +9 -0
- data/spec/support/nlp_clients/luis.rb +9 -0
- data/spec/support/nlp_results/luis_result.rb +163 -0
- data/spec/support/sample_messages.rb +66 -0
- data/spec/support/services.yml +31 -0
- data/spec/support/services_with_erb.yml +31 -0
- data/spec/version_spec.rb +16 -0
- data/xip.gemspec +25 -14
- metadata +320 -18
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SQLite version 3.x
|
|
2
|
+
# gem install sqlite3
|
|
3
|
+
#
|
|
4
|
+
# Ensure the SQLite 3 gem is defined in your Gemfile
|
|
5
|
+
# gem 'sqlite3'
|
|
6
|
+
#
|
|
7
|
+
default: &default
|
|
8
|
+
adapter: sqlite3
|
|
9
|
+
pool: <%= ENV.fetch("XIP_MAX_THREADS") { 5 } %>
|
|
10
|
+
timeout: 5000
|
|
11
|
+
|
|
12
|
+
development:
|
|
13
|
+
<<: *default
|
|
14
|
+
database: db/development.sqlite3
|
|
15
|
+
|
|
16
|
+
# Warning: The database defined as "test" will be erased and
|
|
17
|
+
# re-generated from your development database when you run "rake".
|
|
18
|
+
# Do not set this db to the same as development or production.
|
|
19
|
+
test:
|
|
20
|
+
<<: *default
|
|
21
|
+
database: db/test.sqlite3
|
|
22
|
+
|
|
23
|
+
production:
|
|
24
|
+
<<: *default
|
|
25
|
+
database: db/production.sqlite3
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class FlowMap
|
|
2
|
+
|
|
3
|
+
include Xip::Flow
|
|
4
|
+
|
|
5
|
+
flow :hello do
|
|
6
|
+
state :say_hello
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
flow :goodbye do
|
|
10
|
+
state :say_goodbye
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
flow :interrupt do
|
|
14
|
+
state :say_interrupted
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
flow :unrecognized_message do
|
|
18
|
+
state :handle_unrecognized_message
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
flow :catch_all do
|
|
22
|
+
state :level1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Add additional directories below for hot-reloading during development.
|
|
2
|
+
# You'll want to include any custom directories you create for your code.
|
|
3
|
+
# To stop certain files or directories from autoloading, use autoload_ignore_paths
|
|
4
|
+
|
|
5
|
+
# Xip.config.autoload_paths << File.join(Xip.root, 'bot', 'services')
|
|
6
|
+
# Xip.config.autoload_paths << File.join(Xip.root, 'bot', 'jobs')
|
|
7
|
+
|
|
8
|
+
# Xip.config.autoload_ignore_paths << File.join(Xip.root, 'bot', 'overrides')
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
|
|
3
|
+
# Add new inflection rules using the following format. Inflections
|
|
4
|
+
# are locale specific, and you may define rules for as many different
|
|
5
|
+
# locales as you wish. All of these examples are active by default:
|
|
6
|
+
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
|
7
|
+
# inflect.plural /^(ox)$/i, '\1en'
|
|
8
|
+
# inflect.singular /^(ox)en/i, '\1'
|
|
9
|
+
# inflect.irregular 'person', 'people'
|
|
10
|
+
# inflect.uncountable %w( fish sheep )
|
|
11
|
+
# end
|
|
12
|
+
|
|
13
|
+
# These inflection rules are supported but not enabled by default:
|
|
14
|
+
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
|
15
|
+
# inflect.acronym 'RESTful'
|
|
16
|
+
# end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
threads_count = ENV.fetch("XIP_MAX_THREADS") { 5 }.to_i
|
|
2
|
+
threads threads_count, threads_count
|
|
3
|
+
|
|
4
|
+
# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
|
|
5
|
+
#
|
|
6
|
+
port ENV.fetch("PORT") { 3000 }
|
|
7
|
+
|
|
8
|
+
# Specifies the number of `workers` to boot in clustered mode.
|
|
9
|
+
# Workers are forked webserver processes. If using threads and workers together
|
|
10
|
+
# the concurrency of the application would be max `threads` * `workers`.
|
|
11
|
+
# Workers do not work on JRuby or Windows (both of which do not support
|
|
12
|
+
# processes).
|
|
13
|
+
#
|
|
14
|
+
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
|
|
15
|
+
|
|
16
|
+
# Use the `preload_app!` method when specifying a `workers` number.
|
|
17
|
+
# This directive tells Puma to first boot the application and load code
|
|
18
|
+
# before forking the application. This takes advantage of Copy On Write
|
|
19
|
+
# process behavior so workers use less memory.
|
|
20
|
+
#
|
|
21
|
+
# preload_app!
|
|
22
|
+
|
|
23
|
+
# Specifies the `environment` that Puma will run in.
|
|
24
|
+
#
|
|
25
|
+
environment ENV.fetch("XIP_ENV") { "development" }
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
default: &default
|
|
2
|
+
# ==========================================
|
|
3
|
+
# ===== Example Facebook Service Setup =====
|
|
4
|
+
# ==========================================
|
|
5
|
+
# facebook:
|
|
6
|
+
# verify_token: XXXFACEBOOK_VERIFY_TOKENXXX
|
|
7
|
+
# page_access_token: XXXFACEBOOK_ACCESS_TOKENXXX
|
|
8
|
+
# setup:
|
|
9
|
+
# greeting: # Greetings are broken up by locale
|
|
10
|
+
# - locale: default
|
|
11
|
+
# text: "Welcome to my Facebook Bot."
|
|
12
|
+
# get_started:
|
|
13
|
+
# payload: new_user
|
|
14
|
+
# persistent_menu:
|
|
15
|
+
# - locale: default
|
|
16
|
+
# composer_input_disabled: false
|
|
17
|
+
# call_to_actions:
|
|
18
|
+
# - type: payload
|
|
19
|
+
# text: Some Button
|
|
20
|
+
# payload: some_button
|
|
21
|
+
#
|
|
22
|
+
# ===========================================
|
|
23
|
+
# ======== Example SMS Service Setup ========
|
|
24
|
+
# ===========================================
|
|
25
|
+
# twilio:
|
|
26
|
+
# account_sid: XXXTWILIO_ACCOUNT_SIDXXX
|
|
27
|
+
# auth_token: XXXTWILIO_AUTH_TOKENXXX
|
|
28
|
+
# from_phone: +14155330000
|
|
29
|
+
|
|
30
|
+
production:
|
|
31
|
+
<<: *default
|
|
32
|
+
development:
|
|
33
|
+
<<: *default
|
|
34
|
+
test:
|
|
35
|
+
<<: *default
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# This file should contain all the record creation needed to seed the database with its default values.
|
|
2
|
+
# The data can then be loaded with the `xip db:seed` command (or created alongside the database with db:setup).
|
|
3
|
+
#
|
|
4
|
+
# Examples:
|
|
5
|
+
#
|
|
6
|
+
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
|
|
7
|
+
# Character.create(name: 'Luke', movie: movies.first)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'thor/group'
|
|
5
|
+
|
|
6
|
+
module Xip
|
|
7
|
+
module Generators
|
|
8
|
+
class Generate < Thor::Group
|
|
9
|
+
include Thor::Actions
|
|
10
|
+
|
|
11
|
+
argument :generator
|
|
12
|
+
argument :name
|
|
13
|
+
|
|
14
|
+
def self.source_root
|
|
15
|
+
File.dirname(__FILE__) + "/generate/flow"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_controller
|
|
19
|
+
template('controllers/controller.tt', "bot/controllers/#{name.pluralize}_controller.rb")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_replies
|
|
23
|
+
# Sample Ask Reply
|
|
24
|
+
template('replies/ask_example.tt', "bot/replies/#{name.pluralize}/ask_example.yml.erb")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def create_helper
|
|
28
|
+
template('helpers/helper.tt', "bot/helpers/#{name}_helper.rb")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def edit_flow_map
|
|
32
|
+
inject_into_file "config/flow_map.rb", after: "include Xip::Flow\n" do
|
|
33
|
+
"\n\tflow :#{name} do\n\t\tstate :ask_example\n\tend\n"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Xip
|
|
5
|
+
module Redis
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def get_key(key, expiration: Xip.config.session_ttl)
|
|
12
|
+
if expiration > 0
|
|
13
|
+
getex(key, expiration)
|
|
14
|
+
else
|
|
15
|
+
$redis.get(key)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def delete_key(key)
|
|
20
|
+
$redis.del(key)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def getex(key, expiration=Xip.config.session_ttl)
|
|
24
|
+
$redis.multi do
|
|
25
|
+
$redis.expire(key, expiration)
|
|
26
|
+
$redis.get(key)
|
|
27
|
+
end.last
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def persist_key(key:, value:, expiration: Xip.config.session_ttl)
|
|
31
|
+
if expiration > 0
|
|
32
|
+
$redis.setex(key, expiration, value)
|
|
33
|
+
else
|
|
34
|
+
$redis.set(key, value)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/xip/jobs.rb
ADDED
data/lib/xip/lock.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Xip
|
|
4
|
+
class Lock
|
|
5
|
+
|
|
6
|
+
include Xip::Redis
|
|
7
|
+
|
|
8
|
+
attr_accessor :session_id, :session_slug, :position, :tid
|
|
9
|
+
|
|
10
|
+
def initialize(session_id:, session_slug: nil, position: nil)
|
|
11
|
+
@session_id = session_id
|
|
12
|
+
@session_slug = session_slug
|
|
13
|
+
@position = position
|
|
14
|
+
@tid = Xip.tid
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.find_lock(session_id:)
|
|
18
|
+
lock = Lock.new(session_id: session_id)
|
|
19
|
+
lock_slug = lock.slug # fetch lock from Redis
|
|
20
|
+
|
|
21
|
+
return if lock_slug.nil?
|
|
22
|
+
|
|
23
|
+
# parse the lock slug
|
|
24
|
+
tid_and_session_slug, position = lock_slug.split(':')
|
|
25
|
+
tid, session_slug = tid_and_session_slug.split('#')
|
|
26
|
+
|
|
27
|
+
# set the values from the slug to the lock object
|
|
28
|
+
lock.session_slug = session_slug
|
|
29
|
+
lock.position = position&.to_i
|
|
30
|
+
lock.tid = tid
|
|
31
|
+
lock
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create
|
|
35
|
+
if session_slug.blank?
|
|
36
|
+
raise(
|
|
37
|
+
ArgumentError,
|
|
38
|
+
'A session_slug must be specified before a lock can be created.'
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Expire locks after 30 seconds to prevent zombie locks from blocking
|
|
43
|
+
# other threads to interact with a session.
|
|
44
|
+
persist_key(
|
|
45
|
+
key: lock_key,
|
|
46
|
+
value: generate_lock,
|
|
47
|
+
expiration: Xip.config.lock_autorelease
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def release
|
|
52
|
+
delete_key(lock_key)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def slug
|
|
56
|
+
# We don't want to extend the expiration time that would result if
|
|
57
|
+
# we specified one here.
|
|
58
|
+
get_key(lock_key, expiration: 0)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns a hash:
|
|
62
|
+
# { flow: 'flow_name', state: 'state_name' }
|
|
63
|
+
def flow_and_state
|
|
64
|
+
Session.flow_and_state_from_session_slug(slug: session_slug)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def lock_key
|
|
70
|
+
[@session_id, 'lock'].join('-')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def generate_lock
|
|
74
|
+
if @position.present?
|
|
75
|
+
@session_slug = [@session_slug, @position].join(':')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
[@tid, @session_slug].join('#')
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/xip/logger.rb
CHANGED
|
@@ -25,7 +25,9 @@ module Xip
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def self.log(topic:, message:)
|
|
28
|
-
|
|
28
|
+
unless ENV['XIP_ENV'] == 'test'
|
|
29
|
+
puts "TID-#{Xip.tid} #{print_topic(topic)} #{message}"
|
|
30
|
+
end
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
def self.print_topic(topic)
|
|
@@ -36,13 +38,17 @@ module Xip
|
|
|
36
38
|
:green
|
|
37
39
|
when :previous_session, :back_to_session
|
|
38
40
|
:yellow
|
|
41
|
+
when :interrupt
|
|
42
|
+
:magenta
|
|
39
43
|
when :facebook, :twilio, :bandwidth
|
|
40
44
|
:blue
|
|
41
45
|
when :smooch
|
|
42
46
|
:magenta
|
|
43
|
-
when :alexa
|
|
47
|
+
when :alexa, :voice, :unrecognized_message
|
|
44
48
|
:light_cyan
|
|
45
|
-
when :
|
|
49
|
+
when :nlp
|
|
50
|
+
:cyan
|
|
51
|
+
when :catch_all, :err
|
|
46
52
|
:red
|
|
47
53
|
when :user
|
|
48
54
|
:white
|