#
# Dictionary plugin for rbot
# by MrChucho (mrchucho@mrchucho.net)
# Copyright (C) 2006 Ralph M. Churchill
#
require 'open-uri'
require 'rexml/document'

module Dictionary
    def apply_xpath(xmldoc,xpath)
        return unless xmldoc
        
        ele = xmldoc.elements[xpath]
        if ele.respond_to?(:each) then
            arr = []
            ele.each do |e|
                arr << e
            end
            return arr.join
        else
            return ele
        end
    end

    def snippet_to_s(snippet,tidy=true)
        str = String.new
        snippet.each_line do |line|
            str << ((tidy) ? line.sub(/<div (id|class)=(.*)>/,"<div id=\"#{$1}\">") : line)
        end
        str
    end

    def query_definition(word)
        url = "http://search.yahoo.com/search?p=define+#{word}"
        begin
            snippet = String.new
            alert = false
            open(url) do |html|
                capture = false
                html.each_line do |line|
                   if line =~ /<div id=yschiy>/
                       capture = true
                   elsif line =~ /<div class=yschmsg .*>/
                       capture = true
                       alert = true
                   end
                   if capture
                       snippet << line
                       break if line =~ /<\/div>/
                   end
               end
            end
            
            xmldoc = (REXML::Document.new((snippet_to_s(snippet)))).root
            if not alert 
                result = apply_xpath(xmldoc,'/div/dl/dd')
                result = apply_xpath(xmldoc,'/div/cite/a') if not result
            else
                result = "Did you mean:"+
                apply_xpath(xmldoc,'/div//strong/text()').to_s.sub!(/define/,'')+
                "?"
            end
            result
        rescue => err
            raise err
        end
    end
end

class DictionaryPlugin < Plugin
    include Dictionary
    USAGE="define [WORD] => define a word"
    def help(plugin,topic="")
        USAGE
    end
    def usage(m,params={})
        m.reply USAGE
    end
    def define(m,params)
        word = params[:word].join('+')
        if word =~ /rbot/ then
            m.reply "NOUN: 1. A totally awesome IRC bot written in Ruby."
            return
        end
        begin
            rply = query_definition(word)
            if rply
                m.reply rply
            else
                m.reply "Couldn't find a definition for your \"word\"..."
            end
        rescue => e
            m.reply "Error"
        end
    end
end

plugin = DictionaryPlugin.new
plugin.map 'define *word', :defaults => {:word => false}
