kybus-bot 0.10.0 → 0.11.1
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/lib/kybus/bot/adapters/debug.rb +7 -4
- data/lib/kybus/bot/adapters/telegram.rb +38 -57
- data/lib/kybus/bot/adapters/telegram_file.rb +2 -2
- data/lib/kybus/bot/adapters/telegram_message.rb +7 -3
- data/lib/kybus/bot/base.rb +73 -59
- data/lib/kybus/bot/command/command_definition.rb +2 -0
- data/lib/kybus/bot/command/command_handler.rb +34 -0
- data/lib/kybus/bot/command/command_state.rb +23 -12
- data/lib/kybus/bot/command/command_state_factory.rb +17 -34
- data/lib/kybus/bot/command/execution_context.rb +1 -1
- data/lib/kybus/bot/command/inline_command_matcher.rb +47 -0
- data/lib/kybus/bot/command/parameter_saver.rb +64 -0
- data/lib/kybus/bot/command/regular_command_matcher.rb +47 -0
- data/lib/kybus/bot/command_executor.rb +41 -73
- data/lib/kybus/bot/dsl_methods.rb +7 -3
- data/lib/kybus/bot/exceptions.rb +16 -0
- data/lib/kybus/bot/forkers/base.rb +61 -0
- data/lib/kybus/bot/forkers/lambda_sqs_forker.rb +41 -0
- data/lib/kybus/bot/forkers/thread_forker.rb +18 -0
- data/lib/kybus/bot/migrator.rb +57 -39
- data/lib/kybus/bot/serialized_message.rb +32 -14
- data/lib/kybus/bot/sidekiq_command_executor.rb +2 -0
- data/lib/kybus/bot/version.rb +1 -1
- metadata +11 -3
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class ParameterSaver
|
6
|
+
def initialize(executor)
|
7
|
+
@executor = executor
|
8
|
+
end
|
9
|
+
|
10
|
+
def save_token!(message)
|
11
|
+
@executor.execution_context.last_message = message.serialize
|
12
|
+
if @executor.execution_context.expecting_command?
|
13
|
+
command = @executor.channel_factory.command(message.command)
|
14
|
+
set_command(command, message)
|
15
|
+
else
|
16
|
+
save_param!(message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def save_param!(message)
|
23
|
+
@executor.execution_context.add_param(message.raw_message)
|
24
|
+
save_attachment!(message) if message.has_attachment?
|
25
|
+
end
|
26
|
+
|
27
|
+
def save_attachment!(message)
|
28
|
+
file = @executor.bot.provider.file_builder(message.attachment)
|
29
|
+
@executor.execution_context.add_file(file)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_command(command, message)
|
33
|
+
if @executor.inline_args && !command
|
34
|
+
search_command_with_inline_arg(message)
|
35
|
+
elsif !@executor.inline_args && !command
|
36
|
+
set_default_command
|
37
|
+
else
|
38
|
+
@executor.execution_context.command = command
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def search_command_with_inline_arg(message)
|
43
|
+
command, values = @executor.channel_factory.command_with_inline_arg(message.raw_message || '')
|
44
|
+
if command
|
45
|
+
set_command_with_values(command, values)
|
46
|
+
else
|
47
|
+
set_default_command
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_command_with_values(command, values)
|
52
|
+
@executor.execution_context.command = command
|
53
|
+
values.each do |value|
|
54
|
+
@executor.execution_context.next_param = @executor.execution_context.next_missing_param
|
55
|
+
@executor.execution_context.add_param(value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_default_command
|
60
|
+
@executor.execution_context.command = @executor.channel_factory.default_command
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class RegularCommandMatcher
|
6
|
+
def initialize(definitions)
|
7
|
+
@definitions = definitions
|
8
|
+
@matchers = build_matchers
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_command(search)
|
12
|
+
@definitions.each do |name, command|
|
13
|
+
matcher = @matchers[name.class]
|
14
|
+
result = matcher&.call(name, command, search)
|
15
|
+
return result if result
|
16
|
+
end
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def build_matchers
|
23
|
+
{
|
24
|
+
String => method(:match_string),
|
25
|
+
Class => method(:match_class),
|
26
|
+
Regexp => method(:match_regexp)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def match_string(name, command, search)
|
31
|
+
command if name == search
|
32
|
+
end
|
33
|
+
|
34
|
+
def match_class(name, command, search)
|
35
|
+
command if search.is_a?(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def match_regexp(name, command, search)
|
39
|
+
return unless search.is_a?(String) && name.match?(search)
|
40
|
+
|
41
|
+
storable_command = command.clone
|
42
|
+
storable_command.name = search
|
43
|
+
storable_command
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -4,6 +4,9 @@ require 'forwardable'
|
|
4
4
|
require_relative 'command/command'
|
5
5
|
require_relative 'command/command_definition'
|
6
6
|
require_relative 'command/execution_context'
|
7
|
+
require_relative 'dsl_methods'
|
8
|
+
require_relative 'command/command_handler'
|
9
|
+
require_relative 'command/parameter_saver'
|
7
10
|
|
8
11
|
module Kybus
|
9
12
|
module Bot
|
@@ -11,7 +14,7 @@ module Kybus
|
|
11
14
|
extend Forwardable
|
12
15
|
|
13
16
|
include Kybus::Logger
|
14
|
-
attr_reader :dsl, :bot, :execution_context
|
17
|
+
attr_reader :dsl, :bot, :execution_context, :channel_factory, :inline_args, :error
|
15
18
|
|
16
19
|
def_delegator :execution_context, :save!, :save_execution_context!
|
17
20
|
|
@@ -29,79 +32,32 @@ module Kybus
|
|
29
32
|
@dsl = DSLMethods.new(bot.provider, state, bot)
|
30
33
|
@inline_args = inline_args
|
31
34
|
@precommand_hook = proc {}
|
35
|
+
@parameter_saver = ParameterSaver.new(self)
|
36
|
+
@command_handler = CommandHandler.new(self)
|
32
37
|
end
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@execution_context = ExecutionContest.new(message.channel_id, @channel_factory)
|
38
|
-
save_token!(message)
|
39
|
-
msg = run_command_or_prepare!
|
40
|
-
save_execution_context!
|
41
|
-
msg
|
42
|
-
end
|
43
|
-
|
44
|
-
def save_param!(message)
|
45
|
-
execution_context.add_param(message.raw_message)
|
46
|
-
return unless message.has_attachment?
|
47
|
-
|
48
|
-
file = bot.provider.file_builder(message.attachment)
|
49
|
-
execution_context.add_file(file)
|
50
|
-
end
|
51
|
-
|
52
|
-
def search_command_with_inline_arg(message)
|
53
|
-
command, values = @channel_factory.command_with_inline_arg(message.raw_message || '')
|
54
|
-
if command
|
55
|
-
execution_context.command = command
|
56
|
-
values.each do |value|
|
57
|
-
execution_context.next_param = execution_context.next_missing_param
|
58
|
-
execution_context.add_param(value)
|
59
|
-
end
|
60
|
-
else
|
61
|
-
execution_context.command = @channel_factory.default_command
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def save_token!(message)
|
66
|
-
execution_context.set_last_message(message.serialize)
|
67
|
-
if execution_context.expecting_command?
|
68
|
-
command = @channel_factory.command(message.command)
|
69
|
-
if @inline_args && !command
|
70
|
-
search_command_with_inline_arg(message)
|
71
|
-
elsif !@inline_args && !command
|
72
|
-
execution_context.command = @channel_factory.default_command
|
73
|
-
else
|
74
|
-
execution_context.command = command
|
75
|
-
end
|
76
|
-
else
|
77
|
-
save_param!(message)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def run_command_or_prepare!
|
82
|
-
if execution_context.ready?
|
83
|
-
@dsl.state = execution_context.state
|
84
|
-
@dsl.instance_eval(&@precommand_hook)
|
85
|
-
msg = run_command!
|
86
|
-
execution_context.clear_command
|
87
|
-
msg
|
39
|
+
def precommand_hook(&)
|
40
|
+
if block_given?
|
41
|
+
@precommand_hook = proc(&)
|
88
42
|
else
|
89
|
-
|
90
|
-
ask_param(param, execution_context.state.command.params_ask_label(param))
|
43
|
+
@precommand_hook
|
91
44
|
end
|
92
45
|
end
|
93
46
|
|
94
|
-
def
|
95
|
-
|
47
|
+
def process_message(message)
|
48
|
+
setup_execution_context(message)
|
49
|
+
@parameter_saver.save_token!(message)
|
50
|
+
msg = @command_handler.run_command_or_prepare!
|
51
|
+
save_execution_context!
|
52
|
+
msg
|
96
53
|
end
|
97
54
|
|
98
55
|
def fallback(error)
|
99
|
-
|
56
|
+
catch_command = @channel_factory.command(error)
|
100
57
|
log_error('Unexpected error', error)
|
101
|
-
execution_context.command =
|
58
|
+
execution_context.command = catch_command if catch_command
|
102
59
|
end
|
103
60
|
|
104
|
-
# Method for triggering command
|
105
61
|
def run_command!
|
106
62
|
execution_context.call!(@dsl)
|
107
63
|
rescue StandardError => e
|
@@ -112,28 +68,40 @@ module Kybus
|
|
112
68
|
end
|
113
69
|
|
114
70
|
def invoke(command, args)
|
115
|
-
|
116
|
-
|
117
|
-
state.store_param(param, value)
|
118
|
-
end
|
119
|
-
run_command_or_prepare!
|
71
|
+
set_state_command(command, args)
|
72
|
+
@command_handler.run_command_or_prepare!
|
120
73
|
end
|
121
74
|
|
122
75
|
def redirect(command_name, args)
|
123
76
|
command = @channel_factory.command(command_name)
|
124
|
-
|
125
|
-
raise "Wrong redirect #{command_name}, #{bot.registered_commands}"
|
126
|
-
end
|
127
|
-
|
77
|
+
validate_redirect(command, command_name, args)
|
128
78
|
invoke(command, args)
|
129
79
|
end
|
130
80
|
|
131
|
-
# Sends a message to get the next parameter from the user
|
132
81
|
def ask_param(param, label = nil)
|
133
82
|
msg = label || "I need you to tell me #{param}"
|
134
|
-
bot.send_message(msg, last_message.channel_id)
|
83
|
+
bot.dsl.send_message(msg, last_message.channel_id)
|
135
84
|
execution_context.next_param = param
|
136
85
|
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def setup_execution_context(message)
|
90
|
+
@execution_context = ExecutionContest.new(message.channel_id, @channel_factory)
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_state_command(command, args)
|
94
|
+
state.command = command
|
95
|
+
command.params.zip(args).each do |param, value|
|
96
|
+
state.store_param(param, value)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def validate_redirect(command, command_name, args)
|
101
|
+
return unless command.nil? || command.params_size != args.size
|
102
|
+
|
103
|
+
raise ::Kybus::Bot::Base::BotError, "Wrong redirect #{command_name}, #{bot.registered_commands}"
|
104
|
+
end
|
137
105
|
end
|
138
106
|
end
|
139
107
|
end
|
@@ -6,7 +6,7 @@ module Kybus
|
|
6
6
|
include Kybus::Logger
|
7
7
|
|
8
8
|
attr_accessor :state
|
9
|
-
attr_reader :provider
|
9
|
+
attr_reader :provider, :args
|
10
10
|
|
11
11
|
def initialize(provider, state, bot)
|
12
12
|
@provider = provider
|
@@ -77,13 +77,17 @@ module Kybus
|
|
77
77
|
state&.command&.name
|
78
78
|
end
|
79
79
|
|
80
|
-
def redirect(*
|
81
|
-
@bot.redirect(*
|
80
|
+
def redirect(*)
|
81
|
+
@bot.redirect(*)
|
82
82
|
end
|
83
83
|
|
84
84
|
def abort(msg = nil)
|
85
85
|
raise ::Kybus::Bot::Base::AbortError, msg
|
86
86
|
end
|
87
|
+
|
88
|
+
def fork(command, arguments = {})
|
89
|
+
@bot.invoke_job(command, arguments)
|
90
|
+
end
|
87
91
|
end
|
88
92
|
end
|
89
93
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class Base
|
6
|
+
class BotError < StandardError; end
|
7
|
+
class AbortError < BotError; end
|
8
|
+
|
9
|
+
class EmptyMessageError < BotError
|
10
|
+
def initialize
|
11
|
+
super('Message is empty')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
module Forkers
|
6
|
+
class JobNotFound < ::Kybus::Bot::Base::BotError; end
|
7
|
+
class JobNotReady < ::Kybus::Bot::Base::BotError; end
|
8
|
+
|
9
|
+
extend Kybus::DRY::ResourceInjector
|
10
|
+
register(:forkers, {})
|
11
|
+
|
12
|
+
def self.register_forker(name, provider)
|
13
|
+
forkers = resource(:forkers)
|
14
|
+
forkers[name] = provider
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.forker(name)
|
18
|
+
forkers = resource(:forkers)
|
19
|
+
forkers[name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_config(bot, configs)
|
23
|
+
provider_name = configs&.dig('provider') || 'thread'
|
24
|
+
provider = forker(provider_name)
|
25
|
+
provider.new(bot, configs)
|
26
|
+
end
|
27
|
+
|
28
|
+
class Base
|
29
|
+
include Kybus::Logger
|
30
|
+
|
31
|
+
def initialize(bot, configs)
|
32
|
+
@configs = configs
|
33
|
+
@bot = bot
|
34
|
+
@command_definition = CommandDefinition.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def register_command(command, arguments, &)
|
38
|
+
@command_definition.register_command(command, arguments, &)
|
39
|
+
end
|
40
|
+
|
41
|
+
def fork(command, arguments, dsl)
|
42
|
+
job_definition = @command_definition[command]
|
43
|
+
raise JobNotFound if job_definition.nil?
|
44
|
+
|
45
|
+
raise JobNotReady unless job_definition.ready?(arguments)
|
46
|
+
|
47
|
+
invoke(command, arguments, job_definition, dsl)
|
48
|
+
end
|
49
|
+
|
50
|
+
def handle_job(command, args)
|
51
|
+
job_definition = @command_definition[command]
|
52
|
+
@bot.dsl.instance_eval do
|
53
|
+
@args = args
|
54
|
+
instance_eval(&job_definition.block)
|
55
|
+
end
|
56
|
+
log_info('Job Executed', command:, args:)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
module Forkers
|
6
|
+
class LambdaSQSForker < Base
|
7
|
+
extend Kybus::DRY::ResourceInjector
|
8
|
+
|
9
|
+
def self.register_queue_client(client)
|
10
|
+
register(:sqs, client)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(bot, configs)
|
14
|
+
super
|
15
|
+
@client = LambdaSQSForker.resource(:sqs)
|
16
|
+
@queue = configs['queue']
|
17
|
+
@queue_url = @client.get_queue_url(queue_name: @queue).queue_url
|
18
|
+
end
|
19
|
+
|
20
|
+
def invoke(command, args, _job_definition, dsl)
|
21
|
+
@client.send_message(queue_url: @queue_url, message_body: make_message(command, args, dsl).to_json)
|
22
|
+
end
|
23
|
+
|
24
|
+
def make_message(command, args, dsl)
|
25
|
+
{
|
26
|
+
job: command,
|
27
|
+
args: args.to_h,
|
28
|
+
state: dsl.state.to_h
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_job(command, args)
|
33
|
+
log_info('Got job from SQS', command:)
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
register_forker('sqs', LambdaSQSForker)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
module Forkers
|
6
|
+
class ThreadForker < Base
|
7
|
+
def invoke(command, args, _job_definition, _dsl)
|
8
|
+
Thread.new do
|
9
|
+
log_info('Forking job', command:)
|
10
|
+
handle_job(command, args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
register_forker('thread', ThreadForker)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/kybus/bot/migrator.rb
CHANGED
@@ -5,55 +5,73 @@ module Kybus
|
|
5
5
|
module Migrator
|
6
6
|
class << self
|
7
7
|
def run_migrations!(config)
|
8
|
-
|
8
|
+
migrator = migrator_for(config['name'])
|
9
|
+
migrator.run_migrations!(config)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def migrator_for(name)
|
15
|
+
case name
|
9
16
|
when 'sequel'
|
10
|
-
|
17
|
+
SequelMigrator
|
11
18
|
when 'dynamoid'
|
12
|
-
|
19
|
+
DynamoidMigrator
|
13
20
|
else
|
14
|
-
raise "Provider not supported #{
|
21
|
+
raise "Provider not supported #{name}"
|
15
22
|
end
|
16
23
|
end
|
24
|
+
end
|
17
25
|
|
18
|
-
|
26
|
+
class SequelMigrator
|
27
|
+
class << self
|
28
|
+
def run_migrations!(config)
|
29
|
+
require 'sequel'
|
30
|
+
require 'sequel/extensions/migration'
|
19
31
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
String :cmd
|
32
|
-
String :requested_param
|
33
|
-
String :last_message, text: true
|
32
|
+
conn = Sequel.connect(config['endpoint'])
|
33
|
+
conn.create_table?(:bot_sessions) do
|
34
|
+
String :channel_id
|
35
|
+
String :user
|
36
|
+
String :params, text: true
|
37
|
+
String :metadata, text: true
|
38
|
+
String :files, text: true
|
39
|
+
String :cmd
|
40
|
+
String :requested_param
|
41
|
+
String :last_message, text: true
|
42
|
+
end
|
34
43
|
end
|
35
44
|
end
|
45
|
+
end
|
36
46
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
47
|
+
class DynamoidMigrator
|
48
|
+
class << self
|
49
|
+
def run_migrations!(config)
|
50
|
+
repository = Kybus::Storage::Datasource::DynamoidRepository.from_config(
|
51
|
+
'name' => 'dynamoid',
|
52
|
+
'dynamoid_config' => true,
|
53
|
+
'access_key' => config['access_key'],
|
54
|
+
'secret_key' => config['secret_key'],
|
55
|
+
'region' => config['region'],
|
56
|
+
'endpoint' => config['endpoint'],
|
57
|
+
'namespace' => config['namespace'],
|
58
|
+
'table' => 'bot_sessions',
|
59
|
+
'primary_key' => 'channel_id',
|
60
|
+
'fields' => Base::DYNAMOID_FIELDS,
|
61
|
+
'read_capacity' => config['read_capacity'] || 1,
|
62
|
+
'write_capacity' => config['write_capacity'] || 1
|
63
|
+
)
|
64
|
+
|
65
|
+
create_table_if_not_exists(repository)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def create_table_if_not_exists(repository)
|
71
|
+
return if Dynamoid.adapter.list_tables.include?('bot_sessions')
|
72
|
+
|
73
|
+
repository.model_class.create_table(sync: true)
|
74
|
+
end
|
57
75
|
end
|
58
76
|
end
|
59
77
|
end
|
@@ -2,21 +2,15 @@
|
|
2
2
|
|
3
3
|
module Kybus
|
4
4
|
module Bot
|
5
|
-
# Base
|
5
|
+
# Base implementation for messages from distinct providers
|
6
6
|
class SerializedMessage < Message
|
7
7
|
MANDATORY_FIELDS = %i[channel_id provider message_id user raw_message].freeze
|
8
8
|
|
9
9
|
def initialize(data)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
missing_keys = MANDATORY_FIELDS.reject { |k| data.keys.include?(k) }
|
16
|
-
raise "BadSerializedMessage: Missing keys `#{missing_keys}', got: #{data}" unless missing_keys.empty?
|
17
|
-
|
18
|
-
@data = data.is_a?(String) ? JSON.parse(data, symbolize_names: true) : data
|
19
|
-
@data[:replied_message] = SerializedMessage.new(@data[:replied_message]) if @data[:replied_message]
|
10
|
+
super()
|
11
|
+
@data = parse_data(data)
|
12
|
+
validate_data!
|
13
|
+
parse_replied_message
|
20
14
|
end
|
21
15
|
|
22
16
|
def self.from_json(json)
|
@@ -32,7 +26,7 @@ module Kybus
|
|
32
26
|
!@data[attachment].nil?
|
33
27
|
end
|
34
28
|
|
35
|
-
def method_missing(method, *_args)
|
29
|
+
def method_missing(method, *_args) # rubocop:disable Style/MissingRespondToMissing
|
36
30
|
@data[method]
|
37
31
|
end
|
38
32
|
|
@@ -40,8 +34,32 @@ module Kybus
|
|
40
34
|
@data.dup
|
41
35
|
end
|
42
36
|
|
43
|
-
def to_json(*
|
44
|
-
@data.to_json(*
|
37
|
+
def to_json(*)
|
38
|
+
@data.to_json(*)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_data(data)
|
44
|
+
data = data.to_h if data.is_a?(SerializedMessage)
|
45
|
+
raise Base::BotError, 'BadSerializedMessage: nil message' if data.nil?
|
46
|
+
|
47
|
+
data = data[:data] if data.is_a?(Hash) && data.key?(:data)
|
48
|
+
data.is_a?(String) ? JSON.parse(data, symbolize_names: true) : data
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate_data!
|
52
|
+
missing_keys = MANDATORY_FIELDS.reject { |k| @data.key?(k) }
|
53
|
+
return if missing_keys.empty?
|
54
|
+
|
55
|
+
raise Base::BotError,
|
56
|
+
"BadSerializedMessage: Missing keys `#{missing_keys}', got: #{@data}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse_replied_message
|
60
|
+
return unless @data[:replied_message]
|
61
|
+
|
62
|
+
@data[:replied_message] = SerializedMessage.new(@data[:replied_message])
|
45
63
|
end
|
46
64
|
end
|
47
65
|
end
|