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,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