hipbot 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +19 -12
- data/README.md +7 -4
- data/examples/cleverbot.rb +23 -0
- data/examples/google_images.rb +35 -0
- data/lib/hipbot.rb +5 -2
- data/lib/hipbot/adapters/hipchat/connection.rb +116 -83
- data/lib/hipbot/adapters/hipchat/hipchat.rb +4 -2
- data/lib/hipbot/adapters/telnet/connection.rb +1 -1
- data/lib/hipbot/adapters/telnet/telnet.rb +1 -1
- data/lib/hipbot/bot.rb +11 -20
- data/lib/hipbot/collection.rb +48 -0
- data/lib/hipbot/configuration.rb +4 -2
- data/lib/hipbot/message.rb +6 -9
- data/lib/hipbot/patches/hipchat_client.rb +192 -0
- data/lib/hipbot/reaction.rb +24 -17
- data/lib/hipbot/response.rb +3 -3
- data/lib/hipbot/room.rb +18 -3
- data/lib/hipbot/user.rb +11 -0
- data/lib/hipbot/version.rb +1 -1
- data/spec/integration/hipbot_spec.rb +13 -13
- data/spec/unit/hipbot_spec.rb +61 -57
- metadata +7 -3
- data/lib/hipbot/patches/mucclient.rb +0 -147
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,25 +1,32 @@
|
|
1
1
|
GEM
|
2
|
-
remote:
|
2
|
+
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
4
|
active_support (3.0.0)
|
5
5
|
activesupport (= 3.0.0)
|
6
6
|
activesupport (3.0.0)
|
7
|
-
addressable (2.2
|
8
|
-
|
7
|
+
addressable (2.3.2)
|
8
|
+
cookiejar (0.3.0)
|
9
9
|
daemons (1.1.8)
|
10
10
|
diff-lcs (1.1.3)
|
11
|
-
em-http-request (0.
|
12
|
-
addressable (>= 2.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
em-http-request (1.0.2)
|
12
|
+
addressable (>= 2.2.3)
|
13
|
+
cookiejar
|
14
|
+
em-socksify
|
15
|
+
eventmachine (>= 1.0.0.beta.4)
|
16
|
+
http_parser.rb (>= 0.5.3)
|
17
|
+
em-socksify (0.2.0)
|
18
|
+
eventmachine (>= 1.0.0.beta.4)
|
19
|
+
eventmachine (1.0.0.rc.4)
|
20
|
+
http_parser.rb (0.5.3)
|
21
|
+
httparty (0.8.3)
|
22
|
+
multi_json (~> 1.0)
|
23
|
+
multi_xml
|
19
24
|
i18n (0.6.0)
|
20
25
|
metaclass (0.0.1)
|
21
|
-
mocha (0.
|
26
|
+
mocha (0.12.1)
|
22
27
|
metaclass (~> 0.0.1)
|
28
|
+
multi_json (1.3.6)
|
29
|
+
multi_xml (0.5.1)
|
23
30
|
rake (0.9.2.2)
|
24
31
|
rspec (2.11.0)
|
25
32
|
rspec-core (~> 2.11.0)
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Hipbot
|
2
2
|
|
3
3
|
[![Build Status](https://secure.travis-ci.org/pewniak747/hipbot.png?branch=master)](http://travis-ci.org/pewniak747/hipbot)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/pewniak747/hipbot.png)](https://codeclimate.com/github/pewniak747/hipbot)
|
4
5
|
|
5
6
|
Hipbot is a bot for HipChat, written in ruby & eventmachine.
|
6
7
|
|
@@ -84,6 +85,8 @@ end
|
|
84
85
|
|
85
86
|
(Use with caution!)
|
86
87
|
|
88
|
+
For more examples, check out (https://github.com/pewniak747/hipbot/tree/master/examples)
|
89
|
+
|
87
90
|
#### Response helpers
|
88
91
|
|
89
92
|
Use http helpers (`get`, `post`, `put`, `delete`) to preform a http request:
|
@@ -159,14 +162,14 @@ heroku ps:scale worker=1
|
|
159
162
|
|
160
163
|
## TODO:
|
161
164
|
|
162
|
-
*
|
163
|
-
* add database storage with postgresql adapter
|
164
|
-
* rewrite SimpleMUCClient
|
165
|
+
* add plugins support
|
165
166
|
* add extended logging
|
166
|
-
* handle private messages callbacks in the same way
|
167
167
|
|
168
168
|
### Done:
|
169
169
|
|
170
|
+
* ~~rewrite SimpleMUCClient~~
|
171
|
+
* ~~handle private messages callbacks~~
|
172
|
+
* ~~handle auto joining on room invite~~
|
170
173
|
* ~~add support for custom helpers~~
|
171
174
|
* ~~mentions - returns list of @mentions in message~~
|
172
175
|
* ~~sender_name - returns sender's first name~~
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# example bot that simulates intelligence
|
2
|
+
# using http://cleverbot.com/ api
|
3
|
+
|
4
|
+
require 'hipbot'
|
5
|
+
require 'cleverbot'
|
6
|
+
require 'htmlentities'
|
7
|
+
|
8
|
+
class CleverHipbot < Hipbot::Bot
|
9
|
+
configure do |c|
|
10
|
+
c.jid = ENV['HIPBOT_JID']
|
11
|
+
c.password = ENV['HIPBOT_PASSWORD']
|
12
|
+
c.name = ENV['HIPBOT_NAME']
|
13
|
+
end
|
14
|
+
|
15
|
+
cleverbot = ::Cleverbot::Client.new
|
16
|
+
|
17
|
+
on /(.+)/ do |message|
|
18
|
+
coder = HTMLEntities.new
|
19
|
+
reply(coder.decode(cleverbot.write(message)))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
CleverHipbot.start!
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Pull out a random image from the Google Images API and display it
|
2
|
+
# Uses: google_image_api http://rubygems.org/gems/google_image_api
|
3
|
+
# Author Rushi Vishavadia <rushi.v@gmail.com>
|
4
|
+
|
5
|
+
require 'hipbot'
|
6
|
+
require 'google_image_api'
|
7
|
+
|
8
|
+
class SampleBot < Hipbot::Bot
|
9
|
+
configure do |c|
|
10
|
+
c.jid = ENV['HIPBOT_JID']
|
11
|
+
c.password = ENV['HIPBOT_PASSWORD']
|
12
|
+
c.name = ENV['HIPBOT_NAME']
|
13
|
+
end
|
14
|
+
|
15
|
+
on /\Aimage (.+)/i do |img_str|
|
16
|
+
max = 8 # max number of results you want to pull a random
|
17
|
+
puts img_str
|
18
|
+
begin
|
19
|
+
results = GoogleImageApi.find(img_str, :rsz => max)
|
20
|
+
if results.raw_data["responseStatus"] == 200 and results.images.size > 0
|
21
|
+
reply(results.images.take(max).sample['unescapedUrl'])
|
22
|
+
elsif results.raw_data["responseStatus"] == 200 and results.images.size == 0
|
23
|
+
reply("I'm sorry I couldn't find an image for #{img_str}")
|
24
|
+
else
|
25
|
+
reply("I'm sorry, an error occurred. Try again please") # Most likely a 403
|
26
|
+
end
|
27
|
+
rescue => e
|
28
|
+
reply("I'm sorry, an error occurred trying to find that image")
|
29
|
+
p e.message
|
30
|
+
p e.backtrace
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
SampleBot.start!
|
data/lib/hipbot.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'active_support/all'
|
2
|
+
require 'ostruct'
|
2
3
|
require 'eventmachine'
|
3
4
|
require 'em-http-request'
|
4
5
|
require 'xmpp4r'
|
5
6
|
require 'xmpp4r/muc'
|
6
7
|
|
7
|
-
require 'hipbot/patches/
|
8
|
+
require 'hipbot/patches/hipchat_client'
|
8
9
|
require 'hipbot/patches/encoding'
|
9
10
|
|
10
11
|
require 'hipbot/adapters/hipchat/hipchat'
|
@@ -13,9 +14,11 @@ require 'hipbot/adapters/telnet/telnet'
|
|
13
14
|
require 'hipbot/adapters/telnet/connection'
|
14
15
|
require 'hipbot/bot'
|
15
16
|
require 'hipbot/configuration'
|
17
|
+
require 'hipbot/collection'
|
18
|
+
require 'hipbot/http_response'
|
16
19
|
require 'hipbot/message'
|
17
20
|
require 'hipbot/reaction'
|
18
21
|
require 'hipbot/response'
|
19
|
-
require 'hipbot/http_response'
|
20
22
|
require 'hipbot/room'
|
23
|
+
require 'hipbot/user'
|
21
24
|
require 'hipbot/version'
|
@@ -3,120 +3,153 @@ module Hipbot
|
|
3
3
|
module Hipchat
|
4
4
|
class Connection
|
5
5
|
def initialize bot
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
@bot = bot
|
7
|
+
@bot.connection = self
|
8
|
+
|
9
|
+
return unless setup_bot
|
10
10
|
setup_timers
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
13
|
+
def restart!
|
14
|
+
exit_all_rooms # TODO: Nice quit
|
15
|
+
setup_bot
|
15
16
|
end
|
16
17
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
18
|
+
def send_to_room(room, message)
|
19
|
+
@client.send_message(:groupchat, room.id, message)
|
20
|
+
end
|
21
|
+
|
22
|
+
def send_to_user(user, message)
|
23
|
+
@client.send_message(:chat, user.id, message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_topic(room, topic)
|
27
|
+
@client.send_message(:groupchat, room.id, nil, topic)
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_presence(status = nil, type = :available)
|
31
|
+
@client.set_presence(type, nil, status)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def setup_bot
|
37
|
+
return unless initialize_client
|
20
38
|
initialize_rooms
|
39
|
+
initialize_users
|
40
|
+
initialize_callbacks
|
21
41
|
join_rooms
|
42
|
+
set_presence('Hello humans!')
|
43
|
+
true
|
22
44
|
end
|
23
45
|
|
24
|
-
|
46
|
+
def initialize_client
|
47
|
+
::Jabber.debug = true
|
48
|
+
@client = ::Jabber::MUC::HipchatClient.new(@bot.jid + '/' + @bot.name)
|
49
|
+
@client.connect(@bot.password)
|
50
|
+
end
|
25
51
|
|
26
52
|
def initialize_rooms
|
27
|
-
|
28
|
-
@
|
29
|
-
|
30
|
-
|
53
|
+
Room.bot = @bot
|
54
|
+
@client.get_rooms.each do |r|
|
55
|
+
Room.create(r[:item].jid, r[:item].iname, topic: r[:details]['topic'])
|
56
|
+
end
|
57
|
+
true
|
31
58
|
end
|
32
59
|
|
33
|
-
def
|
34
|
-
|
35
|
-
@
|
60
|
+
def initialize_users
|
61
|
+
User.bot = @bot
|
62
|
+
@client.get_users.each do |v|
|
63
|
+
params = {
|
64
|
+
email: v[:vcard]['EMAIL/USERID'],
|
65
|
+
mention: v[:item].attributes['mention_name'],
|
66
|
+
title: v[:vcard]['TITLE'],
|
67
|
+
photo: v[:vcard]['PHOTO'],
|
68
|
+
}
|
69
|
+
User.create(v[:item].jid, v[:item].iname, params)
|
70
|
+
end
|
71
|
+
true
|
36
72
|
end
|
37
73
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
74
|
+
def join_rooms
|
75
|
+
if Room.empty?
|
76
|
+
Jabber::debuglog "No rooms to join"
|
77
|
+
return false
|
78
|
+
end
|
79
|
+
Room.each do |room_jid, _|
|
80
|
+
@client.join(room_jid)
|
81
|
+
end
|
82
|
+
true
|
43
83
|
end
|
44
84
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
room.
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
85
|
+
def exit_all_rooms
|
86
|
+
Room.each do |room_jid, _|
|
87
|
+
@client.exit(room_jid, 'bye bye!')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize_callbacks
|
92
|
+
@client.on_message do |room_jid, user_name, message|
|
93
|
+
room = Room[room_jid]
|
94
|
+
user = User[user_name]
|
95
|
+
next if room.nil? && user.nil?
|
96
|
+
room.params.topic = message.subject if message.subject.present?
|
97
|
+
next if user_name == @bot.name || message.body.blank?
|
98
|
+
Jabber::debuglog "[#{Time.now}] <#{room.name}> #{user_name}: #{message.body}"
|
99
|
+
begin
|
100
|
+
@bot.react(user, room, message.body)
|
101
|
+
rescue => e
|
102
|
+
Jabber::debuglog e.inspect
|
103
|
+
e.backtrace.each do |line|
|
104
|
+
Jabber::debuglog line
|
66
105
|
end
|
67
106
|
end
|
107
|
+
end
|
68
108
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
109
|
+
@client.on_private_message do |user_jid, message|
|
110
|
+
user = User[user_jid]
|
111
|
+
next if user.blank? || user.name == @bot.name
|
112
|
+
if message.body.nil?
|
113
|
+
# if message.active?
|
114
|
+
# elsif message.inactive?
|
115
|
+
# elsif message.composing?
|
116
|
+
# elsif message.gone?
|
117
|
+
# elsif message.paused?
|
118
|
+
# end
|
119
|
+
else
|
120
|
+
@bot.react(user, nil, message.body)
|
73
121
|
end
|
74
|
-
room.connection.on_leave do |time, nick|
|
75
|
-
room.users.delete(nick)
|
76
|
-
end
|
77
|
-
room.connection.join("#{room.jid}/#{@bot.name}", nil, :history => false)
|
78
122
|
end
|
79
123
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# send_message rooms.first, 'hello!', jid
|
85
|
-
|
86
|
-
## Alternative sending:
|
87
|
-
# msg = ::Jabber::Message.new(jid, 'hello!')
|
88
|
-
# msg.type = :chat
|
89
|
-
# @jabber.send(msg)
|
90
|
-
|
91
|
-
## We can trigger normal message callback but 'reply' won't work since hipchat PM uses
|
92
|
-
## different jid (user_room@chat.hipchat.com/client_name)
|
93
|
-
# rooms.first.connection.message_block.call(time, sender, message)
|
94
|
-
# end
|
95
|
-
end
|
124
|
+
@client.on_invite do |room_jid, user_name, room_name, topic|
|
125
|
+
Room.create(room_jid, room_name, topic: topic)
|
126
|
+
@client.join(room_jid)
|
127
|
+
end
|
96
128
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
129
|
+
@client.on_presence do |room_jid, user_name, pres|
|
130
|
+
room = Room[room_jid]
|
131
|
+
next if room.blank? || user_name.blank?
|
132
|
+
user = User[user_name]
|
133
|
+
if pres == 'unavailable'
|
134
|
+
if user_name == @bot.name
|
135
|
+
room.delete
|
136
|
+
elsif user.present?
|
137
|
+
room.user_ids.delete(user.id)
|
138
|
+
end
|
139
|
+
elsif pres.blank? && user.present? && room.user_ids.exclude?(user.id)
|
140
|
+
room.user_ids << user.id
|
141
|
+
end
|
101
142
|
end
|
143
|
+
|
144
|
+
@client.activate_callbacks
|
102
145
|
end
|
103
146
|
|
104
147
|
def setup_timers
|
105
|
-
::EM::add_periodic_timer(
|
106
|
-
|
107
|
-
initialize_jabber
|
108
|
-
join_rooms
|
109
|
-
end
|
148
|
+
::EM::add_periodic_timer(60) {
|
149
|
+
@client.keep_alive(@bot.password) if @client.present?
|
110
150
|
}
|
111
151
|
end
|
112
152
|
|
113
|
-
def send_message room, message, jid = nil
|
114
|
-
room.connection.say(message, jid)
|
115
|
-
end
|
116
|
-
|
117
|
-
def rooms
|
118
|
-
@rooms || []
|
119
|
-
end
|
120
153
|
end
|
121
154
|
end
|
122
155
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Hipbot
|
2
2
|
module Adapters
|
3
3
|
module Hipchat
|
4
|
-
delegate :reply, to: :connection
|
5
|
-
|
6
4
|
def start!
|
7
5
|
::EM::run do
|
8
6
|
::EM.error_handler do |e|
|
@@ -15,6 +13,10 @@ module Hipbot
|
|
15
13
|
Connection.new(self)
|
16
14
|
end
|
17
15
|
end
|
16
|
+
|
17
|
+
def method_missing(sym, *args, &block)
|
18
|
+
connection.send sym, *args, &block
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|