charyf 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +154 -0
- data/LICENSE.txt +21 -0
- data/README.md +18 -0
- data/Rakefile +6 -0
- data/bin/charyf-debug +7 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/charyf.gemspec +48 -0
- data/exe/charyf +4 -0
- data/lib/charyf/deps.rb +9 -0
- data/lib/charyf/engine/all.rb +22 -0
- data/lib/charyf/engine/charyf.rb +5 -0
- data/lib/charyf/engine/context.rb +61 -0
- data/lib/charyf/engine/controller/actions.rb +29 -0
- data/lib/charyf/engine/controller/controller.rb +62 -0
- data/lib/charyf/engine/controller/conversation.rb +58 -0
- data/lib/charyf/engine/controller/helpers.rb +38 -0
- data/lib/charyf/engine/controller/renderers.rb +103 -0
- data/lib/charyf/engine/dispatcher/base.rb +121 -0
- data/lib/charyf/engine/dispatcher/default.rb +60 -0
- data/lib/charyf/engine/intent/intent.rb +54 -0
- data/lib/charyf/engine/intent/processors/dummy.rb +30 -0
- data/lib/charyf/engine/intent/processors/helpers.rb +32 -0
- data/lib/charyf/engine/intent/processors/processor.rb +56 -0
- data/lib/charyf/engine/interface/interface.rb +35 -0
- data/lib/charyf/engine/interface/program.rb +59 -0
- data/lib/charyf/engine/request.rb +32 -0
- data/lib/charyf/engine/response.rb +41 -0
- data/lib/charyf/engine/session/processors/default.rb +42 -0
- data/lib/charyf/engine/session/processors/processor.rb +39 -0
- data/lib/charyf/engine/session/session.rb +68 -0
- data/lib/charyf/engine/skill/info.rb +24 -0
- data/lib/charyf/engine/skill/routing.rb +57 -0
- data/lib/charyf/engine/skill/skill.rb +40 -0
- data/lib/charyf/engine.rb +3 -0
- data/lib/charyf/support/all.rb +4 -0
- data/lib/charyf/support/hash.rb +43 -0
- data/lib/charyf/support/object.rb +7 -0
- data/lib/charyf/support/string.rb +94 -0
- data/lib/charyf/support/string_inquirer.rb +17 -0
- data/lib/charyf/support.rb +1 -0
- data/lib/charyf/utils/all.rb +13 -0
- data/lib/charyf/utils/app_engine/extensions.rb +21 -0
- data/lib/charyf/utils/app_engine.rb +24 -0
- data/lib/charyf/utils/app_loader.rb +38 -0
- data/lib/charyf/utils/application/bootstrap.rb +176 -0
- data/lib/charyf/utils/application/configuration.rb +51 -0
- data/lib/charyf/utils/application.rb +131 -0
- data/lib/charyf/utils/charyf.rb +44 -0
- data/lib/charyf/utils/cli.rb +14 -0
- data/lib/charyf/utils/command/actions.rb +24 -0
- data/lib/charyf/utils/command/base.rb +138 -0
- data/lib/charyf/utils/command/behavior.rb +81 -0
- data/lib/charyf/utils/command/environment_argument.rb +40 -0
- data/lib/charyf/utils/command.rb +106 -0
- data/lib/charyf/utils/commands/all.rb +6 -0
- data/lib/charyf/utils/commands/application/application_command.rb +21 -0
- data/lib/charyf/utils/commands/cli/cli_command.rb +115 -0
- data/lib/charyf/utils/commands/console/console_command.rb +77 -0
- data/lib/charyf/utils/commands/destroy/destroy_command.rb +26 -0
- data/lib/charyf/utils/commands/generate/generate_command.rb +31 -0
- data/lib/charyf/utils/commands/help/USAGE +9 -0
- data/lib/charyf/utils/commands/help/help.rb +20 -0
- data/lib/charyf/utils/commands.rb +15 -0
- data/lib/charyf/utils/configuration.rb +36 -0
- data/lib/charyf/utils/error_handler.rb +26 -0
- data/lib/charyf/utils/extension/configurable.rb +41 -0
- data/lib/charyf/utils/extension/configuration.rb +63 -0
- data/lib/charyf/utils/extension.rb +129 -0
- data/lib/charyf/utils/generator/actions.rb +281 -0
- data/lib/charyf/utils/generator/base.rb +288 -0
- data/lib/charyf/utils/generators/app/USAGE +8 -0
- data/lib/charyf/utils/generators/app/app_generator.rb +274 -0
- data/lib/charyf/utils/generators/app/templates/Gemfile.erb +20 -0
- data/lib/charyf/utils/generators/app/templates/README.md +24 -0
- data/lib/charyf/utils/generators/app/templates/app/skill_controller.rb.tt +8 -0
- data/lib/charyf/utils/generators/app/templates/bin/charyf +5 -0
- data/lib/charyf/utils/generators/app/templates/config/application.rb.tt +32 -0
- data/lib/charyf/utils/generators/app/templates/config/boot.rb.tt +4 -0
- data/lib/charyf/utils/generators/app/templates/config/chapp.rb.tt +5 -0
- data/lib/charyf/utils/generators/app/templates/config/environments/development.rb.tt +2 -0
- data/lib/charyf/utils/generators/app/templates/config/environments/production.rb.tt +2 -0
- data/lib/charyf/utils/generators/app/templates/config/environments/test.rb.tt +2 -0
- data/lib/charyf/utils/generators/app/templates/config/load.rb.tt +17 -0
- data/lib/charyf/utils/generators/app/templates/gitignore +18 -0
- data/lib/charyf/utils/generators/app_base.rb +277 -0
- data/lib/charyf/utils/generators/defaults.rb +75 -0
- data/lib/charyf/utils/generators/intents/intents_generator.rb +41 -0
- data/lib/charyf/utils/generators/named_base.rb +73 -0
- data/lib/charyf/utils/generators/skill/skill_generator.rb +47 -0
- data/lib/charyf/utils/generators/skill/templates/controllers/skill_controller.rb.tt +10 -0
- data/lib/charyf/utils/generators/skill/templates/module.rb.tt +6 -0
- data/lib/charyf/utils/generators/skill/templates/skill.rb.tt +3 -0
- data/lib/charyf/utils/generators.rb +187 -0
- data/lib/charyf/utils/initializable.rb +95 -0
- data/lib/charyf/utils/logger.rb +26 -0
- data/lib/charyf/utils/machine.rb +129 -0
- data/lib/charyf/utils/parser/en_parser.rb +97 -0
- data/lib/charyf/utils/parser/parser.rb +37 -0
- data/lib/charyf/utils/ruby_version_check.rb +15 -0
- data/lib/charyf/utils/storage/provider.rb +44 -0
- data/lib/charyf/utils/strategy.rb +44 -0
- data/lib/charyf/utils/utils.rb +64 -0
- data/lib/charyf/utils.rb +2 -0
- data/lib/charyf/version.rb +19 -0
- data/lib/charyf.rb +18 -0
- data/lib/locale/en.yml +206 -0
- data/todo.md +3 -0
- metadata +272 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
require_relative '../../utils'
|
4
|
+
|
5
|
+
module Charyf
|
6
|
+
module Controller
|
7
|
+
module Renderers
|
8
|
+
|
9
|
+
class ResponseFileMissingError < StandardError; end
|
10
|
+
class NoResponseFound < StandardError; end
|
11
|
+
class InvalidState < StandardError; end
|
12
|
+
|
13
|
+
def self.included(base)
|
14
|
+
base.extend(ClassMethods)
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
|
19
|
+
def auto_reply(only: [], except: [])
|
20
|
+
@_render_filters = Charyf::Utils.create_action_filters(only, except)
|
21
|
+
end
|
22
|
+
|
23
|
+
def _render_on?(action)
|
24
|
+
Charyf::Utils.match_action_filters?(action.to_sym, _render_filters)
|
25
|
+
end
|
26
|
+
|
27
|
+
def _render_filters
|
28
|
+
@_render_filters ||= Charyf::Utils.create_action_filters
|
29
|
+
end
|
30
|
+
|
31
|
+
end # End of ClassMethods
|
32
|
+
|
33
|
+
# TODO sig
|
34
|
+
def response_folder
|
35
|
+
return nil if skill_name.to_s.blank?
|
36
|
+
|
37
|
+
return skill_name.to_s.constantize.skill_root.join('responses', controller_path)
|
38
|
+
end
|
39
|
+
|
40
|
+
def ensure_responses_for(action)
|
41
|
+
unless response_folder
|
42
|
+
raise Charyf::Controller::Renderers::InvalidState.new('Controller without skill can not render views')
|
43
|
+
end
|
44
|
+
|
45
|
+
if responses_for(action).empty?
|
46
|
+
raise Charyf::Controller::Renderers::NoResponseFound.new('No responses files found for action ' + action.to_s + "\n" +
|
47
|
+
"Expected #{action}.[html|txt].erb in #{response_folder}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# TODO sig
|
52
|
+
def responses_for(action)
|
53
|
+
Dir[response_folder.join("#{action}**")]
|
54
|
+
end
|
55
|
+
|
56
|
+
# TODO sig
|
57
|
+
def render_text_response(action)
|
58
|
+
file_path = response_folder.join("#{action}.txt.erb")
|
59
|
+
|
60
|
+
return nil unless exists?(file_path)
|
61
|
+
|
62
|
+
_render_sample_response file_path
|
63
|
+
end
|
64
|
+
|
65
|
+
# TODO sig
|
66
|
+
def render_html_response(action)
|
67
|
+
file_path = response_folder.join("#{action}.html.erb")
|
68
|
+
|
69
|
+
return nil unless exists?(file_path)
|
70
|
+
|
71
|
+
_render_response file_path
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def _render_sample_response(file)
|
77
|
+
sample = File.read(file).split("###").map(&:strip).sample
|
78
|
+
ERB.new(sample).result(binding)
|
79
|
+
end
|
80
|
+
|
81
|
+
def _render_response(file)
|
82
|
+
sample = File.read(file)
|
83
|
+
ERB.new(sample).result(binding)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
# TODO sig
|
88
|
+
def controller_path
|
89
|
+
controller_name.underscore
|
90
|
+
end
|
91
|
+
|
92
|
+
# TODO sig
|
93
|
+
def exists?(path)
|
94
|
+
File.exists?(path)
|
95
|
+
end
|
96
|
+
|
97
|
+
def exists!(path)
|
98
|
+
raise ResponseFileMissingError.new(path) unless exists?(path)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require_relative '../../utils'
|
2
|
+
|
3
|
+
require_relative '../context'
|
4
|
+
require_relative '../request'
|
5
|
+
|
6
|
+
module Charyf
|
7
|
+
module Engine
|
8
|
+
module Dispatcher
|
9
|
+
class Base
|
10
|
+
|
11
|
+
include Charyf::Strategy
|
12
|
+
def self.base
|
13
|
+
Base
|
14
|
+
end
|
15
|
+
|
16
|
+
sig ['Charyf::Engine::Request'], nil,
|
17
|
+
def dispatch(request)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.setup
|
21
|
+
# Do your setup here
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def self.intent_processors
|
28
|
+
Charyf.application.intent_processors
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.session_processor
|
32
|
+
Charyf.application.session_processor
|
33
|
+
end
|
34
|
+
|
35
|
+
def intent_processors
|
36
|
+
self.class.intent_processors
|
37
|
+
end
|
38
|
+
|
39
|
+
def session_processor
|
40
|
+
self.class.session_processor
|
41
|
+
end
|
42
|
+
|
43
|
+
sig ['Charyf::Engine::Context'], nil,
|
44
|
+
def spawn_controller(context)
|
45
|
+
begin
|
46
|
+
prepare_context context
|
47
|
+
|
48
|
+
Charyf.logger.flow_request("[FLOW] Dispatching request [#{context.request.inspect}]" +
|
49
|
+
", detected intent: [#{context.intent.inspect}]" +
|
50
|
+
", session : [#{context.session.inspect}]"
|
51
|
+
)
|
52
|
+
|
53
|
+
controller = get_controller(context)
|
54
|
+
|
55
|
+
handle_before_actions(controller)
|
56
|
+
controller.send(context.action_name)
|
57
|
+
handle_after_actions(controller)
|
58
|
+
rescue Exception => e
|
59
|
+
# Dispatch the error to all error handlers
|
60
|
+
Charyf.configuration.error_handlers.handle_exception(e)
|
61
|
+
|
62
|
+
# Catch any error that may occur inside the user controller
|
63
|
+
controller.send(:reply, text: 'There was a problem processing your request. Check the logs please.')
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def prepare_context(context)
|
71
|
+
context.intent ||= Charyf::Engine::Intent::UNKNOWN
|
72
|
+
|
73
|
+
context
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_controller(context)
|
77
|
+
controller_name = context.full_controller_name + 'Controller'
|
78
|
+
|
79
|
+
Object.const_get(controller_name).new(context)
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_action_name(context)
|
83
|
+
if context.session && context.session.action
|
84
|
+
return context.session.action
|
85
|
+
end
|
86
|
+
|
87
|
+
context.intent.action
|
88
|
+
end
|
89
|
+
|
90
|
+
def handle_before_actions(controller)
|
91
|
+
action = controller.action_name
|
92
|
+
|
93
|
+
# Handle before actions
|
94
|
+
controller.class._before_actions(action).each do |method_name|
|
95
|
+
controller.send(method_name)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
def handle_after_actions(controller)
|
101
|
+
action = controller.action_name
|
102
|
+
|
103
|
+
# Auto render responses
|
104
|
+
if controller.class._render_on? action
|
105
|
+
controller.send(:reply)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end # End of Base.class
|
110
|
+
|
111
|
+
def self.known
|
112
|
+
Base.known
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.list
|
116
|
+
Base.list
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module Charyf
|
4
|
+
module Engine
|
5
|
+
module Dispatcher
|
6
|
+
class BaseDispatcher < Base
|
7
|
+
|
8
|
+
strategy_name :default
|
9
|
+
|
10
|
+
def self.setup
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def dispatch(request)
|
15
|
+
# Find if session exist for this request
|
16
|
+
|
17
|
+
context = Charyf::Engine::Context.new
|
18
|
+
context.request = request
|
19
|
+
|
20
|
+
# TODO process session as well
|
21
|
+
context.session = session_processor.get.process(request)
|
22
|
+
|
23
|
+
# Get intents
|
24
|
+
intents = intent_processors.collect do |processor_klass|
|
25
|
+
processor = processor_klass.get_for(context.session ? context.session.skill : nil)
|
26
|
+
|
27
|
+
processor.determine(
|
28
|
+
request
|
29
|
+
)
|
30
|
+
end.collect do |intent|
|
31
|
+
[intent, intent.alternatives].flatten
|
32
|
+
end.flatten.sort_by do |intent|
|
33
|
+
intent.confidence
|
34
|
+
end.reverse
|
35
|
+
|
36
|
+
# Sort by confidence
|
37
|
+
best_match = intents.shift
|
38
|
+
|
39
|
+
# Return best match with alternatives
|
40
|
+
if best_match
|
41
|
+
context.intent = Charyf::Engine::Intent.new(
|
42
|
+
best_match.skill,
|
43
|
+
best_match.controller,
|
44
|
+
best_match.action,
|
45
|
+
best_match.confidence,
|
46
|
+
best_match.matches,
|
47
|
+
intents
|
48
|
+
)
|
49
|
+
|
50
|
+
context.intent = best_match
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO
|
54
|
+
spawn_controller(context)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Charyf
|
2
|
+
module Engine
|
3
|
+
class Intent
|
4
|
+
|
5
|
+
sig [['Symbol', 'String', 'NilClass'], ['Symbol', 'String'], ['Symbol', 'String'], 'Numeric', 'Hash', 'Array'], nil,
|
6
|
+
def initialize(skill, controller, action, confidence, matches = Hash.new, alternatives = [])
|
7
|
+
@_skill = skill.to_s
|
8
|
+
@_controller = controller.to_s
|
9
|
+
@_action = action.to_s.downcase
|
10
|
+
@_confidence = confidence
|
11
|
+
@_matches = matches
|
12
|
+
@_alternatives = alternatives
|
13
|
+
end
|
14
|
+
|
15
|
+
sig [], 'Hash',
|
16
|
+
def matches
|
17
|
+
@_matches
|
18
|
+
end
|
19
|
+
|
20
|
+
sig [], 'Numeric',
|
21
|
+
def confidence
|
22
|
+
@_confidence
|
23
|
+
end
|
24
|
+
|
25
|
+
sig [], ['Symbol', 'String'],
|
26
|
+
def full_controller_name
|
27
|
+
@_skill.blank? ? @_controller.camelize : @_skill.camelize + '::' + @_controller.camelize
|
28
|
+
end
|
29
|
+
|
30
|
+
sig [], ['Symbol', 'String'],
|
31
|
+
def controller
|
32
|
+
@_controller
|
33
|
+
end
|
34
|
+
|
35
|
+
sig [], ['Symbol', 'String'],
|
36
|
+
def action
|
37
|
+
@_action
|
38
|
+
end
|
39
|
+
|
40
|
+
sig [], 'Array',
|
41
|
+
def alternatives
|
42
|
+
@_alternatives
|
43
|
+
end
|
44
|
+
|
45
|
+
sig [], ['String', 'Symbol'],
|
46
|
+
def skill
|
47
|
+
@_skill
|
48
|
+
end
|
49
|
+
|
50
|
+
UNKNOWN = Intent.new(nil, :Skill, :unknown, 0)
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative '../../../utils'
|
2
|
+
|
3
|
+
require_relative '../intent'
|
4
|
+
require_relative 'processor'
|
5
|
+
|
6
|
+
module Charyf
|
7
|
+
module Engine
|
8
|
+
class Intent
|
9
|
+
module Processor
|
10
|
+
class Dummy < Base
|
11
|
+
|
12
|
+
strategy_name :dummy
|
13
|
+
|
14
|
+
def self.get_for(skill_name = nil)
|
15
|
+
self.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def determine(request)
|
19
|
+
unknown
|
20
|
+
end
|
21
|
+
|
22
|
+
def load(skill_name, block)
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Charyf
|
2
|
+
module Engine
|
3
|
+
class Intent
|
4
|
+
module Processor
|
5
|
+
module Helpers
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def scoped_name(skill_name, *args)
|
14
|
+
([skill_name.to_s] + args).join('_')
|
15
|
+
end
|
16
|
+
|
17
|
+
def unscope_name(skill_name, name)
|
18
|
+
name.start_with?(skill_name.to_s) ? name.sub("#{skill_name.to_s}_", '') : name
|
19
|
+
end
|
20
|
+
|
21
|
+
end # End of ClassMethods
|
22
|
+
|
23
|
+
sig [], 'Charyf::Engine::Intent',
|
24
|
+
def unknown
|
25
|
+
Charyf::Engine::Intent::UNKNOWN
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative '../../../utils'
|
2
|
+
|
3
|
+
require_relative 'helpers'
|
4
|
+
require_relative '../intent'
|
5
|
+
|
6
|
+
module Charyf
|
7
|
+
module Engine
|
8
|
+
class Intent
|
9
|
+
module Processor
|
10
|
+
class Base
|
11
|
+
|
12
|
+
include Charyf::Strategy
|
13
|
+
include Charyf::Engine::Intent::Processor::Helpers
|
14
|
+
|
15
|
+
def self.base
|
16
|
+
Base
|
17
|
+
end
|
18
|
+
|
19
|
+
sig ['Charyf::Engine::Request'], 'Charyf::Engine::Intent',
|
20
|
+
def determine(request)
|
21
|
+
raise Charyf::Utils::NotImplemented.new
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Load single block of intent definitions
|
26
|
+
#
|
27
|
+
sig_self ['Symbol', 'Proc'], nil,
|
28
|
+
def load(skill_name, block)
|
29
|
+
raise Charyf::Utils::NotImplemented.new
|
30
|
+
end
|
31
|
+
|
32
|
+
sig_self ['Symbol'], 'Charyf::Engine::Intent::Processor::Base',
|
33
|
+
def self.get_for(skill = nil)
|
34
|
+
raise Charyf::Utils::NotImplemented.new
|
35
|
+
end
|
36
|
+
|
37
|
+
sig_self [], 'Charyf::Engine::Intent::Processor::Base',
|
38
|
+
def self.get_global
|
39
|
+
get_for(nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def self.known
|
46
|
+
Base.known
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.list
|
50
|
+
Base.list
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../../utils'
|
2
|
+
|
3
|
+
require_relative '../response'
|
4
|
+
require_relative '../dispatcher/base'
|
5
|
+
|
6
|
+
module Charyf
|
7
|
+
module Interface
|
8
|
+
class Base
|
9
|
+
|
10
|
+
include Charyf::Strategy
|
11
|
+
def self.base
|
12
|
+
Base
|
13
|
+
end
|
14
|
+
|
15
|
+
sig_self [], 'Charyf::Engine::Dispatcher::Base',
|
16
|
+
def self.dispatcher
|
17
|
+
Charyf.application.dispatcher.new
|
18
|
+
end
|
19
|
+
|
20
|
+
sig_self ['String', 'Charyf::Engine::Response'], nil,
|
21
|
+
def self.reply(conversation_id, response)
|
22
|
+
raise Charyf::Utils::NotImplemented.new
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.known
|
28
|
+
Base.known
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.list
|
32
|
+
Base.list
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative 'interface'
|
2
|
+
require_relative '../request'
|
3
|
+
|
4
|
+
module Charyf
|
5
|
+
module Interface
|
6
|
+
class Program < Charyf::Interface::Base
|
7
|
+
|
8
|
+
class InvalidConversationError < StandardError; end
|
9
|
+
|
10
|
+
strategy_name :program
|
11
|
+
|
12
|
+
attr_reader :handler, :conversation_id
|
13
|
+
|
14
|
+
sig_self ['String', 'Charyf::Engine::Response'], nil,
|
15
|
+
def self.reply(conversation_id, response)
|
16
|
+
interface = _interfaces[conversation_id]
|
17
|
+
raise InvalidConversationError.new("No program interface found for conversation #{conversation_id}") unless interface
|
18
|
+
|
19
|
+
interface.reply(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
sig_self ['String', 'Proc'], 'Charyf::Interface::Program',
|
23
|
+
def self.create(conversation_id, handler)
|
24
|
+
interface = self.new(conversation_id, handler)
|
25
|
+
|
26
|
+
_interfaces[conversation_id] = interface
|
27
|
+
|
28
|
+
interface
|
29
|
+
end
|
30
|
+
|
31
|
+
def self._interfaces
|
32
|
+
@_interfaces ||= Hash.new
|
33
|
+
end
|
34
|
+
|
35
|
+
sig [nil, 'Proc'],
|
36
|
+
def initialize(conversation_id, handler)
|
37
|
+
|
38
|
+
@handler = handler
|
39
|
+
@conversation_id = conversation_id.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
sig ['Charyf::Engine::Request'],
|
43
|
+
def process(request)
|
44
|
+
self.class.dispatcher.dispatch(request)
|
45
|
+
end
|
46
|
+
|
47
|
+
sig ['Charyf::Engine::Response'],
|
48
|
+
def reply(response)
|
49
|
+
handler.call(response)
|
50
|
+
end
|
51
|
+
|
52
|
+
sig [], 'Charyf::Engine::Request',
|
53
|
+
def request
|
54
|
+
Charyf::Engine::Request.new(self.class, conversation_id)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Charyf
|
2
|
+
module Engine
|
3
|
+
class Request
|
4
|
+
|
5
|
+
attr_accessor :text
|
6
|
+
|
7
|
+
# Module -> anything of type Charyf::Interface::Base
|
8
|
+
sig ['Module', 'String'], nil,
|
9
|
+
def initialize(referer, conversation_id)
|
10
|
+
@referer = referer
|
11
|
+
@conversation_id = conversation_id
|
12
|
+
end
|
13
|
+
|
14
|
+
# Module -> Charyf::Interface::Base
|
15
|
+
sig [], 'Module',
|
16
|
+
def referer
|
17
|
+
@referer
|
18
|
+
end
|
19
|
+
|
20
|
+
sig [], 'String',
|
21
|
+
def conversation_id
|
22
|
+
@conversation_id
|
23
|
+
end
|
24
|
+
|
25
|
+
sig [], 'String',
|
26
|
+
def id
|
27
|
+
@referer.strategy_name.to_s + '_#_' + @conversation_id
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Charyf
|
2
|
+
module Engine
|
3
|
+
class Response
|
4
|
+
|
5
|
+
attr_accessor :text, :html
|
6
|
+
|
7
|
+
sig [['String', 'NilClass'], ['String', 'NilClass']], nil,
|
8
|
+
def initialize(text, html)
|
9
|
+
@text = text
|
10
|
+
@html = html
|
11
|
+
end
|
12
|
+
|
13
|
+
def empty?
|
14
|
+
text.blank? && html.blank?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Attr methods for type-checking
|
18
|
+
|
19
|
+
sig ['String', 'NilClass'], ['String', 'NilClass'],
|
20
|
+
def text=(text)
|
21
|
+
@text = text
|
22
|
+
end
|
23
|
+
|
24
|
+
sig [], ['String', 'NilClass'],
|
25
|
+
def text
|
26
|
+
@text
|
27
|
+
end
|
28
|
+
|
29
|
+
sig ['String', 'NilClass'], ['String', 'NilClass'],
|
30
|
+
def html=(html)
|
31
|
+
@html = html
|
32
|
+
end
|
33
|
+
|
34
|
+
sig [], ['String', 'NilClass'],
|
35
|
+
def html
|
36
|
+
@html
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative '../../../utils'
|
2
|
+
|
3
|
+
require_relative '../session'
|
4
|
+
require_relative 'processor'
|
5
|
+
|
6
|
+
module Charyf
|
7
|
+
module Engine
|
8
|
+
class Session
|
9
|
+
module Processor
|
10
|
+
class Default < Base
|
11
|
+
|
12
|
+
# 10 Minute
|
13
|
+
# TODO - move to config?
|
14
|
+
SESSION_TIMEOUT = 10 * 60
|
15
|
+
|
16
|
+
strategy_name :default
|
17
|
+
|
18
|
+
def process(request)
|
19
|
+
# session = Charyf::Engine::Session.get(request.id)
|
20
|
+
#
|
21
|
+
# return unless session
|
22
|
+
#
|
23
|
+
# if session && Time.now - session.timestamp > SESSION_TIMEOUT
|
24
|
+
# session.destroy!
|
25
|
+
# return nil
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# session.invalidate!
|
29
|
+
# session
|
30
|
+
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.get
|
35
|
+
self.new
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../../../utils'
|
2
|
+
|
3
|
+
module Charyf
|
4
|
+
module Engine
|
5
|
+
class Session
|
6
|
+
module Processor
|
7
|
+
class Base
|
8
|
+
|
9
|
+
include Charyf::Strategy
|
10
|
+
def self.base
|
11
|
+
Base
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
sig ['Charyf::Engine::Request'], ['Charyf::Engine::Session', 'NilClass'],
|
16
|
+
def process(request)
|
17
|
+
raise Charyf::Utils::NotImplemented.new
|
18
|
+
end
|
19
|
+
|
20
|
+
sig_self [], ['Charyf::Engine::Session::Processor::Base'],
|
21
|
+
def self.get
|
22
|
+
raise Charyf::Utils::NotImplemented.new
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def self.known
|
29
|
+
Base.known
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.list
|
33
|
+
Base.list
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|