campfire-bot 0.0.1
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/.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
|