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.
- data/AUTHORS +16 -0
- data/COPYING +21 -0
- data/ChangeLog +418 -0
- data/INSTALL +8 -0
- data/README +44 -0
- data/REQUIREMENTS +34 -0
- data/TODO +5 -0
- data/Usage_en.txt +129 -0
- data/bin/rbot +81 -0
- data/data/rbot/contrib/plugins/figlet.rb +20 -0
- data/data/rbot/contrib/plugins/ri.rb +83 -0
- data/data/rbot/contrib/plugins/stats.rb +232 -0
- data/data/rbot/contrib/plugins/vandale.rb +49 -0
- data/data/rbot/languages/dutch.lang +73 -0
- data/data/rbot/languages/english.lang +75 -0
- data/data/rbot/languages/french.lang +39 -0
- data/data/rbot/languages/german.lang +67 -0
- data/data/rbot/plugins/autoop.rb +68 -0
- data/data/rbot/plugins/autorejoin.rb +16 -0
- data/data/rbot/plugins/cal.rb +15 -0
- data/data/rbot/plugins/dice.rb +81 -0
- data/data/rbot/plugins/eightball.rb +19 -0
- data/data/rbot/plugins/excuse.rb +470 -0
- data/data/rbot/plugins/fish.rb +61 -0
- data/data/rbot/plugins/fortune.rb +22 -0
- data/data/rbot/plugins/freshmeat.rb +98 -0
- data/data/rbot/plugins/google.rb +51 -0
- data/data/rbot/plugins/host.rb +14 -0
- data/data/rbot/plugins/httpd.rb.disabled +35 -0
- data/data/rbot/plugins/insult.rb +258 -0
- data/data/rbot/plugins/karma.rb +85 -0
- data/data/rbot/plugins/lart.rb +181 -0
- data/data/rbot/plugins/math.rb +122 -0
- data/data/rbot/plugins/nickserv.rb +89 -0
- data/data/rbot/plugins/nslookup.rb +43 -0
- data/data/rbot/plugins/opme.rb +19 -0
- data/data/rbot/plugins/quakeauth.rb +51 -0
- data/data/rbot/plugins/quotes.rb +321 -0
- data/data/rbot/plugins/remind.rb +228 -0
- data/data/rbot/plugins/roshambo.rb +54 -0
- data/data/rbot/plugins/rot13.rb +10 -0
- data/data/rbot/plugins/roulette.rb +147 -0
- data/data/rbot/plugins/rss.rb.disabled +414 -0
- data/data/rbot/plugins/seen.rb +89 -0
- data/data/rbot/plugins/slashdot.rb +94 -0
- data/data/rbot/plugins/spell.rb +36 -0
- data/data/rbot/plugins/tube.rb +71 -0
- data/data/rbot/plugins/url.rb +88 -0
- data/data/rbot/plugins/weather.rb +649 -0
- data/data/rbot/plugins/wserver.rb +71 -0
- data/data/rbot/plugins/xmlrpc.rb.disabled +52 -0
- data/data/rbot/templates/keywords.rbot +4 -0
- data/data/rbot/templates/lart/larts +98 -0
- data/data/rbot/templates/lart/praises +5 -0
- data/data/rbot/templates/levels.rbot +30 -0
- data/data/rbot/templates/users.rbot +1 -0
- data/lib/rbot/auth.rb +203 -0
- data/lib/rbot/channel.rb +54 -0
- data/lib/rbot/config.rb +363 -0
- data/lib/rbot/dbhash.rb +112 -0
- data/lib/rbot/httputil.rb +141 -0
- data/lib/rbot/ircbot.rb +808 -0
- data/lib/rbot/ircsocket.rb +185 -0
- data/lib/rbot/keywords.rb +433 -0
- data/lib/rbot/language.rb +69 -0
- data/lib/rbot/message.rb +256 -0
- data/lib/rbot/messagemapper.rb +262 -0
- data/lib/rbot/plugins.rb +291 -0
- data/lib/rbot/post-install.rb +8 -0
- data/lib/rbot/rbotconfig.rb +36 -0
- data/lib/rbot/registry.rb +271 -0
- data/lib/rbot/rfc2812.rb +1104 -0
- data/lib/rbot/timer.rb +201 -0
- data/lib/rbot/utils.rb +83 -0
- data/setup.rb +1360 -0
- metadata +129 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
class DnsPlugin < Plugin
|
2
|
+
require 'resolv'
|
3
|
+
def gethostname(address)
|
4
|
+
Resolv.getname(address)
|
5
|
+
end
|
6
|
+
def getaddresses(name)
|
7
|
+
Resolv.getaddresses(name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def help(plugin, topic="")
|
11
|
+
"dns <hostname|ip> => show local resolution results for hostname or ip address"
|
12
|
+
end
|
13
|
+
|
14
|
+
def name_to_ip(m, params)
|
15
|
+
Thread.new do
|
16
|
+
begin
|
17
|
+
a = getaddresses(params[:host])
|
18
|
+
if a.length > 0
|
19
|
+
m.reply m.params + ": " + a.join(", ")
|
20
|
+
else
|
21
|
+
m.reply "#{params[:host]}: not found"
|
22
|
+
end
|
23
|
+
rescue StandardError => err
|
24
|
+
m.reply "#{params[:host]}: not found"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def ip_to_name(m, params)
|
30
|
+
Thread.new do
|
31
|
+
begin
|
32
|
+
a = gethostname(params[:ip])
|
33
|
+
m.reply m.params + ": " + a if a
|
34
|
+
rescue StandardError => err
|
35
|
+
m.reply "#{params[:ip]}: not found (does not reverse resolve)"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
plugin = DnsPlugin.new
|
41
|
+
plugin.map 'dns :ip', :action => 'ip_to_name',
|
42
|
+
:requirements => {:ip => /^\d+\.\d+\.\d+\.\d+$/}
|
43
|
+
plugin.map 'dns :host', :action => 'name_to_ip'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class OpMePlugin < Plugin
|
2
|
+
|
3
|
+
def help(plugin, topic="")
|
4
|
+
return "opme <channel> => grant user ops in <channel>"
|
5
|
+
end
|
6
|
+
|
7
|
+
def privmsg(m)
|
8
|
+
if(m.params)
|
9
|
+
channel = m.params
|
10
|
+
else
|
11
|
+
channel = m.channel
|
12
|
+
end
|
13
|
+
target = m.sourcenick
|
14
|
+
@bot.sendq("MODE #{channel} +o #{target}")
|
15
|
+
m.okay
|
16
|
+
end
|
17
|
+
end
|
18
|
+
plugin = OpMePlugin.new
|
19
|
+
plugin.register("opme")
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# automatically auths with Q on quakenet servers
|
2
|
+
|
3
|
+
class QPlugin < Plugin
|
4
|
+
|
5
|
+
def help(plugin, topic="")
|
6
|
+
case topic
|
7
|
+
when ""
|
8
|
+
return "quath plugin: handles Q auths. topics set, identify"
|
9
|
+
when "set"
|
10
|
+
return "nickserv set <user> <passwd>: set the Q user and password and use it to identify in future"
|
11
|
+
when "identify"
|
12
|
+
return "quath identify: identify with Q (if user and auth are set)"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super
|
18
|
+
# this plugin only wants to store strings!
|
19
|
+
class << @registry
|
20
|
+
def store(val)
|
21
|
+
val
|
22
|
+
end
|
23
|
+
def restore(val)
|
24
|
+
val
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def set(m, params)
|
30
|
+
@registry['quakenet.user'] = params[:user]
|
31
|
+
@registry['quakenet.auth'] = params[:passwd]
|
32
|
+
m.okay
|
33
|
+
end
|
34
|
+
|
35
|
+
def connect
|
36
|
+
identify(nil, nil)
|
37
|
+
end
|
38
|
+
def identify(m, params)
|
39
|
+
if @registry.has_key?('quakenet.user') && @registry.has_key?('quakenet.auth')
|
40
|
+
debug "authing with Q using #{@registry['quakenet.user']} #{@registry['quakenet.auth']}"
|
41
|
+
@bot.sendmsg "PRIVMSG", "Q@CServe.quakenet.org", "auth #{@registry['quakenet.user']} #{@registry['quakenet.auth']}"
|
42
|
+
m.okay if m
|
43
|
+
else
|
44
|
+
m.reply "not configured, try 'qauth set :nick :passwd'" if m
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
plugin = QPlugin.new
|
50
|
+
plugin.map 'qauth set :nick :passwd', :action => "set"
|
51
|
+
plugin.map 'quath identify', :action => "identify"
|
@@ -0,0 +1,321 @@
|
|
1
|
+
Quote = Struct.new("Quote", "num", "date", "source", "quote")
|
2
|
+
|
3
|
+
class QuotePlugin < Plugin
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
@lists = Hash.new
|
7
|
+
Dir["#{@bot.botclass}/quotes/*"].each {|f|
|
8
|
+
channel = File.basename(f)
|
9
|
+
@lists[channel] = Array.new if(!@lists.has_key?(channel))
|
10
|
+
IO.foreach(f) {|line|
|
11
|
+
if(line =~ /^(\d+) \| ([^|]+) \| (\S+) \| (.*)$/)
|
12
|
+
num = $1.to_i
|
13
|
+
@lists[channel][num] = Quote.new(num, $2, $3, $4)
|
14
|
+
end
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
def save
|
19
|
+
Dir.mkdir("#{@bot.botclass}/quotes") if(!FileTest.directory?("#{@bot.botclass}/quotes"))
|
20
|
+
@lists.each {|channel, quotes|
|
21
|
+
File.open("#{@bot.botclass}/quotes/#{channel}", "w") {|file|
|
22
|
+
quotes.compact.each {|q|
|
23
|
+
file.puts "#{q.num} | #{q.date} | #{q.source} | #{q.quote}"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
def addquote(source, channel, quote)
|
29
|
+
@lists[channel] = Array.new if(!@lists.has_key?(channel))
|
30
|
+
num = @lists[channel].length
|
31
|
+
@lists[channel][num] = Quote.new(num, Time.new, source, quote)
|
32
|
+
return num
|
33
|
+
end
|
34
|
+
def getquote(source, channel, num=nil)
|
35
|
+
return nil unless(@lists.has_key?(channel))
|
36
|
+
return nil unless(@lists[channel].length > 0)
|
37
|
+
if(num)
|
38
|
+
if(@lists[channel][num])
|
39
|
+
return @lists[channel][num], @lists[channel].length - 1
|
40
|
+
end
|
41
|
+
else
|
42
|
+
# random quote
|
43
|
+
return @lists[channel].compact[rand(@lists[channel].nitems)],
|
44
|
+
@lists[channel].length - 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def delquote(channel, num)
|
48
|
+
return false unless(@lists.has_key?(channel))
|
49
|
+
return false unless(@lists[channel].length > 0)
|
50
|
+
if(@lists[channel][num])
|
51
|
+
@lists[channel][num] = nil
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
def countquote(source, channel=nil, regexp=nil)
|
57
|
+
unless(channel)
|
58
|
+
total=0
|
59
|
+
@lists.each_value {|l|
|
60
|
+
total += l.compact.length
|
61
|
+
}
|
62
|
+
return total
|
63
|
+
end
|
64
|
+
return 0 unless(@lists.has_key?(channel))
|
65
|
+
return 0 unless(@lists[channel].length > 0)
|
66
|
+
if(regexp)
|
67
|
+
matches = @lists[channel].compact.find_all {|a| a.quote =~ /#{regexp}/i }
|
68
|
+
else
|
69
|
+
matches = @lists[channel].compact
|
70
|
+
end
|
71
|
+
return matches.length
|
72
|
+
end
|
73
|
+
def searchquote(source, channel, regexp)
|
74
|
+
return nil unless(@lists.has_key?(channel))
|
75
|
+
return nil unless(@lists[channel].length > 0)
|
76
|
+
matches = @lists[channel].compact.find_all {|a| a.quote =~ /#{regexp}/i }
|
77
|
+
if(matches.length > 0)
|
78
|
+
return matches[rand(matches.length)], @lists[channel].length - 1
|
79
|
+
else
|
80
|
+
return nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
def help(plugin, topic="")
|
84
|
+
case topic
|
85
|
+
when "addquote"
|
86
|
+
return "addquote [<channel>] <quote> => Add quote <quote> for channel <channel>. You only need to supply <channel> if you are addressing #{@bot.nick} privately. Responds to !addquote without addressing if so configured"
|
87
|
+
when "delquote"
|
88
|
+
return "delquote [<channel>] <num> => delete quote from <channel> with number <num>. You only need to supply <channel> if you are addressing #{@bot.nick} privately. Responds to !delquote without addressing if so configured"
|
89
|
+
when "getquote"
|
90
|
+
return "getquote [<channel>] [<num>] => get quote from <channel> with number <num>. You only need to supply <channel> if you are addressing #{@bot.nick} privately. Without <num>, a random quote will be returned. Responds to !getquote without addressing if so configured"
|
91
|
+
when "searchquote"
|
92
|
+
return "searchquote [<channel>] <regexp> => search for quote from <channel> that matches <regexp>. You only need to supply <channel> if you are addressing #{@bot.nick} privately. Responds to !searchquote without addressing if so configured"
|
93
|
+
when "topicquote"
|
94
|
+
return "topicquote [<channel>] [<num>] => set topic to quote from <channel> with number <num>. You only need to supply <channel> if you are addressing #{@bot.nick} privately. Without <num>, a random quote will be set. Responds to !topicquote without addressing if so configured"
|
95
|
+
when "countquote"
|
96
|
+
return "countquote [<channel>] <regexp> => count quotes from <channel> that match <regexp>. You only need to supply <channel> if you are addressing #{@bot.nick} privately. Responds to !countquote without addressing if so configured"
|
97
|
+
when "whoquote"
|
98
|
+
return "whoquote [<channel>] <num> => show who added quote <num>. You only need to supply <channel> if you are addressing #{@bot.nick} privately"
|
99
|
+
when "whenquote"
|
100
|
+
return "whenquote [<channel>] <num> => show when quote <num> was added. You only need to supply <channel> if you are addressing #{@bot.nick} privately"
|
101
|
+
else
|
102
|
+
return "Quote module (Quote storage and retrieval) topics: addquote, getquote, searchquote, topicquote, countquote, whoquote, whenquote"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
def listen(m)
|
106
|
+
return unless(m.kind_of? PrivMessage)
|
107
|
+
|
108
|
+
command = m.message.dup
|
109
|
+
if(m.address? && m.private?)
|
110
|
+
case command
|
111
|
+
when (/^addquote\s+(#\S+)\s+(.*)/)
|
112
|
+
channel = $1
|
113
|
+
quote = $2
|
114
|
+
if(@bot.auth.allow?("addquote", m.source, m.replyto))
|
115
|
+
if(channel =~ /^#/)
|
116
|
+
num = addquote(m.source, channel, quote)
|
117
|
+
m.reply "added the quote (##{num})"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
when (/^getquote\s+(#\S+)$/)
|
121
|
+
channel = $1
|
122
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
123
|
+
quote, total = getquote(m.source, channel)
|
124
|
+
if(quote)
|
125
|
+
m.reply "[#{quote.num}] #{quote.quote}"
|
126
|
+
else
|
127
|
+
m.reply "quote not found!"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
when (/^getquote\s+(#\S+)\s+(\d+)$/)
|
131
|
+
channel = $1
|
132
|
+
num = $2.to_i
|
133
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
134
|
+
quote, total = getquote(m.source, channel, num)
|
135
|
+
if(quote)
|
136
|
+
m.reply "[#{quote.num}] #{quote.quote}"
|
137
|
+
else
|
138
|
+
m.reply "quote not found!"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
when (/^whoquote\s+(#\S+)\s+(\d+)$/)
|
142
|
+
channel = $1
|
143
|
+
num = $2.to_i
|
144
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
145
|
+
quote, total = getquote(m.source, channel, num)
|
146
|
+
if(quote)
|
147
|
+
m.reply "quote #{quote.num} added by #{quote.source}"
|
148
|
+
else
|
149
|
+
m.reply "quote not found!"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
when (/^whenquote\s+(#\S+)\s+(\d+)$/)
|
153
|
+
channel = $1
|
154
|
+
num = $2.to_i
|
155
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
156
|
+
quote, total = getquote(m.source, channel, num)
|
157
|
+
if(quote)
|
158
|
+
m.reply "quote #{quote.num} added on #{quote.date}"
|
159
|
+
else
|
160
|
+
m.reply "quote not found!"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
when (/^topicquote\s+(#\S+)$/)
|
164
|
+
channel = $1
|
165
|
+
if(@bot.auth.allow?("topicquote", m.source, m.replyto))
|
166
|
+
quote, total = getquote(m.source, channel)
|
167
|
+
if(quote)
|
168
|
+
@bot.topic channel, "[#{quote.num}] #{quote.quote}"
|
169
|
+
else
|
170
|
+
m.reply "quote not found!"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
when (/^topicquote\s+(#\S+)\s+(\d+)$/)
|
174
|
+
channel = $1
|
175
|
+
num = $2.to_i
|
176
|
+
if(@bot.auth.allow?("topicquote", m.source, m.replyto))
|
177
|
+
quote, total = getquote(m.source, channel, num)
|
178
|
+
if(quote)
|
179
|
+
@bot.topic channel, "[#{quote.num}] #{quote.quote}"
|
180
|
+
else
|
181
|
+
m.reply "quote not found!"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
when (/^delquote\s+(#\S+)\s+(\d+)$/)
|
185
|
+
channel = $1
|
186
|
+
num = $2.to_i
|
187
|
+
if(@bot.auth.allow?("delquote", m.source, m.replyto))
|
188
|
+
if(delquote(channel, num))
|
189
|
+
m.okay
|
190
|
+
else
|
191
|
+
m.reply "quote not found!"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
when (/^searchquote\s+(#\S+)\s+(.*)$/)
|
195
|
+
channel = $1
|
196
|
+
reg = $2
|
197
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
198
|
+
quote, total = searchquote(m.source, channel, reg)
|
199
|
+
if(quote)
|
200
|
+
m.reply "[#{quote.num}] #{quote.quote}"
|
201
|
+
else
|
202
|
+
m.reply "quote not found!"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
when (/^countquote$/)
|
206
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
207
|
+
total = countquote(m.source)
|
208
|
+
m.reply "#{total} quotes"
|
209
|
+
end
|
210
|
+
when (/^countquote\s+(#\S+)\s*(.*)$/)
|
211
|
+
channel = $1
|
212
|
+
reg = $2
|
213
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
214
|
+
total = countquote(m.source, channel, reg)
|
215
|
+
if(reg.length > 0)
|
216
|
+
m.reply "#{total} quotes match: #{reg}"
|
217
|
+
else
|
218
|
+
m.reply "#{total} quotes"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
elsif (m.address? || (@bot.config["QUOTE_LISTEN"] && command.gsub!(/^!/, "")))
|
223
|
+
case command
|
224
|
+
when (/^addquote\s+(.+)/)
|
225
|
+
if(@bot.auth.allow?("addquote", m.source, m.replyto))
|
226
|
+
num = addquote(m.source, m.target, $1)
|
227
|
+
m.reply "added the quote (##{num})"
|
228
|
+
end
|
229
|
+
when (/^getquote$/)
|
230
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
231
|
+
quote, total = getquote(m.source, m.target)
|
232
|
+
if(quote)
|
233
|
+
m.reply "[#{quote.num}] #{quote.quote}"
|
234
|
+
else
|
235
|
+
m.reply "no quotes found!"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
when (/^getquote\s+(\d+)$/)
|
239
|
+
num = $1.to_i
|
240
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
241
|
+
quote, total = getquote(m.source, m.target, num)
|
242
|
+
if(quote)
|
243
|
+
m.reply "[#{quote.num}] #{quote.quote}"
|
244
|
+
else
|
245
|
+
m.reply "quote not found!"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
when (/^whenquote\s+(\d+)$/)
|
249
|
+
num = $1.to_i
|
250
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
251
|
+
quote, total = getquote(m.source, m.target, num)
|
252
|
+
if(quote)
|
253
|
+
m.reply "quote #{quote.num} added on #{quote.date}"
|
254
|
+
else
|
255
|
+
m.reply "quote not found!"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
when (/^whoquote\s+(\d+)$/)
|
259
|
+
num = $1.to_i
|
260
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
261
|
+
quote, total = getquote(m.source, m.target, num)
|
262
|
+
if(quote)
|
263
|
+
m.reply "quote #{quote.num} added by #{quote.source}"
|
264
|
+
else
|
265
|
+
m.reply "quote not found!"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
when (/^topicquote$/)
|
269
|
+
if(@bot.auth.allow?("topicquote", m.source, m.replyto))
|
270
|
+
quote, total = getquote(m.source, m.target)
|
271
|
+
if(quote)
|
272
|
+
@bot.topic m.target, "[#{quote.num}] #{quote.quote}"
|
273
|
+
else
|
274
|
+
m.reply "no quotes found!"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
when (/^topicquote\s+(\d+)$/)
|
278
|
+
num = $1.to_i
|
279
|
+
if(@bot.auth.allow?("topicquote", m.source, m.replyto))
|
280
|
+
quote, total = getquote(m.source, m.target, num)
|
281
|
+
if(quote)
|
282
|
+
@bot.topic m.target, "[#{quote.num}] #{quote.quote}"
|
283
|
+
else
|
284
|
+
m.reply "quote not found!"
|
285
|
+
end
|
286
|
+
end
|
287
|
+
when (/^delquote\s+(\d+)$/)
|
288
|
+
num = $1.to_i
|
289
|
+
if(@bot.auth.allow?("delquote", m.source, m.replyto))
|
290
|
+
if(delquote(m.target, num))
|
291
|
+
m.okay
|
292
|
+
else
|
293
|
+
m.reply "quote not found!"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
when (/^searchquote\s+(.*)$/)
|
297
|
+
reg = $1
|
298
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
299
|
+
quote, total = searchquote(m.source, m.target, reg)
|
300
|
+
if(quote)
|
301
|
+
m.reply "[#{quote.num}] #{quote.quote}"
|
302
|
+
else
|
303
|
+
m.reply "quote not found!"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
when (/^countquote(?:\s+(.*))?$/)
|
307
|
+
reg = $1
|
308
|
+
if(@bot.auth.allow?("getquote", m.source, m.replyto))
|
309
|
+
total = countquote(m.source, m.target, reg)
|
310
|
+
if(reg && reg.length > 0)
|
311
|
+
m.reply "#{total} quotes match: #{reg}"
|
312
|
+
else
|
313
|
+
m.reply "#{total} quotes"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
plugin = QuotePlugin.new
|
321
|
+
plugin.register("quotes")
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'rbot/utils'
|
2
|
+
|
3
|
+
class RemindPlugin < Plugin
|
4
|
+
# read a time in string format, turn it into "seconds from now".
|
5
|
+
# example formats handled are "5 minutes", "2 days", "five hours",
|
6
|
+
# "11:30", "15:45:11", "one day", etc.
|
7
|
+
#
|
8
|
+
# Throws:: RunTimeError "invalid time string" on parse failure
|
9
|
+
def timestr_offset(timestr)
|
10
|
+
case timestr
|
11
|
+
when (/^(\S+)\s+(\S+)$/)
|
12
|
+
mult = $1
|
13
|
+
unit = $2
|
14
|
+
if(mult =~ /^([\d.]+)$/)
|
15
|
+
num = $1.to_f
|
16
|
+
raise "invalid time string" unless num
|
17
|
+
else
|
18
|
+
case mult
|
19
|
+
when(/^(one|an|a)$/)
|
20
|
+
num = 1
|
21
|
+
when(/^two$/)
|
22
|
+
num = 2
|
23
|
+
when(/^three$/)
|
24
|
+
num = 3
|
25
|
+
when(/^four$/)
|
26
|
+
num = 4
|
27
|
+
when(/^five$/)
|
28
|
+
num = 5
|
29
|
+
when(/^six$/)
|
30
|
+
num = 6
|
31
|
+
when(/^seven$/)
|
32
|
+
num = 7
|
33
|
+
when(/^eight$/)
|
34
|
+
num = 8
|
35
|
+
when(/^nine$/)
|
36
|
+
num = 9
|
37
|
+
when(/^ten$/)
|
38
|
+
num = 10
|
39
|
+
when(/^fifteen$/)
|
40
|
+
num = 15
|
41
|
+
when(/^twenty$/)
|
42
|
+
num = 20
|
43
|
+
when(/^thirty$/)
|
44
|
+
num = 30
|
45
|
+
when(/^sixty$/)
|
46
|
+
num = 60
|
47
|
+
else
|
48
|
+
raise "invalid time string"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
case unit
|
52
|
+
when (/^(s|sec(ond)?s?)$/)
|
53
|
+
return num
|
54
|
+
when (/^(m|min(ute)?s?)$/)
|
55
|
+
return num * 60
|
56
|
+
when (/^(h|h(ou)?rs?)$/)
|
57
|
+
return num * 60 * 60
|
58
|
+
when (/^(d|days?)$/)
|
59
|
+
return num * 60 * 60 * 24
|
60
|
+
else
|
61
|
+
raise "invalid time string"
|
62
|
+
end
|
63
|
+
when (/^(\d+):(\d+):(\d+)$/)
|
64
|
+
hour = $1.to_i
|
65
|
+
min = $2.to_i
|
66
|
+
sec = $3.to_i
|
67
|
+
now = Time.now
|
68
|
+
later = Time.mktime(now.year, now.month, now.day, hour, min, sec)
|
69
|
+
return later - now
|
70
|
+
when (/^(\d+):(\d+)$/)
|
71
|
+
hour = $1.to_i
|
72
|
+
min = $2.to_i
|
73
|
+
now = Time.now
|
74
|
+
later = Time.mktime(now.year, now.month, now.day, hour, min, now.sec)
|
75
|
+
return later - now
|
76
|
+
when (/^(\d+):(\d+)(am|pm)$/)
|
77
|
+
hour = $1.to_i
|
78
|
+
min = $2.to_i
|
79
|
+
ampm = $3
|
80
|
+
if ampm == "pm"
|
81
|
+
hour += 12
|
82
|
+
end
|
83
|
+
now = Time.now
|
84
|
+
later = Time.mktime(now.year, now.month, now.day, hour, min, now.sec)
|
85
|
+
return later - now
|
86
|
+
when (/^(\S+)$/)
|
87
|
+
num = 1
|
88
|
+
unit = $1
|
89
|
+
case unit
|
90
|
+
when (/^(s|sec(ond)?s?)$/)
|
91
|
+
return num
|
92
|
+
when (/^(m|min(ute)?s?)$/)
|
93
|
+
return num * 60
|
94
|
+
when (/^(h|h(ou)?rs?)$/)
|
95
|
+
return num * 60 * 60
|
96
|
+
when (/^(d|days?)$/)
|
97
|
+
return num * 60 * 60 * 24
|
98
|
+
else
|
99
|
+
raise "invalid time string"
|
100
|
+
end
|
101
|
+
else
|
102
|
+
raise "invalid time string"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize
|
107
|
+
super
|
108
|
+
@reminders = Hash.new
|
109
|
+
end
|
110
|
+
def cleanup
|
111
|
+
@reminders.each_value {|v|
|
112
|
+
v.each_value {|vv|
|
113
|
+
@bot.timer.remove(vv)
|
114
|
+
}
|
115
|
+
}
|
116
|
+
@reminders.clear
|
117
|
+
end
|
118
|
+
def help(plugin, topic="")
|
119
|
+
"reminder plugin: remind <who> [about] <message> in <time>, remind <who> [about] <message> every <time>, remind <who> [about] <message> at <time>, remind <who> no more [about] <message>, remind <who> no more. Generally <who> should be 'me', but you can remind others (nick or channel) if you have remind_others auth"
|
120
|
+
end
|
121
|
+
def add_reminder(who, subject, timestr, repeat=false)
|
122
|
+
begin
|
123
|
+
period = timestr_offset(timestr)
|
124
|
+
rescue RuntimeError
|
125
|
+
return "couldn't parse that time string (#{timestr}) :("
|
126
|
+
end
|
127
|
+
if(period <= 0)
|
128
|
+
return "that time is in the past! (#{timestr})"
|
129
|
+
end
|
130
|
+
if(period < 30 && repeat)
|
131
|
+
return "repeats of less than 30 seconds are forbidden"
|
132
|
+
end
|
133
|
+
if(!@reminders.has_key?(who))
|
134
|
+
@reminders[who] = Hash.new
|
135
|
+
elsif(@reminders[who].has_key?(subject))
|
136
|
+
del_reminder(who, subject)
|
137
|
+
end
|
138
|
+
|
139
|
+
if(repeat)
|
140
|
+
@reminders[who][subject] = @bot.timer.add(period) {
|
141
|
+
time = Time.now + period
|
142
|
+
tstr = time.strftime("%H:%M:%S")
|
143
|
+
@bot.say who, "repeat reminder (next at #{tstr}): #{subject}"
|
144
|
+
}
|
145
|
+
else
|
146
|
+
@reminders[who][subject] = @bot.timer.add_once(period) {
|
147
|
+
time = Time.now + period
|
148
|
+
tstr = time.strftime("%H:%M:%S")
|
149
|
+
@bot.say who, "reminder (#{tstr}): #{subject}"
|
150
|
+
}
|
151
|
+
end
|
152
|
+
return false
|
153
|
+
end
|
154
|
+
def del_reminder(who, subject=nil)
|
155
|
+
if(subject)
|
156
|
+
if(@reminders.has_key?(who) && @reminders[who].has_key?(subject))
|
157
|
+
@bot.timer.remove(@reminders[who][subject])
|
158
|
+
@reminders[who].delete(subject)
|
159
|
+
return true
|
160
|
+
else
|
161
|
+
return false
|
162
|
+
end
|
163
|
+
else
|
164
|
+
if(@reminders.has_key?(who))
|
165
|
+
@reminders[who].each_value {|v|
|
166
|
+
@bot.timer.remove(v)
|
167
|
+
}
|
168
|
+
@reminders.delete(who)
|
169
|
+
return true
|
170
|
+
else
|
171
|
+
return false
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
def remind(m, params)
|
176
|
+
who = params.has_key?(:who) ? params[:who] : m.sourcenick
|
177
|
+
string = params[:string].to_s
|
178
|
+
puts "in remind, string is: #{string}"
|
179
|
+
if(string =~ /^(.*)\s+in\s+(.*)$/)
|
180
|
+
subject = $1
|
181
|
+
period = $2
|
182
|
+
if(err = add_reminder(who, subject, period))
|
183
|
+
m.reply "incorrect usage: " + err
|
184
|
+
return
|
185
|
+
end
|
186
|
+
elsif(string =~ /^(.*)\s+every\s+(.*)$/)
|
187
|
+
subject = $1
|
188
|
+
period = $2
|
189
|
+
if(err = add_reminder(who, subject, period, true))
|
190
|
+
m.reply "incorrect usage: " + err
|
191
|
+
return
|
192
|
+
end
|
193
|
+
elsif(string =~ /^(.*)\s+at\s+(.*)$/)
|
194
|
+
subject = $1
|
195
|
+
time = $2
|
196
|
+
if(err = add_reminder(who, subject, time))
|
197
|
+
m.reply "incorrect usage: " + err
|
198
|
+
return
|
199
|
+
end
|
200
|
+
else
|
201
|
+
usage(m)
|
202
|
+
return
|
203
|
+
end
|
204
|
+
m.okay
|
205
|
+
end
|
206
|
+
def no_more(m, params)
|
207
|
+
who = params.has_key?(:who) ? params[:who] : m.sourcenick
|
208
|
+
deleted = params.has_key?(:string) ?
|
209
|
+
del_reminder(who, params[:string].to_s) : del_reminder(who)
|
210
|
+
if deleted
|
211
|
+
m.okay
|
212
|
+
else
|
213
|
+
m.reply "but I wasn't going to :/"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
plugin = RemindPlugin.new
|
218
|
+
plugin.map 'remind me no more', :action => 'no_more'
|
219
|
+
plugin.map 'remind me no more about *string', :action => 'no_more'
|
220
|
+
plugin.map 'remind me no more *string', :action => 'no_more'
|
221
|
+
plugin.map 'remind me about *string'
|
222
|
+
plugin.map 'remind me *string'
|
223
|
+
plugin.map 'remind :who no more', :auth => 'remind_other', :action => 'no_more'
|
224
|
+
plugin.map 'remind :who no more about *string', :auth => 'remind_other', :action => 'no_more'
|
225
|
+
plugin.map 'remind :who no more *string', :auth => 'remind_other', :action => 'no_more'
|
226
|
+
plugin.map 'remind :who about *string', :auth => 'remind_other'
|
227
|
+
plugin.map 'remind :who *string', :auth => 'remind_other'
|
228
|
+
|