boty 0.0.17.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +559 -54
  4. data/bin/bot +10 -13
  5. data/docs/images/readme-01-screen-integration.png +0 -0
  6. data/docs/images/readme-02-screen-integration.png +0 -0
  7. data/docs/images/readme-03-screen-integration.png +0 -0
  8. data/lib/boty/action.rb +1 -1
  9. data/lib/boty/bot.rb +46 -63
  10. data/lib/boty/dsl.rb +52 -0
  11. data/lib/boty/eventable.rb +41 -0
  12. data/lib/boty/http.rb +33 -0
  13. data/lib/boty/locale.rb +17 -4
  14. data/lib/boty/logger.rb +21 -4
  15. data/lib/boty/rspec.rb +2 -3
  16. data/lib/boty/script_loader.rb +1 -1
  17. data/lib/boty/session.rb +21 -17
  18. data/lib/boty/slack/chat.rb +2 -2
  19. data/lib/boty/slack/message.rb +29 -0
  20. data/lib/boty/slack/users.rb +13 -0
  21. data/lib/boty/slack.rb +6 -0
  22. data/lib/boty/version.rb +1 -1
  23. data/lib/boty.rb +4 -4
  24. data/spec/boty/bot_spec.rb +105 -174
  25. data/spec/boty/dsl_spec.rb +125 -0
  26. data/spec/boty/http_spec.rb +5 -0
  27. data/spec/boty/logger_spec.rb +33 -0
  28. data/spec/boty/rspec_spec.rb +1 -1
  29. data/spec/boty/script_loader_spec.rb +27 -0
  30. data/spec/boty/session_spec.rb +9 -11
  31. data/spec/boty/slack/message_spec.rb +34 -0
  32. data/spec/boty/slack/users_spec.rb +41 -15
  33. data/spec/happy_path_spec.rb +22 -12
  34. data/spec/script/i18n_spec.rb +10 -4
  35. data/spec/script/pug_spec.rb +1 -1
  36. data/spec/spec_helper.rb +5 -2
  37. data/spec/support/logger_support.rb +20 -0
  38. data/spec/support/session_support.rb +2 -2
  39. data/template/project/bot.tt +4 -13
  40. data/template/project/script/ping.rb +3 -3
  41. metadata +14 -5
  42. data/lib/boty/message.rb +0 -27
  43. data/lib/boty/script_dsl.rb +0 -80
  44. data/spec/boty/message_spec.rb +0 -32
data/README.md CHANGED
@@ -3,18 +3,128 @@
3
3
 
4
4
  `Boty` is a utilitary to create bots (at this time, specificaly Slack bots).
5
5
 
6
- A bot is this context is a ordinary ruby application, that knows how to receive
7
- messages. Boty will give you a nice way to bind your own logic to specific
8
- messages of your own interest.
6
+ A bot in the context of this gem is an ordinary ruby application that knows how
7
+ to connect and receive messages in a Slack company room. `Boty` will give you a
8
+ nice api to bind your own logic to specific messages of your interest.
9
9
 
10
- ## Slack Bot Integration<a id="integration" />
10
+ ## Usage TL;DR version:<a id="tldr" />
11
+
12
+ - create [new slack bot integration](#integration) (http://[company].slack.com/services)
13
+ - `$ gem install boty`
14
+ - `$ boty new jeeba` (where `jeeba` it's a name that you will choose for the bot in the integration step)
15
+ - type your company name (the one used in the slack url: http://[company].slack.com)
16
+ - type the api key created on the [bot integration step](#integration)
17
+ - `$ cd jeeba` (the dir created after the name passed as parameter to the `new` command
18
+ - ./bot
19
+
20
+ Your bot should be up and running, which means: connected to your Slack room
21
+ under the name configured in the Slack Bot integration.
22
+
23
+ ### Custom scripts
24
+
25
+ On the `script` dir of your bot there is a example `ping` script. But you will
26
+ want to create your own scripts:
27
+
28
+ - stop the bot (if it's already running)
29
+ - add a new file named `hello.rb` into the `script` dir
30
+ - add a `command` to made it available via bot mention (`@jeeba` in my case)
31
+ - add a `hear` instruction so the `bot` listen to any message with the pattern configured
32
+ - use the method `#say` to instruct the `bot` to send a message in the channel
33
+ - use the method `#im` to instruct the `bot` to send a private message
34
+
35
+ ```ruby
36
+ # script/hello.rb
37
+ command "hi" do
38
+ say "hi #{user.name}"
39
+ end
40
+
41
+ command "im me" do
42
+ im "want something?"
43
+ end
44
+
45
+ hear "say something" do
46
+ say "something"
47
+ end
48
+ ```
49
+
50
+ - run the bot `./bot`
51
+ - on the slack room, issue the commands and send messages:
52
+
53
+ ```
54
+ valeriano 12:14 AM
55
+ @jeeba: hi
56
+
57
+ jeeba BOT 12:14 AM
58
+ hi valeriano
59
+
60
+ valeriano 12:14 AM
61
+ @jeeba: im me
62
+
63
+ # a private message will arrive:
64
+ jeeba BOT 12:14 AM
65
+ want something?
66
+
67
+ # back to the general channel:
68
+ valeriano 12:16 AM
69
+ say something
70
+
71
+ jeeba BOT 12:16 AM
72
+ something
73
+ ```
74
+
75
+ #### Regexes
76
+
77
+ There is an api to capture matches when regexes are used on `hear` and `command`
78
+ configurations:
79
+
80
+ - stop the bot (if it's already running)
81
+ - add a new file named `math.rb` into the `script` dir
82
+ - add the `command` `/sum (\d+) (\d+)/`:
83
+
84
+ ```ruby
85
+ # script/math.rb
86
+ command(/sum (\d+) (\d+)/) do |augend, addend|
87
+ say "(#{augend} plus #{addend}) = #{augend.to_i + addend.to_i}"
88
+ end
89
+ ```
90
+
91
+ - run the bot: `./bot`
92
+ - on the slack room, issue the command:
93
+
94
+ ```
95
+ valeriano 12:30 AM
96
+ @jabberu: sum 100 200
97
+
98
+ jabberu BOT 12:30 AM
99
+ (100 plus 200) = 300
100
+ ```
101
+
102
+ And this is pretty much it! :tada:
103
+
104
+ If you need more details about any of the features in `Boty`, you probably will
105
+ find it in this README, on the sections that follow.
106
+ If you don't find what you need, please contact us or even create an issue. Our
107
+ goals with this project are to make it usefull and easy to use, check the
108
+ [contributing](#contributing) info for more.
109
+
110
+ ## Usage (long version)<a id="usage" />
111
+
112
+ Now you will learn how to create a custom bot application for your needs, how to
113
+ configure it to allow the bot say stuff in your slack channels and finally, will
114
+ see how to run the bot properly.
115
+
116
+ ### Slack Bot Integration<a id="integration" />
11
117
 
12
118
  The first thing to do is to create a Slack Bot integration.
13
119
  Go to `http://[your-company-name].slack.com/services` to add a new one.
14
120
  In the process an `API Token` will be generated. That will be used in the [next
15
121
  step](#installation).
16
122
 
17
- ## Installation<a id="installation" />
123
+ - ![](docs/images/readme-01-screen-integration.png)
124
+ - ![](docs/images/readme-02-screen-integration.png)
125
+ - ![](docs/images/readme-03-screen-integration.png)
126
+
127
+ ### Installation<a id="installation" />
18
128
 
19
129
  Now you can install `Boty`:
20
130
 
@@ -26,15 +136,9 @@ This will give you an executable `boty`, which ships with a command `help` so
26
136
  you can know all the stuff that it can do. But the main one is to [create your
27
137
  new shiny bot](#usage).
28
138
 
29
- ## Usage<a id="usage" />
30
-
31
- In this section you will learn how to create a custom bot application for your
32
- needs, how to configure it to allow the bot say stuff in your slack channels and
33
- finally, will see how to run the bot properly.
34
-
35
139
  ### Creating a new bot
36
140
 
37
- To create a new bot, execute:
141
+ To create a new bot, execute this on your terminal:
38
142
 
39
143
  ```sh
40
144
  $ boty new jeeba
@@ -45,7 +149,7 @@ integration](#integration).
45
149
 
46
150
  The command will create a new directory after your bot name (`jeeba` in my
47
151
  example). Your _bot application_ will live in this directory. Feel free to check
48
- the directory, it will have some ruby files, some directories... it's just an
152
+ the contents, it will have some ruby files, some directories... it's just an
49
153
  ordinary ruby application.
50
154
 
51
155
  But first, let's see something about the [configurations](#configuration).
@@ -62,7 +166,360 @@ recently created dir.
62
166
 
63
167
  If you want to understand how this configuration is managed locally, you can
64
168
  check de [`Dotenv` gem documentation](https://github.com/bkeepers/dotenv), but
65
- you don't need to worry about it.
169
+ you don't need to worry about it, if you don't want.
170
+
171
+ Now, let's create some commands and message listeners on your bot.
172
+
173
+ ### Creating a Session (and the `bot` file).
174
+
175
+ Since you already have a `Boty` project configured with your company name and
176
+ api key, you should be able to start a new session for your bot by calling
177
+ `Session#start`.
178
+
179
+ This is a "blocking" call. It will hang to allow the bot to listen for messages
180
+ and send them. You can pass a block to it in order to configure your bot
181
+ preferences, or knowledge if you prefer =).
182
+
183
+ The block passed to `#start` will be _yielded_ in the scope of a `Bot`. In other
184
+ words, you can call any bot method inside this context. Note that at this time,
185
+ you can consider your `Bot` already connected to the Slack room.
186
+
187
+ ```ruby
188
+ session = Boty::Session.new
189
+ session.start do
190
+ # configure your bot here
191
+ end
192
+ ```
193
+
194
+ In your project there is a `bot` executable file. This file already creates a
195
+ `Session` with a minimum bot configuration: a listener with the bot name. Which
196
+ means that any message with the bot name will trigger the behavior in this
197
+ configuration.
198
+
199
+ This is just to save you time. You could start a Session by hand, if you wanted,
200
+ so feel free to check the code on this file and change it at will =).
201
+
202
+ Now it's time to better understand what is a listener, a command and how to use
203
+ regexes to configure the patterns that trigger the bot.
204
+
205
+ #### Command - a bot mention followed by a instruction pattern<a name="command" />
206
+
207
+ A `command` can be understood as a direct instruction to the bot. To be issued
208
+ the bot should be mentioned by the message using the default Slack mention
209
+ "operator" *`@`*.
210
+
211
+ To create a command, call the method `#command` on the bot passed as parameter
212
+ in the `Session#start` method. The `command` method receive the pattern for the
213
+ command, and the _block_ that should be executed when the command is issued.
214
+
215
+ See how to teach your bot to flip tables like a pro.
216
+
217
+ ```ruby
218
+ session = Boty::Session.new
219
+ session.start do
220
+ # ...
221
+
222
+ command("flip") do
223
+ say "HEY! (╯°□°)╯︵ ┻━┻"
224
+ end
225
+ end
226
+ ```
227
+
228
+ Now, to see the result, with the bot running, send in any channel where the bot
229
+ is (the #general is the default):
230
+
231
+ @jeeba: flip
232
+
233
+ (remember: `jeeba` is the name that I choose for my bot, you should use the
234
+ correct name here).
235
+
236
+ The previous command will result in the following response:
237
+
238
+ jeeba BOT 2:25 AM
239
+ HEY! (╯°□°)╯︵ ┻━┻
240
+
241
+ There is an alternative method to create a `command`: `bot#response`. Use the
242
+ one more appealing to you, they are the same.
243
+
244
+ The `bot#say` method used in this example is [better explained here](#bot_say).
245
+
246
+ Wrapping up:
247
+
248
+ - a command is a pattern triggered by a bot mention
249
+ - you can configure your bot patterns in the block passed to `Session#start`
250
+
251
+ Now, let's see how a listener works.
252
+
253
+ #### Listener - a message pattern that the bot should respond to<a name="listenter" />
254
+
255
+ A listener is used when the bot is interested in ANY messages containing some
256
+ pattern. Note that a listener will not be triggered only when there is a bot
257
+ mention, but anytime a message containing the pattern is sent on a channel where
258
+ the bot is.
259
+
260
+ Simple enough, let's get to the code:
261
+
262
+ ```ruby
263
+ session = Boty::Session.new
264
+ session.start do
265
+ # ...
266
+
267
+ hear("what's going on here?") do
268
+ say "I don't know. But something is always wrong. :scream:"
269
+ end
270
+ end
271
+ ```
272
+
273
+ This configuration says that anytime a message containing the string "what's
274
+ going on here?" is sent, the bot will respond. So a valid test could be send the
275
+ following message in the _#general_ channel:
276
+
277
+ valeriano 3:57 AM
278
+ OMG guys, what's going on here?
279
+
280
+ And the response will be, as expected:
281
+
282
+ jeeba BOT 3:57 AM
283
+ I don't know. But something is always wrong. :scream:
284
+
285
+ Wrapping up:
286
+
287
+ - A listener is triggered for any message containing the pattern
288
+ - A listener don't need a bot mention, so careful: the range of this config is wide
289
+
290
+ Before we start to study the "script" way of configuring `command` and
291
+ `listener` binds, let's see how we can use ruby regexps to capture message
292
+ parameters.
293
+
294
+ ##### Regexes - a pattern that allow capture parameters within a message<a name="regexes" />
295
+
296
+ What is a bot if it can't annoy people when we want it to? So let's teach our
297
+ bot to send private messages to people in the Slack room.
298
+
299
+ Let's create an `im` _command_ that will be capable of extract the person to
300
+ whom we want to send a message, and the message that we want the bot send. Our
301
+ bot will be capable of understand the following instruction:
302
+
303
+ valeriano 2:44 PM
304
+ @jeeba: im julian with omg! lol! bbq!
305
+
306
+ The _command_ configuration can be like this:
307
+
308
+ ```ruby
309
+ command /im (\w+) with (.*)/ do |person, message|
310
+ im message, to: person
311
+ end
312
+ ```
313
+
314
+ The regex matched portions will be passed as parameter to the block given to
315
+ _command_.
316
+
317
+ And this is it! :tada:
318
+
319
+ ### Adding custom scripts<a name="custom_scripts" />
320
+
321
+ Now you already know what are [listeners](#listeners) and
322
+ [commands](#command). It's time to know another way to create those "binders",
323
+ it's what we call `scripts`.
324
+
325
+ Any ruby file available on `scripts` will be loaded when a `Session` starts.
326
+ Your bot ships with an example script named `script/ping.rb`, with a very simple
327
+ example of what you can do. But let's create a new script from scratch.
328
+
329
+ Create a new file `script/flip.rb` on your bot directory. Any method available
330
+ in a bot will be available in this file, which means you can use `command`,
331
+ `hear`, `im`, `say`, `message`, etc.
332
+
333
+ Let's code:
334
+
335
+ ```ruby
336
+ # script/flip.rb
337
+ command "flip" do
338
+ say "(╯°□°)╯︵ ┻━┻"
339
+ end
340
+ ```
341
+
342
+ And this is pretty much it. When your bot runs, it will be able to perform the
343
+ command `flip`:
344
+
345
+ valeriano 3:36 PM
346
+ @jeeba: flip
347
+
348
+ jeeba BOT 3:36 PM
349
+ (╯°□°)╯︵ ┻━┻
350
+
351
+ So feel free to customize the `bot` file or create your own scripts. What please
352
+ you more is what you should use.
353
+
354
+ ### DSL for bot scripting<a name="bot_dsl" />
355
+
356
+ In this section you will see all the methods available to configure your `bot`.
357
+
358
+ #### `bot#say` - Sending public messages on Slack channels<a name="bot_say" />
359
+
360
+ Use `#say` when the bot should send a message in the channel that triggered the
361
+ configuration block:
362
+
363
+ ```ruby
364
+ command "flip" do
365
+ say "(╯°□°)╯︵ ┻━┻"
366
+ end
367
+ ```
368
+
369
+ If the bot wants to start a conversation, or even just say something in a
370
+ channel without have received a message (via `#hear` or `#command`), just call
371
+ `#say` inside a script.
372
+
373
+ ```ruby
374
+ say "ready to turn tables", channel: "#general"
375
+
376
+ command "flip" do
377
+ say "(╯°□°)╯︵ ┻━┻"
378
+ end
379
+ ```
380
+
381
+ If a channel isn't passed to `#say` it will defaults to `"#general"`. You can
382
+ use any [Slack RTM postMessage](https://api.slack.com/methods/chat.postMessage)
383
+ parameter when calling `#say`.
384
+
385
+ #### `bot#im`<a name="bot_im" />
386
+
387
+ Bots can send private messages. Use the `#im` method:
388
+
389
+ ```ruby
390
+ command "who am I?" do
391
+ im "you are #{user.name}!"
392
+ end
393
+ ```
394
+
395
+ In the previous example, the private message will be sent to the user that
396
+ issued the command, this is a default. If you want the bot to send a message to
397
+ a specific user, just indicate the user name via the `to` option:
398
+
399
+ ```ruby
400
+ command "annoys julian" do
401
+ im "Loren Ipsum, Julian boy!", to: "julian"
402
+ end
403
+ ```
404
+
405
+ #### `bot#message`<a name="bot_message" />
406
+
407
+ The message that triggered a block is made available in the block's scope in the
408
+ method `#message`:
409
+
410
+ ```ruby
411
+ command "what did you say?" do
412
+ say "Well: #{message.text}"
413
+ end
414
+ ```
415
+
416
+ Execute the previous command will be as follows:
417
+
418
+ valeriano 12:07 AM
419
+ @jeeba: what did you say?
420
+
421
+ jeeba BOT 12:07 AM
422
+ Well: @jeeba: what did you say?
423
+
424
+ Note that the `#text` returns the raw message that triggered the handler,
425
+ including the bot mention itself.
426
+
427
+ #### `bot#user`<a name="bot_user" />
428
+
429
+ If the bot need to access the data about the user that send the message that
430
+ triggered the handler, use the `#user` method.
431
+
432
+ Let me borrow an already used example:
433
+
434
+
435
+ ```ruby
436
+ command "who am I?" do
437
+ im "you are #{user.name}!"
438
+ end
439
+ ```
440
+
441
+ #### `bot#http`<a name="bot_http" />
442
+
443
+ There is an utilitary method `#http` available on the handler block. This guy is
444
+ useful to make, well... http requests. It supports all http verbs and return a
445
+ `Hash` if the http response contains a `"application/json"` _Content-Type_
446
+ header, or else the raw body.
447
+
448
+ Let's create a `command` that fetches a [xkcd](http://xkcd.com/) strip for us:
449
+
450
+ ```ruby
451
+ command /xkcd(\s\d+)?/ do |number|
452
+ number = number ? number.strip : "1"
453
+ xkcd = http.get "http://xkcd.com/#{number}/info.0.json"
454
+ say "#{xkcd["alt"]}\n<#{xkcd["img"]}>"
455
+ end
456
+ ```
457
+
458
+ To execute this command:
459
+
460
+ valeriano 12:40 AM
461
+ @jabberu: xkcd 2
462
+
463
+ The strip number 2 of [xkcd](http://xkcd.com/) will be brought to the room. If
464
+ we don't pass a number parameter, the strip number 1 will be assumed as default.
465
+
466
+ If something goes wrong with the request, you can use the `http#response` method
467
+ to access the inner response object. It'll be a
468
+ [faraday](https://github.com/lostisland/faraday) http response object.
469
+
470
+ #### `bot#desc` - Describing your bindings<a name="bot_desc" />
471
+
472
+ A bot list all the commands and message handlers that it knows in the moment. If
473
+ you want to give a nice description and/or a usage tip on command you can use
474
+ the `desc` method.
475
+
476
+ Given that your bot has the following script:
477
+
478
+ ```ruby
479
+ desc "pug me", "Send some nice pug in the channel."
480
+ respond(/pug me/i) do
481
+ # ...
482
+ end
483
+ ```
484
+
485
+ The follow text will be part of the response for a `@bot: knows` command:
486
+
487
+ pug me: Send some nice pug in the channel.
488
+
489
+ You can use just the description if you want. In this case the `regex` itself
490
+ will be used as the command name.
491
+
492
+ ```ruby
493
+ desc "Send some nice pug in the channel."
494
+ respond(/pug me/i) do
495
+ # ...
496
+ end
497
+ ```
498
+
499
+ valeriano 2:25PM
500
+ @bot: knows
501
+
502
+ bot 2:25PM
503
+ knows: List all the commands known by this bot.
504
+ /pug me/i: Send some nice pug in the channel.
505
+
506
+ We strongly recommend that you describe all of your scripts. But if you don't,
507
+ the bot will be capable of tell you what `regexes` are binded to it:
508
+
509
+ valeriano 2:47PM
510
+ @jabberu: knows
511
+
512
+ jabberu 2:47PM
513
+ knows: List all the commands known by this bot.
514
+ /pug me/i
515
+ /jabberu, are you there\?/i
516
+
517
+ #### Testing your own scripts
518
+
519
+ **todo: document**
520
+
521
+ For now, check the `spec/script/ping_spec.rb` and follow it's leads.
522
+
66
523
 
67
524
  ### Running locally<a id="running" />
68
525
 
@@ -125,77 +582,125 @@ On the tab _Resources_, find a line with the information:
125
582
 
126
583
  Turn on this resource. And done, your bot is up and running!
127
584
 
585
+ ### Using the logger
128
586
 
129
- ## Adding custom scripts
587
+ `Boty` ships with a builtin logger that can be used in your own scripts. It is
588
+ made available via `#logger`.
589
+ This will return a instance of a [Ruby Logger](http://ruby-doc.org/stdlib-2.2.3/libdoc/logger/rdoc/Logger.html).
130
590
 
131
- **todo: document**
591
+ Note that the default logger implementation will write to the `STDOUT` .Let's
592
+ see a usage example:
132
593
 
133
- For now, check the `script/ping.rb` and follow it's leads.
594
+ ```ruby
595
+ session.start do
596
+ command(/hello/i) do
597
+ logger.debug "saying hello"
598
+ say "hello there."
599
+ end
600
+ end
601
+ ```
134
602
 
135
- ### Describing script usage
603
+ By default the logger will write on the standard output, the previous command,
604
+ when triggered, will produce the following log line:
136
605
 
137
- A bot list all the commands and message handlers that it knows in the moment. If
138
- you want to give a nice description and/or a usage tip on command you can use
139
- the `desc` method.
606
+ D, [2015-12-11T00:13:28.712380 #40369] DEBUG -- : saying hello
140
607
 
141
- Given that your bot has the following script:
608
+ Of course, if you need to write to a file, instead of the STDOUT, just change
609
+ the adapter for your logger.
610
+
611
+ #### Log into files (instead of STDOUT)
612
+
613
+ Before start your bot session, configure the file log:
142
614
 
143
615
  ```ruby
144
- desc "pug me", "Send some nice pug in the channel."
145
- respond(/pug me/i) do
146
- # ...
147
- end
616
+ Boty::Logger.adapter = Logger.new("log/output.log")
148
617
  ```
149
618
 
150
- The follow text will be part of the response for a `@bot: knows` command:
619
+ And this is all you need! :tada:
151
620
 
152
- pug me: Send some nice pug in the channel.
621
+ #### Logger adapters
153
622
 
154
- You can use just the description if you want. In this case the `regex` itself
155
- will be used as the command name.
623
+ There is an adapter included on `Boty` that can be used by you and is also a
624
+ good example of how to create a custom logger adapter for `Boty`.
625
+
626
+ Supose that you want to write to a file and still send the logs to the `STDOUT`.
627
+ You can use the `Multi` adapter like this:
156
628
 
157
629
  ```ruby
158
- desc "Send some nice pug in the channel."
159
- respond(/pug me/i) do
160
- # ...
630
+ Boty::Logger.adapter = Boty::Logger::Multi.new([
631
+ Logger.new(STDOUT),
632
+ Logger.new("log/output.log")
633
+ ])
634
+ ```
635
+
636
+ And this is it. Now when you call `logger.debug "some message"` from your bot,
637
+ this log line will be writen to the `"log/output.log"` file and also in the
638
+ `STDOUT`.
639
+
640
+ You can write you own log adapter if you want. The `Multi` adapter
641
+ implementation is fairly simple. Let's use it as an example of how to write your
642
+ own adapter.
643
+
644
+ You can extend the ruby _Logger_ class and worry yourself on write the `#add`
645
+ overrite:
646
+
647
+ ```ruby
648
+ class Multi < ::Logger
649
+ def initialize(adapters)
650
+ @adapters = adapters
651
+ end
652
+
653
+ def add(*args, &block)
654
+ @adapters.each do |adapter|
655
+ adapter.add(*args, &block)
656
+ end
657
+ end
161
658
  end
162
659
  ```
163
660
 
164
- valeriano 2:25PM
165
- @bot: knows
661
+ The add method is called internaly by _Logger_ and has all the information that
662
+ the auxiliary methods like `#debug`, `#info` etc received when called.
166
663
 
167
- bot 2:25PM
168
- knows: List all the commands known by this bot.
169
- /pug me/i: Send some nice pug in the channel.
664
+ The _Multi_ adapter implementation just delegate this call to the underlying
665
+ adapters passed as parameters for the constructor.
170
666
 
171
- We strongly recommend that you describe all of your scripts. But if you don't,
172
- the bot will be capable of tell you what `regexes` are binded to it:
667
+ For more information on the `#add` parameters, [check the ruby doc](http://ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html#method-i-add).
173
668
 
174
- valeriano 2:47PM
175
- @jabberu: knows
669
+ _Multi_ also allows you to change the level for all the underlying adapters at
670
+ once, the `#level=` overrite implementation is like this:
176
671
 
177
- jabberu 2:47PM
178
- knows: List all the commands known by this bot.
179
- /pug me/i
180
- /jabberu, are you there\?/i
672
+ ```ruby
673
+ def level=(level)
674
+ @adapters.each do |adapter|
675
+ adapter.level = level
676
+ end
677
+ end
678
+ ```
181
679
 
182
- ### Testing your own scripts
680
+ ### I18n
183
681
 
184
682
  **todo: document**
185
683
 
186
- For now, check the `spec/script/ping_spec.rb` and follow it's leads.
187
-
188
684
  ## Development
189
685
 
190
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
686
+ After checking out the repo, run `bin/setup` to install dependencies. You can
687
+ also run `bin/console` for an interactive prompt that will allow you to
688
+ experiment.
689
+
690
+ To install this gem onto your local machine, run `bundle exec rake install`.
191
691
 
192
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
692
+ ### The local ./bin/bot
193
693
 
194
- ## Contributing
694
+ ### Code guidelines
195
695
 
196
- Bug reports and pull requests are welcome on GitHub at https://github.com/ricardovaleriano/boty. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
696
+ ## Contributing<a name="contributing" />
197
697
 
698
+ Bug reports and pull requests are very welcome on GitHub at
699
+ https://github.com/ricardovaleriano/boty. This project is intended to be a safe,
700
+ welcoming space for collaboration, and contributors are expected to adhere to
701
+ the [Contributor Covenant](contributor-covenant.org) code of conduct.
198
702
 
199
703
  ## License
200
704
 
201
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
705
+ The gem is available as open source under the terms of the
706
+ [MIT License](http://opensource.org/licenses/MIT).