rbot 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
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
+