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.
@@ -1,7 +1,22 @@
1
1
  module Hipbot
2
- class Room < Struct.new(:jid, :name)
3
- attr_accessor :connection, :users
4
- alias_method :to_s, :name
2
+ class Room < Collection
3
+ attr_accessor :user_ids
5
4
 
5
+ def initialize *args
6
+ super
7
+ self.user_ids = []
8
+ end
9
+
10
+ def set_topic topic
11
+ self.class.bot.set_topic(self, topic)
12
+ end
13
+
14
+ def send_message message
15
+ self.class.bot.send_to_room(self, message)
16
+ end
17
+
18
+ def users
19
+ user_ids.map{ |id| User[id] }
20
+ end
6
21
  end
7
22
  end
@@ -0,0 +1,11 @@
1
+ module Hipbot
2
+ class User < Collection
3
+ def send_message message
4
+ self.class.bot.send_to_user name, message
5
+ end
6
+
7
+ def first_name
8
+ name.split.first
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module Hipbot
2
- VERSION = "0.0.5"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -30,14 +30,14 @@ class MyHipbot < Hipbot::Bot
30
30
  reply(project_name)
31
31
  end
32
32
  on /tell me my name/ do
33
- reply(sender_first_name)
33
+ reply("you are #{sender.first_name}")
34
34
  end
35
35
  end
36
36
 
37
37
  describe MyHipbot do
38
38
  # TODO: replace with actual objects
39
- let(:room) { Hipbot::Room.new('123', 'private') }
40
- let(:sender) { 'John Doe' }
39
+ let(:room) { Hipbot::Room.create('1', 'private', topic: 'topic') }
40
+ let(:sender) { Hipbot::User.create('1', 'John Doe') }
41
41
 
42
42
  describe "configuration" do
43
43
  it "should set robot name" do
@@ -51,30 +51,30 @@ describe MyHipbot do
51
51
 
52
52
  describe "replying" do
53
53
  it "should reply to hello" do
54
- subject.expects(:reply).with(room, 'hello!')
55
- subject.tell(sender, room, '@robbot hello hipbot!')
54
+ subject.expects(:send_to_room).with(room, 'hello!')
55
+ subject.react(sender, room, '@robbot hello hipbot!')
56
56
  end
57
57
 
58
58
  it "should reply with argument" do
59
- subject.expects(:reply).with(room, "I know I'm cool")
60
- subject.tell(sender, room, "@robbot you're cool, robot")
59
+ subject.expects(:send_to_room).with(room, "I know I'm cool")
60
+ subject.react(sender, room, "@robbot you're cool, robot")
61
61
  end
62
62
 
63
63
  it "should reply to global message" do
64
- subject.expects(:reply).with(room, "hello!")
65
- subject.tell(sender, room, "hi everyone!")
64
+ subject.expects(:send_to_room).with(room, "hello!")
65
+ subject.react(sender, room, "hi everyone!")
66
66
  end
67
67
  end
68
68
 
69
69
  describe "custom helpers" do
70
70
  it "should have access to room variable" do
71
- subject.expects(:reply).with(room, 'private project')
72
- subject.tell(sender, room, '@robbot tell me the project name')
71
+ subject.expects(:send_to_room).with(room, 'private project')
72
+ subject.react(sender, room, '@robbot tell me the project name')
73
73
  end
74
74
 
75
75
  it "should have access to message variable" do
76
- subject.expects(:reply).with(room, 'you are John')
77
- subject.tell(sender, room, '@robbot tell me my name')
76
+ subject.expects(:send_to_room).with(room, 'you are John')
77
+ subject.react(sender, room, '@robbot tell me my name')
78
78
  end
79
79
  end
80
80
  end
@@ -2,46 +2,47 @@ require 'spec_helper'
2
2
 
3
3
  describe Hipbot::Bot do
4
4
  context "#on" do
5
- let(:sender) { stub_everything }
6
- let(:room) { stub_everything }
5
+ let(:sender) { stub_everything(name: 'Tom Smith') }
6
+ let(:room) { stub_everything }
7
7
 
8
8
  it "should reply to no arguments" do
9
9
  subject.on /^hello there$/ do
10
10
  reply('hi!')
11
11
  end
12
- subject.expects(:reply).with(room, 'hi!')
13
- subject.tell(sender, room, '@robot hello there')
12
+ subject.expects(:send_to_room).with(room, 'hi!')
13
+ subject.react(sender, room, '@robot hello there')
14
14
  end
15
15
 
16
16
  it "should reply with one argument" do
17
17
  subject.on /^you are (.*), robot$/ do |adj|
18
18
  reply("i know i'm #{adj}!")
19
19
  end
20
- subject.expects(:reply).with(room, "i know i'm cool!")
21
- subject.tell(sender, room, '@robot you are cool, robot')
20
+ subject.expects(:send_to_room).with(room, "i know i'm cool!")
21
+ subject.react(sender, room, '@robot you are cool, robot')
22
22
  end
23
23
 
24
24
  it "should reply with multiple arguments" do
25
25
  subject.on /^send "(.*)" to (.*@.*)$/ do |message, recipient|
26
26
  reply("sent \"#{message}\" to #{recipient}")
27
27
  end
28
- subject.expects(:reply).with(room, 'sent "hello!" to robot@robots.org')
29
- subject.tell(sender, room, '@robot send "hello!" to robot@robots.org')
28
+ subject.expects(:send_to_room).with(room, 'sent "hello!" to robot@robots.org')
29
+ subject.react(sender, room, '@robot send "hello!" to robot@robots.org')
30
30
  end
31
31
 
32
32
  it "should say when does not understand" do
33
- subject.on /^hello there$/ do
34
- reply('hi!')
33
+ Hipbot::Bot.default do |message|
34
+ reply("I don't understand \"#{message}\"")
35
35
  end
36
- subject.expects(:reply).with(room, 'I don\'t understand "hello robot!"')
37
- subject.tell(sender, room, '@robot hello robot!')
36
+ subject.expects(:send_to_room).with(room, 'I don\'t understand "hello robot!"')
37
+ subject.react(sender, room, '@robot hello robot!')
38
+ Hipbot::Bot.class_variable_set :@@default_reaction, nil
38
39
  end
39
40
 
40
41
  it "should choose first option when multiple options match" do
41
42
  subject.on /hello there/ do reply('hello there') end
42
43
  subject.on /hello (.*)/ do reply('hello') end
43
- subject.expects(:reply).with(room, 'hello there')
44
- subject.tell(sender, room, '@robot hello there')
44
+ subject.expects(:send_to_room).with(room, 'hello there')
45
+ subject.react(sender, room, '@robot hello there')
45
46
  end
46
47
 
47
48
  context "multiple regexps" do
@@ -52,18 +53,18 @@ describe Hipbot::Bot do
52
53
  end
53
54
 
54
55
  it "should understand simple english" do |msg|
55
- subject.expects(:reply).with(room, 'hello tom')
56
- subject.tell(sender, room, '@robot hello tom')
56
+ subject.expects(:send_to_room).with(room, 'hello tom')
57
+ subject.react(sender, room, '@robot hello tom')
57
58
  end
58
59
 
59
60
  it "should understand english" do |msg|
60
- subject.expects(:reply).with(room, 'hello tom')
61
- subject.tell(sender, room, '@robot good morning tom')
61
+ subject.expects(:send_to_room).with(room, 'hello tom')
62
+ subject.react(sender, room, '@robot good morning tom')
62
63
  end
63
64
 
64
65
  it "should understand german" do |msg|
65
- subject.expects(:reply).with(room, 'hello tom')
66
- subject.tell(sender, room, '@robot guten tag tom')
66
+ subject.expects(:send_to_room).with(room, 'hello tom')
67
+ subject.react(sender, room, '@robot guten tag tom')
67
68
  end
68
69
  end
69
70
 
@@ -72,122 +73,125 @@ describe Hipbot::Bot do
72
73
  subject.on /^you are (.*)$/, global: true do |adj|
73
74
  reply("i know i'm #{adj}!")
74
75
  end
75
- subject.expects(:reply).with(room, "i know i'm cool!")
76
- subject.tell(sender, room, 'you are cool')
76
+ subject.expects(:send_to_room).with(room, "i know i'm cool!")
77
+ subject.react(sender, room, 'you are cool')
77
78
  end
78
79
 
79
80
  it "should not reply if callback not global" do
80
81
  subject.on /^you are (.*)$/ do |adj|
81
82
  reply("i know i'm #{adj}!")
82
83
  end
83
- subject.expects(:reply).never
84
- subject.tell(sender, room, 'you are cool')
84
+ subject.expects(:send_to_room).never
85
+ subject.react(sender, room, 'you are cool')
85
86
  end
86
87
  end
87
88
 
88
89
  context "messages from particular sender" do
90
+ let(:other_user) { stub(name: "John") }
89
91
  it "should reply" do
90
- subject.on /wazzup\?/, from: sender do
92
+ subject.on /wazzup\?/, from: sender.name do
91
93
  reply('Wazzup, Tom?')
92
94
  end
93
- subject.expects(:reply).with(room, 'Wazzup, Tom?')
94
- subject.tell(sender, room, '@robot wazzup?')
95
+ subject.expects(:send_to_room).with(room, 'Wazzup, Tom?')
96
+ subject.react(sender, room, '@robot wazzup?')
95
97
  end
96
98
  it "should reply if sender acceptable" do
97
- subject.on /wazzup\?/, from: [stub, sender] do
99
+ subject.on /wazzup\?/, from: [stub, sender.name] do
98
100
  reply('wazzup, tom?')
99
101
  end
100
- subject.expects(:reply).with(room, 'wazzup, tom?')
101
- subject.tell(sender, room, '@robot wazzup?')
102
+ subject.expects(:send_to_room).with(room, 'wazzup, tom?')
103
+ subject.react(sender, room, '@robot wazzup?')
102
104
  end
103
105
  it "should not reply if sender unacceptable" do
104
- subject.on /wazzup\?/, from: sender do
106
+ subject.on /wazzup\?/, from: sender.name do
105
107
  reply('wazzup, tom?')
106
108
  end
107
- subject.expects(:reply).with(room, "I don't understand \"wazzup?\"")
108
- subject.tell(stub, room, '@robot wazzup?')
109
+ subject.expects(:send_to_room).never
110
+ subject.react(other_user, room, '@robot wazzup?')
109
111
  end
110
112
  it "should not reply if sender does not match" do
111
- subject.on /wazzup\?/, from: [sender] do
113
+ subject.on /wazzup\?/, from: [sender.name] do
112
114
  reply('wazzup, tom?')
113
115
  end
114
- subject.expects(:reply).with(room, "I don't understand \"wazzup?\"")
115
- subject.tell(stub, room, '@robot wazzup?')
116
+ subject.expects(:send_to_room).never
117
+ subject.react(other_user, room, '@robot wazzup?')
116
118
  end
117
119
  end
118
120
 
119
121
  context "messages in particular room" do
120
- let(:room) { stub(:name => 'room') }
122
+ let(:room) { stub(:name => 'room') }
121
123
  let(:other_room) { stub(:name => 'other_room') }
122
124
  it "should reply" do
123
125
  subject.on /wazzup\?/, room: 'room' do
124
126
  reply('Wazzup, Tom?')
125
127
  end
126
- subject.expects(:reply).with(room, 'Wazzup, Tom?')
127
- subject.tell(sender, room, '@robot wazzup?')
128
+ subject.expects(:send_to_room).with(room, 'Wazzup, Tom?')
129
+ subject.react(sender, room, '@robot wazzup?')
128
130
  end
129
131
  it "should reply if room acceptable" do
130
132
  subject.on /wazzup\?/, room: ['other_room', 'room'] do
131
133
  reply('wazzup, tom?')
132
134
  end
133
- subject.expects(:reply).with(room, 'wazzup, tom?')
134
- subject.tell(sender, room, '@robot wazzup?')
135
+ subject.expects(:send_to_room).with(room, 'wazzup, tom?')
136
+ subject.react(sender, room, '@robot wazzup?')
135
137
  end
136
138
  it "should not reply if room unacceptable" do
137
139
  subject.on /wazzup\?/, room: 'room' do
138
140
  reply('wazzup, tom?')
139
141
  end
140
- subject.expects(:reply).with(other_room, "I don't understand \"wazzup?\"")
141
- subject.tell(sender, other_room, '@robot wazzup?')
142
+ subject.expects(:send_to_room).never
143
+ subject.react(sender, other_room, '@robot wazzup?')
142
144
  end
143
145
  it "should not reply if room does not match" do
144
146
  subject.on /wazzup\?/, room: ['other_room'] do
145
147
  reply('wazzup, tom?')
146
148
  end
147
- subject.expects(:reply).with(room, "I don't understand \"wazzup?\"")
148
- subject.tell(sender, room, '@robot wazzup?')
149
+ subject.expects(:send_to_room).never
150
+ subject.react(sender, room, '@robot wazzup?')
149
151
  end
150
152
  end
151
153
 
152
154
  context "response helper" do
155
+ let(:user){ stub(name: 'Tom Smith', first_name: 'Tom') }
156
+
153
157
  it "message" do
154
158
  subject.on /.*/ do
155
159
  reply("you said: #{message.body}")
156
160
  end
157
- subject.expects(:reply).with(room, "you said: hello")
158
- subject.tell(stub, room, "@robot hello")
161
+ subject.expects(:send_to_room).with(room, "you said: hello")
162
+ subject.react(user, room, "@robot hello")
159
163
  end
160
164
 
161
165
  it "sender" do
162
166
  subject.on /.*/ do
163
- reply("you are: #{sender}")
167
+ reply("you are: #{sender.name}")
164
168
  end
165
- subject.expects(:reply).with(room, "you are: tom")
166
- subject.tell('tom', room, "@robot hello")
169
+ subject.expects(:send_to_room).with(room, "you are: Tom Smith")
170
+ subject.react(user, room, "@robot hello")
167
171
  end
168
172
 
169
173
  it "recipients" do
170
174
  subject.on /.*/ do
171
175
  reply("recipients: #{message.recipients.join(', ')}")
172
176
  end
173
- subject.expects(:reply).with(room, "recipients: robot, dave")
174
- subject.tell('tom', room, "@robot tell @dave hello from me")
177
+ subject.expects(:send_to_room).with(room, "recipients: robot, dave")
178
+ subject.react(user, room, "@robot tell @dave hello from me")
175
179
  end
176
180
 
177
181
  it "sender name" do
178
182
  subject.on /.*/ do
179
- reply(message.sender_name)
183
+ reply(message.sender.first_name)
180
184
  end
181
- subject.expects(:reply).with(room, 'Tom')
182
- subject.tell('Tom Smith', room, '@robot What\'s my name?')
185
+ subject.expects(:send_to_room).with(room, 'Tom')
186
+ subject.react(user, room, '@robot What\'s my name?')
183
187
  end
184
188
 
185
189
  it "mentions" do
186
190
  subject.on /.*/ do
187
191
  reply(message.mentions.join(' '))
188
192
  end
189
- subject.expects(:reply).with(room, 'dave rachel')
190
- subject.tell('Tom Smith', room, '@robot do you know @dave? @dave is @rachel father')
193
+ subject.expects(:send_to_room).with(room, 'dave rachel')
194
+ subject.react(user, room, '@robot do you know @dave? @dave is @rachel father')
191
195
  end
192
196
  end
193
197
  end
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.5
4
+ version: 0.1.0
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-08-29 00:00:00.000000000 Z
12
+ date: 2013-03-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: daemons
@@ -155,6 +155,8 @@ files:
155
155
  - README.md
156
156
  - Rakefile
157
157
  - bin/hipbot
158
+ - examples/cleverbot.rb
159
+ - examples/google_images.rb
158
160
  - hipbot.gemspec
159
161
  - lib/hipbot.rb
160
162
  - lib/hipbot/adapters/hipchat/connection.rb
@@ -162,14 +164,16 @@ files:
162
164
  - lib/hipbot/adapters/telnet/connection.rb
163
165
  - lib/hipbot/adapters/telnet/telnet.rb
164
166
  - lib/hipbot/bot.rb
167
+ - lib/hipbot/collection.rb
165
168
  - lib/hipbot/configuration.rb
166
169
  - lib/hipbot/http_response.rb
167
170
  - lib/hipbot/message.rb
168
171
  - lib/hipbot/patches/encoding.rb
169
- - lib/hipbot/patches/mucclient.rb
172
+ - lib/hipbot/patches/hipchat_client.rb
170
173
  - lib/hipbot/reaction.rb
171
174
  - lib/hipbot/response.rb
172
175
  - lib/hipbot/room.rb
176
+ - lib/hipbot/user.rb
173
177
  - lib/hipbot/version.rb
174
178
  - spec/integration/hipbot_spec.rb
175
179
  - spec/spec_helper.rb
@@ -1,147 +0,0 @@
1
- module Jabber
2
- module MUC
3
-
4
- class MUCClient
5
-
6
- def join(jid, password=nil, opts={})
7
- if active?
8
- raise "MUCClient already active"
9
- end
10
-
11
- @jid = (jid.kind_of?(JID) ? jid : JID.new(jid))
12
- activate
13
-
14
- # Joining
15
- pres = Presence.new
16
- pres.to = @jid
17
- pres.from = @my_jid
18
- xmuc = XMUC.new
19
- xmuc.password = password
20
-
21
- if !opts[:history]
22
- history = REXML::Element.new( 'history').tap {|h| h.add_attribute('maxstanzas','0') }
23
- xmuc.add_element history
24
- end
25
-
26
- pres.add(xmuc)
27
-
28
- # We don't use Stream#send_with_id here as it's unknown
29
- # if the MUC component *always* uses our stanza id.
30
- error = nil
31
- @stream.send(pres) { |r|
32
- if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error
33
- # Error from room
34
- error = r.error
35
- true
36
- # type='unavailable' may occur when the MUC kills our previous instance,
37
- # but all join-failures should be type='error'
38
- elsif r.from == jid and r.kind_of?(Presence) and r.type != :unavailable
39
- # Our own presence reflected back - success
40
- if r.x(XMUCUser) and (i = r.x(XMUCUser).items.first)
41
- @affiliation = i.affiliation # we're interested in if it's :owner
42
- @role = i.role # :moderator ?
43
- end
44
-
45
- handle_presence(r, false)
46
- true
47
- else
48
- # Everything else
49
- false
50
- end
51
- }
52
-
53
- if error
54
- deactivate
55
- raise ServerError.new(error)
56
- end
57
-
58
- self
59
- end
60
-
61
- private
62
- def activate # :nodoc:
63
- @active = true
64
-
65
- # Callbacks
66
- @stream.add_presence_callback(150, self) { |presence|
67
- if from_room?(presence.from)
68
- handle_presence(presence)
69
- true
70
- else
71
- false
72
- end
73
- }
74
-
75
- @stream.add_message_callback(150, self) { |message|
76
- # Not sure if this was hipchat or client bug,
77
- # but this callback didn't allow chat (private) messages since
78
- # they don't belong to any conference room
79
- if from_room?(message.from) || is_chat?(message.type)
80
- handle_message(message)
81
- true
82
- else
83
- false
84
- end
85
- }
86
- end
87
-
88
- def is_chat?(type)
89
- type == :chat
90
- end
91
-
92
- def send(stanza, to = nil)
93
- if stanza.kind_of? Message
94
- stanza.type = to || stanza.to ? :chat : :groupchat
95
- end
96
- stanza.from = @my_jid
97
- # We don't want to override existing message JID
98
- stanza.to = JID.new(jid.node, jid.domain, to) if stanza.to.nil?
99
- @stream.send(stanza)
100
- end
101
-
102
- end
103
-
104
- class SimpleMUCClient < MUCClient
105
-
106
- def say(text, jid = nil)
107
- send(Message.new(jid, text))
108
- end
109
-
110
- private
111
-
112
- def handle_message(msg)
113
- super
114
-
115
- time = Time.now # Hipchat doesn't provide time stamp for message elements
116
- msg.each_element('x') { |x|
117
- if x.kind_of?(Delay::XDelay)
118
- time = x.stamp
119
- end
120
- }
121
- sender_nick = msg.from.resource
122
-
123
-
124
- if msg.subject
125
- @subject = msg.subject
126
- @subject_block.call(time, sender_nick, @subject) if @subject_block
127
- end
128
-
129
- if msg.body
130
- if sender_nick.nil?
131
- @room_message_block.call(time, msg.body) if @room_message_block
132
- else
133
- if msg.type == :chat
134
- # We need to send full jid here (msg.from)
135
- @private_message_block.call(time, msg.from, msg.body) if @private_message_block
136
- elsif msg.type == :groupchat
137
- @message_block.call(time, msg.from.resource, msg.body) if @message_block
138
- else
139
- # ...?
140
- end
141
- end
142
- end
143
- end
144
-
145
- end
146
- end
147
- end