campfire-bot 0.1.0 → 1.0.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.
- data/.gitignore +1 -1
- data/Gemfile +6 -1
- data/README.textile +15 -5
- data/bin/campfire-bot +52 -6
- data/campfire-bot.gemspec +4 -7
- data/config.example.yml +3 -2
- data/lib/bot.rb +26 -26
- data/lib/version.rb +1 -1
- metadata +22 -96
- data/CHANGELOG.md +0 -10
- data/Gemfile.lock +0 -58
- data/plugins/accountability.rb +0 -45
- data/plugins/austin.rb +0 -29
- data/plugins/basecamp.rb +0 -48
- data/plugins/beer.rb +0 -214
- data/plugins/beijing_tally.rb +0 -30
- data/plugins/boop.rb +0 -127
- data/plugins/bruce.rb +0 -15
- data/plugins/bugzilla.rb +0 -198
- data/plugins/calvin.rb +0 -43
- data/plugins/chuck.rb +0 -23
- data/plugins/dilbert.rb +0 -51
- data/plugins/excuse.rb +0 -478
- data/plugins/fail.rb +0 -16
- data/plugins/figlet.rb +0 -10
- data/plugins/fun.rb +0 -95
- data/plugins/garfield.rb +0 -43
- data/plugins/generic_search.rb +0 -66
- data/plugins/help.rb +0 -13
- data/plugins/infobot.rb +0 -58
- data/plugins/insult.rb +0 -87
- data/plugins/jira.rb +0 -197
- data/plugins/lolcats.rb +0 -17
- data/plugins/our_quotes.rb +0 -195
- data/plugins/quote.rb +0 -31
- data/plugins/schneier.rb +0 -28
- data/plugins/seen.rb +0 -88
- data/plugins/signal_filter.rb +0 -9
- data/plugins/svn.rb +0 -167
- data/plugins/twitter_echo.rb +0 -54
- data/plugins/unfuddle.rb +0 -69
- data/plugins/weather.rb +0 -25
- data/plugins/xkcd.rb +0 -43
data/CHANGELOG.md
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
# 0.1.0
|
2
|
-
|
3
|
-
* Fixed loading of plugins by using `require
|
4
|
-
campfire_bot/_plugin_name_.rb` instead of `load _plugin_name_.rb`
|
5
|
-
* Renamed bin/bot to bin/campfire-bot since this project is now gemified, and the bot name was too generic.
|
6
|
-
* Updated to activesupport ~> 3.1.3.
|
7
|
-
|
8
|
-
# 0.0.1
|
9
|
-
|
10
|
-
* Initial release
|
data/Gemfile.lock
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
campfire-bot (0.0.1)
|
5
|
-
activesupport (~> 3.1.3)
|
6
|
-
eventmachine (~> 0.12.10)
|
7
|
-
hpricot (~> 0.8.3)
|
8
|
-
i18n (~> 0.5.0)
|
9
|
-
logging (~> 1.4.3)
|
10
|
-
mime-types (~> 1.16)
|
11
|
-
tinder (>= 1.4.3)
|
12
|
-
twitter-stream (~> 0.1)
|
13
|
-
|
14
|
-
GEM
|
15
|
-
remote: http://rubygems.org/
|
16
|
-
specs:
|
17
|
-
activesupport (3.1.3)
|
18
|
-
multi_json (~> 1.0)
|
19
|
-
addressable (2.2.6)
|
20
|
-
eventmachine (0.12.10)
|
21
|
-
faraday (0.7.5)
|
22
|
-
addressable (~> 2.2.6)
|
23
|
-
multipart-post (~> 1.1.3)
|
24
|
-
rack (>= 1.1.0, < 2)
|
25
|
-
faraday_middleware (0.7.0)
|
26
|
-
faraday (~> 0.7.3)
|
27
|
-
hashie (1.2.0)
|
28
|
-
hpricot (0.8.5)
|
29
|
-
http_parser.rb (0.5.3)
|
30
|
-
i18n (0.5.0)
|
31
|
-
little-plugger (1.1.3)
|
32
|
-
logging (1.4.3)
|
33
|
-
little-plugger (>= 1.1.2)
|
34
|
-
mime-types (1.17.2)
|
35
|
-
multi_json (1.0.4)
|
36
|
-
multipart-post (1.1.4)
|
37
|
-
rack (1.3.5)
|
38
|
-
simple_oauth (0.1.5)
|
39
|
-
tinder (1.8.0)
|
40
|
-
activesupport (>= 2.3, < 4)
|
41
|
-
eventmachine (~> 0.12)
|
42
|
-
faraday (>= 0.6, < 0.8)
|
43
|
-
faraday_middleware (>= 0.6, < 0.8)
|
44
|
-
hashie (~> 1.0)
|
45
|
-
mime-types (~> 1.16)
|
46
|
-
multi_json (~> 1.0)
|
47
|
-
multipart-post (~> 1.1)
|
48
|
-
twitter-stream (~> 0.1)
|
49
|
-
twitter-stream (0.1.14)
|
50
|
-
eventmachine (>= 0.12.8)
|
51
|
-
http_parser.rb (~> 0.5.1)
|
52
|
-
simple_oauth (~> 0.1.4)
|
53
|
-
|
54
|
-
PLATFORMS
|
55
|
-
ruby
|
56
|
-
|
57
|
-
DEPENDENCIES
|
58
|
-
campfire-bot!
|
data/plugins/accountability.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
class Accountability < CampfireBot::Plugin
|
2
|
-
on_message /^\[INDAY/i, :save_speaker
|
3
|
-
at_interval 5.minutes, :keep_them_honest
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@accountable_people = []
|
7
|
-
end
|
8
|
-
|
9
|
-
def save_speaker(msg)
|
10
|
-
if msg[:room].name == accountability_room.name
|
11
|
-
puts "WE'RE IN!"
|
12
|
-
@accountable_people << strip_tags(msg[:person]) unless @accountable_people.include?(strip_tags(msg[:person]))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def keep_them_honest(msg)
|
17
|
-
if accountability_time?
|
18
|
-
unaccountable_people.each do |person|
|
19
|
-
@room.speak("#{person}: We haven't seen your INDAY today. So what's the plan?")
|
20
|
-
end
|
21
|
-
|
22
|
-
@accountable_people.clear
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def unaccountable_people
|
29
|
-
accountability_room.users.map { |u| strip_tags(u) } - @accountable_people - [bot.config['nickname']]
|
30
|
-
end
|
31
|
-
|
32
|
-
def accountability_room
|
33
|
-
@room ||= bot.rooms[bot.config['accountability_room']] || bot.rooms.first
|
34
|
-
end
|
35
|
-
|
36
|
-
def accountability_time?
|
37
|
-
# Once a day, sometime between 11:00 and 11:05.
|
38
|
-
now = Time.now
|
39
|
-
(Time.mktime(now.year, now.month, now.day, 11, 0)..Time.mktime(now.year, now.month, now.day, 11, 5)).include?(now)
|
40
|
-
end
|
41
|
-
|
42
|
-
def strip_tags(str)
|
43
|
-
str.gsub(/<\/?[^>]*>/, '').strip
|
44
|
-
end
|
45
|
-
end
|
data/plugins/austin.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'hpricot'
|
3
|
-
|
4
|
-
class Austin < CampfireBot::Plugin
|
5
|
-
BASE_URL = 'http://www.imdb.com/character/ch0002425/quotes'
|
6
|
-
|
7
|
-
on_command 'austin', :austin
|
8
|
-
|
9
|
-
def austin(msg)
|
10
|
-
doc = Hpricot(open(BASE_URL))
|
11
|
-
chunks = []
|
12
|
-
doc.traverse_element("br") {|b| chunks << b if b.next_node != nil && b.next_node.elem? && b.next_node.to_s == '<br />' }
|
13
|
-
chunks.pop
|
14
|
-
random_chunk = rand(chunks.size - 1)
|
15
|
-
raw_quote = chunks[random_chunk].nodes_at(2..(chunks[random_chunk + 1].node_position - chunks[random_chunk].node_position - 1))
|
16
|
-
quote = raw_quote.to_s
|
17
|
-
quote.gsub!(/(\\n)/, "")
|
18
|
-
quote.gsub!(/(<br \/>)/, "\n")
|
19
|
-
quote.gsub!(/^\s/, "")
|
20
|
-
quote.gsub!(/ {2,}/, " ")
|
21
|
-
quote.gsub!(/<\/?[^>]*>/, "")
|
22
|
-
quote.split("\n")
|
23
|
-
|
24
|
-
quote.each {|l| msg.speak l}
|
25
|
-
|
26
|
-
rescue
|
27
|
-
msg.speak 'Austin Powers: Yeah, baby, yeah'
|
28
|
-
end
|
29
|
-
end
|
data/plugins/basecamp.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'hpricot'
|
2
|
-
|
3
|
-
class Basecamp < CampfireBot::Plugin
|
4
|
-
on_command 'writeboard', :writeboard
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
# TODO find a better temp file name
|
8
|
-
@cookie_jar = BOT_ROOT + '/tmp/basecamp-cookies.txt'
|
9
|
-
@writeboard = bot.config['basecamp_writeboard_url']
|
10
|
-
@domain = @writeboard.split(/\/+/)[1]
|
11
|
-
@username = bot.config['basecamp_username']
|
12
|
-
@password = bot.config['basecamp_password']
|
13
|
-
@ssl = !!bot.config['basecamp_use_ssl']
|
14
|
-
end
|
15
|
-
|
16
|
-
def writeboard(msg)
|
17
|
-
msg.paste get_contents
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
# TODO escape stuff here. output = `#{Escape.shell_command(['figlet', '--', m[:message]])}`
|
23
|
-
def get_contents
|
24
|
-
# Prime the cookie jar: log in.
|
25
|
-
basecamp_login = `curl -c #{@cookie_jar} -b #{@cookie_jar} -d "user_name=#{@username}&password=#{@password}" -L http#{'s' if @ssl}://#{@domain}/login/authenticate`
|
26
|
-
|
27
|
-
# Fetch the contents of the writeboard redirect page
|
28
|
-
writeboard_redir = `curl -c #{@cookie_jar} -b #{@cookie_jar} -L #{@writeboard}`
|
29
|
-
|
30
|
-
# Simulate the javascripted login to the writeboard site
|
31
|
-
redir_form = Hpricot(writeboard_redir).search('form').first
|
32
|
-
writeboard_url = redir_form['action'].gsub(/\/login$/, '')
|
33
|
-
writeboard_author = bot.config['nickname']
|
34
|
-
writeboard_password = redir_form.search("input[@name='password']").first['value']
|
35
|
-
|
36
|
-
writeboard_login = `curl -c #{@cookie_jar} -b #{@cookie_jar} -d "author_name=#{writeboard_author}&password=#{writeboard_password}" -L #{redir_form['action']}`
|
37
|
-
|
38
|
-
# Now we can get the contents of the writeboard's page, which contains a link to the text export
|
39
|
-
writeboard_page = Hpricot(`curl -c #{@cookie_jar} -b #{@cookie_jar} -L #{writeboard_url}`)
|
40
|
-
|
41
|
-
export_link = 'http://123.writeboard.com' + writeboard_page.search("a[@href*='?format=txt']").first['href']
|
42
|
-
|
43
|
-
# Finally, grab the text export
|
44
|
-
writeboard_text = `curl -c #{@cookie_jar} -b #{@cookie_jar} #{export_link}`
|
45
|
-
|
46
|
-
return writeboard_text
|
47
|
-
end
|
48
|
-
end
|
data/plugins/beer.rb
DELETED
@@ -1,214 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
class Beer < CampfireBot::Plugin
|
4
|
-
|
5
|
-
# Beer::COMMAND_REGEXP = "^(?:!|#{bot.config['nickname']},\\s+)"
|
6
|
-
|
7
|
-
# Beer::GIVE_REGEXP = Regexp.new("#{Beer::COMMAND_REGEXP}([a-z\\s\\.]{4,12})([0-9]+)*", Regexp::IGNORECASE)
|
8
|
-
# Beer::CREDIT_REGEXP = //
|
9
|
-
# Beer::BALANCE_REGEXP = //
|
10
|
-
|
11
|
-
# on_message @debit_matcher, :respond
|
12
|
-
# on_message Regexp.new("#{CREDIT_REGEXP.source}", Regexp::IGNORECASE), :credit_cmd
|
13
|
-
on_command 'give_beer', :give_beer
|
14
|
-
on_command 'demand_beer', :demand_beer
|
15
|
-
on_command 'redeem_beer', :redeem_beer
|
16
|
-
on_command 'balance', :balance_cmd
|
17
|
-
|
18
|
-
# balances: {'josh' => {'party1' => 1 }, 'party1': '}
|
19
|
-
|
20
|
-
class BadArgumentException < Exception
|
21
|
-
end
|
22
|
-
|
23
|
-
def give_beer(msg)
|
24
|
-
give_or_demand_beer(msg, :give)
|
25
|
-
end
|
26
|
-
|
27
|
-
def demand_beer(msg)
|
28
|
-
give_or_demand_beer(msg, :demand)
|
29
|
-
end
|
30
|
-
|
31
|
-
def redeem_beer(msg)
|
32
|
-
give_or_demand_beer(msg, :redeem)
|
33
|
-
end
|
34
|
-
|
35
|
-
def balance_cmd(msg)
|
36
|
-
@balances = init()
|
37
|
-
begin
|
38
|
-
if msg[:message].empty?
|
39
|
-
return
|
40
|
-
# raise BadArgumentException.new, "Sorry, I don't know whom to #{trans_type_msg}"
|
41
|
-
end
|
42
|
-
|
43
|
-
speaker = msg[:person]
|
44
|
-
payee = msg[:message]
|
45
|
-
|
46
|
-
bal = balance(speaker, payee)
|
47
|
-
|
48
|
-
units = bal.abs == 1 ? "beer" : "beers"
|
49
|
-
|
50
|
-
if bal < 0
|
51
|
-
msg.speak("#{payee} owes you #{bal * -1} #{units}")
|
52
|
-
elsif bal > 0
|
53
|
-
msg.speak("You owe #{payee} #{bal} #{units}")
|
54
|
-
else
|
55
|
-
msg.speak("You and #{payee} are even")
|
56
|
-
end
|
57
|
-
|
58
|
-
rescue BadArgumentException => exception
|
59
|
-
msg.speak(exception.message)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
def give_or_demand_beer(msg, trans_type)
|
65
|
-
args = msg[:message].match(/(^[a-z\s\.\-]+?)(\s*\-*[0-9]*)$/i)
|
66
|
-
# puts "args = #{args.inspect}"
|
67
|
-
# puts "args[0] = #{args[0]}"
|
68
|
-
# puts "args[1] = #{args[1]}"
|
69
|
-
# puts "args[2] = #{args[2]}"
|
70
|
-
|
71
|
-
trans_type_msg = {:give => 'give beer to', :demand => 'demand beer from', :redeem => 'redeem beer from'}[trans_type]
|
72
|
-
|
73
|
-
begin
|
74
|
-
|
75
|
-
if args.nil?
|
76
|
-
raise BadArgumentException.new, "Sorry, I don't know whom to #{trans_type_msg}"
|
77
|
-
end
|
78
|
-
|
79
|
-
payee = args[1].strip
|
80
|
-
speaker = msg[:person]
|
81
|
-
|
82
|
-
if args[2] != "" and args[2].to_i == 0
|
83
|
-
raise BadArgumentException.new, "Sorry, I don't accept non-integer amounts"
|
84
|
-
end
|
85
|
-
|
86
|
-
amt = args[2] != "" ? args[2].to_i : 1
|
87
|
-
|
88
|
-
if amt <= 0
|
89
|
-
raise BadArgumentException.new, "Sorry, I don't accept negative numbers as an argument"
|
90
|
-
end
|
91
|
-
|
92
|
-
case trans_type
|
93
|
-
when :give
|
94
|
-
# no change - this is a debit
|
95
|
-
when :demand
|
96
|
-
amt = amt * -1 # this is a credit
|
97
|
-
when :redeem
|
98
|
-
# amt = amt * -1 # this is a credit
|
99
|
-
# no change - this is a debit
|
100
|
-
if bal = balance(speaker, payee) == 0
|
101
|
-
raise BadArgumentException.new, "#{payee} didn't owe you any beers to begin with."
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
beer_transaction(speaker, payee, amt)
|
106
|
-
|
107
|
-
bal = balance(speaker, payee)
|
108
|
-
|
109
|
-
# puts "post transaction balance = #{bal}"
|
110
|
-
if bal > 0
|
111
|
-
msg.speak("Okay, you now owe #{payee} #{bal} beers")
|
112
|
-
elsif bal < 0
|
113
|
-
msg.speak("Okay, #{payee} now owes you #{bal * -1} beers")
|
114
|
-
else
|
115
|
-
msg.speak("Okay, you and #{payee} are now even")
|
116
|
-
end
|
117
|
-
|
118
|
-
rescue BadArgumentException => exception
|
119
|
-
msg.speak(exception.message)
|
120
|
-
end
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
|
125
|
-
def beer_transaction(user1, user2, amount)
|
126
|
-
#beer_transaction user1, user2, 1 : user1 owes user2 a beer
|
127
|
-
#beer_transaction user1, user2, -1 : user1 demands a beer from user2 (user1 owes user2 -1 beers)
|
128
|
-
@balances = init()
|
129
|
-
# puts 'beer_transaction'
|
130
|
-
# p "beer_transaction start: #{@balances.inspect}"
|
131
|
-
# p "beer_transaction args: #{user1}, #{user2}, #{amount}"
|
132
|
-
user1 = user1.downcase.strip
|
133
|
-
user2 = user2.downcase.strip
|
134
|
-
|
135
|
-
if !@balances.key?(user1)
|
136
|
-
@balances[user1] = {}
|
137
|
-
end
|
138
|
-
|
139
|
-
if !@balances[user1].key?(user2)
|
140
|
-
@balances[user1][user2] = 0
|
141
|
-
end
|
142
|
-
|
143
|
-
@balances[user1][user2] += amount
|
144
|
-
|
145
|
-
# p "beer_transaction end: #{@balances.inspect}"
|
146
|
-
write
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
def balance(user1, user2)
|
153
|
-
# verb => user1 owes user2 #{balance} beers
|
154
|
-
# bal(user1, user2) = 1 # user1 is owed a beer from user2
|
155
|
-
# bal(user1, user2) = -1 # user1 is owed -1 beers from user 2 (meaning user2 owes user1)
|
156
|
-
|
157
|
-
@balances = init()
|
158
|
-
|
159
|
-
# puts "hash is #{hash}, @balances[#{hash}] = #{@balances[hash]}"
|
160
|
-
user1 = user1.downcase.strip
|
161
|
-
user2 = user2.downcase.strip
|
162
|
-
|
163
|
-
if @balances.key?(user1) and @balances[user1].key?(user2)
|
164
|
-
bal1 = @balances[user1][user2]
|
165
|
-
else
|
166
|
-
bal1 = 0
|
167
|
-
end
|
168
|
-
|
169
|
-
if @balances.key?(user2) and @balances[user2].key?(user1)
|
170
|
-
bal2 = @balances[user2][user1]
|
171
|
-
else
|
172
|
-
bal2 = 0
|
173
|
-
end
|
174
|
-
|
175
|
-
bal = bal1 - bal2
|
176
|
-
|
177
|
-
if (@balances.key?(user1) ? !@balances[user1].key?(user2) : true) and
|
178
|
-
(@balances.key?(user2) ? !@balances[user2].key?(user1) : true)
|
179
|
-
raise BadArgumentException.new, "Sorry, you don't have any beer transactions with anyone named #{user2}"
|
180
|
-
end
|
181
|
-
|
182
|
-
bal
|
183
|
-
end
|
184
|
-
|
185
|
-
def get_hash(user_1, user_2)
|
186
|
-
user1 = user_1.downcase
|
187
|
-
user2 = user_2.downcase
|
188
|
-
|
189
|
-
[user1,user2].sort.to_s
|
190
|
-
# if user1 < user2
|
191
|
-
# "#{user1}#{user2}"
|
192
|
-
# else
|
193
|
-
# "#{user2}#{user1}"
|
194
|
-
# end
|
195
|
-
end
|
196
|
-
|
197
|
-
def init
|
198
|
-
# puts "entering init()"
|
199
|
-
YAML::load(File.read(File.join(BOT_ROOT, 'tmp', 'beer.yml')))
|
200
|
-
end
|
201
|
-
|
202
|
-
def write
|
203
|
-
File.open(File.join(BOT_ROOT, 'tmp', 'beer.yml'), 'w') do |out|
|
204
|
-
YAML.dump(@balances, out)
|
205
|
-
end
|
206
|
-
|
207
|
-
end
|
208
|
-
|
209
|
-
def reload(msg)
|
210
|
-
@balances = init()
|
211
|
-
speak("ok, reloaded #{@balances.size} balances")
|
212
|
-
end
|
213
|
-
|
214
|
-
end
|
data/plugins/beijing_tally.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'hpricot'
|
3
|
-
|
4
|
-
class BeijingTally < CampfireBot::Plugin
|
5
|
-
|
6
|
-
on_command 'tally', :tally
|
7
|
-
|
8
|
-
def tally(msg)
|
9
|
-
output = "#{'Pos.'.rjust(6)} - #{'Country'.ljust(25)} - G - S - B - Total\n"
|
10
|
-
rows = ((Hpricot(open('http://results.beijing2008.cn/WRM/ENG/INF/GL/95A/GL0000000.shtml'))/'//table')[1]/'tr')[2..-1]
|
11
|
-
rows.each_with_index do |row, i|
|
12
|
-
cells = row/'td'
|
13
|
-
output += "#{strip_tags_or_zero(cells[0].inner_html).rjust(6)} - " # position
|
14
|
-
output += "#{((i == rows.length - 1) ? '' : strip_tags_or_zero(cells[1].inner_html)).ljust(25)} - " # country
|
15
|
-
output += "#{strip_tags_or_zero(cells[-5].inner_html).rjust(3)} - " # gold
|
16
|
-
output += "#{strip_tags_or_zero(cells[-4].inner_html).rjust(3)} - " # silver
|
17
|
-
output += "#{strip_tags_or_zero(cells[-3].inner_html).rjust(3)} - " # bronze
|
18
|
-
output += "#{strip_tags_or_zero(cells[-2].inner_html).rjust(3)}\n" # total
|
19
|
-
end
|
20
|
-
|
21
|
-
msg.paste(output)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
# Take away the HTML tags from the string and insert a '0' if it is empty
|
27
|
-
def strip_tags_or_zero(str)
|
28
|
-
(out = str.gsub(/<\/?[^>]*>/, "").strip).blank? ? '0' : out
|
29
|
-
end
|
30
|
-
end
|
data/plugins/boop.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
# TODO
|
2
|
-
#
|
3
|
-
# - convert/filter out HTML entities like "
|
4
|
-
# - add a callback to prime the chains when the bot is ready, and do this in a thread.
|
5
|
-
|
6
|
-
class Boop < CampfireBot::Plugin
|
7
|
-
|
8
|
-
# Markov chain implementation courtesy of http://blog.segment7.net/articles/2006/02/25/markov-chain
|
9
|
-
|
10
|
-
on_message /.*/, :listen
|
11
|
-
on_command 'speak', :random_chatter
|
12
|
-
on_command 'prime_chains', :load_transcripts
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@phrases = Hash.new { |hash, key| hash[key] = [] } # phrase => next-word possibilities
|
16
|
-
@word_count = 0
|
17
|
-
end
|
18
|
-
|
19
|
-
def listen(msg)
|
20
|
-
add_line(msg[:message])
|
21
|
-
end
|
22
|
-
|
23
|
-
def random_chatter(msg)
|
24
|
-
puts "random_chatter"
|
25
|
-
msg.speak(generate_line)
|
26
|
-
end
|
27
|
-
|
28
|
-
def focused_chatter(msg)
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def load_transcripts(msg)
|
33
|
-
msg.speak("Filling my brain with transcripts...")
|
34
|
-
|
35
|
-
puts "available transcripts - #{bot.room.available_transcripts.to_yaml}"
|
36
|
-
|
37
|
-
bot.room.available_transcripts.to_a.each do |date|
|
38
|
-
puts "loading transcript #{date}"
|
39
|
-
|
40
|
-
transcript = bot.room.transcript(date)
|
41
|
-
|
42
|
-
transcript.each do |message|
|
43
|
-
puts "message: #{message[:message]}"
|
44
|
-
|
45
|
-
filtered_text = strip_message(message)
|
46
|
-
|
47
|
-
filtered_text.split("\n").each { |line| add_line(line) unless line.blank? }
|
48
|
-
filtered_text.split("\n").each { |line| puts "ACCEPTED: " + line unless line.blank? }
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
msg.speak("Primed!")
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def add_line(line)
|
59
|
-
words = line.scan(/\S+/)
|
60
|
-
@word_count += words.length
|
61
|
-
|
62
|
-
words.each_with_index do |word, index|
|
63
|
-
phrase = words[index, phrase_length] # current phrase
|
64
|
-
@phrases[phrase] << words[index + phrase_length] # next possibility
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def generate_line
|
69
|
-
# our seed phrase
|
70
|
-
# phrase = words[0, phrase_length]
|
71
|
-
phrase = [random_word]
|
72
|
-
|
73
|
-
output = []
|
74
|
-
|
75
|
-
@word_count.times do
|
76
|
-
# grab all possibilities for our state
|
77
|
-
options = @phrases[phrase]
|
78
|
-
|
79
|
-
# add the first word to our output and discard
|
80
|
-
output << phrase.shift
|
81
|
-
|
82
|
-
# select at random and add it to our phrase
|
83
|
-
phrase.push(options.rand)
|
84
|
-
|
85
|
-
# the last phrase of the input text will map to an empty array of
|
86
|
-
# possibilities so exit cleanly.
|
87
|
-
break if phrase.compact.empty? # all out of words
|
88
|
-
end
|
89
|
-
|
90
|
-
# return our output
|
91
|
-
output.join(' ')
|
92
|
-
end
|
93
|
-
|
94
|
-
def random_word
|
95
|
-
@phrases.keys.rand.first
|
96
|
-
end
|
97
|
-
|
98
|
-
# amount of state (order-k)
|
99
|
-
def phrase_length
|
100
|
-
1
|
101
|
-
end
|
102
|
-
|
103
|
-
def strip_message(msg)
|
104
|
-
str = msg[:message].to_s
|
105
|
-
|
106
|
-
return '' if str.blank?
|
107
|
-
|
108
|
-
# return nothing if the line is a bot command
|
109
|
-
return '' if str[0..0] == '!' || str =~ Regexp.new("^#{bot.config['nickname']},", Regexp::IGNORECASE)
|
110
|
-
|
111
|
-
# and get rid of the messages that are generated by the campfire system itself
|
112
|
-
return '' if str =~ /has (entered|left) the room/
|
113
|
-
|
114
|
-
# keep the contents of the pastes, but strip out the 'view paste' link.
|
115
|
-
str.gsub!(/<a href=.*?>View paste<\/a>/, '')
|
116
|
-
|
117
|
-
# also get rid of the stuff spoken by the bot
|
118
|
-
return '' if msg[:person] == bot.config['nickname']
|
119
|
-
|
120
|
-
# now strip out all image tags completely
|
121
|
-
str.gsub!(/<img\s.*?\/>/, '')
|
122
|
-
|
123
|
-
# and now strip out all other html tags, leaving their contents intact
|
124
|
-
str.gsub(/<\/?[^>]*>/, "")
|
125
|
-
end
|
126
|
-
|
127
|
-
end
|