]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - data/rbot/plugins/urban.rb
urban: updated pattern
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / urban.rb
index 95210b252460980d7918c9067327ce929685189e..a15b36224e05be4586ae82b876555df537a65d58 100644 (file)
@@ -1,96 +1,77 @@
-require 'uri'
-
 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. urbanday: give the word-of-the-day at urban"
   end
 
-  def urban(m, params)
-    words = params[:words].to_s
-    n = params[:n].nil? ? 1 : params[:n].to_i rescue 1
+  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
 
-    if words.empty?
-      uri = URI.parse( "http://www.urbandictionary.com/random.php" )
-      @bot.httputil.head(uri) { |redir|
-        words = URI.unescape(redir.match(/define.php\?term=(.*)$/)[1]) rescue nil
-      }
-    end
-    # we give a very high 'skip' because this will allow us to get the number of definitions by retrieving the previous definition
-    uri = URI.parse("http://www.urbanwap.com/search.php?term=#{URI.escape words}&skip=65536")
-    page = @bot.httputil.get(uri)
-    if page.nil?
-      m.reply "Couldn't retrieve an urban dictionary definition of #{words}"
-      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{<div id='paginator'>.*?</div>}m]
+      $&.scan(/\d+/).collect {|x| x.to_i}.max || 1
+    else 1 end
+
+    rv = Array.new
+    s.scan(%r{<div class='word'[^>]*>.*?<a class="index"[^>]*>.*?(\d+)\..*?</a>.*?<span>(.*?)</span>.*?<div class="definition">(.+?)</div>.*?<div class="example">(.+?)</div>}m) do |num, wrd, desc, ex|
+      rv << [num.to_i, wrd.strip, desc.strip, ex.strip]
     end
-    if page =~ / is undefined<\/card><\/wml>/
-      m.reply "There is no urban dictionary definition of #{words}"
+
+    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
-    if page =~ /&amp;skip=(\d+)">prev<\/a>/
-      numdefs = $1.to_i + 1
-    else
-      numdefs = 1
-    end
-    n = numdefs + n + 1 if n < 0
-    if n > numdefs
-      m.reply "Urban dictionary only has #{numdefs} definitions for '#{words}'"
-      n = numdefs
-    end
-    if n < numdefs
-      uri = URI.parse("http://www.urbanwap.com/search.php?term=#{URI.escape words}&skip=#{n-1}")
-      page = @bot.httputil.get(uri)
-      if page.nil?
-        case n % 10
-        when 1
-          ord = 'st'
-        when 2
-          ord = 'nd'
-        when 3
-          ord = 'rd'
-        else
-          ord = 'th'
-        end
-        m.reply "Couldn't retrieve the #{n}#{ord} urban dictionary definition of #{words}"
-        return
-      end
-    end
-    m.reply "#{get_def(page)} (#{n}/#{numdefs})"
-  end
 
-  def get_def(text)
-    # Start by removing the prev/home/next links
-    t = text.gsub(/(?:<a href.*?>prev<\/a> )?<a href.*?>home<\/a>(?: <a href.*?>next<\/a>)?/,'')
-    # Close up paragraphs
-    t.gsub!(/<\/?p>/, ' ')
-    t.gsub!("\n", ' ')
-    # Reverse headings
-    t.gsub!(/<\/?b>/,"#{Reverse}")
-    # Enbolden links
-    t.gsub!(/<\/?a(?: .*?)?>/,"#{Bold}")
-    # Reverse examples
-    t.gsub!(/<\/?(?:i|em)>/,"#{Underline}")
-    # Clear anything else
-    t.gsub!(/<.*?>/, '')
+    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
 
-    Utils.decode_html_entities t.strip
+  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
+    end
+    get_def(m, words, params[:n])
   end
 
   def uotd(m, params)
-    home = @bot.httputil.get("http://www.urbanwap.com/")
+    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(/Word of the Day: <a href="(.*?)">.*?<\/a>/)
+    home.match(%r{href="/define.php\?term=.*?">(.*?)<})
     wotd = $1
     debug "Urban word of the day: #{wotd}"
-    page = @bot.httputil.get(wotd)
-    if page.nil?
+    if !wotd
       m.reply "Couldn't get the urban dictionary word of the day"
-    else
-      m.reply get_def(page)
+      return
     end
+    get_def(m, wotd, 1)
   end
 end