hipbot 0.0.5 → 0.1.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.
- 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
|
[](http://travis-ci.org/pewniak747/hipbot)
|
4
|
+
[](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
|