bot_platform 0.2.3 → 0.3.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/.gitignore +2 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +1 -1
- data/README.md +36 -5
- data/images/bot-platform.png +0 -0
- data/lib/bot_platform/asserts.rb +4 -0
- data/lib/bot_platform/dialogs/dialog_context.rb +9 -4
- data/lib/bot_platform/dialogs/dialog_reason.rb +14 -0
- data/lib/bot_platform/dialogs/dialog_result.rb +1 -0
- data/lib/bot_platform/dialogs/dialog_state.rb +4 -2
- data/lib/bot_platform/dialogs/prompts/confirm_prompt.rb +50 -0
- data/lib/bot_platform/dialogs/prompts/number_prompt.rb +43 -0
- data/lib/bot_platform/dialogs/prompts/prompt.rb +5 -3
- data/lib/bot_platform/dialogs/prompts/prompt_options.rb +3 -0
- data/lib/bot_platform/dialogs/waterfall_dialog.rb +124 -0
- data/lib/bot_platform/dialogs/waterfall_step.rb +17 -0
- data/lib/bot_platform/dialogs/waterfall_step_context.rb +29 -0
- data/lib/bot_platform/dialogs.rb +9 -0
- data/lib/bot_platform/state/bot_state.rb +9 -0
- data/lib/bot_platform/state/user_state.rb +16 -0
- data/lib/bot_platform/version.rb +1 -1
- data/lib/bot_platform.rb +1 -0
- data/samples/dialogs/dialog_simple.rb +4 -3
- data/samples/dialogs/waterfall_dialogs.rb +46 -0
- data/samples/dialogs/waterfall_steps.rb +50 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c7889efb278cdccac2f362eba726567c20523b0f71295fd99dcf02c599dde66
|
4
|
+
data.tar.gz: 50eae5a0a56f0d024adaded78b83761b7a88a2ae03162bc573582f5d97863c0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e69556208d3f547699c078223e8d5669c87af5224f42ffb8d98adc063172a6bdf42d8094ee25168de1f24c037c8ddb55e9972b7b346d5cc988ecb908f1267d5f
|
7
|
+
data.tar.gz: 3a2b1ef5b894d09c0f1e1a222363db7af962bc4dd2bb92bb23c02374fb50485d89b9c928b91d32834f8a30b2228827b2e5b84901061c68a3a1fe06915ac97ba3
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## [0.3.0] - 2021-09-06
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- Waterfall dialog support
|
14
|
+
- Waterfall sample
|
15
|
+
- user_state
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
- end_of_turn response
|
19
|
+
|
10
20
|
## [0.2.2-0.2.3] - 2021-09-06
|
11
21
|
|
12
22
|
### Added
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
##
|
2
2
|
*This Project is still underconstruction.*
|
3
3
|
|
4
|
+

|
5
|
+
|
4
6
|
# Bot Platform (Ruby Version)
|
5
7
|
|
6
8
|
A ruby based Bot platform to let developers to focus on bot's business logic ONLY. You can connect your bot to channels such as slack, teams, lineworks, chatwork and etc within only a few steps of settings(without coding) to use the same bot's logic. check the [supported bot channels](https://github.com/lifevar/bot-platform/blob/main/docs/channels.md#supported).
|
@@ -27,20 +29,49 @@ And then execute:
|
|
27
29
|
|
28
30
|
Or install it yourself as:
|
29
31
|
|
30
|
-
|
32
|
+
```bash
|
33
|
+
$ gem install bot_platform
|
34
|
+
```
|
31
35
|
|
32
36
|
## Usage
|
33
37
|
|
34
|
-
|
38
|
+
Documents are under-construction.
|
39
|
+
|
40
|
+
## Demos
|
41
|
+
|
42
|
+
### CLI
|
35
43
|
|
44
|
+
Clone this repository first. Go to the root directory and run:
|
36
45
|
|
37
|
-
|
46
|
+
```bash
|
47
|
+
bin/cli [bot-script]
|
48
|
+
```
|
49
|
+
|
50
|
+
echo sample:
|
51
|
+
|
52
|
+
```bash
|
53
|
+
$ bin/cli samples/echo.rb
|
54
|
+
```
|
38
55
|
|
39
|
-
|
56
|
+
simple dialog sample:
|
57
|
+
|
58
|
+
```bash
|
59
|
+
$ bin/cli samples/dialogs/dialog_simple.rb
|
60
|
+
```
|
61
|
+
|
62
|
+
waterfall dialog sample:
|
63
|
+
|
64
|
+
```bash
|
65
|
+
$ bin/cli samples/dialogs/waterfall_dialogs.rb
|
66
|
+
```
|
67
|
+
|
68
|
+
You can use 'exit' to quit bot shell. You can write your own bot scripts, be careful the file's name should be snake format.(We guess the class name from the file's name)
|
40
69
|
|
41
70
|
## Development
|
42
71
|
|
43
|
-
We're working on both console bot and Line Works bot nowtime.
|
72
|
+
We're working on both console bot and Line Works bot nowtime and has plan to develop to other channels.
|
73
|
+
|
74
|
+
It's welcome to share your channel's code to us.
|
44
75
|
|
45
76
|
## Contributing
|
46
77
|
|
Binary file
|
data/lib/bot_platform/asserts.rb
CHANGED
@@ -34,6 +34,10 @@ module BotPlatform
|
|
34
34
|
raise "dialog is aready added" if !hash[id.to_sym].nil?
|
35
35
|
end
|
36
36
|
|
37
|
+
def assert_waterfall_step_context_is_valid(ctx)
|
38
|
+
raise "Waterfall Step Context is not valid" if ctx.nil? || !(ctx.is_a? Dialogs::WaterfallStepContext)
|
39
|
+
end
|
40
|
+
|
37
41
|
def assert_activity_is_not_null(activity)
|
38
42
|
raise "activity cannot be null" if activity.nil?
|
39
43
|
end
|
@@ -52,15 +52,20 @@ module BotPlatform
|
|
52
52
|
return DialogResult.new :empty
|
53
53
|
end
|
54
54
|
|
55
|
-
def stop_dialog(result)
|
55
|
+
def stop_dialog(result=nil)
|
56
|
+
|
56
57
|
if @dialog_stack.any?
|
57
58
|
@dialog_stack.pop
|
58
59
|
end
|
59
|
-
|
60
|
+
|
61
|
+
instance = active_dialog
|
60
62
|
|
61
63
|
#previous dialog
|
62
|
-
if
|
63
|
-
dialog.
|
64
|
+
if !instance.nil?
|
65
|
+
dialog = @dialogs.find instance.dialog_id
|
66
|
+
if dialog
|
67
|
+
return dialog.resume self, DialogReason::END_CALLED, result
|
68
|
+
end
|
64
69
|
else
|
65
70
|
return DialogResult.new :complete, result
|
66
71
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module Dialogs
|
5
|
+
module Prompts
|
6
|
+
class ConfirmPrompt < Prompt
|
7
|
+
attr_reader :choice_options, :confirm_choices, :choice_defaults, :default_locale
|
8
|
+
|
9
|
+
def initialize(dialog_id, validator=nil, default_locale=nil)
|
10
|
+
super(dialog_id, validator)
|
11
|
+
@default_locale = default_locale
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_prompt(ctx, state, options, is_retry)
|
15
|
+
assert_turn_context_is_valid ctx
|
16
|
+
#assert_dialog_instance_state_is_valid state
|
17
|
+
assert_prompt_options_is_valid options
|
18
|
+
|
19
|
+
if is_retry && !options.retry_prompt.nil?
|
20
|
+
ctx.send_activity options.retry_prompt
|
21
|
+
else
|
22
|
+
ctx.send_activity options.prompt
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_recognize(ctx, state, options)
|
28
|
+
assert_turn_context_is_valid ctx
|
29
|
+
|
30
|
+
result = PromptRecognizerResult.new
|
31
|
+
if ctx.activity.type == BotPlatform::Activity::TYPES[:message]
|
32
|
+
message = ctx.activity.text
|
33
|
+
if !message.nil? && !message.empty?
|
34
|
+
case message.downcase
|
35
|
+
when 'y','yes','yeah', 'ok', 'okay'
|
36
|
+
result.succeeded = true
|
37
|
+
result.value = true
|
38
|
+
else
|
39
|
+
result.succeeded = true
|
40
|
+
result.value = false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
return result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module Dialogs
|
5
|
+
module Prompts
|
6
|
+
class NumberPrompt < Prompt
|
7
|
+
attr_reader :default_locale
|
8
|
+
|
9
|
+
def initialize(dialog_id, validator=nil, default_locale=nil)
|
10
|
+
super(dialog_id, validator)
|
11
|
+
@default_locale = default_locale
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_prompt(ctx, state, options, is_retry)
|
15
|
+
assert_turn_context_is_valid ctx
|
16
|
+
#assert_dialog_instance_state_is_valid state
|
17
|
+
assert_prompt_options_is_valid options
|
18
|
+
|
19
|
+
if is_retry && !options.retry_prompt.nil?
|
20
|
+
ctx.send_activity options.retry_prompt
|
21
|
+
else
|
22
|
+
ctx.send_activity options.prompt
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def on_recognize(ctx, state, options)
|
27
|
+
assert_turn_context_is_valid ctx
|
28
|
+
|
29
|
+
result = PromptRecognizerResult.new
|
30
|
+
if ctx.activity.type == BotPlatform::Activity::TYPES[:message]
|
31
|
+
message = ctx.activity.text
|
32
|
+
if !message.nil? && !message.empty? && message =~ /\A[-+]?[0-9]*\.?[0-9]+\Z/
|
33
|
+
result.succeeded = true
|
34
|
+
result.value = message.to_i
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
return result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -20,7 +20,7 @@ module BotPlatform
|
|
20
20
|
state[:state] = {}
|
21
21
|
|
22
22
|
on_prompt(dc.turn_context, state[:state], state[:options], false)
|
23
|
-
return BotPlatform::Dialogs::DialogResult.new :
|
23
|
+
return BotPlatform::Dialogs::DialogResult.new :end_of_turn
|
24
24
|
end
|
25
25
|
|
26
26
|
def continue(dc)
|
@@ -49,15 +49,17 @@ module BotPlatform
|
|
49
49
|
if is_valid
|
50
50
|
return dc.stop_dialog(recognized.value)
|
51
51
|
else
|
52
|
-
|
52
|
+
on_prompt(dc.turn_context, state, options, true)
|
53
53
|
end
|
54
|
+
|
55
|
+
return BotPlatform::Dialogs::DialogResult.new :end_of_turn
|
54
56
|
end
|
55
57
|
|
56
58
|
def resume(dc, result=null)
|
57
59
|
assert_dialog_context_is_valid dc
|
58
60
|
|
59
61
|
reprompt(dc.turn_context, dc.active_dialog)
|
60
|
-
return BotPlatform::Dialogs::DialogResult.new :
|
62
|
+
return BotPlatform::Dialogs::DialogResult.new :end_of_turn
|
61
63
|
end
|
62
64
|
|
63
65
|
def repromp(ttx, instance)
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
module BotPlatform
|
7
|
+
module Dialogs
|
8
|
+
class WaterfallDialog < Dialog
|
9
|
+
include BotPlatform::Asserts
|
10
|
+
|
11
|
+
LOGLEVELS = %w[DEBUG INFO WARN ERROR FATAL UNKNOWN].freeze
|
12
|
+
attr_reader :steps
|
13
|
+
|
14
|
+
def initialize(dialog_id, actions)
|
15
|
+
super(dialog_id)
|
16
|
+
@steps = actions.nil? ? [] : actions
|
17
|
+
@logger = Logger.new(STDOUT)
|
18
|
+
|
19
|
+
level ||= LOGLEVELS.index ENV.fetch("BOT_LOG_LEVEL","WARN")
|
20
|
+
level ||= Logger::WARN
|
21
|
+
@logger.level = level
|
22
|
+
end
|
23
|
+
|
24
|
+
def version
|
25
|
+
return "#{@id}:#{@steps.count}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_step(step)
|
29
|
+
@steps.push step
|
30
|
+
return self
|
31
|
+
end
|
32
|
+
|
33
|
+
def start(dc, options=nil)
|
34
|
+
assert_dialog_context_is_valid dc
|
35
|
+
|
36
|
+
state = dc.active_dialog.state
|
37
|
+
instance_id = SecureRandom.uuid
|
38
|
+
|
39
|
+
state[:options] = options
|
40
|
+
state[:values] = {}
|
41
|
+
state[:instace_id] = instance_id
|
42
|
+
|
43
|
+
# first step
|
44
|
+
run_step(dc, 0, DialogReason::BEGIN_CALLED, nil)
|
45
|
+
end
|
46
|
+
|
47
|
+
def continue(dc)
|
48
|
+
@logger.debug "continue dc:#{dc.inspect}"
|
49
|
+
assert_dialog_context_is_valid dc
|
50
|
+
|
51
|
+
if dc.turn_context.activity.type != Activity::TYPES[:message]
|
52
|
+
return DialogResult.new :complete
|
53
|
+
end
|
54
|
+
|
55
|
+
return resume(dc, DialogReason::CONTINUE_CALLED, dc.turn_context.activity.text)
|
56
|
+
end
|
57
|
+
|
58
|
+
def resume(dc, reason, result)
|
59
|
+
assert_dialog_context_is_valid dc
|
60
|
+
|
61
|
+
state = dc.active_dialog.state
|
62
|
+
|
63
|
+
index = state[:step_index]
|
64
|
+
run_step(dc, index+1, reason, result)
|
65
|
+
end
|
66
|
+
|
67
|
+
def stop(turn_ctx, instance, reason)
|
68
|
+
assert_turn_context_is_valid turn_ctx
|
69
|
+
assert_dialog_instance_is_valid instance
|
70
|
+
assert_dialog_reason_is_valid reason
|
71
|
+
|
72
|
+
if reason == DialogReason::CANCEL_CALLED
|
73
|
+
state = instance.state.dup
|
74
|
+
index = state[:step_index]
|
75
|
+
step_name = waterfall_step_name(index)
|
76
|
+
instance_id = state[:instance_id]
|
77
|
+
|
78
|
+
logger.debug {dialog_id:@id, step_name:step_name, instance_id:instance_id}.to_json
|
79
|
+
elsif reason == DialogReason::END_CALLED
|
80
|
+
state = instance.state.dup
|
81
|
+
index = state[:step_index]
|
82
|
+
instance_id = state[:instance_id]
|
83
|
+
|
84
|
+
logger.debug {dialog_id:@id, instance_id:instance_id}.to_json
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
def on_step(step_ctx)
|
90
|
+
step_name = waterfall_step_name(step_ctx.index)
|
91
|
+
instance_id = step_ctx.active_dialog.state[:instance_id]
|
92
|
+
return @steps[step_ctx.index][:method].call step_ctx
|
93
|
+
end
|
94
|
+
|
95
|
+
def run_step(dc, index, reason, result)
|
96
|
+
assert_dialog_context_is_valid dc
|
97
|
+
|
98
|
+
if index < @steps.count
|
99
|
+
state = dc.active_dialog.state
|
100
|
+
state[:step_index] = index
|
101
|
+
|
102
|
+
options = state[:options]
|
103
|
+
values = state[:values]
|
104
|
+
step_context = WaterfallStepContext.new self, dc, options, values, index, reason, result
|
105
|
+
|
106
|
+
return on_step(step_context)
|
107
|
+
end
|
108
|
+
|
109
|
+
return dc.end_dialog(result)
|
110
|
+
end
|
111
|
+
|
112
|
+
def waterfall_step_name(index)
|
113
|
+
step_name = @steps[index][:name]
|
114
|
+
|
115
|
+
if step_name.nil? || step_name.empty? || step_name.include?("<")
|
116
|
+
step_name = "Step#{index+1}of#{@steps.count}"
|
117
|
+
end
|
118
|
+
|
119
|
+
step_name
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module Dialogs
|
5
|
+
class WaterfallStepContext < DialogContext
|
6
|
+
attr_reader :parent_waterfall_dialog, :index, :options,:result, :reason, :values
|
7
|
+
attr_accessor :next_called
|
8
|
+
|
9
|
+
def initialize(parent, dc, options, values, index, reason, result)
|
10
|
+
super(dc.dialogs, dc.turn_context, DialogState.new(dc.dialog_stack))
|
11
|
+
@parent_waterfall_dialog = parent
|
12
|
+
@next_called = false
|
13
|
+
@options = options
|
14
|
+
@index = index
|
15
|
+
@reason = reason
|
16
|
+
@result = result
|
17
|
+
@values = values
|
18
|
+
end
|
19
|
+
|
20
|
+
def next(result=nil)
|
21
|
+
raise "cannot use next() twice." if @next_called
|
22
|
+
|
23
|
+
@next_called = true
|
24
|
+
return @parent_waterfall_dialog.resume(self, DialogReason::NEXT_CALLED, result)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/bot_platform/dialogs.rb
CHANGED
@@ -4,12 +4,21 @@ require_relative 'dialogs/dialog_instance'
|
|
4
4
|
require_relative 'dialogs/dialog_result'
|
5
5
|
require_relative 'dialogs/dialog_set'
|
6
6
|
require_relative 'dialogs/dialog_state'
|
7
|
+
require_relative 'dialogs/dialog_reason'
|
7
8
|
|
8
9
|
require_relative 'dialogs/prompts/prompt'
|
9
10
|
require_relative 'dialogs/prompts/prompt_options'
|
11
|
+
require_relative 'dialogs/prompts/confirm_prompt'
|
12
|
+
require_relative 'dialogs/prompts/number_prompt'
|
10
13
|
require_relative 'dialogs/prompts/text_prompt'
|
11
14
|
require_relative 'dialogs/prompts/prompt_recognizer_result'
|
12
15
|
|
16
|
+
|
17
|
+
require_relative 'dialogs/waterfall_dialog'
|
18
|
+
require_relative 'dialogs/waterfall_step'
|
19
|
+
require_relative 'dialogs/waterfall_step_context'
|
20
|
+
|
21
|
+
|
13
22
|
module BotPlatform
|
14
23
|
module Dialogs
|
15
24
|
|
@@ -11,6 +11,15 @@ module BotPlatform
|
|
11
11
|
@service_key = service_key
|
12
12
|
end
|
13
13
|
|
14
|
+
def create_property(key)
|
15
|
+
@storage.data[key.to_sym] = {}
|
16
|
+
return @storage.data[key.to_sym]
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_property(key)
|
20
|
+
return @storage.data[key.to_sym]
|
21
|
+
end
|
22
|
+
|
14
23
|
def save_changes(turn_context, force=false)
|
15
24
|
assert_turn_context_is_valid turn_context
|
16
25
|
|
@@ -1 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module State
|
5
|
+
class UserState < BotState
|
6
|
+
def initialize(storage)
|
7
|
+
super(storage, "user_state")
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_storage_key(turn_context)
|
11
|
+
channel_id = turn_context.activity.channel_id
|
12
|
+
user_id = turn_context.from.user_id
|
13
|
+
"#{channel_id}/users/#{user_id}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/bot_platform/version.rb
CHANGED
data/lib/bot_platform.rb
CHANGED
@@ -12,6 +12,7 @@ require_relative "bot_platform/storage/storageable"
|
|
12
12
|
require_relative "bot_platform/storage/memory_storage"
|
13
13
|
require_relative "bot_platform/state/bot_state"
|
14
14
|
require_relative "bot_platform/state/conversation_state"
|
15
|
+
require_relative "bot_platform/state/user_state"
|
15
16
|
|
16
17
|
module BotPlatform
|
17
18
|
class Error < StandardError; end
|
@@ -12,12 +12,13 @@ class DialogSimple
|
|
12
12
|
def on_turn(ctx)
|
13
13
|
dialog_ctx = @dialogs.create_dialog_context(ctx)
|
14
14
|
results = dialog_ctx.continue_dialog
|
15
|
-
|
16
|
-
options.prompt = BotPlatform::MessageFactory.Text("Input your name please:")
|
15
|
+
|
17
16
|
if results.status == :empty
|
18
17
|
dialog_ctx.prompt(
|
19
18
|
"name",
|
20
|
-
|
19
|
+
BotPlatform::Dialogs::Prompts::PromptOptions.new(
|
20
|
+
prompt: BotPlatform::MessageFactory.Text("Input your name please:")
|
21
|
+
)
|
21
22
|
)
|
22
23
|
elsif results.status == :complete
|
23
24
|
unless results.result.nil?
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'waterfall_steps'
|
2
|
+
class WaterfallDialogs
|
3
|
+
include Waterfall::Steps
|
4
|
+
|
5
|
+
attr_accessor :dialogs
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
storage = BotPlatform::Storage::MemoryStorage.instance
|
9
|
+
@user_state = BotPlatform::State::UserState.new storage
|
10
|
+
profile = @user_state.create_property("user_profile")
|
11
|
+
@dialogs = BotPlatform::Dialogs::DialogSet.new
|
12
|
+
steps = [
|
13
|
+
{name:'request-name', method:->(ctx) { request_name_step(ctx) }},
|
14
|
+
{name: 'confirm_asking_age_step', method:->(ctx) { confirm_asking_age_step(ctx, profile) }},
|
15
|
+
{name: 'request_age_step', method:->(ctx) { request_age_step(ctx) }},
|
16
|
+
{name: 'confirm_register_step', method: ->(ctx) { confirm_register_step(ctx, profile) }},
|
17
|
+
{name: 'summary', method: ->(ctx) { summary_step(ctx) }},
|
18
|
+
]
|
19
|
+
@dialogs.add BotPlatform::Dialogs::WaterfallDialog.new("profile", steps)
|
20
|
+
@dialogs.add BotPlatform::Dialogs::Prompts::TextPrompt.new("name")
|
21
|
+
@dialogs.add BotPlatform::Dialogs::Prompts::NumberPrompt.new("age")
|
22
|
+
@dialogs.add BotPlatform::Dialogs::Prompts::ConfirmPrompt.new("confirm")
|
23
|
+
|
24
|
+
@conversation_state = BotPlatform::State::ConversationState.new storage
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_turn(ctx)
|
28
|
+
if ctx.activity.type == BotPlatform::Activity::TYPES[:message]
|
29
|
+
dialog_ctx = @dialogs.create_dialog_context(ctx)
|
30
|
+
|
31
|
+
# run continue is there're some existed dialogs
|
32
|
+
results = dialog_ctx.continue_dialog
|
33
|
+
|
34
|
+
# there's no existed dialog
|
35
|
+
if results.status == :empty
|
36
|
+
dialog_ctx.start_dialog "profile", nil
|
37
|
+
elsif results.status == :complete
|
38
|
+
user_profile = @user_state.get_property(:user_profile)
|
39
|
+
end
|
40
|
+
|
41
|
+
# save user_profile and dialog_state
|
42
|
+
@user_state.save_changes(ctx, false)
|
43
|
+
@conversation_state.save_changes(ctx, false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Waterfall
|
2
|
+
module Steps
|
3
|
+
def request_name_step(step_ctx)
|
4
|
+
return step_ctx.prompt(
|
5
|
+
"name",
|
6
|
+
BotPlatform::Dialogs::Prompts::PromptOptions.new(
|
7
|
+
prompt:BotPlatform::MessageFactory.Text("Input your name please.")
|
8
|
+
)
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def confirm_asking_age_step(step_ctx, user_profile)
|
13
|
+
profile = user_profile
|
14
|
+
profile[:name] = step_ctx.result
|
15
|
+
return step_ctx.prompt(
|
16
|
+
"confirm",
|
17
|
+
BotPlatform::Dialogs::Prompts::PromptOptions.new(
|
18
|
+
prompt:BotPlatform::MessageFactory.Text("May I ask your age?")
|
19
|
+
)
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def request_age_step(step_ctx)
|
24
|
+
if step_ctx.result
|
25
|
+
step_ctx.prompt("age", BotPlatform::Dialogs::Prompts::PromptOptions.new(prompt:BotPlatform::MessageFactory.Text("Input your age please")))
|
26
|
+
else
|
27
|
+
step_ctx.next(-1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def confirm_register_step(step_ctx, profile)
|
32
|
+
age = step_ctx.result.to_i
|
33
|
+
|
34
|
+
profile[:age] = '(unknown)'
|
35
|
+
profile[:age] = age if age != -1
|
36
|
+
|
37
|
+
prompt = "Register user profile as below. Is it okay?\n Name:#{profile[:name]}\n Age: #{profile[:age]}"
|
38
|
+
step_ctx.prompt("confirm", BotPlatform::Dialogs::Prompts::PromptOptions.new(prompt:BotPlatform::MessageFactory.Text(prompt)))
|
39
|
+
end
|
40
|
+
|
41
|
+
def summary_step(step_ctx)
|
42
|
+
if step_ctx.result
|
43
|
+
step_ctx.turn_context.send_message "Profile saved."
|
44
|
+
else
|
45
|
+
step_ctx.turn_context.send_message "Profile registration has been canceled."
|
46
|
+
end
|
47
|
+
step_ctx.stop_dialog
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bot_platform
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ningfeng Yang
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: One bot, multiple channels supported
|
14
14
|
email:
|
@@ -41,6 +41,7 @@ files:
|
|
41
41
|
- bot_platform.gemspec
|
42
42
|
- docs/channels.md
|
43
43
|
- exe/welcome
|
44
|
+
- images/bot-platform.png
|
44
45
|
- lib/bot_platform.rb
|
45
46
|
- lib/bot_platform/activity.rb
|
46
47
|
- lib/bot_platform/adapter.rb
|
@@ -65,13 +66,19 @@ files:
|
|
65
66
|
- lib/bot_platform/dialogs/dialog.rb
|
66
67
|
- lib/bot_platform/dialogs/dialog_context.rb
|
67
68
|
- lib/bot_platform/dialogs/dialog_instance.rb
|
69
|
+
- lib/bot_platform/dialogs/dialog_reason.rb
|
68
70
|
- lib/bot_platform/dialogs/dialog_result.rb
|
69
71
|
- lib/bot_platform/dialogs/dialog_set.rb
|
70
72
|
- lib/bot_platform/dialogs/dialog_state.rb
|
73
|
+
- lib/bot_platform/dialogs/prompts/confirm_prompt.rb
|
74
|
+
- lib/bot_platform/dialogs/prompts/number_prompt.rb
|
71
75
|
- lib/bot_platform/dialogs/prompts/prompt.rb
|
72
76
|
- lib/bot_platform/dialogs/prompts/prompt_options.rb
|
73
77
|
- lib/bot_platform/dialogs/prompts/prompt_recognizer_result.rb
|
74
78
|
- lib/bot_platform/dialogs/prompts/text_prompt.rb
|
79
|
+
- lib/bot_platform/dialogs/waterfall_dialog.rb
|
80
|
+
- lib/bot_platform/dialogs/waterfall_step.rb
|
81
|
+
- lib/bot_platform/dialogs/waterfall_step_context.rb
|
75
82
|
- lib/bot_platform/message_factory.rb
|
76
83
|
- lib/bot_platform/state/bot_state.rb
|
77
84
|
- lib/bot_platform/state/conversation_state.rb
|
@@ -83,6 +90,8 @@ files:
|
|
83
90
|
- lib/bot_platform/turn_context.rb
|
84
91
|
- lib/bot_platform/version.rb
|
85
92
|
- samples/dialogs/dialog_simple.rb
|
93
|
+
- samples/dialogs/waterfall_dialogs.rb
|
94
|
+
- samples/dialogs/waterfall_steps.rb
|
86
95
|
- samples/echo.rb
|
87
96
|
homepage: https://github.com/lifevar/bot-platform
|
88
97
|
licenses:
|