hipbot 1.0.0.rc2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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~~