campfire-bot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +11 -0
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +57 -0
- data/README.textile +52 -0
- data/TODO +72 -0
- data/bin/bot +13 -0
- data/campfire-bot.gemspec +27 -0
- data/cfbot-stop.sh +8 -0
- data/config.example.yml +31 -0
- data/lib/bot.rb +194 -0
- data/lib/event.rb +114 -0
- data/lib/message.rb +30 -0
- data/lib/plugin.rb +77 -0
- data/lib/version.rb +3 -0
- data/plugins/accountability.rb +45 -0
- data/plugins/austin.rb +29 -0
- data/plugins/basecamp.rb +48 -0
- data/plugins/beer.rb +214 -0
- data/plugins/beijing_tally.rb +30 -0
- data/plugins/boop.rb +127 -0
- data/plugins/bruce.rb +15 -0
- data/plugins/bugzilla.rb +198 -0
- data/plugins/calvin.rb +43 -0
- data/plugins/chuck.rb +23 -0
- data/plugins/dilbert.rb +51 -0
- data/plugins/excuse.rb +478 -0
- data/plugins/fail.rb +16 -0
- data/plugins/figlet.rb +10 -0
- data/plugins/fun.rb +95 -0
- data/plugins/garfield.rb +43 -0
- data/plugins/generic_search.rb +66 -0
- data/plugins/help.rb +13 -0
- data/plugins/infobot.rb +58 -0
- data/plugins/insult.rb +87 -0
- data/plugins/jira.rb +197 -0
- data/plugins/lolcats.rb +17 -0
- data/plugins/our_quotes.rb +195 -0
- data/plugins/quote.rb +31 -0
- data/plugins/schneier.rb +28 -0
- data/plugins/seen.rb +88 -0
- data/plugins/signal_filter.rb +9 -0
- data/plugins/svn.rb +167 -0
- data/plugins/twitter_echo.rb +54 -0
- data/plugins/unfuddle.rb +69 -0
- data/plugins/weather.rb +25 -0
- data/plugins/xkcd.rb +43 -0
- data/spec/beer_spec.rb +224 -0
- data/spec/bugzilla_spec.rb +90 -0
- data/spec/command_spec.rb +96 -0
- data/spec/jira_spec.rb +264 -0
- data/spec/our_quotes_spec.rb +186 -0
- data/spec/plugin_spec.rb +43 -0
- data/spec/spec.opts +1 -0
- data/vendor/escape/ChangeLog +30 -0
- data/vendor/escape/Makefile +5 -0
- data/vendor/escape/README +81 -0
- data/vendor/escape/VERSION +1 -0
- data/vendor/escape/escape.rb +302 -0
- data/vendor/escape/install.rb +109 -0
- data/vendor/escape/misc/README.erb +85 -0
- data/vendor/escape/rdoc/classes/Escape.html +427 -0
- data/vendor/escape/rdoc/classes/Escape.src/M000022.html +19 -0
- data/vendor/escape/rdoc/classes/Escape.src/M000023.html +32 -0
- data/vendor/escape/rdoc/classes/Escape.src/M000024.html +24 -0
- data/vendor/escape/rdoc/classes/Escape.src/M000025.html +19 -0
- data/vendor/escape/rdoc/classes/Escape.src/M000026.html +48 -0
- data/vendor/escape/rdoc/classes/Escape.src/M000027.html +19 -0
- data/vendor/escape/rdoc/classes/Escape.src/M000028.html +19 -0
- data/vendor/escape/rdoc/classes/Escape/HTMLAttrValue.html +113 -0
- data/vendor/escape/rdoc/classes/Escape/HTMLEscaped.html +113 -0
- data/vendor/escape/rdoc/classes/Escape/PercentEncoded.html +113 -0
- data/vendor/escape/rdoc/classes/Escape/ShellEscaped.html +113 -0
- data/vendor/escape/rdoc/classes/Escape/StringWrapper.html +242 -0
- data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000029.html +18 -0
- data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000030.html +18 -0
- data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000031.html +18 -0
- data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000032.html +18 -0
- data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000033.html +18 -0
- data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000035.html +18 -0
- data/vendor/escape/rdoc/classes/TestEscapeHTML.html +182 -0
- data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000008.html +18 -0
- data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000009.html +18 -0
- data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000010.html +18 -0
- data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000011.html +18 -0
- data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.html +182 -0
- data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000012.html +18 -0
- data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000013.html +19 -0
- data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000014.html +20 -0
- data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000015.html +22 -0
- data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.html +167 -0
- data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.src/M000016.html +18 -0
- data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.src/M000017.html +20 -0
- data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.src/M000018.html +20 -0
- data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.html +167 -0
- data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.src/M000019.html +20 -0
- data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.src/M000020.html +24 -0
- data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.src/M000021.html +22 -0
- data/vendor/escape/rdoc/files/escape_rb.html +136 -0
- data/vendor/escape/rdoc/files/install_rb.html +250 -0
- data/vendor/escape/rdoc/files/install_rb.src/M000001.html +23 -0
- data/vendor/escape/rdoc/files/install_rb.src/M000002.html +31 -0
- data/vendor/escape/rdoc/files/install_rb.src/M000003.html +27 -0
- data/vendor/escape/rdoc/files/install_rb.src/M000004.html +27 -0
- data/vendor/escape/rdoc/files/install_rb.src/M000005.html +21 -0
- data/vendor/escape/rdoc/files/install_rb.src/M000006.html +23 -0
- data/vendor/escape/rdoc/files/install_rb.src/M000007.html +21 -0
- data/vendor/escape/rdoc/files/test/test-escape_rb.html +109 -0
- data/vendor/escape/rdoc/fr_class_index.html +36 -0
- data/vendor/escape/rdoc/fr_file_index.html +29 -0
- data/vendor/escape/rdoc/fr_method_index.html +61 -0
- data/vendor/escape/rdoc/index.html +24 -0
- data/vendor/escape/rdoc/rdoc-style.css +208 -0
- data/vendor/escape/test/test-escape.rb +90 -0
- metadata +259 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec'
|
2
|
+
BOT_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
BOT_ENVIRONMENT = 'development'
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), '../lib/bot.rb')
|
6
|
+
bot = CampfireBot::Bot.instance
|
7
|
+
require "#{BOT_ROOT}/lib/event.rb"
|
8
|
+
|
9
|
+
|
10
|
+
class TestingCommand < CampfireBot::Event::Command
|
11
|
+
|
12
|
+
def filter_message(msg)
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "processing messages" do
|
18
|
+
|
19
|
+
before(:all) do
|
20
|
+
bot = CampfireBot::Bot.instance
|
21
|
+
@nickname = bot.config['nickname']
|
22
|
+
end
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
@command = TestingCommand.new("command", nil, nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
def match?(msg)
|
29
|
+
@command.match?({:message => msg})
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "and recognizing a command" do
|
33
|
+
|
34
|
+
it "should handle a !command" do
|
35
|
+
match?("!command").should be_true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should handle a !command with arguments" do
|
39
|
+
match?("!command foo").should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should handle a command with nickname and a comma" do
|
43
|
+
match?("#{@nickname}, command").should be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should handle a command with nickname and a colon" do
|
47
|
+
match?("#{@nickname}: command").should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should handle a command with nickname and arguments" do
|
51
|
+
match?("#{@nickname}, command foo").should be_true
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should ignore a non-matching !command" do
|
55
|
+
match?("!foo").should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should ignore an addressed non-command" do
|
59
|
+
match?("#{@nickname}, nothing").should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should ignore things that aren't commands at all" do
|
63
|
+
["nothing", "#{@nickname}, ", " ! command", "hey #{@nickname}", "!command!command", "!command,command"].each do |t|
|
64
|
+
match?(t).should be_false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "and filtering it" do
|
70
|
+
|
71
|
+
def filter(msg)
|
72
|
+
@command.filter_message({:message => msg})[:message]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should be empty with no arguments" do
|
76
|
+
filter("!command").should == ""
|
77
|
+
filter("#{@nickname}, command").should == ""
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return one argument" do
|
81
|
+
filter("!command foo").should == "foo"
|
82
|
+
filter("#{@nickname}, command foo").should == "foo"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return more than one argument" do
|
86
|
+
filter("!command foo bar baz").should == "foo bar baz"
|
87
|
+
filter("#{@nickname}, command foo bar baz").should == "foo bar baz"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should deal with some weirdness" do
|
91
|
+
filter("!command !command").should == "!command"
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
data/spec/jira_spec.rb
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
require 'spec'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'xmlsimple'
|
4
|
+
|
5
|
+
BOT_ROOT = File.join(File.dirname(__FILE__), '..')
|
6
|
+
BOT_ENVIRONMENT = 'development'
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), '../lib/bot.rb')
|
9
|
+
bot = CampfireBot::Bot.instance
|
10
|
+
require "#{BOT_ROOT}/plugins/jira.rb"
|
11
|
+
|
12
|
+
|
13
|
+
class SpecMessage < CampfireBot::Message
|
14
|
+
attr_reader :response
|
15
|
+
|
16
|
+
#overwrite message.speak method so that we can expose the output
|
17
|
+
def speak(msg)
|
18
|
+
puts "specmessage.speak(#{msg})"
|
19
|
+
@response = msg
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
class SpecJira < CampfireBot::Plugin::Jira
|
25
|
+
attr_accessor :cached_ids, :last_checked
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
describe "checking jira and" do
|
31
|
+
|
32
|
+
|
33
|
+
# send a message to the room and return the response
|
34
|
+
def sendmsg(msg)
|
35
|
+
# puts "sendmsg(#{msg})"
|
36
|
+
@message[:message] = msg
|
37
|
+
@message[:room] = mock('room', :name => 'test')
|
38
|
+
bot.send(:handle_message, @message)
|
39
|
+
# puts "sendmsg returns #{@message.response}"
|
40
|
+
@message.response
|
41
|
+
end
|
42
|
+
|
43
|
+
# instantiate the bot and the plugin fresh
|
44
|
+
|
45
|
+
def setup
|
46
|
+
bot = CampfireBot::Bot.instance
|
47
|
+
bot.stub!(:config).and_return({'nickname' => 'Bot', 'jira_url' => 'foo'})
|
48
|
+
YAML.stub!(:load).and_return {}
|
49
|
+
YAML.stub!(:dump).and_return true
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
@jira = SpecJira.new()
|
54
|
+
CampfireBot::Plugin.registered_plugins['Jira'] = @jira
|
55
|
+
@jira.cached_ids = {}
|
56
|
+
@jira.last_checked = 15.minutes.ago
|
57
|
+
@message = nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def jira_response(ticketarray)
|
61
|
+
|
62
|
+
jira_hash = {'rss' => {'channel' => [] }}
|
63
|
+
|
64
|
+
ticketarray.each do |ticket|
|
65
|
+
ticket.merge!({'description' => 'foo',
|
66
|
+
'link' => "http://oz/jira/browse/#{ticket['key']}",
|
67
|
+
'title' => 'foo',
|
68
|
+
'reporter' => 'foo',
|
69
|
+
'priority' => 'Critical',
|
70
|
+
'type' => 'Bug'})
|
71
|
+
|
72
|
+
jira_hash['rss']['channel'] << {'item' => ticket }
|
73
|
+
end
|
74
|
+
|
75
|
+
@message = SpecMessage.new(:person => 'Josh', :room => mock('room', :name => 'test'))
|
76
|
+
|
77
|
+
xmldata = XmlSimple.xml_out(jira_hash, {'NoAttr' => true, 'RootName' => nil})
|
78
|
+
|
79
|
+
@jira.stub!(:open).and_return(mock('foo', :read => xmldata))
|
80
|
+
|
81
|
+
@jira.check_jira(@message)
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "seeing a ticket higher than the last stored id" do
|
85
|
+
|
86
|
+
before(:all) do
|
87
|
+
setup
|
88
|
+
jira_response([{
|
89
|
+
'key' => 'PIM-123',
|
90
|
+
'description' => 'foo',
|
91
|
+
'link' => 'http://oz/jira/browse/PIM-123',
|
92
|
+
'title' => 'foo',
|
93
|
+
'reporter' => 'foo',
|
94
|
+
'priority' => 'Critical',
|
95
|
+
'type' => 'Bug',
|
96
|
+
'updated' => 5.minutes.ago.to_s
|
97
|
+
}])
|
98
|
+
|
99
|
+
@jira.last_checked = 5.minutes.ago
|
100
|
+
jira_response([{
|
101
|
+
'key' => 'PIM-124',
|
102
|
+
'description' => 'foo',
|
103
|
+
'link' => 'http://oz/jira/browse/PIM-124',
|
104
|
+
'title' => 'foo',
|
105
|
+
'reporter' => 'foo',
|
106
|
+
'priority' => 'Critical',
|
107
|
+
'type' => 'Bug',
|
108
|
+
'updated' => 3.minutes.ago.to_s
|
109
|
+
}])
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should update the cached highest id" do
|
113
|
+
@jira.cached_ids['PIM'].should eql(124)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should speak the info of the ticket" do
|
117
|
+
@message.response.should match(/PIM-124/)
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "seeing a ticket we've already seen" do
|
124
|
+
|
125
|
+
before(:all) do
|
126
|
+
setup
|
127
|
+
jira_response([{
|
128
|
+
'key' => 'PIM-123',
|
129
|
+
|
130
|
+
'updated' => Time.now().to_s
|
131
|
+
}])
|
132
|
+
|
133
|
+
jira_response([{
|
134
|
+
'key' => 'PIM-123',
|
135
|
+
'description' => 'foo',
|
136
|
+
'link' => 'http://oz/jira/browse/PIM-123',
|
137
|
+
'title' => 'foo',
|
138
|
+
'reporter' => 'foo',
|
139
|
+
'priority' => 'Critical',
|
140
|
+
'type' => 'Bug',
|
141
|
+
'updated' => Time.now().to_s
|
142
|
+
}])
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should be quiet" do
|
146
|
+
@message.response.should be(nil)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should not change the list of cached ids" do
|
150
|
+
@jira.cached_ids.size.should eql(1)
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "seeing a ticket whose ID is lower than the highest seen id" do
|
157
|
+
before(:all) do
|
158
|
+
setup
|
159
|
+
jira_response([{
|
160
|
+
'key' => 'PIM-123',
|
161
|
+
'updated' => 5.minutes.ago.to_s
|
162
|
+
}])
|
163
|
+
|
164
|
+
@jira.last_checked = 3.minutes.ago
|
165
|
+
|
166
|
+
jira_response([{
|
167
|
+
'key' => 'PIM-120',
|
168
|
+
'updated' => Time.now().to_s
|
169
|
+
}])
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should be quiet" do
|
174
|
+
@message.response.should be(nil)
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "seeing a space we've never seen before" do
|
180
|
+
before(:all) do
|
181
|
+
setup
|
182
|
+
jira_response([{
|
183
|
+
'key' => 'PIM-123',
|
184
|
+
'updated' => 5.minutes.ago.to_s
|
185
|
+
}])
|
186
|
+
|
187
|
+
@jira.last_checked = 5.minutes.ago
|
188
|
+
jira_response([{
|
189
|
+
'key' => 'FOO-124',
|
190
|
+
'updated' => 3.minutes.ago.to_s
|
191
|
+
}])
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should update the cached highest id" do
|
195
|
+
@jira.cached_ids['FOO'].should eql(124)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should speak the info of the ticket" do
|
199
|
+
@message.response.should match(/FOO-124/)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "getting a bunch of tickets in one go" do
|
204
|
+
before(:all) do
|
205
|
+
setup
|
206
|
+
end
|
207
|
+
|
208
|
+
it "with all new" do
|
209
|
+
@jira.cached_ids = {}
|
210
|
+
|
211
|
+
msg = SpecMessage.new(:person => 'Josh', :room => mock('room', :name => 'test'))
|
212
|
+
SpecMessage.should_receive(:new).and_return(msg)
|
213
|
+
msg.should_receive(:speak).twice
|
214
|
+
|
215
|
+
jira_response([{
|
216
|
+
'key' => 'PIM-1124',
|
217
|
+
'updated' => 5.minutes.ago.to_s
|
218
|
+
},
|
219
|
+
{'key' => 'PIM-1123',
|
220
|
+
'updated' => 5.minutes.ago.to_s}])
|
221
|
+
@jira.cached_ids['PIM'].should eql(1124)
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
it "with a mix of old and new" do
|
226
|
+
msg = SpecMessage.new(:person => 'Josh', :room => mock('room', :name => 'test'))
|
227
|
+
SpecMessage.should_receive(:new).and_return(msg)
|
228
|
+
msg.should_receive(:speak).twice
|
229
|
+
|
230
|
+
@jira.cached_ids['PIM'] = 1124
|
231
|
+
jira_response([{
|
232
|
+
'key' => 'PIM-1126',
|
233
|
+
'updated' => 5.minutes.ago.to_s
|
234
|
+
},
|
235
|
+
{
|
236
|
+
'key' => 'PIM-1125',
|
237
|
+
'updated' => 5.minutes.ago.to_s
|
238
|
+
},
|
239
|
+
{
|
240
|
+
'key' => 'PIM-1124',
|
241
|
+
'updated' => 5.minutes.ago.to_s
|
242
|
+
}
|
243
|
+
])
|
244
|
+
@jira.cached_ids['PIM'].should eql(1126)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "with all old" do
|
248
|
+
@jira.cached_ids['PIM'] = 1125
|
249
|
+
jira_response([{
|
250
|
+
'key' => 'PIM-1125',
|
251
|
+
'updated' => 5.minutes.ago.to_s
|
252
|
+
},
|
253
|
+
{'key' => 'PIM-1124',
|
254
|
+
'updated' => 5.minutes.ago.to_s}])
|
255
|
+
@jira.cached_ids['PIM'].should eql(1125)
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'spec'
|
2
|
+
BOT_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
BOT_ENVIRONMENT = 'test'
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), '../lib/bot.rb')
|
6
|
+
bot = CampfireBot::Bot.instance
|
7
|
+
require "#{BOT_ROOT}/plugins/our_quotes.rb"
|
8
|
+
|
9
|
+
describe "OurQuotes plugin" do
|
10
|
+
|
11
|
+
it "should remember added quotes" do
|
12
|
+
when_saying "!addquote Someone: Hello world."
|
13
|
+
bot_should_reply "Added quote #1."
|
14
|
+
quotes[0].should == "Someone: Hello world."
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should complain when !addquote is given without a quote" do
|
18
|
+
when_saying "!addquote"
|
19
|
+
bot_should_reply "Please include the text of the quote and attribution."
|
20
|
+
quotes.size.should == 0
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should regurgitate random quotes" do
|
24
|
+
with_quote_log {
|
25
|
+
add "Someone: Hello world."
|
26
|
+
}
|
27
|
+
when_saying "!quote"
|
28
|
+
# How to show attribution, index, room, and timestamp?
|
29
|
+
#bot_should_reply "Someone spake thusly: Hello world"
|
30
|
+
# "Foo quoth thither
|
31
|
+
bot_should_reply "#1 Someone: Hello world."
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should find matching quotes" do
|
35
|
+
with_quote_log {
|
36
|
+
add "Anyone: Hello world."
|
37
|
+
add "Someone: Hello world."
|
38
|
+
del 1
|
39
|
+
add "Someone: It's too cold."
|
40
|
+
}
|
41
|
+
when_saying "!quote o w"
|
42
|
+
bot_should_reply "#2 Someone: Hello world. (1 match)"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should use proper grammer when showing number of matches" do
|
46
|
+
with_quote_log {
|
47
|
+
add "Anyone: hi!"
|
48
|
+
add "Anyone: bye."
|
49
|
+
}
|
50
|
+
when_saying "!quote Anyone"
|
51
|
+
bot_should_reply %r/ \(2 matches\)$/
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should retrieve quotes by ID when the query is numeric" do
|
55
|
+
with_quote_log {
|
56
|
+
add "Anyone: 2+2"
|
57
|
+
add "Anyone: hi!"
|
58
|
+
}
|
59
|
+
when_saying "!quote 2"
|
60
|
+
bot_should_reply "#2 Anyone: hi!"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should display an explanation when !quote is given an invalid ID" do
|
64
|
+
when_saying "!quote 1"
|
65
|
+
bot_should_reply "No quote #1."
|
66
|
+
end
|
67
|
+
|
68
|
+
# Implementation idea: save array of matches in a hash
|
69
|
+
# keyed by query and perhaps user. Should expire after
|
70
|
+
# a few minutes, so don't bother persisting it even to tmp/.
|
71
|
+
it "should iterate through results on repeat command" do
|
72
|
+
pending
|
73
|
+
with_quote_log {
|
74
|
+
add "Someone: Foo"
|
75
|
+
add "Someone: Bar"
|
76
|
+
add "Someone: Baz"
|
77
|
+
}
|
78
|
+
when_saying "!quote Someone"
|
79
|
+
bot_should_reply %r/#\d Someone: ... \(3 matches\)$/
|
80
|
+
when_saying "!quote Someone"
|
81
|
+
bot_should_reply %r/#\d Someone: ... \(2 of 3 matches\)$/
|
82
|
+
when_saying "!quote Someone"
|
83
|
+
bot_should_reply %r/#\d Someone: ... \(3 of 3 matches\)$/
|
84
|
+
# Or maybe (3 matches, none left) ?
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should remove last quote upon request" do
|
88
|
+
with_quote_log {
|
89
|
+
add "Hello world."
|
90
|
+
}
|
91
|
+
when_saying "!rmquote 1"
|
92
|
+
bot_should_reply "Deleted quote #1."
|
93
|
+
@quote.quotes.size.should == 0
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should free trailing IDs when removing quotes" do
|
97
|
+
with_quote_log {
|
98
|
+
add "One"
|
99
|
+
add "Two"
|
100
|
+
add "Three"
|
101
|
+
add "Four"
|
102
|
+
del 3
|
103
|
+
del 4
|
104
|
+
add "III"
|
105
|
+
}
|
106
|
+
quotes[3 - 1].should == "III"
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should preserve IDs of quotes after the removed one" do
|
110
|
+
with_quote_log {
|
111
|
+
add "One"
|
112
|
+
add "Two"
|
113
|
+
add "Three"
|
114
|
+
del 2
|
115
|
+
}
|
116
|
+
quotes[3 - 1].should == "Three"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should display an explanation when !rmquote is given an invalid ID" do
|
120
|
+
when_saying "!rmquote 1"
|
121
|
+
bot_should_reply "No quote #1."
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should save quotes between runs" do
|
125
|
+
with_quote_log {
|
126
|
+
add "One"
|
127
|
+
add "Two"
|
128
|
+
}
|
129
|
+
init_plugin # Should re-read the .yml file
|
130
|
+
quotes[2 - 1].should == "Two"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should handle angle brackets appropriately" do
|
134
|
+
# One convention for attribution is to place the speaker in brackets.
|
135
|
+
# And this is how Campfire+Tinder+CampfireBot send us the message.
|
136
|
+
when_saying "!addquote \\u0026lt;Someone\\u0026gt; Hello"
|
137
|
+
bot_should_reply "Added quote #1."
|
138
|
+
quotes[1 - 1].should == "<Someone> Hello"
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
before :each do
|
143
|
+
@bot = CampfireBot::Bot.instance
|
144
|
+
@bot.stub!(:config).and_return('nickname' => 'Bot',
|
145
|
+
'our_quotes_recall_command' => 'quote'
|
146
|
+
#,'our_quotes_debug_enabled' => true
|
147
|
+
)
|
148
|
+
init_plugin
|
149
|
+
end
|
150
|
+
after :each do
|
151
|
+
if File.exist? @quote.data_file
|
152
|
+
File.unlink(@quote.data_file)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
def init_plugin
|
156
|
+
@quote = OurQuotes.new
|
157
|
+
CampfireBot::Plugin.registered_plugins['OurQuotes'] = @quote
|
158
|
+
end
|
159
|
+
|
160
|
+
def when_saying(msg)
|
161
|
+
@message = CampfireBot::Message.new(:room => Tinder::Room.new(42, "Room1"),
|
162
|
+
:message => msg,
|
163
|
+
:person => 'Josh')
|
164
|
+
end
|
165
|
+
def bot_should_reply(msg)
|
166
|
+
@message.should_receive(:speak).with(msg)
|
167
|
+
@bot.send(:handle_message, @message)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Group log setup calls into a block
|
171
|
+
def with_quote_log
|
172
|
+
yield
|
173
|
+
end
|
174
|
+
# Add a quote to the log
|
175
|
+
def add(quote)
|
176
|
+
@quote.append_add("Someoneelse", "Room1", quote)
|
177
|
+
end
|
178
|
+
# Remove a quote from the log by id
|
179
|
+
def del(quote_id)
|
180
|
+
@quote.append_del("Someoneelse", "Room1", quote_id)
|
181
|
+
end
|
182
|
+
def quotes
|
183
|
+
@quote.quotes
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|