rbot 0.9.9 → 0.9.10

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 (72) hide show
  1. data/AUTHORS +8 -0
  2. data/ChangeLog +51 -0
  3. data/INSTALL +4 -0
  4. data/README +1 -0
  5. data/REQUIREMENTS +11 -0
  6. data/TODO +2 -0
  7. data/bin/rbot +21 -2
  8. data/data/rbot/languages/german.lang +4 -1
  9. data/data/rbot/languages/russian.lang +75 -0
  10. data/data/rbot/plugins/autoop.rb +42 -51
  11. data/data/rbot/plugins/bans.rb +205 -0
  12. data/data/rbot/plugins/bash.rb +56 -0
  13. data/data/rbot/plugins/chucknorris.rb +74 -0
  14. data/data/rbot/plugins/chucknorris.yml.gz +0 -0
  15. data/data/rbot/plugins/deepthoughts.rb +95 -0
  16. data/data/rbot/plugins/demauro.rb +95 -0
  17. data/data/rbot/plugins/digg.rb +51 -0
  18. data/data/rbot/plugins/figlet.rb +24 -0
  19. data/data/rbot/plugins/forecast.rb +133 -0
  20. data/data/rbot/plugins/freshmeat.rb +13 -7
  21. data/data/rbot/plugins/google.rb +2 -0
  22. data/data/rbot/plugins/grouphug.rb +36 -0
  23. data/data/rbot/plugins/imdb.rb +92 -0
  24. data/data/rbot/plugins/insult.rb +8 -1
  25. data/data/rbot/plugins/iplookup.rb +227 -0
  26. data/data/rbot/plugins/karma.rb +2 -2
  27. data/data/rbot/plugins/keywords.rb +470 -0
  28. data/data/rbot/plugins/lart.rb +132 -146
  29. data/data/rbot/plugins/lastfm.rb +25 -0
  30. data/data/rbot/plugins/markov.rb +204 -0
  31. data/data/rbot/plugins/math.rb +5 -1
  32. data/data/rbot/plugins/nickserv.rb +71 -11
  33. data/data/rbot/plugins/opme.rb +19 -19
  34. data/data/rbot/plugins/quakeauth.rb +2 -2
  35. data/data/rbot/plugins/quotes.rb +40 -25
  36. data/data/rbot/plugins/remind.rb +1 -1
  37. data/data/rbot/plugins/rot13.rb +2 -2
  38. data/data/rbot/plugins/roulette.rb +49 -15
  39. data/data/rbot/plugins/rss.rb +585 -0
  40. data/data/rbot/plugins/rubyurl.rb +39 -0
  41. data/data/rbot/plugins/seen.rb +2 -1
  42. data/data/rbot/plugins/slashdot.rb +5 -5
  43. data/data/rbot/plugins/spell.rb +5 -0
  44. data/data/rbot/plugins/theyfightcrime.rb +121 -0
  45. data/data/rbot/plugins/threat.rb +55 -0
  46. data/data/rbot/plugins/tinyurl.rb +39 -0
  47. data/data/rbot/plugins/topic.rb +204 -0
  48. data/data/rbot/plugins/urban.rb +71 -0
  49. data/data/rbot/plugins/url.rb +399 -4
  50. data/data/rbot/plugins/wow.rb +123 -0
  51. data/data/rbot/plugins/wserver.rb +1 -1
  52. data/data/rbot/templates/levels.rbot +2 -0
  53. data/lib/rbot/auth.rb +207 -96
  54. data/lib/rbot/channel.rb +5 -5
  55. data/lib/rbot/config.rb +125 -24
  56. data/lib/rbot/dbhash.rb +87 -21
  57. data/lib/rbot/httputil.rb +181 -13
  58. data/lib/rbot/ircbot.rb +525 -179
  59. data/lib/rbot/ircsocket.rb +330 -54
  60. data/lib/rbot/message.rb +66 -23
  61. data/lib/rbot/messagemapper.rb +25 -17
  62. data/lib/rbot/plugins.rb +244 -115
  63. data/lib/rbot/post-clean.rb +1 -0
  64. data/lib/rbot/{post-install.rb → post-config.rb} +1 -1
  65. data/lib/rbot/rbotconfig.rb +29 -14
  66. data/lib/rbot/registry.rb +111 -72
  67. data/lib/rbot/rfc2812.rb +208 -197
  68. data/lib/rbot/timer.rb +4 -0
  69. data/lib/rbot/utils.rb +2 -2
  70. metadata +127 -104
  71. data/data/rbot/plugins/rss.rb.disabled +0 -414
  72. data/lib/rbot/keywords.rb +0 -433
@@ -0,0 +1,71 @@
1
+ require 'cgi'
2
+ begin
3
+ require 'rubyful_soup'
4
+ rescue
5
+ warning "could not load rubyful_soup, urban dictionary disabled"
6
+ warning "please get it from http://www.crummy.com/software/RubyfulSoup/"
7
+ warning "or install it via gem"
8
+ return
9
+ end
10
+ require 'uri/common'
11
+
12
+ class UrbanPlugin < Plugin
13
+
14
+ def help( plugin, topic="")
15
+ "urban [word] [n]. Give the [n]th definition of [word] from urbandictionary.com."
16
+ end
17
+
18
+ def privmsg( m )
19
+
20
+ unless(m.params && m.params.length > 0)
21
+ m.reply "incorrect usage: " + help(m.plugin)
22
+ return
23
+ end
24
+
25
+ paramArray = m.params.split(' ')
26
+ definitionN = 0
27
+ if m.params == 'random' then
28
+ uri = URI.parse( "http://www.urbandictionary.com/random.php" )
29
+ else
30
+ if( paramArray.last.to_i != 0 ) then
31
+ definitionN = paramArray.last.to_i - 1
32
+ query = m.params.chomp( paramArray.last )
33
+ query.rstrip!
34
+ else
35
+ query = m.params
36
+ end
37
+ uri = URI.parse( "http://www.urbandictionary.com/define.php?term=#{ URI.escape query}" )
38
+ end
39
+
40
+ soup = BeautifulSoup.new( @bot.httputil.get_cached( uri ) )
41
+ if titleNavi = soup.find_all( 'td', :attrs => { 'class' => 'def_word' } )[0] then
42
+ title = titleNavi.contents
43
+ results = soup.find_all( 'div', :attrs => { 'class' => 'def_p' } )
44
+ # debug PP.pp(results,'')
45
+ output = Array.new
46
+ if results[definitionN] then
47
+ results[definitionN].p.contents.each { |s| output.push( strip_tags( s.to_s ) ) }
48
+ m.reply "\002#{title}\002 - #{output}"
49
+ else
50
+ m.reply "#{query} does not have #{definitionN + 1} definitions."
51
+ end
52
+ else
53
+ m.reply "#{m.params} not found."
54
+ end
55
+
56
+ end
57
+
58
+ def strip_tags(html)
59
+ html.gsub(/<.+?>/,'').
60
+ gsub(/&amp;/,'&').
61
+ gsub(/&quot;/,'"').
62
+ gsub(/&lt;/,'<').
63
+ gsub(/&gt;/,'>').
64
+ gsub(/&ellip;/,'...').
65
+ gsub(/&apos;/, "'").
66
+ gsub("\n",'')
67
+ end
68
+ end
69
+
70
+ plugin = UrbanPlugin.new
71
+ plugin.register( "urban" )
@@ -1,17 +1,401 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'cgi'
4
+
1
5
  Url = Struct.new("Url", :channel, :nick, :time, :url)
6
+ TITLE_RE = /<\s*?title\s*?>(.+?)<\s*?\/title\s*?>/im
7
+
8
+ UNESCAPE_TABLE = {
9
+ 'raquo' => '>>',
10
+ 'quot' => '"',
11
+ 'micro' => 'u',
12
+ 'copy' => '(c)',
13
+ 'trade' => '(tm)',
14
+ 'reg' => '(R)',
15
+ '#174' => '(R)',
16
+ '#8220' => '"',
17
+ '#8221' => '"',
18
+ '#8212' => '--',
19
+ '#39' => '\'',
20
+ =begin
21
+ # extras codes, for future use...
22
+ 'zwnj' => '&#8204;',
23
+ 'aring' => '\xe5',
24
+ 'gt' => '>',
25
+ 'yen' => '\xa5',
26
+ 'ograve' => '\xf2',
27
+ 'Chi' => '&#935;',
28
+ 'bull' => '&#8226;',
29
+ 'Egrave' => '\xc8',
30
+ 'Ntilde' => '\xd1',
31
+ 'upsih' => '&#978;',
32
+ 'Yacute' => '\xdd',
33
+ 'asymp' => '&#8776;',
34
+ 'radic' => '&#8730;',
35
+ 'otimes' => '&#8855;',
36
+ 'nabla' => '&#8711;',
37
+ 'aelig' => '\xe6',
38
+ 'oelig' => '&#339;',
39
+ 'equiv' => '&#8801;',
40
+ 'Psi' => '&#936;',
41
+ 'auml' => '\xe4',
42
+ 'circ' => '&#710;',
43
+ 'Acirc' => '\xc2',
44
+ 'Epsilon' => '&#917;',
45
+ 'Yuml' => '&#376;',
46
+ 'Eta' => '&#919;',
47
+ 'lt' => '<',
48
+ 'Icirc' => '\xce',
49
+ 'Upsilon' => '&#933;',
50
+ 'ndash' => '&#8211;',
51
+ 'there4' => '&#8756;',
52
+ 'Prime' => '&#8243;',
53
+ 'prime' => '&#8242;',
54
+ 'psi' => '&#968;',
55
+ 'Kappa' => '&#922;',
56
+ 'rsaquo' => '&#8250;',
57
+ 'Tau' => '&#932;',
58
+ 'darr' => '&#8595;',
59
+ 'ocirc' => '\xf4',
60
+ 'lrm' => '&#8206;',
61
+ 'zwj' => '&#8205;',
62
+ 'cedil' => '\xb8',
63
+ 'Ecirc' => '\xca',
64
+ 'not' => '\xac',
65
+ 'amp' => '&',
66
+ 'AElig' => '\xc6',
67
+ 'oslash' => '\xf8',
68
+ 'acute' => '\xb4',
69
+ 'lceil' => '&#8968;',
70
+ 'laquo' => '\xab',
71
+ 'shy' => '\xad',
72
+ 'rdquo' => '&#8221;',
73
+ 'ge' => '&#8805;',
74
+ 'Igrave' => '\xcc',
75
+ 'Ograve' => '\xd2',
76
+ 'euro' => '&#8364;',
77
+ 'dArr' => '&#8659;',
78
+ 'sdot' => '&#8901;',
79
+ 'nbsp' => '\xa0',
80
+ 'lfloor' => '&#8970;',
81
+ 'lArr' => '&#8656;',
82
+ 'Auml' => '\xc4',
83
+ 'larr' => '&#8592;',
84
+ 'Atilde' => '\xc3',
85
+ 'Otilde' => '\xd5',
86
+ 'szlig' => '\xdf',
87
+ 'clubs' => '&#9827;',
88
+ 'diams' => '&#9830;',
89
+ 'agrave' => '\xe0',
90
+ 'Ocirc' => '\xd4',
91
+ 'Iota' => '&#921;',
92
+ 'Theta' => '&#920;',
93
+ 'Pi' => '&#928;',
94
+ 'OElig' => '&#338;',
95
+ 'Scaron' => '&#352;',
96
+ 'frac14' => '\xbc',
97
+ 'egrave' => '\xe8',
98
+ 'sub' => '&#8834;',
99
+ 'iexcl' => '\xa1',
100
+ 'frac12' => '\xbd',
101
+ 'sbquo' => '&#8218;',
102
+ 'ordf' => '\xaa',
103
+ 'sum' => '&#8721;',
104
+ 'prop' => '&#8733;',
105
+ 'Uuml' => '\xdc',
106
+ 'ntilde' => '\xf1',
107
+ 'sup' => '&#8835;',
108
+ 'theta' => '&#952;',
109
+ 'prod' => '&#8719;',
110
+ 'nsub' => '&#8836;',
111
+ 'hArr' => '&#8660;',
112
+ 'rlm' => '&#8207;',
113
+ 'THORN' => '\xde',
114
+ 'infin' => '&#8734;',
115
+ 'yuml' => '\xff',
116
+ 'Mu' => '&#924;',
117
+ 'le' => '&#8804;',
118
+ 'Eacute' => '\xc9',
119
+ 'thinsp' => '&#8201;',
120
+ 'ecirc' => '\xea',
121
+ 'bdquo' => '&#8222;',
122
+ 'Sigma' => '&#931;',
123
+ 'fnof' => '&#402;',
124
+ 'Aring' => '\xc5',
125
+ 'tilde' => '&#732;',
126
+ 'frac34' => '\xbe',
127
+ 'emsp' => '&#8195;',
128
+ 'mdash' => '&#8212;',
129
+ 'uarr' => '&#8593;',
130
+ 'permil' => '&#8240;',
131
+ 'Ugrave' => '\xd9',
132
+ 'rarr' => '&#8594;',
133
+ 'Agrave' => '\xc0',
134
+ 'chi' => '&#967;',
135
+ 'forall' => '&#8704;',
136
+ 'eth' => '\xf0',
137
+ 'rceil' => '&#8969;',
138
+ 'iuml' => '\xef',
139
+ 'gamma' => '&#947;',
140
+ 'lambda' => '&#955;',
141
+ 'harr' => '&#8596;',
142
+ 'rang' => '&#9002;',
143
+ 'xi' => '&#958;',
144
+ 'dagger' => '&#8224;',
145
+ 'divide' => '\xf7',
146
+ 'Ouml' => '\xd6',
147
+ 'image' => '&#8465;',
148
+ 'alefsym' => '&#8501;',
149
+ 'igrave' => '\xec',
150
+ 'otilde' => '\xf5',
151
+ 'Oacute' => '\xd3',
152
+ 'sube' => '&#8838;',
153
+ 'alpha' => '&#945;',
154
+ 'frasl' => '&#8260;',
155
+ 'ETH' => '\xd0',
156
+ 'lowast' => '&#8727;',
157
+ 'Nu' => '&#925;',
158
+ 'plusmn' => '\xb1',
159
+ 'Euml' => '\xcb',
160
+ 'real' => '&#8476;',
161
+ 'sup1' => '\xb9',
162
+ 'sup2' => '\xb2',
163
+ 'sup3' => '\xb3',
164
+ 'Oslash' => '\xd8',
165
+ 'Aacute' => '\xc1',
166
+ 'cent' => '\xa2',
167
+ 'oline' => '&#8254;',
168
+ 'Beta' => '&#914;',
169
+ 'perp' => '&#8869;',
170
+ 'Delta' => '&#916;',
171
+ 'loz' => '&#9674;',
172
+ 'pi' => '&#960;',
173
+ 'iota' => '&#953;',
174
+ 'empty' => '&#8709;',
175
+ 'euml' => '\xeb',
176
+ 'brvbar' => '\xa6',
177
+ 'iacute' => '\xed',
178
+ 'para' => '\xb6',
179
+ 'micro' => '\xb5',
180
+ 'cup' => '&#8746;',
181
+ 'weierp' => '&#8472;',
182
+ 'uuml' => '\xfc',
183
+ 'part' => '&#8706;',
184
+ 'icirc' => '\xee',
185
+ 'delta' => '&#948;',
186
+ 'omicron' => '&#959;',
187
+ 'upsilon' => '&#965;',
188
+ 'Iuml' => '\xcf',
189
+ 'Lambda' => '&#923;',
190
+ 'Xi' => '&#926;',
191
+ 'kappa' => '&#954;',
192
+ 'ccedil' => '\xe7',
193
+ 'Ucirc' => '\xdb',
194
+ 'cap' => '&#8745;',
195
+ 'mu' => '&#956;',
196
+ 'scaron' => '&#353;',
197
+ 'lsquo' => '&#8216;',
198
+ 'isin' => '&#8712;',
199
+ 'Zeta' => '&#918;',
200
+ 'supe' => '&#8839;',
201
+ 'deg' => '\xb0',
202
+ 'and' => '&#8743;',
203
+ 'tau' => '&#964;',
204
+ 'pound' => '\xa3',
205
+ 'hellip' => '&#8230;',
206
+ 'curren' => '\xa4',
207
+ 'int' => '&#8747;',
208
+ 'ucirc' => '\xfb',
209
+ 'rfloor' => '&#8971;',
210
+ 'ensp' => '&#8194;',
211
+ 'crarr' => '&#8629;',
212
+ 'ugrave' => '\xf9',
213
+ 'notin' => '&#8713;',
214
+ 'exist' => '&#8707;',
215
+ 'uArr' => '&#8657;',
216
+ 'cong' => '&#8773;',
217
+ 'Dagger' => '&#8225;',
218
+ 'oplus' => '&#8853;',
219
+ 'times' => '\xd7',
220
+ 'atilde' => '\xe3',
221
+ 'piv' => '&#982;',
222
+ 'ni' => '&#8715;',
223
+ 'Phi' => '&#934;',
224
+ 'lsaquo' => '&#8249;',
225
+ 'Uacute' => '\xda',
226
+ 'Omicron' => '&#927;',
227
+ 'ang' => '&#8736;',
228
+ 'ne' => '&#8800;',
229
+ 'iquest' => '\xbf',
230
+ 'eta' => '&#951;',
231
+ 'yacute' => '\xfd',
232
+ 'Rho' => '&#929;',
233
+ 'uacute' => '\xfa',
234
+ 'Alpha' => '&#913;',
235
+ 'zeta' => '&#950;',
236
+ 'Omega' => '&#937;',
237
+ 'nu' => '&#957;',
238
+ 'sim' => '&#8764;',
239
+ 'sect' => '\xa7',
240
+ 'phi' => '&#966;',
241
+ 'sigmaf' => '&#962;',
242
+ 'macr' => '\xaf',
243
+ 'minus' => '&#8722;',
244
+ 'Ccedil' => '\xc7',
245
+ 'ordm' => '\xba',
246
+ 'epsilon' => '&#949;',
247
+ 'beta' => '&#946;',
248
+ 'rArr' => '&#8658;',
249
+ 'rho' => '&#961;',
250
+ 'aacute' => '\xe1',
251
+ 'eacute' => '\xe9',
252
+ 'omega' => '&#969;',
253
+ 'middot' => '\xb7',
254
+ 'Gamma' => '&#915;',
255
+ 'Iacute' => '\xcd',
256
+ 'lang' => '&#9001;',
257
+ 'spades' => '&#9824;',
258
+ 'rsquo' => '&#8217;',
259
+ 'uml' => '\xa8',
260
+ 'thorn' => '\xfe',
261
+ 'ouml' => '\xf6',
262
+ 'thetasym' => '&#977;',
263
+ 'or' => '&#8744;',
264
+ 'raquo' => '\xbb',
265
+ 'acirc' => '\xe2',
266
+ 'ldquo' => '&#8220;',
267
+ 'hearts' => '&#9829;',
268
+ 'sigma' => '&#963;',
269
+ 'oacute' => '\xf3',
270
+ =end
271
+ }
2
272
 
3
273
  class UrlPlugin < Plugin
4
274
  BotConfig.register BotConfigIntegerValue.new('url.max_urls',
5
275
  :default => 100, :validate => Proc.new{|v| v > 0},
6
276
  :desc => "Maximum number of urls to store. New urls replace oldest ones.")
277
+ BotConfig.register BotConfigBooleanValue.new('url.display_link_info',
278
+ :default => false,
279
+ :desc => "Get the title of any links pasted to the channel and display it (also tells if the link is broken or the site is down)")
7
280
 
8
281
  def initialize
9
282
  super
10
283
  @registry.set_default(Array.new)
11
284
  end
285
+
12
286
  def help(plugin, topic="")
13
287
  "urls [<max>=4] => list <max> last urls mentioned in current channel, urls search [<max>=4] <regexp> => search for matching urls. In a private message, you must specify the channel to query, eg. urls <channel> [max], urls search <channel> [max] <regexp>"
14
288
  end
289
+
290
+ def unescape_title(htmldata)
291
+ # first pass -- let CGI try to attack it...
292
+ htmldata = CGI::unescapeHTML htmldata
293
+
294
+ # second pass -- destroy the remaining bits...
295
+ htmldata.gsub(/(&(.+?);)/) {
296
+ symbol = $2
297
+
298
+ # remove the 0-paddng from unicode integers
299
+ if symbol =~ /#(.+)/
300
+ symbol = "##{$1.to_i.to_s}"
301
+ end
302
+
303
+ # output the symbol's irc-translated character, or a * if it's unknown
304
+ UNESCAPE_TABLE[symbol] || '*'
305
+ }
306
+ end
307
+
308
+ def get_title_from_html(pagedata)
309
+ return unless TITLE_RE.match(pagedata)
310
+ title = $1.strip.gsub(/\s*\n+\s*/, " ")
311
+ title = unescape_title title
312
+ title = title[0..255] if title.length > 255
313
+ "[Link Info] title: #{title}"
314
+ end
315
+
316
+ def read_data_from_response(response, amount)
317
+
318
+ amount_read = 0
319
+ chunks = []
320
+
321
+ response.read_body do |chunk| # read body now
322
+
323
+ amount_read += chunk.length
324
+
325
+ if amount_read > amount
326
+ amount_of_overflow = amount_read - amount
327
+ chunk = chunk[0...-amount_of_overflow]
328
+ end
329
+
330
+ chunks << chunk
331
+
332
+ break if amount_read >= amount
333
+
334
+ end
335
+
336
+ chunks.join('')
337
+
338
+ end
339
+
340
+
341
+ def get_title_for_url(uri_str, depth=10)
342
+ # This god-awful mess is what the ruby http library has reduced me to.
343
+ # Python's HTTP lib is so much nicer. :~(
344
+
345
+ if depth == 0
346
+ raise "Error: Maximum redirects hit."
347
+ end
348
+
349
+ debug "+ Getting #{uri_str}"
350
+ url = URI.parse(uri_str)
351
+ return if url.scheme !~ /https?/
352
+
353
+ title = nil
354
+
355
+ debug "+ connecting to #{url.host}:#{url.port}"
356
+ http = @bot.httputil.get_proxy(url)
357
+ http.start { |http|
358
+ url.path = '/' if url.path == ''
359
+
360
+ http.request_get(url.path, "User-Agent" => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)") { |response|
361
+
362
+ case response
363
+ when Net::HTTPRedirection, Net::HTTPMovedPermanently then
364
+ # call self recursively if this is a redirect
365
+ redirect_to = response['location'] || './'
366
+ debug "+ redirect location: #{redirect_to.inspect}"
367
+ url = URI.join url.to_s, redirect_to
368
+ debug "+ whee, redirecting to #{url.to_s}!"
369
+ return get_title_for_url(url.to_s, depth-1)
370
+ when Net::HTTPSuccess then
371
+ if response['content-type'] =~ /^text\//
372
+ # since the content is 'text/*' and is small enough to
373
+ # be a webpage, retrieve the title from the page
374
+ debug "+ getting #{url.request_uri}"
375
+ data = read_data_from_response(response, 50000)
376
+ return get_title_from_html(data)
377
+ else
378
+ # content doesn't have title, just display info.
379
+ size = response['content-length'].gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')
380
+ return "[Link Info] type: #{response['content-type']}#{size ? ", size: #{size} bytes" : ""}"
381
+ end
382
+ when Net::HTTPClientError then
383
+ return "[Link Info] Error getting link (#{response.code} - #{response.message})"
384
+ when Net::HTTPServerError then
385
+ return "[Link Info] Error getting link (#{response.code} - #{response.message})"
386
+ else
387
+ return nil
388
+ end # end of "case response"
389
+
390
+ } # end of request block
391
+ } # end of http start block
392
+
393
+ return title
394
+
395
+ rescue SocketError => e
396
+ return "[Link Info] Error connecting to site (#{e.message})"
397
+ end
398
+
15
399
  def listen(m)
16
400
  return unless m.kind_of?(PrivMessage)
17
401
  return if m.address?
@@ -20,10 +404,21 @@ class UrlPlugin < Plugin
20
404
  if m.message =~ /((f|ht)tps?:\/\/.*?)(?:\s+|$)/
21
405
  urlstr = $1
22
406
  list = @registry[m.target]
407
+
408
+ if @bot.config['url.display_link_info']
409
+ debug "Getting title for #{urlstr}..."
410
+ title = get_title_for_url urlstr
411
+ if title
412
+ m.reply title
413
+ debug "Title found!"
414
+ else
415
+ debug "Title not found!"
416
+ end
417
+ end
418
+
23
419
  # check to see if this url is already listed
24
- return if list.find {|u|
25
- u.url == urlstr
26
- }
420
+ return if list.find {|u| u.url == urlstr }
421
+
27
422
  url = Url.new(m.target, m.sourcenick, Time.new, urlstr)
28
423
  debug "#{list.length} urls so far"
29
424
  if list.length > @bot.config['url.max_urls']
@@ -58,7 +453,7 @@ class UrlPlugin < Plugin
58
453
  string = params[:string]
59
454
  max = 10 if max > 10
60
455
  max = 1 if max < 1
61
- regex = Regexp.new(string)
456
+ regex = Regexp.new(string, Regexp::IGNORECASE)
62
457
  list = @registry[channel].find_all {|url|
63
458
  regex.match(url.url) || regex.match(url.nick)
64
459
  }