hipbot 0.0.3 → 0.0.5
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/.travis.yml +6 -0
- data/Gemfile +0 -3
- data/Gemfile.lock +7 -10
- data/README.md +129 -21
- data/bin/hipbot +8 -1
- data/hipbot.gemspec +2 -1
- data/lib/hipbot.rb +8 -7
- data/lib/hipbot/adapters/hipchat/connection.rb +123 -0
- data/lib/hipbot/adapters/hipchat/hipchat.rb +20 -0
- data/lib/hipbot/adapters/{telnet.rb → telnet/connection.rb} +0 -10
- data/lib/hipbot/adapters/telnet/telnet.rb +16 -0
- data/lib/hipbot/bot.rb +10 -9
- data/lib/hipbot/configuration.rb +3 -0
- data/lib/hipbot/http_response.rb +15 -0
- data/lib/hipbot/message.rb +9 -1
- data/lib/hipbot/{encoding.rb → patches/encoding.rb} +0 -0
- data/lib/hipbot/patches/mucclient.rb +147 -0
- data/lib/hipbot/reaction.rb +14 -6
- data/lib/hipbot/response.rb +10 -18
- data/lib/hipbot/room.rb +2 -5
- data/lib/hipbot/version.rb +1 -1
- data/spec/integration/hipbot_spec.rb +33 -4
- data/spec/unit/hipbot_spec.rb +75 -3
- metadata +29 -12
- data/bot.rb +0 -92
- data/lib/hipbot/adapters/hipchat.rb +0 -86
- data/lib/hipbot/mucclient.rb +0 -60
- data/test_server.rb +0 -23
data/spec/unit/hipbot_spec.rb
CHANGED
@@ -44,6 +44,29 @@ describe Hipbot::Bot do
|
|
44
44
|
subject.tell(sender, room, '@robot hello there')
|
45
45
|
end
|
46
46
|
|
47
|
+
context "multiple regexps" do
|
48
|
+
before do
|
49
|
+
subject.on /hello (.*)/, /good morning (.*)/, /guten tag (.*)/ do |name|
|
50
|
+
reply("hello #{name}")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should understand simple english" do |msg|
|
55
|
+
subject.expects(:reply).with(room, 'hello tom')
|
56
|
+
subject.tell(sender, room, '@robot hello tom')
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should understand english" do |msg|
|
60
|
+
subject.expects(:reply).with(room, 'hello tom')
|
61
|
+
subject.tell(sender, room, '@robot good morning tom')
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should understand german" do |msg|
|
65
|
+
subject.expects(:reply).with(room, 'hello tom')
|
66
|
+
subject.tell(sender, room, '@robot guten tag tom')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
47
70
|
context "global messages" do
|
48
71
|
it "should reply if callback is global" do
|
49
72
|
subject.on /^you are (.*)$/, global: true do |adj|
|
@@ -93,10 +116,43 @@ describe Hipbot::Bot do
|
|
93
116
|
end
|
94
117
|
end
|
95
118
|
|
96
|
-
context "
|
119
|
+
context "messages in particular room" do
|
120
|
+
let(:room) { stub(:name => 'room') }
|
121
|
+
let(:other_room) { stub(:name => 'other_room') }
|
122
|
+
it "should reply" do
|
123
|
+
subject.on /wazzup\?/, room: 'room' do
|
124
|
+
reply('Wazzup, Tom?')
|
125
|
+
end
|
126
|
+
subject.expects(:reply).with(room, 'Wazzup, Tom?')
|
127
|
+
subject.tell(sender, room, '@robot wazzup?')
|
128
|
+
end
|
129
|
+
it "should reply if room acceptable" do
|
130
|
+
subject.on /wazzup\?/, room: ['other_room', 'room'] do
|
131
|
+
reply('wazzup, tom?')
|
132
|
+
end
|
133
|
+
subject.expects(:reply).with(room, 'wazzup, tom?')
|
134
|
+
subject.tell(sender, room, '@robot wazzup?')
|
135
|
+
end
|
136
|
+
it "should not reply if room unacceptable" do
|
137
|
+
subject.on /wazzup\?/, room: 'room' do
|
138
|
+
reply('wazzup, tom?')
|
139
|
+
end
|
140
|
+
subject.expects(:reply).with(other_room, "I don't understand \"wazzup?\"")
|
141
|
+
subject.tell(sender, other_room, '@robot wazzup?')
|
142
|
+
end
|
143
|
+
it "should not reply if room does not match" do
|
144
|
+
subject.on /wazzup\?/, room: ['other_room'] do
|
145
|
+
reply('wazzup, tom?')
|
146
|
+
end
|
147
|
+
subject.expects(:reply).with(room, "I don't understand \"wazzup?\"")
|
148
|
+
subject.tell(sender, room, '@robot wazzup?')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "response helper" do
|
97
153
|
it "message" do
|
98
154
|
subject.on /.*/ do
|
99
|
-
reply("you said: #{message}")
|
155
|
+
reply("you said: #{message.body}")
|
100
156
|
end
|
101
157
|
subject.expects(:reply).with(room, "you said: hello")
|
102
158
|
subject.tell(stub, room, "@robot hello")
|
@@ -112,11 +168,27 @@ describe Hipbot::Bot do
|
|
112
168
|
|
113
169
|
it "recipients" do
|
114
170
|
subject.on /.*/ do
|
115
|
-
reply("recipients: #{recipients.join(', ')}")
|
171
|
+
reply("recipients: #{message.recipients.join(', ')}")
|
116
172
|
end
|
117
173
|
subject.expects(:reply).with(room, "recipients: robot, dave")
|
118
174
|
subject.tell('tom', room, "@robot tell @dave hello from me")
|
119
175
|
end
|
176
|
+
|
177
|
+
it "sender name" do
|
178
|
+
subject.on /.*/ do
|
179
|
+
reply(message.sender_name)
|
180
|
+
end
|
181
|
+
subject.expects(:reply).with(room, 'Tom')
|
182
|
+
subject.tell('Tom Smith', room, '@robot What\'s my name?')
|
183
|
+
end
|
184
|
+
|
185
|
+
it "mentions" do
|
186
|
+
subject.on /.*/ do
|
187
|
+
reply(message.mentions.join(' '))
|
188
|
+
end
|
189
|
+
subject.expects(:reply).with(room, 'dave rachel')
|
190
|
+
subject.tell('Tom Smith', room, '@robot do you know @dave? @dave is @rachel father')
|
191
|
+
end
|
120
192
|
end
|
121
193
|
end
|
122
194
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hipbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: daemons
|
@@ -108,21 +108,37 @@ dependencies:
|
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0.5'
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
|
-
name:
|
111
|
+
name: rspec
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
113
113
|
none: false
|
114
114
|
requirements:
|
115
115
|
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
118
|
-
type: :
|
117
|
+
version: 2.11.0
|
118
|
+
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
none: false
|
122
122
|
requirements:
|
123
123
|
- - ~>
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
125
|
+
version: 2.11.0
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: mocha
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.11.4
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 0.11.4
|
126
142
|
description: Hipbot is a bot for HipChat, written in ruby & eventmachine.
|
127
143
|
email:
|
128
144
|
- pewniak747@gmail.com
|
@@ -139,16 +155,18 @@ files:
|
|
139
155
|
- README.md
|
140
156
|
- Rakefile
|
141
157
|
- bin/hipbot
|
142
|
-
- bot.rb
|
143
158
|
- hipbot.gemspec
|
144
159
|
- lib/hipbot.rb
|
145
|
-
- lib/hipbot/adapters/hipchat.rb
|
146
|
-
- lib/hipbot/adapters/
|
160
|
+
- lib/hipbot/adapters/hipchat/connection.rb
|
161
|
+
- lib/hipbot/adapters/hipchat/hipchat.rb
|
162
|
+
- lib/hipbot/adapters/telnet/connection.rb
|
163
|
+
- lib/hipbot/adapters/telnet/telnet.rb
|
147
164
|
- lib/hipbot/bot.rb
|
148
165
|
- lib/hipbot/configuration.rb
|
149
|
-
- lib/hipbot/
|
166
|
+
- lib/hipbot/http_response.rb
|
150
167
|
- lib/hipbot/message.rb
|
151
|
-
- lib/hipbot/
|
168
|
+
- lib/hipbot/patches/encoding.rb
|
169
|
+
- lib/hipbot/patches/mucclient.rb
|
152
170
|
- lib/hipbot/reaction.rb
|
153
171
|
- lib/hipbot/response.rb
|
154
172
|
- lib/hipbot/room.rb
|
@@ -157,7 +175,6 @@ files:
|
|
157
175
|
- spec/spec_helper.rb
|
158
176
|
- spec/unit/hipbot_spec.rb
|
159
177
|
- spec/unit/message_spec.rb
|
160
|
-
- test_server.rb
|
161
178
|
homepage: http://github.com/pewniak747/hipbot
|
162
179
|
licenses: []
|
163
180
|
post_install_message:
|
data/bot.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'hipbot'
|
2
|
-
|
3
|
-
class MyBot < Hipbot::Bot
|
4
|
-
configure do |c|
|
5
|
-
c.jid = ENV['HIPBOT_JID']
|
6
|
-
c.password = ENV['HIPBOT_PASSWORD']
|
7
|
-
c.name = ENV['HIPBOT_NAME']
|
8
|
-
end
|
9
|
-
|
10
|
-
# Works for message and response
|
11
|
-
# TODO: Reload existing objects? / Full bot restart
|
12
|
-
on /^reload (.*)/, global: true do |clazz|
|
13
|
-
const = clazz.capitalize.to_sym
|
14
|
-
Hipbot.class_eval do
|
15
|
-
remove_const const if const_defined? const
|
16
|
-
end
|
17
|
-
load("./lib/hipbot/" + clazz + ".rb")
|
18
|
-
reply('Reloaded')
|
19
|
-
end
|
20
|
-
|
21
|
-
on /get (.*)/ do |url|
|
22
|
-
get(url) do |http|
|
23
|
-
reply("Server responded with code: #{http.response_header.status}")
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
on /^wiki (.+)/, global: true do |search|
|
28
|
-
search = URI::encode search
|
29
|
-
get("http://en.wikipedia.org/w/api.php?action=query&format=json&titles=#{search}&prop=extracts&exlimit=3&explaintext=1&exsentences=2") do |http|
|
30
|
-
extracts = JSON.parse http.response.force_encoding 'utf-8'
|
31
|
-
extracts['query']['pages'].each do |page|
|
32
|
-
reply(page[1]['extract'])
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
on /^google (.+)/, global: true do |search|
|
38
|
-
search = URI::encode search
|
39
|
-
get("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&safe=off&q=#{search}") do |http|
|
40
|
-
extracts = JSON.parse http.response.force_encoding 'utf-8'
|
41
|
-
extracts['responseData']['results'].each do |page|
|
42
|
-
reply("#{page['url']} - #{page['titleNoFormatting']}")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
on /weather\s(.*)/ do |city|
|
48
|
-
reply("checking weather for #{city}")
|
49
|
-
conditions = ::GoogleWeather.new(city).forecast_conditions.first
|
50
|
-
reply("weather in #{city} - #{conditions.condition}, max #{conditions.high}F")
|
51
|
-
end
|
52
|
-
|
53
|
-
on /^hello.*/ do
|
54
|
-
reply('hello!')
|
55
|
-
end
|
56
|
-
|
57
|
-
on /deploy to (.*) pls/ do |stage|
|
58
|
-
reply("deploying #{room} to #{stage}!")
|
59
|
-
sleep(3)
|
60
|
-
reply("deployed!")
|
61
|
-
end
|
62
|
-
|
63
|
-
on /.*hello everyone.*/, global: true do
|
64
|
-
reply('hello!')
|
65
|
-
end
|
66
|
-
|
67
|
-
on /sleep/, global: true do
|
68
|
-
reply("sleeping...")
|
69
|
-
sleep(10)
|
70
|
-
reply("woke up")
|
71
|
-
end
|
72
|
-
|
73
|
-
on /help|commands/ do
|
74
|
-
commands = []
|
75
|
-
bot.reactions.each do |r|
|
76
|
-
commands << r.regexp
|
77
|
-
end
|
78
|
-
reply(commands.join("\n"))
|
79
|
-
end
|
80
|
-
|
81
|
-
on /^rand (.*)/, global: true do |message|
|
82
|
-
options = message.split(',').map { |s| s.strip }
|
83
|
-
rsp = options[rand(options.length)]
|
84
|
-
reply("And the winner is... #{rsp}") if rsp
|
85
|
-
end
|
86
|
-
|
87
|
-
on /^debug/, global: true do
|
88
|
-
reply "Debug " + (Jabber::debug = !Jabber::debug ? 'on' : 'off')
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
MyBot.start!
|
@@ -1,86 +0,0 @@
|
|
1
|
-
module Hipbot
|
2
|
-
module Adapters
|
3
|
-
module Hipchat
|
4
|
-
delegate :reply, to: :connection
|
5
|
-
|
6
|
-
class Connection
|
7
|
-
|
8
|
-
def initialize bot
|
9
|
-
initialize_bot(bot)
|
10
|
-
initialize_jabber
|
11
|
-
initialize_rooms
|
12
|
-
join_rooms
|
13
|
-
end
|
14
|
-
|
15
|
-
def reply room, message
|
16
|
-
for_room room do |room|
|
17
|
-
puts("Replied to #{room.name} - #{message}")
|
18
|
-
send_message(room, message)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def initialize_rooms
|
25
|
-
@rooms ||= []
|
26
|
-
@muc_browser = Jabber::MUC::MUCBrowser.new(@jabber)
|
27
|
-
@rooms = @muc_browser.muc_rooms('conf.hipchat.com').map { |jid, name|
|
28
|
-
::Hipbot::Room.new(jid, name)
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
def initialize_bot bot
|
33
|
-
@bot = bot
|
34
|
-
@bot.connection = self
|
35
|
-
end
|
36
|
-
|
37
|
-
def initialize_jabber
|
38
|
-
@jabber = ::Jabber::Client.new(@bot.jid)
|
39
|
-
@jabber.connect
|
40
|
-
@jabber.auth(@bot.password)
|
41
|
-
end
|
42
|
-
|
43
|
-
def join_rooms
|
44
|
-
rooms.each do |room|
|
45
|
-
puts "joining #{room.name}"
|
46
|
-
room.connection = ::Jabber::MUC::SimpleMUCClient.new(@jabber)
|
47
|
-
room.connection.on_message do |time, sender, message|
|
48
|
-
puts "#{Time.now} <#{sender}> #{message}"
|
49
|
-
begin
|
50
|
-
@bot.tell(sender, room.name, message)
|
51
|
-
rescue => e
|
52
|
-
puts e.inspect
|
53
|
-
end
|
54
|
-
end
|
55
|
-
room.connection.join("#{room.jid}/#{@bot.name}", nil, :history => false)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def for_room room_name
|
60
|
-
room = rooms.find { |r| r.name == room_name }
|
61
|
-
if room.present?
|
62
|
-
yield(room) if block_given?
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def send_message room, message
|
67
|
-
room.connection.say(message)
|
68
|
-
end
|
69
|
-
|
70
|
-
def rooms
|
71
|
-
@rooms || []
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def start!
|
76
|
-
::EM::run do
|
77
|
-
::EM.error_handler do |e|
|
78
|
-
puts e.inspect
|
79
|
-
end
|
80
|
-
Connection.new(self)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
data/lib/hipbot/mucclient.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
module Jabber
|
2
|
-
module MUC
|
3
|
-
class MUCClient
|
4
|
-
def join(jid, password=nil, opts={})
|
5
|
-
if active?
|
6
|
-
raise "MUCClient already active"
|
7
|
-
end
|
8
|
-
|
9
|
-
@jid = (jid.kind_of?(JID) ? jid : JID.new(jid))
|
10
|
-
activate
|
11
|
-
|
12
|
-
# Joining
|
13
|
-
pres = Presence.new
|
14
|
-
pres.to = @jid
|
15
|
-
pres.from = @my_jid
|
16
|
-
xmuc = XMUC.new
|
17
|
-
xmuc.password = password
|
18
|
-
|
19
|
-
if !opts[:history]
|
20
|
-
history = REXML::Element.new( 'history').tap {|h| h.add_attribute('maxstanzas','0') }
|
21
|
-
xmuc.add_element history
|
22
|
-
end
|
23
|
-
|
24
|
-
pres.add(xmuc)
|
25
|
-
|
26
|
-
# We don't use Stream#send_with_id here as it's unknown
|
27
|
-
# if the MUC component *always* uses our stanza id.
|
28
|
-
error = nil
|
29
|
-
@stream.send(pres) { |r|
|
30
|
-
if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error
|
31
|
-
# Error from room
|
32
|
-
error = r.error
|
33
|
-
true
|
34
|
-
# type='unavailable' may occur when the MUC kills our previous instance,
|
35
|
-
# but all join-failures should be type='error'
|
36
|
-
elsif r.from == jid and r.kind_of?(Presence) and r.type != :unavailable
|
37
|
-
# Our own presence reflected back - success
|
38
|
-
if r.x(XMUCUser) and (i = r.x(XMUCUser).items.first)
|
39
|
-
@affiliation = i.affiliation # we're interested in if it's :owner
|
40
|
-
@role = i.role # :moderator ?
|
41
|
-
end
|
42
|
-
|
43
|
-
handle_presence(r, false)
|
44
|
-
true
|
45
|
-
else
|
46
|
-
# Everything else
|
47
|
-
false
|
48
|
-
end
|
49
|
-
}
|
50
|
-
|
51
|
-
if error
|
52
|
-
deactivate
|
53
|
-
raise ServerError.new(error)
|
54
|
-
end
|
55
|
-
|
56
|
-
self
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
data/test_server.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
|
3
|
-
$connections = []
|
4
|
-
|
5
|
-
class ChatServer < EM::Connection
|
6
|
-
def post_init
|
7
|
-
$connections << self
|
8
|
-
end
|
9
|
-
|
10
|
-
def receive_data data
|
11
|
-
messages = data.split("\n").map{ |m| "#{m}\n" }.each do |msg|
|
12
|
-
sender, room, message = *msg.strip.split(':')
|
13
|
-
$connections.reject{|c| c==self}.each do |connection|
|
14
|
-
connection.send_data msg
|
15
|
-
end
|
16
|
-
puts "#{sender}@#{room} > #{message}"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
EM::run do
|
22
|
-
EM::start_server('0.0.0.0', 3001, ChatServer)
|
23
|
-
end
|