hipbot 0.2.0 → 1.0.0.rc1
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.
- data/.gitignore +2 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +15 -0
- data/README.md +28 -20
- data/hipbot.gemspec +2 -2
- data/lib/hipbot.rb +1 -0
- data/lib/hipbot/adapters/hipchat/connection.rb +46 -41
- data/lib/hipbot/adapters/hipchat/hipchat.rb +1 -1
- data/lib/hipbot/adapters/telnet/connection.rb +4 -5
- data/lib/hipbot/bot.rb +61 -48
- data/lib/hipbot/collection.rb +34 -9
- data/lib/hipbot/configuration.rb +15 -7
- data/lib/hipbot/helpers.rb +10 -4
- data/lib/hipbot/logger.rb +0 -4
- data/lib/hipbot/match.rb +48 -0
- data/lib/hipbot/message.rb +13 -13
- data/lib/hipbot/patches/hipchat_client.rb +50 -12
- data/lib/hipbot/plugin.rb +24 -5
- data/lib/hipbot/reactable.rb +27 -42
- data/lib/hipbot/reaction.rb +33 -34
- data/lib/hipbot/response.rb +14 -11
- data/lib/hipbot/room.rb +4 -11
- data/lib/hipbot/user.rb +8 -2
- data/lib/hipbot/version.rb +1 -1
- data/spec/integration/hipbot_spec.rb +96 -68
- data/spec/integration/my_hipbot.rb +104 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/unit/hipbot_spec.rb +45 -34
- data/spec/unit/message_spec.rb +17 -18
- metadata +10 -5
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -6,7 +6,14 @@ GEM
|
|
6
6
|
multi_json (~> 1.0)
|
7
7
|
addressable (2.3.3)
|
8
8
|
coderay (1.0.9)
|
9
|
+
colorize (0.5.8)
|
9
10
|
cookiejar (0.3.0)
|
11
|
+
coveralls (0.6.7)
|
12
|
+
colorize
|
13
|
+
multi_json (~> 1.3)
|
14
|
+
rest-client
|
15
|
+
simplecov (>= 0.7)
|
16
|
+
thor
|
10
17
|
daemons (1.1.9)
|
11
18
|
diff-lcs (1.2.2)
|
12
19
|
em-http-request (1.0.3)
|
@@ -37,6 +44,7 @@ GEM
|
|
37
44
|
lumberjack (1.0.3)
|
38
45
|
metaclass (0.0.1)
|
39
46
|
method_source (0.8.1)
|
47
|
+
mime-types (1.23)
|
40
48
|
mocha (0.13.3)
|
41
49
|
metaclass (~> 0.0.1)
|
42
50
|
multi_json (1.7.2)
|
@@ -46,6 +54,8 @@ GEM
|
|
46
54
|
method_source (~> 0.8)
|
47
55
|
slop (~> 3.4)
|
48
56
|
rake (10.0.4)
|
57
|
+
rest-client (1.6.7)
|
58
|
+
mime-types (>= 1.16)
|
49
59
|
rspec (2.13.0)
|
50
60
|
rspec-core (~> 2.13.0)
|
51
61
|
rspec-expectations (~> 2.13.0)
|
@@ -54,6 +64,10 @@ GEM
|
|
54
64
|
rspec-expectations (2.13.0)
|
55
65
|
diff-lcs (>= 1.1.3, < 2.0)
|
56
66
|
rspec-mocks (2.13.0)
|
67
|
+
simplecov (0.7.1)
|
68
|
+
multi_json (~> 1.0)
|
69
|
+
simplecov-html (~> 0.7.1)
|
70
|
+
simplecov-html (0.7.1)
|
57
71
|
slop (3.4.4)
|
58
72
|
thor (0.18.1)
|
59
73
|
xmpp4r (0.5)
|
@@ -63,6 +77,7 @@ PLATFORMS
|
|
63
77
|
|
64
78
|
DEPENDENCIES
|
65
79
|
activesupport
|
80
|
+
coveralls
|
66
81
|
daemons
|
67
82
|
em-http-request
|
68
83
|
eventmachine
|
data/README.md
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
[](http://travis-ci.org/pewniak747/hipbot)
|
4
4
|
[](https://codeclimate.com/github/pewniak747/hipbot)
|
5
|
+
[](https://coveralls.io/r/pewniak747/hipbot)
|
6
|
+
[](https://gemnasium.com/pewniak747/hipbot)
|
7
|
+
[](http://badge.fury.io/rb/hipbot)
|
5
8
|
|
6
9
|
Hipbot is a XMPP bot for HipChat, written in ruby & eventmachine.
|
7
10
|
|
@@ -17,7 +20,7 @@ gem install hipbot
|
|
17
20
|
|
18
21
|
Create `bot.rb` file, subclass `Hipbot::Bot` and customize the responses.
|
19
22
|
|
20
|
-
```
|
23
|
+
```ruby
|
21
24
|
require 'hipbot'
|
22
25
|
|
23
26
|
class MyCompanyBot < Hipbot::Bot
|
@@ -27,7 +30,6 @@ class MyCompanyBot < Hipbot::Bot
|
|
27
30
|
c.password = 'secret' # required
|
28
31
|
c.teams = { vip: ['John', 'Mike'] }
|
29
32
|
c.rooms = { project_rooms: ['Project 1', 'Project 2'] }
|
30
|
-
c.plugins = [ PluginClass ]
|
31
33
|
end
|
32
34
|
|
33
35
|
on /^hello/ do
|
@@ -49,7 +51,9 @@ class MyCompanyBot < Hipbot::Bot
|
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
|
-
class PluginClass
|
54
|
+
class PluginClass
|
55
|
+
include Hipbot::Plugin
|
56
|
+
|
53
57
|
on /^plugin/ do
|
54
58
|
reply('this is from plugin!')
|
55
59
|
end
|
@@ -60,7 +64,7 @@ MyCompanyBot.start!
|
|
60
64
|
|
61
65
|
You can create a response by providing simple regexp:
|
62
66
|
|
63
|
-
```
|
67
|
+
```ruby
|
64
68
|
on /^hello/ do
|
65
69
|
reply('hello!')
|
66
70
|
end
|
@@ -68,7 +72,7 @@ end
|
|
68
72
|
|
69
73
|
Responses can pass arguments from regexps:
|
70
74
|
|
71
|
-
```
|
75
|
+
```ruby
|
72
76
|
on /my name is (.*)/ do |user_name|
|
73
77
|
reply('hello #{user_name}!')
|
74
78
|
end
|
@@ -76,7 +80,7 @@ end
|
|
76
80
|
|
77
81
|
Define multiple regexps for a response:
|
78
82
|
|
79
|
-
```
|
83
|
+
```ruby
|
80
84
|
on /my name is (.*)/, /I am (.*)/ do |name|
|
81
85
|
reply('hello #{user_name}!')
|
82
86
|
end
|
@@ -84,7 +88,7 @@ end
|
|
84
88
|
|
85
89
|
Use :from to only match messages from certain users or user groups defined in configuration
|
86
90
|
|
87
|
-
```
|
91
|
+
```ruby
|
88
92
|
configure do |c|
|
89
93
|
# ...
|
90
94
|
c.teams = { vip: ['John', 'Mike'] }
|
@@ -97,7 +101,7 @@ end
|
|
97
101
|
|
98
102
|
Use :room to only match messages in certain hipchat rooms
|
99
103
|
|
100
|
-
```
|
104
|
+
```ruby
|
101
105
|
configure do |c|
|
102
106
|
# ...
|
103
107
|
c.rooms = { project_rooms: ['Project 1', 'Project 2'] }
|
@@ -110,7 +114,7 @@ end
|
|
110
114
|
|
111
115
|
Use :global to react to messages that are not sent directly to @robot
|
112
116
|
|
113
|
-
```
|
117
|
+
```ruby
|
114
118
|
on /hey I just met you/, global: true do
|
115
119
|
reply('and this is crazy...')
|
116
120
|
end
|
@@ -124,7 +128,7 @@ For more examples, check out (https://github.com/pewniak747/hipbot/tree/master/e
|
|
124
128
|
|
125
129
|
Use http helpers (`get`, `post`, `put`, `delete`) to preform a http request:
|
126
130
|
|
127
|
-
```
|
131
|
+
```ruby
|
128
132
|
on /curl (\S+)/ do |url|
|
129
133
|
get url do |response|
|
130
134
|
reply(response.code)
|
@@ -134,7 +138,7 @@ on /curl (\S+)/ do |url|
|
|
134
138
|
end
|
135
139
|
```
|
136
140
|
|
137
|
-
```
|
141
|
+
```ruby
|
138
142
|
on /ping site/ do
|
139
143
|
get 'http://example.com', ping: "1" # issues http://example.com?ping=1
|
140
144
|
end
|
@@ -149,7 +153,7 @@ Inside response you have access to following variables:
|
|
149
153
|
|
150
154
|
You can define your own helpers and use them inside responses like this:
|
151
155
|
|
152
|
-
```
|
156
|
+
```ruby
|
153
157
|
module HipbotHelpers
|
154
158
|
def project_name
|
155
159
|
"#{room.name}-project"
|
@@ -170,10 +174,11 @@ end
|
|
170
174
|
|
171
175
|
#### Plugins
|
172
176
|
|
173
|
-
To define a plugin,
|
177
|
+
To define a plugin, include `Hipbot::Plugin` and add responses like in bot:
|
174
178
|
|
175
|
-
```
|
176
|
-
class GreeterPlugin
|
179
|
+
```ruby
|
180
|
+
class GreeterPlugin
|
181
|
+
include Hipbot::Plugin
|
177
182
|
on /^hello/ do
|
178
183
|
reply('hello there!')
|
179
184
|
end
|
@@ -182,12 +187,11 @@ end
|
|
182
187
|
|
183
188
|
You can gain access to plugin data inside reaction with `plugin` helper:
|
184
189
|
|
185
|
-
```
|
186
|
-
class GreeterPlugin
|
190
|
+
```ruby
|
191
|
+
class GreeterPlugin
|
192
|
+
include Hipbot::Plugin
|
193
|
+
|
187
194
|
attr_accessor :language
|
188
|
-
def initialize(language)
|
189
|
-
self.language = language
|
190
|
-
end
|
191
195
|
|
192
196
|
on /^hello/ do
|
193
197
|
case plugin.language
|
@@ -200,6 +204,10 @@ class GreeterPlugin < Hipbot::Plugin
|
|
200
204
|
end
|
201
205
|
end
|
202
206
|
end
|
207
|
+
|
208
|
+
GreeterPlugin.configure do |c|
|
209
|
+
c.language = :jp
|
210
|
+
end
|
203
211
|
```
|
204
212
|
|
205
213
|
For a collection of open-source plugins, see https://github.com/netguru/hipbot-plugins
|
data/hipbot.gemspec
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
require File.expand_path('../lib/hipbot/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ["Tomasz Pewiński"]
|
6
|
-
gem.email = ["pewniak747@gmail.com"]
|
5
|
+
gem.authors = ["Bartosz Kopiński", "Tomasz Pewiński"]
|
6
|
+
gem.email = ["bartosz.kopinski@netguru.pl", "pewniak747@gmail.com"]
|
7
7
|
gem.description = "Hipbot is a bot for HipChat, written in ruby & eventmachine."
|
8
8
|
gem.summary = "Hipbot is a bot for HipChat, written in ruby & eventmachine."
|
9
9
|
gem.homepage = "http://github.com/pewniak747/hipbot"
|
data/lib/hipbot.rb
CHANGED
@@ -2,10 +2,8 @@ module Hipbot
|
|
2
2
|
module Adapters
|
3
3
|
module Hipchat
|
4
4
|
class Connection
|
5
|
-
def initialize
|
6
|
-
|
7
|
-
@bot.connection = self
|
8
|
-
|
5
|
+
def initialize
|
6
|
+
Hipbot.connection = self
|
9
7
|
setup_error_handler && setup_bot && setup_timers
|
10
8
|
end
|
11
9
|
|
@@ -15,71 +13,78 @@ module Hipbot
|
|
15
13
|
end
|
16
14
|
|
17
15
|
def send_to_room(room, message)
|
16
|
+
Hipbot.logger.info("REPLY in #{room}: #{message}")
|
18
17
|
@client.send_message(:groupchat, room.id, message)
|
19
18
|
end
|
20
19
|
|
21
20
|
def send_to_user(user, message)
|
21
|
+
Hipbot.logger.info("REPLY to #{user}: #{message}")
|
22
22
|
@client.send_message(:chat, user.id, message)
|
23
23
|
end
|
24
24
|
|
25
25
|
def set_topic(room, topic)
|
26
|
+
Hipbot.logger.info("TOPIC set in #{room} to '#{topic}'")
|
26
27
|
@client.send_message(:groupchat, room.id, nil, topic)
|
27
28
|
end
|
28
29
|
|
29
30
|
def set_presence(status = nil, type = :available)
|
31
|
+
Hipbot.logger.info("PRESENCE set to #{type} with '#{status}'")
|
30
32
|
@client.set_presence(type, nil, status)
|
31
33
|
end
|
32
34
|
|
33
|
-
|
35
|
+
protected
|
34
36
|
|
35
37
|
def setup_bot
|
36
38
|
initialize_client do
|
37
39
|
initialize_rooms
|
38
40
|
initialize_users
|
39
41
|
initialize_callbacks
|
42
|
+
set_bot_user
|
40
43
|
join_rooms
|
41
44
|
set_presence('Hello humans!')
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
48
|
def initialize_client
|
46
|
-
@client = ::Jabber::MUC::HipchatClient.new(
|
47
|
-
yield if @client.connect(
|
49
|
+
@client = ::Jabber::MUC::HipchatClient.new(Hipbot.jid)
|
50
|
+
yield if @client.connect(Hipbot.password)
|
48
51
|
end
|
49
52
|
|
50
53
|
def initialize_rooms
|
51
|
-
@client.get_rooms.each do |
|
52
|
-
Room.
|
54
|
+
@client.get_rooms.each do |room_data|
|
55
|
+
room = Room.find_or_create_by(id: room_data[:item].jid.to_s)
|
56
|
+
room.update_attributes({
|
57
|
+
name: room_data[:item].iname,
|
58
|
+
topic: room_data[:details]['topic'],
|
59
|
+
})
|
53
60
|
end
|
54
|
-
true
|
55
61
|
end
|
56
62
|
|
57
63
|
def initialize_users
|
58
|
-
@client.get_users.each do |
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
User.create(v[:item].jid, v[:item].iname, params)
|
64
|
+
@client.get_users.each do |user_data|
|
65
|
+
user = User.find_or_create_by(id: user_data.delete(:jid))
|
66
|
+
user.update_attributes(user_data)
|
67
|
+
|
68
|
+
if user.attributes['email'].nil?
|
69
|
+
user.update_attributes(@client.get_user_details(user.id))
|
70
|
+
end
|
66
71
|
end
|
67
|
-
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_bot_user
|
75
|
+
Hipbot.configuration.user = User[Hipbot.jid]
|
76
|
+
@client.name = Hipbot.user
|
68
77
|
end
|
69
78
|
|
70
79
|
def join_rooms
|
71
|
-
with_rooms do |
|
72
|
-
|
73
|
-
@client.join(r.id)
|
74
|
-
end
|
80
|
+
with_rooms do |room|
|
81
|
+
@client.join(room.id)
|
75
82
|
end
|
76
83
|
end
|
77
84
|
|
78
85
|
def exit_all_rooms
|
79
|
-
with_rooms do |
|
80
|
-
|
81
|
-
@client.exit(r.id, 'bye bye!')
|
82
|
-
end
|
86
|
+
with_rooms do |room|
|
87
|
+
@client.exit(room.id, 'bye bye!')
|
83
88
|
end
|
84
89
|
end
|
85
90
|
|
@@ -93,40 +98,40 @@ module Hipbot
|
|
93
98
|
|
94
99
|
def message_callback room_jid, user_name, message
|
95
100
|
with_sender(room_jid, user_name) do |room, user|
|
96
|
-
room.
|
97
|
-
return if user_name ==
|
98
|
-
|
101
|
+
room.update_attribute(:topic, message.subject) if message.subject.present?
|
102
|
+
return if user_name == Hipbot.name || message.body.blank?
|
103
|
+
Hipbot.react(user, room, message.body)
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
102
107
|
def invite_callback room_jid, user_name, room_name, topic
|
103
|
-
Room.create(room_jid, room_name, topic: topic)
|
108
|
+
Room.create(id: room_jid, name: room_name, topic: topic)
|
104
109
|
@client.join(room_jid)
|
105
110
|
end
|
106
111
|
|
107
112
|
def presence_callback room_jid, user_name, pres
|
108
113
|
with_sender(room_jid, user_name) do |room, user|
|
109
114
|
if pres == 'unavailable'
|
110
|
-
if user_name ==
|
115
|
+
if user_name == Hipbot.name
|
111
116
|
room.delete
|
112
117
|
elsif user.present?
|
113
|
-
room.
|
118
|
+
room.users.delete(user)
|
114
119
|
end
|
115
|
-
elsif pres.blank? && room.
|
116
|
-
room.
|
120
|
+
elsif pres.blank? && room.users.exclude?(user)
|
121
|
+
room.users << user
|
117
122
|
end
|
118
123
|
end
|
119
124
|
end
|
120
125
|
|
121
126
|
def private_message_callback user_jid, message
|
122
127
|
with_user(user_jid) do |user|
|
123
|
-
|
128
|
+
Hipbot.react(user, nil, message.body) if user.name != Hipbot.name
|
124
129
|
end if message.body.present?
|
125
130
|
end
|
126
131
|
|
127
132
|
def with_rooms
|
128
|
-
return
|
129
|
-
yield
|
133
|
+
return Hipbot.logger.error 'No rooms found' if Room.empty?
|
134
|
+
Room.each{ |room| yield room }
|
130
135
|
end
|
131
136
|
|
132
137
|
def with_sender room_id, user_id
|
@@ -143,15 +148,15 @@ module Hipbot
|
|
143
148
|
|
144
149
|
def setup_timers
|
145
150
|
::EM::add_periodic_timer(60) do
|
146
|
-
@client.keep_alive(
|
151
|
+
@client.keep_alive(Hipbot.password) if @client.present?
|
147
152
|
end
|
148
153
|
end
|
149
154
|
|
150
155
|
def setup_error_handler
|
151
156
|
::EM.error_handler do |e|
|
152
|
-
|
157
|
+
Hipbot.logger.error e.inspect
|
153
158
|
e.backtrace.each do |line|
|
154
|
-
|
159
|
+
Hipbot.logger.error line
|
155
160
|
end
|
156
161
|
end
|
157
162
|
end
|
@@ -2,14 +2,13 @@ module Hipbot
|
|
2
2
|
module Adapters
|
3
3
|
module Telnet
|
4
4
|
class Connection < EM::Connection
|
5
|
-
def initialize
|
6
|
-
|
7
|
-
@bot.connection = self
|
5
|
+
def initialize
|
6
|
+
Hipbot.connection = self
|
8
7
|
end
|
9
8
|
|
10
9
|
def receive_data(data)
|
11
|
-
sender, room, message =
|
12
|
-
|
10
|
+
sender, room, message = data.strip.split(':')
|
11
|
+
Hipbot.react(sender, room, message)
|
13
12
|
end
|
14
13
|
end
|
15
14
|
end
|