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.
@@ -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
@@ -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!
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,127 +0,0 @@
1
- # TODO
2
- #
3
- # - convert/filter out HTML entities like &quot;
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