hipbot 1.0.0.rc2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +6 -0
  4. data/Gemfile +1 -2
  5. data/README.md +482 -88
  6. data/Rakefile +1 -1
  7. data/bin/hipbot +4 -4
  8. data/hipbot.gemspec +9 -9
  9. data/lib/hipbot.rb +28 -11
  10. data/lib/hipbot/adapter.rb +80 -0
  11. data/lib/hipbot/adapters/hipchat.rb +53 -0
  12. data/lib/hipbot/adapters/hipchat/initializer.rb +83 -0
  13. data/lib/hipbot/adapters/shell.rb +37 -0
  14. data/lib/hipbot/adapters/telnet.rb +41 -0
  15. data/lib/hipbot/bot.rb +15 -52
  16. data/lib/hipbot/cache.rb +23 -0
  17. data/lib/hipbot/callbacks/base.rb +15 -0
  18. data/lib/hipbot/callbacks/invite.rb +11 -0
  19. data/lib/hipbot/callbacks/lobby_presence.rb +13 -0
  20. data/lib/hipbot/callbacks/message.rb +11 -0
  21. data/lib/hipbot/callbacks/presence.rb +17 -0
  22. data/lib/hipbot/callbacks/private_message.rb +12 -0
  23. data/lib/hipbot/callbacks/room_message.rb +21 -0
  24. data/lib/hipbot/callbacks/room_presence.rb +28 -0
  25. data/lib/hipbot/configurable.rb +22 -0
  26. data/lib/hipbot/configuration.rb +9 -3
  27. data/lib/hipbot/helpers.rb +4 -40
  28. data/lib/hipbot/http.rb +65 -0
  29. data/lib/hipbot/match.rb +21 -9
  30. data/lib/hipbot/matchable.rb +38 -0
  31. data/lib/hipbot/message.rb +24 -9
  32. data/lib/hipbot/plugin.rb +3 -3
  33. data/lib/hipbot/reactable.rb +14 -21
  34. data/lib/hipbot/reaction.rb +27 -15
  35. data/lib/hipbot/reaction_factory.rb +38 -0
  36. data/lib/hipbot/response.rb +18 -10
  37. data/lib/hipbot/room.rb +34 -2
  38. data/lib/hipbot/storages/base.rb +78 -0
  39. data/lib/hipbot/storages/hash.rb +89 -0
  40. data/lib/hipbot/storages/mongoid.rb +18 -0
  41. data/lib/hipbot/user.rb +8 -2
  42. data/lib/hipbot/version.rb +1 -1
  43. data/spec/integration/my_hipbot.rb +24 -4
  44. data/spec/integration/{hipbot_spec.rb → my_hipbot_spec.rb} +41 -23
  45. data/spec/spec_helper.rb +14 -2
  46. data/spec/unit/adapters/hipchat_spec.rb +5 -0
  47. data/spec/unit/{hipbot_spec.rb → bot_spec.rb} +13 -12
  48. data/spec/unit/match_spec.rb +148 -0
  49. data/spec/unit/message_spec.rb +14 -7
  50. data/spec/unit/reaction_factory_spec.rb +54 -0
  51. data/spec/unit/reaction_spec.rb +99 -0
  52. data/spec/unit/storages/hash_spec.rb +75 -0
  53. data/spec/unit/user_spec.rb +0 -2
  54. metadata +64 -54
  55. data/Gemfile.lock +0 -90
  56. data/examples/cleverbot.rb +0 -23
  57. data/examples/google_images.rb +0 -35
  58. data/lib/hipbot/adapters/hipchat/connection.rb +0 -166
  59. data/lib/hipbot/adapters/hipchat/hipchat.rb +0 -13
  60. data/lib/hipbot/adapters/telnet/connection.rb +0 -17
  61. data/lib/hipbot/adapters/telnet/telnet.rb +0 -14
  62. data/lib/hipbot/collection.rb +0 -72
  63. data/lib/hipbot/patches/hipchat_client.rb +0 -230
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 817d131f49971f64a368aa7f2da59edc03707fd8
4
- data.tar.gz: ead66146d16bae22138ac8b80bd36c5efdfe2433
3
+ metadata.gz: ef74572ebd12e87ab892010a3c8c0bae5b146584
4
+ data.tar.gz: 03a8912f6c9958a88d3e2294844f6fc5fa5b7bc9
5
5
  SHA512:
6
- metadata.gz: 84968ca38161cdd6ea4ed251b8bc3dc692d7eba6e92bb237bbe934339dbb2204e1371a4ac8d0d97a008e3c3fed1de33ac7c9c52d1ce27f1f2f75795a42c46046
7
- data.tar.gz: dc0807cab3a8b9b70b19d941839406e4c0e7055a41226814fa0729f5907fd3ae301fe5cb38d86be5006677a9ede886ee676e94eb2e6ac7e77cfe0773027f1dab
6
+ metadata.gz: e8f9b8bd967a44c5b0b09057c63b257418f988a616e02cb63d91f55a26115f72da08ff3d82ead405ed48f38d7e24d8bf458bf6ed45d49bd16ab483c77d4e0bd2
7
+ data.tar.gz: e174318fef49cc39dc116ce31057d5377a015c35989f4b2be9451fbb7737b98dae68f6de96bd1a2c8111be5dbaa245e61ae081f938a3bee1b43078e625a315ce
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  *.gem
2
- test_bot.rb
3
2
  coverage/*
3
+ .bundle
4
+ Gemfile.lock
@@ -3,6 +3,12 @@ rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
5
  - 2.0.0
6
+ - jruby-19mode
7
+ - rbx-19mode
8
+ - jruby-head
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: ruby-head
6
12
  notifications:
7
13
  email:
8
14
  recipients:
data/Gemfile CHANGED
@@ -3,11 +3,10 @@ source 'https://rubygems.org'
3
3
  gem 'rake'
4
4
  gem 'eventmachine'
5
5
  gem 'em-http-request'
6
- gem 'xmpp4r'
7
6
  gem 'httparty'
8
7
  gem 'activesupport'
9
- gem 'i18n'
10
8
  gem 'daemons'
9
+ gem 'xmpp4r-hipchat', github: 'bartoszkopinski/xmpp4r-hipchat', branch: 'master'
11
10
 
12
11
  gem 'rspec'
13
12
  gem 'guard-rspec'
data/README.md CHANGED
@@ -1,161 +1,472 @@
1
1
  # Hipbot
2
2
 
3
+ Hipbot is a XMPP bot for HipChat, written in Ruby with EventMachine.
4
+
3
5
  [![Build Status](https://secure.travis-ci.org/pewniak747/hipbot.png?branch=master)](http://travis-ci.org/pewniak747/hipbot)
4
6
  [![Code Climate](https://codeclimate.com/github/pewniak747/hipbot.png)](https://codeclimate.com/github/pewniak747/hipbot)
5
7
  [![Coverage Status](https://coveralls.io/repos/pewniak747/hipbot/badge.png?branch=master)](https://coveralls.io/r/pewniak747/hipbot)
6
8
  [![Dependency Status](https://gemnasium.com/pewniak747/hipbot.png)](https://gemnasium.com/pewniak747/hipbot)
7
9
  [![Gem Version](https://badge.fury.io/rb/hipbot.png)](http://badge.fury.io/rb/hipbot)
8
10
 
9
- Hipbot is a XMPP bot for HipChat, written in ruby & eventmachine.
11
+ ### Compatibility
12
+ Hipbot is tested on:
10
13
 
11
- ## Usage
14
+ * Ruby 1.9.2, 1.9.3 and 2.0.0
15
+ * JRuby 1.9 mode
16
+ * Rubinus 1.9 mode
12
17
 
13
- For easy install, follow the instructions on https://github.com/netguru/hipbot-example .
18
+ ### Dependencies
14
19
 
15
- ### Install
20
+ * daemons >= 1.1.8
21
+ * activesupport >= 3.2.12
22
+ * eventmachine >= 1.0.3
23
+ * em-http-request >= 1.0.3
24
+ * xmpp4r ~> 0.5
16
25
 
17
- ```
26
+ ## Getting started
27
+ ### Installation
28
+
29
+ ```shell
18
30
  gem install hipbot
19
31
  ```
20
32
 
21
- ### Customize
33
+ ### 1 minute setup on heroku
22
34
 
35
+ Follow the instructions on [hipbot-example](https://github.com/netguru/hipbot-example).
36
+
37
+ ### Custom setup
23
38
  Create `bot.rb` file, subclass `Hipbot::Bot` and customize the responses.
24
39
 
25
40
  ```ruby
26
41
  require 'hipbot'
27
42
 
28
- class MyCompanyBot < Hipbot::Bot
43
+ class MyBot < Hipbot::Bot
29
44
  configure do |c|
30
- c.jid = 'changeme@chat.hipchat.com' # required
31
- c.password = 'secret' # required
32
- c.teams = { vip: ['John', 'Mike'] }
33
- c.rooms = { project_rooms: ['Project 1', 'Project 2'] }
45
+ c.jid = 'changeme@chat.hipchat.com'
46
+ c.password = 'secret'
34
47
  end
35
48
 
36
- on /^hello/ do
37
- reply('hello!')
49
+ on /^hello$/ do
50
+ reply("Hello!")
38
51
  end
52
+ end
39
53
 
40
- on /^restart/, from: :vip do
41
- # ...
42
- reply('restarting...')
43
- end
54
+ MyBot.start!
55
+ ```
44
56
 
45
- on /^deploy/, room: :project_rooms do
46
- # ...
47
- reply('deploying...')
48
- end
57
+ ### Running
58
+ Start Hipbot as a daemon by executing:
59
+
60
+ ```shell
61
+ hipbot start
62
+ ```
63
+
64
+ Run `hipbot` to see all available commands.
65
+
66
+ Start in shell:
67
+
68
+ ```shell
69
+ ruby bot.rb
70
+ ```
71
+
72
+ ### Behavior
73
+ * On start and runtime:
74
+ * Fetches details and presences of all users in Lobby
75
+ * Pings XMPP server every 60 seconds to keep alive
76
+ * On new message:
77
+ * Invokes all matching reactions or falls back to default reaction
78
+
79
+ ## Usage
80
+ ### Configuration
81
+ Full configuration example:
82
+ ```ruby
83
+ class MyBot < Hipbot::Bot
84
+ configure do |c|
85
+ # Account JID (required) - see https://hipchat.com/account/xmpp for your JID
86
+ c.jid = 'changeme@chat.hipchat.com'
87
+
88
+ # Account password (required)
89
+ c.password = 'secret'
49
90
 
50
- default do
51
- reply('I don\'t understand you!')
91
+ # Custom helpers module (optional) - see below for examples
92
+ c.helpers = MyHipbotHelpers
93
+
94
+ # Logger (default: Hipbot::Logger.new($stdout))
95
+ c.logger = Hipbot::Logger.new($stdout)
96
+
97
+ # Initial status message (default: '')
98
+ c.status = "I'm here to help"
99
+
100
+ # Storage adapter (default: Hipbot::Storages::Hash)
101
+ c.storage = Hipbot::Storages::Hash
102
+
103
+ # Predefined room groups (optional)
104
+ c.rooms = { project_rooms: ['Project 1', 'Project 2'] }
105
+
106
+ # Predefined user groups (optional)
107
+ c.teams = { admins: ['John Smith'] }
108
+
109
+ # Auto join criteria (default: :all)
110
+ # Accepted values: :all, :public, :private, :none, "room name"
111
+ c.join = :private
52
112
  end
53
113
  end
114
+ ```
115
+ ### Reaction helpers
116
+ Inside the reaction block you have access to following context objects:
54
117
 
55
- class PluginClass
56
- include Hipbot::Plugin
118
+ * `bot`
119
+ * `room`
120
+ * `sender`
121
+ * `message`
122
+ * `reaction`
57
123
 
58
- on /^plugin/ do
59
- reply('this is from plugin!')
60
- end
124
+ ### Joining rooms
125
+ Hipbot will join all accessible rooms by default on startup and invite.
126
+
127
+ To change auto join method use `join` configuration option:
128
+ ```ruby
129
+ configure do |c|
130
+ # ...
131
+ c.join = :private
132
+ end
133
+ ```
134
+ ```ruby
135
+ configure do |c|
136
+ # ...
137
+ c.join = :none
61
138
  end
139
+ ```
140
+ ```ruby
141
+ configure do |c|
142
+ # ...
143
+ c.join = ['Project Room', :public]
144
+ end
145
+ ```
146
+ Notice: Archived rooms are always ignored
62
147
 
63
- MyCompanyBot.start!
148
+ ### Bot presence
149
+ Use `bot.set_presence` method to change Hipbot presence:
150
+ ```ruby
151
+ on /^change status$/ do
152
+ bot.set_presence("Hello humans")
153
+ end
154
+ ```
155
+ ```ruby
156
+ on /^go away$/ do
157
+ bot.set_presence("I'm away", :away)
158
+ end
159
+ ```
160
+ ```ruby
161
+ on /^do not disturb$/ do
162
+ bot.set_presence(nil, :dnd)
163
+ end
64
164
  ```
65
165
 
66
- You can create a response by providing simple regexp:
166
+ ### Rooms
167
+ Use `Hipbot::Room` for collection of available rooms.
168
+ ```ruby
169
+ on /^list all rooms$/ do
170
+ all_rooms = Hipbot::Room.all.map(&:name)
171
+ reply(all_rooms.join(', '))
172
+ end
173
+ ```
174
+ ```ruby
175
+ on /^get project room JID$/ do
176
+ project_room = Hipbot::Room.find_by(name: 'project room')
177
+ reply(project_room.id)
178
+ end
179
+ ```
180
+ Use `room` for current room object (it's `nil` if message is private):
181
+ ```ruby
182
+ on /^where am I\?$/ do
183
+ reply(
184
+ "You are in #{room}\n" +
185
+ "JID: #{room.id}\n" +
186
+ "Topic: #{room.topic}\n" +
187
+ "Users online: #{room.users.count}\n" +
188
+ "Privacy: #{room.privacy}\n" +
189
+ "Hipchat ID: #{room.hipchat_id}\n" +
190
+ "Archived?: #{room.archived ? 'yes' : 'no'}\n" +
191
+ "Guest URL: #{room.guest_url}"
192
+ )
193
+ end
194
+ ```
67
195
 
196
+ ### Users
197
+ Use `Hipbot::User` for collection of all users:
198
+ ```ruby
199
+ on /^list all users$/ do
200
+ all_users = Hipbot::User.all.map(&:name)
201
+ reply(all_users.join(', '))
202
+ end
203
+ ```
204
+ ```ruby
205
+ on /^get John Smith's JID$/ do
206
+ john = Hipbot::Room.find_by(name: 'John Smith')
207
+ reply(john.id)
208
+ end
209
+ ```
210
+ Use `sender` for message sender object:
211
+ ```ruby
212
+ on /^who am I\?$/ do
213
+ reply(
214
+ "You are #{sender}\n" +
215
+ "JID: #{sender.id}\n" +
216
+ "Mention: @#{sender.mention}\n" +
217
+ "E-mail: #{sender.email}\n" +
218
+ "Title: #{sender.title}\n" +
219
+ "Photo: #{sender.photo}"
220
+ )
221
+ end
222
+ ```
223
+ Use `Room#users` method for online users array:
68
224
  ```ruby
69
- on /^hello/ do
70
- reply('hello!')
225
+ on /^list online users$/ do
226
+ reply room.users.map(&:name).join(', ')
71
227
  end
72
228
  ```
73
229
 
74
- Responses can pass arguments from regexps:
230
+ ### Replying
231
+ Use `reply` method to send a message.
232
+
233
+ Reply in the same room / chat:
234
+ ```ruby
235
+ on /^hello$/ do
236
+ reply("Hello!")
237
+ end
238
+ ```
239
+ Reply in "help room":
240
+ ```ruby
241
+ on /^I need help$/ do
242
+ help_room = Hipbot::Room.find_by(name: 'help room')
243
+ reply("#{sender} needs help in #{room}", help_room)
244
+ end
245
+ ```
75
246
 
247
+ ### Private messaging
248
+ ```ruby
249
+ on /^send me private message$/ do
250
+ sender.send_message("Hello, #{sender}")
251
+ end
252
+ ```
76
253
  ```ruby
77
- on /my name is (.*)/ do |user_name|
78
- reply('hello #{user_name}!')
254
+ on /^send private message to John$/ do
255
+ john = Hipbot::User.find_by(name: 'John Smith')
256
+ john.send_message("Hello, John!")
79
257
  end
80
258
  ```
81
259
 
82
- Define multiple regexps for a response:
260
+ ### Topics
261
+ ```ruby
262
+ on /^current topic$/ do
263
+ reply("Current topic: #{room.topic}")
264
+ end
265
+ ```
266
+ ```ruby
267
+ on /^change topic here$/ do
268
+ room.set_topic("New Topic")
269
+ end
270
+ ```
271
+ ```ruby
272
+ on /^change topic there$/ do
273
+ there = Hipbot::Room.find_by(name: 'there')
274
+ there.set_topic("New Topic")
275
+ end
276
+ ```
83
277
 
278
+ ### Regexp matchdata
279
+ ```ruby
280
+ on /^My name is (.*)$/ do |user_name|
281
+ reply("Hello, #{user_name}!")
282
+ end
283
+ ```
84
284
  ```ruby
85
- on /my name is (.*)/, /I am (.*)/ do |name|
86
- reply('hello #{user_name}!')
285
+ on /^My name is (\S*) (\S*)$/ do |first_name, last_name|
286
+ reply("Hello, #{first_name} #{last_name}!")
87
287
  end
88
288
  ```
89
289
 
90
- Use :from to only match messages from certain users or user groups defined in configuration
290
+ ### Multiple regexps
291
+ ```ruby
292
+ on /^My name is (.*)$/, /^I am (.*)$/ do |user_name|
293
+ reply("Hello, #{user_name}!")
294
+ end
295
+ ```
91
296
 
297
+ ### Sender restriction
298
+ Use `:from` option to match messages only from certain users or user groups defined in configuration.
299
+ It accepts string, symbol and array values.
92
300
  ```ruby
93
301
  configure do |c|
94
302
  # ...
95
- c.teams = { vip: ['John', 'Mike'] }
303
+ c.teams = { vip: ['John Edward', 'Mike Anderson'] }
96
304
  end
97
305
 
98
- on /status report/, from: ['Tom', 'Dave', :vip] do
99
- reply('all clear')
306
+ on /^report status$/, from: ['Tom Smith', 'Jane Doe', :vip] do
307
+ reply('All clear')
100
308
  end
101
309
  ```
102
310
 
103
- Use :room to only match messages in certain hipchat rooms
104
-
311
+ ### Room restriction
312
+ Use `:room` option to match messages opny from certain HipChat rooms.
313
+ It accepts string, symbol, array and boolean values.
105
314
  ```ruby
106
315
  configure do |c|
107
316
  # ...
108
317
  c.rooms = { project_rooms: ['Project 1', 'Project 2'] }
109
318
  end
110
319
 
111
- on /hello/, room: ['Public Room', :project_rooms] do
112
- reply('hello!')
320
+ on /^hello$/, room: ['Public Room', :project_rooms] do
321
+ reply('Hello!')
322
+ end
323
+ ```
324
+ Match only private messages:
325
+ ```ruby
326
+ on /^private hello$/, room: false do
327
+ reply('Private hello!')
328
+ end
329
+ ```
330
+ Match only room messages:
331
+ ```ruby
332
+ on /^public hello$/, room: true do
333
+ reply('Public hello!')
113
334
  end
114
335
  ```
115
336
 
116
- Use :global to react to messages that are not sent directly to @robot
337
+ ### Global reaction
338
+ By default, Hipbot reacts only to its HipChat mention.
339
+ Use `global: true` option to match all messages:
117
340
 
118
341
  ```ruby
119
- on /hey I just met you/, global: true do
342
+ on /^Hey I just met you$/, global: true do
120
343
  reply('and this is crazy...')
121
344
  end
122
345
  ```
123
346
 
124
- (Use with caution!)
347
+ ### Conditional reaction
348
+ Use `:if` option to specify certain dynamic conditions:
349
+ ```ruby
350
+ on /^Is it friday\?$/, if: ->{ Time.now.friday? } do
351
+ reply('Yes, indeed')
352
+ end
353
+ ```
354
+ ```ruby
355
+ admins = ['John Smith']
356
+ on /^add admin (.*)$/, if: ->(sender){ admins.include?(sender.name) } do |user_name|
357
+ admins << user_name
358
+ end
359
+ ```
360
+ ```ruby
361
+ on /^choose volunteer$/, if: ->(room){ room.users.count > 3 } do
362
+ reply("Choosing #{room.users.sample}")
363
+ end
364
+ ```
125
365
 
126
- For more examples, check out (https://github.com/pewniak747/hipbot/tree/master/examples)
366
+ ### Method reaction
367
+ Use symbol instead of block to react with a instance method:
368
+ ```ruby
369
+ def hello(user_name)
370
+ reply("Hello #{user_name}!")
371
+ end
127
372
 
128
- #### Response helpers
373
+ on /^My name is (.*)$/, :hello
374
+ ```
129
375
 
130
- Use http helpers (`get`, `post`, `put`, `delete`) to preform a http request:
376
+ ### Scopes
377
+ Use `scope` blocks to extract common options:
378
+ ```ruby
379
+ configure do |c|
380
+ # ...
381
+ c.teams = { admins: ['John Edward', 'Mike Anderson'] }
382
+ end
383
+
384
+ scope from: :admins, room: true do
385
+ on /^restart server$/ do
386
+ # Restarting...
387
+ end
388
+
389
+ scope global: true do
390
+ on /^deploy production$/ do
391
+ # Deploying...
392
+ end
393
+
394
+ on /^check status$/ do
395
+ # Checking...
396
+ end
397
+ end
398
+ end
399
+ ```
400
+
401
+ ### Default reactions
402
+ Default reaction can take the same options as regular one.
403
+ Hipbot fall backs to default reactions if there is no matching normal reaction.
404
+ ```ruby
405
+ default do
406
+ reply("I don't understand you!")
407
+ end
408
+ ```
409
+ ```ruby
410
+ default from: 'Mike Johnson' do
411
+ reply("Not you again, Mike!")
412
+ end
413
+ ```
131
414
 
415
+ ### Descriptions
416
+ Use `desc` modifier to describe following reaction:
417
+ ```ruby
418
+ desc '@hipbot restart server_name - Restarts the server'
419
+ on /^restart (.*)$/ do |server|
420
+ if server.empty?
421
+ reply("Usage: #{reaction.desc}")
422
+ else
423
+ # Restarting...
424
+ end
425
+ end
426
+ ```
427
+ You can fetch the descriptions and create help reaction, eg:
132
428
  ```ruby
133
- on /curl (\S+)/ do |url|
134
- get url do |response|
429
+ on /^help$/ do
430
+ reply Hipbot.reactions.map(&:desc).compact.join("\n")
431
+ end
432
+ ```
433
+
434
+ ### User managment
435
+ This behavior is experimental and not officially supported by HipChat. Bot must be an admin in order to perform this actions.
436
+ ```ruby
437
+ on /^kick (.*)/ do |user_name|
438
+ user = Hipbot::User.find_by(name: user_name)
439
+ room.kick(user)
440
+ end
441
+ ```
442
+ ```ruby
443
+ on /^invite (.*)$/ do |user_name|
444
+ user = Hipbot::User.find_by(name: user_name)
445
+ room.invite(user)
446
+ end
447
+ ```
448
+
449
+ ### HTTP helpers
450
+ Use `get`, `post`, `put` and `delete` helpers to preform a HTTP requests:
451
+ ```ruby
452
+ on /^curl (\S+)$/ do |url|
453
+ get(url) do |response|
135
454
  reply(response.code)
136
455
  reply(response.headers)
137
456
  reply(response.body)
138
457
  end
139
458
  end
140
459
  ```
141
-
142
460
  ```ruby
143
- on /ping site/ do
144
- get 'http://example.com', ping: "1" # issues http://example.com?ping=1
461
+ on /^ping site/ do
462
+ get('http://example.com', ping: '1') # GET http://example.com?ping=1
145
463
  end
146
464
  ```
147
465
 
148
- Inside response you have access to following variables:
149
-
150
- * `message.body` - sent message
151
- * `message.sender` - user who sent message
152
- * `message.mentions` - array of @mentions inside message, without bot
153
- * `room.name` - name of the current room
154
-
466
+ ### Custom response helpers
155
467
  You can define your own helpers and use them inside responses like this:
156
-
157
468
  ```ruby
158
- module HipbotHelpers
469
+ module MyHipbotHelpers
159
470
  def project_name
160
471
  "#{room.name}-project"
161
472
  end
@@ -164,42 +475,40 @@ end
164
475
  class Bot < Hipbot::Bot
165
476
  configure do |c|
166
477
  # ...
167
- c.helpers = HipbotHelpers
478
+ c.helpers = MyHipbotHelpers
168
479
  end
169
480
 
170
- on /what's the project called\?/ do
481
+ on /^what's the project name\?$/ do
171
482
  reply(project_name)
172
483
  end
173
484
  end
174
485
  ```
175
486
 
176
- #### Plugins
177
-
178
- To define a plugin, include `Hipbot::Plugin` and add responses like in bot:
179
-
487
+ ### Plugins
488
+ To define a plugin, include `Hipbot::Plugin` module in your class:
180
489
  ```ruby
181
490
  class GreeterPlugin
182
491
  include Hipbot::Plugin
183
- on /^hello/ do
184
- reply('hello there!')
492
+
493
+ on /^hello$/ do
494
+ reply('Hello there!')
185
495
  end
186
496
  end
187
497
  ```
188
498
 
189
- You can gain access to plugin data inside reaction with `plugin` helper:
190
-
499
+ You can access plugin data inside reaction with `plugin` helper:
191
500
  ```ruby
192
501
  class GreeterPlugin
193
502
  include Hipbot::Plugin
194
503
 
195
504
  attr_accessor :language
196
505
 
197
- on /^hello/ do
506
+ on /^hello$/ do
198
507
  case plugin.language
199
508
  when :en
200
- reply("hello!")
509
+ reply("Hello!")
201
510
  when :pl
202
- reply("cześć!")
511
+ reply("Cześć!")
203
512
  when :jp
204
513
  reply("おはよう!")
205
514
  end
@@ -210,27 +519,112 @@ GreeterPlugin.configure do |c|
210
519
  c.language = :jp
211
520
  end
212
521
  ```
522
+ For more examples, check out [hipbot-plugins](https://github.com/netguru/hipbot-plugins).
213
523
 
214
- For a collection of open-source plugins, see https://github.com/netguru/hipbot-plugins
524
+ ### Exception handling
525
+ Define `on_exception` block in your Hipbot class to handle runtime exceptions:
526
+ ```ruby
527
+ class MyBot < Hipbot::Bot
528
+ on_exception do |e|
529
+ hipbot_room = Hipbot::Room.find_by(name: 'hipbot room')
530
+ reply(e.message, hipbot_room)
531
+ # If exception was raised in reaction, there are some context variables available:
532
+ reply("#{e.message} raised by #{message.body} from #{sender} in #{room}", hipbot_room)
533
+ end
534
+ end
535
+ ```
215
536
 
216
- ### Run
537
+ ### Preloader for EventMachine
538
+ In order to use EventMachine runtime methods, define them within `on_preload` block in your Hipbot class:
539
+ ```ruby
540
+ class MyBot < Hipbot::Bot
541
+ on_preload do
542
+ EM::add_periodic_timer(60) do
543
+ Updater::update_stock_prices
544
+ Updater::update_server_statuses
545
+ end
546
+ end
547
+ end
548
+ ```
217
549
 
218
- Run hipbot as daemon by saying:
550
+ ### Storage
551
+ Hipbot uses in-memory hash storage by default, however you can use persistent
552
+ storage adapter to speed up boot time and extend the functionality.
219
553
 
554
+ #### MongoDB
555
+ In order to use MongoDB storage, enable Mongoid adapter and add `allow_dynamic_fields: true` to your Mongoid config:
556
+ ```ruby
557
+ require 'hipbot/storages/mongoid'
558
+ configure do |c|
559
+ # ...
560
+ c.storage = Hipbot::Storages::Mongoid
561
+ end
220
562
  ```
221
- hipbot start
563
+ Sample config file:
564
+ ```yaml
565
+ sessions:
566
+ default:
567
+ hosts:
568
+ - localhost:27017
569
+ database: hipbot
570
+ options:
571
+ allow_dynamic_fields: true
222
572
  ```
573
+ You can optionally override user and room classes with these base models:
574
+ ```ruby
575
+ module Hipbot
576
+ class User
577
+ include Mongoid::Document
578
+
579
+ has_and_belongs_to_many :rooms, class_name: 'Hipbot::User', inverse_of: :users
580
+
581
+ field :email, type: String
582
+ field :mention, type: String
583
+ field :phone, type: String
584
+ field :photo, type: String
585
+ field :title, type: String
586
+ field :is_online, type: Boolean
587
+ end
588
+ end
589
+ ```
590
+ ```ruby
591
+ module Hipbot
592
+ class Room
593
+ include Mongoid::Document
223
594
 
224
- Run `hipbot` to see all available commands.
595
+ has_and_belongs_to_many :users, class_name: 'Hipbot::User', inverse_of: :rooms
225
596
 
226
- ## Deploying to Heroku
597
+ field :archived, type: Boolean
598
+ field :guest_url, type: String
599
+ field :hipchat_id, type: String
600
+ field :privacy, type: String
601
+ field :topic, type: String
602
+ end
603
+ end
604
+ ```
605
+ #### Other storage
606
+ Storage adapter is included in room and user classes upon loading.
607
+ Make sure your adapter implements all methods from [Hipbot::Storages::Base](https://github.com/pewniak747/hipbot/blob/master/lib/hipbot/storages/base.rb)
608
+ ```ruby
609
+ module MyStorageAdapter
610
+ include Hipbot::Storages::Base
611
+ # ...
612
+ end
227
613
 
228
- Follow the instructions on https://github.com/netguru/hipbot-example .
614
+ configure do |c|
615
+ # ...
616
+ c.storage = MyStorageAdapter
617
+ end
618
+ ```
229
619
 
230
- ## TODO:
620
+ ## Contributing
621
+ ### To do:
231
622
 
232
- ### Done:
623
+ * add tests for Match class
624
+ * add testing adapter for testing custom responses with RSpec
625
+ * add HipChat API integration (?)
233
626
 
627
+ ### Done:
234
628
  * ~~add extended logging~~
235
629
  * ~~add plugins support~~
236
630
  * ~~rewrite SimpleMUCClient~~