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.
Files changed (115) hide show
  1. data/.autotest +11 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +57 -0
  5. data/README.textile +52 -0
  6. data/TODO +72 -0
  7. data/bin/bot +13 -0
  8. data/campfire-bot.gemspec +27 -0
  9. data/cfbot-stop.sh +8 -0
  10. data/config.example.yml +31 -0
  11. data/lib/bot.rb +194 -0
  12. data/lib/event.rb +114 -0
  13. data/lib/message.rb +30 -0
  14. data/lib/plugin.rb +77 -0
  15. data/lib/version.rb +3 -0
  16. data/plugins/accountability.rb +45 -0
  17. data/plugins/austin.rb +29 -0
  18. data/plugins/basecamp.rb +48 -0
  19. data/plugins/beer.rb +214 -0
  20. data/plugins/beijing_tally.rb +30 -0
  21. data/plugins/boop.rb +127 -0
  22. data/plugins/bruce.rb +15 -0
  23. data/plugins/bugzilla.rb +198 -0
  24. data/plugins/calvin.rb +43 -0
  25. data/plugins/chuck.rb +23 -0
  26. data/plugins/dilbert.rb +51 -0
  27. data/plugins/excuse.rb +478 -0
  28. data/plugins/fail.rb +16 -0
  29. data/plugins/figlet.rb +10 -0
  30. data/plugins/fun.rb +95 -0
  31. data/plugins/garfield.rb +43 -0
  32. data/plugins/generic_search.rb +66 -0
  33. data/plugins/help.rb +13 -0
  34. data/plugins/infobot.rb +58 -0
  35. data/plugins/insult.rb +87 -0
  36. data/plugins/jira.rb +197 -0
  37. data/plugins/lolcats.rb +17 -0
  38. data/plugins/our_quotes.rb +195 -0
  39. data/plugins/quote.rb +31 -0
  40. data/plugins/schneier.rb +28 -0
  41. data/plugins/seen.rb +88 -0
  42. data/plugins/signal_filter.rb +9 -0
  43. data/plugins/svn.rb +167 -0
  44. data/plugins/twitter_echo.rb +54 -0
  45. data/plugins/unfuddle.rb +69 -0
  46. data/plugins/weather.rb +25 -0
  47. data/plugins/xkcd.rb +43 -0
  48. data/spec/beer_spec.rb +224 -0
  49. data/spec/bugzilla_spec.rb +90 -0
  50. data/spec/command_spec.rb +96 -0
  51. data/spec/jira_spec.rb +264 -0
  52. data/spec/our_quotes_spec.rb +186 -0
  53. data/spec/plugin_spec.rb +43 -0
  54. data/spec/spec.opts +1 -0
  55. data/vendor/escape/ChangeLog +30 -0
  56. data/vendor/escape/Makefile +5 -0
  57. data/vendor/escape/README +81 -0
  58. data/vendor/escape/VERSION +1 -0
  59. data/vendor/escape/escape.rb +302 -0
  60. data/vendor/escape/install.rb +109 -0
  61. data/vendor/escape/misc/README.erb +85 -0
  62. data/vendor/escape/rdoc/classes/Escape.html +427 -0
  63. data/vendor/escape/rdoc/classes/Escape.src/M000022.html +19 -0
  64. data/vendor/escape/rdoc/classes/Escape.src/M000023.html +32 -0
  65. data/vendor/escape/rdoc/classes/Escape.src/M000024.html +24 -0
  66. data/vendor/escape/rdoc/classes/Escape.src/M000025.html +19 -0
  67. data/vendor/escape/rdoc/classes/Escape.src/M000026.html +48 -0
  68. data/vendor/escape/rdoc/classes/Escape.src/M000027.html +19 -0
  69. data/vendor/escape/rdoc/classes/Escape.src/M000028.html +19 -0
  70. data/vendor/escape/rdoc/classes/Escape/HTMLAttrValue.html +113 -0
  71. data/vendor/escape/rdoc/classes/Escape/HTMLEscaped.html +113 -0
  72. data/vendor/escape/rdoc/classes/Escape/PercentEncoded.html +113 -0
  73. data/vendor/escape/rdoc/classes/Escape/ShellEscaped.html +113 -0
  74. data/vendor/escape/rdoc/classes/Escape/StringWrapper.html +242 -0
  75. data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000029.html +18 -0
  76. data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000030.html +18 -0
  77. data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000031.html +18 -0
  78. data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000032.html +18 -0
  79. data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000033.html +18 -0
  80. data/vendor/escape/rdoc/classes/Escape/StringWrapper.src/M000035.html +18 -0
  81. data/vendor/escape/rdoc/classes/TestEscapeHTML.html +182 -0
  82. data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000008.html +18 -0
  83. data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000009.html +18 -0
  84. data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000010.html +18 -0
  85. data/vendor/escape/rdoc/classes/TestEscapeHTML.src/M000011.html +18 -0
  86. data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.html +182 -0
  87. data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000012.html +18 -0
  88. data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000013.html +19 -0
  89. data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000014.html +20 -0
  90. data/vendor/escape/rdoc/classes/TestEscapePercentEncoded.src/M000015.html +22 -0
  91. data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.html +167 -0
  92. data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.src/M000016.html +18 -0
  93. data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.src/M000017.html +20 -0
  94. data/vendor/escape/rdoc/classes/TestEscapeShellEscaped.src/M000018.html +20 -0
  95. data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.html +167 -0
  96. data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.src/M000019.html +20 -0
  97. data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.src/M000020.html +24 -0
  98. data/vendor/escape/rdoc/classes/TestEscapeStringWrapper.src/M000021.html +22 -0
  99. data/vendor/escape/rdoc/files/escape_rb.html +136 -0
  100. data/vendor/escape/rdoc/files/install_rb.html +250 -0
  101. data/vendor/escape/rdoc/files/install_rb.src/M000001.html +23 -0
  102. data/vendor/escape/rdoc/files/install_rb.src/M000002.html +31 -0
  103. data/vendor/escape/rdoc/files/install_rb.src/M000003.html +27 -0
  104. data/vendor/escape/rdoc/files/install_rb.src/M000004.html +27 -0
  105. data/vendor/escape/rdoc/files/install_rb.src/M000005.html +21 -0
  106. data/vendor/escape/rdoc/files/install_rb.src/M000006.html +23 -0
  107. data/vendor/escape/rdoc/files/install_rb.src/M000007.html +21 -0
  108. data/vendor/escape/rdoc/files/test/test-escape_rb.html +109 -0
  109. data/vendor/escape/rdoc/fr_class_index.html +36 -0
  110. data/vendor/escape/rdoc/fr_file_index.html +29 -0
  111. data/vendor/escape/rdoc/fr_method_index.html +61 -0
  112. data/vendor/escape/rdoc/index.html +24 -0
  113. data/vendor/escape/rdoc/rdoc-style.css +208 -0
  114. data/vendor/escape/test/test-escape.rb +90 -0
  115. metadata +259 -0
@@ -0,0 +1,54 @@
1
+ require 'hpricot'
2
+ require 'open-uri'
3
+ require 'ostruct'
4
+ require 'time'
5
+ require 'htmlentities'
6
+
7
+ # The workings of this plugin are based on http://github.com/paulca/twitter2campfire
8
+ # Thanks to Paul Campbell and Contrast! <http://www.contrast.ie/>
9
+
10
+ class TwitterEcho < CampfireBot::Plugin
11
+
12
+ at_interval 2.minutes, :echo_tweets
13
+
14
+ def initialize
15
+ @feed = bot.config['twitter_feed']
16
+ @hide_replies = bot.config.key?('twitter_hide_replies') ? bot.config['twitter_hide_replies'] : false
17
+ @latest = Time.now
18
+ end
19
+
20
+ def echo_tweets(msg = nil)
21
+ recent_tweets.reverse.each do |tweet|
22
+ msg.speak("#{coder.decode(tweet.from)}: #{coder.decode(tweet.text)} #{tweet.link}") unless (tweet.text =~ /^@/ && @hide_replies)
23
+ end
24
+ @latest = latest_tweet.date # next time, only print tweets newer than this
25
+ @doc = nil # reset the feed so that next time we can actually any new tweets
26
+ end
27
+
28
+ protected
29
+
30
+ def raw_feed
31
+ @doc ||= Hpricot(open(@feed))
32
+ end
33
+
34
+ def all_tweets
35
+ (raw_feed/'entry').map { |e| OpenStruct.new(
36
+ :from => (e/'name').inner_html,
37
+ :text => (e/'title').inner_html,
38
+ :link => (e/'link').first['href'],
39
+ :date => Time.parse((e/'published').inner_html)
40
+ )}
41
+ end
42
+
43
+ def latest_tweet
44
+ all_tweets.first
45
+ end
46
+
47
+ def recent_tweets
48
+ all_tweets.reject { |e| e.date.to_i <= @latest.to_i }
49
+ end
50
+
51
+ def coder
52
+ HTMLEntities.new
53
+ end
54
+ end
@@ -0,0 +1,69 @@
1
+ # Unfuddle RSS echo plugin. Uses the following config.yml settings:
2
+ #
3
+ # unfuddle:
4
+ # domain: you.unfuddle.com
5
+ # rss_path: "/account/activity.rss?aak=aaaaaaaaaaaaabbbbbbbbccccccccddddddeeee0000"
6
+ # port: 443
7
+ # msg_filters:
8
+ # - reassigned
9
+ # - closed
10
+ # - commented
11
+ # - resolved
12
+
13
+ require 'rubygems'
14
+ require 'simple-rss'
15
+ require 'net/https'
16
+
17
+ class Unfuddle < CampfireBot::Plugin
18
+ at_interval 2.minutes, :fetch_rss
19
+ on_command 'unfuddle', :fetch_rss
20
+
21
+ def initialize
22
+ @last_item = 12.hours.ago
23
+ @http = Net::HTTP.new(bot.config['unfuddle']['domain'], bot.config['unfuddle']['port'])
24
+
25
+ if bot.config['unfuddle']['port'] == 443
26
+ @http.use_ssl = true
27
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
28
+ end
29
+ end
30
+
31
+ def fetch_rss(msg)
32
+ feed = SimpleRSS.parse(@http.get(bot.config['unfuddle']['rss_path']).body)
33
+
34
+ feed.items.each do |item|
35
+ msg.speak "#{item.title} #{item.link}" if published?(item) && !filtered?(item.title)
36
+ end
37
+
38
+ @last_item = feed.items.first.pubDate
39
+ rescue => e
40
+ msg.speak e
41
+ end
42
+
43
+ def published?(item)
44
+ item.pubDate > @last_item
45
+ end
46
+
47
+ def filtered?(title)
48
+ bot.config['unfuddle']['msg_filters'].each do |msg_filter|
49
+ return true if send("#{msg_filter}?", title)
50
+ end
51
+ return false
52
+ end
53
+
54
+ def closed?(title)
55
+ (title =~ /Closed Ticket:/) != nil
56
+ end
57
+
58
+ def reassigned?(title)
59
+ (title =~ /Reassigned Ticket:/) != nil
60
+ end
61
+
62
+ def commented?(title)
63
+ (title =~ /Created Ticket Comment:/) != nil
64
+ end
65
+
66
+ def resolved?(title)
67
+ (title =~ /Resolved Ticket:/) != nil
68
+ end
69
+ end
@@ -0,0 +1,25 @@
1
+ require 'yahoo-weather'
2
+
3
+ class Weather < CampfireBot::Plugin
4
+ on_command 'weather', :weather
5
+
6
+ def weather(msg)
7
+ cities = {
8
+ 'adelaide' => '1099805',
9
+ 'brisbane' => '1100661',
10
+ 'canberra' => '1100968',
11
+ 'darwin' => '1101597',
12
+ 'hobart' => '1102670',
13
+ 'melbourne' => '1103816',
14
+ 'perth' => '1098081',
15
+ 'sydney' => '1105779'
16
+ }
17
+
18
+ city_id = cities[(msg[:message]).downcase] # select city, or
19
+ city_id ||= cities['canberra'] # use default if no matches
20
+
21
+ data = YahooWeather::Client.new.lookup_by_woeid(city_id, 'c')
22
+
23
+ msg.speak("#{data.title} - #{data.condition.text}, #{data.condition.temp} deg C (high #{data.forecasts.first.high}, low #{data.forecasts.first.low})")
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ require 'open-uri'
2
+ require 'hpricot'
3
+ require 'tempfile'
4
+
5
+ class Xkcd < CampfireBot::Plugin
6
+ BASE_URL = 'http://xkcd.com/'
7
+
8
+ on_command 'xkcd', :xkcd
9
+
10
+ def xkcd(msg)
11
+ # Get the comic info
12
+ comic = case msg[:message].split(/\s+/)[0]
13
+ when 'latest'
14
+ fetch_latest
15
+ when 'random'
16
+ fetch_random
17
+ when /d+/
18
+ fetch_comic(msg[:message].split(/\s+/)[0])
19
+ else
20
+ fetch_random
21
+ end
22
+
23
+ msg.speak comic['src']
24
+ msg.speak comic['title']
25
+ end
26
+
27
+ private
28
+
29
+ def fetch_latest
30
+ fetch_comic
31
+ end
32
+
33
+ def fetch_random
34
+ # Fetch the latest page and then find the link to the previous comic.
35
+ # This will give us a number to work with (that of the penultimate strip).
36
+ fetch_comic(rand((Hpricot(open(BASE_URL))/'//*[@accesskey="p"]').first['href'].gsub(/\D/, '').to_i + 1))
37
+ end
38
+
39
+ def fetch_comic(id = nil)
40
+ # Rely on the comic being the last image on the page with a title attribute
41
+ (Hpricot(open("#{BASE_URL}#{id.to_s + '/' if id}"))/'img[@title]').last
42
+ end
43
+ end
@@ -0,0 +1,224 @@
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
+ require "#{BOT_ROOT}/plugins/beer.rb"
7
+
8
+
9
+ class SpecMessage < CampfireBot::Message
10
+ attr_reader :response
11
+
12
+ #overwrite message.speak method so that we can expose the output
13
+ def speak(msg)
14
+ # puts "specmessage.speak(#{msg})"
15
+ @response = msg
16
+ end
17
+
18
+ end
19
+
20
+ class SpecBeer < CampfireBot::Plugin::Beer
21
+ attr_accessor :balances
22
+ end
23
+
24
+ # send a message to the room and return the response
25
+ def sendmsg(msg)
26
+ # puts "sendmsg(#{msg})"
27
+ @message[:message] = msg
28
+ @message[:type] = "TextMessage"
29
+ @message[:room] = mock('room', :name => 'test')
30
+ # bot.send(:handle_message, @message)
31
+ %w(commands speakers messages).each do |type|
32
+ CampfireBot::Plugin.send("registered_#{type}").each do |handler|
33
+ handler.run(@message)
34
+ end
35
+ end
36
+ # puts "sendmsg returns #{@message.response}"
37
+ @message.response
38
+ end
39
+
40
+ # instantiate the bot and the plugin fresh
41
+ def setup
42
+ bot = CampfireBot::Bot.instance
43
+ bot.stub!(:config).and_return({'nickname' => 'Bot'})
44
+ @beer = SpecBeer.new()
45
+ CampfireBot::Plugin.registered_plugins['Beer'] = @beer
46
+ @message = SpecMessage.new(:person => 'Josh')
47
+ @beer.balances = {}
48
+ @beer.stub!(:init).and_return(@beer.balances)
49
+ @beer.stub!(:write)
50
+ puts @beer.balances
51
+ @message = SpecMessage.new(:person => 'Josh')
52
+ end
53
+
54
+ describe "giving beer" do
55
+ before(:each) do
56
+ setup
57
+ end
58
+
59
+ # it "should respond to the command !give_beer" do
60
+ # @beer.should_receive(:give_beer)
61
+ # sendmsg "!give_beer"
62
+ # end
63
+
64
+
65
+ it "should increase my balance with Foo" do
66
+ bal = 0
67
+ sendmsg '!give_beer Foo'
68
+ @beer.balance('Josh', 'Foo').should eql(bal + 1)
69
+ end
70
+
71
+
72
+ it "should say back to me what my balance is" do
73
+
74
+ sendmsg('!give_beer bruce').should =~ /1/
75
+ end
76
+
77
+ it "should accept an argument of the number of beers to credit" do
78
+ bal = 2
79
+ sendmsg('!give_beer harvey 2')
80
+ @beer.balance('Josh', 'harvey').should eql(bal)
81
+ end
82
+
83
+ it "should handle nicely names with spaces in them with no argument" do
84
+ bal = 1
85
+ sendmsg('!give_beer harvey A.')
86
+ @beer.balance('Josh', 'harvey A.').should eql(bal)
87
+ end
88
+
89
+ it "should handle nicely names with spaces in them and an argument" do
90
+ bal = 2
91
+ sendmsg('!give_beer harvey D. 2')
92
+ @beer.balance('Josh', 'harvey D.').should eql(bal)
93
+ end
94
+
95
+ it "should not accept negative numbers as an argument" do
96
+ sendmsg('!give_beer harvey -2').should =~ /negative number/
97
+ end
98
+
99
+ end
100
+
101
+ describe "demanding beer" do
102
+
103
+ before(:each) do
104
+ setup
105
+ end
106
+
107
+ it "should respond to the command !demand_beer" do
108
+ @beer.should_receive(:demand_beer)
109
+ sendmsg("!demand_beer albert")
110
+ end
111
+
112
+ it "should decrease my balance with the opposite party" do
113
+ bal = 0
114
+ # p "initial bal is #{bal}"
115
+ sendmsg '!demand_beer Foo'
116
+ puts @beer.balance('Josh', 'Foo')
117
+ @beer.balance('Josh', 'Foo').should eql(bal - 1)
118
+ end
119
+
120
+ end
121
+
122
+ describe "redeeming beer" do
123
+ before(:each) do
124
+ setup
125
+ end
126
+
127
+ it "should respond to the command !redeem_beer" do
128
+ @beer.should_receive(:redeem_beer)
129
+ sendmsg('!redeem_beer Foo')
130
+
131
+ end
132
+
133
+ it "should increase my balance with the opposite party (redeeming is the same as giving)" do
134
+ sendmsg '!demand_beer albert'
135
+ sendmsg '!demand_beer albert'
136
+ bal = @beer.balance('Josh', 'albert')
137
+ # puts "------ #{bal}"
138
+ sendmsg '!redeem_beer albert'
139
+ @beer.balance('Josh', 'albert').should eql(bal + 1)
140
+ end
141
+
142
+ it "should not increase my balance if it is already zero" do
143
+ @beer.should_receive('balance').with('Josh', 'bill').and_return(0)
144
+ sendmsg("!redeem_beer bill").should =~ /to begin with/
145
+ # @beer.balance('Josh', 'bill').should eql(bal)
146
+ end
147
+ end
148
+
149
+
150
+ describe "should have the correct reply for" do
151
+
152
+ before(:each) do
153
+ setup
154
+ end
155
+
156
+ it "negative balances (I owe beers)" do
157
+ @beer.should_receive('balance').with('Josh', 'james').and_return(1)
158
+ sendmsg("!give_beer james").should =~ /you now owe james .* beer/
159
+ end
160
+
161
+ it "positive balances (I am owed beers)" do
162
+ @beer.balances['albert'] = {}
163
+ @beer.balances['albert']['Josh'] = 1
164
+ sendmsg("!demand_beer albert").should =~ /albert now owes you .* beer/
165
+ end
166
+
167
+ it "zero balance (all even)" do
168
+ @beer.should_receive('balance').with('Josh', 'albert').and_return(0)
169
+ sendmsg("!give_beer albert").should =~ /albert .* even/
170
+ end
171
+
172
+ it "missing all arguments" do
173
+ sendmsg("!give_beer").should =~ /don't know whom/
174
+ end
175
+
176
+ # it "non-integer 2nd arg" do
177
+ # sendmsg("!give_beer albert non-int").should =~ /I don't accept non-integer amounts/
178
+ # end
179
+
180
+ end
181
+
182
+ describe "!balance command" do
183
+ before(:each) do
184
+ setup
185
+ end
186
+
187
+ it "should respond to the !balance command" do
188
+ @beer.should_receive(:balance_cmd)
189
+ sendmsg("!balance")
190
+ end
191
+
192
+ it "should require an argument of a user" do
193
+ sendmsg("!balance").should be_nil
194
+ end
195
+
196
+ describe "should return the correct balance for" do
197
+ it "negative balances" do
198
+ sendmsg("!demand_beer maxim 2")
199
+ # @beer.balance('Josh', 'max').should eql(-2)
200
+ # @beer.should_receive('balance').with('Josh', 'Foo').and_return(-1)
201
+ sendmsg("!balance maxim").should =~ /owes you 2 beers/
202
+ end
203
+
204
+ it "positive balances" do
205
+ sendmsg("!give_beer maximo 9")
206
+ # @beer.balance('Josh', 'max').should eql(7)
207
+ # @beer.should_receive('balance').with('Josh', 'Foo').and_return(1)
208
+ sendmsg("!balance maximo").should =~ /You owe .* 9 beers/
209
+ end
210
+
211
+ it "non-existent balances" do
212
+ sendmsg("!balance Fsdfsdfsdfsdfsdfoo").should =~ /transactions/
213
+ end
214
+
215
+ end
216
+ end
217
+
218
+ describe "beer_transactiona and balance" do
219
+ it "should handle equivalent transactions equivalently" do
220
+ pending
221
+ end
222
+
223
+
224
+ end
@@ -0,0 +1,90 @@
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/bugzilla.rb"
8
+
9
+ describe "Bugzilla plugin" do
10
+ before(:each) do
11
+ require 'shorturl'
12
+ ShortURL.stub!(:shorten).
13
+ with("https://bugzilla/show_bug.cgi?id=1234").
14
+ and_return("http://rubyurl.com/xyz")
15
+ @bot = CampfireBot::Bot.instance
16
+ @bot.stub!(:config).and_return('nickname' => 'Bot'
17
+ #,'bugzilla_debug_enabled' => true
18
+ )
19
+ @bugzilla = Bugzilla.new
20
+ @bugzilla.stub!(:http_fetch_body).
21
+ with("https://bugzilla/show_bug.cgi?id=1234").
22
+ and_return(
23
+ "<html>
24
+ <head>
25
+ <title>Bug 1234 - Fix widget behavior</title>
26
+ </head>
27
+ </html>")
28
+ CampfireBot::Plugin.registered_plugins['Bugzilla'] = @bugzilla
29
+ @message = CampfireBot::Message.new(:room => Tinder::Room.new(42, "Main"),
30
+ :person => 'Josh')
31
+ end
32
+
33
+ after(:each) do
34
+ if File.exist? @bugzilla.data_file
35
+ File.unlink(@bugzilla.data_file)
36
+ end
37
+ end
38
+
39
+ it "should respond to the command !bug" do
40
+ @bugzilla.should_receive(:describe_command)
41
+ @message[:message] = "!bug"
42
+ @bot.send(:handle_message, @message)
43
+ end
44
+
45
+ it "should respond to !bug with a bug title" do
46
+ @message.should_receive(:speak).
47
+ with("Bug 1234 - Fix widget behavior (http://rubyurl.com/xyz)")
48
+ @message[:message] = "!bug 1234"
49
+ @bot.send(:handle_message, @message)
50
+ end
51
+
52
+ it "should overhear mentions of 'bug NNNN' and offer the title" do
53
+ @message.should_receive(:speak).
54
+ with("Bug 1234 - Fix widget behavior (http://rubyurl.com/xyz)")
55
+ @message[:message] = "What about bug 1234?"
56
+ @bot.send(:handle_message, @message)
57
+ end
58
+
59
+ it "should not repeat a bug title twice in a short time when overhearing" do
60
+ @message.should_receive(:speak).
61
+ with("Bug 1234 - Fix widget behavior (http://rubyurl.com/xyz)")
62
+ @message[:message] = "What about bug 1234?"
63
+ @bot.send(:handle_message, @message)
64
+
65
+ @message2 = CampfireBot::Message.new(:room => Tinder::Room.new(42, "Main"),
66
+ :person => 'Josh')
67
+ @message2.should_not_receive(:speak)
68
+ @message2[:message] = "I fixed bug 1234, too."
69
+ @bot.send(:handle_message, @message2)
70
+ end
71
+ end
72
+
73
+ describe "http_fetch_body method" do
74
+ before(:each) do
75
+ end
76
+ # Probably this method should live elsewhere, and in that location be
77
+ # broken down into smaller methods to facilitate testing.
78
+ it "should return the body of an HTTP response" do
79
+ pending
80
+ end
81
+ it "should raise an exception for non-success status" do
82
+ pending
83
+ end
84
+ it "should use netrc credentials when possible" do
85
+ pending
86
+ end
87
+ it "should support https when necessary" do
88
+ pending
89
+ end
90
+ end