bot_platform 0.1.0 → 0.2.3
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/.idea/.gitignore +8 -0
- data/.idea/bot_platform.iml +317 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile.lock +1 -1
- data/LICENSE +21 -0
- data/README.md +21 -9
- data/bin/cli +34 -0
- data/bot_platform.gemspec +3 -2
- data/docs/channels.md +13 -0
- data/lib/bot_platform/activity.rb +32 -0
- data/lib/bot_platform/adapter.rb +87 -0
- data/lib/bot_platform/asserts.rb +69 -0
- data/lib/bot_platform/boot.rb +12 -0
- data/lib/bot_platform/channels/base.rb +26 -0
- data/lib/bot_platform/channels/chatwork.rb +1 -0
- data/lib/bot_platform/channels/console.rb +60 -0
- data/lib/bot_platform/channels/facebook.rb +1 -0
- data/lib/bot_platform/channels/line.rb +1 -0
- data/lib/bot_platform/channels/lineworks.rb +102 -0
- data/lib/bot_platform/channels/skype.rb +1 -0
- data/lib/bot_platform/channels/skype_for_business.rb +1 -0
- data/lib/bot_platform/channels/slack.rb +15 -0
- data/lib/bot_platform/channels/teams.rb +15 -0
- data/lib/bot_platform/channels/web.rb +15 -0
- data/lib/bot_platform/channels/wechat.rb +1 -0
- data/lib/bot_platform/channels.rb +9 -0
- data/lib/bot_platform/cli.rb +97 -0
- data/lib/bot_platform/conversation_state.rb +32 -0
- data/lib/bot_platform/dialogs/dialog.rb +48 -0
- data/lib/bot_platform/dialogs/dialog_context.rb +104 -0
- data/lib/bot_platform/dialogs/dialog_instance.rb +15 -0
- data/lib/bot_platform/dialogs/dialog_result.rb +22 -0
- data/lib/bot_platform/dialogs/dialog_set.rb +38 -0
- data/lib/bot_platform/dialogs/dialog_state.rb +11 -0
- data/lib/bot_platform/dialogs/prompts/prompt.rb +84 -0
- data/lib/bot_platform/dialogs/prompts/prompt_options.rb +12 -0
- data/lib/bot_platform/dialogs/prompts/prompt_recognizer_result.rb +16 -0
- data/lib/bot_platform/dialogs/prompts/text_prompt.rb +36 -0
- data/lib/bot_platform/dialogs.rb +17 -0
- data/lib/bot_platform/message_factory.rb +9 -0
- data/lib/bot_platform/state/bot_state.rb +21 -0
- data/lib/bot_platform/state/conversation_state.rb +17 -0
- data/lib/bot_platform/state/user_state.rb +1 -0
- data/lib/bot_platform/storage/memory_storage.rb +51 -0
- data/lib/bot_platform/storage/mysql_storage.rb +1 -0
- data/lib/bot_platform/storage/redis_storage.rb +1 -0
- data/lib/bot_platform/storage/storageable.rb +33 -0
- data/lib/bot_platform/turn_context.rb +105 -0
- data/lib/bot_platform/version.rb +1 -1
- data/lib/bot_platform.rb +11 -0
- data/samples/dialogs/dialog_simple.rb +29 -0
- data/samples/echo.rb +5 -0
- metadata +56 -5
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module Dialogs
|
5
|
+
module Prompts
|
6
|
+
class Prompt < Dialog
|
7
|
+
attr_reader :validator
|
8
|
+
|
9
|
+
def initialize(dialog_id, validtor=nil)
|
10
|
+
super(dialog_id)
|
11
|
+
@validator = validator
|
12
|
+
end
|
13
|
+
|
14
|
+
def start(dc, options)
|
15
|
+
assert_dialog_context_is_valid dc
|
16
|
+
assert_prompt_options_is_valid options
|
17
|
+
|
18
|
+
state = dc.active_dialog.state
|
19
|
+
state[:options] = options
|
20
|
+
state[:state] = {}
|
21
|
+
|
22
|
+
on_prompt(dc.turn_context, state[:state], state[:options], false)
|
23
|
+
return BotPlatform::Dialogs::DialogResult.new :complete
|
24
|
+
end
|
25
|
+
|
26
|
+
def continue(dc)
|
27
|
+
assert_dialog_context_is_valid dc
|
28
|
+
|
29
|
+
if dc.turn_context.activity.type != BotPlatform::Activity::TYPES[:message]
|
30
|
+
# do nothing
|
31
|
+
return BotPlatform::Dialogs::DialogResult.new :complete
|
32
|
+
end
|
33
|
+
|
34
|
+
instance = dc.active_dialog
|
35
|
+
state = instance.state[:state]
|
36
|
+
options = instance.state[:options]
|
37
|
+
|
38
|
+
recognized = on_recognize(dc.turn_context, state, options)
|
39
|
+
|
40
|
+
is_valid = false
|
41
|
+
|
42
|
+
if !@validator.nil?
|
43
|
+
prompt_validator_ctx = PromptValidatorContext.new dc.turn_context, recognized, state, options
|
44
|
+
is_valid = @validator.send(prompt_validator_ctx)
|
45
|
+
elsif recognized.succeeded
|
46
|
+
is_valid = true
|
47
|
+
end
|
48
|
+
|
49
|
+
if is_valid
|
50
|
+
return dc.stop_dialog(recognized.value)
|
51
|
+
else
|
52
|
+
return on_prompt(dc.turn_context, state, options, true)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def resume(dc, result=null)
|
57
|
+
assert_dialog_context_is_valid dc
|
58
|
+
|
59
|
+
reprompt(dc.turn_context, dc.active_dialog)
|
60
|
+
return BotPlatform::Dialogs::DialogResult.new :complete
|
61
|
+
end
|
62
|
+
|
63
|
+
def repromp(ttx, instance)
|
64
|
+
assert_turn_context_is_valid ttx
|
65
|
+
assert_dialog_instance_is_valid instance
|
66
|
+
|
67
|
+
state = instace.state[:state]
|
68
|
+
options = instance.state[:options]
|
69
|
+
|
70
|
+
on_prompt(ttx, state, options, false)
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_prompt(turn_context, state, options, is_retry)
|
74
|
+
raise "not implemented(abstrct in super)"
|
75
|
+
end
|
76
|
+
|
77
|
+
def on_recognize(turn_context, state, options, is_retry)
|
78
|
+
raise "not implemented(abstrct in super)"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module Dialogs
|
5
|
+
module Prompts
|
6
|
+
class TextPrompt < Prompt
|
7
|
+
def on_prompt(ctx, state, options, is_retry)
|
8
|
+
assert_turn_context_is_valid ctx
|
9
|
+
#assert_dialog_instance_state_is_valid state
|
10
|
+
assert_prompt_options_is_valid options
|
11
|
+
|
12
|
+
if is_retry && !options.retry_prompt.nil?
|
13
|
+
ctx.send_activity options.retry_prompt
|
14
|
+
else
|
15
|
+
ctx.send_activity options.prompt
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_recognize(ctx, state, options)
|
20
|
+
assert_turn_context_is_valid ctx
|
21
|
+
|
22
|
+
result = PromptRecognizerResult.new
|
23
|
+
if ctx.activity.type == BotPlatform::Activity::TYPES[:message]
|
24
|
+
message = ctx.activity.text
|
25
|
+
unless message.nil? || message.empty?
|
26
|
+
result.succeeded = true
|
27
|
+
result.value = message
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
return result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'dialogs/dialog'
|
2
|
+
require_relative 'dialogs/dialog_context'
|
3
|
+
require_relative 'dialogs/dialog_instance'
|
4
|
+
require_relative 'dialogs/dialog_result'
|
5
|
+
require_relative 'dialogs/dialog_set'
|
6
|
+
require_relative 'dialogs/dialog_state'
|
7
|
+
|
8
|
+
require_relative 'dialogs/prompts/prompt'
|
9
|
+
require_relative 'dialogs/prompts/prompt_options'
|
10
|
+
require_relative 'dialogs/prompts/text_prompt'
|
11
|
+
require_relative 'dialogs/prompts/prompt_recognizer_result'
|
12
|
+
|
13
|
+
module BotPlatform
|
14
|
+
module Dialogs
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module State
|
5
|
+
class BotState
|
6
|
+
include BotPlatform::Asserts
|
7
|
+
|
8
|
+
attr_accessor :storage, :service_key
|
9
|
+
def initialize(storage, service_key)
|
10
|
+
@storage = storage
|
11
|
+
@service_key = service_key
|
12
|
+
end
|
13
|
+
|
14
|
+
def save_changes(turn_context, force=false)
|
15
|
+
assert_turn_context_is_valid turn_context
|
16
|
+
|
17
|
+
#TODO:
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module State
|
5
|
+
class ConversationState < BotState
|
6
|
+
def initialize(storage)
|
7
|
+
super(storage, "conversation_state")
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_storage_key(turn_context)
|
11
|
+
channel_id = turn_context.activity.channel_id
|
12
|
+
conversation_id = turn_context.conversation.id
|
13
|
+
"#{channel_id}/conversations/#{conversation_id}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module BotPlatform
|
6
|
+
module Storage
|
7
|
+
class MemoryStorage
|
8
|
+
include Singleton
|
9
|
+
include Storageable
|
10
|
+
|
11
|
+
attr_accessor :data, :locker
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@locker = Mutex::new
|
15
|
+
@data = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def read(keys)
|
19
|
+
new_hash = {}
|
20
|
+
@locker.synchronize do
|
21
|
+
keys.each do |key|
|
22
|
+
if @data.key?(key)
|
23
|
+
k = key.to_sym
|
24
|
+
new_hash[k] = @data[k]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
return new_hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def write(changes)
|
32
|
+
@locker.synchronize do
|
33
|
+
changes.each do |change|
|
34
|
+
@data[change.key.to_sym] = change.value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def getState(context)
|
40
|
+
user_id = context.from[:user_id]
|
41
|
+
room_id = context.from[:room_id] || ""
|
42
|
+
# FIXME: room_id appear and disappear
|
43
|
+
#key = "#{user_id}@#{room_id}"
|
44
|
+
key = "#{user_id}".intern
|
45
|
+
@data[key] = ConversationState.new(key) if @data[key].nil?
|
46
|
+
return @data[key]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
module Storage
|
5
|
+
module Storageable
|
6
|
+
attr_accessor :data, :_user_state, :coversation_state, :dialog_state
|
7
|
+
|
8
|
+
def set(key, value, exipred=false)
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(key)
|
12
|
+
end
|
13
|
+
|
14
|
+
def del(key)
|
15
|
+
end
|
16
|
+
|
17
|
+
def read(keys)
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(changes)
|
21
|
+
end
|
22
|
+
|
23
|
+
def user_state
|
24
|
+
get(:_user_state)
|
25
|
+
end
|
26
|
+
|
27
|
+
def user_state=(state)
|
28
|
+
set(:_user_state, state)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BotPlatform
|
4
|
+
class TurnContext
|
5
|
+
include Asserts
|
6
|
+
|
7
|
+
attr_reader :adpter, #元のアダプター情報
|
8
|
+
:activity, # ユーザーからの要求(incoming)
|
9
|
+
:channel_id,
|
10
|
+
:from
|
11
|
+
|
12
|
+
attr_accessor :state, #コンテキストに登録されたサービスを保持
|
13
|
+
:responded, # 応答済フラグ
|
14
|
+
:locale,
|
15
|
+
:buffered_reply_activities,
|
16
|
+
:turn_state, # コンテキストに登録されたサービスを保持
|
17
|
+
:_on_send_activities,
|
18
|
+
:_on_update_activities,
|
19
|
+
:_on_delete_activities
|
20
|
+
|
21
|
+
def initialize(adapter, activity)
|
22
|
+
@adapter = adapter
|
23
|
+
@activity = activity # incoming activity
|
24
|
+
@from = activity.from
|
25
|
+
@channel_id = activity.channel_id
|
26
|
+
@responded = false
|
27
|
+
@locale = "ja"
|
28
|
+
@_on_send_activities = []
|
29
|
+
@_on_update_activities = []
|
30
|
+
@_on_delete_activities = []
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_on_send_activities(activity_handler)
|
35
|
+
@_on_send_activities << activity_handler
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_on_update_activities(activity_handler)
|
40
|
+
@_on_update_activities << activity_handler
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_on_delete_activits(activity_handler)
|
45
|
+
@_on_delete_activities << activity_handler
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.dup_context(context, activity)
|
50
|
+
ctx = TurnContext.new context.adapter, activity
|
51
|
+
ctx.state = context.state
|
52
|
+
ctx.responded = context.responded
|
53
|
+
if context.is_a?(TurnContext)
|
54
|
+
ctx.buffered_reply_activities = context.buffered_reply_activities
|
55
|
+
# keep private middleware pipeline hooks.
|
56
|
+
ctx._on_send_activities = context._on_send_activities
|
57
|
+
ctx._on_update_activity = context._on_update_activity
|
58
|
+
ctx._on_delete_activity = context._on_delete_activity
|
59
|
+
end
|
60
|
+
return ctx
|
61
|
+
end
|
62
|
+
|
63
|
+
def send_message(text)
|
64
|
+
activity_to_send = Activity.new(Activity::TYPES[:message], {text: text})
|
65
|
+
send_activity(activity_to_send)
|
66
|
+
end
|
67
|
+
|
68
|
+
def send_confirm(text,prefix="")
|
69
|
+
activity_to_send = Activity.new(Activity::TYPES[:confirm], {text: text, prefix: prefix})
|
70
|
+
send_activity(activity_to_send)
|
71
|
+
end
|
72
|
+
|
73
|
+
def send_options(caption, prefix, options)
|
74
|
+
activity_to_send = Activity.new(Activity::TYPES[:options], {text: caption, options: options, prefix: prefix})
|
75
|
+
send_activity(activity_to_send)
|
76
|
+
end
|
77
|
+
|
78
|
+
def send_image(preview_url, resource_url)
|
79
|
+
activity_to_send = Activity.new(Activity::TYPES[:image], {resource_url: resource_url, preview_url: preview_url})
|
80
|
+
send_activity(activity_to_send)
|
81
|
+
end
|
82
|
+
|
83
|
+
def send_content(content)
|
84
|
+
activity_to_send = Activity.new(Activity::TYPES[:carousel], {
|
85
|
+
content: content, to: @activity.from
|
86
|
+
})
|
87
|
+
send_activity(activity_to_send)
|
88
|
+
end
|
89
|
+
|
90
|
+
def send_activity(activity)
|
91
|
+
activity.to = @activity.from
|
92
|
+
send_activities([activity])
|
93
|
+
end
|
94
|
+
|
95
|
+
# Sends a set of activities to the sender of the incoming activity.
|
96
|
+
def send_activities(activities)
|
97
|
+
assert_activity_is_not_null activities
|
98
|
+
assert_activity_is_not_null activities[0]
|
99
|
+
|
100
|
+
@adapter.send_activities(self, activities)
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
data/lib/bot_platform/version.rb
CHANGED
data/lib/bot_platform.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "bot_platform/version"
|
4
|
+
require_relative "bot_platform/activity"
|
5
|
+
require_relative "bot_platform/adapter"
|
6
|
+
require_relative "bot_platform/asserts"
|
7
|
+
require_relative "bot_platform/message_factory"
|
8
|
+
require_relative "bot_platform/turn_context"
|
9
|
+
require_relative "bot_platform/channels"
|
10
|
+
require_relative "bot_platform/dialogs"
|
11
|
+
require_relative "bot_platform/storage/storageable"
|
12
|
+
require_relative "bot_platform/storage/memory_storage"
|
13
|
+
require_relative "bot_platform/state/bot_state"
|
14
|
+
require_relative "bot_platform/state/conversation_state"
|
4
15
|
|
5
16
|
module BotPlatform
|
6
17
|
class Error < StandardError; end
|