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,71 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ Net::HTTP.version_1_2
4
+
5
+ class WserverPlugin < Plugin
6
+ def help(plugin, topic="")
7
+ "wserver <uri> => try and determine what webserver <uri> is using"
8
+ end
9
+
10
+ def wserver(m, params)
11
+ redirect_count = 0
12
+ hostname = params[:host].dup
13
+ hostname = "http://#{hostname}" unless hostname =~ /:\/\//
14
+ begin
15
+ if(redirect_count > 3)
16
+ m.reply "cowardly refusing to follow more than 3 redirects"
17
+ return
18
+ end
19
+
20
+ begin
21
+ uri = URI.parse(hostname)
22
+ rescue URI::InvalidURIError => err
23
+ m.reply "#{hostname} is not a valid URI"
24
+ return
25
+ end
26
+
27
+ unless(uri)
28
+ m.reply "incorrect usage: " + help(m.plugin)
29
+ return
30
+ end
31
+
32
+ http = @bot.httputil.get_proxy(uri)
33
+ http.open_timeout = 5
34
+
35
+ http.start {|http|
36
+ resp = http.head('/')
37
+ server = resp['Server']
38
+ if(server && server.length > 0)
39
+ m.reply "#{uri.host} is running #{server}"
40
+ else
41
+ m.reply "couldn't tell what #{uri.host} is running"
42
+ end
43
+
44
+ if(resp.code == "302" || resp.code == "301")
45
+ newloc = resp['location']
46
+ newuri = URI.parse(newloc)
47
+ # detect and ignore incorrect redirects (to relative paths etc)
48
+ if (newuri.host != nil)
49
+ if(uri.host != newuri.host)
50
+ m.reply "#{uri.host} redirects to #{newuri.scheme}://#{newuri.host}"
51
+ raise resp['location']
52
+ end
53
+ end
54
+ end
55
+ }
56
+ rescue TimeoutError => err
57
+ m.reply "timed out connecting to #{uri.host}:#{uri.port} :("
58
+ return
59
+ rescue RuntimeError => err
60
+ redirect_count += 1
61
+ hostname = err.message
62
+ retry
63
+ rescue StandardError => err
64
+ puts err
65
+ m.reply "couldn't connect to #{uri.host}:#{uri.port} :("
66
+ return
67
+ end
68
+ end
69
+ end
70
+ plugin = WserverPlugin.new
71
+ plugin.map 'wserver :host'
@@ -0,0 +1,52 @@
1
+ require "xmlrpc/server"
2
+
3
+ class XmlRpcPlugin < Plugin
4
+
5
+ def port
6
+ @port = 8083
7
+ end
8
+
9
+ INTERFACE = XMLRPC::interface("rbot") {
10
+ meth 'string say(string)', 'Speak into the current channel', 'say'
11
+ }
12
+
13
+ def xmlrpc
14
+ @xmlrpc
15
+ end
16
+
17
+ def initialize
18
+ @xmlrpc = Thread.new {
19
+ @server = XMLRPC::Server.new(port)
20
+ @server.add_handler(XmlRpcPlugin::INTERFACE, self)
21
+ @server.serve
22
+ puts "here"
23
+ }
24
+
25
+ super()
26
+ end
27
+
28
+ def cleanup
29
+ puts "killing"
30
+ @server.shutdown
31
+ xmlrpc.kill
32
+ xmlrpc.join
33
+ end
34
+
35
+ def help(plugin, topic="")
36
+ "xmlrpc runs on port {#port}"
37
+ end
38
+
39
+ def say(msg)
40
+ m.reply msg
41
+ msg
42
+ end
43
+
44
+ def privmsg(m)
45
+ m.reply help(m.plugin)
46
+ end
47
+
48
+ end
49
+
50
+ plugin = XmlRpcPlugin.new
51
+ plugin.register("xmlrpc")
52
+ plugin.xmlrpc.run
@@ -0,0 +1,4 @@
1
+ lb<=is=>http://linuxbrit.co.uk
2
+ offended<=is=><reply><who> is offended!
3
+ giblet<=is=><reply>daddy!
4
+ rbot<=is=><reply>That's me! :-))
@@ -0,0 +1,98 @@
1
+ swaps <who>'s shampoo with nair
2
+ installs windows on <who>'s machine
3
+ forces <who> to use perl for 3 weeks
4
+ registers <who>'s name with 50 known spammers
5
+ resizes <who>'s terminal to 40x24
6
+ takes <who>'s tea
7
+ dispenses <who>'s email address to a few hundred 'bulk mailing services'
8
+ pokes <who> in the eye
9
+ beats <who> senseless with a 50lb Unix manual
10
+ cats /dev/urandom into <who>'s ear
11
+ signs <who> up for AOL
12
+ enrolls <who> in Visual Basic 101
13
+ sporks <who>
14
+ drops a truckload of VAXen on <who>
15
+ judo chops <who>
16
+ resizes <who>'s terminal to 40x24
17
+ formats <who>'s harddrive to fat12
18
+ rm -rf's <who>
19
+ stabs <who>
20
+ steals <who>'s mojo
21
+ strangles <who> with a doohicky mouse cord
22
+ whacks <who> with the cluebat
23
+ sells <who> on E-Bay
24
+ uses <who> as a biological warfare study
25
+ uses the "Customer Appreciation Bat" on <who>
26
+ reads <who> some vogon poetry
27
+ puts <who> in the Total Perspective Vortex
28
+ casts <who> into the fires of Mt. Doom
29
+ gives <who> a melvin
30
+ turns over <who> to Agent Smith to be "bugged"
31
+ takes away <who>'s internet connection
32
+ pushes <who> past the Shoe Event Horizon
33
+ counts "1, 2, 5... er... 3!" and hurls the Holy Handgrenade Of Antioch at <who>
34
+ puts <who> in a nest of camel spiders
35
+ makes <who> read slashdot at -1
36
+ puts "alias vim=emacs" in <who>'s /etc/profile
37
+ uninstalls ld from <who>'s system
38
+ locks <who> in the Chateau d'If
39
+ signs <who> up for getting hit on the head lessons
40
+ makes <who> try to set up a Lexmark printer
41
+ fills <who>'s Visene eyedrop bottle with lime juice
42
+ casts <who> into the fires of Mt. Doom.
43
+ gives <who> a Chicago Steamer
44
+ rips off <who>'s arm, and uses it to beat them to death
45
+ pierces <who>'s nose with a rusty paper hole puncher
46
+ pokes <who> with a rusty nail
47
+ puts sugar between <who>'s bedsheets
48
+ pours sand into <who>'s oatmeal
49
+ mixes epoxy into <who>'s toothpaste
50
+ puts Icy-Hot in <who>'s lip balm
51
+ straps <who> to a chair, and plays a endless low bitrate MP3 loop of "the world's most annoying sound" from "Dumb and Dumber"
52
+ tells Dr. Dre that <who> was talking smack
53
+ forces <who> to use a Commodore 64 for all their word processing
54
+ smacks <who> in the face with a burlap sack full of broken glass
55
+ puts <who> in a room with several heavily armed manic depressives
56
+ makes <who> watch reruns of "Blue's Clues"
57
+ puts lye in <who>'s coffee
58
+ tattoos the Windows symbol on <who>'s ass
59
+ lets Borg have his way with <who>
60
+ signs <who> up for line dancing classes at the local senior center
61
+ wakes <who> out of a sound sleep with some brand new nipple piercings
62
+ gives <who> a 2 guage Prince Albert
63
+ forces <who> to eat all their veggies
64
+ covers <who>'s toilet paper with lemon-pepper
65
+ fills <who>'s ketchup bottle with Dave's Insanity sauce
66
+ forces <who> to stare at an incredibly frustrating and seemingly neverending IRC political debate
67
+ knocks two of <who>'s teeth out with a 2x4
68
+ removes debian from <who>'s system
69
+ uses <who>'s debian cds for skeet shooting practice
70
+ gives <who>'s phone number to Borg
71
+ posts <who>'s IP and root password on alt.2600
72
+ forces <who> to use words like "irregardless" and "administrate" (thereby sounding like a real dumbass)"
73
+ tickles <who> until they wet their pants and pass out
74
+ replaces <who>'s KY with elmer's clear wood glue
75
+ replaces <who>'s TUMS with alka-seltzer tablets
76
+ squeezes habanero pepper juice into <who>'s tub of vaseline for <who>
77
+ submits <who>'s photo to the people at SA for photoshopping
78
+ Forces <who> to learn the Win32 API
79
+ gives <who> an atomic wedgie
80
+ ties <who> to a chair and forces them to listen to 'N Sync at full blast
81
+ forces <who> to use emacs for text editing
82
+ frowns at <who> really really hard
83
+ jabs a hot car lighter into <who>'s eye sockets
84
+ forces <who> to browse the web with IE
85
+ takes <who> out at the knees with a broken pool cue
86
+ forces <who> to listen to only emo music
87
+ signs <who> up for the Iowa State Ferret Legging Championship
88
+ attempts to hotswap <who>'s RAM
89
+ donkey punches <who>
90
+ puts track spikes into <who>'s side
91
+ replaces <who>'s Astroglide with JB Weld
92
+ replaces <who>'s hypertension pills with rat poison pellets
93
+ replaces <who>s jock itch cream with Nair
94
+ does the Australian Death Grip on <who>
95
+ dances upon the grave of <who>'s ancestors.
96
+ farts in <who>'s general direction
97
+ flogs <who> with stinging neddle
98
+ hands <who> a poison ivy joint
@@ -0,0 +1,5 @@
1
+ hugs <who>
2
+ gives <who> some love
3
+ gives <who> a cookie
4
+ slaps <who> heartily on the back
5
+ tickles <who>
@@ -0,0 +1,30 @@
1
+ 100 auth
2
+ 90 quit
3
+ 90 restart
4
+ 85 config
5
+ 80 nick
6
+ 80 nickserv
7
+ 80 qauth
8
+ 80 http
9
+ 70 opme
10
+ 70 mode
11
+ 70 say
12
+ 70 action
13
+ 40 quiet
14
+ 40 talk
15
+ 50 part
16
+ 50 hide
17
+ 50 join
18
+ 15 delquote
19
+ 12 msginsult
20
+ 12 remind_other
21
+ 5 rmlart
22
+ 5 rmpraise
23
+ 5 keycmd
24
+ 5 lart
25
+ 5 addlart
26
+ 5 addpraise
27
+ 5 remind
28
+ 5 keyword
29
+ 5 addquote
30
+ 5 getquote
@@ -0,0 +1 @@
1
+ 10 *!*@*
@@ -0,0 +1,203 @@
1
+ module Irc
2
+
3
+ # globmask:: glob to test with
4
+ # netmask:: netmask to test against
5
+ # Compare a netmask with a standard IRC glob, e.g foo!bar@baz.com would
6
+ # match *!*@baz.com, foo!*@*, *!bar@*, etc.
7
+ def Irc.netmaskmatch(globmask, netmask)
8
+ regmask = globmask.gsub(/\*/, ".*?")
9
+ return true if(netmask =~ /#{regmask}/)
10
+ return false
11
+ end
12
+
13
+ # check if a string is an actual IRC hostmask
14
+ def Irc.ismask(mask)
15
+ mask =~ /^.+!.+@.+$/
16
+ end
17
+
18
+
19
+ # User-level authentication to allow/disallow access to bot commands based
20
+ # on hostmask and userlevel.
21
+ class IrcAuth
22
+ BotConfig.register BotConfigStringValue.new('auth.password',
23
+ :default => "rbotauth", :wizard => true,
24
+ :desc => "Your password for maxing your auth with the bot (used to associate new hostmasks with your owner-status etc)")
25
+
26
+ # create a new IrcAuth instance.
27
+ # bot:: associated bot class
28
+ def initialize(bot)
29
+ @bot = bot
30
+ @users = Hash.new(0)
31
+ @levels = Hash.new(0)
32
+ if(File.exist?("#{@bot.botclass}/users.rbot"))
33
+ IO.foreach("#{@bot.botclass}/users.rbot") do |line|
34
+ if(line =~ /\s*(\d+)\s*(\S+)/)
35
+ level = $1.to_i
36
+ mask = $2
37
+ @users[mask] = level
38
+ end
39
+ end
40
+ end
41
+ if(File.exist?("#{@bot.botclass}/levels.rbot"))
42
+ IO.foreach("#{@bot.botclass}/levels.rbot") do |line|
43
+ if(line =~ /\s*(\d+)\s*(\S+)/)
44
+ level = $1.to_i
45
+ command = $2
46
+ @levels[command] = level
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # save current users and levels to files.
53
+ # levels are written to #{botclass}/levels.rbot
54
+ # users are written to #{botclass}/users.rbot
55
+ def save
56
+ Dir.mkdir("#{@bot.botclass}") if(!File.exist?("#{@bot.botclass}"))
57
+ File.open("#{@bot.botclass}/users.rbot", "w") do |file|
58
+ @users.each do |key, value|
59
+ file.puts "#{value} #{key}"
60
+ end
61
+ end
62
+ File.open("#{@bot.botclass}/levels.rbot", "w") do |file|
63
+ @levels.each do |key, value|
64
+ file.puts "#{value} #{key}"
65
+ end
66
+ end
67
+ end
68
+
69
+ # command:: command user wishes to perform
70
+ # mask:: hostmask of user
71
+ # tell:: optional recipient for "insufficient auth" message
72
+ #
73
+ # returns true if user with hostmask +mask+ is permitted to perform
74
+ # +command+ optionally pass tell as the target for the "insufficient auth"
75
+ # message, if the user is not authorised
76
+ def allow?(command, mask, tell=nil)
77
+ auth = userlevel(mask)
78
+ if(auth >= @levels[command])
79
+ return true
80
+ else
81
+ debug "#{mask} is not allowed to perform #{command}"
82
+ @bot.say tell, "insufficient \"#{command}\" auth (have #{auth}, need #{@levels[command]})" if tell
83
+ return false
84
+ end
85
+ end
86
+
87
+ # add user with hostmask matching +mask+ with initial auth level +level+
88
+ def useradd(mask, level)
89
+ if(Irc.ismask(mask))
90
+ @users[mask] = level
91
+ end
92
+ end
93
+
94
+ # mask:: mask of user to remove
95
+ # remove user with mask +mask+
96
+ def userdel(mask)
97
+ if(Irc.ismask(mask))
98
+ @users.delete(mask)
99
+ end
100
+ end
101
+
102
+ # command:: command to adjust
103
+ # level:: new auth level for the command
104
+ # set required auth level of +command+ to +level+
105
+ def setlevel(command, level)
106
+ @levels[command] = level
107
+ end
108
+
109
+ # specific users.
110
+ # mask:: mask of user
111
+ # returns the authlevel of user with mask +mask+
112
+ # finds the matching user which has the highest authlevel (so you can have
113
+ # a default level of 5 for *!*@*, and yet still give higher levels to
114
+ def userlevel(mask)
115
+ # go through hostmask list, find match with _highest_ level (all users
116
+ # will match *!*@*)
117
+ level = 0
118
+ @users.each {|user,userlevel|
119
+ if(Irc.netmaskmatch(user, mask))
120
+ level = userlevel if userlevel > level
121
+ end
122
+ }
123
+ level
124
+ end
125
+
126
+ # return all currently defined commands (for which auth is required) and
127
+ # their required authlevels
128
+ def showlevels
129
+ reply = "Current levels are:"
130
+ @levels.sort.each {|a|
131
+ key = a[0]
132
+ value = a[1]
133
+ reply += " #{key}(#{value})"
134
+ }
135
+ reply
136
+ end
137
+
138
+ # return all currently defined users and their authlevels
139
+ def showusers
140
+ reply = "Current users are:"
141
+ @users.sort.each {|a|
142
+ key = a[0]
143
+ value = a[1]
144
+ reply += " #{key}(#{value})"
145
+ }
146
+ reply
147
+ end
148
+
149
+ # module help
150
+ def help(topic="")
151
+ case topic
152
+ when "setlevel"
153
+ return "setlevel <command> <level> => Sets required level for <command> to <level> (private addressing only)"
154
+ when "useradd"
155
+ return "useradd <mask> <level> => Add user <mask> at level <level> (private addressing only)"
156
+ when "userdel"
157
+ return "userdel <mask> => Remove user <mask> (private addressing only)"
158
+ when "auth"
159
+ return "auth <masterpw> => Recognise your hostmask as bot master (private addressing only)"
160
+ when "levels"
161
+ return "levels => list commands and their required levels (private addressing only)"
162
+ when "users"
163
+ return "users => list users and their levels (private addressing only)"
164
+ else
165
+ return "Auth module (User authentication) topics: setlevel, useradd, userdel, auth, levels, users"
166
+ end
167
+ end
168
+
169
+ # privmsg handler
170
+ def privmsg(m)
171
+ if(m.address? && m.private?)
172
+ case m.message
173
+ when (/^setlevel\s+(\S+)\s+(\d+)$/)
174
+ if(@bot.auth.allow?("auth", m.source, m.replyto))
175
+ @bot.auth.setlevel($1, $2.to_i)
176
+ m.reply "level for #$1 set to #$2"
177
+ end
178
+ when (/^useradd\s+(\S+)\s+(\d+)/)
179
+ if(@bot.auth.allow?("auth", m.source, m.replyto))
180
+ @bot.auth.useradd($1, $2.to_i)
181
+ m.reply "added user #$1 at level #$2"
182
+ end
183
+ when (/^userdel\s+(\S+)/)
184
+ if(@bot.auth.allow?("auth", m.source, m.replyto))
185
+ @bot.auth.userdel($1)
186
+ m.reply "user #$1 is gone"
187
+ end
188
+ when (/^auth\s+(\S+)/)
189
+ if($1 == @bot.config["auth.password"])
190
+ @bot.auth.useradd(Regexp.escape(m.source), 1000)
191
+ m.reply "Identified, security level maxed out"
192
+ else
193
+ m.reply "incorrect password"
194
+ end
195
+ when ("levels")
196
+ m.reply @bot.auth.showlevels if(@bot.auth.allow?("config", m.source, m.replyto))
197
+ when ("users")
198
+ m.reply @bot.auth.showusers if(@bot.auth.allow?("config", m.source, m.replyto))
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end