]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/urban.rb
chucknorris: read gzip stream before passing it to YAML.load
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / urban.rb
index dd275e2de7a995e1c90f3fdc7d7287d5a3dcc1a2..70d451af7788d5848dbfca074367a0e350859d61 100644 (file)
@@ -1,64 +1,84 @@
-require 'cgi'
-require 'rubyful_soup'
-require 'uri/common'
-
 class UrbanPlugin < Plugin
+  URBAN = 'http://www.urbandictionary.com/define.php?term='
 
   def help( plugin, topic="")
-    "~urban [word] [n]. Give the [n]th definition of [word] from urbandictionary.com."
+    "urban [word] [n]: give the [n]th definition of [word] from urbandictionary.com. urbanday: give the word-of-the-day at urban"
   end
 
-  def privmsg( m )
+  def format_definition(total, num, word, desc, ex)
+    "#{Bold}#{word} (#{num}/#{total})#{Bold}: " +
+    desc.ircify_html(:limit => 300) + " " +
+    "<i>#{ex}</i>".ircify_html(:limit => 100)
+  end
 
-    unless(m.params && m.params.length > 0)
-      m.reply "incorrect usage: " + help(m.plugin)
-      return
+  def get_def(m, word, n = nil)
+    n = n ? n.to_i : 1
+    p = (n-1)/7 + 1
+    u = URBAN + URI.escape(word)
+    u += '&page=' + p.to_s if p > 1
+    s = @bot.httputil.get(u)
+    return m.reply("Couldn't get the urban dictionary definition for #{word}") if s.nil?
+
+    notfound = s.match %r{<i>.*?</i> isn't defined}
+
+    numpages = if s[%r{<ul class="pagination[^"]+">.*?</ul>}m]
+      $&.scan(/>(\d+)</).collect {|x| x[0].to_i}.max || 1
+    else 1 end
+
+    rv = Array.new
+    num = 1
+    s.scan(%r{<a class="word"[^>]* href="\/define[^>]*>([^<]+)</a>.*?<div class='meaning'>(.+?)</div>.*?<div class='example'>(.+?)</div>}m) do |wrd, desc, ex|
+      rv << [num, wrd.strip, desc.strip, ex.strip]
+      num += 1
     end
 
-    paramArray = m.params.split(' ')
-    definitionN = 0
-    if m.params == 'random' then
-      uri = URI.parse( "http://www.urbandictionary.com/random.php" )
-    else 
-      if( paramArray.last.to_i != 0 ) then
-        definitionN = paramArray.last.to_i - 1
-        query = m.params.chomp( paramArray.last )
-        query.rstrip!
-      else
-        query = m.params
-      end
-      uri = URI.parse( "http://www.urbandictionary.com/define.php?term=#{ URI.escape query}" )
+    maxnum = rv.collect {|x| x[0]}.max || 0
+    return m.reply("#{Bold}#{word}#{Bold} not found") if rv.empty?
+
+    if notfound
+      suggestions = rv.map { |str| Underline + str[1] + Underline }.uniq.join ', '
+      m.reply "#{Bold}#{word}#{Bold} not found. maybe you mean #{suggestions}?"
+      return
     end
 
-    soup = BeautifulSoup.new( @bot.httputil.get( uri ) )
-    if titleNavi = soup.find_all( 'td', :attrs => { 'class' => 'def_word' } )[0] then
-      title = titleNavi.contents
-      results = soup.find_all( 'div', :attrs => { 'class' => 'def_p' } )
-      debug PP.pp(results,'')
-      output = Array.new
-      if results[definitionN] then
-        results[definitionN].p.contents.each { |s| output.push( strip_tags( s.to_s ) ) }
-        m.reply "\002#{title}\002 - #{output}"
-      else
-        m.reply "#{query} does not have #{definitionN + 1} definitions."
+    answer = rv.find { |a| a[0] == n }
+    answer ||= (n > maxnum ? rv.last : rv.first)
+    m.reply format_definition((p == numpages ? maxnum : "#{(numpages-1)*7 + 1}+"), *answer)
+  end
+
+  def urban(m, params)
+    words = params[:words].to_s
+    if words.empty?
+      resp = @bot.httputil.head('http://www.urbandictionary.com/random.php',
+                               :max_redir => -1,
+                               :cache => false)
+      return m.reply("Couldn't get a random urban dictionary word") if resp.nil?
+      if resp.code == "302" && (loc = resp['location'])
+        words = URI.unescape(loc.match(/define.php\?term=(.*)$/)[1]) rescue nil
       end
-    else
-      m.reply "#{m.params} not found."
     end
-
+    get_def(m, words, params[:n])
   end
 
-  def strip_tags(html)
-    html.gsub(/<.+?>/,'').
-    gsub(/&amp;/,'&').
-    gsub(/&quot;/,'"').
-    gsub(/&lt;/,'<').
-    gsub(/&gt;/,'>').
-    gsub(/&ellip;/,'...').
-    gsub(/&apos;/, "'").
-    gsub("\n",'')
+  def uotd(m, params)
+    home = @bot.httputil.get("http://www.urbandictionary.com/daily.php")
+    if home.nil?
+      m.reply "Couldn't get the urban dictionary word of the day"
+      return
+    end
+    home.match(%r{href="/define.php\?term=.*?">(.*?)<})
+    wotd = $1
+    debug "Urban word of the day: #{wotd}"
+    if !wotd
+      m.reply "Couldn't get the urban dictionary word of the day"
+      return
+    end
+    get_def(m, wotd, 1)
   end
 end
 
 plugin = UrbanPlugin.new
-plugin.register( "urban" )
+plugin.map "urban *words :n", :requirements => { :n => /^-?\d+$/ }, :action => 'urban'
+plugin.map "urban [*words]", :action => 'urban'
+plugin.map "urbanday", :action => 'uotd'
+