lita 1.1.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +202 -45
- data/lib/lita.rb +45 -24
- data/lib/lita/adapter.rb +35 -0
- data/lib/lita/adapters/shell.rb +14 -3
- data/lib/lita/authorization.rb +24 -0
- data/lib/lita/cli.rb +1 -0
- data/lib/lita/config.rb +52 -19
- data/lib/lita/handler.rb +100 -36
- data/lib/lita/handlers/authorization.rb +38 -27
- data/lib/lita/handlers/help.rb +25 -22
- data/lib/lita/handlers/web.rb +25 -0
- data/lib/lita/http_route.rb +64 -0
- data/lib/lita/logger.rb +34 -0
- data/lib/lita/message.rb +41 -7
- data/lib/lita/rack_app_builder.rb +110 -0
- data/lib/lita/response.rb +30 -0
- data/lib/lita/robot.rb +56 -1
- data/lib/lita/rspec.rb +23 -50
- data/lib/lita/rspec/handler.rb +168 -0
- data/lib/lita/source.rb +19 -1
- data/lib/lita/user.rb +37 -1
- data/lib/lita/util.rb +26 -0
- data/lib/lita/version.rb +2 -1
- data/lita.gemspec +5 -0
- data/spec/lita/adapters/shell_spec.rb +12 -4
- data/spec/lita/config_spec.rb +18 -2
- data/spec/lita/handler_spec.rb +43 -46
- data/spec/lita/handlers/authorization_spec.rb +24 -31
- data/spec/lita/handlers/help_spec.rb +10 -8
- data/spec/lita/handlers/web_spec.rb +19 -0
- data/spec/lita/logger_spec.rb +26 -0
- data/spec/lita/message_spec.rb +16 -11
- data/spec/lita/robot_spec.rb +25 -2
- data/spec/lita/rspec_spec.rb +32 -20
- data/spec/lita/util_spec.rb +9 -0
- data/spec/lita_spec.rb +0 -51
- data/spec/spec_helper.rb +2 -1
- metadata +85 -3
- data/CHANGELOG.md +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 08671280114ef4f96291a7b7f296e7b616f40647
|
4
|
+
data.tar.gz: dc0372bef9351ea61ae833568d07302f586896fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6c6c3f23fa4657320607973ef740765863539a1b5fe4fb281c92b8bddd8c6f6285be942b691b04ab9f0a0f1ea54a8aafbb81615bf88bfc79df4d02c4fa4bf4e
|
7
|
+
data.tar.gz: b655f0ff87524fb958f83398ffa5adae67b955eca3b281c3eab915dbda71517e034d2016fb05ed3f3685dc68f5497ce02c2a97fbd9c29ba6e09793154d0863e8
|
data/README.md
CHANGED
@@ -4,10 +4,23 @@
|
|
4
4
|
[![Code Climate](https://codeclimate.com/github/jimmycuadra/lita.png)](https://codeclimate.com/github/jimmycuadra/lita)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/jimmycuadra/lita/badge.png)](https://coveralls.io/r/jimmycuadra/lita)
|
6
6
|
|
7
|
+
![Lita](http://f.cl.ly/items/0c271a2P3k2V180B1R0X/lita.jpg)
|
8
|
+
|
7
9
|
**Lita** is a chat bot written in Ruby with persistent storage provided by [Redis](http://redis.io/). It can connect to any chat service (given that there is an [adapter](#adapters) available for it) and can have new behavior added via [handlers](#handlers). The plugin system is managed with regular RubyGems and [Bundler](http://gembundler.com/).
|
8
10
|
|
9
11
|
Automate your business and have fun with your very own robot companion.
|
10
12
|
|
13
|
+
## Features
|
14
|
+
|
15
|
+
* Can work with any chat service
|
16
|
+
* Simple installation and setup
|
17
|
+
* Easily extendable with plugins
|
18
|
+
* Data persistence with Redis
|
19
|
+
* Built-in web server and routing
|
20
|
+
* Support for outgoing HTTP requests
|
21
|
+
* Group-based authorization
|
22
|
+
* Configurable logging
|
23
|
+
|
11
24
|
## Why?
|
12
25
|
|
13
26
|
Lita draws much inspiration from GitHub's fantastic [Hubot](http://hubot.github.com/), but has a few key differences and strengths:
|
@@ -15,9 +28,13 @@ Lita draws much inspiration from GitHub's fantastic [Hubot](http://hubot.github.
|
|
15
28
|
* It's written in Ruby.
|
16
29
|
* It exposes the full power of Redis rather than using it to serialize JSON.
|
17
30
|
* Is easy to develop and test plugins for with the provied [RSpec](https://github.com/rspec/rspec) extras. Lita strongly encourages thorough testing of plugins.
|
18
|
-
* It uses uses the Ruby ecosystem's standard tools (RubyGems and Bundler) for
|
31
|
+
* It uses uses the Ruby ecosystem's standard tools (RubyGems and Bundler) for plugin installation and loading.
|
19
32
|
* It's thoroughly documented.
|
20
33
|
|
34
|
+
## Is it any good?
|
35
|
+
|
36
|
+
Yes.
|
37
|
+
|
21
38
|
## Dependencies
|
22
39
|
|
23
40
|
* Ruby 2.0
|
@@ -31,7 +48,7 @@ Generate a new Lita instance by running `lita new NAME`. This will create a new
|
|
31
48
|
|
32
49
|
## Usage
|
33
50
|
|
34
|
-
To start your Lita instance, simply run `
|
51
|
+
To start your Lita instance, simply run `lita`. This will load up all the plugins (adapters and handlers) declared in your Gemfile, load any configuration you've defined (more on that later) and start the bot.
|
35
52
|
|
36
53
|
## Adapters
|
37
54
|
|
@@ -66,19 +83,22 @@ Lita.configure do |config|
|
|
66
83
|
config.adapter.password = "secret"
|
67
84
|
config.redis.host = "redis.example.com"
|
68
85
|
config.handlers.karma.cooldown = 300
|
69
|
-
config.handlers.google_images.safe_search =
|
86
|
+
config.handlers.google_images.safe_search = :off
|
70
87
|
end
|
71
88
|
```
|
72
89
|
|
73
90
|
The main config objects are:
|
74
91
|
|
75
92
|
* `robot` - General settings for Lita.
|
76
|
-
* `name` - The display name the bot will use on the chat service.
|
77
|
-
* `mention_name` - The name the bot will look for in messages to determine if the message is being addressed to it. Usually this is the same as the display name, but in some cases it may not be. For example,
|
78
|
-
* `adapter`
|
79
|
-
* `log_level`
|
80
|
-
* `admins` - An array of string user IDs which tell Lita which users are considered administrators. Only these users will have access to Lita's `auth` command.
|
93
|
+
* `name` (String) - The display name the bot will use on the chat service. Default: `"Lita"`.
|
94
|
+
* `mention_name` (String) - The name the bot will look for in messages to determine if the message is being addressed to it. Usually this is the same as the display name, but in some cases it may not be. For example, in HipChat, display names are required to be a first and last name, such as "Lita Bot", whereas the mention system would use a name like "LitaBot". Default: `Lita.config.robot.name`.
|
95
|
+
* `adapter` (Symbol, String) - The adapter to load. Default: `:shell`.
|
96
|
+
* `log_level` (Symbol, String) - The severity level of log messages to output. Valid options are, in order of severity: `:debug`, `:info`, `:warn`, `:error`, and `:fatal`. For whichever level you choose, log messages of that severity and greater will be output. Default: `:info`.
|
97
|
+
* `admins` (Array<String>) - An array of string user IDs which tell Lita which users are considered administrators. Only these users will have access to Lita's `auth` command. Default: `nil`.
|
81
98
|
* `redis` - Options for the Redis connection. See the [Redis gem](https://github.com/redis/redis-rb) documentation.
|
99
|
+
* `http` - Settings related to Lita's built-in web server.
|
100
|
+
* `port` (Integer) - The port the server should run on. Default: `8080`.
|
101
|
+
* `debug` (Boolean) - Set to true to display the web server's logs mixed in with Lita's own logs. Default: `false`.
|
82
102
|
* `adapter` - Options for the chosen adapter. See the adapter's documentation.
|
83
103
|
* `handlers` - Handlers may choose to expose a config object here with their own options. See the handler's documentation.
|
84
104
|
|
@@ -99,6 +119,12 @@ The first command adds a user whose ID or name is "joe" to the authorization gro
|
|
99
119
|
|
100
120
|
Message Lita `help` for a list of commands it knows about. You can also message it `help FOO` to list only commands beginning with FOO.
|
101
121
|
|
122
|
+
## Shell adapter
|
123
|
+
|
124
|
+
Lita ships with one adapter for use directly in the shell. Simply type text at the input to send messages, and Lita will respond with any registered handlers. The shell adapter has one configuration attribute:
|
125
|
+
|
126
|
+
* `private_chat` (Boolean) - If true, all messages will be treated as though they were sent in a private chat, so they will be considered commands even when not prefixed with the bot's name. Default: `false`.
|
127
|
+
|
102
128
|
## Writing an adapter
|
103
129
|
|
104
130
|
An adapter is a packaged as a RubyGem. The adapter is a class that inherits from `Lita::Adapter`, implements a few required methods, and is registered by calling `Lita.register_adapter(:symbol_that_identifies_the_adapter, TheAdapterClass)`.
|
@@ -140,56 +166,90 @@ end
|
|
140
166
|
|
141
167
|
It's important to note that each adapter should employ its own thread or event mechanism so that incoming messages can still be processed even while a handler is processing a previous message.
|
142
168
|
|
143
|
-
For more detailed examples, check out the built in shell adapter
|
169
|
+
For more detailed examples, check out the built in shell adapter, [lita-hipchat](https://github.com/jimmycuadra/lita-hipchat), or [lita-irc](https://github.com/jimmycuadra/lita-irc). See the API documentation for the exact methods and signatures adapters must implement.
|
144
170
|
|
145
171
|
## Writing a handler
|
146
172
|
|
147
|
-
A handler is packaged as a RubyGem. A handler is a class that inherits from `Lita::Handler` and is registered by calling `Lita.register_handler(TheHandlerClass)`. There are two components to a handler: route definitions, and the methods that implement those routes.
|
173
|
+
A handler is packaged as a RubyGem. A handler is a class that inherits from `Lita::Handler` and is registered by calling `Lita.register_handler(TheHandlerClass)`. There are two components to a handler: route definitions, and the methods that implement those routes. There are both chat routes and HTTP routes available to handlers.
|
174
|
+
|
175
|
+
### Chat routes
|
148
176
|
|
149
177
|
To define a route, use the class method `route`:
|
150
178
|
|
151
179
|
``` ruby
|
152
|
-
route /^echo\s+(.+)/,
|
180
|
+
route /^echo\s+(.+)/, :echo
|
153
181
|
```
|
154
182
|
|
155
|
-
`route` takes a regular expression that will be used to determine whether or not an incoming message should trigger the route
|
183
|
+
`route` takes a regular expression that will be used to determine whether or not an incoming message should trigger the route, and the name of the method that should be called when this route is triggered. `route` takes a few additional options:
|
156
184
|
|
157
|
-
* `:command` -
|
158
|
-
* `:
|
185
|
+
* `:command` (Boolean) - If set to true, the route will only trigger when "directed" at the robot. Directed means that it's sent via a private message, or the message is prefixed with the bot's name in some form (optionally prefixed with an @, and optionally followed by a colon or comma and white space). This prefix is stripped from the message body itself, but `Lita::Message#command?` available in handlers can be used if you need to determine whether or not a message was a command after it's been routed. Default: `false`.
|
186
|
+
* `:restrict_to` (Symbol, String, Array<String, Symbol>) - Authorization groups necessary to trigger the route. The user sending the message must be a member of at least one of the supplied groups. See the section on authorization for more information. Default: `nil`.
|
187
|
+
* `:help` (Hash<String>) - A map of example invocations of the route and descriptions of what they do. These values will be used to generate the listing for the built-in "help" handler. The robot's mention name will automatically be added to the front of the example if the route is a command. Default: `{}`.
|
159
188
|
|
160
189
|
Here is an example of a route declaration with all the options:
|
161
190
|
|
162
191
|
``` ruby
|
163
|
-
route /^echo\s+(.+)/, to :echo, command: true,
|
192
|
+
route /^echo\s+(.+)/, to: :echo, command: true, restrict_to: [:testers, :committers], help => {
|
193
|
+
"echo FOO" => "Replies back with FOO."
|
194
|
+
}
|
164
195
|
```
|
165
196
|
|
166
|
-
Each method that is called by a route takes one argument,
|
197
|
+
Each method that is called by a route takes one argument, a `Lita::Response` object. This object has the following useful methods:
|
167
198
|
|
168
199
|
* `reply` - Sends one or more string messages back to the source of the original message, either a private message or a chat room.
|
169
|
-
* `
|
170
|
-
* `args` - The user's message as an array of strings, as it would be parsed by `Shellwords.split`. For example, if the message was "Lita: auth add joe committers", calling `args` would return `["
|
200
|
+
* `matches` - An array of regular expression matches obtained by calling `body_of_message.scan(route_regex)`.
|
201
|
+
* `args` - The user's message as an array of strings, as it would be parsed by `Shellwords.split`. For example, if the message was "Lita: auth add joe committers", calling `args` would return `["add", "joe", "committers"]`. ("auth" is considered the command and so is not included in the arguments.) This is very handy for commands that take arguments in a way similar to how a UNIX shell would work.
|
202
|
+
* `message` - A `Lita::Message` object for the incoming message.
|
171
203
|
* `user` - A `Lita::User` object for the user who sent the message.
|
172
|
-
* `command?` - A boolean indicating whether or not the current message was directed at the robot.
|
173
|
-
* `message_body` - The full body of the user's message, as a string.
|
174
204
|
|
175
|
-
|
205
|
+
Additionally, handlers have access to these top-level methods:
|
176
206
|
|
177
|
-
|
207
|
+
* `robot` - Direct access to the currently running `Lita::Robot` object.
|
208
|
+
* `redis` - A `Redis::Namespace` object which provides each handler with its own isolated Redis store, suitable for many data persistence and manipulation tasks.
|
209
|
+
* `http` - A `Faraday::Connection` object for making HTTP requests. Takes an optional hash of options and optional block which are passed on to [Faraday](https://github.com/lostisland/faraday).
|
178
210
|
|
179
|
-
|
211
|
+
### HTTP routes
|
212
|
+
|
213
|
+
In addition to chat routes, handlers can also define HTTP routes for the built-in web server. This is done with the class-level `http` method. `http` returns a `Lita::HTTPRoute` object, which has methods for the most common HTTP methods. These methods take two arguments: the path for the route, and the name of the method that it will invoke as a symbol. The callback method takes two arguments: a `Rack::Request` and a `Rack::Response`. For example:
|
214
|
+
|
215
|
+
``` ruby
|
216
|
+
http.get "/foo/bar", :baz
|
217
|
+
|
218
|
+
def baz(request, response)
|
219
|
+
response.body = "Hello, world!"
|
220
|
+
end
|
221
|
+
```
|
222
|
+
|
223
|
+
### Handler-specific configuration
|
224
|
+
|
225
|
+
If you want your handler to expose config settings to the user, use the class-level `default_config` method. This method accepts a single config object as an argument, which will be exposed to the user as `Lita.config.handlers.your_handler_namespace`.
|
180
226
|
|
181
227
|
``` ruby
|
182
228
|
module Lita
|
183
229
|
module Handlers
|
184
|
-
class
|
185
|
-
def self.
|
186
|
-
|
230
|
+
class HandlerWithConfig < Handler
|
231
|
+
def self.default_config(config)
|
232
|
+
config.enabled = true
|
187
233
|
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
Lita.config.handlers.handler_with_config.enabled # => true
|
239
|
+
```
|
188
240
|
|
189
|
-
|
241
|
+
### Examples
|
242
|
+
|
243
|
+
Here is a basic handler which simply echoes back whatever the user says.
|
244
|
+
|
245
|
+
``` ruby
|
246
|
+
module Lita
|
247
|
+
module Handlers
|
248
|
+
class Echo < Handler
|
249
|
+
route /^echo\s+(.+)/, :echo, help: { "echo FOO" => "Echoes back FOO." }
|
190
250
|
|
191
251
|
def echo(matches)
|
192
|
-
reply
|
252
|
+
response.reply(response.matches)
|
193
253
|
end
|
194
254
|
end
|
195
255
|
|
@@ -197,51 +257,148 @@ module Lita
|
|
197
257
|
end
|
198
258
|
end
|
199
259
|
```
|
200
|
-
|
260
|
+
|
261
|
+
Here is a handler that tells a user who their United States congressional representative is based on zip code with data from a fictional HTTP API. The results are saved in the handler's namespaced Redis store to save HTTP calls on future requests.
|
262
|
+
|
263
|
+
``` ruby
|
264
|
+
module Lita
|
265
|
+
module Handlers
|
266
|
+
class Representative < Handler
|
267
|
+
route /representative\s+(\d{5})/, :lookup, command: true, help: {
|
268
|
+
"representative ZIP_CODE" => "Looks up the United States congressional representative for your zip code."
|
269
|
+
}
|
270
|
+
|
271
|
+
def lookup(response)
|
272
|
+
zip = response.matches[0][0]
|
273
|
+
rep = redis.get(zip)
|
274
|
+
rep = get_rep(zip) unless rep
|
275
|
+
response.reply "The representative for #{zip} is #{rep}."
|
276
|
+
end
|
277
|
+
|
278
|
+
private
|
279
|
+
|
280
|
+
def get_rep(zip)
|
281
|
+
http_response = http.get(
|
282
|
+
"http://www.example.com/api/represenative",
|
283
|
+
zip_code: zip
|
284
|
+
)
|
285
|
+
|
286
|
+
data = MultiJson.load(http_response.body)
|
287
|
+
rep = data["representative"]["name"]
|
288
|
+
redis.set(zip, data["representative"]["name"])
|
289
|
+
rep
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
Lita.register_handler(Representative)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
```
|
297
|
+
|
298
|
+
For more detailed examples, check out the built in authorization, help, and web handlers, or external handlers [lita-karma](https://github.com/jimmycuadra/lita-karma) and [lita-google-images](https://github.com/jimmycuadra/lita-google-images). See the API documentation for exact specifications for handlers' methods.
|
201
299
|
|
202
300
|
## Testing
|
203
301
|
|
204
|
-
It's a core philosophy of Lita that any
|
302
|
+
It's a core philosophy of Lita that any plugins you write for your robot should be as thoroughly tested as any other program you would write. To make this easier, Lita ships with some handy extras for [RSpec](https://github.com/rspec/rspec) that make testing a handler dead simple. They require the full RSpec suite (rspec-core, rspec-expectations, and rspec-mocks) version 2.14 or higher, as they use the newer `expect(obj).to receive(:message)` syntax.
|
303
|
+
|
304
|
+
### Testing handlers
|
205
305
|
|
206
|
-
To include Lita's RSpec extras, require "lita/rspec"
|
306
|
+
To include Lita's RSpec extras for testing a handler, require "lita/rspec", then add `lita_handler: true` to the metadata for the example group.
|
207
307
|
|
208
308
|
``` ruby
|
209
309
|
require "lita/rspec"
|
210
310
|
|
211
|
-
describe Lita::Handlers::MyHandler,
|
311
|
+
describe Lita::Handlers::MyHandler, lita_handler: true do
|
212
312
|
# ...
|
213
313
|
end
|
214
314
|
```
|
215
315
|
|
216
|
-
|
316
|
+
This provides the following:
|
217
317
|
|
218
|
-
* `Lita.handlers` will return an array with only the class you're testing (`described_class`).
|
219
318
|
* All Redis interaction will be namespaced to a test environment and automatically cleared out before each example.
|
220
|
-
*
|
221
|
-
*
|
319
|
+
* Lita's logger is stubbed to prevent log messages from cluttering up your test output.
|
320
|
+
* Lita's configuration is cleared out before each example, so that the first call to `Lita.config` will start from the default configuration.
|
321
|
+
* `Lita.handlers` will return an array with only the class you're testing (`described_class`).
|
322
|
+
* Strings sent with `Lita::Robot#send_messages` will be pushed to an array accessible as `replies` so you can make expectations about output from the robot.
|
323
|
+
* You have access to the following cached objects set with `let`: `robot`, `source`, and `user`. Note that these objects are instances of the real classes and not test doubles.
|
222
324
|
|
223
|
-
The custom helper methods are where `Lita::RSpec` really shines. You can test routes very easily using this syntax:
|
325
|
+
The custom helper methods are where `Lita::RSpec` really shines. You can test routes (both chat and HTTP routes) very easily using this syntax:
|
224
326
|
|
225
327
|
``` ruby
|
226
328
|
it { routes("some message").to(:some_method) }
|
227
|
-
it {
|
329
|
+
it { routes_command("directed message").to(:some_command_method) }
|
228
330
|
it { doesnt_route("message").to(:some_command_method) }
|
331
|
+
it { routes_http(:get, "/foo/bar").to(:baz) }
|
332
|
+
it { doesnt_route_http(:post, "/foo/bar").to(:baz) }
|
229
333
|
```
|
230
334
|
|
231
|
-
|
335
|
+
* `routes` - Sets an expectation that the given string will trigger the given method when overheard by the robot.
|
336
|
+
* `routes_command` - Sets an expectation that the given string will trigger the given method when directed at the robot, either in a private message, or by prefixing a message in a chat room with the robot's mention name.
|
337
|
+
* `doesnt_route` - Sets an expectation that is the inverse of the one set by `routes`. Also aliased to `does_not_route`.
|
338
|
+
* `doesnt_route_command` - Sets an expectation that is the inverse of the one set by `routes_command`. Also aliased to `does_not_route_command`.
|
339
|
+
* `routes_http` - Sets an expectation that an HTTP request with the given HTTP method and path will route to the given handler method.
|
340
|
+
* `doesnt_route_http` - Sets an expectation that is the inverse of `routes_http`. Also aliased to `does_not_route_http`.
|
232
341
|
|
233
|
-
|
342
|
+
**Note: These routing helpers bypass authorization for routes restricted to authorization groups.**
|
343
|
+
|
344
|
+
To send a message to the robot, use `send_message` and `send_command`. Then set expectations about the contents of the `replies` array.
|
234
345
|
|
235
346
|
``` ruby
|
236
|
-
|
237
|
-
|
347
|
+
it "lets everyone know when someone is happy" do
|
348
|
+
send_message("I'm happy!")
|
349
|
+
expect(replies.last).to eq("Hey, everyone! #{user.name} is happy! Isn't that nice?")
|
350
|
+
end
|
351
|
+
|
352
|
+
it "greets anyone that says hi to it" do
|
353
|
+
send_command("hi")
|
354
|
+
expect(repliest.last).to eq("Hello, #{user.name}!")
|
355
|
+
end
|
238
356
|
```
|
239
357
|
|
240
|
-
|
358
|
+
If you want to send a message or command from a user other than the default test user (set up for you with `let(:user)` by `Lita::RSpec`), you can invoke either method with the `:as` option, supplying a `Lita::User` object.
|
359
|
+
|
360
|
+
``` ruby
|
361
|
+
it "lets everyone know that Carl is happy" do
|
362
|
+
carl = Lita::User.create(123, name: "Carl")
|
363
|
+
send_message("I'm happy!", as: carl)
|
364
|
+
expect(replies.last).to eq("Hey, everyone! Carl is happy! Isn't that nice?")
|
365
|
+
end
|
366
|
+
```
|
367
|
+
|
368
|
+
* `send_message(string, as: user)` - Sends the given string to the robot.
|
369
|
+
* `send_command(string, as: user)` - Sends the given string to the robot, prefixing it with the robot's mention name.
|
370
|
+
|
371
|
+
### Testing adapters or other code
|
372
|
+
|
373
|
+
If you use `lita: true` instead of `lita_handler: true` in the metadata for your example group, only a small subset of Lita's RSpec extras will be enabled:
|
374
|
+
|
375
|
+
* All Redis interaction will be namespaced to a test environment and automatically cleared out before each example.
|
376
|
+
* Lita's logger is stubbed to prevent log messages from cluttering up your test output.
|
377
|
+
* Lita's configuration is cleared out before each example, so that the first call to `Lita.config` will start from the default configuration.
|
378
|
+
|
379
|
+
## Deploying to Heroku
|
380
|
+
|
381
|
+
There are a few things worth mentioning when deploying an instance of Lita to Heroku:
|
382
|
+
|
383
|
+
1. Your Procfile should contain one process: `web: bundle exec lita`.
|
384
|
+
|
385
|
+
1. To use the Redis To Go add-on, configure Lita's redis connection like this:
|
386
|
+
|
387
|
+
``` ruby
|
388
|
+
Lita.configure do |config|
|
389
|
+
config.redis.url = ENV["REDISTOGO_URL"]
|
390
|
+
end
|
391
|
+
```
|
392
|
+
|
393
|
+
1. Consider using a service like [Uptime Robot](http://www.uptimerobot.com/) to monitor your Lita instance and keep it from [sleeping](https://blog.heroku.com/archives/2013/6/20/app_sleeping_on_heroku) when running on a free dyno. `/lita/info` is a reliable path to hit from the web to keep it running.
|
394
|
+
|
395
|
+
## API documentation
|
396
|
+
|
397
|
+
Complete documentation for all of Lita's classes and methods can be found at [rdoc.info](http://rdoc.info/gems/lita/frames).
|
241
398
|
|
242
|
-
|
399
|
+
## History
|
243
400
|
|
244
|
-
For
|
401
|
+
For a history of releases, see the [Releases](https://github.com/jimmycuadra/lita/releases) page.
|
245
402
|
|
246
403
|
## License
|
247
404
|
|
data/lib/lita.rb
CHANGED
@@ -3,50 +3,78 @@ require "logger"
|
|
3
3
|
require "set"
|
4
4
|
require "shellwords"
|
5
5
|
|
6
|
+
require "faraday"
|
7
|
+
require "multi_json"
|
8
|
+
require "rack"
|
6
9
|
require "redis-namespace"
|
10
|
+
require "thin"
|
7
11
|
|
8
12
|
require "lita/version"
|
9
13
|
require "lita/config"
|
10
14
|
|
15
|
+
# The main namespace for Lita. Provides a global registry of adapters and
|
16
|
+
# handlers, as well as global configuration, logger, and Redis store.
|
11
17
|
module Lita
|
18
|
+
# The base Redis namespace for all Lita data.
|
12
19
|
REDIS_NAMESPACE = "lita"
|
13
20
|
|
14
21
|
class << self
|
22
|
+
# The global registry of adapters.
|
23
|
+
# @return [Hash] A map of adapter keys to adapter classes.
|
15
24
|
def adapters
|
16
25
|
@adapters ||= {}
|
17
26
|
end
|
18
27
|
|
28
|
+
# Adds an adapter to the global registry under the provided key.
|
29
|
+
# @param key [String, Symbol] The key that identifies the adapter.
|
30
|
+
# @param adapter [Lita::Adapter] The adapter class.
|
31
|
+
# @return [void]
|
19
32
|
def register_adapter(key, adapter)
|
20
33
|
adapters[key.to_sym] = adapter
|
21
34
|
end
|
22
35
|
|
36
|
+
# The global registry of handlers.
|
37
|
+
# @return [Set] The set of handlers.
|
23
38
|
def handlers
|
24
39
|
@handlers ||= Set.new
|
25
40
|
end
|
26
41
|
|
42
|
+
# Adds a handler to the global registry.
|
43
|
+
# @param handler [Lita::Handler] The handler class.
|
44
|
+
# @return [void]
|
27
45
|
def register_handler(handler)
|
28
46
|
handlers << handler
|
29
47
|
end
|
30
48
|
|
49
|
+
# The global configuration object. Provides user settings for the robot.
|
50
|
+
# @return [Lita::Config] The Lita configuration object.
|
31
51
|
def config
|
32
52
|
@config ||= Config.default_config
|
33
53
|
end
|
34
54
|
|
55
|
+
# Yields the global configuration object. Called by the user in a
|
56
|
+
# lita_config.rb file.
|
57
|
+
# @yieldparam [Lita::Configuration] config The global configuration object.
|
58
|
+
# @return [void]
|
35
59
|
def configure
|
36
60
|
yield config
|
37
61
|
end
|
38
62
|
|
63
|
+
# Clears the global configuration object. The next call to {Lita.config}
|
64
|
+
# will create a fresh config object.
|
65
|
+
# @return [void]
|
66
|
+
def clear_config
|
67
|
+
@config = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
# The global Logger object.
|
71
|
+
# @return [::Logger] The global Logger object.
|
39
72
|
def logger
|
40
|
-
@logger ||=
|
41
|
-
logger = Logger.new(STDERR)
|
42
|
-
logger.level = log_level
|
43
|
-
logger.formatter = proc do |severity, datetime, progname, msg|
|
44
|
-
"[#{datetime.utc}] #{severity}: #{msg}\n"
|
45
|
-
end
|
46
|
-
logger
|
47
|
-
end
|
73
|
+
@logger ||= Logger.get_logger(Lita.config.robot.log_level)
|
48
74
|
end
|
49
75
|
|
76
|
+
# The root Redis object.
|
77
|
+
# @return [Redis::Namespace] The root Redis object.
|
50
78
|
def redis
|
51
79
|
@redis ||= begin
|
52
80
|
redis = Redis.new(config.redis)
|
@@ -54,36 +82,29 @@ module Lita
|
|
54
82
|
end
|
55
83
|
end
|
56
84
|
|
85
|
+
# Loads user configuration and starts the robot.
|
86
|
+
# @param config_path [String] The path to the user configuration file.
|
87
|
+
# @return [void]
|
57
88
|
def run(config_path = nil)
|
58
89
|
Config.load_user_config(config_path)
|
59
90
|
Robot.new.run
|
60
91
|
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
def log_level
|
65
|
-
level = config.robot.log_level
|
66
|
-
|
67
|
-
if level
|
68
|
-
begin
|
69
|
-
Logger.const_get(level.to_s.upcase)
|
70
|
-
rescue NameError
|
71
|
-
return Logger::INFO
|
72
|
-
end
|
73
|
-
else
|
74
|
-
Logger::INFO
|
75
|
-
end
|
76
|
-
end
|
77
92
|
end
|
78
93
|
end
|
79
94
|
|
95
|
+
require "lita/util"
|
96
|
+
require "lita/logger"
|
80
97
|
require "lita/user"
|
81
98
|
require "lita/source"
|
82
99
|
require "lita/authorization"
|
83
100
|
require "lita/message"
|
101
|
+
require "lita/response"
|
102
|
+
require "lita/http_route"
|
103
|
+
require "lita/rack_app_builder"
|
84
104
|
require "lita/robot"
|
85
105
|
require "lita/adapter"
|
86
106
|
require "lita/adapters/shell"
|
87
107
|
require "lita/handler"
|
88
108
|
require "lita/handlers/authorization"
|
89
109
|
require "lita/handlers/help"
|
110
|
+
require "lita/handlers/web"
|