pepito 0.0.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 +7 -0
- data/.gitignore +41 -0
- data/.rubocop.yml +8 -0
- data/Gemfile +3 -0
- data/README.md +26 -0
- data/Rakefile +11 -0
- data/bin/pepito +5 -0
- data/lib/pepito/adapter.rb +101 -0
- data/lib/pepito/adapters.rb +4 -0
- data/lib/pepito/database.rb +14 -0
- data/lib/pepito/errors/missing_configuration_value_error.rb +15 -0
- data/lib/pepito/errors/required_methods_error.rb +15 -0
- data/lib/pepito/handler/chat_router.rb +36 -0
- data/lib/pepito/handler/http_router.rb +30 -0
- data/lib/pepito/handler.rb +38 -0
- data/lib/pepito/handlers/extensions_catalog.rb +108 -0
- data/lib/pepito/handlers/help.rb +36 -0
- data/lib/pepito/handlers/info.rb +40 -0
- data/lib/pepito/handlers/room.rb +23 -0
- data/lib/pepito/http_api/http_callback.rb +49 -0
- data/lib/pepito/http_api/http_route.rb +48 -0
- data/lib/pepito/http_api/rack_app.rb +27 -0
- data/lib/pepito/message.rb +59 -0
- data/lib/pepito/robot.rb +367 -0
- data/lib/pepito/source.rb +32 -0
- data/lib/pepito/version.rb +4 -0
- data/lib/pepito/web_app/app.rb +41 -0
- data/lib/pepito/web_app/views/index.erb +69 -0
- data/lib/pepito.rb +21 -0
- data/pepito.gemspec +35 -0
- data/test/pepito/handler/test_chat_router.rb +37 -0
- data/test/pepito/handler/test_http_router.rb +20 -0
- data/test/pepito/handlers/test_extensions_catalog.rb +38 -0
- data/test/pepito/handlers/test_help.rb +38 -0
- data/test/pepito/handlers/test_info.rb +32 -0
- data/test/pepito/handlers/test_room.rb +33 -0
- data/test/pepito/test_adapter.rb +71 -0
- data/test/pepito/test_handler.rb +28 -0
- data/test/pepito/test_message.rb +101 -0
- data/test/pepito/test_robot.rb +259 -0
- data/test/pepito/test_source.rb +27 -0
- data/test/test_pepito.rb +8 -0
- metadata +300 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'http_router'
|
3
|
+
|
4
|
+
module Pepito
|
5
|
+
module HTTPApi
|
6
|
+
# The rack app for the http api.
|
7
|
+
class RackApp
|
8
|
+
# Router for the rack app.
|
9
|
+
# @return [HttpRouter]
|
10
|
+
attr_reader :router
|
11
|
+
|
12
|
+
# Rack App
|
13
|
+
# @return [Object]
|
14
|
+
attr_reader :app
|
15
|
+
|
16
|
+
# @return [void]
|
17
|
+
def initialize
|
18
|
+
@router = HttpRouter.new
|
19
|
+
|
20
|
+
builder = Rack::Builder.new
|
21
|
+
builder.run(@router)
|
22
|
+
|
23
|
+
@app = builder.to_app
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Pepito
|
2
|
+
# Message received by an adapter
|
3
|
+
class Message
|
4
|
+
# The source of the message.
|
5
|
+
# @return [Pepito::Source]
|
6
|
+
attr_reader :source
|
7
|
+
|
8
|
+
# The text received.
|
9
|
+
# @return [String]
|
10
|
+
attr_reader :body
|
11
|
+
|
12
|
+
# The command part of the message.
|
13
|
+
# Example: body is -> "pepito info", command is "info".
|
14
|
+
# @return [String, nil] Returns nil if command could not be parsed.
|
15
|
+
attr_reader :command
|
16
|
+
|
17
|
+
# The currently running robot.
|
18
|
+
# @return [Pepito::Robot]
|
19
|
+
attr_reader :robot
|
20
|
+
|
21
|
+
# @param robot [Pepito::Robot] The currently running robot.
|
22
|
+
# @param source [Pepito::Source] The source of the message.
|
23
|
+
# @param body [String] The text received.
|
24
|
+
# @return [void]
|
25
|
+
def initialize(robot, source, body)
|
26
|
+
@robot = robot
|
27
|
+
@source = source
|
28
|
+
@body = body
|
29
|
+
|
30
|
+
@command = parse_command
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns whether a command exists or not.
|
34
|
+
# @return [Boolean]
|
35
|
+
def command?
|
36
|
+
@command.nil? ? false : true
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns whether a message matches a route or not
|
40
|
+
# @return [Boolean]
|
41
|
+
def match_route?(route)
|
42
|
+
return true if !route.command && route.pattern.match(body)
|
43
|
+
return true if route.command && command? && route.pattern.match(command)
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Parses the command from the body attribute.
|
50
|
+
# @return [String] The command string
|
51
|
+
def parse_command
|
52
|
+
return nil if @robot.name.nil? || @robot.name.empty?
|
53
|
+
|
54
|
+
command_data = /^#{@robot.name}\s?(?<command>.*)$/.match(@body)
|
55
|
+
|
56
|
+
command_data[:command] unless command_data.nil?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/pepito/robot.rb
ADDED
@@ -0,0 +1,367 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'puma'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubygems/dependency_installer'
|
5
|
+
|
6
|
+
require_relative 'http_api/rack_app'
|
7
|
+
require_relative 'web_app/app'
|
8
|
+
require_relative 'handlers/info'
|
9
|
+
require_relative 'handlers/extensions_catalog'
|
10
|
+
require_relative 'handlers/help'
|
11
|
+
require_relative 'handlers/room'
|
12
|
+
require_relative 'database'
|
13
|
+
require_relative 'adapters'
|
14
|
+
require_relative 'errors/required_methods_error'
|
15
|
+
require_relative 'errors/missing_configuration_value_error'
|
16
|
+
|
17
|
+
module Pepito
|
18
|
+
# The robot component of the bot.
|
19
|
+
class Robot
|
20
|
+
# The running http_api.
|
21
|
+
# @return [Pepito::HTTPApi::RackApp]
|
22
|
+
attr_reader :http_api
|
23
|
+
|
24
|
+
# The thread running the HTTP API.
|
25
|
+
# @return [Thread]
|
26
|
+
attr_reader :http_api_thread
|
27
|
+
|
28
|
+
# The Puma::Server running the HTTP API
|
29
|
+
# @return [Puma::Server]
|
30
|
+
attr_reader :http_api_server
|
31
|
+
|
32
|
+
# The web app.
|
33
|
+
# @return [Pepito::WebApp::App]
|
34
|
+
attr_reader :web_app
|
35
|
+
|
36
|
+
# The thread running the web app.
|
37
|
+
# @return [Thread]
|
38
|
+
attr_reader :web_app_thread
|
39
|
+
|
40
|
+
# The Puma::Server running the Web App
|
41
|
+
# @return [Puma::Server]
|
42
|
+
attr_reader :web_app_server
|
43
|
+
|
44
|
+
# List of running handlers.
|
45
|
+
# @return [Hash] A map of handler's keys to classes.
|
46
|
+
attr_reader :handlers
|
47
|
+
|
48
|
+
# List of running adapters.
|
49
|
+
# @return [Hash] A map of adapter's keys to classes.
|
50
|
+
attr_reader :adapters
|
51
|
+
|
52
|
+
# Name of the bot.
|
53
|
+
# @return [String]
|
54
|
+
attr_reader :name
|
55
|
+
|
56
|
+
# Redis connection
|
57
|
+
# @return [Pepito::Database]
|
58
|
+
attr_reader :database
|
59
|
+
|
60
|
+
# Logger
|
61
|
+
# @return [Logger]
|
62
|
+
attr_reader :logger
|
63
|
+
|
64
|
+
# Default handlers that can't be turned off
|
65
|
+
# @return [Array<String>]
|
66
|
+
attr_reader :default_handlers
|
67
|
+
|
68
|
+
# Default adapters that can't be turned off
|
69
|
+
# @return [Array<String>]
|
70
|
+
attr_reader :default_adapters
|
71
|
+
|
72
|
+
# @return [void]
|
73
|
+
def initialize
|
74
|
+
@logger = Logger.new(ENV['LOG_FILE'] || STDOUT)
|
75
|
+
|
76
|
+
@logger.info('Connecting to the database')
|
77
|
+
@database = Database.new
|
78
|
+
|
79
|
+
@http_api = HTTPApi::RackApp.new
|
80
|
+
|
81
|
+
@web_app = WebApp::App
|
82
|
+
|
83
|
+
@default_handlers = %w(Info Help Room)
|
84
|
+
@handlers = {}
|
85
|
+
|
86
|
+
@default_adapters = []
|
87
|
+
@adapters = {}
|
88
|
+
|
89
|
+
@name = @database.get('name') || 'pepito'
|
90
|
+
end
|
91
|
+
|
92
|
+
# Runs the robot.
|
93
|
+
# @return [void]
|
94
|
+
def run
|
95
|
+
run_http_api
|
96
|
+
run_web_app
|
97
|
+
run_handlers
|
98
|
+
run_adapters
|
99
|
+
begin
|
100
|
+
sleep
|
101
|
+
rescue Interrupt
|
102
|
+
@logger.info('Exiting')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Helper to receive a message.
|
107
|
+
# @param message [Pepito::Message] A message received by an adapter.
|
108
|
+
# @return [void]
|
109
|
+
def receive_message(message)
|
110
|
+
match = @handlers.dup.map do |_, handler|
|
111
|
+
handler.chat_routes.map do |route|
|
112
|
+
next unless message.match_route?(route)
|
113
|
+
strings = handler.public_send(route.func, message.source, route.pattern.match(message.command || message.body))
|
114
|
+
message.source.adapter.send_messages(message.source, strings) unless strings.nil?
|
115
|
+
true
|
116
|
+
end.any?
|
117
|
+
end.any?
|
118
|
+
|
119
|
+
message.source.adapter.send_messages(message.source, ['No match for command "' + message.command + '"']) if !match && message.command
|
120
|
+
end
|
121
|
+
|
122
|
+
# Retrieve the list of possible handlers to install from server
|
123
|
+
# @return [Array<String>]
|
124
|
+
def handlers_list
|
125
|
+
%w(Info Help ExtensionsCatalog Room)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Retrieve the list of possible adapters to install from server
|
129
|
+
# @return [Array<String>]
|
130
|
+
def adapters_list
|
131
|
+
[
|
132
|
+
{
|
133
|
+
name: 'Slack',
|
134
|
+
gem: 'pepito-slack',
|
135
|
+
configs: [
|
136
|
+
{
|
137
|
+
name: 'SLACK_API_TOKEN',
|
138
|
+
required: true
|
139
|
+
}
|
140
|
+
]
|
141
|
+
}
|
142
|
+
]
|
143
|
+
end
|
144
|
+
|
145
|
+
# Starts an handler.
|
146
|
+
# @param handler [String] Name of the handler to start.
|
147
|
+
# @return [Integer]
|
148
|
+
# 0 - If success
|
149
|
+
# 1 - If failed because handler is already running
|
150
|
+
# 2 - If handler can't be found
|
151
|
+
# 3 - Other errors
|
152
|
+
def start_handler(handler)
|
153
|
+
@logger.info('"' + handler.to_s + '" handler starting')
|
154
|
+
if @handlers.key?(handler)
|
155
|
+
@logger.warn('"' + handler.to_s + '" handler is already running')
|
156
|
+
return 1
|
157
|
+
else
|
158
|
+
begin
|
159
|
+
@handlers[handler] = Handlers.const_get(handler).new(self)
|
160
|
+
rescue NameError
|
161
|
+
@logger.error('"' + handler.to_s + '" handler does not exist')
|
162
|
+
return 2
|
163
|
+
rescue => e
|
164
|
+
@logger.error('"' + handler.to_s + '" handler failed to start. Error: ' + e.message.to_s)
|
165
|
+
@logger.error(e)
|
166
|
+
return 3
|
167
|
+
end
|
168
|
+
@http_api.router.uncompile
|
169
|
+
@handlers[handler].run
|
170
|
+
@handlers[handler].start
|
171
|
+
@database.sadd('handlers', handler)
|
172
|
+
@logger.info('"' + handler.to_s + '" handler started successfully')
|
173
|
+
return 0
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Stops an handler.
|
178
|
+
# @param handler [String] Name of the handler to stop. Must match the handler's class name.
|
179
|
+
# @return [Integer]
|
180
|
+
# 0 - If handler stopped
|
181
|
+
# 1 - If it is a default handler
|
182
|
+
# 2 - If it is not running
|
183
|
+
def stop_handler(handler)
|
184
|
+
@logger.info('Stopping "' + handler.to_s + '" handler')
|
185
|
+
if @default_handlers.include?(handler)
|
186
|
+
@logger.error('Can\'t stop "' + handler.to_s + '" because it is a default handler')
|
187
|
+
return 1
|
188
|
+
elsif !@handlers.key?(handler)
|
189
|
+
@logger.warn('"' + handler.to_s + '" handler is not running')
|
190
|
+
return 2
|
191
|
+
else
|
192
|
+
@handlers.delete(handler)
|
193
|
+
@database.srem('handlers', handler)
|
194
|
+
@http_api.router.reset!
|
195
|
+
@handlers.each do |_, h|
|
196
|
+
h.start
|
197
|
+
end
|
198
|
+
@logger.info('"' + handler.to_s + '" handler stopped successfully')
|
199
|
+
return 0
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Checks if an handler is running or not.
|
204
|
+
# @param handler [String] Name of the handler.
|
205
|
+
# @return [Boolean]
|
206
|
+
def handler?(handler)
|
207
|
+
@handlers.key?(handler)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Starts an adapter.
|
211
|
+
# @param adapter [String] Name of the adapter to start. Must match the adapter's class name.
|
212
|
+
# @param gem_name [String] Name of the gem for the adapter
|
213
|
+
# @param config [Hash<String,String>] The config for the adapter
|
214
|
+
# @return [Integer]
|
215
|
+
# 0 - if adapter was started
|
216
|
+
# 1 - if adapter is already running
|
217
|
+
# 2 - if adapter can't be found
|
218
|
+
# 3 - if there are missing methods on the adapter
|
219
|
+
# 4 - if there are missing configuration values
|
220
|
+
# 5 - other errors
|
221
|
+
def start_adapter(adapter, gem_name, config)
|
222
|
+
@logger.info('"' + adapter.to_s + '" adapter starting')
|
223
|
+
if @adapters.key?(adapter)
|
224
|
+
@logger.warn('"' + adapter.to_s + '" adapter already running')
|
225
|
+
return 1
|
226
|
+
else
|
227
|
+
begin
|
228
|
+
require gem_name
|
229
|
+
rescue LoadError
|
230
|
+
begin
|
231
|
+
inst = Gem::DependencyInstaller.new
|
232
|
+
inst.install gem_name
|
233
|
+
require gem_name
|
234
|
+
rescue => e
|
235
|
+
@logger.error(e)
|
236
|
+
return 2
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
begin
|
241
|
+
adp = Pepito::Adapters.const_get(adapter).new(self, config)
|
242
|
+
rescue NameError => e
|
243
|
+
@logger.error('"' + adapter.to_s + '" adapter could not be found')
|
244
|
+
@logger.error(e)
|
245
|
+
return 2
|
246
|
+
rescue Pepito::Errors::RequiredMethodsError => e
|
247
|
+
@logger.error('"' + adapter.to_s + '" adapter failed to start. ' + e.message + ': ' + e.missing_methods.to_s)
|
248
|
+
return 3
|
249
|
+
rescue Pepito::Errors::MissingConfigurationValueError => e
|
250
|
+
@logger.error('"' + adapter.to_s + '" adapter failed to start. ' + e.message + ': ' + e.configuration_values.to_s)
|
251
|
+
return 4
|
252
|
+
rescue => e
|
253
|
+
@logger.error('"' + adapter.to_s + '" adapter failed to start. Error: ' + e.message.to_s)
|
254
|
+
@logger.error(e)
|
255
|
+
return 5
|
256
|
+
end
|
257
|
+
|
258
|
+
# If it didnt fail, spawn adapter thread
|
259
|
+
@adapters[adapter] = adp
|
260
|
+
@database.sadd('adapters', adapter)
|
261
|
+
# Clear old config in database
|
262
|
+
@database.del(adapter)
|
263
|
+
# Set gem name in database
|
264
|
+
@database.set(adapter + ':gem', gem_name)
|
265
|
+
# Setup new config in database
|
266
|
+
config.each do |key, value|
|
267
|
+
@database.hset(adapter + ':config', key, value)
|
268
|
+
end
|
269
|
+
|
270
|
+
Thread.new do
|
271
|
+
adp.run
|
272
|
+
end
|
273
|
+
|
274
|
+
@logger.info('"' + adapter.to_s + '" adapter started successfully')
|
275
|
+
return 0
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Stops an adapter.
|
280
|
+
# @param adapter [String] Name of the adapter to stop. Must match the adapter's class name.
|
281
|
+
# @return [Integer]
|
282
|
+
# 0 - If successful
|
283
|
+
# 1 - If adapter is default
|
284
|
+
# 2 - If adapter is not running
|
285
|
+
def stop_adapter(adapter)
|
286
|
+
if @default_adapters.include?(adapter)
|
287
|
+
@logger.error('Can\'t stop "' + adapter.to_s + '" adapter because it is a default adapter')
|
288
|
+
return 1
|
289
|
+
elsif !@adapters.key?(adapter)
|
290
|
+
@logger.warn('"' + adapter.to_s + '" adapter is not running')
|
291
|
+
return 2
|
292
|
+
else
|
293
|
+
@adapters[adapter].stop
|
294
|
+
@adapters.delete(adapter)
|
295
|
+
@database.del(adapter + ':config')
|
296
|
+
@database.del(adapter + ':gem')
|
297
|
+
@database.srem('adapters', adapter)
|
298
|
+
@logger.info('"' + adapter.to_s + '" adapter stopped successfully')
|
299
|
+
return 0
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# Checks if an adapter is running or not.
|
304
|
+
# @param adapter [String] Name of the adapter.
|
305
|
+
# @return [Boolean]
|
306
|
+
def adapter?(adapter)
|
307
|
+
@adapters.key?(adapter)
|
308
|
+
end
|
309
|
+
|
310
|
+
private
|
311
|
+
|
312
|
+
# Runs the http api in a new thread.
|
313
|
+
# @return [void]
|
314
|
+
def run_http_api
|
315
|
+
@logger.info('Starting the HTTP API')
|
316
|
+
@http_api_thread = Thread.new do
|
317
|
+
@http_api_server = Puma::Server.new(@http_api.app)
|
318
|
+
@http_api_server.add_tcp_listener('127.0.0.1', 8080)
|
319
|
+
@http_api_server.run
|
320
|
+
end
|
321
|
+
|
322
|
+
@http_api_thread.abort_on_exception = true
|
323
|
+
end
|
324
|
+
|
325
|
+
# Runs the web app in a new thread.
|
326
|
+
# @return [void]
|
327
|
+
def run_web_app
|
328
|
+
@logger.info('Starting the web app')
|
329
|
+
@web_app_thread = Thread.new do
|
330
|
+
@web_app.set(:robot, self)
|
331
|
+
|
332
|
+
@web_app_server = Puma::Server.new(@web_app)
|
333
|
+
@web_app_server.add_tcp_listener('127.0.0.1', 4567)
|
334
|
+
|
335
|
+
@web_app_server.run
|
336
|
+
end
|
337
|
+
|
338
|
+
@web_app_thread.abort_on_exception = true
|
339
|
+
end
|
340
|
+
|
341
|
+
# Runs the handlers saved in the database
|
342
|
+
# @return [void]
|
343
|
+
def run_handlers
|
344
|
+
@logger.info('Starting the handlers')
|
345
|
+
@default_handlers.each do |handler|
|
346
|
+
start_handler(handler)
|
347
|
+
end
|
348
|
+
|
349
|
+
@database.smembers('handlers').each do |handler|
|
350
|
+
start_handler(handler) unless @default_handlers.include?(handler)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
# Runs the adapters saved in the database
|
355
|
+
# @return [void]
|
356
|
+
def run_adapters
|
357
|
+
@logger.info('Starting the adapters')
|
358
|
+
@default_adapters.each do |adapter, gem_name, configs|
|
359
|
+
start_adapter(adapter, gem_name, configs)
|
360
|
+
end
|
361
|
+
|
362
|
+
@database.smembers('adapters').each do |adapter|
|
363
|
+
start_adapter(adapter, @database.get(adapter + ':gem'), @database.hgetall(adapter + ':config')) unless @default_adapters.include?(adapter)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Pepito
|
2
|
+
# Source for a message, where it comes from, where it should go
|
3
|
+
class Source
|
4
|
+
# Adapter that received the message.
|
5
|
+
# @return [Pepito::Adapter]
|
6
|
+
attr_reader :adapter
|
7
|
+
|
8
|
+
# User that sent the message.
|
9
|
+
# @return [String]
|
10
|
+
attr_reader :user
|
11
|
+
|
12
|
+
# Room where the message originated
|
13
|
+
# @return [String]
|
14
|
+
attr_reader :room
|
15
|
+
|
16
|
+
# Whether the message is private or not
|
17
|
+
# @return [Boolean]
|
18
|
+
attr_reader :private_message
|
19
|
+
|
20
|
+
# @param adapter [Adapter] The adapter that received the message.
|
21
|
+
# @param user [String] The user that sent the message.
|
22
|
+
# @param room [String] The room where the message was sent from.
|
23
|
+
# @param private_message [Boolean] Whether the message is private or not.
|
24
|
+
# @return [void]
|
25
|
+
def initialize(adapter, user, room, private_message)
|
26
|
+
@adapter = adapter
|
27
|
+
@user = user
|
28
|
+
@room = room
|
29
|
+
@private_message = private_message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'tilt/erb'
|
3
|
+
|
4
|
+
module Pepito
|
5
|
+
module WebApp
|
6
|
+
# Web App to control the bot
|
7
|
+
class App < Sinatra::Base
|
8
|
+
get '/' do
|
9
|
+
@handlers = settings.robot.handlers_list
|
10
|
+
@adapters = settings.robot.adapters_list
|
11
|
+
erb :index
|
12
|
+
end
|
13
|
+
|
14
|
+
post '/deactivate/handler/:handler' do
|
15
|
+
settings.robot.stop_handler(params['handler'])
|
16
|
+
redirect to('/')
|
17
|
+
end
|
18
|
+
|
19
|
+
post '/activate/handler/:handler' do
|
20
|
+
settings.robot.start_handler(params['handler'])
|
21
|
+
redirect to('/')
|
22
|
+
end
|
23
|
+
|
24
|
+
post '/deactivate/adapter/:adapter' do
|
25
|
+
settings.robot.stop_adapter(params['adapter'])
|
26
|
+
redirect to('/')
|
27
|
+
end
|
28
|
+
|
29
|
+
post '/activate/adapter/:adapter' do
|
30
|
+
c = {}
|
31
|
+
params.each do |key, value|
|
32
|
+
if key.start_with?(params['adapter'] + ':config:')
|
33
|
+
c[key.split(params['adapter'] + ':config:')[1]] = value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
settings.robot.start_adapter(params['adapter'], params[params['adapter'] + ':gem_name'], c)
|
37
|
+
redirect to('/')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
<h1><%= settings.robot.name.capitalize %> bot!</h1>
|
2
|
+
|
3
|
+
<h3>Handlers List</h3>
|
4
|
+
<table border=1 style="text-align: left; min-width: 200px">
|
5
|
+
<tr>
|
6
|
+
<th>Handler</th>
|
7
|
+
<th>Action</th>
|
8
|
+
</tr>
|
9
|
+
<% settings.robot.default_handlers.each do |handler| %>
|
10
|
+
<tr>
|
11
|
+
<td><%= handler.to_s %></td>
|
12
|
+
<td>Default Handler, can not be deactivated.</td>
|
13
|
+
</tr>
|
14
|
+
<% end %>
|
15
|
+
<% @handlers.each do |handler| %>
|
16
|
+
<% if !settings.robot.default_handlers.include?(handler) %>
|
17
|
+
<tr>
|
18
|
+
<td><%= handler.to_s %></td>
|
19
|
+
<td>
|
20
|
+
<% if settings.robot.handlers.keys.include?(handler) %>
|
21
|
+
<form action="/deactivate/handler/<%= handler.to_s %>" method="POST">
|
22
|
+
<input type="submit" value="Deactivate">
|
23
|
+
</form>
|
24
|
+
<% else %>
|
25
|
+
<form action="/activate/handler/<%= handler.to_s %>" method="POST">
|
26
|
+
<input type="submit" value="Activate">
|
27
|
+
</form>
|
28
|
+
<% end %>
|
29
|
+
</td>
|
30
|
+
</tr>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
33
|
+
</table>
|
34
|
+
|
35
|
+
<h3>Adapters List</h3>
|
36
|
+
<table border=1 style="text-align: left; min-width: 200px;">
|
37
|
+
<tr>
|
38
|
+
<th>Handler</th>
|
39
|
+
<th>Action</th>
|
40
|
+
</tr>
|
41
|
+
<% settings.robot.default_adapters.each do |adapter| %>
|
42
|
+
<tr>
|
43
|
+
<td><%= adapter[:name].to_s %></td>
|
44
|
+
<td>Default Adapter, can not be deactivated.</td>
|
45
|
+
</tr>
|
46
|
+
<% end %>
|
47
|
+
<% @adapters.each do |adapter| %>
|
48
|
+
<% if !settings.robot.default_adapters.include?(adapter[:name]) %>
|
49
|
+
<tr>
|
50
|
+
<td><%= adapter[:name].to_s %></td>
|
51
|
+
<td>
|
52
|
+
<% if settings.robot.adapters.keys.include?(adapter[:name]) %>
|
53
|
+
<form action="/deactivate/adapter/<%= adapter[:name].to_s %>" method="POST">
|
54
|
+
<input type="submit" value="Deactivate">
|
55
|
+
</form>
|
56
|
+
<% else %>
|
57
|
+
<form action="/activate/adapter/<%= adapter[:name].to_s %>" method="POST">
|
58
|
+
<input type="hidden" name="<%= adapter[:name].to_s %>:gem_name" value="<%= adapter[:gem].to_s %>">
|
59
|
+
<% adapter[:configs].each do |c| %>
|
60
|
+
<%= c[:name].to_s %><% if !c[:required] %>(optional)<% end %>: <input type="text" name="<%= adapter[:name].to_s %>:config:<%= c[:name].to_s %>"><br>
|
61
|
+
<% end %>
|
62
|
+
<input type="submit" value="Activate">
|
63
|
+
</form>
|
64
|
+
<% end %>
|
65
|
+
</td>
|
66
|
+
</tr>
|
67
|
+
<% end %>
|
68
|
+
<% end %>
|
69
|
+
</table>
|
data/lib/pepito.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'pepito/http_api/rack_app'
|
2
|
+
require_relative 'pepito/robot'
|
3
|
+
|
4
|
+
# Pepito's main namespace
|
5
|
+
module Pepito
|
6
|
+
# Name for redis table
|
7
|
+
REDIS_NAMESPACE = :pepito
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# Running robot
|
11
|
+
# @return [Pepito::Robot]
|
12
|
+
attr_reader :robot
|
13
|
+
|
14
|
+
# Initializes the robot and runs it.
|
15
|
+
def run
|
16
|
+
@robot = Pepito::Robot.new
|
17
|
+
|
18
|
+
@robot.run
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/pepito.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require File.expand_path('../lib/pepito/version', __FILE__)
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'pepito'
|
8
|
+
s.version = Pepito::VERSION
|
9
|
+
s.authors = ['Olivier']
|
10
|
+
s.email = ['olivier@yafoy.com']
|
11
|
+
s.summary = 'Pepito is your very own corporate bot'
|
12
|
+
s.description = 'Integrate a bot in your company with custom extensions'
|
13
|
+
s.homepage = 'https://github.com/yafoy/pepito'
|
14
|
+
s.license = 'MIT'
|
15
|
+
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
|
21
|
+
s.required_ruby_version = '>= 2.0.0'
|
22
|
+
|
23
|
+
s.add_runtime_dependency 'redis-namespace', '~> 1.5', '>= 1.5.2'
|
24
|
+
s.add_runtime_dependency 'multi_json', '~> 1.11', '>= 1.11.2'
|
25
|
+
s.add_runtime_dependency 'rack', '~> 1.6', '>= 1.6.4'
|
26
|
+
s.add_runtime_dependency 'eventmachine', '~> 1.0.8', '>= 1.0.8'
|
27
|
+
s.add_runtime_dependency 'http_router', '~> 0.11.2', '>= 0.11.2'
|
28
|
+
s.add_runtime_dependency 'sinatra', '~> 1.4.6', '>= 1.4.6'
|
29
|
+
s.add_runtime_dependency 'tilt', '~> 2.0.2', '>= 2.0.2'
|
30
|
+
s.add_runtime_dependency 'puma', '~> 2.15.3', '>= 2.15.3'
|
31
|
+
|
32
|
+
s.add_development_dependency 'rake'
|
33
|
+
s.add_development_dependency 'minitest'
|
34
|
+
s.add_development_dependency 'rubocop', '~> 0.37'
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'pepito/handler/chat_router'
|
3
|
+
|
4
|
+
class Stub
|
5
|
+
include Pepito::Handler::ChatRouter
|
6
|
+
end
|
7
|
+
|
8
|
+
class TestPepitoHandlerChatRouter < MiniTest::Test
|
9
|
+
def test_emtpy_routes
|
10
|
+
stub = Stub.new
|
11
|
+
assert_empty stub.chat_routes
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_add_route
|
15
|
+
stub = Stub.new
|
16
|
+
stub.chat_route(/test/, :func_sym, command: true, help: 'help')
|
17
|
+
|
18
|
+
assert_equal stub.chat_routes[0].pattern, /test/
|
19
|
+
assert_equal stub.chat_routes[0].func, :func_sym
|
20
|
+
assert_equal stub.chat_routes[0].command, true
|
21
|
+
assert_equal stub.chat_routes[0].help, 'help'
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_add_route_no_command
|
25
|
+
stub = Stub.new
|
26
|
+
stub.chat_route(/test/, :func_sym)
|
27
|
+
|
28
|
+
assert_equal stub.chat_routes[0].command, false
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_add_route_no_help
|
32
|
+
stub = Stub.new
|
33
|
+
stub.chat_route(/test/, :func_sym)
|
34
|
+
|
35
|
+
assert_nil stub.chat_routes[0].help
|
36
|
+
end
|
37
|
+
end
|