kybus-bot 0.5.1 → 0.7.0
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 +55 -8
- data/lib/kybus/bot/adapters/discord.rb +9 -9
- data/lib/kybus/bot/adapters/telegram.rb +21 -98
- data/lib/kybus/bot/adapters/telegram_file.rb +55 -0
- data/lib/kybus/bot/adapters/telegram_message.rb +55 -0
- data/lib/kybus/bot/base.rb +31 -215
- data/lib/kybus/bot/{command_definition.rb → command/command.rb} +5 -25
- data/lib/kybus/bot/command/command_definition.rb +29 -0
- data/lib/kybus/bot/command/command_state.rb +77 -0
- data/lib/kybus/bot/command/command_state_factory.rb +45 -0
- data/lib/kybus/bot/command/execution_context.rb +58 -0
- data/lib/kybus/bot/command_executor.rb +112 -0
- data/lib/kybus/bot/dsl_methods.rb +70 -0
- data/lib/kybus/bot/message.rb +5 -8
- data/lib/kybus/bot/test.rb +13 -6
- data/lib/kybus/bot/version.rb +1 -1
- metadata +14 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5c13b85c7bdfcde5cf2aabfa9c07e78a59da781c06d86ca91842605e3467b61
|
4
|
+
data.tar.gz: ef7f22cea28720b25bbbee6930b397b28eb5890e1e470bb66155c691050ed101
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c01b8aadc1b567f9181ad731baa7861882ec535482c79c51eb45fee0257ab443ee9fc8857e133eab1b4dd814b725b4170fff2513484a1759f08ed1add74741ad
|
7
|
+
data.tar.gz: e80319c534274c58df1cf58e8794a56c44100ac46c0483e0d7b9a193e612944efbf610dc3b6da24f91648ad764fa45fb8e7503f4a0774c5b1c541e8c41be3b6b
|
@@ -13,7 +13,30 @@ module Kybus
|
|
13
13
|
# It receives a string with the raw text and the id of the channel
|
14
14
|
attr_reader :attachment
|
15
15
|
|
16
|
+
class DebugFile
|
17
|
+
def initialize(path)
|
18
|
+
@path = path
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_json(obj)
|
22
|
+
to_h.to_json(obj)
|
23
|
+
end
|
24
|
+
|
25
|
+
def file_name
|
26
|
+
@path
|
27
|
+
end
|
28
|
+
|
29
|
+
def download
|
30
|
+
File.read(@path)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_h
|
34
|
+
{ path: @path }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
16
38
|
def initialize(text, channel, attachment = nil)
|
39
|
+
super()
|
17
40
|
@text = text
|
18
41
|
@channel = channel
|
19
42
|
@attachment = attachment
|
@@ -36,6 +59,14 @@ module Kybus
|
|
36
59
|
def has_attachment?
|
37
60
|
!!attachment
|
38
61
|
end
|
62
|
+
|
63
|
+
def reply?
|
64
|
+
@reply
|
65
|
+
end
|
66
|
+
|
67
|
+
def is_private?
|
68
|
+
true
|
69
|
+
end
|
39
70
|
end
|
40
71
|
|
41
72
|
# This class simulates a message chat with a user.
|
@@ -66,7 +97,7 @@ module Kybus
|
|
66
97
|
DebugMessage.new(@pending_messages.shift, @name)
|
67
98
|
end
|
68
99
|
|
69
|
-
def send_data(message,
|
100
|
+
def send_data(message, _attachment)
|
70
101
|
return unless @echo
|
71
102
|
|
72
103
|
puts "Sending message to channel: #{@name}"
|
@@ -92,6 +123,8 @@ module Kybus
|
|
92
123
|
end
|
93
124
|
end
|
94
125
|
|
126
|
+
attr_accessor :last_message
|
127
|
+
|
95
128
|
# It receives a hash with the configurations:
|
96
129
|
# - name: the name of the channel
|
97
130
|
# - channels a key value, where the key is a name and the value the
|
@@ -112,11 +145,7 @@ module Kybus
|
|
112
145
|
raise NoMoreMessageException if @channels.values.all?(&:empty?)
|
113
146
|
|
114
147
|
msg = @channels.values.find(&:open?)
|
115
|
-
return msg.read_message if msg
|
116
|
-
|
117
|
-
# :nocov: #
|
118
|
-
sleep(1)
|
119
|
-
# :nocov: #
|
148
|
+
return @last_message = msg.read_message if msg
|
120
149
|
end
|
121
150
|
end
|
122
151
|
|
@@ -131,7 +160,7 @@ module Kybus
|
|
131
160
|
end
|
132
161
|
|
133
162
|
# interface for sending video
|
134
|
-
def send_video(channel_name, video_url)
|
163
|
+
def send_video(channel_name, video_url, caption = nil)
|
135
164
|
channel(channel_name).answer("VIDEO: #{video_url}")
|
136
165
|
end
|
137
166
|
|
@@ -141,10 +170,28 @@ module Kybus
|
|
141
170
|
end
|
142
171
|
|
143
172
|
# interface for sending image
|
144
|
-
def send_image(channel_name, image_url)
|
173
|
+
def send_image(channel_name, image_url, caption = nil)
|
145
174
|
channel(channel_name).answer("IMG: #{image_url}")
|
146
175
|
end
|
147
176
|
|
177
|
+
# interface for sending image
|
178
|
+
def send_document(channel_name, doc_url)
|
179
|
+
channel(channel_name).answer("DOC: #{doc_url}")
|
180
|
+
end
|
181
|
+
|
182
|
+
def file_builder(data)
|
183
|
+
case data
|
184
|
+
when DebugMessage::DebugFile
|
185
|
+
data
|
186
|
+
when Hash
|
187
|
+
DebugMessage::DebugFile.new(data[:path])
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def mention(user)
|
192
|
+
"@#{user}"
|
193
|
+
end
|
194
|
+
|
148
195
|
# changes echo config
|
149
196
|
def echo=(toogle)
|
150
197
|
@channels.each { |_, channel| channel.echo = toogle }
|
@@ -11,6 +11,7 @@ module Kybus
|
|
11
11
|
class DiscordMessage < Kybus::Bot::Message
|
12
12
|
# It receives a string with the raw text and the id of the channel
|
13
13
|
def initialize(msg)
|
14
|
+
super
|
14
15
|
@message = msg
|
15
16
|
end
|
16
17
|
|
@@ -45,6 +46,9 @@ module Kybus
|
|
45
46
|
# This adapter is intended to be used on unit tests and development.
|
46
47
|
class Discord
|
47
48
|
include ::Kybus::Logger
|
49
|
+
|
50
|
+
attr_reader :last_message, :client
|
51
|
+
|
48
52
|
# It receives a hash with the configurations:
|
49
53
|
# - name: the name of the channel
|
50
54
|
# - channels a key value, where the key is a name and the value the
|
@@ -60,8 +64,6 @@ module Kybus
|
|
60
64
|
@client.run(:async)
|
61
65
|
end
|
62
66
|
|
63
|
-
attr_reader :client
|
64
|
-
|
65
67
|
def mention(id)
|
66
68
|
"<@!#{id}>"
|
67
69
|
end
|
@@ -70,17 +72,15 @@ module Kybus
|
|
70
72
|
def read_message
|
71
73
|
# take the first message from the first open message,
|
72
74
|
loop do
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
break
|
77
|
-
end
|
75
|
+
break unless @pool.empty?
|
76
|
+
|
77
|
+
sleep(0.1)
|
78
78
|
end
|
79
|
-
DiscordMessage.new(@pool.shift)
|
79
|
+
@last_message = DiscordMessage.new(@pool.shift)
|
80
80
|
end
|
81
81
|
|
82
82
|
# interface for sending messages
|
83
|
-
def send_message(channel_name, contents)
|
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
|
@@ -1,100 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'telegram/bot'
|
4
|
+
require 'faraday'
|
5
|
+
require_relative 'telegram_file'
|
6
|
+
require_relative 'telegram_message'
|
4
7
|
|
5
8
|
module Kybus
|
6
9
|
module Bot
|
7
|
-
# :nodoc: #
|
8
10
|
module Adapter
|
9
|
-
# :nodoc: #
|
10
|
-
# Wraps a debugging message inside a class.
|
11
|
-
class TelegramMessage < Kybus::Bot::Message
|
12
|
-
# It receives a string with the raw text and the id of the channel
|
13
|
-
def initialize(message)
|
14
|
-
@message = message
|
15
|
-
end
|
16
|
-
|
17
|
-
def reply?
|
18
|
-
!!@message.reply_to_message
|
19
|
-
end
|
20
|
-
|
21
|
-
def replied_message
|
22
|
-
TelegramMessage.new(@message.reply_to_message)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Returns the channel id
|
26
|
-
def channel_id
|
27
|
-
@message.chat.id
|
28
|
-
end
|
29
|
-
|
30
|
-
# Returns the message contents
|
31
|
-
def raw_message
|
32
|
-
@message.to_s
|
33
|
-
end
|
34
|
-
|
35
|
-
def is_private?
|
36
|
-
@message.chat.type == 'private'
|
37
|
-
end
|
38
|
-
|
39
|
-
def has_attachment?
|
40
|
-
!!@message.document
|
41
|
-
end
|
42
|
-
|
43
|
-
def attachment
|
44
|
-
@message.document
|
45
|
-
end
|
46
|
-
|
47
|
-
def user
|
48
|
-
@message.from.id
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class TelegramFile
|
53
|
-
extend Kybus::DRY::ResourceInjector
|
54
|
-
attr_reader :id
|
55
|
-
def initialize(message)
|
56
|
-
if message.is_a?(String)
|
57
|
-
@id = message
|
58
|
-
elsif message.is_a?(Hash)
|
59
|
-
@id = message['id'] || message[:id]
|
60
|
-
elsif message.is_a?(TelegramFile)
|
61
|
-
@id = message.id
|
62
|
-
else
|
63
|
-
@id = message.file_id
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def to_h
|
68
|
-
{
|
69
|
-
provide: 'telegram',
|
70
|
-
id: @id
|
71
|
-
}
|
72
|
-
end
|
73
|
-
|
74
|
-
def cli
|
75
|
-
@cli ||= TelegramFile.resource(:cli)
|
76
|
-
end
|
77
|
-
|
78
|
-
def meta
|
79
|
-
@meta ||= cli.api.get_file(file_id: @id)
|
80
|
-
end
|
81
|
-
|
82
|
-
def original_name
|
83
|
-
meta.dig('result', 'file_name')
|
84
|
-
end
|
85
|
-
|
86
|
-
def download
|
87
|
-
token = cli.api.token
|
88
|
-
file_path = meta.dig('result', 'file_path')
|
89
|
-
path = "https://api.telegram.org/file/bot#{token}/#{file_path}"
|
90
|
-
Faraday.get(path).body
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
11
|
##
|
95
12
|
# This adapter is intended to be used on unit tests and development.
|
96
13
|
class Telegram
|
97
14
|
include ::Kybus::Logger
|
15
|
+
|
16
|
+
attr_reader :last_message
|
17
|
+
|
98
18
|
# It receives a hash with the configurations:
|
99
19
|
# - name: the name of the channel
|
100
20
|
# - channels a key value, where the key is a name and the value the
|
@@ -113,10 +33,12 @@ module Kybus
|
|
113
33
|
@client.listen do |message|
|
114
34
|
log_info('Received message', message: message.to_h,
|
115
35
|
from: message.from.to_h)
|
116
|
-
return TelegramMessage.new(message)
|
36
|
+
return @last_message = TelegramMessage.new(message)
|
117
37
|
end
|
118
38
|
rescue ::Telegram::Bot::Exceptions::ResponseError => e
|
39
|
+
# :nocov:
|
119
40
|
log_error('An error ocurred while calling to Telegram API', e)
|
41
|
+
# :nocov:
|
120
42
|
end
|
121
43
|
end
|
122
44
|
|
@@ -124,36 +46,37 @@ module Kybus
|
|
124
46
|
"[user](tg://user?id=#{id})"
|
125
47
|
end
|
126
48
|
|
127
|
-
|
128
49
|
# interface for sending messages
|
129
50
|
def send_message(channel_name, contents)
|
130
51
|
puts "#{channel_name} => #{contents}" if @config['debug']
|
131
52
|
@client.api.send_message(chat_id: channel_name, text: contents)
|
132
|
-
|
133
|
-
|
53
|
+
# :nocov:
|
54
|
+
rescue ::Telegram::Bot::Exceptions::ResponseError => e
|
55
|
+
return if e[:error_code] == '403'
|
134
56
|
end
|
57
|
+
# :nocov:
|
135
58
|
|
136
59
|
# interface for sending video
|
137
|
-
def send_video(channel_name, video_url)
|
138
|
-
file = Faraday::
|
139
|
-
@client.api.send_video(chat_id: channel_name,
|
60
|
+
def send_video(channel_name, video_url, comment = nil)
|
61
|
+
file = Faraday::FilePart.new(video_url, 'video/mp4')
|
62
|
+
@client.api.send_video(chat_id: channel_name, video: file, caption: comment)
|
140
63
|
end
|
141
64
|
|
142
65
|
# interface for sending uadio
|
143
66
|
def send_audio(channel_name, audio_url)
|
144
|
-
file = Faraday::
|
67
|
+
file = Faraday::FilePart.new(audio_url, 'audio/mp3')
|
145
68
|
@client.api.send_audio(chat_id: channel_name, audio: file)
|
146
69
|
end
|
147
70
|
|
148
71
|
# interface for sending image
|
149
|
-
def send_image(channel_name, image_url)
|
150
|
-
file = Faraday::
|
151
|
-
@client.api.send_photo(chat_id: channel_name, photo: file)
|
72
|
+
def send_image(channel_name, image_url, comment = nil)
|
73
|
+
file = Faraday::FilePart.new(image_url, 'image/jpeg')
|
74
|
+
@client.api.send_photo(chat_id: channel_name, photo: file, caption: comment)
|
152
75
|
end
|
153
76
|
|
154
77
|
# interface for sending document
|
155
78
|
def send_document(channel_name, image_url)
|
156
|
-
file = Faraday::
|
79
|
+
file = Faraday::FilePart.new(image_url, 'application/octect-stream')
|
157
80
|
@client.api.send_document(chat_id: channel_name, document: file)
|
158
81
|
end
|
159
82
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'telegram/bot'
|
4
|
+
require 'faraday'
|
5
|
+
|
6
|
+
module Kybus
|
7
|
+
module Bot
|
8
|
+
# :nodoc: #
|
9
|
+
module Adapter
|
10
|
+
class TelegramFile
|
11
|
+
extend Kybus::DRY::ResourceInjector
|
12
|
+
attr_reader :id
|
13
|
+
|
14
|
+
def initialize(message)
|
15
|
+
@id = case message
|
16
|
+
when String
|
17
|
+
message
|
18
|
+
when Hash
|
19
|
+
message['id'] || message[:id]
|
20
|
+
when TelegramFile
|
21
|
+
message.id
|
22
|
+
else
|
23
|
+
message.file_id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_h
|
28
|
+
{
|
29
|
+
provide: 'telegram',
|
30
|
+
id: @id
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def cli
|
35
|
+
@cli ||= TelegramFile.resource(:cli)
|
36
|
+
end
|
37
|
+
|
38
|
+
def meta
|
39
|
+
@meta ||= cli.api.get_file(file_id: @id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def original_name
|
43
|
+
meta.dig('result', 'file_name')
|
44
|
+
end
|
45
|
+
|
46
|
+
def download
|
47
|
+
token = cli.api.token
|
48
|
+
file_path = meta.dig('result', 'file_path')
|
49
|
+
path = "https://api.telegram.org/file/bot#{token}/#{file_path}"
|
50
|
+
Faraday.get(path).body
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'telegram/bot'
|
4
|
+
require 'faraday'
|
5
|
+
|
6
|
+
module Kybus
|
7
|
+
module Bot
|
8
|
+
# :nodoc: #
|
9
|
+
module Adapter
|
10
|
+
# :nodoc: #
|
11
|
+
# Wraps a debugging message inside a class.
|
12
|
+
class TelegramMessage < Kybus::Bot::Message
|
13
|
+
# It receives a string with the raw text and the id of the channel
|
14
|
+
def initialize(message)
|
15
|
+
super()
|
16
|
+
@message = message
|
17
|
+
end
|
18
|
+
|
19
|
+
def reply?
|
20
|
+
!!@message.reply_to_message
|
21
|
+
end
|
22
|
+
|
23
|
+
def replied_message
|
24
|
+
TelegramMessage.new(@message.reply_to_message)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the channel id
|
28
|
+
def channel_id
|
29
|
+
@message.chat.id
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the message contents
|
33
|
+
def raw_message
|
34
|
+
@message.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_private?
|
38
|
+
@message.chat.type == 'private'
|
39
|
+
end
|
40
|
+
|
41
|
+
def has_attachment?
|
42
|
+
!!attachment
|
43
|
+
end
|
44
|
+
|
45
|
+
def attachment
|
46
|
+
@message.document || @message.photo&.last || @message.audio
|
47
|
+
end
|
48
|
+
|
49
|
+
def user
|
50
|
+
@message.from.id
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/kybus/bot/base.rb
CHANGED
@@ -3,19 +3,19 @@
|
|
3
3
|
require 'kybus/dry/daemon'
|
4
4
|
require 'kybus/bot/adapters/base'
|
5
5
|
require 'kybus/storage'
|
6
|
-
require_relative '
|
6
|
+
require_relative 'command/command_state'
|
7
|
+
require_relative 'dsl_methods'
|
8
|
+
require_relative 'command_executor'
|
9
|
+
require_relative 'command/command_state_factory'
|
7
10
|
|
8
11
|
require 'kybus/logger'
|
12
|
+
require 'forwardable'
|
9
13
|
|
10
14
|
module Kybus
|
11
15
|
module Bot
|
12
16
|
# Base class for bot implementation. It wraps the threads execution, the
|
13
17
|
# provider and the state storage inside an object.
|
14
18
|
class Base
|
15
|
-
include Kybus::Storage::Datasource
|
16
|
-
include Kybus::Logger
|
17
|
-
attr_reader :provider
|
18
|
-
|
19
19
|
class BotError < StandardError; end
|
20
20
|
|
21
21
|
class EmptyMessageError < BotError
|
@@ -24,26 +24,13 @@ module Kybus
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
provider.send_message(channel || current_channel, content)
|
30
|
-
end
|
31
|
-
|
32
|
-
def rescue_from(klass, &block)
|
33
|
-
@commands.register_command(klass, [], block)
|
34
|
-
end
|
35
|
-
|
36
|
-
def send_image(content, channel = nil)
|
37
|
-
provider.send_image(channel || current_channel, content)
|
38
|
-
end
|
27
|
+
extend Forwardable
|
28
|
+
include Kybus::Logger
|
39
29
|
|
40
|
-
|
41
|
-
provider.send_audio(channel || current_channel, content)
|
42
|
-
end
|
30
|
+
attr_reader :provider, :executor, :pool_size, :pool, :definitions
|
43
31
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
32
|
+
def_delegators :executor, :state, :precommand_hook
|
33
|
+
def_delegators :definitions, :registered_commands
|
47
34
|
|
48
35
|
# Configurations needed:
|
49
36
|
# - pool_size: number of threads created in execution
|
@@ -52,216 +39,45 @@ module Kybus
|
|
52
39
|
# - name: The bot name
|
53
40
|
# - repository: Configurations about the state storage
|
54
41
|
def initialize(configs)
|
55
|
-
|
42
|
+
build_pool(configs['pool_size'])
|
56
43
|
@provider = Kybus::Bot::Adapter.from_config(configs['provider'])
|
57
|
-
@commands = Kybus::Bot::CommandDefinition.new
|
58
|
-
register_command('default') do; end
|
59
|
-
|
60
44
|
# TODO: move this to config
|
61
|
-
|
45
|
+
repository = Kybus::Storage::Repository.from_config(
|
62
46
|
nil,
|
63
|
-
configs['state_repository']
|
64
|
-
.merge('primary_key' => 'channel_id',
|
65
|
-
'table' => 'bot_sessions'),
|
47
|
+
configs['state_repository'].merge('primary_key' => 'channel_id', 'table' => 'bot_sessions'),
|
66
48
|
{}
|
67
49
|
)
|
68
|
-
@
|
69
|
-
|
70
|
-
@
|
50
|
+
@definitions = Kybus::Bot::CommandDefinition.new
|
51
|
+
command_factory = CommandStateFactory.new(repository, @definitions)
|
52
|
+
@executor = Kybus::Bot::CommandExecutor.new(self, command_factory, configs['inline_args'])
|
53
|
+
register_command('default') { nil }
|
71
54
|
end
|
72
55
|
|
73
|
-
|
74
|
-
|
75
|
-
@pool = Array.new(@pool_size) do
|
56
|
+
def build_pool(pool_size)
|
57
|
+
@pool = Array.new(pool_size) do
|
76
58
|
# TODO: Create a subclass with the context execution
|
77
|
-
Kybus::DRY::Daemon.new(
|
59
|
+
Kybus::DRY::Daemon.new(pool_size, true) do
|
78
60
|
message = provider.read_message
|
79
|
-
|
80
|
-
process_message(message)
|
61
|
+
executor.process_message(message)
|
81
62
|
end
|
82
63
|
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Starts the bot execution, this is a blocking call.
|
67
|
+
def run
|
83
68
|
# TODO: Implement an interface for killing the process
|
84
|
-
|
69
|
+
pool.each(&:run)
|
85
70
|
# :nocov: #
|
86
|
-
|
71
|
+
pool.each(&:await)
|
87
72
|
# :nocov: #
|
88
73
|
end
|
89
74
|
|
90
|
-
|
91
|
-
|
92
|
-
def process_message(message)
|
93
|
-
run_simple_command!(message)
|
94
|
-
end
|
95
|
-
|
96
|
-
# Executes a command with the easiest definition. It runs a state machine:
|
97
|
-
# - If the message is a command, set the status to asking params
|
98
|
-
# - If the message is a param, stores it
|
99
|
-
# - If the command is ready to be executed, trigger it.
|
100
|
-
def run_simple_command!(message)
|
101
|
-
load_state!(message.channel_id)
|
102
|
-
log_debug('loaded state', message: message.to_h, state: @state.to_h)
|
103
|
-
if message.command?
|
104
|
-
self.command = message.raw_message
|
105
|
-
else
|
106
|
-
add_param(message.raw_message)
|
107
|
-
add_file(message.attachment) if message.has_attachment?
|
108
|
-
end
|
109
|
-
if command_ready?
|
110
|
-
run_command!
|
111
|
-
else
|
112
|
-
ask_param(next_missing_param)
|
113
|
-
end
|
114
|
-
save_state!
|
115
|
-
rescue StandardError => e
|
116
|
-
catch = @commands[e.class]
|
117
|
-
raise if catch.nil?
|
118
|
-
|
119
|
-
instance_eval(&catch.block)
|
120
|
-
clear_command
|
121
|
-
end
|
122
|
-
|
123
|
-
# DSL method for adding simple commands
|
124
|
-
def register_command(name, params = [], &block)
|
125
|
-
@commands.register_command(name, params, block)
|
126
|
-
end
|
127
|
-
|
128
|
-
# Method for triggering command
|
129
|
-
def run_command!
|
130
|
-
instance_eval(¤t_command_object.block)
|
131
|
-
clear_command
|
132
|
-
end
|
133
|
-
|
134
|
-
def clear_command
|
135
|
-
@state[:cmd] = nil
|
136
|
-
end
|
137
|
-
|
138
|
-
# Checks if the command is ready to be executed
|
139
|
-
def command_ready?
|
140
|
-
cmd = current_command_object
|
141
|
-
cmd.ready?(current_params)
|
142
|
-
end
|
143
|
-
|
144
|
-
# loads parameters from state
|
145
|
-
def current_params
|
146
|
-
@state[:params] || {}
|
147
|
-
end
|
148
|
-
|
149
|
-
def params
|
150
|
-
current_params
|
151
|
-
end
|
152
|
-
|
153
|
-
def add_file(file)
|
154
|
-
return if @state[:requested_param].nil?
|
155
|
-
|
156
|
-
log_debug('Received new file',
|
157
|
-
param: @state[:requested_param].to_sym,
|
158
|
-
file: file.to_h)
|
159
|
-
|
160
|
-
files[@state[:requested_param].to_sym] = provider.file_builder(file)
|
161
|
-
@state[:params][("_#{@state[:requested_param]}_filename").to_sym] = file.file_name
|
162
|
-
end
|
163
|
-
|
164
|
-
def files
|
165
|
-
@state[:files] ||= {}
|
166
|
-
end
|
167
|
-
|
168
|
-
def file(name)
|
169
|
-
(file = files[name]) && provider.file_builder(file)
|
170
|
-
end
|
171
|
-
|
172
|
-
def mention(name)
|
173
|
-
provider.mention(name)
|
174
|
-
end
|
175
|
-
|
176
|
-
def registered_commands
|
177
|
-
@commands.registered_commands
|
178
|
-
end
|
179
|
-
|
180
|
-
# Loads command from state
|
181
|
-
def current_command_object
|
182
|
-
command = @state[:cmd]
|
183
|
-
@commands[command] || @commands['default']
|
75
|
+
def register_command(klass, params = [], &block)
|
76
|
+
definitions.register_command(klass, params, &block)
|
184
77
|
end
|
185
78
|
|
186
|
-
|
187
|
-
|
188
|
-
@state[:channel_id]
|
189
|
-
end
|
190
|
-
|
191
|
-
def current_user
|
192
|
-
@last_message.user
|
193
|
-
end
|
194
|
-
|
195
|
-
def is_private?
|
196
|
-
@last_message.is_private?
|
197
|
-
end
|
198
|
-
|
199
|
-
# stores the command into state
|
200
|
-
def command=(cmd)
|
201
|
-
log_debug('Message set as command', command: cmd)
|
202
|
-
|
203
|
-
@state[:cmd] = cmd.split(' ').first
|
204
|
-
@state[:params] = { }
|
205
|
-
@state[:files] = { }
|
206
|
-
end
|
207
|
-
|
208
|
-
# validates which is the following parameter required
|
209
|
-
def next_missing_param
|
210
|
-
current_command_object.next_missing_param(current_params)
|
211
|
-
end
|
212
|
-
|
213
|
-
# Sends a message to get the next parameter from the user
|
214
|
-
def ask_param(param)
|
215
|
-
log_debug('I\'m going to ask the next param', param: param)
|
216
|
-
provider.send_message(current_channel,
|
217
|
-
"I need you to tell me #{param}")
|
218
|
-
@state[:requested_param] = param.to_s
|
219
|
-
end
|
220
|
-
|
221
|
-
# Stores a parameter into the status
|
222
|
-
def add_param(value)
|
223
|
-
return if @state[:requested_param].nil?
|
224
|
-
|
225
|
-
log_debug('Received new param',
|
226
|
-
param: @state[:requested_param].to_sym,
|
227
|
-
value: value)
|
228
|
-
|
229
|
-
@state[:params][@state[:requested_param].to_sym] = value
|
230
|
-
end
|
231
|
-
|
232
|
-
# Loads the state from storage
|
233
|
-
def load_state!(channel)
|
234
|
-
@state = load_state(channel)
|
235
|
-
end
|
236
|
-
|
237
|
-
# Private implementation for load message
|
238
|
-
def load_state(channel)
|
239
|
-
data = @factory.get(channel)
|
240
|
-
data[:params] = JSON.parse(data[:params] || '{}', symbolize_names: true)
|
241
|
-
data[:files] = JSON.parse(data[:files] || '{}', symbolize_names: true)
|
242
|
-
data
|
243
|
-
rescue Kybus::Storage::Exceptions::ObjectNotFound
|
244
|
-
@factory.create(channel_id: channel, params: {}.to_json)
|
245
|
-
end
|
246
|
-
|
247
|
-
def parse_state!
|
248
|
-
end
|
249
|
-
|
250
|
-
# Saves the state into storage
|
251
|
-
def save_state!
|
252
|
-
backup = @state.clone
|
253
|
-
%i[params files].each do |param|
|
254
|
-
@state[param] = @state[param].to_json
|
255
|
-
end
|
256
|
-
|
257
|
-
@state.store
|
258
|
-
%i[params files].each do |param|
|
259
|
-
@state[param] = backup[param]
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
def session
|
264
|
-
@repository
|
79
|
+
def rescue_from(klass, &block)
|
80
|
+
definitions.register_command(klass, [], &block)
|
265
81
|
end
|
266
82
|
end
|
267
83
|
end
|
@@ -6,43 +6,23 @@ 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
|
9
|
+
attr_reader :block, :params, :name
|
10
10
|
|
11
11
|
# Receives a list of params as symbols and the lambda with the block.
|
12
|
-
def initialize(params, block)
|
12
|
+
def initialize(name, params, &block)
|
13
|
+
@name = name
|
13
14
|
@params = params
|
14
15
|
@block = block
|
15
16
|
end
|
16
17
|
|
17
18
|
# Checks if the params object given contains all the needed values
|
18
19
|
def ready?(current_params)
|
19
|
-
|
20
|
+
params.all? { |key| current_params.key?(key) }
|
20
21
|
end
|
21
22
|
|
22
23
|
# Finds the first empty param from the given parameter
|
23
24
|
def next_missing_param(current_params)
|
24
|
-
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Wraps a collection of commands.
|
29
|
-
class CommandDefinition
|
30
|
-
def initialize
|
31
|
-
@commands = {}
|
32
|
-
end
|
33
|
-
|
34
|
-
# Stores an operation definition
|
35
|
-
def register_command(name, params, block)
|
36
|
-
@commands[name] = Command.new(params, block)
|
37
|
-
end
|
38
|
-
|
39
|
-
def registered_commands
|
40
|
-
@commands.keys
|
41
|
-
end
|
42
|
-
|
43
|
-
# Returns a command with the name
|
44
|
-
def [](name)
|
45
|
-
@commands[name]
|
25
|
+
params.find { |key| !current_params.key?(key) }.to_s
|
46
26
|
end
|
47
27
|
end
|
48
28
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class CommandDefinition
|
6
|
+
def initialize
|
7
|
+
@commands = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Stores an operation definition
|
11
|
+
def register_command(name, params, &block)
|
12
|
+
@commands[name] = Command.new(name, params, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def registered_commands
|
16
|
+
@commands.keys
|
17
|
+
end
|
18
|
+
|
19
|
+
def each(&block)
|
20
|
+
@commands.each(&block)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a command with the name
|
24
|
+
def [](name)
|
25
|
+
@commands[name]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class CommandState
|
6
|
+
attr_reader :command
|
7
|
+
|
8
|
+
def initialize(data, command)
|
9
|
+
@command = command
|
10
|
+
data[:params] = JSON.parse(data[:params] || '{}', symbolize_names: true)
|
11
|
+
data[:files] = JSON.parse(data[:files] || '{}', symbolize_names: true)
|
12
|
+
@data = data
|
13
|
+
end
|
14
|
+
|
15
|
+
def clear_command
|
16
|
+
@data[:cmd] = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def ready?
|
20
|
+
command.ready?(params)
|
21
|
+
end
|
22
|
+
|
23
|
+
# validates which is the following parameter required
|
24
|
+
def next_missing_param
|
25
|
+
command.next_missing_param(params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def command=(cmd)
|
29
|
+
@command = cmd
|
30
|
+
@data[:cmd] = cmd.name
|
31
|
+
@data[:params] = {}
|
32
|
+
@data[:files] = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def params
|
36
|
+
@data[:params] || {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def channel_id
|
40
|
+
@data[:channel_id]
|
41
|
+
end
|
42
|
+
|
43
|
+
def files
|
44
|
+
@data[:files] || {}
|
45
|
+
end
|
46
|
+
|
47
|
+
def save_file(identifier, file)
|
48
|
+
files[identifier] = file
|
49
|
+
store_param("_#{@data[:requested_param]}_filename".to_sym, file.file_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def requested_param=(param)
|
53
|
+
@data[:requested_param] = param
|
54
|
+
end
|
55
|
+
|
56
|
+
def requested_param
|
57
|
+
@data[:requested_param]
|
58
|
+
end
|
59
|
+
|
60
|
+
def store_param(param, value)
|
61
|
+
@data[:params][param] = value
|
62
|
+
end
|
63
|
+
|
64
|
+
def save!
|
65
|
+
backup = @data.clone
|
66
|
+
%i[params files].each do |param|
|
67
|
+
@data[param] = @data[param].to_json
|
68
|
+
end
|
69
|
+
|
70
|
+
@data.store
|
71
|
+
%i[params files].each do |param|
|
72
|
+
@data[param] = backup[param]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class CommandStateFactory
|
6
|
+
include Kybus::Storage::Datasource
|
7
|
+
attr_reader :factory
|
8
|
+
|
9
|
+
def initialize(repository, definitions)
|
10
|
+
factory = Kybus::Storage::Factory.new(EmptyModel)
|
11
|
+
factory.register(:default, :json)
|
12
|
+
factory.register(:json, repository)
|
13
|
+
@factory = factory
|
14
|
+
@definitions = definitions
|
15
|
+
end
|
16
|
+
|
17
|
+
def command(name)
|
18
|
+
@definitions[name]
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_command
|
22
|
+
@definitions['default']
|
23
|
+
end
|
24
|
+
|
25
|
+
def command_or_default(name)
|
26
|
+
command(name) || default_command
|
27
|
+
end
|
28
|
+
|
29
|
+
def command_with_inline_arg(name_with_arg)
|
30
|
+
@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)
|
33
|
+
end
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_state(channel)
|
38
|
+
data = factory.get(channel)
|
39
|
+
CommandState.new(data, command_or_default(data[:cmd]))
|
40
|
+
rescue Kybus::Storage::Exceptions::ObjectNotFound
|
41
|
+
CommandState.new(factory.create(channel_id: channel, params: '{}'), nil)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class ExecutionContest
|
6
|
+
include Kybus::Logger
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_reader :state
|
10
|
+
|
11
|
+
def_delegator :state, :requested_param=, :next_param=
|
12
|
+
def_delegators :state, :clear_command, :save!, :ready?, :next_missing_param
|
13
|
+
|
14
|
+
def block
|
15
|
+
state.command.block
|
16
|
+
end
|
17
|
+
|
18
|
+
def call!(context)
|
19
|
+
context.state = state
|
20
|
+
context.instance_eval(&block)
|
21
|
+
clear_command
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(channel_id, channel_factory)
|
25
|
+
@channel_factory = channel_factory
|
26
|
+
load_state!(channel_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Stores a parameter into the status
|
30
|
+
def add_param(value)
|
31
|
+
param = state.requested_param
|
32
|
+
return unless param
|
33
|
+
|
34
|
+
log_debug('Received new param', param:, value:)
|
35
|
+
state.store_param(param.to_sym, value)
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_file(file)
|
39
|
+
param = state.requested_param
|
40
|
+
return unless param
|
41
|
+
|
42
|
+
log_debug('Received new file', param:, file: file.to_h)
|
43
|
+
state.save_file(param.to_sym, file)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Loads the state from storage
|
47
|
+
def load_state!(channel)
|
48
|
+
@state = @channel_factory.load_state(channel)
|
49
|
+
end
|
50
|
+
|
51
|
+
# stores the command into state
|
52
|
+
def command=(cmd)
|
53
|
+
log_debug('Message set as command', command: cmd)
|
54
|
+
state.command = cmd
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
require_relative 'command/command'
|
5
|
+
require_relative 'command/command_definition'
|
6
|
+
require_relative 'command/execution_context'
|
7
|
+
|
8
|
+
module Kybus
|
9
|
+
module Bot
|
10
|
+
class CommandExecutor
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
include Kybus::Logger
|
14
|
+
attr_reader :dsl, :bot, :execution_context
|
15
|
+
|
16
|
+
def_delegator :execution_context, :save!, :save_execution_context!
|
17
|
+
|
18
|
+
def state
|
19
|
+
execution_context&.state
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(bot, channel_factory, inline_args)
|
23
|
+
@bot = bot
|
24
|
+
@channel_factory = channel_factory
|
25
|
+
@dsl = DSLMethods.new(bot.provider, state)
|
26
|
+
@inline_args = inline_args
|
27
|
+
@precommand_hook = proc {}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Process a single message, this method can be overwriten to enable
|
31
|
+
# more complex implementations of commands. It receives a message object.
|
32
|
+
def process_message(message)
|
33
|
+
@execution_context = ExecutionContest.new(message.channel_id, @channel_factory)
|
34
|
+
save_token!(message)
|
35
|
+
run_command_or_prepare!
|
36
|
+
save_execution_context!
|
37
|
+
end
|
38
|
+
|
39
|
+
def save_param!(message)
|
40
|
+
execution_context.add_param(message.raw_message)
|
41
|
+
return unless message.has_attachment?
|
42
|
+
|
43
|
+
file = bot.provider.file_builder(message.attachment)
|
44
|
+
execution_context.add_file(file)
|
45
|
+
end
|
46
|
+
|
47
|
+
def search_command_with_inline_arg(message)
|
48
|
+
command, value = @channel_factory.command_with_inline_arg(message.raw_message)
|
49
|
+
if command
|
50
|
+
execution_context.command = command
|
51
|
+
execution_context.next_param = execution_context.next_missing_param
|
52
|
+
execution_context.add_param(value)
|
53
|
+
else
|
54
|
+
execution_context.command = @channel_factory.default_command
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def save_token!(message)
|
59
|
+
if message.command?
|
60
|
+
command = @channel_factory.command(message.command)
|
61
|
+
if @inline_args && !command
|
62
|
+
search_command_with_inline_arg(message)
|
63
|
+
elsif !@inline_args && !command
|
64
|
+
execution_context.command = @channel_factory.default_command
|
65
|
+
else
|
66
|
+
execution_context.command = command
|
67
|
+
end
|
68
|
+
else
|
69
|
+
save_param!(message)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def run_command_or_prepare!
|
74
|
+
if execution_context.ready?
|
75
|
+
@dsl.state = execution_context.state
|
76
|
+
@dsl.instance_eval(&@precommand_hook)
|
77
|
+
run_command!
|
78
|
+
else
|
79
|
+
ask_param(execution_context.next_missing_param)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def precommand_hook(&block)
|
84
|
+
@precommand_hook = proc(&block)
|
85
|
+
end
|
86
|
+
|
87
|
+
def fallback(error)
|
88
|
+
catch = @channel_factory.command(error.class)
|
89
|
+
log_error('Unexpected error', error)
|
90
|
+
execution_context.command = catch if catch
|
91
|
+
end
|
92
|
+
|
93
|
+
# Method for triggering command
|
94
|
+
def run_command!
|
95
|
+
execution_context.call!(@dsl)
|
96
|
+
rescue StandardError => e
|
97
|
+
raise unless fallback(e)
|
98
|
+
|
99
|
+
retry
|
100
|
+
end
|
101
|
+
|
102
|
+
# Sends a message to get the next parameter from the user
|
103
|
+
def ask_param(param)
|
104
|
+
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)
|
108
|
+
execution_context.next_param = param
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Bot
|
5
|
+
class DSLMethods
|
6
|
+
attr_accessor :state
|
7
|
+
attr_reader :provider
|
8
|
+
|
9
|
+
def initialize(provider, state)
|
10
|
+
@provider = provider
|
11
|
+
@state = state
|
12
|
+
end
|
13
|
+
|
14
|
+
def send_message(content, channel = nil)
|
15
|
+
raise(Base::EmptyMessageError) unless content
|
16
|
+
|
17
|
+
provider.send_message(channel || current_channel, content)
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_image(content, channel = nil, caption: nil)
|
21
|
+
provider.send_image(channel || current_channel, content, caption)
|
22
|
+
end
|
23
|
+
|
24
|
+
def send_video(content, channel = nil, caption: nil)
|
25
|
+
provider.send_video(channel || current_channel, content, caption)
|
26
|
+
end
|
27
|
+
|
28
|
+
def send_audio(content, channel = nil)
|
29
|
+
provider.send_audio(channel || current_channel, content)
|
30
|
+
end
|
31
|
+
|
32
|
+
def send_document(content, channel = nil)
|
33
|
+
provider.send_document(channel || current_channel, content)
|
34
|
+
end
|
35
|
+
|
36
|
+
def params
|
37
|
+
state.params
|
38
|
+
end
|
39
|
+
|
40
|
+
def files
|
41
|
+
state.files
|
42
|
+
end
|
43
|
+
|
44
|
+
def file(name)
|
45
|
+
(file = files[name]) && provider.file_builder(file)
|
46
|
+
end
|
47
|
+
|
48
|
+
def mention(name)
|
49
|
+
provider.mention(name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def current_user
|
53
|
+
provider.last_message.user
|
54
|
+
end
|
55
|
+
|
56
|
+
def is_private?
|
57
|
+
provider.last_message.is_private?
|
58
|
+
end
|
59
|
+
|
60
|
+
def last_message
|
61
|
+
provider.last_message
|
62
|
+
end
|
63
|
+
|
64
|
+
# returns the current_channel from where the message was sent
|
65
|
+
def current_channel
|
66
|
+
state.channel_id
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/kybus/bot/message.rb
CHANGED
@@ -8,17 +8,14 @@ module Kybus
|
|
8
8
|
# Base implementation for messages from distinct providers
|
9
9
|
class Message
|
10
10
|
# Converts the messages into a hash
|
11
|
-
def to_h
|
12
|
-
{
|
13
|
-
text: raw_message,
|
14
|
-
channel: channel_id
|
15
|
-
}
|
16
|
-
end
|
17
|
-
|
18
11
|
# Returns true when the received message is a command. Convention states
|
19
12
|
# that messages should start with '/' to be considered commands
|
20
13
|
def command?
|
21
|
-
|
14
|
+
command&.start_with?('/')
|
15
|
+
end
|
16
|
+
|
17
|
+
def command
|
18
|
+
raw_message&.split(' ')&.first
|
22
19
|
end
|
23
20
|
end
|
24
21
|
end
|
data/lib/kybus/bot/test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'base'
|
2
4
|
require_relative 'adapters/debug'
|
3
5
|
|
@@ -13,19 +15,24 @@ module Kybus
|
|
13
15
|
'pool_size' => 1,
|
14
16
|
'provider' => {
|
15
17
|
'name' => 'debug',
|
16
|
-
'echo' =>
|
18
|
+
'echo' => false,
|
17
19
|
'channels' => { 'testing' => [] }
|
18
20
|
}
|
19
21
|
}.freeze
|
20
22
|
|
21
|
-
def self.make_test_bot
|
22
|
-
new(CONFIG)
|
23
|
+
def self.make_test_bot(extra_configs = {})
|
24
|
+
new(CONFIG.merge(extra_configs))
|
23
25
|
end
|
24
26
|
|
25
27
|
def receives(msg, attachments = nil)
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
attachments = Adapter::DebugMessage::DebugFile.new(attachments) if attachments
|
29
|
+
msg = Adapter::DebugMessage.new(msg, 'testing', attachments)
|
30
|
+
provider.last_message = msg
|
31
|
+
executor.process_message(msg)
|
32
|
+
end
|
33
|
+
|
34
|
+
def expects(method)
|
35
|
+
executor.dsl.expects(method)
|
29
36
|
end
|
30
37
|
end
|
31
38
|
end
|
data/lib/kybus/bot/version.rb
CHANGED
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.
|
4
|
+
version: 0.7.0
|
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
|
+
date: 2022-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kybus-core
|
@@ -218,8 +218,16 @@ files:
|
|
218
218
|
- lib/kybus/bot/adapters/debug.rb
|
219
219
|
- lib/kybus/bot/adapters/discord.rb
|
220
220
|
- lib/kybus/bot/adapters/telegram.rb
|
221
|
+
- lib/kybus/bot/adapters/telegram_file.rb
|
222
|
+
- lib/kybus/bot/adapters/telegram_message.rb
|
221
223
|
- lib/kybus/bot/base.rb
|
222
|
-
- lib/kybus/bot/
|
224
|
+
- lib/kybus/bot/command/command.rb
|
225
|
+
- lib/kybus/bot/command/command_definition.rb
|
226
|
+
- lib/kybus/bot/command/command_state.rb
|
227
|
+
- lib/kybus/bot/command/command_state_factory.rb
|
228
|
+
- lib/kybus/bot/command/execution_context.rb
|
229
|
+
- lib/kybus/bot/command_executor.rb
|
230
|
+
- lib/kybus/bot/dsl_methods.rb
|
223
231
|
- lib/kybus/bot/message.rb
|
224
232
|
- lib/kybus/bot/migrator.rb
|
225
233
|
- lib/kybus/bot/test.rb
|
@@ -228,7 +236,8 @@ files:
|
|
228
236
|
homepage: https://github.com/tachomex/kybus
|
229
237
|
licenses:
|
230
238
|
- MIT
|
231
|
-
metadata:
|
239
|
+
metadata:
|
240
|
+
rubygems_mfa_required: 'true'
|
232
241
|
post_install_message:
|
233
242
|
rdoc_options: []
|
234
243
|
require_paths:
|
@@ -244,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
244
253
|
- !ruby/object:Gem::Version
|
245
254
|
version: '0'
|
246
255
|
requirements: []
|
247
|
-
rubygems_version: 3.
|
256
|
+
rubygems_version: 3.3.7
|
248
257
|
signing_key:
|
249
258
|
specification_version: 4
|
250
259
|
summary: Provides a framework for building bots with ruby
|