rbot 0.9.9

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 (76) hide show
  1. data/AUTHORS +16 -0
  2. data/COPYING +21 -0
  3. data/ChangeLog +418 -0
  4. data/INSTALL +8 -0
  5. data/README +44 -0
  6. data/REQUIREMENTS +34 -0
  7. data/TODO +5 -0
  8. data/Usage_en.txt +129 -0
  9. data/bin/rbot +81 -0
  10. data/data/rbot/contrib/plugins/figlet.rb +20 -0
  11. data/data/rbot/contrib/plugins/ri.rb +83 -0
  12. data/data/rbot/contrib/plugins/stats.rb +232 -0
  13. data/data/rbot/contrib/plugins/vandale.rb +49 -0
  14. data/data/rbot/languages/dutch.lang +73 -0
  15. data/data/rbot/languages/english.lang +75 -0
  16. data/data/rbot/languages/french.lang +39 -0
  17. data/data/rbot/languages/german.lang +67 -0
  18. data/data/rbot/plugins/autoop.rb +68 -0
  19. data/data/rbot/plugins/autorejoin.rb +16 -0
  20. data/data/rbot/plugins/cal.rb +15 -0
  21. data/data/rbot/plugins/dice.rb +81 -0
  22. data/data/rbot/plugins/eightball.rb +19 -0
  23. data/data/rbot/plugins/excuse.rb +470 -0
  24. data/data/rbot/plugins/fish.rb +61 -0
  25. data/data/rbot/plugins/fortune.rb +22 -0
  26. data/data/rbot/plugins/freshmeat.rb +98 -0
  27. data/data/rbot/plugins/google.rb +51 -0
  28. data/data/rbot/plugins/host.rb +14 -0
  29. data/data/rbot/plugins/httpd.rb.disabled +35 -0
  30. data/data/rbot/plugins/insult.rb +258 -0
  31. data/data/rbot/plugins/karma.rb +85 -0
  32. data/data/rbot/plugins/lart.rb +181 -0
  33. data/data/rbot/plugins/math.rb +122 -0
  34. data/data/rbot/plugins/nickserv.rb +89 -0
  35. data/data/rbot/plugins/nslookup.rb +43 -0
  36. data/data/rbot/plugins/opme.rb +19 -0
  37. data/data/rbot/plugins/quakeauth.rb +51 -0
  38. data/data/rbot/plugins/quotes.rb +321 -0
  39. data/data/rbot/plugins/remind.rb +228 -0
  40. data/data/rbot/plugins/roshambo.rb +54 -0
  41. data/data/rbot/plugins/rot13.rb +10 -0
  42. data/data/rbot/plugins/roulette.rb +147 -0
  43. data/data/rbot/plugins/rss.rb.disabled +414 -0
  44. data/data/rbot/plugins/seen.rb +89 -0
  45. data/data/rbot/plugins/slashdot.rb +94 -0
  46. data/data/rbot/plugins/spell.rb +36 -0
  47. data/data/rbot/plugins/tube.rb +71 -0
  48. data/data/rbot/plugins/url.rb +88 -0
  49. data/data/rbot/plugins/weather.rb +649 -0
  50. data/data/rbot/plugins/wserver.rb +71 -0
  51. data/data/rbot/plugins/xmlrpc.rb.disabled +52 -0
  52. data/data/rbot/templates/keywords.rbot +4 -0
  53. data/data/rbot/templates/lart/larts +98 -0
  54. data/data/rbot/templates/lart/praises +5 -0
  55. data/data/rbot/templates/levels.rbot +30 -0
  56. data/data/rbot/templates/users.rbot +1 -0
  57. data/lib/rbot/auth.rb +203 -0
  58. data/lib/rbot/channel.rb +54 -0
  59. data/lib/rbot/config.rb +363 -0
  60. data/lib/rbot/dbhash.rb +112 -0
  61. data/lib/rbot/httputil.rb +141 -0
  62. data/lib/rbot/ircbot.rb +808 -0
  63. data/lib/rbot/ircsocket.rb +185 -0
  64. data/lib/rbot/keywords.rb +433 -0
  65. data/lib/rbot/language.rb +69 -0
  66. data/lib/rbot/message.rb +256 -0
  67. data/lib/rbot/messagemapper.rb +262 -0
  68. data/lib/rbot/plugins.rb +291 -0
  69. data/lib/rbot/post-install.rb +8 -0
  70. data/lib/rbot/rbotconfig.rb +36 -0
  71. data/lib/rbot/registry.rb +271 -0
  72. data/lib/rbot/rfc2812.rb +1104 -0
  73. data/lib/rbot/timer.rb +201 -0
  74. data/lib/rbot/utils.rb +83 -0
  75. data/setup.rb +1360 -0
  76. metadata +129 -0
@@ -0,0 +1,61 @@
1
+ require 'net/http'
2
+ require 'uri/common'
3
+ Net::HTTP.version_1_2
4
+
5
+ class BabelPlugin < Plugin
6
+ def help(plugin, topic="")
7
+ "translate to <lang> <string> => translate from english to <lang>, translate from <lang> <string> => translate to english from <lang>, translate <fromlang> <tolang> <string> => translate from <fromlang> to <tolang>. Languages: en, fr, de, it, pt, es, nl"
8
+ end
9
+ def translate(m, params)
10
+ langs = ["en", "fr", "de", "it", "pt", "es", "nl"]
11
+ trans_from = params[:fromlang] ? params[:fromlang] : 'en'
12
+ trans_to = params[:tolang] ? params[:tolang] : 'en'
13
+ trans_text = params[:phrase].to_s
14
+
15
+ query = "/babelfish/tr"
16
+ lang_match = langs.join("|")
17
+ unless(trans_from =~ /^(#{lang_match})$/ && trans_to =~ /^(#{lang_match})$/)
18
+ m.reply "invalid language: valid languagess are: #{langs.join(' ')}"
19
+ return
20
+ end
21
+
22
+ data_text = URI.escape trans_text
23
+ trans_pair = "#{trans_from}_#{trans_to}"
24
+ data = "lp=#{trans_pair}&doit=done&intl=1&tt=urltext&urltext=#{data_text}"
25
+
26
+ # check cache for previous lookups
27
+ if @registry.has_key?("#{trans_pair}/#{data_text}")
28
+ m.reply @registry["#{trans_pair}/#{data_text}"]
29
+ return
30
+ end
31
+
32
+ http = @bot.httputil.get_proxy(URI.parse("http://babelfish.altavista.com"))
33
+
34
+ http.start {|http|
35
+ resp = http.post(query, data, {"content-type",
36
+ "application/x-www-form-urlencoded"})
37
+
38
+ if (resp.code == "200")
39
+ resp.body.each_line do |l|
40
+ if(l =~ /^\s+<td bgcolor=white class=s><div style=padding:10px;>(.*)<\/div>/)
41
+ answer = $1
42
+ # cache the answer
43
+ if(answer.length > 0)
44
+ @registry["#{trans_pair}/#{data_text}"] = answer
45
+ end
46
+ m.reply answer
47
+ return
48
+ end
49
+ end
50
+ m.reply "couldn't parse babelfish response html :("
51
+ else
52
+ m.reply "couldn't talk to babelfish :("
53
+ end
54
+ }
55
+ end
56
+ end
57
+ plugin = BabelPlugin.new
58
+ plugin.map 'translate to :tolang *phrase'
59
+ plugin.map 'translate from :fromlang *phrase'
60
+ plugin.map 'translate :fromlang :tolang *phrase'
61
+
@@ -0,0 +1,22 @@
1
+ class FortunePlugin < Plugin
2
+ def help(plugin, topic="")
3
+ "fortune [<module>] => get a (short) fortune, optionally specifying fortune db"
4
+ end
5
+ def fortune(m, params)
6
+ db = params[:db]
7
+ fortune = nil
8
+ ["/usr/games/fortune", "/usr/bin/fortune", "/usr/local/bin/fortune"].each {|f|
9
+ if FileTest.executable? f
10
+ fortune = f
11
+ break
12
+ end
13
+ }
14
+ m.reply "fortune binary not found" unless fortune
15
+ ret = Utils.safe_exec(fortune, "-n", "255", "-s", db)
16
+ m.reply ret.gsub(/\t/, " ").split(/\n/).join(" ")
17
+ return
18
+ end
19
+ end
20
+ plugin = FortunePlugin.new
21
+ plugin.map 'fortune :db', :defaults => {:db => 'fortunes'},
22
+ :requirements => {:db => /^[^-][\w-]+$/}
@@ -0,0 +1,98 @@
1
+ require 'rexml/document'
2
+ require 'uri/common'
3
+
4
+ class FreshmeatPlugin < Plugin
5
+ include REXML
6
+ def help(plugin, topic="")
7
+ "freshmeat search [<max>=4] <string> => search freshmeat for <string>, freshmeat [<max>=4] => return up to <max> freshmeat headlines"
8
+ end
9
+
10
+ def search_freshmeat(m, params)
11
+ max = params[:limit].to_i
12
+ search = params[:search].to_s
13
+ max = 8 if max > 8
14
+ begin
15
+ xml = @bot.httputil.get(URI.parse("http://freshmeat.net/search-xml/?orderby=locate_projectname_full_DESC&q=#{URI.escape(search)}"))
16
+ rescue URI::InvalidURIError, URI::BadURIError => e
17
+ m.reply "illegal search string #{search}"
18
+ return
19
+ end
20
+ unless xml
21
+ m.reply "search for #{search} failed"
22
+ return
23
+ end
24
+ doc = Document.new xml
25
+ unless doc
26
+ m.reply "search for #{search} failed"
27
+ return
28
+ end
29
+ matches = Array.new
30
+ max_width = 250
31
+ title_width = 0
32
+ url_width = 0
33
+ done = 0
34
+ doc.elements.each("*/match") {|e|
35
+ name = e.elements["projectname_short"].text
36
+ url = "http://freshmeat.net/projects/#{name}/"
37
+ desc = e.elements["desc_short"].text
38
+ title = e.elements["projectname_full"].text
39
+ #title_width = title.length if title.length > title_width
40
+ url_width = url.length if url.length > url_width
41
+ matches << [title, url, desc]
42
+ done += 1
43
+ break if done >= max
44
+ }
45
+ if matches.length == 0
46
+ m.reply "not found: #{search}"
47
+ end
48
+ matches.each {|mat|
49
+ title = mat[0]
50
+ url = mat[1]
51
+ desc = mat[2]
52
+ desc.gsub!(/(.{#{max_width - 3 - url_width}}).*/, '\1..')
53
+ reply = sprintf("%s | %s", url.ljust(url_width), desc)
54
+ m.reply reply
55
+ }
56
+ end
57
+
58
+ def freshmeat(m, params)
59
+ max = params[:limit].to_i
60
+ max = 8 if max > 8
61
+ xml = @bot.httputil.get(URI.parse("http://images.feedstermedia.com/feedcache/ostg/freshmeat/fm-releases-global.xml"))
62
+ unless xml
63
+ m.reply "freshmeat news parse failed"
64
+ return
65
+ end
66
+ doc = Document.new xml
67
+ unless doc
68
+ m.reply "freshmeat news parse failed"
69
+ return
70
+ end
71
+ matches = Array.new
72
+ max_width = 60
73
+ title_width = 0
74
+ done = 0
75
+ doc.elements.each("*/channel/item") {|e|
76
+ desc = e.elements["description"].text
77
+ title = e.elements["title"].text
78
+ #title.gsub!(/\s+\(.*\)\s*$/, "")
79
+ title.strip!
80
+ title_width = title.length if title.length > title_width
81
+ matches << [title, desc]
82
+ done += 1
83
+ break if done >= max
84
+ }
85
+ matches.each {|mat|
86
+ title = mat[0]
87
+ #desc = mat[1]
88
+ #desc.gsub!(/(.{#{max_width - 3 - title_width}}).*/, '\1..')
89
+ #reply = sprintf("%#{title_width}s | %s", title, desc)
90
+ m.reply title
91
+ }
92
+ end
93
+ end
94
+ plugin = FreshmeatPlugin.new
95
+ plugin.map 'freshmeat search :limit *search', :action => 'search_freshmeat',
96
+ :defaults => {:limit => 4}, :requirements => {:limit => /^\d+$/}
97
+ plugin.map 'freshmeat :limit', :defaults => {:limit => 4},
98
+ :requirements => {:limit => /^\d+$/}
@@ -0,0 +1,51 @@
1
+ require 'net/http'
2
+ require 'uri/common'
3
+
4
+ Net::HTTP.version_1_2
5
+
6
+ class GooglePlugin < Plugin
7
+ def help(plugin, topic="")
8
+ "search <string> => search google for <string>"
9
+ end
10
+ def privmsg(m)
11
+ unless(m.params && m.params.length > 0)
12
+ m.reply "incorrect usage: " + help(m.plugin)
13
+ return
14
+ end
15
+ searchfor = URI.escape m.params
16
+
17
+ query = "/search?q=#{searchfor}&btnI=I%27m%20feeling%20lucky"
18
+ result = "not found!"
19
+
20
+ proxy_host = nil
21
+ proxy_port = nil
22
+
23
+ if(ENV['http_proxy'])
24
+ if(ENV['http_proxy'] =~ /^http:\/\/(.+):(\d+)$/)
25
+ proxy_host = $1
26
+ proxy_port = $2
27
+ end
28
+ end
29
+
30
+ http = @bot.httputil.get_proxy(URI.parse("http://www.google.com"))
31
+
32
+ begin
33
+ http.start {|http|
34
+ resp = http.get(query)
35
+ if resp.code == "302"
36
+ result = resp['location']
37
+ end
38
+ }
39
+ rescue => e
40
+ p e
41
+ if e.response && e.response['location']
42
+ result = e.response['location']
43
+ else
44
+ result = "error!"
45
+ end
46
+ end
47
+ m.reply "#{m.params}: #{result}"
48
+ end
49
+ end
50
+ plugin = GooglePlugin.new
51
+ plugin.register("search")
@@ -0,0 +1,14 @@
1
+ class HostPlugin < Plugin
2
+ def help(plugin, topic="")
3
+ "host <domain> => query nameserver about domain names and zones for <domain>"
4
+ end
5
+ def privmsg(m)
6
+ unless(m.params =~ /^(\w|-|\.)+$/)
7
+ m.reply "incorrect usage: " + help(m.plugin)
8
+ return
9
+ end
10
+ m.reply Utils.safe_exec("host", m.params)
11
+ end
12
+ end
13
+ plugin = HostPlugin.new
14
+ plugin.register("host")
@@ -0,0 +1,35 @@
1
+ require 'webrick'
2
+
3
+ class HttpPlugin < Plugin
4
+ include WEBrick
5
+
6
+
7
+ def initialize
8
+ super
9
+ @http_server = HTTPServer.new(
10
+ :Port => 5555
11
+ )
12
+ @http_server.mount_proc("/") { |req, resp|
13
+ resp['content-type'] = 'text/html'
14
+ resp.body = "<html><head><title>rbot httpd plugin</title></head><body>"
15
+ resp.body += "#{@bot.status} <br />"
16
+ resp.body += "hello from rbot."
17
+ resp.body += "</body>"
18
+ raise HTTPStatus::OK
19
+ }
20
+ Thread.new {
21
+ @http_server.start
22
+ }
23
+ end
24
+ def cleanup
25
+ @http_server.shutdown
26
+ end
27
+ def help(plugin, topic="")
28
+ "no help yet"
29
+ end
30
+ def privmsg(m)
31
+ end
32
+ end
33
+
34
+ plugin = HttpPlugin.new
35
+ plugin.register("http")
@@ -0,0 +1,258 @@
1
+ class InsultPlugin < Plugin
2
+
3
+ ## insults courtesy of http://insulthost.colorado.edu/
4
+
5
+ ##
6
+ # Adjectives
7
+ ##
8
+ @@adj = [
9
+ "acidic",
10
+ "antique",
11
+ "contemptible",
12
+ "culturally-unsound",
13
+ "despicable",
14
+ "evil",
15
+ "fermented",
16
+ "festering",
17
+ "foul",
18
+ "fulminating",
19
+ "humid",
20
+ "impure",
21
+ "inept",
22
+ "inferior",
23
+ "industrial",
24
+ "left-over",
25
+ "low-quality",
26
+ "malodorous",
27
+ "off-color",
28
+ "penguin-molesting",
29
+ "petrified",
30
+ "pointy-nosed",
31
+ "salty",
32
+ "sausage-snorfling",
33
+ "tastless",
34
+ "tempestuous",
35
+ "tepid",
36
+ "tofu-nibbling",
37
+ "unintelligent",
38
+ "unoriginal",
39
+ "uninspiring",
40
+ "weasel-smelling",
41
+ "wretched",
42
+ "spam-sucking",
43
+ "egg-sucking",
44
+ "decayed",
45
+ "halfbaked",
46
+ "infected",
47
+ "squishy",
48
+ "porous",
49
+ "pickled",
50
+ "coughed-up",
51
+ "thick",
52
+ "vapid",
53
+ "hacked-up",
54
+ "unmuzzled",
55
+ "bawdy",
56
+ "vain",
57
+ "lumpish",
58
+ "churlish",
59
+ "fobbing",
60
+ "rank",
61
+ "craven",
62
+ "puking",
63
+ "jarring",
64
+ "fly-bitten",
65
+ "pox-marked",
66
+ "fen-sucked",
67
+ "spongy",
68
+ "droning",
69
+ "gleeking",
70
+ "warped",
71
+ "currish",
72
+ "milk-livered",
73
+ "surly",
74
+ "mammering",
75
+ "ill-borne",
76
+ "beef-witted",
77
+ "tickle-brained",
78
+ "half-faced",
79
+ "headless",
80
+ "wayward",
81
+ "rump-fed",
82
+ "onion-eyed",
83
+ "beslubbering",
84
+ "villainous",
85
+ "lewd-minded",
86
+ "cockered",
87
+ "full-gorged",
88
+ "rude-snouted",
89
+ "crook-pated",
90
+ "pribbling",
91
+ "dread-bolted",
92
+ "fool-born",
93
+ "puny",
94
+ "fawning",
95
+ "sheep-biting",
96
+ "dankish",
97
+ "goatish",
98
+ "weather-bitten",
99
+ "knotty-pated",
100
+ "malt-wormy",
101
+ "saucyspleened",
102
+ "motley-mind",
103
+ "it-fowling",
104
+ "vassal-willed",
105
+ "loggerheaded",
106
+ "clapper-clawed",
107
+ "frothy",
108
+ "ruttish",
109
+ "clouted",
110
+ "common-kissing",
111
+ "pignutted",
112
+ "folly-fallen",
113
+ "plume-plucked",
114
+ "flap-mouthed",
115
+ "swag-bellied",
116
+ "dizzy-eyed",
117
+ "gorbellied",
118
+ "weedy",
119
+ "reeky",
120
+ "measled",
121
+ "spur-galled",
122
+ "mangled",
123
+ "impertinent",
124
+ "bootless",
125
+ "toad-spotted",
126
+ "hasty-witted",
127
+ "horn-beat",
128
+ "yeasty",
129
+ "boil-brained",
130
+ "tottering",
131
+ "hedge-born",
132
+ "hugger-muggered",
133
+ "elf-skinned",
134
+ ]
135
+
136
+ ##
137
+ # Amounts
138
+ ##
139
+ @@amt = [
140
+ "accumulation",
141
+ "bucket",
142
+ "coagulation",
143
+ "enema-bucketful",
144
+ "gob",
145
+ "half-mouthful",
146
+ "heap",
147
+ "mass",
148
+ "mound",
149
+ "petrification",
150
+ "pile",
151
+ "puddle",
152
+ "stack",
153
+ "thimbleful",
154
+ "tongueful",
155
+ "ooze",
156
+ "quart",
157
+ "bag",
158
+ "plate",
159
+ "ass-full",
160
+ "assload",
161
+ ]
162
+
163
+ ##
164
+ # Objects
165
+ ##
166
+ @@noun = [
167
+ "bat toenails",
168
+ "bug spit",
169
+ "cat hair",
170
+ "chicken piss",
171
+ "dog vomit",
172
+ "dung",
173
+ "fat-woman's stomach-bile",
174
+ "fish heads",
175
+ "guano",
176
+ "gunk",
177
+ "pond scum",
178
+ "rat retch",
179
+ "red dye number-9",
180
+ "Sun IPC manuals",
181
+ "waffle-house grits",
182
+ "yoo-hoo",
183
+ "dog balls",
184
+ "seagull puke",
185
+ "cat bladders",
186
+ "pus",
187
+ "urine samples",
188
+ "squirrel guts",
189
+ "snake assholes",
190
+ "snake bait",
191
+ "buzzard gizzards",
192
+ "cat-hair-balls",
193
+ "rat-farts",
194
+ "pods",
195
+ "armadillo snouts",
196
+ "entrails",
197
+ "snake snot",
198
+ "eel ooze",
199
+ "slurpee-backwash",
200
+ "toxic waste",
201
+ "Stimpy-drool",
202
+ "poopy",
203
+ "poop",
204
+ "craptacular carpet droppings",
205
+ "jizzum",
206
+ "cold sores",
207
+ "anal warts",
208
+ ]
209
+
210
+ def help(plugin, topic="")
211
+ if(plugin == "insult")
212
+ return "insult me|<person> => insult you or <person>"
213
+ elsif(plugin == "msginsult")
214
+ return "msginsult <nick> => insult <nick> via /msg"
215
+ else
216
+ return "insult module topics: msginsult, insult"
217
+ end
218
+ end
219
+ def privmsg(m)
220
+ suffix=""
221
+ unless(m.params)
222
+ m.reply "incorrect usage: " + help(m.plugin)
223
+ return
224
+ end
225
+ msgto = m.channel
226
+ if(m.plugin =~ /^msginsult$/)
227
+ prefix = "you are "
228
+ if (m.params =~ /^#/)
229
+ prefix += "all "
230
+ end
231
+ msgto = m.params
232
+ suffix = " (from #{m.sourcenick})"
233
+ elsif(m.params =~ /^me$/)
234
+ prefix = "you are "
235
+ else
236
+ prefix = "#{m.params} is "
237
+ end
238
+ insult = generate_insult
239
+ @bot.say msgto, prefix + insult + suffix
240
+ end
241
+ def generate_insult
242
+ adj = @@adj[rand(@@adj.length)]
243
+ adj2 = ""
244
+ loop do
245
+ adj2 = @@adj[rand(@@adj.length)]
246
+ break if adj2 != adj
247
+ end
248
+ amt = @@amt[rand(@@amt.length)]
249
+ noun = @@noun[rand(@@noun.length)]
250
+ start = "a "
251
+ start = "an " if ['a','e','i','o','u'].include?(adj[0].chr)
252
+ "#{start}#{adj} #{amt} of #{adj2} #{noun}"
253
+ end
254
+ end
255
+ plugin = InsultPlugin.new
256
+ plugin.register("insult")
257
+ plugin.register("msginsult")
258
+