]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/dict.rb
5176591ae7d84d4f04837146c247dffd7b708c99
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / dict.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: Dictionary lookup plugin for rbot
5 #
6 # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
7 # Copyright:: (C) 2006-2007 Giuseppe Bilotta
8 # License:: GPL v2
9 #
10 # Provides a link to the definition of a word in one of the supported
11 # dictionaries. Currently available are
12 #   * the Oxford dictionary for (British) English
13 #   * the De Mauro/Paravia dictionary for Italian
14 #   * the Chambers dictionary for English (accepts both US and UK)
15 #   * the Littré dictionary for French
16 #
17 # Other plugins can use this one to check if a given word is valid in italian
18 # or english or french by using the is_italian?, is_british?, is_english?,
19 # is_french? methods
20 #
21 # TODO: cache results and reuse them if get_cached returns a cache copy
22
23 DEMAURO_LEMMA = /<anchor>(.*?)(?: - (.*?))<go href="lemma.php\?ID=(\d+)"\/><\/anchor>/
24 CHAMBERS_LEMMA = /<p><span class="hwd">(.*?)<\/span> <span class="psa">(.*?)<\/span>(.*?)<\/p>/
25
26 class DictPlugin < Plugin
27   Config.register Config::IntegerValue.new('dict.hits',
28     :default => 3,
29     :desc => "Number of hits to return from a dictionary lookup")
30   Config.register Config::IntegerValue.new('dict.first_par',
31     :default => 0,
32     :desc => "When set to n > 0, the bot will return the first paragraph from the first n dictionary hits")
33
34   def initialize
35     super
36     @dmurl = "http://www.demauroparavia.it/"
37     @dmwapurl = "http://wap.demauroparavia.it/index.php?lemma=%s"
38     @dmwaplemma = "http://wap.demauroparavia.it/lemma.php?ID=%s"
39     @oxurl = "http://www.askoxford.com/concise_oed/%s"
40     @chambersurl = "http://www.chambersharrap.co.uk/chambers/features/chref/chref.py/main?query=%s&title=21st"
41     @littreurl = "http://francois.gannaz.free.fr/Littre/xmlittre.php?requete=%s"
42   end
43
44
45   def help(plugin, topic="")
46     case topic
47     when "demauro"
48       return "demauro <word> => provides a link to the definition of <word> from the De Mauro/Paravia dictionary"
49     when "oxford"
50       return "oxford <word> => provides a link to the definition of <word> (it can also be an expression) from the Concise Oxford dictionary"
51     when "chambers"
52       return "chambers <word> => provides a link to the definition of <word> (it can also be an expression) from the Chambers 21st Century Dictionary"
53     when "littre"
54       return "littre <word> => provides a link to the definition of <word> (it can also be an expression) from the Littré online dictionary"
55     end
56     return "<dictionary> <word>: check for <word> on <dictionary> where <dictionary> can be one of: demauro, oxford, chambers, littre"
57   end
58
59   def demauro(m, params)
60     justcheck = params[:justcheck]
61
62     word = params[:word].downcase
63     url = @dmwapurl % CGI.escape(word)
64     xml = nil
65     info = @bot.httputil.get_response(url) rescue nil
66     xml = info.body if info
67     if xml.nil?
68       info = info ? " (#{info.code} - #{info.message})" : ""
69       return false if justcheck
70       m.reply "An error occurred while looking for #{word}#{info}"
71       return
72     end
73     if xml=~ /Non ho trovato occorrenze per/
74       return false if justcheck
75       m.reply "Nothing found for #{word}"
76       return
77     end
78     entries = xml.scan(DEMAURO_LEMMA)
79     text = word
80     urls = []
81     if not entries.transpose.first.grep(/\b#{word}\b/)
82       return false if justcheck
83       text += " not found. Similar words"
84     end
85     return true if justcheck
86     text += ": "
87     n = 0
88     hits = @bot.config['dict.hits']
89     text += entries[0...hits].map { |ar|
90       n += 1
91       urls << @dmwaplemma % ar[2]
92       "#{n}. #{Bold}#{ar[0]}#{Bold} - #{ar[1].gsub(/<\/?em>/,'')}: #{@dmurl}#{ar[2]}"
93     }.join(" | ")
94     m.reply text
95
96     first_pars = @bot.config['dict.first_par']
97
98     return unless first_pars > 0
99
100     Utils.get_first_pars urls, first_pars, :message => m,
101       :strip => /^.+?\s+-\s+/
102
103   end
104
105   def is_italian?(word)
106     return demauro(nil, :word => word, :justcheck => true)
107   end
108
109
110   def oxford(m, params)
111     justcheck = params[:justcheck]
112
113     word = params[:word].join
114     [word, word + "_1"].each { |check|
115       url = @oxurl % CGI.escape(check)
116       if params[:british]
117         url << "?view=uk"
118       end
119       h = @bot.httputil.get(url, :max_redir => 5)
120       if h and h.match(%r!<h2>#{word}(?:<sup>1</sup>)?</h2>!)
121         m.reply("#{word} : #{url}") unless justcheck
122         defn = $'
123         m.reply("#{Bold}%s#{Bold}: %s" % [word, defn.ircify_html(:nbsp => :space)], :overlong => :truncate)
124         return true
125       end
126     }
127     return false if justcheck
128     m.reply "#{word} not found"
129   end
130
131   def is_british?(word)
132     return oxford(nil, :word => word, :justcheck => true, :british => true)
133   end
134
135
136   def chambers(m, params)
137     justcheck = params[:justcheck]
138
139     word = params[:word].to_s.downcase
140     url = @chambersurl % CGI.escape(word)
141     xml = nil
142     info = @bot.httputil.get_response(url) rescue nil
143     xml = info.body if info
144     case xml
145     when nil
146       info = info ? " (#{info.code} - #{info.message})" : ""
147       return false if justcheck
148       m.reply "An error occurred while looking for #{word}#{info}"
149       return
150     when /Sorry, no entries for <b>.*?<\/b> were found./
151       return false if justcheck
152       m.reply "Nothing found for #{word}"
153       return
154     when /No exact matches for <b>.*?<\/b>, but the following may be helpful./
155       return false if justcheck
156       m.reply "Nothing found for #{word}, but see #{url} for possible suggestions"
157       return
158     end
159     # Else, we have a hit
160     return true if justcheck
161     m.reply "#{word}: #{url}"
162     entries = xml.scan(CHAMBERS_LEMMA)
163     hits = @bot.config['dict.hits']
164     entries[0...hits].map { |ar|
165       m.reply(("#{Bold}%s#{Bold} #{Underline}%s#{Underline}%s" % ar).ircify_html, :overlong => :truncate)
166     }
167   end
168
169   def is_english?(word)
170     return chambers(nil, :word => word, :justcheck => true)
171   end
172
173   def littre(m, params)
174     justcheck = params[:justcheck]
175
176     word = params[:word].to_s.downcase
177     url = @littreurl % CGI.escape(word)
178     xml = nil
179     info = @bot.httputil.get_response(url) rescue nil
180     xml = info.body if info
181     head ||= xml.match(/<div class="entree">(.*?)<\/div>/)[1] rescue nil
182     case xml
183     when nil
184       info = info ? " (#{info.code} - #{info.message})" : ""
185       return false if justcheck
186       m.reply "An error occurred while looking for #{word}#{info}"
187       return
188     when /Erreur : le mot <STRONG>.*?<\/STRONG> n'a pas./
189       return false if justcheck
190       if head
191         m.reply "Nothing found for #{word}, I'll assume you meant #{head}"
192       else
193         m.reply "Nothing found for #{word}"
194         return
195       end
196     end
197     return true if justcheck
198     entete = xml.match(/<div class="entete">(.*?)<\/div>/m)[1] rescue nil
199     m.reply "#{head}: #{url} : #{entete.ircify_html rescue nil}"
200     entries = xml.scan(/<span class="variante">(.*?)<\!--variante-->/m)
201     hits = @bot.config['dict.hits']
202     n = 0
203     entries[0...hits].map { |ar|
204       n += 1
205       m.reply(("#{Bold}#{n}#{Bold} %s" % ar).ircify_html, :overlong => :truncate)
206     }
207   end
208
209   def is_french?(word)
210     return littre(nil, :word => word, :justcheck => true)
211   end
212
213 end
214
215 plugin = DictPlugin.new
216 plugin.map 'demauro :word', :action => 'demauro', :thread => true
217 plugin.map 'oxford *word', :action => 'oxford', :thread => true
218 plugin.map 'chambers *word', :action => 'chambers', :thread => true
219 plugin.map 'littre *word', :action => 'littre', :thread => true
220