kybus-bot 0.7.0 → 0.8.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5c13b85c7bdfcde5cf2aabfa9c07e78a59da781c06d86ca91842605e3467b61
4
- data.tar.gz: ef7f22cea28720b25bbbee6930b397b28eb5890e1e470bb66155c691050ed101
3
+ metadata.gz: c7c076fdf29d45a346d07aa5639349a66cff1a83ed15f0cfbafc4e6d4698cbd9
4
+ data.tar.gz: 0fa6891cd37efd3a37b87b59e3dc90fd1628384c43863237e70ea6f757f2086a
5
5
  SHA512:
6
- metadata.gz: c01b8aadc1b567f9181ad731baa7861882ec535482c79c51eb45fee0257ab443ee9fc8857e133eab1b4dd814b725b4170fff2513484a1759f08ed1add74741ad
7
- data.tar.gz: e80319c534274c58df1cf58e8794a56c44100ac46c0483e0d7b9a193e612944efbf610dc3b6da24f91648ad764fa45fb8e7503f4a0774c5b1c541e8c41be3b6b
6
+ metadata.gz: f620f4d3674eb392f61f7a50abf378c1fa2fef5b718a93cf4ec1c340f906b1d924948f374fc0214d817664c26a97e4d5cdfa301c6588ba0c2e30bf5af8d7fb75
7
+ data.tar.gz: f2b708234bb392bfaf98d75f29720ea081ead5e3ea4cba36a7703abd9dcc7516e8328eb8f2583604c0de819e15c391ba1a7066cb3b74bf4ef39c0713186f6e96
@@ -11,7 +11,7 @@ module Kybus
11
11
  # Wraps a debugging message inside a class.
12
12
  class DebugMessage < Kybus::Bot::Message
13
13
  # It receives a string with the raw text and the id of the channel
14
- attr_reader :attachment
14
+ attr_reader :attachment, :message_id
15
15
 
16
16
  class DebugFile
17
17
  def initialize(path)
@@ -40,6 +40,9 @@ module Kybus
40
40
  @text = text
41
41
  @channel = channel
42
42
  @attachment = attachment
43
+ @@message_id ||= 0
44
+ @@message_id += 1
45
+ @message_id = @@message_id + 1
43
46
  end
44
47
 
45
48
  # Returns the channel id
@@ -110,6 +113,7 @@ module Kybus
110
113
  def answer(message, attachment = nil)
111
114
  send_data(message, attachment)
112
115
  @state = :open
116
+ DebugMessage.new(message, @name)
113
117
  end
114
118
  end
115
119
 
@@ -144,8 +148,8 @@ module Kybus
144
148
  loop do
145
149
  raise NoMoreMessageException if @channels.values.all?(&:empty?)
146
150
 
147
- msg = @channels.values.find(&:open?)
148
- return @last_message = msg.read_message if msg
151
+ open_channel = @channels.values.find(&:open?)
152
+ return @last_message = open_channel.read_message if open_channel
149
153
  end
150
154
  end
151
155
 
@@ -155,12 +159,12 @@ module Kybus
155
159
  end
156
160
 
157
161
  # interface for sending messages
158
- def send_message(channel_name, contents, attachment = nil)
162
+ def send_message(contents, channel_name, attachment = nil)
159
163
  channel(channel_name).answer(contents, attachment)
160
164
  end
161
165
 
162
166
  # interface for sending video
163
- def send_video(channel_name, video_url, caption = nil)
167
+ def send_video(channel_name, video_url, _caption = nil)
164
168
  channel(channel_name).answer("VIDEO: #{video_url}")
165
169
  end
166
170
 
@@ -170,7 +174,7 @@ module Kybus
170
174
  end
171
175
 
172
176
  # interface for sending image
173
- def send_image(channel_name, image_url, caption = nil)
177
+ def send_image(channel_name, image_url, _caption = nil)
174
178
  channel(channel_name).answer("IMG: #{image_url}")
175
179
  end
176
180
 
@@ -188,6 +192,13 @@ module Kybus
188
192
  end
189
193
  end
190
194
 
195
+ include Kybus::Logger
196
+
197
+ def message_builder(msg)
198
+ log_info('Building message object', msg:, msg_class: msg.class.name)
199
+ msg
200
+ end
201
+
191
202
  def mention(user)
192
203
  "@#{user}"
193
204
  end
@@ -80,7 +80,7 @@ module Kybus
80
80
  end
81
81
 
82
82
  # interface for sending messages
83
- def send_message(channel_name, contents, caption = nil)
83
+ def send_message(channel_name, contents, _caption = nil)
84
84
  puts "#{channel_name} => #{contents}" if @config['debug']
85
85
  channel = @client.channel(channel_name)
86
86
  if channel
@@ -47,12 +47,12 @@ module Kybus
47
47
  end
48
48
 
49
49
  # interface for sending messages
50
- def send_message(channel_name, contents)
50
+ def send_message(contents, channel_name)
51
51
  puts "#{channel_name} => #{contents}" if @config['debug']
52
- @client.api.send_message(chat_id: channel_name, text: contents)
52
+ @client.api.send_message(chat_id: channel_name.to_i, text: contents, parse_mode: @config['parse_mode'])
53
53
  # :nocov:
54
54
  rescue ::Telegram::Bot::Exceptions::ResponseError => e
55
- return if e[:error_code] == '403'
55
+ return if e.error_code == '403'
56
56
  end
57
57
  # :nocov:
58
58
 
@@ -80,6 +80,10 @@ module Kybus
80
80
  @client.api.send_document(chat_id: channel_name, document: file)
81
81
  end
82
82
 
83
+ def message_builder(raw_message)
84
+ TelegramMessage.new(raw_message)
85
+ end
86
+
83
87
  def file_builder(file)
84
88
  TelegramFile.new(file)
85
89
  end
@@ -43,6 +43,10 @@ module Kybus
43
43
  meta.dig('result', 'file_name')
44
44
  end
45
45
 
46
+ def file_name
47
+ original_name
48
+ end
49
+
46
50
  def download
47
51
  token = cli.api.token
48
52
  file_path = meta.dig('result', 'file_path')
@@ -17,7 +17,7 @@ module Kybus
17
17
  end
18
18
 
19
19
  def reply?
20
- !!@message.reply_to_message
20
+ @message.respond_to?(:reply_to_message) && @message.reply_to_message
21
21
  end
22
22
 
23
23
  def replied_message
@@ -29,6 +29,10 @@ module Kybus
29
29
  @message.chat.id
30
30
  end
31
31
 
32
+ def message_id
33
+ @message.respond_to?(:message_id) ? @message.message_id : @message['result']['message_id']
34
+ end
35
+
32
36
  # Returns the message contents
33
37
  def raw_message
34
38
  @message.to_s
@@ -43,7 +47,9 @@ module Kybus
43
47
  end
44
48
 
45
49
  def attachment
46
- @message.document || @message.photo&.last || @message.audio
50
+ (@message.respond_to?(:document) && @message&.document) ||
51
+ (@message.respond_to?(:photo) && @message.photo&.last) ||
52
+ (@message.respond_to?(:audio) && @message&.audio)
47
53
  end
48
54
 
49
55
  def user
@@ -63,6 +63,10 @@ module Kybus
63
63
  end
64
64
  end
65
65
 
66
+ def dsl
67
+ @executor.dsl
68
+ end
69
+
66
70
  # Starts the bot execution, this is a blocking call.
67
71
  def run
68
72
  # TODO: Implement an interface for killing the process
@@ -72,6 +76,15 @@ module Kybus
72
76
  # :nocov: #
73
77
  end
74
78
 
79
+ def redirect(command, *params)
80
+ @executor.invoke(command, params)
81
+ end
82
+
83
+ def send_message(contents, channel)
84
+ log_debug('Sending message', contents:, channel:)
85
+ provider.message_builder(@provider.send_message(contents, channel))
86
+ end
87
+
75
88
  def register_command(klass, params = [], &block)
76
89
  definitions.register_command(klass, params, &block)
77
90
  end
@@ -6,13 +6,21 @@ module Kybus
6
6
  # it currently only gets a param list, but it will be extended to a more
7
7
  # complex DSL.
8
8
  class Command
9
- attr_reader :block, :params, :name
9
+ attr_accessor :name
10
+ attr_reader :block, :params
10
11
 
11
12
  # Receives a list of params as symbols and the lambda with the block.
12
- def initialize(name, params, &block)
13
+ def initialize(name, params_config, &block)
13
14
  @name = name
14
- @params = params
15
15
  @block = block
16
+ case params_config
17
+ when Array
18
+ @params = params_config
19
+ @params_config = {}
20
+ when Hash
21
+ @params = params_config.keys
22
+ @params_config = params_config
23
+ end
16
24
  end
17
25
 
18
26
  # Checks if the params object given contains all the needed values
@@ -24,6 +32,14 @@ module Kybus
24
32
  def next_missing_param(current_params)
25
33
  params.find { |key| !current_params.key?(key) }.to_s
26
34
  end
35
+
36
+ def params_ask_label(param)
37
+ @params_config[param.to_sym]
38
+ end
39
+
40
+ def params_size
41
+ @params.size
42
+ end
27
43
  end
28
44
  end
29
45
  end
@@ -17,7 +17,7 @@ module Kybus
17
17
  end
18
18
 
19
19
  def ready?
20
- command.ready?(params)
20
+ command&.ready?(params)
21
21
  end
22
22
 
23
23
  # validates which is the following parameter required
@@ -66,7 +66,6 @@ module Kybus
66
66
  %i[params files].each do |param|
67
67
  @data[param] = @data[param].to_json
68
68
  end
69
-
70
69
  @data.store
71
70
  %i[params files].each do |param|
72
71
  @data[param] = backup[param]
@@ -14,8 +14,22 @@ module Kybus
14
14
  @definitions = definitions
15
15
  end
16
16
 
17
- def command(name)
18
- @definitions[name]
17
+ def command(search)
18
+ @definitions.each do |name, command|
19
+ case name
20
+ when String
21
+ return command if name == search
22
+ when Class
23
+ return command if search.is_a?(name)
24
+ when Regexp
25
+ if search.is_a?(String) && name.match?(search)
26
+ storable_command = command.clone
27
+ storable_command.name = search
28
+ return storable_command
29
+ end
30
+ end
31
+ end
32
+ nil
19
33
  end
20
34
 
21
35
  def default_command
@@ -28,17 +42,27 @@ module Kybus
28
42
 
29
43
  def command_with_inline_arg(name_with_arg)
30
44
  @definitions.each do |name, command|
31
- next unless name.is_a?(String)
32
- return [command, name_with_arg.gsub(name, '')] if name_with_arg.start_with?(name)
45
+ case name
46
+ when Class
47
+ return [command, []] if name_with_arg.is_a?(name)
48
+ when String
49
+ return [command, name_with_arg.gsub(name, '').split('__')] if name_with_arg.start_with?(name)
50
+ when Regexp
51
+ next unless name_with_arg.match?(name)
52
+
53
+ storable_command = command.dup
54
+ storable_command.name = name_with_arg
55
+ return [storable_command, [name_with_arg]]
56
+ end
33
57
  end
34
58
  nil
35
59
  end
36
60
 
37
61
  def load_state(channel)
38
- data = factory.get(channel)
39
- CommandState.new(data, command_or_default(data[:cmd]))
62
+ data = factory.get(channel.to_s)
63
+ CommandState.new(data, command(data[:cmd]))
40
64
  rescue Kybus::Storage::Exceptions::ObjectNotFound
41
- CommandState.new(factory.create(channel_id: channel, params: '{}'), nil)
65
+ CommandState.new(factory.create(channel_id: channel.to_s, params: '{}'), nil)
42
66
  end
43
67
  end
44
68
  end
@@ -17,8 +17,9 @@ module Kybus
17
17
 
18
18
  def call!(context)
19
19
  context.state = state
20
- context.instance_eval(&block)
20
+ statement = context.instance_eval(&block)
21
21
  clear_command
22
+ statement
22
23
  end
23
24
 
24
25
  def initialize(channel_id, channel_factory)
@@ -35,6 +36,10 @@ module Kybus
35
36
  state.store_param(param.to_sym, value)
36
37
  end
37
38
 
39
+ def expecting_command?
40
+ state.command.nil?
41
+ end
42
+
38
43
  def add_file(file)
39
44
  param = state.requested_param
40
45
  return unless param
@@ -22,7 +22,7 @@ module Kybus
22
22
  def initialize(bot, channel_factory, inline_args)
23
23
  @bot = bot
24
24
  @channel_factory = channel_factory
25
- @dsl = DSLMethods.new(bot.provider, state)
25
+ @dsl = DSLMethods.new(bot.provider, state, bot)
26
26
  @inline_args = inline_args
27
27
  @precommand_hook = proc {}
28
28
  end
@@ -32,8 +32,9 @@ module Kybus
32
32
  def process_message(message)
33
33
  @execution_context = ExecutionContest.new(message.channel_id, @channel_factory)
34
34
  save_token!(message)
35
- run_command_or_prepare!
35
+ msg = run_command_or_prepare!
36
36
  save_execution_context!
37
+ msg
37
38
  end
38
39
 
39
40
  def save_param!(message)
@@ -45,18 +46,20 @@ module Kybus
45
46
  end
46
47
 
47
48
  def search_command_with_inline_arg(message)
48
- command, value = @channel_factory.command_with_inline_arg(message.raw_message)
49
+ command, values = @channel_factory.command_with_inline_arg(message.raw_message)
49
50
  if command
50
51
  execution_context.command = command
51
- execution_context.next_param = execution_context.next_missing_param
52
- execution_context.add_param(value)
52
+ values.each do |value|
53
+ execution_context.next_param = execution_context.next_missing_param
54
+ execution_context.add_param(value)
55
+ end
53
56
  else
54
57
  execution_context.command = @channel_factory.default_command
55
58
  end
56
59
  end
57
60
 
58
61
  def save_token!(message)
59
- if message.command?
62
+ if execution_context.expecting_command?
60
63
  command = @channel_factory.command(message.command)
61
64
  if @inline_args && !command
62
65
  search_command_with_inline_arg(message)
@@ -74,9 +77,12 @@ module Kybus
74
77
  if execution_context.ready?
75
78
  @dsl.state = execution_context.state
76
79
  @dsl.instance_eval(&@precommand_hook)
77
- run_command!
80
+ msg = run_command!
81
+ execution_context.clear_command
82
+ msg
78
83
  else
79
- ask_param(execution_context.next_missing_param)
84
+ param = execution_context.next_missing_param
85
+ ask_param(param, execution_context.state.command.params_ask_label(param))
80
86
  end
81
87
  end
82
88
 
@@ -85,7 +91,7 @@ module Kybus
85
91
  end
86
92
 
87
93
  def fallback(error)
88
- catch = @channel_factory.command(error.class)
94
+ catch = @channel_factory.command(error)
89
95
  log_error('Unexpected error', error)
90
96
  execution_context.command = catch if catch
91
97
  end
@@ -96,15 +102,28 @@ module Kybus
96
102
  rescue StandardError => e
97
103
  raise unless fallback(e)
98
104
 
105
+ execution_context.state.store_param(:_last_exception, e)
99
106
  retry
100
107
  end
101
108
 
109
+ def invoke(command_name, args)
110
+ command = @channel_factory.command(command_name)
111
+ if command.nil? || command.params_size != args.size
112
+ raise "Wrong redirect #{command_name}, #{bot.registered_commands}"
113
+ end
114
+
115
+ state.command = command
116
+ command.params.zip(args).each do |param, value|
117
+ state.store_param(param, value)
118
+ end
119
+ run_command_or_prepare!
120
+ end
121
+
102
122
  # Sends a message to get the next parameter from the user
103
- def ask_param(param)
123
+ def ask_param(param, label = nil)
104
124
  provider = bot.provider
105
- msg = "I need you to tell me #{param}"
106
- log_debug(msg)
107
- provider.send_message(provider.last_message.channel_id, msg)
125
+ msg = label || "I need you to tell me #{param}"
126
+ bot.send_message(msg, provider.last_message.channel_id)
108
127
  execution_context.next_param = param
109
128
  end
110
129
  end
@@ -6,15 +6,16 @@ module Kybus
6
6
  attr_accessor :state
7
7
  attr_reader :provider
8
8
 
9
- def initialize(provider, state)
9
+ def initialize(provider, state, bot)
10
10
  @provider = provider
11
11
  @state = state
12
+ @bot = bot
12
13
  end
13
14
 
14
15
  def send_message(content, channel = nil)
15
16
  raise(Base::EmptyMessageError) unless content
16
17
 
17
- provider.send_message(channel || current_channel, content)
18
+ @bot.send_message(content, channel || current_channel)
18
19
  end
19
20
 
20
21
  def send_image(content, channel = nil, caption: nil)
@@ -65,6 +66,14 @@ module Kybus
65
66
  def current_channel
66
67
  state.channel_id
67
68
  end
69
+
70
+ def command_name
71
+ state&.command&.name
72
+ end
73
+
74
+ def method_missing(method, *args, &block)
75
+ @bot.send(method, *args, &block)
76
+ end
68
77
  end
69
78
  end
70
79
  end
@@ -21,12 +21,17 @@ module Kybus
21
21
  }.freeze
22
22
 
23
23
  def self.make_test_bot(extra_configs = {})
24
- new(CONFIG.merge(extra_configs))
24
+ conf = CONFIG.merge(extra_configs)
25
+ conf['provider']['channels'] = { conf['channel_id'] => [] } if conf['channel_id']
26
+ bot = new(conf)
27
+ bot.instance_variable_set(:@default_channel_id, conf['provider']['channels'].keys.first)
28
+ bot
25
29
  end
26
30
 
27
31
  def receives(msg, attachments = nil)
28
32
  attachments = Adapter::DebugMessage::DebugFile.new(attachments) if attachments
29
- msg = Adapter::DebugMessage.new(msg, 'testing', attachments)
33
+ msg = Adapter::DebugMessage.new(msg, @default_channel_id, attachments)
34
+ log_info('Received message', channel: @default_channel_id, msg:)
30
35
  provider.last_message = msg
31
36
  executor.process_message(msg)
32
37
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kybus
4
4
  module Bot
5
- VERSION = '0.7.0'
5
+ VERSION = '0.8.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kybus-bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gilberto Vargas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-17 00:00:00.000000000 Z
11
+ date: 2023-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kybus-core
@@ -253,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
253
253
  - !ruby/object:Gem::Version
254
254
  version: '0'
255
255
  requirements: []
256
- rubygems_version: 3.3.7
256
+ rubygems_version: 3.4.10
257
257
  signing_key:
258
258
  specification_version: 4
259
259
  summary: Provides a framework for building bots with ruby