kanal 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +14 -16
- data/lib/kanal/core/helpers/response_block.rb +29 -1
- data/lib/kanal/core/helpers/response_execution_block.rb +48 -2
- data/lib/kanal/core/output/output.rb +20 -2
- data/lib/kanal/core/router/router.rb +3 -1
- data/lib/kanal/core/router/router_node.rb +12 -0
- data/lib/kanal/plugins/batteries/batteries_plugin.rb +10 -0
- data/lib/kanal/plugins/batteries/specifics.rb +34 -0
- data/lib/kanal/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3fa557dde04dae9b2a64daefc5b05e083331240c38701248bc3d8e2f02f136f
|
4
|
+
data.tar.gz: 2602843cdb547c6633322520e25b158def2d110952466cd8d80de9ab15ea8377
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b87922aa8cdaaf257ed89b6a6eea547a22181ed7dd60c3284b8bb7f8cb68ed048de256f38fa50ddedc83cd758ed4b35172692513c0aa5773401433833ee82732
|
7
|
+
data.tar.gz: c882a6864449692ae4ce1dd63450b9ed61d12dc3d469468c355ec28b862a6f103ccaffe0eeab87e6993d7ad761d1111adf2f7d80e1d5f603acaa0b0e05a86d55
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.8.0] 2023-05-02
|
4
|
+
- after_respond, after_respond_async to store blocks of code to be executed after responses. They do not spawn outputs
|
5
|
+
- respond do; cancel end - now we can use cancel DSL keyword in response block if response should not be processed further to spawn an output
|
6
|
+
|
7
|
+
## [0.7.0] 2023-04-25
|
8
|
+
- new output property for batteries: specifics. You can now add specific properties for whatever purpose like specifics.add, specifics.get. specifics.has?
|
9
|
+
|
3
10
|
## [0.6.0] 2023-04-24
|
4
11
|
- .composite_logger method for core now gives possibility to take that logger and provide it as ruby logger somewhere in the other library (usually to flow some libraries used in your kanal app logs into the kanal logs to have logs in the same place)
|
5
12
|
- you can now get beautified router info in string format for debug purpose via router.routes_info_string method
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kanal (0.
|
4
|
+
kanal (0.8.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -22,21 +22,19 @@ GEM
|
|
22
22
|
kramdown-parser-gfm (1.1.0)
|
23
23
|
kramdown (~> 2.0)
|
24
24
|
mini_mime (1.1.2)
|
25
|
-
mini_portile2 (2.8.1)
|
26
25
|
multi_xml (0.6.0)
|
27
|
-
nokogiri (1.14.3)
|
28
|
-
mini_portile2 (~> 2.8.0)
|
29
|
-
racc (~> 1.4)
|
30
26
|
nokogiri (1.14.3-x86_64-darwin)
|
31
27
|
racc (~> 1.4)
|
32
|
-
|
33
|
-
|
28
|
+
nokogiri (1.14.3-x86_64-linux)
|
29
|
+
racc (~> 1.4)
|
30
|
+
parallel (1.23.0)
|
31
|
+
parser (3.2.2.1)
|
34
32
|
ast (~> 2.4.1)
|
35
33
|
racc (1.6.2)
|
36
34
|
rainbow (3.1.1)
|
37
35
|
rake (13.0.6)
|
38
36
|
rbs (2.8.4)
|
39
|
-
regexp_parser (2.
|
37
|
+
regexp_parser (2.8.0)
|
40
38
|
reverse_markdown (2.1.1)
|
41
39
|
nokogiri
|
42
40
|
rexml (3.2.5)
|
@@ -44,16 +42,16 @@ GEM
|
|
44
42
|
rspec-core (~> 3.12.0)
|
45
43
|
rspec-expectations (~> 3.12.0)
|
46
44
|
rspec-mocks (~> 3.12.0)
|
47
|
-
rspec-core (3.12.
|
45
|
+
rspec-core (3.12.2)
|
48
46
|
rspec-support (~> 3.12.0)
|
49
|
-
rspec-expectations (3.12.
|
47
|
+
rspec-expectations (3.12.3)
|
50
48
|
diff-lcs (>= 1.2.0, < 2.0)
|
51
49
|
rspec-support (~> 3.12.0)
|
52
50
|
rspec-mocks (3.12.5)
|
53
51
|
diff-lcs (>= 1.2.0, < 2.0)
|
54
52
|
rspec-support (~> 3.12.0)
|
55
53
|
rspec-support (3.12.0)
|
56
|
-
rubocop (1.50.
|
54
|
+
rubocop (1.50.2)
|
57
55
|
json (~> 2.3)
|
58
56
|
parallel (~> 1.10)
|
59
57
|
parser (>= 3.2.0.0)
|
@@ -63,7 +61,7 @@ GEM
|
|
63
61
|
rubocop-ast (>= 1.28.0, < 2.0)
|
64
62
|
ruby-progressbar (~> 1.7)
|
65
63
|
unicode-display_width (>= 2.4.0, < 3.0)
|
66
|
-
rubocop-ast (1.28.
|
64
|
+
rubocop-ast (1.28.1)
|
67
65
|
parser (>= 3.2.1.0)
|
68
66
|
ruby-debug-ide (0.7.3)
|
69
67
|
rake (>= 0.8.1)
|
@@ -93,11 +91,11 @@ GEM
|
|
93
91
|
thor (1.2.1)
|
94
92
|
tilt (2.1.0)
|
95
93
|
unicode-display_width (2.4.2)
|
96
|
-
yard (0.9.
|
94
|
+
yard (0.9.34)
|
97
95
|
|
98
96
|
PLATFORMS
|
99
|
-
|
100
|
-
x86_64-
|
97
|
+
x86_64-darwin-22
|
98
|
+
x86_64-linux
|
101
99
|
|
102
100
|
DEPENDENCIES
|
103
101
|
httparty (= 0.21.0)
|
@@ -111,4 +109,4 @@ DEPENDENCIES
|
|
111
109
|
yard
|
112
110
|
|
113
111
|
BUNDLED WITH
|
114
|
-
2.4.
|
112
|
+
2.4.9
|
@@ -3,14 +3,42 @@
|
|
3
3
|
module Kanal
|
4
4
|
module Core
|
5
5
|
module Helpers
|
6
|
+
#
|
7
|
+
# Response block stores block of code
|
8
|
+
# to be executed at runtime and output to be created
|
9
|
+
#
|
6
10
|
class ResponseBlock
|
7
11
|
attr_reader :block
|
8
12
|
|
9
|
-
|
13
|
+
#
|
14
|
+
# Creates response block that stores block for evaluation
|
15
|
+
# at runtime, when output is constructed
|
16
|
+
#
|
17
|
+
# @param block [Proc] block of code to be evaluated at runtime and output to be constructed with it
|
18
|
+
# @param async [Boolean] block should be executed in thread
|
19
|
+
# @param functional [Boolean] block should be executed but not shipped as outpu
|
20
|
+
#
|
21
|
+
def initialize(block, async: false, functional: false)
|
10
22
|
@block = block
|
11
23
|
@async = async
|
24
|
+
@functional = functional
|
12
25
|
end
|
13
26
|
|
27
|
+
#
|
28
|
+
# Whether response block is functional, means no output should
|
29
|
+
# be processed after execution of block
|
30
|
+
#
|
31
|
+
# @return [Boolean] <description>
|
32
|
+
#
|
33
|
+
def functional?
|
34
|
+
@functional
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Should execution of block be async?
|
39
|
+
#
|
40
|
+
# @return [Boolean] <description>
|
41
|
+
#
|
14
42
|
def async?
|
15
43
|
@async
|
16
44
|
end
|
@@ -7,12 +7,25 @@ require_relative "../helpers/input_output_pair"
|
|
7
7
|
module Kanal
|
8
8
|
module Core
|
9
9
|
module Helpers
|
10
|
+
#
|
11
|
+
# This class executes response block and constructs output
|
12
|
+
# It is also can execute response block and disable moving it forward to the
|
13
|
+
# queue
|
14
|
+
#
|
10
15
|
class ResponseExecutionBlock
|
11
16
|
include Output
|
12
17
|
include Logging::Logger
|
13
18
|
|
14
19
|
attr_reader :response_block, :input
|
15
20
|
|
21
|
+
#
|
22
|
+
# Creating response execution block with all needed parameters
|
23
|
+
#
|
24
|
+
# @param response_block [Kanal::Core::Helpers::ResponseBlock] response block
|
25
|
+
# @param input [Kanal::Core::Input::Input] input provided by router
|
26
|
+
# @param default_error_node [Kanal::Core::Router::RouterNode] default error node if no user defined error node available
|
27
|
+
# @param error_node [Kanal::Core::Router::RouterNode] user (developer of bot) defined error node with information about error
|
28
|
+
#
|
16
29
|
def initialize(response_block, input, default_error_node, error_node)
|
17
30
|
@response_block = response_block
|
18
31
|
@input = input
|
@@ -20,31 +33,61 @@ module Kanal
|
|
20
33
|
@error_node = error_node
|
21
34
|
end
|
22
35
|
|
36
|
+
#
|
37
|
+
# Execute response block and ship created output into the queue
|
38
|
+
#
|
39
|
+
# @param core [Kanal::Core::Core] core to access parameter registrators and stuff TODO: remove core here and provide registrator as dependency
|
40
|
+
# @param input_output_pair_queue [Kanal::Core::Helpers::Queue] queue where Kanal::Core::Helpers::InputOutputPair will be stored
|
41
|
+
#
|
42
|
+
# @return [void] <description>
|
43
|
+
#
|
23
44
|
def execute(core, input_output_pair_queue)
|
24
45
|
if response_block.async?
|
25
46
|
# NOTE: Thread doesnt just die here - it's execution is continued in input_output_pair_queue.enqueue in router
|
26
47
|
# then :item_queued hook is called inside and subsequently output_ready_block gets called in this thread
|
27
48
|
# TODO: be aware that this can cause unexpected behaviour. Maybe think how to rework it.
|
28
49
|
Thread.new do
|
29
|
-
|
50
|
+
output = construct_output core
|
51
|
+
unless output.canceled?
|
52
|
+
input_output_pair_queue.enqueue InputOutputPair.new(@input, output)
|
53
|
+
end
|
30
54
|
end
|
31
55
|
else
|
32
|
-
|
56
|
+
output = construct_output core
|
57
|
+
unless output.canceled?
|
58
|
+
input_output_pair_queue.enqueue InputOutputPair.new(@input, output)
|
59
|
+
end
|
33
60
|
end
|
34
61
|
end
|
35
62
|
|
36
63
|
private
|
37
64
|
|
65
|
+
#
|
66
|
+
# Construct output from response block
|
67
|
+
#
|
68
|
+
# @param core [Kanal::Core::Core] core to access registrator
|
69
|
+
#
|
70
|
+
# @return [Kanal::Core::Output::Output] output created
|
71
|
+
#
|
38
72
|
def construct_output(core)
|
39
73
|
logger.debug "Constructing output for input ##{input.__id__}"
|
40
74
|
|
41
75
|
output = Output::Output.new core.output_parameter_registrator, @input, core
|
42
76
|
|
77
|
+
# Canceling output to be processed further if response block is functional.
|
78
|
+
# Whole .functional thing is done to allow after_respond and after_respond_async blocks
|
79
|
+
# that should not spawn outputs
|
80
|
+
output.cancel if @response_block.functional?
|
81
|
+
|
43
82
|
begin
|
44
83
|
core.hooks.call :output_just_created, input, output
|
45
84
|
|
85
|
+
# Evaluating response block
|
46
86
|
output.instance_eval(&@response_block.block)
|
47
87
|
rescue => e
|
88
|
+
# Something wrong happened
|
89
|
+
# we try and construct error response provided by the user (dev created bot)
|
90
|
+
# if there is no any - we use default user response block
|
48
91
|
logger.error "Failed to construct output for input ##{input.__id__}. Error: '#{e}'"
|
49
92
|
|
50
93
|
output = Output::Output.new core.output_parameter_registrator, @input, core
|
@@ -56,6 +99,9 @@ module Kanal
|
|
56
99
|
begin
|
57
100
|
output.instance_eval(&error_node.response_blocks.first.block)
|
58
101
|
rescue => e
|
102
|
+
# Something wrong happened in user defined error response or
|
103
|
+
# for some reason even default error response block failed
|
104
|
+
# Logging error and trying default error block
|
59
105
|
logger.error "Failed to construct error response for input ##{input.__id__}. Error: '#{e}'"
|
60
106
|
|
61
107
|
logger.debug "Trying to construct default error response for input ##{input.__id__}"
|
@@ -12,23 +12,41 @@ module Kanal
|
|
12
12
|
include Helpers
|
13
13
|
include Helpers::ParameterFinderWithMethodMissingMixin
|
14
14
|
|
15
|
-
attr_reader :input, :core
|
15
|
+
attr_reader :input, :core, :canceled
|
16
16
|
|
17
17
|
#
|
18
|
-
#
|
18
|
+
# Creates new output with input, core and registered output parameters
|
19
|
+
#
|
20
|
+
# @param parameter_registrator [Kanal::Core::Helpers::ParameterRegistrator]
|
19
21
|
# @param input [Kanal::Core::Input::Input] input required for dsl in respond blocks to have access to input
|
20
22
|
# @param core [Kanal::Core::Core] core required also for dsl to access services or other information about core
|
21
23
|
def initialize(parameter_registrator, input, core)
|
22
24
|
@core = core
|
23
25
|
@input = input
|
24
26
|
@parameter_bag = ParameterBagWithRegistrator.new parameter_registrator
|
27
|
+
@canceled = false
|
25
28
|
end
|
26
29
|
|
27
30
|
def configure_dsl(&block)
|
28
31
|
instance_eval(&block)
|
29
32
|
end
|
30
33
|
|
34
|
+
def canceled?
|
35
|
+
@canceled == true
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Canceles this output.
|
40
|
+
# It won't be processed further and given out from router
|
41
|
+
#
|
42
|
+
# @return [void] <description>
|
43
|
+
#
|
44
|
+
def cancel
|
45
|
+
@canceled = true
|
46
|
+
end
|
47
|
+
|
31
48
|
private :core
|
49
|
+
|
32
50
|
end
|
33
51
|
end
|
34
52
|
end
|
@@ -176,7 +176,9 @@ module Kanal
|
|
176
176
|
|
177
177
|
error_node = @error_node || @default_error_node
|
178
178
|
|
179
|
-
response_execution_blocks = response_blocks.map
|
179
|
+
response_execution_blocks = response_blocks.map do |rb|
|
180
|
+
ResponseExecutionBlock.new rb, input, @default_error_node, @error_node
|
181
|
+
end
|
180
182
|
|
181
183
|
response_execution_blocks.each do |reb|
|
182
184
|
@response_execution_queue.enqueue reb
|
@@ -72,6 +72,18 @@ module Kanal
|
|
72
72
|
@response_blocks.append ResponseBlock.new(block, async: true)
|
73
73
|
end
|
74
74
|
|
75
|
+
def after_respond(&block)
|
76
|
+
raise "Router node with children cannot have response" unless @children.empty?
|
77
|
+
|
78
|
+
@response_blocks.append ResponseBlock.new(block, functional: true)
|
79
|
+
end
|
80
|
+
|
81
|
+
def after_respond_async(&block)
|
82
|
+
raise "Router node with children cannot have response" unless @children.empty?
|
83
|
+
|
84
|
+
@response_blocks.append ResponseBlock.new(block, functional: true, async: true)
|
85
|
+
end
|
86
|
+
|
75
87
|
def response?
|
76
88
|
!@response_blocks.empty?
|
77
89
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "kanal/core/plugins/plugin"
|
4
4
|
require_relative "keyboard"
|
5
|
+
require_relative "specifics"
|
5
6
|
|
6
7
|
module Kanal
|
7
8
|
module Plugins
|
@@ -23,6 +24,7 @@ module Kanal
|
|
23
24
|
keyboard_batteries core
|
24
25
|
username_batteries core
|
25
26
|
button_batteries core
|
27
|
+
specifics_batteries core
|
26
28
|
end
|
27
29
|
|
28
30
|
def flow_batteries(core)
|
@@ -237,6 +239,14 @@ module Kanal
|
|
237
239
|
end
|
238
240
|
end
|
239
241
|
end
|
242
|
+
|
243
|
+
def specifics_batteries(core)
|
244
|
+
core.register_output_parameter :specifics
|
245
|
+
|
246
|
+
core.hooks.attach :output_just_created do |input, output|
|
247
|
+
output.specifics = Specifics.new
|
248
|
+
end
|
249
|
+
end
|
240
250
|
end
|
241
251
|
end
|
242
252
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "kanal/core/logging/composite_logger"
|
4
|
+
|
5
|
+
module Kanal
|
6
|
+
module Plugins
|
7
|
+
module Batteries
|
8
|
+
#
|
9
|
+
# This class provides possibility to store custom key-value pairs in outputs
|
10
|
+
#
|
11
|
+
class Specifics
|
12
|
+
include Kanal::Core::Logging
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@specifics = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(specific_name, specific_value)
|
19
|
+
@specifics[specific_name] = specific_value
|
20
|
+
end
|
21
|
+
|
22
|
+
def get(specific_name)
|
23
|
+
return nil unless has? specific_name
|
24
|
+
|
25
|
+
@specifics[specific_name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def has?(specific_name)
|
29
|
+
@specifics.key? specific_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/kanal/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kanal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- idchlife
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Thanks to the core library, ecosystem of Kanal tools can be extendted
|
14
14
|
to use with input-output bot-like behaviour, with routing
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- lib/kanal/plugins/batteries/attachments/attachment.rb
|
64
64
|
- lib/kanal/plugins/batteries/batteries_plugin.rb
|
65
65
|
- lib/kanal/plugins/batteries/keyboard.rb
|
66
|
+
- lib/kanal/plugins/batteries/specifics.rb
|
66
67
|
- lib/kanal/version.rb
|
67
68
|
- lib/shortcuts.rb
|
68
69
|
- sig/kanal.rbs
|