hipbot 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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