stealth 2.0.0.beta6 → 2.1.0
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/.github/workflows/ci.yml +3 -5
- data/.github/workflows/release.yml +29 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +4 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +54 -48
- data/README.md +2 -1
- data/VERSION +1 -1
- data/lib/stealth/base.rb +6 -2
- data/lib/stealth/controller/catch_all.rb +2 -2
- data/lib/stealth/controller/replies.rb +11 -5
- data/lib/stealth/generators/builder/Gemfile +2 -2
- data/lib/stealth/helpers/redis.rb +10 -8
- data/lib/stealth/redis.rb +61 -0
- data/lib/stealth/reloader.rb +1 -0
- data/lib/stealth/server.rb +5 -1
- data/lib/stealth/session.rb +3 -3
- data/spec/controller/replies_spec.rb +48 -0
- data/spec/replies/messages/say_simple_hello.yml +2 -0
- data/spec/session_spec.rb +2 -4
- data/spec/spec_helper.rb +25 -2
- data/stealth.gemspec +8 -6
- metadata +66 -85
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac41b0515e5073d79de1d4c5abdc76ec7ab57eccbc3ba5b8ce0e081f4ef8de51
|
4
|
+
data.tar.gz: 88621a529af26a406f02e65b8f757a0969d3a936577b522b2589e781e676a987
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78ece1a059e95b7df55ed430f35adb79cb1bb8e7a9b5df659def6513cf670db0123525f026855b31f96d00d15506478f77a6aa567a99597df122297dad8c979d
|
7
|
+
data.tar.gz: 92e908365e8256fa2264609224b9a136254bec5fd91aea08bf277f6b2e2173c9b09774fac1da3762617ac29df08ac56cbcb4ae9178f02674b927a5d24667e0db
|
data/.github/workflows/ci.yml
CHANGED
@@ -11,13 +11,11 @@ jobs:
|
|
11
11
|
strategy:
|
12
12
|
fail-fast: false
|
13
13
|
matrix:
|
14
|
-
os: [ubuntu-
|
15
|
-
ruby: [
|
14
|
+
os: [ubuntu-22.04, macos-latest]
|
15
|
+
ruby: [ 3.3, truffleruby ]
|
16
16
|
exclude:
|
17
17
|
- os: ubuntu-22.04
|
18
|
-
ruby:
|
19
|
-
- os: ubuntu-22.04
|
20
|
-
ruby: truffleruby-head
|
18
|
+
ruby: truffleruby
|
21
19
|
|
22
20
|
runs-on: ${{ matrix.os }}
|
23
21
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
name: Release Gem
|
2
|
+
on:
|
3
|
+
# Triggers the workflow on push with a tag prefixed with v*
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- 'v*'
|
7
|
+
|
8
|
+
# Allows you to run this workflow manually from the Actions tab
|
9
|
+
workflow_dispatch:
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
release:
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v3
|
16
|
+
- uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: 2.7
|
19
|
+
bundler-cache: true
|
20
|
+
- name: Publish gem
|
21
|
+
env:
|
22
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
23
|
+
run: |
|
24
|
+
mkdir -p $HOME/.gem
|
25
|
+
touch $HOME/.gem/credentials
|
26
|
+
chmod 0600 $HOME/.gem/credentials
|
27
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
28
|
+
gem build *.gemspec
|
29
|
+
gem push *.gem
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -14,9 +14,9 @@
|
|
14
14
|
* [Logging] `primary_session`, `previous_session`, and `back_to_session` now explicitly logged
|
15
15
|
* [Sessions] The session is no longer set on update or stepping witht destination flow and state match the existing session.
|
16
16
|
* [Scheduled Replies] The `service_message.target_id` is now set for scheduled replies. NOTE: scheduled replies that are already enqueued will NOT have this set.
|
17
|
-
* [Server] Updated to Puma
|
18
|
-
* [Server] Updated to Sidekiq
|
19
|
-
* [Server] Updated to Sinatra
|
17
|
+
* [Server] Updated to Puma 6.x
|
18
|
+
* [Server] Updated to Sidekiq 7.x
|
19
|
+
* [Server] Updated to Sinatra 3.x
|
20
20
|
* [Sessions] Added `to_s` for sessions to pretty print the slug. Useful when debugging.
|
21
21
|
* `send_reples` now supports two additional options for replies:
|
22
22
|
`send_replies(custom_reply: 'hello/say_hello')`
|
@@ -56,6 +56,7 @@
|
|
56
56
|
* [Replies] Voice services (determined by having "voice" in the name) now automatically skip auto-delays.
|
57
57
|
* [Controllers] `current_message` now has a `confidence` attribute containing a float with the confidence value of the transcription (from 0 to 1).
|
58
58
|
* [Controllers] Added a `halt!` method that can be used with the controller error handlers to stop code execution.
|
59
|
+
* [Logger] If the driver makes the `translated_reply` instance variable available, it will now be logged.
|
59
60
|
|
60
61
|
## Bug Fixes
|
61
62
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,85 +1,91 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
stealth (2.
|
5
|
-
activesupport (~>
|
4
|
+
stealth (2.1.0)
|
5
|
+
activesupport (~> 7.0)
|
6
|
+
connection_pool (~> 2.4)
|
6
7
|
multi_json (~> 1.12)
|
7
|
-
puma (
|
8
|
-
|
9
|
-
|
8
|
+
puma (~> 6.0)
|
9
|
+
redis (~> 5.0)
|
10
|
+
sidekiq (~> 7.0)
|
11
|
+
sinatra (>= 2, < 4)
|
10
12
|
thor (~> 1.0)
|
13
|
+
zeitwerk (~> 2.6)
|
11
14
|
|
12
15
|
GEM
|
13
16
|
remote: https://rubygems.org/
|
14
17
|
specs:
|
15
|
-
activesupport (
|
18
|
+
activesupport (7.0.5)
|
16
19
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
20
|
i18n (>= 1.6, < 2)
|
18
21
|
minitest (>= 5.1)
|
19
22
|
tzinfo (~> 2.0)
|
20
|
-
|
21
|
-
concurrent-ruby (1.
|
22
|
-
connection_pool (2.3
|
23
|
+
base64 (0.3.0)
|
24
|
+
concurrent-ruby (1.3.5)
|
25
|
+
connection_pool (2.5.3)
|
23
26
|
diff-lcs (1.5.0)
|
24
|
-
i18n (1.
|
27
|
+
i18n (1.13.0)
|
25
28
|
concurrent-ruby (~> 1.0)
|
26
|
-
|
27
|
-
|
29
|
+
logger (1.7.0)
|
30
|
+
minitest (5.18.0)
|
31
|
+
mock_redis (0.36.0)
|
28
32
|
ruby2_keywords
|
29
33
|
multi_json (1.15.0)
|
30
|
-
mustermann (
|
34
|
+
mustermann (3.0.0)
|
31
35
|
ruby2_keywords (~> 0.0.1)
|
32
|
-
nio4r (2.5.
|
33
|
-
oj (3.
|
34
|
-
puma (
|
36
|
+
nio4r (2.5.9)
|
37
|
+
oj (3.14.3)
|
38
|
+
puma (6.3.0)
|
35
39
|
nio4r (~> 2.0)
|
36
|
-
rack (2.2.
|
37
|
-
rack-protection (
|
40
|
+
rack (2.2.17)
|
41
|
+
rack-protection (3.0.6)
|
38
42
|
rack
|
39
|
-
rack-test (2.0
|
43
|
+
rack-test (2.1.0)
|
40
44
|
rack (>= 1.3)
|
41
|
-
redis (4.
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
rspec-
|
48
|
-
|
45
|
+
redis (5.4.1)
|
46
|
+
redis-client (>= 0.22.0)
|
47
|
+
redis-client (0.25.1)
|
48
|
+
connection_pool
|
49
|
+
rspec (3.12.0)
|
50
|
+
rspec-core (~> 3.12.0)
|
51
|
+
rspec-expectations (~> 3.12.0)
|
52
|
+
rspec-mocks (~> 3.12.0)
|
53
|
+
rspec-core (3.12.0)
|
54
|
+
rspec-support (~> 3.12.0)
|
55
|
+
rspec-expectations (3.12.0)
|
49
56
|
diff-lcs (>= 1.2.0, < 2.0)
|
50
|
-
rspec-support (~> 3.
|
51
|
-
rspec-mocks (3.
|
57
|
+
rspec-support (~> 3.12.0)
|
58
|
+
rspec-mocks (3.12.0)
|
52
59
|
diff-lcs (>= 1.2.0, < 2.0)
|
53
|
-
rspec-support (~> 3.
|
54
|
-
rspec-support (3.
|
55
|
-
rspec_junit_formatter (0.4.1)
|
56
|
-
rspec-core (>= 2, < 4, != 2.12.0)
|
60
|
+
rspec-support (~> 3.12.0)
|
61
|
+
rspec-support (3.12.0)
|
57
62
|
ruby2_keywords (0.0.5)
|
58
|
-
sidekiq (
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
sidekiq (7.3.9)
|
64
|
+
base64
|
65
|
+
connection_pool (>= 2.3.0)
|
66
|
+
logger
|
67
|
+
rack (>= 2.2.4)
|
68
|
+
redis-client (>= 0.22.2)
|
69
|
+
sinatra (3.0.6)
|
70
|
+
mustermann (~> 3.0)
|
71
|
+
rack (~> 2.2, >= 2.2.4)
|
72
|
+
rack-protection (= 3.0.6)
|
66
73
|
tilt (~> 2.0)
|
67
|
-
thor (1.2.
|
68
|
-
tilt (2.0
|
69
|
-
tzinfo (2.0.
|
74
|
+
thor (1.2.2)
|
75
|
+
tilt (2.2.0)
|
76
|
+
tzinfo (2.0.6)
|
70
77
|
concurrent-ruby (~> 1.0)
|
71
|
-
zeitwerk (2.6.
|
78
|
+
zeitwerk (2.6.8)
|
72
79
|
|
73
80
|
PLATFORMS
|
74
81
|
ruby
|
75
82
|
|
76
83
|
DEPENDENCIES
|
77
84
|
mock_redis (~> 0.22)
|
78
|
-
oj (~> 3.
|
85
|
+
oj (~> 3.14)
|
79
86
|
rack-test (~> 2.0)
|
80
87
|
rspec (~> 3.9)
|
81
|
-
rspec_junit_formatter (~> 0.3)
|
82
88
|
stealth!
|
83
89
|
|
84
90
|
BUNDLED WITH
|
85
|
-
2.
|
91
|
+
2.3.26
|
data/README.md
CHANGED
@@ -32,6 +32,7 @@ Currently, there are gems for:
|
|
32
32
|
### Messaging
|
33
33
|
* [Facebook Messenger](https://github.com/hellostealth/stealth-facebook)
|
34
34
|
* [Twilio SMS](https://github.com/hellostealth/stealth-twilio)
|
35
|
+
* [Bandwidth](https://github.com/hellostealth/stealth-bandwidth)
|
35
36
|
* [Smooch](https://github.com/hellostealth/stealth-smooch)
|
36
37
|
|
37
38
|
### Voice
|
@@ -54,4 +55,4 @@ Stealth is versioned using [Semantic Versioning](https://semver.org), but it's m
|
|
54
55
|
|
55
56
|
## License
|
56
57
|
|
57
|
-
"Stealth" and the Stealth logo are Copyright (c) 2017-
|
58
|
+
"Stealth" and the Stealth logo are Copyright (c) 2017-2024 MAV Automated Ventures Inc.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.1.0
|
data/lib/stealth/base.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
# base requirements
|
5
5
|
require 'yaml'
|
6
6
|
require 'sidekiq'
|
7
|
+
require 'redis'
|
7
8
|
require 'active_support/all'
|
8
9
|
|
9
10
|
begin
|
@@ -20,6 +21,7 @@ require 'stealth/core_ext'
|
|
20
21
|
require 'stealth/logger'
|
21
22
|
require 'stealth/configuration'
|
22
23
|
require 'stealth/reloader'
|
24
|
+
require 'stealth/redis'
|
23
25
|
|
24
26
|
# helpers
|
25
27
|
require 'stealth/helpers/redis'
|
@@ -123,7 +125,9 @@ module Stealth
|
|
123
125
|
|
124
126
|
load_bot!
|
125
127
|
|
126
|
-
Sidekiq.
|
128
|
+
Sidekiq.configure_server do |config|
|
129
|
+
config[:reloader] = Stealth.bot_reloader
|
130
|
+
end
|
127
131
|
|
128
132
|
if defined?(ActiveRecord)
|
129
133
|
if ENV['DATABASE_URL'].present?
|
@@ -131,7 +135,7 @@ module Stealth
|
|
131
135
|
else
|
132
136
|
database_config = File.read(File.join(Stealth.root, 'config', 'database.yml'))
|
133
137
|
ActiveRecord::Base.establish_connection(
|
134
|
-
YAML.load(ERB.new(database_config).result)[Stealth.env]
|
138
|
+
YAML.load(ERB.new(database_config).result, aliases: true)[Stealth.env]
|
135
139
|
)
|
136
140
|
end
|
137
141
|
end
|
@@ -52,7 +52,7 @@ module Stealth
|
|
52
52
|
private
|
53
53
|
|
54
54
|
def fetch_error_level
|
55
|
-
if fail_attempts =
|
55
|
+
if fail_attempts = Stealth::RedisSupport.with { |r| r.get(error_slug) }
|
56
56
|
begin
|
57
57
|
fail_attempts = Integer(fail_attempts)
|
58
58
|
rescue ArgumentError
|
@@ -65,7 +65,7 @@ module Stealth
|
|
65
65
|
end
|
66
66
|
|
67
67
|
# Set the error with an expiration to avoid filling Redis
|
68
|
-
|
68
|
+
Stealth::RedisSupport.with { |r| r.setex(error_slug, 15.minutes.to_i, fail_attempts) }
|
69
69
|
|
70
70
|
fail_attempts
|
71
71
|
end
|
@@ -96,11 +96,11 @@ module Stealth
|
|
96
96
|
reply: reply
|
97
97
|
)
|
98
98
|
|
99
|
-
|
100
|
-
client = service_client.new(reply:
|
99
|
+
formatted_reply = handler.send(reply.reply_type)
|
100
|
+
client = service_client.new(reply: formatted_reply)
|
101
101
|
client.transmit
|
102
102
|
|
103
|
-
log_reply(reply) if Stealth.config.transcript_logging
|
103
|
+
log_reply(reply, handler) if Stealth.config.transcript_logging
|
104
104
|
|
105
105
|
# If this was a 'delay' type of reply, we insert the delay
|
106
106
|
if reply.delay?
|
@@ -264,10 +264,14 @@ module Stealth
|
|
264
264
|
end
|
265
265
|
end
|
266
266
|
|
267
|
-
def log_reply(reply)
|
267
|
+
def log_reply(reply, reply_handler)
|
268
268
|
message = case reply.reply_type
|
269
269
|
when 'text'
|
270
|
-
|
270
|
+
if reply_handler.respond_to?(:translated_reply)
|
271
|
+
reply_handler.translated_reply
|
272
|
+
else
|
273
|
+
reply['text']
|
274
|
+
end
|
271
275
|
when 'speech'
|
272
276
|
reply['speech']
|
273
277
|
when 'ssml'
|
@@ -282,6 +286,8 @@ module Stealth
|
|
282
286
|
topic: current_service,
|
283
287
|
message: "User #{current_session_id} -> Sending: #{message}"
|
284
288
|
)
|
289
|
+
|
290
|
+
message
|
285
291
|
end
|
286
292
|
|
287
293
|
end # instance methods
|
@@ -12,26 +12,28 @@ module Stealth
|
|
12
12
|
if expiration > 0
|
13
13
|
getex(key, expiration)
|
14
14
|
else
|
15
|
-
|
15
|
+
Stealth::RedisSupport.with { |r| r.get(key) }
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
def delete_key(key)
|
20
|
-
|
20
|
+
Stealth::RedisSupport.with { |r| r.del(key) }
|
21
21
|
end
|
22
22
|
|
23
23
|
def getex(key, expiration=Stealth.config.session_ttl)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
Stealth::RedisSupport.with do |r|
|
25
|
+
r.multi do |pipeline|
|
26
|
+
pipeline.expire(key, expiration)
|
27
|
+
pipeline.get(key)
|
28
|
+
end.last
|
29
|
+
end
|
28
30
|
end
|
29
31
|
|
30
32
|
def persist_key(key:, value:, expiration: Stealth.config.session_ttl)
|
31
33
|
if expiration > 0
|
32
|
-
|
34
|
+
Stealth::RedisSupport.with { |r| r.setex(key, expiration, value) }
|
33
35
|
else
|
34
|
-
|
36
|
+
Stealth::RedisSupport.with { |r| r.set(key, value) }
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "redis"
|
4
|
+
require "connection_pool"
|
5
|
+
|
6
|
+
module Stealth
|
7
|
+
class RedisConfig
|
8
|
+
attr_accessor :url, :pool_size, :pool_timeout
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@url = Stealth.env.development? ? "redis://localhost:6379/0" : ENV["STEALTH_REDIS_URL"] || ENV["REDIS_URL"]
|
12
|
+
@pool_size = Integer(ENV["STEALTH_REDIS_POOL"] || 5)
|
13
|
+
@pool_timeout = Integer(ENV["STEALTH_REDIS_TIMEOUT"] || 5)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_redis_kwargs
|
17
|
+
{ url: url }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module RedisSupport
|
22
|
+
class << self
|
23
|
+
def config
|
24
|
+
@config ||= RedisConfig.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def configure
|
28
|
+
yield(config)
|
29
|
+
reset_pool!
|
30
|
+
end
|
31
|
+
|
32
|
+
def pool
|
33
|
+
@pool ||= build_pool
|
34
|
+
end
|
35
|
+
|
36
|
+
def with(&blk)
|
37
|
+
pool.with(&blk)
|
38
|
+
end
|
39
|
+
|
40
|
+
def connection_pool
|
41
|
+
pool
|
42
|
+
end
|
43
|
+
|
44
|
+
def reset_pool!
|
45
|
+
if defined?(@pool) && @pool
|
46
|
+
@pool.shutdown(&:close) rescue nil
|
47
|
+
end
|
48
|
+
@pool = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def build_pool
|
54
|
+
ConnectionPool.new(size: config.pool_size, timeout: config.pool_timeout) do
|
55
|
+
::Redis.new(**config.to_redis_kwargs)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/lib/stealth/reloader.rb
CHANGED
data/lib/stealth/server.rb
CHANGED
@@ -37,7 +37,11 @@ module Stealth
|
|
37
37
|
json_params = MultiJson.load(request.body.read)
|
38
38
|
|
39
39
|
if bandwidth?
|
40
|
-
|
40
|
+
if json_params.is_a?(Array)
|
41
|
+
params.merge!(json_params.first)
|
42
|
+
else
|
43
|
+
return [200, 'Ok']
|
44
|
+
end
|
41
45
|
else
|
42
46
|
params.merge!(json_params)
|
43
47
|
end
|
data/lib/stealth/session.rb
CHANGED
@@ -20,10 +20,10 @@ module Stealth
|
|
20
20
|
@type = type
|
21
21
|
|
22
22
|
if id.present?
|
23
|
-
unless defined?(
|
23
|
+
unless defined?(Stealth::RedisSupport) && Stealth::RedisSupport.connection_pool.present?
|
24
24
|
raise(
|
25
25
|
Stealth::Errors::RedisNotConfigured,
|
26
|
-
"Please make sure REDIS_URL is configured before using sessions"
|
26
|
+
"Please make sure STEALTH_REDIS_URL or REDIS_URL is configured before using sessions"
|
27
27
|
)
|
28
28
|
end
|
29
29
|
|
@@ -91,7 +91,7 @@ module Stealth
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def clear_session
|
94
|
-
|
94
|
+
Stealth::RedisSupport.with { |r| r.del(session_key) }
|
95
95
|
end
|
96
96
|
|
97
97
|
def present?
|
@@ -66,6 +66,10 @@ describe "Stealth::Controller replies" do
|
|
66
66
|
send_replies custom_reply: 'messages/sub1/sub2/say_nested'
|
67
67
|
end
|
68
68
|
|
69
|
+
def say_simple_hello
|
70
|
+
send_replies
|
71
|
+
end
|
72
|
+
|
69
73
|
def say_inline_reply
|
70
74
|
reply = [
|
71
75
|
{ 'reply_type' => 'text', 'text' => 'Hi, Morty. Welcome to Stealth bot...' },
|
@@ -609,6 +613,50 @@ describe "Stealth::Controller replies" do
|
|
609
613
|
end
|
610
614
|
end
|
611
615
|
|
616
|
+
describe "Logging replies" do
|
617
|
+
let(:stubbed_handler) { double("handler") }
|
618
|
+
let(:stubbed_client) { double("client") }
|
619
|
+
|
620
|
+
before(:each) do
|
621
|
+
allow(Stealth::Services::Facebook::ReplyHandler).to receive(:new).and_return(stubbed_handler)
|
622
|
+
allow(Stealth::Services::Facebook::Client).to receive(:new).and_return(stubbed_client)
|
623
|
+
allow(controller.current_session).to receive(:flow_string).and_return("message")
|
624
|
+
allow(controller.current_session).to receive(:state_string).and_return("say_simple_hello")
|
625
|
+
Stealth.config.auto_insert_delays = false
|
626
|
+
Stealth.config.transcript_logging = true
|
627
|
+
end
|
628
|
+
|
629
|
+
after(:each) do
|
630
|
+
Stealth.config.auto_insert_delays = true
|
631
|
+
Stealth.config.transcript_logging = false
|
632
|
+
end
|
633
|
+
|
634
|
+
it "should log replies if transcript_logging is enabled" do
|
635
|
+
allow(stubbed_client).to receive(:transmit).and_return(true)
|
636
|
+
allow(controller).to receive(:sleep).and_return(true).with(2.0)
|
637
|
+
|
638
|
+
allow(stubbed_handler).to receive(:text).exactly(1).times
|
639
|
+
expect(Stealth::Logger).to receive(:l).with(
|
640
|
+
topic: 'facebook',
|
641
|
+
message: "User #{controller.current_session_id} -> Sending: Hello"
|
642
|
+
)
|
643
|
+
controller.say_simple_hello
|
644
|
+
end
|
645
|
+
|
646
|
+
it "should log translated replies if transcript_logging is enabled and the driver supports it" do
|
647
|
+
allow(stubbed_client).to receive(:transmit).and_return(true)
|
648
|
+
allow(controller).to receive(:sleep).and_return(true).with(2.0)
|
649
|
+
|
650
|
+
allow(stubbed_handler).to receive(:text).exactly(1).times
|
651
|
+
allow(stubbed_handler).to receive(:translated_reply).and_return("Bonjour")
|
652
|
+
expect(Stealth::Logger).to receive(:l).with(
|
653
|
+
topic: 'facebook',
|
654
|
+
message: "User #{controller.current_session_id} -> Sending: Bonjour"
|
655
|
+
)
|
656
|
+
controller.say_simple_hello
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
612
660
|
describe "client errors" do
|
613
661
|
let(:stubbed_handler) { double("handler") }
|
614
662
|
let(:stubbed_client) { double("client") }
|
data/spec/session_spec.rb
CHANGED
@@ -20,14 +20,12 @@ end
|
|
20
20
|
describe "Stealth::Session" do
|
21
21
|
let(:id) { '0xDEADBEEF' }
|
22
22
|
|
23
|
-
it "should raise an error if
|
24
|
-
|
23
|
+
it "should raise an error if Stealth::RedisSupport connection_pool is not set" do
|
24
|
+
allow(Stealth::RedisSupport).to receive(:connection_pool).and_return(nil)
|
25
25
|
|
26
26
|
expect {
|
27
27
|
Stealth::Session.new(id: id)
|
28
28
|
}.to raise_error(Stealth::Errors::RedisNotConfigured)
|
29
|
-
|
30
|
-
$redis = MockRedis.new
|
31
29
|
end
|
32
30
|
|
33
31
|
describe "without a session" do
|
data/spec/spec_helper.rb
CHANGED
@@ -4,18 +4,41 @@
|
|
4
4
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
5
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
6
|
require 'rspec'
|
7
|
+
require 'connection_pool'
|
8
|
+
require 'mock_redis'
|
9
|
+
|
10
|
+
REDIS_TEST_CLIENT = MockRedis.new
|
11
|
+
REDIS_TEST_WRAPPER = ConnectionPool::Wrapper.new(size: 1, timeout: 1) { REDIS_TEST_CLIENT }
|
12
|
+
|
13
|
+
$redis = REDIS_TEST_WRAPPER
|
7
14
|
|
8
15
|
require 'stealth'
|
9
16
|
require 'sidekiq/testing'
|
10
|
-
|
17
|
+
|
18
|
+
module Stealth
|
19
|
+
module RedisSupport
|
20
|
+
class << self
|
21
|
+
def with(&blk)
|
22
|
+
REDIS_TEST_WRAPPER.with(&blk)
|
23
|
+
end
|
24
|
+
def pool
|
25
|
+
REDIS_TEST_WRAPPER
|
26
|
+
end
|
27
|
+
def reset_pool!
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
11
33
|
|
12
34
|
# Requires supporting files with custom matchers and macros, etc,
|
13
35
|
# in ./support/ and its subdirectories.
|
14
36
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
15
37
|
|
16
|
-
$redis = MockRedis.new
|
17
38
|
$services_yml = File.read(File.join(File.dirname(__FILE__), 'support', 'services.yml'))
|
18
39
|
|
40
|
+
Sidekiq.logger.level = Logger::ERROR
|
41
|
+
|
19
42
|
RSpec.configure do |config|
|
20
43
|
ENV['STEALTH_ENV'] = 'test'
|
21
44
|
|
data/stealth.gemspec
CHANGED
@@ -12,15 +12,17 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.authors = ['Mauricio Gomes', 'Matthew Black']
|
13
13
|
s.email = 'mauricio@edge14.com'
|
14
14
|
|
15
|
-
s.add_dependency '
|
16
|
-
s.add_dependency 'puma', '>= 4.2', '< 6.0'
|
17
|
-
s.add_dependency 'thor', '~> 1.0'
|
15
|
+
s.add_dependency 'activesupport', '~> 7.0'
|
18
16
|
s.add_dependency 'multi_json', '~> 1.12'
|
19
|
-
s.add_dependency '
|
20
|
-
s.add_dependency '
|
17
|
+
s.add_dependency 'puma', '~> 6.0'
|
18
|
+
s.add_dependency 'redis', '~> 5.0'
|
19
|
+
s.add_dependency "connection_pool", "~> 2.4"
|
20
|
+
s.add_dependency 'sidekiq', '~> 7.0'
|
21
|
+
s.add_dependency 'sinatra', '>= 2', '< 4'
|
22
|
+
s.add_dependency 'thor', '~> 1.0'
|
23
|
+
s.add_dependency 'zeitwerk', '~> 2.6'
|
21
24
|
|
22
25
|
s.add_development_dependency 'rspec', '~> 3.9'
|
23
|
-
s.add_development_dependency 'rspec_junit_formatter', '~> 0.3'
|
24
26
|
s.add_development_dependency 'rack-test', '~> 2.0'
|
25
27
|
s.add_development_dependency 'mock_redis', '~> 0.22'
|
26
28
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stealth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mauricio Gomes
|
@@ -9,126 +9,154 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2025-08-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: activesupport
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '7.0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '7.0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: multi_json
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
32
|
+
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
35
|
-
|
34
|
+
version: '1.12'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.12'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: puma
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
36
47
|
- !ruby/object:Gem::Version
|
37
48
|
version: '6.0'
|
38
49
|
type: :runtime
|
39
50
|
prerelease: false
|
40
51
|
version_requirements: !ruby/object:Gem::Requirement
|
41
52
|
requirements:
|
42
|
-
- - "
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version: '4.2'
|
45
|
-
- - "<"
|
53
|
+
- - "~>"
|
46
54
|
- !ruby/object:Gem::Version
|
47
55
|
version: '6.0'
|
48
56
|
- !ruby/object:Gem::Dependency
|
49
|
-
name:
|
57
|
+
name: redis
|
50
58
|
requirement: !ruby/object:Gem::Requirement
|
51
59
|
requirements:
|
52
60
|
- - "~>"
|
53
61
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
62
|
+
version: '5.0'
|
55
63
|
type: :runtime
|
56
64
|
prerelease: false
|
57
65
|
version_requirements: !ruby/object:Gem::Requirement
|
58
66
|
requirements:
|
59
67
|
- - "~>"
|
60
68
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
69
|
+
version: '5.0'
|
62
70
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
71
|
+
name: connection_pool
|
64
72
|
requirement: !ruby/object:Gem::Requirement
|
65
73
|
requirements:
|
66
74
|
- - "~>"
|
67
75
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
76
|
+
version: '2.4'
|
69
77
|
type: :runtime
|
70
78
|
prerelease: false
|
71
79
|
version_requirements: !ruby/object:Gem::Requirement
|
72
80
|
requirements:
|
73
81
|
- - "~>"
|
74
82
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
83
|
+
version: '2.4'
|
76
84
|
- !ruby/object:Gem::Dependency
|
77
85
|
name: sidekiq
|
78
86
|
requirement: !ruby/object:Gem::Requirement
|
79
87
|
requirements:
|
80
88
|
- - "~>"
|
81
89
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
90
|
+
version: '7.0'
|
83
91
|
type: :runtime
|
84
92
|
prerelease: false
|
85
93
|
version_requirements: !ruby/object:Gem::Requirement
|
86
94
|
requirements:
|
87
95
|
- - "~>"
|
88
96
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
97
|
+
version: '7.0'
|
90
98
|
- !ruby/object:Gem::Dependency
|
91
|
-
name:
|
99
|
+
name: sinatra
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '2'
|
105
|
+
- - "<"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '4'
|
108
|
+
type: :runtime
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '2'
|
115
|
+
- - "<"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '4'
|
118
|
+
- !ruby/object:Gem::Dependency
|
119
|
+
name: thor
|
92
120
|
requirement: !ruby/object:Gem::Requirement
|
93
121
|
requirements:
|
94
122
|
- - "~>"
|
95
123
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
124
|
+
version: '1.0'
|
97
125
|
type: :runtime
|
98
126
|
prerelease: false
|
99
127
|
version_requirements: !ruby/object:Gem::Requirement
|
100
128
|
requirements:
|
101
129
|
- - "~>"
|
102
130
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
131
|
+
version: '1.0'
|
104
132
|
- !ruby/object:Gem::Dependency
|
105
|
-
name:
|
133
|
+
name: zeitwerk
|
106
134
|
requirement: !ruby/object:Gem::Requirement
|
107
135
|
requirements:
|
108
136
|
- - "~>"
|
109
137
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
111
|
-
type: :
|
138
|
+
version: '2.6'
|
139
|
+
type: :runtime
|
112
140
|
prerelease: false
|
113
141
|
version_requirements: !ruby/object:Gem::Requirement
|
114
142
|
requirements:
|
115
143
|
- - "~>"
|
116
144
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
145
|
+
version: '2.6'
|
118
146
|
- !ruby/object:Gem::Dependency
|
119
|
-
name:
|
147
|
+
name: rspec
|
120
148
|
requirement: !ruby/object:Gem::Requirement
|
121
149
|
requirements:
|
122
150
|
- - "~>"
|
123
151
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
152
|
+
version: '3.9'
|
125
153
|
type: :development
|
126
154
|
prerelease: false
|
127
155
|
version_requirements: !ruby/object:Gem::Requirement
|
128
156
|
requirements:
|
129
157
|
- - "~>"
|
130
158
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
159
|
+
version: '3.9'
|
132
160
|
- !ruby/object:Gem::Dependency
|
133
161
|
name: rack-test
|
134
162
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,6 +195,7 @@ files:
|
|
167
195
|
- ".gitbook.yaml"
|
168
196
|
- ".github/dependabot.yml"
|
169
197
|
- ".github/workflows/ci.yml"
|
198
|
+
- ".github/workflows/release.yml"
|
170
199
|
- ".gitignore"
|
171
200
|
- CHANGELOG.md
|
172
201
|
- Gemfile
|
@@ -320,6 +349,7 @@ files:
|
|
320
349
|
- lib/stealth/migrations/tasks.rb
|
321
350
|
- lib/stealth/nlp/client.rb
|
322
351
|
- lib/stealth/nlp/result.rb
|
352
|
+
- lib/stealth/redis.rb
|
323
353
|
- lib/stealth/reloader.rb
|
324
354
|
- lib/stealth/reply.rb
|
325
355
|
- lib/stealth/scheduled_reply.rb
|
@@ -362,6 +392,7 @@ files:
|
|
362
392
|
- spec/replies/messages/say_oi.yml.erb
|
363
393
|
- spec/replies/messages/say_randomize_speech.yml
|
364
394
|
- spec/replies/messages/say_randomize_text.yml
|
395
|
+
- spec/replies/messages/say_simple_hello.yml
|
365
396
|
- spec/replies/messages/say_yo.yml
|
366
397
|
- spec/replies/messages/say_yo.yml+twitter
|
367
398
|
- spec/replies/messages/sub1/sub2/say_nested.yml
|
@@ -399,62 +430,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
399
430
|
version: '0'
|
400
431
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
401
432
|
requirements:
|
402
|
-
- - "
|
433
|
+
- - ">="
|
403
434
|
- !ruby/object:Gem::Version
|
404
|
-
version:
|
435
|
+
version: '0'
|
405
436
|
requirements: []
|
406
|
-
rubygems_version: 3.
|
437
|
+
rubygems_version: 3.1.6
|
407
438
|
signing_key:
|
408
439
|
specification_version: 4
|
409
440
|
summary: Ruby framework for conversational bots
|
410
|
-
test_files:
|
411
|
-
- spec/configuration_spec.rb
|
412
|
-
- spec/controller/callbacks_spec.rb
|
413
|
-
- spec/controller/catch_all_spec.rb
|
414
|
-
- spec/controller/controller_spec.rb
|
415
|
-
- spec/controller/dynamic_delay_spec.rb
|
416
|
-
- spec/controller/helpers_spec.rb
|
417
|
-
- spec/controller/interrupt_detect_spec.rb
|
418
|
-
- spec/controller/messages_spec.rb
|
419
|
-
- spec/controller/nlp_spec.rb
|
420
|
-
- spec/controller/replies_spec.rb
|
421
|
-
- spec/controller/unrecognized_message_spec.rb
|
422
|
-
- spec/dispatcher_spec.rb
|
423
|
-
- spec/flow/flow_spec.rb
|
424
|
-
- spec/flow/state_spec.rb
|
425
|
-
- spec/helpers/redis_spec.rb
|
426
|
-
- spec/lock_spec.rb
|
427
|
-
- spec/nlp/client_spec.rb
|
428
|
-
- spec/nlp/result_spec.rb
|
429
|
-
- spec/replies/hello.yml.erb
|
430
|
-
- spec/replies/messages/say_hola.yml+facebook.erb
|
431
|
-
- spec/replies/messages/say_hola.yml+twilio.erb
|
432
|
-
- spec/replies/messages/say_hola.yml.erb
|
433
|
-
- spec/replies/messages/say_howdy_with_dynamic.yml
|
434
|
-
- spec/replies/messages/say_msgs_without_breaks.yml
|
435
|
-
- spec/replies/messages/say_offer.yml
|
436
|
-
- spec/replies/messages/say_offer_with_dynamic.yml
|
437
|
-
- spec/replies/messages/say_oi.yml.erb
|
438
|
-
- spec/replies/messages/say_randomize_speech.yml
|
439
|
-
- spec/replies/messages/say_randomize_text.yml
|
440
|
-
- spec/replies/messages/say_yo.yml
|
441
|
-
- spec/replies/messages/say_yo.yml+twitter
|
442
|
-
- spec/replies/messages/sub1/sub2/say_nested.yml
|
443
|
-
- spec/reply_spec.rb
|
444
|
-
- spec/scheduled_reply_spec.rb
|
445
|
-
- spec/service_reply_spec.rb
|
446
|
-
- spec/session_spec.rb
|
447
|
-
- spec/spec_helper.rb
|
448
|
-
- spec/support/alternate_helpers/foo_helper.rb
|
449
|
-
- spec/support/controllers/vaders_controller.rb
|
450
|
-
- spec/support/helpers/fun/games_helper.rb
|
451
|
-
- spec/support/helpers/fun/pdf_helper.rb
|
452
|
-
- spec/support/helpers/standalone_helper.rb
|
453
|
-
- spec/support/helpers_typo/users_helper.rb
|
454
|
-
- spec/support/nlp_clients/dialogflow.rb
|
455
|
-
- spec/support/nlp_clients/luis.rb
|
456
|
-
- spec/support/nlp_results/luis_result.rb
|
457
|
-
- spec/support/sample_messages.rb
|
458
|
-
- spec/support/services.yml
|
459
|
-
- spec/support/services_with_erb.yml
|
460
|
-
- spec/version_spec.rb
|
441
|
+
test_files: []
|